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
|
package log
import (
"io"
"os"
grpcmwlogrus "github.com/grpc-ecosystem/go-grpc-middleware/logging/logrus"
"github.com/sirupsen/logrus"
)
const (
// GitalyLogDirEnvKey defines the environment variable used to specify the Gitaly log directory
GitalyLogDirEnvKey = "GITALY_LOG_DIR"
// LogTimestampFormat defines the timestamp format in log files
LogTimestampFormat = "2006-01-02T15:04:05.000"
// LogTimestampFormatUTC defines the utc timestamp format in log files
LogTimestampFormatUTC = "2006-01-02T15:04:05.000Z"
)
type utcFormatter struct {
logrus.Formatter
}
func (u utcFormatter) Format(e *logrus.Entry) ([]byte, error) {
e.Time = e.Time.UTC()
return u.Formatter.Format(e)
}
// UTCJsonFormatter returns a Formatter that formats a logrus Entry's as json and converts the time
// field into UTC
func UTCJsonFormatter() logrus.Formatter {
return &utcFormatter{Formatter: &logrus.JSONFormatter{TimestampFormat: LogTimestampFormatUTC}}
}
// UTCTextFormatter returns a Formatter that formats a logrus Entry's as text and converts the time
// field into UTC
func UTCTextFormatter() logrus.Formatter {
return &utcFormatter{Formatter: &logrus.TextFormatter{TimestampFormat: LogTimestampFormatUTC}}
}
// defaultLogger is the logger that is returned via `Default()` and via logrus' direct log invocations like e.g.
// `logrus.Info()`. By default it is configured to log to standard output, but in practice it should be configured via
// a call to `Configure()` after the configuration has been loaded.
var defaultLogger = func() *logrus.Logger {
//nolint:forbidigo // We reuse the standard logger such that dependencies which might use logrus are properly
// configured, as well.
logger := logrus.StandardLogger()
logger.Out = os.Stdout
return logger
}()
// Config contains logging configuration values
type Config struct {
Dir string `toml:"dir,omitempty" json:"dir"`
Format string `toml:"format,omitempty" json:"format"`
Level string `toml:"level,omitempty" json:"level"`
}
// Configure configures the default and gRPC loggers. The gRPC logger's log level will be mapped in order to decrease
// its default verbosity. Returns the configured default logger that would also be returned by `Default()`.
func Configure(out io.Writer, format string, level string, hooks ...logrus.Hook) logrus.FieldLogger {
configure(defaultLogger, out, format, level, hooks...)
// We replace the gRPC logger with a custom one because the default one is too chatty.
grpcLogger := logrus.New()
configure(grpcLogger, out, format, mapGRPCLogLevel(level), hooks...)
grpcmwlogrus.ReplaceGrpcLogger(grpcLogger.WithField("pid", os.Getpid()))
return Default()
}
func configure(logger *logrus.Logger, out io.Writer, format, level string, hooks ...logrus.Hook) {
var formatter logrus.Formatter
switch format {
case "json":
formatter = UTCJsonFormatter()
case "", "text":
formatter = UTCTextFormatter()
default:
logrus.WithField("format", format).Fatal("invalid logger format")
}
logrusLevel, err := logrus.ParseLevel(level)
if err != nil {
logrusLevel = logrus.InfoLevel
}
logger.Out = out
logger.SetLevel(logrusLevel)
logger.Formatter = formatter
for _, hook := range hooks {
logger.Hooks.Add(hook)
}
}
func mapGRPCLogLevel(level string) string {
// Honor grpc-go's debug settings: https://github.com/grpc/grpc-go#how-to-turn-on-logging
switch os.Getenv("GRPC_GO_LOG_SEVERITY_LEVEL") {
case "ERROR", "error":
return "error"
case "WARNING", "warning":
return "warning"
case "INFO", "info":
return "info"
}
// grpc-go is too verbose at level 'info'. So when config.toml requests
// level info, we tell grpc-go to log at 'warn' instead.
if level == "info" {
return "warning"
}
return level
}
// Default returns the default logger that has been configured via `Configure()`.
func Default() *logrus.Entry { return defaultLogger.WithField("pid", os.Getpid()) }
|