1
0
Fork 0

Adding upstream version 1.34.4.

Signed-off-by: Daniel Baumann <daniel@debian.org>
This commit is contained in:
Daniel Baumann 2025-05-24 07:26:29 +02:00
parent e393c3af3f
commit 4978089aab
Signed by: daniel
GPG key ID: FBB4F0E80A80222F
4963 changed files with 677545 additions and 0 deletions

View file

@ -0,0 +1,73 @@
# Postfix Input Plugin
The postfix plugin reports metrics on the postfix queues.
For each of the active, hold, incoming, maildrop, and deferred queues
(<http://www.postfix.org/QSHAPE_README.html#queues>), it will report the queue
length (number of items), size (bytes used by items), and age (age of oldest
item in seconds).
## Global configuration options <!-- @/docs/includes/plugin_config.md -->
In addition to the plugin-specific configuration settings, plugins support
additional global and plugin configuration settings. These settings are used to
modify metrics, tags, and field or create aliases and configure ordering, etc.
See the [CONFIGURATION.md][CONFIGURATION.md] for more details.
[CONFIGURATION.md]: ../../../docs/CONFIGURATION.md#plugins
## Configuration
```toml @sample.conf
# Measure postfix queue statistics
# This plugin ONLY supports non-Windows
[[inputs.postfix]]
## Postfix queue directory. If not provided, telegraf will try to use
## 'postconf -h queue_directory' to determine it.
# queue_directory = "/var/spool/postfix"
```
### Permissions
Telegraf will need read access to the files in the queue directory. You may
need to alter the permissions of these directories to provide access to the
telegraf user.
This can be setup either using standard unix permissions or with Posix ACLs,
you will only need to use one method:
Unix permissions:
```sh
sudo chgrp -R telegraf /var/spool/postfix/{active,hold,incoming,deferred}
sudo chmod -R g+rXs /var/spool/postfix/{active,hold,incoming,deferred}
sudo usermod -a -G postdrop telegraf
sudo chmod g+r /var/spool/postfix/maildrop
```
Posix ACL:
```sh
sudo setfacl -Rm g:telegraf:rX /var/spool/postfix/
sudo setfacl -dm g:telegraf:rX /var/spool/postfix/
```
## Metrics
- postfix_queue
- tags:
- queue
- fields:
- length (integer)
- size (integer, bytes)
- age (integer, seconds)
## Example Output
```text
postfix_queue,queue=active length=3,size=12345,age=9
postfix_queue,queue=hold length=0,size=0,age=0
postfix_queue,queue=maildrop length=1,size=2000,age=2
postfix_queue,queue=incoming length=1,size=1020,age=0
postfix_queue,queue=deferred length=400,size=76543210,age=3600
```

View file

@ -0,0 +1,114 @@
//go:generate ../../../tools/readme_config_includer/generator
//go:build !windows
// postfix doesn't aim for Windows
package postfix
import (
_ "embed"
"fmt"
"os"
"os/exec"
"path/filepath"
"strings"
"time"
"github.com/influxdata/telegraf"
"github.com/influxdata/telegraf/plugins/inputs"
)
//go:embed sample.conf
var sampleConfig string
type Postfix struct {
QueueDirectory string `toml:"queue_directory"`
}
func (*Postfix) SampleConfig() string {
return sampleConfig
}
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: %w", err)
}
}
for _, q := range []string{"active", "hold", "incoming", "maildrop", "deferred"} {
fields, err := qScan(filepath.Join(p.QueueDirectory, q), acc)
if err != nil {
acc.AddError(fmt.Errorf("error scanning queue %q: %w", q, err))
continue
}
acc.AddFields("postfix_queue", fields, map[string]string{"queue": q})
}
return nil
}
func getQueueDirectory() (string, error) {
qd, err := exec.Command("postconf", "-h", "queue_directory").Output()
if err != nil {
return "", err
}
return strings.TrimSpace(string(qd)), nil
}
func qScan(path string, acc telegraf.Accumulator) (map[string]interface{}, error) {
var length, size int64
var oldest time.Time
err := filepath.Walk(path, func(_ string, finfo os.FileInfo, err error) error {
if err != nil {
acc.AddError(fmt.Errorf("error scanning %q: %w", path, err))
return nil
}
if finfo.IsDir() {
return nil
}
length++
size += finfo.Size()
ctime := statCTime(finfo.Sys())
if ctime.IsZero() {
return nil
}
if oldest.IsZero() || ctime.Before(oldest) {
oldest = ctime
}
return nil
})
if err != nil {
return nil, err
}
var age int64
if !oldest.IsZero() {
age = int64(time.Since(oldest) / time.Second)
} else if length != 0 {
// system doesn't support ctime
age = -1
}
fields := map[string]interface{}{"length": length, "size": size}
if age != -1 {
fields["age"] = age
}
return fields, nil
}
func init() {
inputs.Add("postfix", func() telegraf.Input {
return &Postfix{
QueueDirectory: "/var/spool/postfix",
}
})
}

