github.com/TBD54566975/ftl@v0.219.0/internal/observability/logger.go (about)

     1  package observability
     2  
     3  import (
     4  	"fmt"
     5  
     6  	"github.com/go-logr/logr"
     7  
     8  	"github.com/TBD54566975/ftl/internal/log"
     9  )
    10  
    11  type logSink struct {
    12  	keyValues map[string]interface{}
    13  	logger    *log.Logger
    14  }
    15  
    16  func NewOtelLogger(logger *log.Logger, level log.Level) logr.Logger {
    17  	sink := &logSink{
    18  		logger: logger.Scope("otel").Level(level),
    19  	}
    20  	return logr.New(sink)
    21  }
    22  
    23  var _ logr.LogSink = &logSink{}
    24  
    25  func (l *logSink) Init(info logr.RuntimeInfo) {
    26  }
    27  
    28  func (l logSink) Enabled(level int) bool {
    29  	return otelLevelToLevel(level) >= l.logger.GetLevel()
    30  }
    31  
    32  func (l logSink) Info(level int, msg string, kvs ...interface{}) {
    33  	// otel uses the following mapping for level to our log.Level
    34  	// 8 = Debug
    35  	// 4 = Info
    36  	// 1 = Warning
    37  	// 0 = Error
    38  	var logLevel log.Level
    39  	switch level {
    40  	case 4:
    41  		logLevel = log.Info
    42  	case 8:
    43  		logLevel = log.Debug
    44  	case 1:
    45  		logLevel = log.Warn
    46  	case 0:
    47  		logLevel = log.Error
    48  	default:
    49  		logLevel = log.Trace
    50  	}
    51  
    52  	logMsg := msg + " "
    53  	for k, v := range l.keyValues {
    54  		logMsg += fmt.Sprintf("%s: %+v  ", k, v)
    55  	}
    56  	for i := 0; i < len(kvs); i += 2 {
    57  		logMsg += fmt.Sprintf("%s: %+v  ", kvs[i], kvs[i+1])
    58  	}
    59  
    60  	l.logger.Logf(logLevel, logMsg)
    61  }
    62  
    63  func (l logSink) Error(err error, msg string, kvs ...interface{}) {
    64  	l.logger.Errorf(err, msg, kvs...)
    65  }
    66  
    67  func (l logSink) WithName(name string) logr.LogSink {
    68  	return &logSink{
    69  		keyValues: l.keyValues,
    70  		logger:    l.logger.Scope(name),
    71  	}
    72  }
    73  
    74  func (l logSink) WithValues(kvs ...interface{}) logr.LogSink {
    75  	newMap := make(map[string]interface{}, len(l.keyValues)+len(kvs)/2)
    76  	for k, v := range l.keyValues {
    77  		newMap[k] = v
    78  	}
    79  	for i := 0; i < len(kvs); i += 2 {
    80  		newMap[kvs[i].(string)] = kvs[i+1] //nolint:forcetypeassert
    81  	}
    82  	return &logSink{
    83  		keyValues: newMap,
    84  		logger:    l.logger,
    85  	}
    86  }
    87  
    88  func otelLevelToLevel(level int) log.Level {
    89  	switch level {
    90  	case 4:
    91  		return log.Info
    92  	case 8:
    93  		return log.Debug
    94  	case 1:
    95  		return log.Warn
    96  	case 0:
    97  		return log.Error
    98  	default:
    99  		return log.Trace
   100  	}
   101  }