Move to Ubuntu 18 image
[ric-plt/e2mgr.git] / E2Manager / logger / logger.go
1 //
2 // Copyright 2019 AT&T Intellectual Property
3 // Copyright 2019 Nokia
4 //
5 // Licensed under the Apache License, Version 2.0 (the "License");
6 // you may not use this file except in compliance with the License.
7 // You may obtain a copy of the License at
8 //
9 //      http://www.apache.org/licenses/LICENSE-2.0
10 //
11 // Unless required by applicable law or agreed to in writing, software
12 // distributed under the License is distributed on an "AS IS" BASIS,
13 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 // See the License for the specific language governing permissions and
15 // limitations under the License.
16
17 //  This source code is part of the near-RT RIC (RAN Intelligent Controller)
18 //  platform project (RICP).
19
20
21 package logger
22
23 import (
24         "fmt"
25         "go.uber.org/zap"
26         "go.uber.org/zap/zapcore"
27         "strings"
28         "time"
29 )
30
31 type Logger struct {
32         Logger     *zap.Logger
33 }
34
35 // Copied from zap logger
36 //
37 // A Level is a logging priority. Higher levels are more important.
38 type LogLevel int8
39
40 const (
41         // DebugLevel logs are typically voluminous, and are usually disabled in
42         // production.
43         DebugLevel LogLevel = iota - 1
44         // InfoLevel is the default logging priority.
45         InfoLevel
46         // WarnLevel logs are more important than Info, but don't need individual
47         // human review.
48         WarnLevel
49         // ErrorLevel logs are high-priority. If an application is running smoothly,
50         // it shouldn't generate any error-level logs.
51         ErrorLevel
52         // DPanicLevel logs are particularly important errors. In development the
53         // logger panics after writing the message.
54         DPanicLevel
55         // PanicLevel logs a message, then panics.
56         PanicLevel
57         // FatalLevel logs a message, then calls os.Exit(1).
58         FatalLevel
59
60         _minLevel = DebugLevel
61         _maxLevel = FatalLevel
62 )
63
64 var logLevelTokenToLevel = map[string] LogLevel {
65         "debug" : DebugLevel,
66         "info": InfoLevel,
67         "warn": WarnLevel,
68         "error": ErrorLevel,
69         "dpanic": DPanicLevel,
70         "panic": PanicLevel,
71         "fatal": FatalLevel,
72 }
73
74 func LogLevelTokenToLevel(level string) (LogLevel, bool) {
75         if level, ok := logLevelTokenToLevel[strings.TrimSpace(strings.ToLower(level))];ok {
76                 return level, true
77         }
78         return _maxLevel+1, false
79 }
80
81 func InitLogger(requested LogLevel) (*Logger, error) {
82         var logger *zap.Logger
83         var err error
84         switch requested {
85         case DebugLevel:
86                 logger, err = initLoggerByLevel(zapcore.DebugLevel)
87         case InfoLevel:
88                 logger, err = initLoggerByLevel(zapcore.InfoLevel)
89         case WarnLevel:
90                 logger, err = initLoggerByLevel(zapcore.WarnLevel)
91         case ErrorLevel:
92                 logger, err = initLoggerByLevel(zapcore.ErrorLevel)
93         case DPanicLevel:
94                 logger, err = initLoggerByLevel(zapcore.DPanicLevel)
95         case PanicLevel:
96                 logger, err = initLoggerByLevel(zapcore.PanicLevel)
97         case FatalLevel:
98                 logger, err = initLoggerByLevel(zapcore.FatalLevel)
99         default:
100                 err = fmt.Errorf("Invalid logging Level :%d",requested)
101         }
102         if err != nil {
103                 return nil, err
104         }
105         return &Logger{Logger:logger}, nil
106
107 }
108 func(l *Logger)Sync() error {
109         l.Debugf("#logger.Sync - Going to flush buffered log")
110         return l.Logger.Sync()
111 }
112
113 func (l *Logger)Infof(formatMsg string, a ...interface{})  {
114         if l.InfoEnabled() {
115                 msg := fmt.Sprintf(formatMsg, a...)
116                 l.Logger.Info(msg, zap.Any("mdc", l.getTimeStampMdc()))
117         }
118 }
119
120 func (l *Logger)Debugf(formatMsg string, a ...interface{})  {
121         if l.DebugEnabled(){
122                 msg := fmt.Sprintf(formatMsg, a...)
123                 l.Logger.Debug(msg, zap.Any("mdc", l.getTimeStampMdc()))
124         }
125 }
126
127 func (l *Logger)Errorf(formatMsg string, a ...interface{})  {
128         msg := fmt.Sprintf(formatMsg, a...)
129         l.Logger.Error(msg, zap.Any("mdc", l.getTimeStampMdc()))
130 }
131
132 func (l *Logger)Warnf(formatMsg string, a ...interface{})  {
133         msg := fmt.Sprintf(formatMsg, a...)
134         l.Logger.Warn(msg, zap.Any("mdc", l.getTimeStampMdc()))
135 }
136
137 func (l *Logger) getTimeStampMdc() map[string]string {
138         timeStr := time.Now().Format("2006-01-02 15:04:05.000")
139         mdc := map[string]string{"time": timeStr}
140         return mdc
141 }
142
143 func (l *Logger)InfoEnabled()bool{
144         return l.Logger.Core().Enabled(zap.InfoLevel)
145 }
146
147 func (l *Logger)DebugEnabled()bool{
148         return l.Logger.Core().Enabled(zap.DebugLevel)
149 }
150
151 func (l *Logger)DPanicf(formatMsg string, a ...interface{})  {
152         msg := fmt.Sprintf(formatMsg, a...)
153         l.Logger.DPanic(msg, zap.Any("mdc", l.getTimeStampMdc()))
154 }
155
156 func initLoggerByLevel(l zapcore.Level) (*zap.Logger, error) {
157         cfg := zap.Config{
158                 Encoding:         "json",
159                 Level:            zap.NewAtomicLevelAt(l),
160                 OutputPaths:      []string{"stdout"},
161                 ErrorOutputPaths: []string{"stderr"},
162                 EncoderConfig: zapcore.EncoderConfig{
163                         MessageKey: "msg",
164
165                         LevelKey:    "crit",
166                         EncodeLevel: zapcore.CapitalLevelEncoder,
167
168                         TimeKey:    "ts",
169                         EncodeTime: epochMillisIntegerTimeEncoder,
170
171                         CallerKey: "id",
172                         EncodeCaller: e2ManagerCallerEncoder,
173                 },
174         }
175         return cfg.Build()
176 }
177
178 func e2ManagerCallerEncoder(caller zapcore.EntryCaller, enc zapcore.PrimitiveArrayEncoder) {
179         enc.AppendString("E2Manager")
180 }
181
182 func epochMillisIntegerTimeEncoder(t time.Time, enc zapcore.PrimitiveArrayEncoder) {
183         nanos := t.UnixNano()
184         millis := int64(nanos) / int64(time.Millisecond)
185         enc.AppendInt64(millis)
186 }
187