-
Notifications
You must be signed in to change notification settings - Fork 487
/
log.go
129 lines (111 loc) · 3.35 KB
/
log.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
129
// Package log is a fork of
// github.com/cortexproject/cortex@v1.11.0/pkg/util/log/log.go.
//
// See https://github.com/cortexproject/cortex/blob/v1.11.0/LICENSE for
// LICENSE details.
package log
import (
"fmt"
"os"
"github.com/go-kit/log"
"github.com/go-kit/log/level"
dskit "github.com/grafana/dskit/log"
"github.com/grafana/dskit/server"
"github.com/prometheus/client_golang/prometheus"
)
var (
Logger = log.NewNopLogger()
logMessages = prometheus.NewCounterVec(prometheus.CounterOpts{
Name: "log_messages_total",
Help: "Total number of log messages.",
}, []string{"level"})
supportedLevels = []level.Value{
level.DebugValue(),
level.InfoValue(),
level.WarnValue(),
level.ErrorValue(),
}
)
func init() {
prometheus.MustRegister(logMessages)
}
// InitLogger initialises the global gokit logger (util_log.Logger) and overrides the
// default logger for the server.
func InitLogger(cfg *server.Config) {
l, err := NewPrometheusLogger(cfg.LogLevel, cfg.LogFormat)
if err != nil {
panic(err)
}
// when use util_log.Logger, skip 3 stack frames.
Logger = log.With(l, "caller", log.Caller(3))
// cfg.Log wraps log function, skip 4 stack frames to get caller information.
// this works in go 1.12, but doesn't work in versions earlier.
// it will always shows the wrapper function generated by compiler
// marked <autogenerated> in old versions.
cfg.Log = log.With(l, "caller", log.Caller(4))
}
// PrometheusLogger exposes Prometheus counters for each of go-kit's log levels.
type PrometheusLogger struct {
logger log.Logger
}
// NewPrometheusLogger creates a new instance of PrometheusLogger which exposes
// Prometheus counters for various log levels.
func NewPrometheusLogger(l dskit.Level, format string) (log.Logger, error) {
logger := log.NewLogfmtLogger(log.NewSyncWriter(os.Stderr))
if format == "json" {
logger = log.NewJSONLogger(log.NewSyncWriter(os.Stderr))
}
logger = level.NewFilter(logger, LevelFilter(l.String()))
// Initialise counters for all supported levels:
for _, level := range supportedLevels {
logMessages.WithLabelValues(level.String())
}
logger = &PrometheusLogger{
logger: logger,
}
// return a Logger without caller information, shouldn't use directly
logger = log.With(logger, "ts", log.DefaultTimestampUTC)
return logger, nil
}
// Log increments the appropriate Prometheus counter depending on the log level.
func (pl *PrometheusLogger) Log(kv ...interface{}) error {
pl.logger.Log(kv...)
l := "unknown"
for i := 1; i < len(kv); i += 2 {
if v, ok := kv[i].(level.Value); ok {
l = v.String()
break
}
}
logMessages.WithLabelValues(l).Inc()
return nil
}
// CheckFatal prints an error and exits with error code 1 if err is non-nil
func CheckFatal(location string, err error) {
if err != nil {
logger := level.Error(Logger)
if location != "" {
logger = log.With(logger, "msg", "error "+location)
}
// %+v gets the stack trace from errors using github.com/pkg/errors
logger.Log("err", fmt.Sprintf("%+v", err))
os.Exit(1)
}
}
// TODO(dannyk): remove once weaveworks/common updates to go-kit/log
//
// -> we can then revert to using Level.Gokit
func LevelFilter(l string) level.Option {
switch l {
case "debug":
return level.AllowDebug()
case "info":
return level.AllowInfo()
case "warn":
return level.AllowWarn()
case "error":
return level.AllowError()
default:
return level.AllowAll()
}
}