2 * Copyright (c) 2019 AT&T Intellectual Property.
3 * Copyright (c) 2018-2019 Nokia.
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
9 * http://www.apache.org/licenses/LICENSE-2.0
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.
18 // Package golog implements a simple structured logging with MDC (Mapped Diagnostics Context) support.
31 // Level is a type define for the logging level.
35 // ERR is an error level log entry.
37 // WARN is a warning level log entry.
39 // INFO is an info level log entry.
41 // DEBUG is a debug level log entry.
45 // MdcLogger is the logger instance, created with InitLogger() function.
46 type MdcLogger struct {
54 type logEntry struct {
56 Crit string `json:"crit"`
58 Mdc map[string]string `json:"mdc"`
59 Msg string `json:"msg"`
62 func levelString(level Level) string {
77 func getTime() int64 {
78 ns := time.Time.UnixNano(time.Now())
79 return ns / int64(time.Millisecond)
82 func (l *MdcLogger) formatLog(level Level, msg string) ([]byte, error) {
83 log := logEntry{getTime(), levelString(level), l.proc, l.mdc, msg}
84 buf := bytes.NewBuffer(nil)
85 encoder := json.NewEncoder(buf)
86 encoder.SetEscapeHTML(false)
87 err := encoder.Encode(log)
88 return buf.Bytes(), err
91 func initLogger(proc string, writer io.Writer) (*MdcLogger, error) {
92 return &MdcLogger{proc: proc, writer: writer, mdc: make(map[string]string), level: DEBUG}, nil
95 // InitLogger is the init routine which returns a new logger instance.
96 // The program identity is given as a parameter. The identity
97 // is added to every log writing.
98 // The function returns a new instance or an error.
99 func InitLogger(proc string) (*MdcLogger, error) {
100 return initLogger(proc, os.Stdout)
103 // Log is the basic logging function to write a log message with
105 func (l *MdcLogger) Log(level Level, formatMsg string, a ...interface{}) {
107 defer l.mutex.Unlock()
111 log, err := l.formatLog(level, fmt.Sprintf(formatMsg, a...))
117 // Error is the "error" level logging function.
118 func (l *MdcLogger) Error(formatMsg string, a ...interface{}) {
119 l.Log(ERR, formatMsg, a...)
122 // Warning is the "warning" level logging function.
123 func (l *MdcLogger) Warning(formatMsg string, a ...interface{}) {
124 l.Log(WARN, formatMsg, a...)
127 // Info is the "info" level logging function.
128 func (l *MdcLogger) Info(formatMsg string, a ...interface{}) {
129 l.Log(INFO, formatMsg, a...)
132 // Debug is the "debug" level logging function.
133 func (l *MdcLogger) Debug(formatMsg string, a ...interface{}) {
134 l.Log(DEBUG, formatMsg, a...)
137 // LevelSet sets the current logging level.
138 // Log writings with less significant level are discarded.
139 func (l *MdcLogger) LevelSet(level Level) {
143 // LevelGet returns the current logging level.
144 func (l *MdcLogger) LevelGet() Level {
148 // MdcAdd adds a new MDC key value pair to the logger.
149 func (l *MdcLogger) MdcAdd(key string, value string) {
151 defer l.mutex.Unlock()
155 // MdcRemove removes an MDC key from the logger.
156 func (l *MdcLogger) MdcRemove(key string) {
158 defer l.mutex.Unlock()
162 // MdcGet gets the value of an MDC from the logger.
163 // The function returns the value string and a boolean
164 // which tells if the key was found or not.
165 func (l *MdcLogger) MdcGet(key string) (string, bool) {
167 defer l.mutex.Unlock()
168 val, ok := l.mdc[key]
172 // MdcClean removes all MDC keys from the logger.
173 func (l *MdcLogger) MdcClean() {
175 defer l.mutex.Unlock()
176 l.mdc = make(map[string]string)