Files
grafana/pkg/plugins/log/logger.go
Will Browne 466a27deff Plugins: Remove pkg/infra/log as dependency (#115832)
* remove pkg/infra/log as dependency

* add pluginslog

* add slog caching
2026-01-06 14:44:49 +00:00

86 lines
1.8 KiB
Go

package log
import (
"context"
"log/slog"
"sync"
)
// loggerFactory is a function that creates a Logger given a name.
// It can be set by calling SetLoggerFactory to use a custom logger implementation.
var loggerFactory func(name string) Logger
// SetLoggerFactory sets the factory function used to create loggers.
// This should be called during initialization to register a custom logger implementation.
// If not set, a default slog-based logger will be used.
func SetLoggerFactory(factory func(name string) Logger) {
loggerFactory = factory
}
var slogLogManager = &slogLoggerManager{
cache: sync.Map{},
}
func New(name string) Logger {
if loggerFactory != nil {
return loggerFactory(name)
}
// add a caching layer since slog doesn't perform any caching itself
return slogLogManager.getOrCreate(name)
}
type slogLoggerManager struct {
cache sync.Map
}
func (m *slogLoggerManager) getOrCreate(name string) Logger {
if cached, ok := m.cache.Load(name); ok {
return cached.(*slogLogger)
}
logger := &slogLogger{
logger: slog.Default().With("logger", name),
name: name,
}
actual, _ := m.cache.LoadOrStore(name, logger)
return actual.(*slogLogger)
}
type slogLogger struct {
logger *slog.Logger
name string
}
func (l *slogLogger) New(ctx ...any) Logger {
if len(ctx) == 0 {
return &slogLogger{
logger: l.logger,
name: l.name,
}
}
return &slogLogger{
logger: l.logger.With(ctx...),
name: l.name,
}
}
func (l *slogLogger) Debug(msg string, ctx ...any) {
l.logger.Debug(msg, ctx...)
}
func (l *slogLogger) Info(msg string, ctx ...any) {
l.logger.Info(msg, ctx...)
}
func (l *slogLogger) Warn(msg string, ctx ...any) {
l.logger.Warn(msg, ctx...)
}
func (l *slogLogger) Error(msg string, ctx ...any) {
l.logger.Error(msg, ctx...)
}
func (l *slogLogger) FromContext(_ context.Context) Logger {
return l
}