12
"go.avito.ru/DO/moira"
13
"go.avito.ru/DO/moira/logging/go-logging"
14
"go.avito.ru/DO/moira/metrics"
33
func Init(appComponent string, config Config, rateLimit moira.RateLimit) error {
38
return ErrAlreadyInitialized{}
41
hostname, err := os.Hostname()
43
return ErrFailedInitialize{reason: err}
46
level, weight := parseLogLevel(config.Level)
50
enabled: config.Enabled,
59
fallback, _ = logging.ConfigureLog(config.Fallback, level, appComponent)
60
loggersStore = newStore()
61
statsd = metrics.NewLoggerMetric()
63
worker, err = newLoggingWorker()
65
return ErrFailedInitialize{reason: err}
72
// GetLogger returns logger instance for given id
73
// id must be either uuid or empty string
74
func GetLogger(id string) *Logger {
75
if cfg == nil || loggersStore == nil {
76
panic(ErrNotInitialized{})
79
return loggersStore.getOrCreate(id)
82
// GetLoggerSafe is equivalent to GetLogger
83
// but returns an error instead of panic
84
// if something goes wrong
85
func GetLoggerSafe(id string) (logger *Logger, err error) {
87
if r := recover(); r != nil {
88
err = fmt.Errorf("failed to get logger: panic = %v", r)
92
logger = GetLogger(id)
96
func (logger *Logger) Debug(message string) {
97
logger.log(logLevelDebug, message, nil)
100
func (logger *Logger) DebugE(message string, extra interface{}) {
101
logger.log(logLevelDebug, message, extra)
104
func (logger *Logger) DebugF(format string, args ...interface{}) {
105
logger.log(logLevelDebug, fmt.Sprintf(format, args...), nil)
108
func (logger *Logger) Info(message string) {
109
logger.log(logLevelInfo, message, nil)
112
func (logger *Logger) InfoE(message string, extra interface{}) {
113
logger.log(logLevelInfo, message, extra)
116
func (logger *Logger) InfoF(format string, args ...interface{}) {
117
logger.log(logLevelInfo, fmt.Sprintf(format, args...), nil)
120
func (logger *Logger) Warn(message string) {
121
logger.log(logLevelWarn, message, nil)
124
func (logger *Logger) WarnE(message string, extra interface{}) {
125
logger.log(logLevelWarn, message, extra)
128
func (logger *Logger) WarnF(format string, args ...interface{}) {
129
logger.log(logLevelWarn, fmt.Sprintf(format, args...), nil)
132
func (logger *Logger) Error(message string) {
133
logger.log(logLevelError, message, nil)
136
func (logger *Logger) ErrorE(message string, extra interface{}) {
137
logger.log(logLevelError, message, extra)
140
func (logger *Logger) ErrorF(format string, args ...interface{}) {
141
logger.log(logLevelError, fmt.Sprintf(format, args...), nil)
144
func (logger *Logger) Fatal(message string) {
145
logger.log(logLevelFatal, message, nil)
149
func (logger *Logger) FatalE(message string, extra interface{}) {
150
logger.log(logLevelFatal, message, extra)
154
func (logger *Logger) FatalF(format string, args ...interface{}) {
155
logger.log(logLevelFatal, fmt.Sprintf(format, args...), nil)
159
func (logger *Logger) TracePanic(message string, extra interface{}) {
160
logger.ErrorE(message, extra)
161
useFallbackLogger(logLevelError, message, extra)
164
func (logger *Logger) TraceSelfStats(id string, started time.Time) {
165
margin := moira.TriggerCheckThreshold * time.Second
166
passed := time.Since(started)
168
log := newInstance("self-stats")
169
msg := fmt.Sprintf("Total log calls for id %s: %d", id, logger.callCounter)
170
extra := map[string]interface{}{
171
"calls": logger.callCounter,
172
"duration": passed.String(),
177
log.InfoE(msg, extra)
179
log.ErrorE(msg, extra)
183
func (logger *Logger) log(level, message string, extra interface{}) {
185
worker.queue <- &logDelayedMessage{
186
component: logger.appComponent,
187
contextId: logger.contextID,
188
dateTime: time.Now(),
196
func (logger *Logger) setContextID(contextID uint64) {
197
logger.contextID = ContextID(contextID)
200
func (logger *Logger) setContextIDFromUUID(uuidRaw string) {
201
// remove all dashes and prepend leading zero if needed
202
uuid := strings.Replace(uuidRaw, "-", "", -1)
204
uuid = strings.Repeat("0", 32-len(uuid)) + uuid
207
// split uuid to 2 equal parts and parse them as integers
208
x1, _ := big.NewInt(0).SetString(uuid[:16], 16)
209
x2, _ := big.NewInt(0).SetString(uuid[16:], 16)
213
mod.Exp(mod, big.NewInt(64), nil)
215
// (x1 + x2) % (2 ** 64)
221
panic(fmt.Sprintf("Could not parse %s as integer", uuidRaw))
223
logger.setContextID(x3.Uint64())
227
func formatPath(skipFrames int) string {
228
pc, file, line, _ := runtime.Caller(skipFrames)
229
_, fileName := path.Split(file)
230
parts := strings.Split(runtime.FuncForPC(pc).Name(), ".")
231
partsTotal := len(parts)
234
funcName := parts[partsTotal-1]
236
if parts[partsTotal-2][0] == '(' {
237
funcName = parts[partsTotal-2] + "." + funcName
238
packageName = strings.Join(parts[0:partsTotal-2], ".")
240
packageName = strings.Join(parts[0:partsTotal-1], ".")
243
return fmt.Sprintf("[%s] %s: %s#%d", packageName, fileName, funcName, line)
246
func newInstance(id string) *Logger {
248
appComponent: cfg.app,
253
logger.setContextID(defaultContextId)
254
} else if id == "panic" {
255
logger.setContextID(panicContextId)
256
} else if id == "self-stats" {
257
logger.setContextID(selfStatsContextId)
259
logger.setContextIDFromUUID(id)