/
deploy.go
132 lines (116 loc) · 3.4 KB
/
deploy.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
130
131
132
package zap
import (
"go.uber.org/zap"
"go.uber.org/zap/zapcore"
"go.ytsaurus.tech/library/go/core/log"
)
// NewDeployEncoderConfig returns an opinionated EncoderConfig for
// deploy environment.
func NewDeployEncoderConfig() zapcore.EncoderConfig {
return zapcore.EncoderConfig{
MessageKey: "msg",
LevelKey: "levelStr",
StacktraceKey: "stackTrace",
TimeKey: "@timestamp",
CallerKey: "",
NameKey: "loggerName",
EncodeLevel: zapcore.CapitalLevelEncoder,
EncodeTime: zapcore.ISO8601TimeEncoder,
EncodeDuration: zapcore.StringDurationEncoder,
EncodeCaller: zapcore.ShortCallerEncoder,
}
}
type cfgOption func(cfg *zap.Config)
// WithSampling sets sampling settings initial and thereafter
func WithSampling(initial int, thereafter int) cfgOption {
return cfgOption(func(cfg *zap.Config) {
cfg.Sampling = &zap.SamplingConfig{
Initial: initial,
Thereafter: thereafter,
}
})
}
// SetOutputPaths sets OutputPaths (stdout by default)
func SetOutputPaths(paths []string) cfgOption {
return cfgOption(func(cfg *zap.Config) {
cfg.OutputPaths = paths
})
}
// WithDevelopment sets Development option of zap.Config
func WithDevelopment(enabled bool) cfgOption {
return cfgOption(func(cfg *zap.Config) {
cfg.Development = enabled
})
}
// WithLevel sets level of logging
func WithLevel(level log.Level) cfgOption {
return cfgOption(func(cfg *zap.Config) {
cfg.Level = zap.NewAtomicLevelAt(ZapifyLevel(level))
})
}
// NewDeployConfig returns default configuration (with no sampling).
// Not recommended for production use.
func NewDeployConfig(opts ...cfgOption) zap.Config {
cfg := zap.Config{
Level: zap.NewAtomicLevelAt(zap.DebugLevel),
Encoding: "json",
OutputPaths: []string{"stdout"},
ErrorOutputPaths: []string{"stderr"},
EncoderConfig: NewDeployEncoderConfig(),
}
for _, opt := range opts {
opt(&cfg)
}
return cfg
}
// NewCustomDeployLogger constructs new logger by config cfg
func NewCustomDeployLogger(cfg zap.Config, opts ...zap.Option) (*Logger, error) {
zl, err := cfg.Build(opts...)
if err != nil {
return nil, err
}
return &Logger{
L: addDeployContext(zl).(*zap.Logger),
}, nil
}
// NewDeployLogger constructs fully-fledged Deploy compatible logger
// based on predefined config. See https://deploy.yandex-team.ru/docs/concepts/pod/sidecars/logs/logs#format
// for more information
func NewDeployLogger(level log.Level, opts ...zap.Option) (*Logger, error) {
return NewCustomDeployLogger(
NewDeployConfig(
WithLevel(level),
),
opts...,
)
}
// NewProductionDeployConfig returns configuration, suitable for production use.
//
// It uses a JSON encoder, writes to standard error, and enables sampling.
// Stacktraces are automatically included on logs of ErrorLevel and above.
func NewProductionDeployConfig() zap.Config {
return NewDeployConfig(
WithDevelopment(false),
WithSampling(100, 100),
)
}
// Same as NewDeployLogger, but with sampling
func NewProductionDeployLogger(level log.Level, opts ...zap.Option) (*Logger, error) {
return NewCustomDeployLogger(
NewDeployConfig(
WithLevel(level),
WithDevelopment(false),
WithSampling(100, 100),
),
opts...,
)
}
func addDeployContext(i interface{}) interface{} {
switch c := i.(type) {
case *zap.Logger:
return c.With(zap.Namespace("@fields"))
case zapcore.Core:
return c.With([]zapcore.Field{zap.Namespace("@fields")})
}
return i
}