X-Git-Url: https://gerrit.akraino.org/r/gitweb?a=blobdiff_plain;f=src%2Ffoundation%2Fapi%2Frevel%2Flogger%2Fwrap_handlers.go;fp=src%2Ffoundation%2Fapi%2Frevel%2Flogger%2Fwrap_handlers.go;h=3d68e750a7710b612fb1cec757db7eb72e0f69ed;hb=1d1ee6961c93781e1187d8c7faa868da6b2f01f4;hp=0000000000000000000000000000000000000000;hpb=56dd5e0f2164b37b40ac1daa188ccc618b4cbd19;p=iec.git diff --git a/src/foundation/api/revel/logger/wrap_handlers.go b/src/foundation/api/revel/logger/wrap_handlers.go new file mode 100644 index 0000000..3d68e75 --- /dev/null +++ b/src/foundation/api/revel/logger/wrap_handlers.go @@ -0,0 +1,98 @@ +package logger + +// FuncHandler returns a Handler that logs records with the given +// function. +import ( + "fmt" + "reflect" + "sync" + "time" +) + +// Function handler wraps the declared function and returns the handler for it +func FuncHandler(fn func(r *Record) error) LogHandler { + return funcHandler(fn) +} + +// The type decleration for the function +type funcHandler func(r *Record) error + +// The implementation of the Log +func (h funcHandler) Log(r *Record) error { + return h(r) +} + +// This function allows you to do a full declaration for the log, +// it is recommended you use FuncHandler instead +func HandlerFunc(log func(message string, time time.Time, level LogLevel, call CallStack, context ContextMap) error) LogHandler { + return remoteHandler(log) +} + +// The type used for the HandlerFunc +type remoteHandler func(message string, time time.Time, level LogLevel, call CallStack, context ContextMap) error + +// The Log implementation +func (c remoteHandler) Log(record *Record) error { + return c(record.Message, record.Time, record.Level, record.Call, record.Context) +} + +// SyncHandler can be wrapped around a handler to guarantee that +// only a single Log operation can proceed at a time. It's necessary +// for thread-safe concurrent writes. +func SyncHandler(h LogHandler) LogHandler { + var mu sync.Mutex + return FuncHandler(func(r *Record) error { + defer mu.Unlock() + mu.Lock() + return h.Log(r) + }) +} + +// LazyHandler writes all values to the wrapped handler after evaluating +// any lazy functions in the record's context. It is already wrapped +// around StreamHandler and SyslogHandler in this library, you'll only need +// it if you write your own Handler. +func LazyHandler(h LogHandler) LogHandler { + return FuncHandler(func(r *Record) error { + for k, v := range r.Context { + if lz, ok := v.(Lazy); ok { + value, err := evaluateLazy(lz) + if err != nil { + r.Context[errorKey] = "bad lazy " + k + } else { + v = value + } + } + } + + return h.Log(r) + }) +} + +func evaluateLazy(lz Lazy) (interface{}, error) { + t := reflect.TypeOf(lz.Fn) + + if t.Kind() != reflect.Func { + return nil, fmt.Errorf("INVALID_LAZY, not func: %+v", lz.Fn) + } + + if t.NumIn() > 0 { + return nil, fmt.Errorf("INVALID_LAZY, func takes args: %+v", lz.Fn) + } + + if t.NumOut() == 0 { + return nil, fmt.Errorf("INVALID_LAZY, no func return val: %+v", lz.Fn) + } + + value := reflect.ValueOf(lz.Fn) + results := value.Call([]reflect.Value{}) + if len(results) == 1 { + return results[0].Interface(), nil + } else { + values := make([]interface{}, len(results)) + for i, v := range results { + values[i] = v.Interface() + } + return values, nil + } +}