123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142 |
- // Copyright The OpenTelemetry Authors
- // SPDX-License-Identifier: Apache-2.0
- package internal // import "github.com/open-telemetry/opentelemetry-collector-contrib/receiver/prometheusreceiver/internal"
- import (
- gokitLog "github.com/go-kit/log"
- "github.com/go-kit/log/level"
- "go.uber.org/zap"
- )
- const (
- levelKey = "level"
- msgKey = "msg"
- errKey = "err"
- )
- // NewZapToGokitLogAdapter create an adapter for zap.Logger to gokitLog.Logger
- func NewZapToGokitLogAdapter(logger *zap.Logger) gokitLog.Logger {
- // need to skip two levels in order to get the correct caller
- // one for this method, the other for gokitLog
- logger = logger.WithOptions(zap.AddCallerSkip(2))
- return &zapToGokitLogAdapter{l: logger.Sugar()}
- }
- type zapToGokitLogAdapter struct {
- l *zap.SugaredLogger
- }
- type logData struct {
- level level.Value
- msg string
- otherFields []any
- }
- func (w *zapToGokitLogAdapter) Log(keyvals ...any) error {
- // expecting key value pairs, the number of items need to be even
- if len(keyvals)%2 == 0 {
- // Extract log level and message and log them using corresponding zap function
- ld := extractLogData(keyvals)
- logFunc := levelToFunc(w.l, ld.level)
- logFunc(ld.msg, ld.otherFields...)
- } else {
- // in case something goes wrong
- w.l.Info(keyvals...)
- }
- return nil
- }
- func extractLogData(keyvals []any) logData {
- ld := logData{
- level: level.InfoValue(), // default
- }
- for i := 0; i < len(keyvals); i += 2 {
- key := keyvals[i]
- val := keyvals[i+1]
- if l, ok := matchLogLevel(key, val); ok {
- ld.level = l
- continue
- }
- if m, ok := matchLogMessage(key, val); ok {
- ld.msg = m
- continue
- }
- if err, ok := matchError(key, val); ok {
- ld.otherFields = append(ld.otherFields, zap.Error(err))
- continue
- }
- ld.otherFields = append(ld.otherFields, key, val)
- }
- return ld
- }
- // check if a given key-value pair represents go-kit log message and return it
- func matchLogMessage(key any, val any) (string, bool) {
- if strKey, ok := key.(string); !ok || strKey != msgKey {
- return "", false
- }
- msg, ok := val.(string)
- if !ok {
- return "", false
- }
- return msg, true
- }
- // check if a given key-value pair represents go-kit log level and return it
- func matchLogLevel(key any, val any) (level.Value, bool) {
- strKey, ok := key.(string)
- if !ok || strKey != levelKey {
- return nil, false
- }
- levelVal, ok := val.(level.Value)
- if !ok {
- return nil, false
- }
- return levelVal, true
- }
- //revive:disable:error-return
- // check if a given key-value pair represents an error and return it
- func matchError(key any, val any) (error, bool) {
- strKey, ok := key.(string)
- if !ok || strKey != errKey {
- return nil, false
- }
- err, ok := val.(error)
- if !ok {
- return nil, false
- }
- return err, true
- }
- //revive:enable:error-return
- // find a matching zap logging function to be used for a given level
- func levelToFunc(logger *zap.SugaredLogger, lvl level.Value) func(string, ...any) {
- switch lvl {
- case level.DebugValue():
- return logger.Debugw
- case level.InfoValue():
- return logger.Infow
- case level.WarnValue():
- return logger.Warnw
- case level.ErrorValue():
- return logger.Errorw
- }
- // default
- return logger.Infow
- }
- var _ gokitLog.Logger = (*zapToGokitLogAdapter)(nil)
|