postfix-exporter 2.0.3 → 2.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (4) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +17 -2
  3. data/bin/postfix-exporter +65 -4
  4. metadata +3 -3
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: d6e9b995c8c56b28d9500d51b20a8857b3fdcc44
4
- data.tar.gz: 34c495ffd68b19de2c65c5297e58a7d197a0f705
3
+ metadata.gz: 59a89aac9e188bb3a7a5cf1617425bd797ebf68f
4
+ data.tar.gz: d7fd70f12daadfd79a90c66efce6c862afd31b00
5
5
  SHA512:
6
- metadata.gz: 1483d066cc63929f244a0337f0c61ab2740d9d105fcc1af92881b79c0a5a819da42e81b64d82cccf5855853f3ef04342a4f09836d89e66fac545f48f0754e224
7
- data.tar.gz: 8a1f46107f17a18d6d9ca6b64c2e6b6ad6e0a4b7f2e489495640af5ec82b8b08f371f741c31438b46fa39b935cf76c7304f98db1c58c9606a9369efac71052c2
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 (`postfix_disposition`) per DSN, as well as delay summaries per
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
 
@@ -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
- sleep 1
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 = prometheus.summary(:postfix_delivery_delays, "Distribution of time taken to deliver (or bounce) messages")
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.3
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: 2017-07-05 00:00:00.000000000 Z
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.5.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