-
Notifications
You must be signed in to change notification settings - Fork 0
/
check_mailq.lua
135 lines (115 loc) · 3.7 KB
/
check_mailq.lua
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
--
-- Copyright (c) 2010, Cloudkick, Inc.
-- All right reserved.
--
module(..., package.seeall);
local io = require 'io'
local util = require 'util'
local Check = util.Check
local log = util.log
local structs = require 'structs'
local function stats_add(qstats, stat, item)
--log.dbg("stats add %s %s", stat, item)
if not qstats[stat] then qstats[stat] = {} end
if not qstats[stat][item] then qstats[stat][item] = 0 end
qstats[stat][item] = qstats[stat][item] + 1
end
-- Parse the first line of the message information from mailq
-- this varies from sendmail to postfix/courier
local function parsemessagetop(line, m, sendmail)
if sendmail then
-- AA02508 3 1005 Dec 17 10:01 root
local msg_reg = "([%u%d]+)%s+(%d+)%s+%d+%s*(%a+)%s+(%d+)%s+(%d+)%:(%d+)%s+(.*)%s*"
m.id, m.size, m.month, m.day, m.hour,
m.minute, m.sender = line:match(msg_reg)
else
-- 92F7852E6C5 2532 Wed Oct 13 07:40:40 MAILER-DAEMON
local msg_reg = "([%u%d]+)%s+(%d+)%s+(%a+)%s+(%a+)%s+(%d+)%s+(%d+)%:(%d+)%:(%d+)%s+(.*)%s*$"
m.id, m.size, m.dow, m.month, m.day, m.hour,
m.minute, m.second, m.sender = line:match(msg_reg)
end
if not m.id or not m.size or not m.month or not m.day or not m.hour
or not m.minute or not m.sender then
return nil
end
end
local function parsemessage(line, f, qstats, sendmail, rcheck)
local i = 1
local m = {}
m.recipients = {}
repeat
if i == 1 then
parsemessagetop(line, m, sendmail)
-- second line has the reason things are on the queue
elseif i == 2 then
m.reason = line:match("%s*%p*%s*([%w%s]+)%s*%p*%s*$")
-- remaining lines are recipients
elseif i > 2 then
if line:find("^$") then return m end
r = line:match("%s*(.*)%s*$")
table.insert(m.recipients, r)
end
i = i + 1
line = f:read()
until not line
if i <= 2 then
rcheck:set_error("mailq match error")
return nil
end
return m
end
local function getmetrics(args, rcheck)
local header_found, tmp, qid = nil
local sendmail = nil
local qstats = {}
qstats.messages = 0
qstats.size = 0
-- TODO: test framework to use something like:
-- cmd = "cat equus/tests/mailq/0001.mailq"
cmd = "mailq"
local f = assert(io.popen('mailq', 'r'))
while true do
local line = f:read()
if not line then break end
--log.dbg("line %s", line)
if not header_found then
header_found, tmp, qid = line:find("%-+(Q%l*%s*ID)%-+%s+%-+Size%-+%s%-+.*Time%-+%s%-+Sender.Recipient%-+$")
if qid == "QID" then sendmail = true end
else
if line:find("%-+%s+%d+%s+.*byte. in %d+ [Rr]equest..*$") then break end
local msg = parsemessage(line, f, qstats, sendmail, rcheck)
stats_add(qstats, "reason", msg.reason)
stats_add(qstats, "sender", msg.sender)
qstats.messages = qstats.messages + 1
qstats.size = qstats.size + msg.size
end
end
if not header_found then
f:close()
rcheck:set_error("mailq header match error")
return nil
end
f:close()
return qstats
end
function run(rcheck, args)
local rv, r = pcall(getmetrics, args, rcheck)
if not rv then
log.err("err calling mailq: %s", r)
rcheck:set_error("mailq error")
return rcheck
end
if not r then return rcheck end
for i, v in pairs(r.reason) do
rcheck:add_metric(i, v, Check.enum.uint64)
end
for i, v in pairs(r.sender) do
rcheck:add_metric(string.format("Messages from %s", i), v,
Check.enum.uint64)
end
rcheck:add_metric("Messages", r.messages, Check.enum.uint64)
rcheck:add_metric("Queue Size", r.size, Check.enum.uint64)
rcheck:set_status(string.format("%s messages and %s bytes",
r.messages, r.size))
return rcheck
end