/
systemd_linux.go
111 lines (95 loc) · 2.63 KB
/
systemd_linux.go
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
package system
import (
"github.com/coreos/go-systemd/journal"
"github.com/tychoish/fun/ers"
"github.com/tychoish/grip/level"
"github.com/tychoish/grip/message"
"github.com/tychoish/grip/send"
)
type systemdJournal struct {
fallback send.Sender
options map[string]string
send.Base
}
// MakeSystemdSender creates a Sender object that writes log messages
// to the sysemd journal service directly. If such a service does not
// exist on the current system, returns a sender that writes all
// messages to standard output.
func MakeSystemdSender() send.Sender {
if !journal.Enabled() {
return send.MakeStdError()
}
s := &systemdJournal{
options: make(map[string]string),
fallback: send.MakeStdError(),
}
s.SetErrorHandler(send.ErrorHandlerFromSender(s.fallback))
s.SetFormatter(send.MakePlainFormatter())
s.reconfig()
return s
}
func (s *systemdJournal) reconfig() {
s.fallback.SetFormatter(s.GetFormatter())
s.fallback.SetName(s.Name())
}
func (s *systemdJournal) SetName(name string) { s.Base.SetName(name); s.reconfig() }
func (s *systemdJournal) SetFormater(fmtr send.MessageFormatter) {
s.Base.SetFormatter(fmtr)
s.reconfig()
}
func (s *systemdJournal) Send(m message.Composer) {
if !send.ShouldLog(s, m) {
return
}
if err := ers.WithRecoverCall(func() {
outstr, err := s.Format(m)
if !s.HandleErrorOK(send.WrapError(err, m)) {
return
}
if err := journal.Send(outstr, convertPrioritySystemd(m.Priority(), 0), s.options); err != nil {
s.HandleError(send.WrapError(err, m))
}
}); err != nil {
// there was a panic
s.HandleError(send.WrapError(err, m))
}
}
func convertPrioritySystemd(prio level.Priority, depth int) journal.Priority {
switch prio {
case level.Emergency:
return journal.PriEmerg
case level.Alert:
return journal.PriAlert
case level.Critical:
return journal.PriCrit
case level.Error:
return journal.PriErr
case level.Warning:
return journal.PriWarning
case level.Notice:
return journal.PriNotice
case level.Info:
return journal.PriInfo
case level.Debug, level.Trace, level.Invalid:
return journal.PriDebug
default:
// levels increase by 25(ish); if we're going to be
// invalid by being too low, just return debug now,
// otherwise, attempt to round down to the nearest 25,
// should only need 1 or 2 recursions to get to some
// return.
switch {
case prio <= 25:
return journal.PriDebug
case prio%25 == 0 && int(prio)-25 >= 0:
prio -= 25
return convertPrioritySystemd(prio, depth+1)
default:
val := int(prio) - int(prio)%25
if val >= 0 {
return convertPrioritySystemd(level.Priority(val), depth+1)
}
return journal.PriDebug
}
}
}