Log levels for better coupling and clarity

There are over 170 go packages using this log module which simply write the logs with 'Error' as the log level. The existing logging technique works well for terminal but it is not friendly when integrated with other systems. change will produce clearly formatted logs with appropriate log levels.
This commit is contained in:
Abhay Gupta 2018-07-17 21:14:47 +05:30 committed by GitHub
parent 5d30be412b
commit f8c068f877
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23

View file

@ -1,11 +1,15 @@
package log package log
import ( import (
"bytes"
"fmt" "fmt"
"os" "os"
"strings"
"sync/atomic"
"time" "time"
"github.com/go-stack/stack" "github.com/go-stack/stack"
"github.com/golang/glog"
) )
const timeKey = "t" const timeKey = "t"
@ -131,19 +135,22 @@ type logger struct {
} }
func (l *logger) write(msg string, lvl Lvl, ctx []interface{}, skip int) { func (l *logger) write(msg string, lvl Lvl, ctx []interface{}, skip int) {
l.h.Log(&Record{ switch lvl {
Time: time.Now(), case LvlTrace:
Lvl: lvl, glog.V(3).Info(getLogMsg(msg, newContext(l.ctx, ctx), skip))
Msg: msg, case LvlDebug:
Ctx: newContext(l.ctx, ctx), glog.V(2).Info(getLogMsg(msg, newContext(l.ctx, ctx), skip))
Call: stack.Caller(skip), case LvlInfo:
KeyNames: RecordKeyNames{ glog.Info(getLogMsg(msg, newContext(l.ctx, ctx), skip))
Time: timeKey, case LvlWarn:
Msg: msgKey, glog.Warning(getLogMsg(msg, newContext(l.ctx, ctx), skip))
Lvl: lvlKey, case LvlError:
Ctx: ctxKey, glog.Error(getLogMsg(msg, newContext(l.ctx, ctx), skip))
}, case LvlCrit:
}) glog.Fatal(getLogMsg(msg, newContext(l.ctx, ctx), skip))
default:
glog.Info(getLogMsg(msg, newContext(l.ctx, ctx), skip))
}
} }
func (l *logger) New(ctx ...interface{}) Logger { func (l *logger) New(ctx ...interface{}) Logger {
@ -193,6 +200,41 @@ func (l *logger) SetHandler(h Handler) {
l.h.Swap(h) l.h.Swap(h)
} }
// getLogMsg method returns the log message in the following format:
// <Full path of origin> <padding> <Log message> <padding> <Context key & value>
func getLogMsg(msg string, ctx []interface{}, skip int) string {
// locationEnabled is an atomic flag controlling whether the formatter should
// append the log locations too when printing entries.
atomic.StoreUint32(&locationEnabled, 0)
// Format the location path and line number.
location := fmt.Sprintf("%+v", stack.Caller(skip))
align := int(atomic.LoadUint32(&locationLength))
// Maintain the maximum location length for fancyer alignment.
if align < len(location) {
align = len(location)
atomic.StoreUint32(&locationLength, uint32(align))
}
// Specifying padding based on the maximum length of the string representing
// the location of the origin of the log.
padding := strings.Repeat(" ", align-len(location))
buf := &bytes.Buffer{}
buf.WriteString(location)
buf.WriteString(padding)
buf.WriteString(msg)
// Maintain the maximum log message length for fancier alignment.
if align < len(msg) {
align = len(msg)
atomic.StoreUint32(&locationLength, uint32(align))
}
// Specifying padding based on the maximum length of the string representing
// the logged message.
padding = strings.Repeat(" ", align-len(msg))
buf.WriteString(padding)
// Writing key-value pairs of the context into the buffer.
logfmt(buf, ctx, 0, false)
return string(buf.Bytes()[:])
}
func normalize(ctx []interface{}) []interface{} { func normalize(ctx []interface{}) []interface{} {
// if the caller passed a Ctx object, then expand it // if the caller passed a Ctx object, then expand it
if len(ctx) == 1 { if len(ctx) == 1 {