2017-11-28 18:08:41 +00:00
|
|
|
package postfix
|
|
|
|
|
|
|
|
import (
|
|
|
|
"fmt"
|
|
|
|
"os"
|
|
|
|
"os/exec"
|
2018-06-21 23:01:38 +00:00
|
|
|
"path/filepath"
|
2017-11-28 18:08:41 +00:00
|
|
|
"strings"
|
|
|
|
"time"
|
|
|
|
|
|
|
|
"github.com/influxdata/telegraf"
|
|
|
|
"github.com/influxdata/telegraf/plugins/inputs"
|
|
|
|
)
|
|
|
|
|
|
|
|
const sampleConfig = `
|
|
|
|
## Postfix queue directory. If not provided, telegraf will try to use
|
|
|
|
## 'postconf -h queue_directory' to determine it.
|
|
|
|
# queue_directory = "/var/spool/postfix"
|
|
|
|
`
|
|
|
|
|
|
|
|
const description = "Measure postfix queue statistics"
|
|
|
|
|
|
|
|
func getQueueDirectory() (string, error) {
|
|
|
|
qd, err := exec.Command("postconf", "-h", "queue_directory").Output()
|
|
|
|
if err != nil {
|
|
|
|
return "", err
|
|
|
|
}
|
|
|
|
return strings.TrimSpace(string(qd)), nil
|
|
|
|
}
|
|
|
|
|
2018-06-21 23:01:38 +00:00
|
|
|
func qScan(path string, acc telegraf.Accumulator) (int64, int64, int64, error) {
|
2017-11-28 18:08:41 +00:00
|
|
|
var length, size int64
|
|
|
|
var oldest time.Time
|
2018-06-21 23:01:38 +00:00
|
|
|
err := filepath.Walk(path, func(_ string, finfo os.FileInfo, err error) error {
|
|
|
|
if err != nil {
|
|
|
|
acc.AddError(fmt.Errorf("error scanning %s: %s", path, err))
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
if finfo.IsDir() {
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
2017-11-28 18:08:41 +00:00
|
|
|
length++
|
|
|
|
size += finfo.Size()
|
2017-11-29 19:25:31 +00:00
|
|
|
|
|
|
|
ctime := statCTime(finfo.Sys())
|
|
|
|
if ctime.IsZero() {
|
2018-06-21 23:01:38 +00:00
|
|
|
return nil
|
2017-11-29 19:25:31 +00:00
|
|
|
}
|
|
|
|
if oldest.IsZero() || ctime.Before(oldest) {
|
|
|
|
oldest = ctime
|
2017-11-28 18:08:41 +00:00
|
|
|
}
|
2018-06-21 23:01:38 +00:00
|
|
|
return nil
|
|
|
|
})
|
|
|
|
if err != nil {
|
|
|
|
return 0, 0, 0, err
|
2017-11-28 18:08:41 +00:00
|
|
|
}
|
2017-11-29 19:25:31 +00:00
|
|
|
var age int64
|
2017-11-28 18:08:41 +00:00
|
|
|
if !oldest.IsZero() {
|
2017-11-29 19:25:31 +00:00
|
|
|
age = int64(time.Now().Sub(oldest) / time.Second)
|
2018-06-21 23:01:38 +00:00
|
|
|
} else if length != 0 {
|
2017-11-29 19:25:31 +00:00
|
|
|
// system doesn't support ctime
|
|
|
|
age = -1
|
2017-11-28 18:08:41 +00:00
|
|
|
}
|
2017-11-29 19:25:31 +00:00
|
|
|
return length, size, age, nil
|
2017-11-28 18:08:41 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
type Postfix struct {
|
|
|
|
QueueDirectory string
|
|
|
|
}
|
|
|
|
|
|
|
|
func (p *Postfix) Gather(acc telegraf.Accumulator) error {
|
|
|
|
if p.QueueDirectory == "" {
|
|
|
|
var err error
|
|
|
|
p.QueueDirectory, err = getQueueDirectory()
|
|
|
|
if err != nil {
|
|
|
|
return fmt.Errorf("unable to determine queue directory: %s", err)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-06-21 23:01:38 +00:00
|
|
|
for _, q := range []string{"active", "hold", "incoming", "maildrop", "deferred"} {
|
|
|
|
length, size, age, err := qScan(filepath.Join(p.QueueDirectory, q), acc)
|
2017-11-28 18:08:41 +00:00
|
|
|
if err != nil {
|
|
|
|
acc.AddError(fmt.Errorf("error scanning queue %s: %s", q, err))
|
|
|
|
continue
|
|
|
|
}
|
2017-11-29 19:25:31 +00:00
|
|
|
fields := map[string]interface{}{"length": length, "size": size}
|
|
|
|
if age != -1 {
|
|
|
|
fields["age"] = age
|
|
|
|
}
|
2017-11-28 18:08:41 +00:00
|
|
|
acc.AddFields("postfix_queue", fields, map[string]string{"queue": q})
|
|
|
|
}
|
|
|
|
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func (p *Postfix) SampleConfig() string {
|
|
|
|
return sampleConfig
|
|
|
|
}
|
|
|
|
|
|
|
|
func (p *Postfix) Description() string {
|
|
|
|
return description
|
|
|
|
}
|
|
|
|
|
|
|
|
func init() {
|
|
|
|
inputs.Add("postfix", func() telegraf.Input {
|
|
|
|
return &Postfix{
|
|
|
|
QueueDirectory: "/var/spool/postfix",
|
|
|
|
}
|
|
|
|
})
|
|
|
|
}
|