package logging
import (
"fmt"
"io"
"log"
"os"
"strings"
"sync"
)
type loggerWriter struct {
sync .RWMutex
output io .Writer
}
func (lw *loggerWriter ) SetOutput (output io .Writer ) {
lw .Lock ()
defer lw .Unlock ()
lw .output = output
}
func (lw *loggerWriter ) Write (data []byte ) (int , error ) {
lw .RLock ()
defer lw .RUnlock ()
return lw .output .Write (data )
}
type DefaultLeveledLogger struct {
level LogLevel
writer *loggerWriter
trace *log .Logger
debug *log .Logger
info *log .Logger
warn *log .Logger
err *log .Logger
}
func (ll *DefaultLeveledLogger ) WithTraceLogger (log *log .Logger ) *DefaultLeveledLogger {
ll .trace = log
return ll
}
func (ll *DefaultLeveledLogger ) WithDebugLogger (log *log .Logger ) *DefaultLeveledLogger {
ll .debug = log
return ll
}
func (ll *DefaultLeveledLogger ) WithInfoLogger (log *log .Logger ) *DefaultLeveledLogger {
ll .info = log
return ll
}
func (ll *DefaultLeveledLogger ) WithWarnLogger (log *log .Logger ) *DefaultLeveledLogger {
ll .warn = log
return ll
}
func (ll *DefaultLeveledLogger ) WithErrorLogger (log *log .Logger ) *DefaultLeveledLogger {
ll .err = log
return ll
}
func (ll *DefaultLeveledLogger ) WithOutput (output io .Writer ) *DefaultLeveledLogger {
ll .writer .SetOutput (output )
return ll
}
func (ll *DefaultLeveledLogger ) logf (logger *log .Logger , level LogLevel , format string , args ...interface {}) {
if ll .level .Get () < level {
return
}
callDepth := 3
msg := fmt .Sprintf (format , args ...)
if err := logger .Output (callDepth , msg ); err != nil {
fmt .Fprintf (os .Stderr , "Unable to log: %s" , err )
}
}
func (ll *DefaultLeveledLogger ) SetLevel (newLevel LogLevel ) {
ll .level .Set (newLevel )
}
func (ll *DefaultLeveledLogger ) Trace (msg string ) {
ll .logf (ll .trace , LogLevelTrace , msg )
}
func (ll *DefaultLeveledLogger ) Tracef (format string , args ...interface {}) {
ll .logf (ll .trace , LogLevelTrace , format , args ...)
}
func (ll *DefaultLeveledLogger ) Debug (msg string ) {
ll .logf (ll .debug , LogLevelDebug , msg )
}
func (ll *DefaultLeveledLogger ) Debugf (format string , args ...interface {}) {
ll .logf (ll .debug , LogLevelDebug , format , args ...)
}
func (ll *DefaultLeveledLogger ) Info (msg string ) {
ll .logf (ll .info , LogLevelInfo , msg )
}
func (ll *DefaultLeveledLogger ) Infof (format string , args ...interface {}) {
ll .logf (ll .info , LogLevelInfo , format , args ...)
}
func (ll *DefaultLeveledLogger ) Warn (msg string ) {
ll .logf (ll .warn , LogLevelWarn , msg )
}
func (ll *DefaultLeveledLogger ) Warnf (format string , args ...interface {}) {
ll .logf (ll .warn , LogLevelWarn , format , args ...)
}
func (ll *DefaultLeveledLogger ) Error (msg string ) {
ll .logf (ll .err , LogLevelError , msg )
}
func (ll *DefaultLeveledLogger ) Errorf (format string , args ...interface {}) {
ll .logf (ll .err , LogLevelError , format , args ...)
}
func NewDefaultLeveledLoggerForScope (scope string , level LogLevel , writer io .Writer ) *DefaultLeveledLogger {
if writer == nil {
writer = os .Stderr
}
logger := &DefaultLeveledLogger {
writer : &loggerWriter {output : writer },
level : level ,
}
return logger .
WithTraceLogger (log .New (logger .writer , fmt .Sprintf ("%s TRACE: " , scope ), log .Lmicroseconds |log .Lshortfile )).
WithDebugLogger (log .New (logger .writer , fmt .Sprintf ("%s DEBUG: " , scope ), log .Lmicroseconds |log .Lshortfile )).
WithInfoLogger (log .New (logger .writer , fmt .Sprintf ("%s INFO: " , scope ), log .LstdFlags )).
WithWarnLogger (log .New (logger .writer , fmt .Sprintf ("%s WARNING: " , scope ), log .LstdFlags )).
WithErrorLogger (log .New (logger .writer , fmt .Sprintf ("%s ERROR: " , scope ), log .LstdFlags ))
}
type DefaultLoggerFactory struct {
Writer io .Writer
DefaultLogLevel LogLevel
ScopeLevels map [string ]LogLevel
}
func NewDefaultLoggerFactory () *DefaultLoggerFactory {
factory := DefaultLoggerFactory {}
factory .DefaultLogLevel = LogLevelError
factory .ScopeLevels = make (map [string ]LogLevel )
factory .Writer = os .Stderr
logLevels := map [string ]LogLevel {
"DISABLE" : LogLevelDisabled ,
"ERROR" : LogLevelError ,
"WARN" : LogLevelWarn ,
"INFO" : LogLevelInfo ,
"DEBUG" : LogLevelDebug ,
"TRACE" : LogLevelTrace ,
}
for name , level := range logLevels {
env := os .Getenv (fmt .Sprintf ("PION_LOG_%s" , name ))
if env == "" {
env = os .Getenv (fmt .Sprintf ("PIONS_LOG_%s" , name ))
}
if env == "" {
continue
}
if strings .ToLower (env ) == "all" {
if factory .DefaultLogLevel < level {
factory .DefaultLogLevel = level
}
continue
}
scopes := strings .Split (strings .ToLower (env ), "," )
for _ , scope := range scopes {
factory .ScopeLevels [scope ] = level
}
}
return &factory
}
func (f *DefaultLoggerFactory ) NewLogger (scope string ) LeveledLogger {
logLevel := f .DefaultLogLevel
if f .ScopeLevels != nil {
scopeLevel , found := f .ScopeLevels [scope ]
if found {
logLevel = scopeLevel
}
}
return NewDefaultLeveledLoggerForScope (scope , logLevel , f .Writer )
}
The pages are generated with Golds v0.8.2 . (GOOS=linux GOARCH=amd64)
Golds is a Go 101 project developed by Tapir Liu .
PR and bug reports are welcome and can be submitted to the issue list .
Please follow @zigo_101 (reachable from the left QR code) to get the latest news of Golds .