go.undefinedlabs.com/scopeagent@v0.4.2/instrumentation/logrus/hook.go (about) 1 package logrus 2 3 import ( 4 "fmt" 5 "path/filepath" 6 7 "github.com/opentracing/opentracing-go" 8 otLog "github.com/opentracing/opentracing-go/log" 9 10 log "github.com/sirupsen/logrus" 11 12 "go.undefinedlabs.com/scopeagent/tags" 13 "go.undefinedlabs.com/scopeagent/tracer" 14 ) 15 16 type ( 17 ScopeHook struct { 18 LogLevels []log.Level 19 } 20 ) 21 22 var scopeHook = &ScopeHook{} 23 24 // Adds an scope hook in the logger if is not already added. 25 func AddScopeHook(logger *log.Logger) { 26 // We check first if the logger already contains a ScopeHook instance 27 for _, hooks := range logger.Hooks { 28 for _, hook := range hooks { 29 if _, ok := hook.(*ScopeHook); ok { 30 return 31 } 32 } 33 } 34 logger.AddHook(scopeHook) 35 } 36 37 // Fire will be called when some logging function is called with current hook 38 // It will format log entry to string and write it to appropriate writer 39 func (hook *ScopeHook) Fire(entry *log.Entry) error { 40 if entry.Context == nil { 41 return nil 42 } 43 44 // If context is found, we try to find the a span from the context and write the logs 45 if span := opentracing.SpanFromContext(entry.Context); span != nil { 46 47 logLevel := tags.LogLevel_VERBOSE 48 if entry.Level == log.PanicLevel || entry.Level == log.FatalLevel || entry.Level == log.ErrorLevel { 49 logLevel = tags.LogLevel_ERROR 50 } else if entry.Level == log.WarnLevel { 51 logLevel = tags.LogLevel_WARNING 52 } else if entry.Level == log.InfoLevel { 53 logLevel = tags.LogLevel_INFO 54 } else if entry.Level == log.DebugLevel { 55 logLevel = tags.LogLevel_DEBUG 56 } else if entry.Level == log.TraceLevel { 57 logLevel = tags.LogLevel_VERBOSE 58 } 59 60 fields := []otLog.Field{ 61 otLog.String(tags.EventType, tags.LogEvent), 62 otLog.String(tags.LogEventLevel, logLevel), 63 otLog.String("log.logger", "logrus"), 64 otLog.String("log.level", entry.Level.String()), 65 otLog.String(tags.EventMessage, entry.Message), 66 } 67 68 if entry.Caller != nil && entry.Caller.File != "" && entry.Caller.Line != 0 { 69 fields = append(fields, otLog.String(tags.EventSource, fmt.Sprintf("%s:%d", filepath.Clean(entry.Caller.File), entry.Caller.Line))) 70 } 71 72 if entry.Data != nil { 73 for k, v := range entry.Data { 74 fields = append(fields, otLog.Object(k, v)) 75 } 76 } 77 78 if ownSpan, ok := span.(tracer.Span); ok { 79 ownSpan.LogFieldsWithTimestamp(entry.Time, fields...) 80 } else { 81 span.LogFields(fields...) 82 } 83 } 84 return nil 85 } 86 87 // Levels define on which log levels this hook would trigger 88 func (hook *ScopeHook) Levels() []log.Level { 89 if hook.LogLevels == nil { 90 hook.LogLevels = []log.Level{ 91 log.PanicLevel, 92 log.FatalLevel, 93 log.ErrorLevel, 94 log.WarnLevel, 95 log.InfoLevel, 96 log.DebugLevel, 97 log.TraceLevel, 98 } 99 } 100 return hook.LogLevels 101 }