package log
import (
"context"
"errors"
"sync"
"sync/atomic"
"go.opentelemetry.io/otel"
"go.opentelemetry.io/otel/internal/global"
"go.opentelemetry.io/otel/log"
"go.opentelemetry.io/otel/log/embedded"
"go.opentelemetry.io/otel/log/noop"
"go.opentelemetry.io/otel/sdk/instrumentation"
"go.opentelemetry.io/otel/sdk/resource"
)
const (
defaultAttrCntLim = 128
defaultAttrValLenLim = -1
envarAttrCntLim = "OTEL_LOGRECORD_ATTRIBUTE_COUNT_LIMIT"
envarAttrValLenLim = "OTEL_LOGRECORD_ATTRIBUTE_VALUE_LENGTH_LIMIT"
)
type providerConfig struct {
resource *resource .Resource
processors []Processor
fltrProcessors []FilterProcessor
attrCntLim setting [int ]
attrValLenLim setting [int ]
allowDupKeys setting [bool ]
}
func newProviderConfig(opts []LoggerProviderOption ) providerConfig {
var c providerConfig
for _ , opt := range opts {
c = opt .apply (c )
}
if c .resource == nil {
c .resource = resource .Default ()
}
c .attrCntLim = c .attrCntLim .Resolve (
getenv [int ](envarAttrCntLim ),
fallback [int ](defaultAttrCntLim ),
)
c .attrValLenLim = c .attrValLenLim .Resolve (
getenv [int ](envarAttrValLenLim ),
fallback [int ](defaultAttrValLenLim ),
)
return c
}
type LoggerProvider struct {
embedded .LoggerProvider
resource *resource .Resource
processors []Processor
fltrProcessors []FilterProcessor
attributeCountLimit int
attributeValueLengthLimit int
allowDupKeys bool
loggersMu sync .Mutex
loggers map [instrumentation .Scope ]*logger
stopped atomic .Bool
noCmp [0 ]func ()
}
var _ log .LoggerProvider = (*LoggerProvider )(nil )
func NewLoggerProvider (opts ...LoggerProviderOption ) *LoggerProvider {
cfg := newProviderConfig (opts )
return &LoggerProvider {
resource : cfg .resource ,
processors : cfg .processors ,
fltrProcessors : cfg .fltrProcessors ,
attributeCountLimit : cfg .attrCntLim .Value ,
attributeValueLengthLimit : cfg .attrValLenLim .Value ,
allowDupKeys : cfg .allowDupKeys .Value ,
}
}
func (p *LoggerProvider ) Logger (name string , opts ...log .LoggerOption ) log .Logger {
if name == "" {
global .Warn ("Invalid Logger name." , "name" , name )
}
if p .stopped .Load () {
return noop .NewLoggerProvider ().Logger (name , opts ...)
}
cfg := log .NewLoggerConfig (opts ...)
scope := instrumentation .Scope {
Name : name ,
Version : cfg .InstrumentationVersion (),
SchemaURL : cfg .SchemaURL (),
Attributes : cfg .InstrumentationAttributes (),
}
p .loggersMu .Lock ()
defer p .loggersMu .Unlock ()
if p .loggers == nil {
l := newLogger (p , scope )
p .loggers = map [instrumentation .Scope ]*logger {scope : l }
return l
}
l , ok := p .loggers [scope ]
if !ok {
l = newLogger (p , scope )
p .loggers [scope ] = l
}
return l
}
func (p *LoggerProvider ) Shutdown (ctx context .Context ) error {
stopped := p .stopped .Swap (true )
if stopped {
return nil
}
var err error
for _ , p := range p .processors {
err = errors .Join (err , p .Shutdown (ctx ))
}
return err
}
func (p *LoggerProvider ) ForceFlush (ctx context .Context ) error {
if p .stopped .Load () {
return nil
}
var err error
for _ , p := range p .processors {
err = errors .Join (err , p .ForceFlush (ctx ))
}
return err
}
type LoggerProviderOption interface {
apply(providerConfig ) providerConfig
}
type loggerProviderOptionFunc func (providerConfig ) providerConfig
func (fn loggerProviderOptionFunc ) apply (c providerConfig ) providerConfig {
return fn (c )
}
func WithResource (res *resource .Resource ) LoggerProviderOption {
return loggerProviderOptionFunc (func (cfg providerConfig ) providerConfig {
var err error
cfg .resource , err = resource .Merge (resource .Environment (), res )
if err != nil {
otel .Handle (err )
}
return cfg
})
}
func WithProcessor (processor Processor ) LoggerProviderOption {
return loggerProviderOptionFunc (func (cfg providerConfig ) providerConfig {
cfg .processors = append (cfg .processors , processor )
if f , ok := processor .(FilterProcessor ); ok {
cfg .fltrProcessors = append (cfg .fltrProcessors , f )
}
return cfg
})
}
func WithAttributeCountLimit (limit int ) LoggerProviderOption {
return loggerProviderOptionFunc (func (cfg providerConfig ) providerConfig {
cfg .attrCntLim = newSetting (limit )
return cfg
})
}
func WithAttributeValueLengthLimit (limit int ) LoggerProviderOption {
return loggerProviderOptionFunc (func (cfg providerConfig ) providerConfig {
cfg .attrValLenLim = newSetting (limit )
return cfg
})
}
func WithAllowKeyDuplication () LoggerProviderOption {
return loggerProviderOptionFunc (func (cfg providerConfig ) providerConfig {
cfg .allowDupKeys = newSetting (true )
return cfg
})
}
The pages are generated with Golds v0.8.2 . (GOOS=linux GOARCH=amd64)
Golds is a Go 101 project developed by Tapir Liu .
PR and bug reports are welcome and can be submitted to the issue list .
Please follow @zigo_101 (reachable from the left QR code) to get the latest news of Golds .