safing-portbase/log/trace.go
2019-05-10 11:51:18 +02:00

223 lines
4.8 KiB
Go

package log
import (
"context"
"fmt"
"runtime"
"sync"
"sync/atomic"
"time"
)
// Key for context value
type ContextTracerKey struct{}
type ContextTracer struct {
sync.Mutex
actions []*Action
}
type Action struct {
timestamp time.Time
level severity
msg string
file string
line int
}
var (
key = ContextTracerKey{}
nilTracer *ContextTracer
)
func AddTracer(ctx context.Context) context.Context {
if ctx != nil && fastcheckLevel(TraceLevel) {
_, ok := ctx.Value(key).(*ContextTracer)
if !ok {
return context.WithValue(ctx, key, &ContextTracer{})
}
}
return ctx
}
func Tracer(ctx context.Context) *ContextTracer {
if ctx != nil {
tracer, ok := ctx.Value(key).(*ContextTracer)
if ok {
return tracer
}
}
return nilTracer
}
func (ct *ContextTracer) logTrace(level severity, msg string) {
// get file and line
_, file, line, ok := runtime.Caller(2)
if !ok {
file = ""
line = 0
} else {
if len(file) > 3 {
file = file[:len(file)-3]
} else {
file = ""
}
}
ct.Lock()
defer ct.Unlock()
ct.actions = append(ct.actions, &Action{
timestamp: time.Now(),
level: level,
msg: msg,
file: file,
line: line,
})
}
func (ct *ContextTracer) Tracef(things ...interface{}) (ok bool) {
if ct != nil {
if fastcheckLevel(TraceLevel) {
ct.logTrace(TraceLevel, fmt.Sprintf(things[0].(string), things[1:]...))
}
return true
}
return false
}
func (ct *ContextTracer) Trace(msg string) (ok bool) {
if ct != nil {
if fastcheckLevel(TraceLevel) {
ct.logTrace(TraceLevel, msg)
}
return true
}
return false
}
func (ct *ContextTracer) Warningf(things ...interface{}) (ok bool) {
if ct != nil {
if fastcheckLevel(TraceLevel) {
ct.logTrace(WarningLevel, fmt.Sprintf(things[0].(string), things[1:]...))
}
return true
}
return false
}
func (ct *ContextTracer) Warning(msg string) (ok bool) {
if ct != nil {
if fastcheckLevel(TraceLevel) {
ct.logTrace(WarningLevel, msg)
}
return true
}
return false
}
func (ct *ContextTracer) Errorf(things ...interface{}) (ok bool) {
if ct != nil {
if fastcheckLevel(TraceLevel) {
ct.logTrace(ErrorLevel, fmt.Sprintf(things[0].(string), things[1:]...))
}
return true
}
return false
}
func (ct *ContextTracer) Error(msg string) (ok bool) {
if ct != nil {
if fastcheckLevel(TraceLevel) {
ct.logTrace(ErrorLevel, msg)
}
return true
}
return false
}
func DebugTrace(ctx context.Context, msg string) (ok bool) {
tracer, ok := ctx.Value(key).(*ContextTracer)
if ok && fastcheckLevel(TraceLevel) {
log(DebugLevel, msg, tracer)
return true
}
log(DebugLevel, msg, nil)
return false
}
func DebugTracef(ctx context.Context, things ...interface{}) (ok bool) {
tracer, ok := ctx.Value(key).(*ContextTracer)
if ok && fastcheckLevel(TraceLevel) {
log(DebugLevel, fmt.Sprintf(things[0].(string), things[1:]...), tracer)
return true
}
log(DebugLevel, fmt.Sprintf(things[0].(string), things[1:]...), nil)
return false
}
func InfoTrace(ctx context.Context, msg string) (ok bool) {
tracer, ok := ctx.Value(key).(*ContextTracer)
if ok && fastcheckLevel(TraceLevel) {
log(InfoLevel, msg, tracer)
return true
}
log(InfoLevel, msg, nil)
return false
}
func InfoTracef(ctx context.Context, things ...interface{}) (ok bool) {
tracer, ok := ctx.Value(key).(*ContextTracer)
if ok && fastcheckLevel(TraceLevel) {
log(InfoLevel, fmt.Sprintf(things[0].(string), things[1:]...), tracer)
return true
}
log(InfoLevel, fmt.Sprintf(things[0].(string), things[1:]...), nil)
return false
}
func WarningTrace(ctx context.Context, msg string) (ok bool) {
tracer, ok := ctx.Value(key).(*ContextTracer)
if ok && fastcheckLevel(TraceLevel) {
log(WarningLevel, msg, tracer)
return true
}
log(WarningLevel, msg, nil)
return false
}
func WarningTracef(ctx context.Context, things ...interface{}) (ok bool) {
tracer, ok := ctx.Value(key).(*ContextTracer)
if ok && fastcheckLevel(TraceLevel) {
log(WarningLevel, fmt.Sprintf(things[0].(string), things[1:]...), tracer)
return true
}
log(WarningLevel, fmt.Sprintf(things[0].(string), things[1:]...), nil)
return false
}
func ErrorTrace(ctx context.Context, msg string) (ok bool) {
tracer, ok := ctx.Value(key).(*ContextTracer)
if ok && fastcheckLevel(TraceLevel) {
log(ErrorLevel, msg, tracer)
return true
}
log(ErrorLevel, msg, nil)
return false
}
func ErrorTracef(ctx context.Context, things ...interface{}) (ok bool) {
tracer, ok := ctx.Value(key).(*ContextTracer)
if ok && fastcheckLevel(TraceLevel) {
log(ErrorLevel, fmt.Sprintf(things[0].(string), things[1:]...), tracer)
return true
}
log(ErrorLevel, fmt.Sprintf(things[0].(string), things[1:]...), nil)
return false
}
func fastcheckLevel(level severity) bool {
if uint32(level) < atomic.LoadUint32(logLevel) {
return false
}
return true
}