Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
aos
GitHub Repository: aos/grafana-agent
Path: blob/main/pkg/integrations/logruskit.go
5318 views
1
package integrations //nolint:golint
2
3
import (
4
"encoding/json"
5
"fmt"
6
"sort"
7
"time"
8
9
"github.com/go-kit/log/level"
10
11
"github.com/go-kit/log"
12
"github.com/sirupsen/logrus"
13
)
14
15
// NewLogger translates log.Logger to logrus.Logger
16
func NewLogger(logger log.Logger, opts ...Option) *logrus.Logger {
17
o := output{}
18
for _, apply := range opts {
19
apply(&o)
20
}
21
22
l := logrus.New()
23
l.SetFormatter(formatter{})
24
l.SetOutput(output{l: logger})
25
return l
26
}
27
28
// Option Exposes logging options
29
type Option func(*output)
30
31
// WithTimestampFromLogrus sets tsFromLogrus logging option
32
func WithTimestampFromLogrus() Option {
33
return func(o *output) {
34
o.tsFromLogrus = true
35
}
36
}
37
38
type output struct {
39
l log.Logger
40
tsFromLogrus bool
41
}
42
43
func (o output) Write(data []byte) (n int, err error) {
44
var ll line
45
if err := json.Unmarshal(data, &ll); err != nil {
46
return 0, fmt.Errorf("can't unmarshal line: %w", err)
47
}
48
keys := make([]string, 0, len(ll.Data))
49
for k := range ll.Data {
50
keys = append(keys, k)
51
}
52
sort.Strings(keys)
53
54
vals := make([]interface{}, 0, 2*len(ll.Data)+2)
55
for _, k := range keys {
56
vals = append(vals, k, ll.Data[k])
57
}
58
vals = append(vals, "msg", ll.Message)
59
60
logger := o.l
61
if o.tsFromLogrus {
62
logger = log.WithPrefix(o.l, "ts", ll.Time)
63
}
64
65
lvl := level.InfoValue()
66
if mappedLvl, ok := levelMap[ll.Level]; ok {
67
lvl = mappedLvl
68
}
69
logger = log.WithPrefix(logger, level.Key(), lvl)
70
71
return 0, logger.Log(vals...)
72
}
73
74
type formatter struct{}
75
76
func (f formatter) Format(e *logrus.Entry) ([]byte, error) {
77
ll := line{
78
Time: e.Time,
79
Level: e.Level,
80
Data: e.Data,
81
Message: e.Message,
82
}
83
84
// FIXME: this can be much better in performance, but we can change it anytime since it's an internal contract
85
return json.Marshal(ll)
86
}
87
88
type line struct {
89
Time time.Time
90
Level logrus.Level
91
Data logrus.Fields
92
Message string
93
}
94
95
var levelMap = map[logrus.Level]level.Value{
96
logrus.PanicLevel: level.ErrorValue(),
97
logrus.FatalLevel: level.ErrorValue(),
98
logrus.ErrorLevel: level.ErrorValue(),
99
logrus.WarnLevel: level.WarnValue(),
100
logrus.InfoLevel: level.InfoValue(),
101
logrus.DebugLevel: level.DebugValue(),
102
logrus.TraceLevel: level.DebugValue(),
103
}
104
105