Add the name of the message queue as a label.
Instead of providing stats for all messages collectively, it would make more sense to group them by queue. That way it's possible to alert on the number of active, deferred, etc. messages. For Postfix 2.x there isn't a lot we can do, as there only is a single ASCII character distinguishing between two queues specifically.
This commit is contained in:
parent
1df13fe2c1
commit
c3262ed850
@ -62,30 +62,40 @@ func CollectTextualShowqFromReader(file io.Reader, ch chan<- prometheus.Metric)
|
|||||||
|
|
||||||
// Regular expression for matching postqueue's output. Example:
|
// Regular expression for matching postqueue's output. Example:
|
||||||
// "A07A81514 5156 Tue Feb 14 13:13:54 MAILER-DAEMON"
|
// "A07A81514 5156 Tue Feb 14 13:13:54 MAILER-DAEMON"
|
||||||
messageLine := regexp.MustCompile("^[0-9A-F]+ +(\\d+) (\\w{3} \\w{3} +\\d+ +\\d+:\\d{2}:\\d{2}) +")
|
messageLine := regexp.MustCompile("^[0-9A-F]+([\\*!]?) +(\\d+) (\\w{3} \\w{3} +\\d+ +\\d+:\\d{2}:\\d{2}) +")
|
||||||
|
|
||||||
// Histograms tracking the messages by size and age.
|
// Histograms tracking the messages by size and age.
|
||||||
sizeHistogram := prometheus.NewHistogram(
|
sizeHistogram := prometheus.NewHistogramVec(
|
||||||
prometheus.HistogramOpts{
|
prometheus.HistogramOpts{
|
||||||
Namespace: "postfix",
|
Namespace: "postfix",
|
||||||
Name: "queue_message_size_bytes",
|
Name: "queue_message_size_bytes",
|
||||||
Help: "Size of messages in Postfix's message queue, in bytes",
|
Help: "Size of messages in Postfix's message queue, in bytes",
|
||||||
Buckets: []float64{1e3, 1e4, 1e5, 1e6, 1e7, 1e8, 1e9},
|
Buckets: []float64{1e3, 1e4, 1e5, 1e6, 1e7, 1e8, 1e9},
|
||||||
})
|
},
|
||||||
ageHistogram := prometheus.NewHistogram(
|
[]string{"queue"})
|
||||||
|
ageHistogram := prometheus.NewHistogramVec(
|
||||||
prometheus.HistogramOpts{
|
prometheus.HistogramOpts{
|
||||||
Namespace: "postfix",
|
Namespace: "postfix",
|
||||||
Name: "queue_message_age_seconds",
|
Name: "queue_message_age_seconds",
|
||||||
Help: "Age of messages in Postfix's message queue, in seconds",
|
Help: "Age of messages in Postfix's message queue, in seconds",
|
||||||
Buckets: []float64{1e1, 1e2, 1e3, 1e4, 1e5, 1e6, 1e7, 1e8},
|
Buckets: []float64{1e1, 1e2, 1e3, 1e4, 1e5, 1e6, 1e7, 1e8},
|
||||||
})
|
},
|
||||||
|
[]string{"queue"})
|
||||||
|
|
||||||
now := time.Now()
|
now := time.Now()
|
||||||
for scanner.Scan() {
|
for scanner.Scan() {
|
||||||
matches := messageLine.FindStringSubmatch(scanner.Text())
|
matches := messageLine.FindStringSubmatch(scanner.Text())
|
||||||
if matches != nil {
|
if matches != nil {
|
||||||
|
// Derive the name of the message queue.
|
||||||
|
queue := "other"
|
||||||
|
if matches[1] == "*" {
|
||||||
|
queue = "active"
|
||||||
|
} else if matches[1] == "!" {
|
||||||
|
queue = "hold"
|
||||||
|
}
|
||||||
|
|
||||||
// Parse the message size.
|
// Parse the message size.
|
||||||
size, err := strconv.ParseFloat(matches[1], 64)
|
size, err := strconv.ParseFloat(matches[2], 64)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -94,7 +104,7 @@ func CollectTextualShowqFromReader(file io.Reader, ch chan<- prometheus.Metric)
|
|||||||
// output contains no year number. Assume it
|
// output contains no year number. Assume it
|
||||||
// applies to the last year for which the
|
// applies to the last year for which the
|
||||||
// message date doesn't exceed time.Now().
|
// message date doesn't exceed time.Now().
|
||||||
date, err := time.Parse("Mon Jan 2 15:04:05", matches[2])
|
date, err := time.Parse("Mon Jan 2 15:04:05", matches[3])
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -103,13 +113,13 @@ func CollectTextualShowqFromReader(file io.Reader, ch chan<- prometheus.Metric)
|
|||||||
date = date.AddDate(-1, 0, 0)
|
date = date.AddDate(-1, 0, 0)
|
||||||
}
|
}
|
||||||
|
|
||||||
sizeHistogram.Observe(size)
|
sizeHistogram.WithLabelValues(queue).Observe(size)
|
||||||
ageHistogram.Observe(now.Sub(date).Seconds())
|
ageHistogram.WithLabelValues(queue).Observe(now.Sub(date).Seconds())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ch <- sizeHistogram
|
sizeHistogram.Collect(ch)
|
||||||
ch <- ageHistogram
|
ageHistogram.Collect(ch)
|
||||||
return scanner.Err()
|
return scanner.Err()
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -133,27 +143,31 @@ func CollectBinaryShowqFromReader(file io.Reader, ch chan<- prometheus.Metric) e
|
|||||||
scanner.Split(ScanNullTerminatedEntries)
|
scanner.Split(ScanNullTerminatedEntries)
|
||||||
|
|
||||||
// Histograms tracking the messages by size and age.
|
// Histograms tracking the messages by size and age.
|
||||||
sizeHistogram := prometheus.NewHistogram(
|
sizeHistogram := prometheus.NewHistogramVec(
|
||||||
prometheus.HistogramOpts{
|
prometheus.HistogramOpts{
|
||||||
Namespace: "postfix",
|
Namespace: "postfix",
|
||||||
Name: "queue_message_size_bytes",
|
Name: "queue_message_size_bytes",
|
||||||
Help: "Size of messages in Postfix's message queue, in bytes",
|
Help: "Size of messages in Postfix's message queue, in bytes",
|
||||||
Buckets: []float64{1e3, 1e4, 1e5, 1e6, 1e7, 1e8, 1e9},
|
Buckets: []float64{1e3, 1e4, 1e5, 1e6, 1e7, 1e8, 1e9},
|
||||||
})
|
},
|
||||||
ageHistogram := prometheus.NewHistogram(
|
[]string{"queue"})
|
||||||
|
ageHistogram := prometheus.NewHistogramVec(
|
||||||
prometheus.HistogramOpts{
|
prometheus.HistogramOpts{
|
||||||
Namespace: "postfix",
|
Namespace: "postfix",
|
||||||
Name: "queue_message_age_seconds",
|
Name: "queue_message_age_seconds",
|
||||||
Help: "Age of messages in Postfix's message queue, in seconds",
|
Help: "Age of messages in Postfix's message queue, in seconds",
|
||||||
Buckets: []float64{1e1, 1e2, 1e3, 1e4, 1e5, 1e6, 1e7, 1e8},
|
Buckets: []float64{1e1, 1e2, 1e3, 1e4, 1e5, 1e6, 1e7, 1e8},
|
||||||
})
|
},
|
||||||
|
[]string{"queue"})
|
||||||
|
|
||||||
now := float64(time.Now().UnixNano()) / 1e9
|
now := float64(time.Now().UnixNano()) / 1e9
|
||||||
|
queue := "unknown"
|
||||||
for scanner.Scan() {
|
for scanner.Scan() {
|
||||||
// Parse a key/value entry.
|
// Parse a key/value entry.
|
||||||
key := scanner.Text()
|
key := scanner.Text()
|
||||||
if len(key) == 0 {
|
if len(key) == 0 {
|
||||||
// Empty key means a record separator. We don't care.
|
// Empty key means a record separator.
|
||||||
|
queue := "unknown"
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
if !scanner.Scan() {
|
if !scanner.Scan() {
|
||||||
@ -161,25 +175,28 @@ func CollectBinaryShowqFromReader(file io.Reader, ch chan<- prometheus.Metric) e
|
|||||||
}
|
}
|
||||||
value := scanner.Text()
|
value := scanner.Text()
|
||||||
|
|
||||||
if key == "size" {
|
if key == "queue_name" {
|
||||||
|
// The name of the message queue.
|
||||||
|
queue = value
|
||||||
|
} else if key == "size" {
|
||||||
// Message size in bytes.
|
// Message size in bytes.
|
||||||
size, err := strconv.ParseFloat(value, 64)
|
size, err := strconv.ParseFloat(value, 64)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
sizeHistogram.Observe(size)
|
sizeHistogram.WithLabelValues(queue).Observe(size)
|
||||||
} else if key == "time" {
|
} else if key == "time" {
|
||||||
// Message time as a UNIX timestamp.
|
// Message time as a UNIX timestamp.
|
||||||
time, err := strconv.ParseFloat(value, 64)
|
time, err := strconv.ParseFloat(value, 64)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
ageHistogram.Observe(now - time)
|
ageHistogram.WithLabelValues(queue).Observe(now - time)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ch <- sizeHistogram
|
sizeHistogram.Collect(ch)
|
||||||
ch <- ageHistogram
|
ageHistogram.Collect(ch)
|
||||||
return scanner.Err()
|
return scanner.Err()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user