1
0
mirror of https://github.com/open-telemetry/opentelemetry-go.git synced 2025-01-05 22:54:18 +02:00
opentelemetry-go/log/internal/global/log.go
Tyler Yahn 335f4de960
Add global log package (#5085)
* Add the log/global package

* Implement the stubbed features

* Add ConcurrentSafe tests

* Restructure with internal implementation

* Add internal global state

* Use internal state in log/global

* Add TestDelegation

* Fix lint

* Clean log_test.go

* Clean up

* Add changelog entry

* Simplify TestMultipleGlobalLoggerProvider

* Shorten log.go

* Fix comment text wrapping

* Shorten state_test.go

* Don't pollute output in TestSetLoggerProvider
2024-03-19 11:28:11 -07:00

97 lines
2.1 KiB
Go

// Copyright The OpenTelemetry Authors
// SPDX-License-Identifier: Apache-2.0
package global // import "go.opentelemetry.io/otel/log/internal/global"
import (
"context"
"sync"
"sync/atomic"
"go.opentelemetry.io/otel/log"
"go.opentelemetry.io/otel/log/embedded"
)
// instLib defines the instrumentation library a logger is created for.
//
// Do not use sdk/instrumentation (API cannot depend on the SDK).
type instLib struct{ name, version string }
type loggerProvider struct {
embedded.LoggerProvider
mu sync.Mutex
loggers map[instLib]*logger
delegate log.LoggerProvider
}
// Compile-time guarantee loggerProvider implements LoggerProvider.
var _ log.LoggerProvider = (*loggerProvider)(nil)
func (p *loggerProvider) Logger(name string, options ...log.LoggerOption) log.Logger {
p.mu.Lock()
defer p.mu.Unlock()
if p.delegate != nil {
return p.delegate.Logger(name, options...)
}
cfg := log.NewLoggerConfig(options...)
key := instLib{name, cfg.InstrumentationVersion()}
if p.loggers == nil {
l := &logger{name: name, options: options}
p.loggers = map[instLib]*logger{key: l}
return l
}
if l, ok := p.loggers[key]; ok {
return l
}
l := &logger{name: name, options: options}
p.loggers[key] = l
return l
}
func (p *loggerProvider) setDelegate(provider log.LoggerProvider) {
p.mu.Lock()
defer p.mu.Unlock()
p.delegate = provider
for _, l := range p.loggers {
l.setDelegate(provider)
}
p.loggers = nil // Only set logger delegates once.
}
type logger struct {
embedded.Logger
name string
options []log.LoggerOption
delegate atomic.Value // log.Logger
}
// Compile-time guarantee logger implements Logger.
var _ log.Logger = (*logger)(nil)
func (l *logger) Emit(ctx context.Context, r log.Record) {
if del, ok := l.delegate.Load().(log.Logger); ok {
del.Emit(ctx, r)
}
}
func (l *logger) Enabled(ctx context.Context, r log.Record) bool {
var enabled bool
if del, ok := l.delegate.Load().(log.Logger); ok {
enabled = del.Enabled(ctx, r)
}
return enabled
}
func (l *logger) setDelegate(provider log.LoggerProvider) {
l.delegate.Store(provider.Logger(l.name, l.options...))
}