View file

@ -0,0 +1,57 @@
//go:build !windows
package postfix
import (
"os"
"path/filepath"
"testing"
"github.com/stretchr/testify/require"
"github.com/influxdata/telegraf/testutil"
)
func TestGather(t *testing.T) {
td := t.TempDir()
for _, q := range []string{"active", "hold", "incoming", "maildrop", "deferred/0/0", "deferred/F/F"} {
require.NoError(t, os.MkdirAll(filepath.FromSlash(td+"/"+q), 0750))
}
require.NoError(t, os.WriteFile(filepath.FromSlash(td+"/active/01"), []byte("abc"), 0640))
require.NoError(t, os.WriteFile(filepath.FromSlash(td+"/active/02"), []byte("defg"), 0640))
require.NoError(t, os.WriteFile(filepath.FromSlash(td+"/hold/01"), []byte("abc"), 0640))
require.NoError(t, os.WriteFile(filepath.FromSlash(td+"/incoming/01"), []byte("abcd"), 0640))
require.NoError(t, os.WriteFile(filepath.FromSlash(td+"/deferred/0/0/01"), []byte("abc"), 0640))
require.NoError(t, os.WriteFile(filepath.FromSlash(td+"/deferred/F/F/F1"), []byte("abc"), 0640))
p := Postfix{
QueueDirectory: td,
}
var acc testutil.Accumulator
require.NoError(t, p.Gather(&acc))
metrics := map[string]*testutil.Metric{}
for _, m := range acc.Metrics {
metrics[m.Tags["queue"]] = m
}
require.Equal(t, int64(2), metrics["active"].Fields["length"])
require.Equal(t, int64(7), metrics["active"].Fields["size"])
require.InDelta(t, 0, metrics["active"].Fields["age"], 10)
require.Equal(t, int64(1), metrics["hold"].Fields["length"])
require.Equal(t, int64(3), metrics["hold"].Fields["size"])
require.Equal(t, int64(1), metrics["incoming"].Fields["length"])
require.Equal(t, int64(4), metrics["incoming"].Fields["size"])
require.Equal(t, int64(0), metrics["maildrop"].Fields["length"])
require.Equal(t, int64(0), metrics["maildrop"].Fields["size"])
require.Equal(t, int64(0), metrics["maildrop"].Fields["age"])
require.Equal(t, int64(2), metrics["deferred"].Fields["length"])
require.Equal(t, int64(6), metrics["deferred"].Fields["size"])
}

View file

@ -0,0 +1,32 @@
//go:build windows
package postfix
import (
_ "embed"
"github.com/influxdata/telegraf"
"github.com/influxdata/telegraf/plugins/inputs"
)
//go:embed sample.conf
var sampleConfig string
type Postfix struct {
Log telegraf.Logger `toml:"-"`
}
func (*Postfix) SampleConfig() string { return sampleConfig }
func (p *Postfix) Init() error {
p.Log.Warn("Current platform is not supported")
return nil
}
func (*Postfix) Gather(_ telegraf.Accumulator) error { return nil }
func init() {
inputs.Add("postfix", func() telegraf.Input {
return &Postfix{}
})
}

View file

@ -0,0 +1,6 @@
# Measure postfix queue statistics
# This plugin ONLY supports non-Windows
[[inputs.postfix]]
## Postfix queue directory. If not provided, telegraf will try to use
## 'postconf -h queue_directory' to determine it.
# queue_directory = "/var/spool/postfix"

View file

@ -0,0 +1,16 @@
//go:build dragonfly || linux || netbsd || openbsd || solaris
package postfix
import (
"syscall"
"time"
)
func statCTime(sys interface{}) time.Time {
stat, ok := sys.(*syscall.Stat_t)
if !ok {
return time.Time{}
}
return time.Unix(stat.Ctim.Unix())
}

View file

@ -0,0 +1,16 @@
//go:build darwin || freebsd
package postfix
import (
"syscall"
"time"
)
func statCTime(sys interface{}) time.Time {
stat, ok := sys.(*syscall.Stat_t)
if !ok {
return time.Time{}
}
return time.Unix(stat.Ctimespec.Unix())
}