...
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18 package logutil
19
20 import (
21 "bytes"
22 "encoding/json"
23 "fmt"
24 "io"
25 "os"
26 "path/filepath"
27
28 "go.etcd.io/etcd/client/pkg/v3/systemd"
29
30 "github.com/coreos/go-systemd/v22/journal"
31 "go.uber.org/zap/zapcore"
32 )
33
34
35
36
37
38
39 func NewJournalWriter(wr io.Writer) (io.Writer, error) {
40 return &journalWriter{Writer: wr}, systemd.DialJournal()
41 }
42
43 type journalWriter struct {
44 io.Writer
45 }
46
47
48
49 type logLine struct {
50 Level string `json:"level"`
51 Caller string `json:"caller"`
52 }
53
54 func (w *journalWriter) Write(p []byte) (int, error) {
55 line := &logLine{}
56 if err := json.NewDecoder(bytes.NewReader(p)).Decode(line); err != nil {
57 return 0, err
58 }
59
60 var pri journal.Priority
61 switch line.Level {
62 case zapcore.DebugLevel.String():
63 pri = journal.PriDebug
64 case zapcore.InfoLevel.String():
65 pri = journal.PriInfo
66
67 case zapcore.WarnLevel.String():
68 pri = journal.PriWarning
69 case zapcore.ErrorLevel.String():
70 pri = journal.PriErr
71
72 case zapcore.DPanicLevel.String():
73 pri = journal.PriCrit
74 case zapcore.PanicLevel.String():
75 pri = journal.PriCrit
76 case zapcore.FatalLevel.String():
77 pri = journal.PriCrit
78
79 default:
80 panic(fmt.Errorf("unknown log level: %q", line.Level))
81 }
82
83 err := journal.Send(string(p), pri, map[string]string{
84 "PACKAGE": filepath.Dir(line.Caller),
85 "SYSLOG_IDENTIFIER": filepath.Base(os.Args[0]),
86 })
87 if err != nil {
88
89
90 return w.Writer.Write(p)
91 }
92 return 0, nil
93 }
94
View as plain text