forked from jperon/lunatik_snihook
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathlog.moon
More file actions
69 lines (59 loc) · 1.71 KB
/
log.moon
File metadata and controls
69 lines (59 loc) · 1.71 KB
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
import concat from table
:time = require"linux"
levels = {"EMERGENCY", "ALERT", "CRITICAL", "ERROR", "WARNING", "NOTICE", "INFO", "DEBUG"}
levels[levels[i]] = i-1 for i = 1, #levels
sanitize = (part) ->
s = "#{part}"
-- Keep kernel logs text-only: replace non-printable bytes.
if s\find "[%z\1-\8\11\12\14-\31\127-\255]"
s\gsub("[^ -~\t]", ".")
else
s
prune_rate_state = (state, now, window) ->
return unless state and next(state)
for k, v in pairs state
if (now - v.t0) >= (window * 10)
state[k] = nil
can_log = (self, lvl, line) ->
rl = self.rate_limit
return true unless rl
now = time! / 1000000000
key = "#{lvl}\0#{line}"
ent = rl.state[key]
unless ent
rl.state[key] = {t0: now, n: 1}
if rl.size > 2048
prune_rate_state rl.state, now, rl.window
rl.size = 0
for _ in pairs rl.state
rl.size += 1
else
rl.size += 1
return true
if (now - ent.t0) >= rl.window
ent.t0 = now
ent.n = 1
return true
if ent.n < rl.burst
ent.n += 1
return true
false
logger = (lvl, txt=levels[lvl+1]) =>
(...) ->
unless @level < lvl
line = concat [ sanitize(part) for part in *{...} ], "\t"
return unless can_log @, lvl, line
@.log "#{@msg} #{txt}: #{line}"
(level, msg="", log=print, opts=nil) ->
if type(log) == "table" and not opts
opts = log
log = print
opts or= {}
window = tonumber(opts.rate_limit_window) or 2
burst = tonumber(opts.rate_limit_burst) or 1
rate_limit = nil
if window > 0 and burst > 0
rate_limit = window: window, burst: burst, state: {}, size: 0
@ = :log, :msg, :rate_limit, level: tonumber(level) or levels[level]
@[lvl\lower!] = logger(@, i-1) for i, lvl in ipairs levels
@