blob: 84a99878dc65d1e62c4fb5258e925836d535d6c8 [file] [log] [blame]
iomodoc6abf5b2021-02-19 14:48:03 +04001package log
2
3import (
4 "os"
5
6 "go.uber.org/zap"
7 "go.uber.org/zap/zapcore"
8 "gopkg.in/natefinch/lumberjack.v2"
9)
10
11const (
12 // LevelDebug represents very verbose messages for debugging specific issues
13 LevelDebug = "debug"
14 // LevelInfo represents default log level, informational
15 LevelInfo = "info"
16 // LevelWarn represents messages about possible issues
17 LevelWarn = "warn"
18 // LevelError represents messages about things we know are problems
19 LevelError = "error"
20)
21
22// Type and function aliases from zap to limit the libraries scope into our code
23type Field = zapcore.Field
24
25var Int = zap.Int
26var String = zap.String
27var Any = zap.Any
28var Err = zap.Error
29var Time = zap.Time
30var Duration = zap.Duration
31
32// Logger logs messages
33type Logger struct {
34 zap *zap.Logger
35 consoleLevel zap.AtomicLevel
36 fileLevel zap.AtomicLevel
37}
38
39// LoggerConfiguration represents configuration of the logger
40type LoggerConfiguration struct {
41 EnableConsole bool
42 ConsoleJSON bool
43 ConsoleLevel string
44 EnableFile bool
45 FileJSON bool
46 FileLevel string
47 FileLocation string
48}
49
50// NewLogger creates new logger
51func NewLogger(config *LoggerConfiguration) *Logger {
52 cores := []zapcore.Core{}
53 logger := &Logger{
54 consoleLevel: zap.NewAtomicLevelAt(getZapLevel(config.ConsoleLevel)),
55 fileLevel: zap.NewAtomicLevelAt(getZapLevel(config.FileLevel)),
56 }
57
58 if config.EnableConsole {
59 writer := zapcore.Lock(os.Stderr)
60 core := zapcore.NewCore(makeEncoder(config.ConsoleJSON), writer, logger.consoleLevel)
61 cores = append(cores, core)
62 }
63
64 if config.EnableFile {
65 writer := zapcore.AddSync(&lumberjack.Logger{
66 Filename: config.FileLocation,
67 MaxSize: 100,
68 Compress: true,
69 })
70 core := zapcore.NewCore(makeEncoder(config.FileJSON), writer, logger.fileLevel)
71 cores = append(cores, core)
72 }
73
74 combinedCore := zapcore.NewTee(cores...)
75
76 logger.zap = zap.New(combinedCore,
77 zap.AddCaller(),
78 )
79
80 return logger
81}
82
83func (l *Logger) Debug(message string, fields ...Field) {
84 l.zap.Debug(message, fields...)
85}
86
87func (l *Logger) Info(message string, fields ...Field) {
88 l.zap.Info(message, fields...)
89}
90
91func (l *Logger) Warn(message string, fields ...Field) {
92 l.zap.Warn(message, fields...)
93}
94
95func (l *Logger) Error(message string, fields ...Field) {
96 l.zap.Error(message, fields...)
97}
98
99func getZapLevel(level string) zapcore.Level {
100 switch level {
101 case LevelInfo:
102 return zapcore.InfoLevel
103 case LevelWarn:
104 return zapcore.WarnLevel
105 case LevelDebug:
106 return zapcore.DebugLevel
107 case LevelError:
108 return zapcore.ErrorLevel
109 default:
110 return zapcore.InfoLevel
111 }
112}
113
114func makeEncoder(json bool) zapcore.Encoder {
115 encoderConfig := zap.NewProductionEncoderConfig()
116 if json {
117 return zapcore.NewJSONEncoder(encoderConfig)
118 }
119
120 encoderConfig.EncodeTime = zapcore.ISO8601TimeEncoder
121 return zapcore.NewConsoleEncoder(encoderConfig)
122}