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  }