logger.go 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142
  1. // Copyright The OpenTelemetry Authors
  2. // SPDX-License-Identifier: Apache-2.0
  3. package internal // import "github.com/open-telemetry/opentelemetry-collector-contrib/receiver/prometheusreceiver/internal"
  4. import (
  5. gokitLog "github.com/go-kit/log"
  6. "github.com/go-kit/log/level"
  7. "go.uber.org/zap"
  8. )
  9. const (
  10. levelKey = "level"
  11. msgKey = "msg"
  12. errKey = "err"
  13. )
  14. // NewZapToGokitLogAdapter create an adapter for zap.Logger to gokitLog.Logger
  15. func NewZapToGokitLogAdapter(logger *zap.Logger) gokitLog.Logger {
  16. // need to skip two levels in order to get the correct caller
  17. // one for this method, the other for gokitLog
  18. logger = logger.WithOptions(zap.AddCallerSkip(2))
  19. return &zapToGokitLogAdapter{l: logger.Sugar()}
  20. }
  21. type zapToGokitLogAdapter struct {
  22. l *zap.SugaredLogger
  23. }
  24. type logData struct {
  25. level level.Value
  26. msg string
  27. otherFields []any
  28. }
  29. func (w *zapToGokitLogAdapter) Log(keyvals ...any) error {
  30. // expecting key value pairs, the number of items need to be even
  31. if len(keyvals)%2 == 0 {
  32. // Extract log level and message and log them using corresponding zap function
  33. ld := extractLogData(keyvals)
  34. logFunc := levelToFunc(w.l, ld.level)
  35. logFunc(ld.msg, ld.otherFields...)
  36. } else {
  37. // in case something goes wrong
  38. w.l.Info(keyvals...)
  39. }
  40. return nil
  41. }
  42. func extractLogData(keyvals []any) logData {
  43. ld := logData{
  44. level: level.InfoValue(), // default
  45. }
  46. for i := 0; i < len(keyvals); i += 2 {
  47. key := keyvals[i]
  48. val := keyvals[i+1]
  49. if l, ok := matchLogLevel(key, val); ok {
  50. ld.level = l
  51. continue
  52. }
  53. if m, ok := matchLogMessage(key, val); ok {
  54. ld.msg = m
  55. continue
  56. }
  57. if err, ok := matchError(key, val); ok {
  58. ld.otherFields = append(ld.otherFields, zap.Error(err))
  59. continue
  60. }
  61. ld.otherFields = append(ld.otherFields, key, val)
  62. }
  63. return ld
  64. }
  65. // check if a given key-value pair represents go-kit log message and return it
  66. func matchLogMessage(key any, val any) (string, bool) {
  67. if strKey, ok := key.(string); !ok || strKey != msgKey {
  68. return "", false
  69. }
  70. msg, ok := val.(string)
  71. if !ok {
  72. return "", false
  73. }
  74. return msg, true
  75. }
  76. // check if a given key-value pair represents go-kit log level and return it
  77. func matchLogLevel(key any, val any) (level.Value, bool) {
  78. strKey, ok := key.(string)
  79. if !ok || strKey != levelKey {
  80. return nil, false
  81. }
  82. levelVal, ok := val.(level.Value)
  83. if !ok {
  84. return nil, false
  85. }
  86. return levelVal, true
  87. }
  88. //revive:disable:error-return
  89. // check if a given key-value pair represents an error and return it
  90. func matchError(key any, val any) (error, bool) {
  91. strKey, ok := key.(string)
  92. if !ok || strKey != errKey {
  93. return nil, false
  94. }
  95. err, ok := val.(error)
  96. if !ok {
  97. return nil, false
  98. }
  99. return err, true
  100. }
  101. //revive:enable:error-return
  102. // find a matching zap logging function to be used for a given level
  103. func levelToFunc(logger *zap.SugaredLogger, lvl level.Value) func(string, ...any) {
  104. switch lvl {
  105. case level.DebugValue():
  106. return logger.Debugw
  107. case level.InfoValue():
  108. return logger.Infow
  109. case level.WarnValue():
  110. return logger.Warnw
  111. case level.ErrorValue():
  112. return logger.Errorw
  113. }
  114. // default
  115. return logger.Infow
  116. }
  117. var _ gokitLog.Logger = (*zapToGokitLogAdapter)(nil)