postfix-exporter 2.0.3 → 2.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +17 -2
- data/bin/postfix-exporter +65 -4
- metadata +3 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 59a89aac9e188bb3a7a5cf1617425bd797ebf68f
|
4
|
+
data.tar.gz: d7fd70f12daadfd79a90c66efce6c862afd31b00
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 0e51b58b74c279e81a3a88f9e3322f95f363571a6e959d14a8f3ebf1b3d77a5f899821f0673a9b347c1a9906574983bbc8ba297667917238a18eb933da55daed
|
7
|
+
data.tar.gz: 6e6ecffdb49e584e2592ba7d69bdc08fb67efd1abc4162024b7511a5e97a393ef6bc643ca8d44993744b0230d26d434b3eda8adff91d143b5c224ba3c12d9a02
|
data/README.md
CHANGED
@@ -7,8 +7,18 @@ server.
|
|
7
7
|
* Examines mail queue periodically and exports `postfix_mail_queue_size`;
|
8
8
|
|
9
9
|
* Reads syslog entries as they happen, and exports disposition status
|
10
|
-
counters (`
|
11
|
-
DSN;
|
10
|
+
counters (`postfix_delivery_delays_count`) per DSN, as well as delay summaries per
|
11
|
+
DSN (`postfix_delivery_delays{quantile="..."}`);
|
12
|
+
|
13
|
+
* Total number of SMTP connections (`postfix_smtpd_connections_total`) and
|
14
|
+
currently-active connections (`postfix_smtpd_active_connections`);
|
15
|
+
|
16
|
+
* Count how many delivery attempts were received
|
17
|
+
(`postfix_incoming_delivery_attempts_total`), split out by whether we
|
18
|
+
accepted or rejected the message (`status`) and the exact DSN provided to
|
19
|
+
the client (`dsn`);
|
20
|
+
|
21
|
+
* Whether or not the Postfix `master` process is running (`postfix_up`);
|
12
22
|
|
13
23
|
* Drinks from the syslog stream directly.
|
14
24
|
|
@@ -21,6 +31,11 @@ available in the container as `/var/spool/postfix`), and some env
|
|
21
31
|
vars. You can also run it directly (via the gem), with the same env vars,
|
22
32
|
and with the expectation that `/var/spool/postfix` is in the usual place.
|
23
33
|
|
34
|
+
If you configure the postfix-exporter to run in the same PID namespace as
|
35
|
+
whatever it is that's running Postfix itself (either `--pid=host` or in the
|
36
|
+
same NS namespace, a la k8s pods), then the `postfix_up` metric will be
|
37
|
+
valid, otherwise it'll be random (but unlikely to be correct).
|
38
|
+
|
24
39
|
|
25
40
|
## Environment Variables
|
26
41
|
|
data/bin/postfix-exporter
CHANGED
@@ -8,7 +8,11 @@ require 'logger'
|
|
8
8
|
|
9
9
|
prometheus = Prometheus::Client.registry
|
10
10
|
|
11
|
+
prometheus.gauge(:postfix_exporter_start_time_seconds, "When this process started up").set({}, Time.now.to_f)
|
12
|
+
|
11
13
|
mailq = prometheus.gauge(:postfix_queue_size, "Number of messages in the mail queue")
|
14
|
+
q_err = prometheus.counter(:postfix_queue_processing_error_total, "Exceptions raised whilst scanning the Postfix queue")
|
15
|
+
up = prometheus.gauge(:postfix_up, "Whether the master process is running or not")
|
12
16
|
|
13
17
|
Thread.abort_on_exception = true
|
14
18
|
|
@@ -22,18 +26,49 @@ Thread.new do
|
|
22
26
|
# deferred is special, because it's often hueg it gets sharded into
|
23
27
|
# multiple subdirectories
|
24
28
|
mailq.set({ queue: 'deferred' }, Dir["/var/spool/postfix/deferred/*/*"].size)
|
25
|
-
|
26
|
-
sleep 5
|
27
29
|
rescue StandardError => ex
|
28
30
|
$stderr.puts "Error while monitoring queue sizes: #{ex.message} (#{ex.class})"
|
29
31
|
$stderr.puts ex.backtrace.map { |l| " #{l}" }.join("\n")
|
30
|
-
|
32
|
+
q_err.increment(class: ex.class.to_s, phase: "scan")
|
31
33
|
end
|
34
|
+
|
35
|
+
begin
|
36
|
+
master_pid = File.read("/var/spool/postfix/pid/master.pid").to_i
|
37
|
+
|
38
|
+
if master_pid > 1
|
39
|
+
Process.kill(0, master_pid)
|
40
|
+
# If we get here, then the process exists, and
|
41
|
+
# that'll do for our purposes
|
42
|
+
up.set({}, 1)
|
43
|
+
else
|
44
|
+
up.set({}, 0)
|
45
|
+
end
|
46
|
+
rescue Errno::ENOENT, Errno::ESRCH, Errno::EACCES
|
47
|
+
up.set({}, 0)
|
48
|
+
rescue Errno::EPERM
|
49
|
+
# Ironically, we don't need to be able to *actually*
|
50
|
+
# signal the process; EPERM means it exists and is running
|
51
|
+
# as someone more privileged than us, which is enough
|
52
|
+
# for our purposes
|
53
|
+
up.set({}, 1)
|
54
|
+
rescue StandardError => ex
|
55
|
+
$stderr.puts "Error while checking master process: #{ex.message} (#{ex.class})"
|
56
|
+
$stderr.puts ex.backtrace.map { |l| " #{l}" }.join("\n")
|
57
|
+
q_err.increment(class: ex.class.to_s, phase: "up")
|
58
|
+
end
|
59
|
+
|
60
|
+
sleep 5
|
61
|
+
|
32
62
|
end
|
33
63
|
end
|
34
64
|
|
35
65
|
if ENV["SYSLOG_SOCKET"]
|
36
|
-
delays
|
66
|
+
delays = prometheus.summary(:postfix_delivery_delays, "Distribution of time taken to deliver (or bounce) messages")
|
67
|
+
connects = prometheus.counter(:postfix_smtpd_connections_total, "Connections to smtpd")
|
68
|
+
active = prometheus.gauge(:postfix_smtpd_active_connections, "Current connections to smtpd")
|
69
|
+
incoming = prometheus.counter(:postfix_incoming_delivery_attempts_total, "Delivery attempts, labelled by dsn and status")
|
70
|
+
messages = prometheus.counter(:postfix_log_messages_total, "Syslog messages received, labelled by how it was handled")
|
71
|
+
log_errors = prometheus.counter(:postfix_log_processing_error_total, "Exceptions raised whilst processing log messages")
|
37
72
|
|
38
73
|
Thread.new do
|
39
74
|
begin
|
@@ -55,10 +90,36 @@ if ENV["SYSLOG_SOCKET"]
|
|
55
90
|
if status == "bounced" or status == "sent"
|
56
91
|
delays.observe({dsn: dsn, status: status}, delay)
|
57
92
|
end
|
93
|
+
|
94
|
+
messages.increment(type: "delay")
|
95
|
+
elsif msg =~ %r{postfix/smtpd\[\d+\]: connect from }
|
96
|
+
connects.increment({})
|
97
|
+
active.send(:synchronize) { active.set({}, active.get({}) || 0 + 1) }
|
98
|
+
messages.increment(type: "connect")
|
99
|
+
elsif msg =~ %r{postfix/smtpd\[\d+\]: disconnect from }
|
100
|
+
active.send(:synchronize) do
|
101
|
+
new = (active.get({}) || 0) - 1
|
102
|
+
# If we start running mid-stream,
|
103
|
+
# we might end up seeing more
|
104
|
+
# disconnects than connections,
|
105
|
+
# which would be confusing
|
106
|
+
new = 0 if new < 0
|
107
|
+
active.set({}, new)
|
108
|
+
end
|
109
|
+
messages.increment(type: "disconnect")
|
110
|
+
elsif msg =~ %r{postfix/smtpd\[\d+\]: [A-F0-9]+: client=}
|
111
|
+
incoming.increment(dsn: "2.0.0", status: "queued")
|
112
|
+
messages.increment(type: "queued")
|
113
|
+
elsif msg =~ %r{postfix/smtpd\[\d+\]: NOQUEUE: reject: RCPT from \S+: \d{3} (\d+\.\d+\.\d+) }
|
114
|
+
incoming.increment(dsn: $1, status: "rejected")
|
115
|
+
messages.increment(type: "noqueue")
|
116
|
+
else
|
117
|
+
messages.increment(type: "ignored")
|
58
118
|
end
|
59
119
|
rescue StandardError => ex
|
60
120
|
$stderr.puts "Error while receiving postfix logs: #{ex.message} (#{ex.class})"
|
61
121
|
$stderr.puts ex.backtrace.map { |l| " #{l}" }.join("\n")
|
122
|
+
log_errors.increment(class: ex.class.to_s)
|
62
123
|
sleep 1
|
63
124
|
end
|
64
125
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: postfix-exporter
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 2.0
|
4
|
+
version: 2.1.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Matt Palmer
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2018-01-30 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: prometheus-client
|
@@ -118,7 +118,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
118
118
|
version: '0'
|
119
119
|
requirements: []
|
120
120
|
rubyforge_project:
|
121
|
-
rubygems_version: 2.
|
121
|
+
rubygems_version: 2.6.13
|
122
122
|
signing_key:
|
123
123
|
specification_version: 4
|
124
124
|
summary: Export Prometheus statistics for a Postfix server
|