-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathlogruseq.go
128 lines (108 loc) · 2.83 KB
/
logruseq.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
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
package logruseq
import (
"bytes"
"fmt"
"io/ioutil"
"net/http"
"time"
"github.com/sirupsen/logrus"
)
// SeqHook sends logs to Seq via HTTP.
type SeqHook struct {
endpoint string
apiKey string
levels []logrus.Level
}
// NewSeqHook creates a Seq hook for logrus which can send log events to the
// host specified, for example:
// logruseq.NewSeqHook("http://localhost:5341")
// Optionally, the hook can be used with an API key, for example:
// logruseq.NewSeqHook("http://localhost:5341",
// logruseq.OptionAPIKey("N1ncujiT5pYGD6m4CF0"))
// Optionally, which levels to log can be specified:
// logruseq.NewSeqHook("http://localhost:5341",
// logruseq.OptionLevels([]logrus.Level{
// logrus.WarnLevel,
// logrus.ErrorLevel,
// logrus.FatalLevel,
// logrus.PanicLevel,
// }))
func NewSeqHook(host string, opts ...func(*SeqHookOptions)) *SeqHook {
sho := &SeqHookOptions{
levels: []logrus.Level{
logrus.TraceLevel,
logrus.DebugLevel,
logrus.InfoLevel,
logrus.WarnLevel,
logrus.ErrorLevel,
logrus.FatalLevel,
logrus.PanicLevel,
},
}
for _, opt := range opts {
opt(sho)
}
endpoint := fmt.Sprintf("%v/api/events/raw", host)
return &SeqHook{
endpoint: endpoint,
apiKey: sho.apiKey,
levels: sho.levels,
}
}
// Fire sends a log entry to Seq.
func (hook *SeqHook) Fire(entry *logrus.Entry) error {
formatter := logrus.JSONFormatter{
TimestampFormat: time.RFC3339Nano,
FieldMap: logrus.FieldMap{
logrus.FieldKeyMsg: "@mt",
logrus.FieldKeyLevel: "@l",
logrus.FieldKeyTime: "@t",
},
}
data, err := formatter.Format(entry)
if err != nil {
return err
}
req, err := http.NewRequest("POST", hook.endpoint, bytes.NewReader(data))
if err != nil {
return err
}
req.Header.Set("Content-Type", "application/vnd.serilog.clef")
if hook.apiKey != "" {
req.Header.Add("X-Seq-ApiKey", hook.apiKey)
}
resp, err := http.DefaultClient.Do(req)
if err != nil {
return err
}
defer resp.Body.Close()
if resp.StatusCode != http.StatusCreated {
data, err = ioutil.ReadAll(resp.Body)
if err != nil {
return err
}
return fmt.Errorf("error creating seq event: %v", string(data))
}
return nil
}
// Levels returns the levels for which Fire will be called.
func (hook *SeqHook) Levels() []logrus.Level {
return hook.levels
}
// SeqHookOptions collects non-default Seq hook options.
type SeqHookOptions struct {
apiKey string
levels []logrus.Level
}
// OptionAPIKey sets the Seq API key option.
func OptionAPIKey(apiKey string) func(opts *SeqHookOptions) {
return func(opts *SeqHookOptions) {
opts.apiKey = apiKey
}
}
// OptionLevels sets the levels for which Fire will be called.
func OptionLevels(levels []logrus.Level) func(opts *SeqHookOptions) {
return func(opts *SeqHookOptions) {
opts.levels = levels
}
}