diff --git a/pkg/logger/logger.go b/pkg/logger/logger.go index 6ac6031e7..e2ed670af 100644 --- a/pkg/logger/logger.go +++ b/pkg/logger/logger.go @@ -96,6 +96,16 @@ func NewWith(cfgFn func(*zap.Config)) (Logger, error) { return &logger{core.Sugar()}, nil } +func NewWithCore(cfgFn func(*zap.Config), core zapcore.Core) (Logger, error) { + cfg := zap.NewProductionConfig() + cfgFn(&cfg) + c, err := cfg.Build() + if err != nil { + return nil, err + } + return &logger{zap.New(zapcore.NewTee(c.Core(), core)).Sugar()}, nil +} + // NewWithSync returns a new Logger with a given SyncWriter. func NewWithSync(w io.Writer) Logger { core := zapcore.NewCore(zapcore.NewJSONEncoder(zap.NewProductionEncoderConfig()), zapcore.AddSync(w), zapcore.InfoLevel) diff --git a/pkg/loop/logger.go b/pkg/loop/logger.go index 76b6bd11a..1d37ecf60 100644 --- a/pkg/loop/logger.go +++ b/pkg/loop/logger.go @@ -14,6 +14,8 @@ import ( "golang.org/x/exp/slices" "github.com/smartcontractkit/chainlink-common/pkg/logger" + "github.com/smartcontractkit/chainlink-common/pkg/logger/otelzap" + otellog "go.opentelemetry.io/otel/log" ) // HCLogLogger returns an [hclog.Logger] backed by the given [logger.Logger]. @@ -171,6 +173,17 @@ func NewLogger() (logger.Logger, error) { }) } +func NewOtelLogger(otelLogger otellog.Logger) (logger.Logger, error) { + cfgFn := func(cfg *zap.Config) { + cfg.Level.SetLevel(zap.DebugLevel) + cfg.EncoderConfig.LevelKey = "@level" + cfg.EncoderConfig.MessageKey = "@message" + cfg.EncoderConfig.TimeKey = "@timestamp" + cfg.EncoderConfig.EncodeTime = zapcore.TimeEncoderOfLayout("2006-01-02T15:04:05.000000Z07:00") + } + return logger.NewWithCore(cfgFn, otelzap.NewCore(otelLogger)) +} + // onceValue returns a function that invokes f only once and returns the value // returned by f. The returned function may be called concurrently. // diff --git a/pkg/loop/server.go b/pkg/loop/server.go index 4523e48a8..6d7d84457 100644 --- a/pkg/loop/server.go +++ b/pkg/loop/server.go @@ -148,6 +148,14 @@ func (s *Server) start() error { } beholder.SetClient(beholderClient) beholder.SetGlobalOtelProviders() + + if beholderCfg.LogStreamingEnabled { + otelLogger, err := NewOtelLogger(beholder.GetLogger()) + if err != nil { + return fmt.Errorf("failed to enable log streaming: %w", err) + } + s.Logger = logger.Sugared(logger.Named(otelLogger, s.Logger.Name())) + } } s.promServer = NewPromServer(s.EnvConfig.PrometheusPort, s.Logger)