You've already forked opentelemetry-go
mirror of
https://github.com/open-telemetry/opentelemetry-go.git
synced 2026-06-03 18:35:08 +02:00
Implement the providerConfig (#5074)
* Implement the providerConfig * Add test for NewLoggerProvider configuration * Add TestLimitValueFailsOpen * Fix merge
This commit is contained in:
+97
-9
@@ -5,22 +5,105 @@ package log // import "go.opentelemetry.io/otel/sdk/log"
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
"fmt"
|
||||||
|
"os"
|
||||||
|
"strconv"
|
||||||
|
|
||||||
|
"go.opentelemetry.io/otel"
|
||||||
"go.opentelemetry.io/otel/log"
|
"go.opentelemetry.io/otel/log"
|
||||||
"go.opentelemetry.io/otel/log/embedded"
|
"go.opentelemetry.io/otel/log/embedded"
|
||||||
"go.opentelemetry.io/otel/sdk/resource"
|
"go.opentelemetry.io/otel/sdk/resource"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Compile-time check LoggerProvider implements log.LoggerProvider.
|
const (
|
||||||
var _ log.LoggerProvider = (*LoggerProvider)(nil)
|
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
|
||||||
|
attrCntLim limit
|
||||||
|
attrValLenLim limit
|
||||||
|
}
|
||||||
|
|
||||||
|
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(
|
||||||
|
envarAttrCntLim,
|
||||||
|
defaultAttrCntLim,
|
||||||
|
)
|
||||||
|
|
||||||
|
c.attrValLenLim = c.attrValLenLim.Resolve(
|
||||||
|
envarAttrValLenLim,
|
||||||
|
defaultAttrValLenLim,
|
||||||
|
)
|
||||||
|
|
||||||
|
return c
|
||||||
|
}
|
||||||
|
|
||||||
|
type limit struct {
|
||||||
|
value int
|
||||||
|
set bool
|
||||||
|
}
|
||||||
|
|
||||||
|
func newLimit(value int) limit {
|
||||||
|
return limit{value: value, set: true}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Resolve returns the resolved form of the limit l. If l's value is set, it
|
||||||
|
// will return l. If the l's value is not set, a new limit based on the
|
||||||
|
// environment variable envar will be returned if that environment variable is
|
||||||
|
// set. Otherwise, fallback is used to construct a new limit that is returned.
|
||||||
|
func (l limit) Resolve(envar string, fallback int) limit {
|
||||||
|
if l.set {
|
||||||
|
return l
|
||||||
|
}
|
||||||
|
|
||||||
|
if v := os.Getenv(envar); v != "" {
|
||||||
|
n, err := strconv.Atoi(v)
|
||||||
|
if err == nil {
|
||||||
|
return newLimit(n)
|
||||||
|
}
|
||||||
|
otel.Handle(fmt.Errorf("invalid %s value %s: %w", envar, v, err))
|
||||||
|
}
|
||||||
|
|
||||||
|
return newLimit(fallback)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Value returns the limit value if set. Otherwise, it returns -1.
|
||||||
|
func (l limit) Value() int {
|
||||||
|
if l.set {
|
||||||
|
return l.value
|
||||||
|
}
|
||||||
|
// Fail open, not closed (-1 == unlimited).
|
||||||
|
return -1
|
||||||
|
}
|
||||||
|
|
||||||
// LoggerProvider handles the creation and coordination of Loggers. All Loggers
|
// LoggerProvider handles the creation and coordination of Loggers. All Loggers
|
||||||
// created by a LoggerProvider will be associated with the same Resource.
|
// created by a LoggerProvider will be associated with the same Resource.
|
||||||
type LoggerProvider struct {
|
type LoggerProvider struct {
|
||||||
embedded.LoggerProvider
|
embedded.LoggerProvider
|
||||||
|
|
||||||
|
resource *resource.Resource
|
||||||
|
processors []Processor
|
||||||
|
attributeCountLimit int
|
||||||
|
attributeValueLengthLimit int
|
||||||
}
|
}
|
||||||
|
|
||||||
type providerConfig struct{}
|
// Compile-time check LoggerProvider implements log.LoggerProvider.
|
||||||
|
var _ log.LoggerProvider = (*LoggerProvider)(nil)
|
||||||
|
|
||||||
// NewLoggerProvider returns a new and configured LoggerProvider.
|
// NewLoggerProvider returns a new and configured LoggerProvider.
|
||||||
//
|
//
|
||||||
@@ -29,8 +112,13 @@ type providerConfig struct{}
|
|||||||
// created. This means the returned LoggerProvider, one created with no
|
// created. This means the returned LoggerProvider, one created with no
|
||||||
// Processors, will perform no operations.
|
// Processors, will perform no operations.
|
||||||
func NewLoggerProvider(opts ...LoggerProviderOption) *LoggerProvider {
|
func NewLoggerProvider(opts ...LoggerProviderOption) *LoggerProvider {
|
||||||
// TODO (#5060): Implement.
|
cfg := newProviderConfig(opts)
|
||||||
return nil
|
return &LoggerProvider{
|
||||||
|
resource: cfg.resource,
|
||||||
|
processors: cfg.processors,
|
||||||
|
attributeCountLimit: cfg.attrCntLim.Value(),
|
||||||
|
attributeValueLengthLimit: cfg.attrValLenLim.Value(),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Logger returns a new [log.Logger] with the provided name and configuration.
|
// Logger returns a new [log.Logger] with the provided name and configuration.
|
||||||
@@ -76,7 +164,7 @@ func (fn loggerProviderOptionFunc) apply(c providerConfig) providerConfig {
|
|||||||
// go.opentelemetry.io/otel/sdk/resource package will be used.
|
// go.opentelemetry.io/otel/sdk/resource package will be used.
|
||||||
func WithResource(res *resource.Resource) LoggerProviderOption {
|
func WithResource(res *resource.Resource) LoggerProviderOption {
|
||||||
return loggerProviderOptionFunc(func(cfg providerConfig) providerConfig {
|
return loggerProviderOptionFunc(func(cfg providerConfig) providerConfig {
|
||||||
// TODO (#5060): Implement.
|
cfg.resource = res
|
||||||
return cfg
|
return cfg
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@@ -93,7 +181,7 @@ func WithResource(res *resource.Resource) LoggerProviderOption {
|
|||||||
// For testing and debugging, use [NewSimpleProcessor] to synchronously export log records.
|
// For testing and debugging, use [NewSimpleProcessor] to synchronously export log records.
|
||||||
func WithProcessor(processor Processor) LoggerProviderOption {
|
func WithProcessor(processor Processor) LoggerProviderOption {
|
||||||
return loggerProviderOptionFunc(func(cfg providerConfig) providerConfig {
|
return loggerProviderOptionFunc(func(cfg providerConfig) providerConfig {
|
||||||
// TODO (#5060): Implement.
|
cfg.processors = append(cfg.processors, processor)
|
||||||
return cfg
|
return cfg
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@@ -112,7 +200,7 @@ func WithProcessor(processor Processor) LoggerProviderOption {
|
|||||||
// passed, 128 will be used.
|
// passed, 128 will be used.
|
||||||
func WithAttributeCountLimit(limit int) LoggerProviderOption {
|
func WithAttributeCountLimit(limit int) LoggerProviderOption {
|
||||||
return loggerProviderOptionFunc(func(cfg providerConfig) providerConfig {
|
return loggerProviderOptionFunc(func(cfg providerConfig) providerConfig {
|
||||||
// TODO (#5060): Implement.
|
cfg.attrCntLim = newLimit(limit)
|
||||||
return cfg
|
return cfg
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@@ -131,7 +219,7 @@ func WithAttributeCountLimit(limit int) LoggerProviderOption {
|
|||||||
// passed, no limit (-1) will be used.
|
// passed, no limit (-1) will be used.
|
||||||
func WithAttributeValueLengthLimit(limit int) LoggerProviderOption {
|
func WithAttributeValueLengthLimit(limit int) LoggerProviderOption {
|
||||||
return loggerProviderOptionFunc(func(cfg providerConfig) providerConfig {
|
return loggerProviderOptionFunc(func(cfg providerConfig) providerConfig {
|
||||||
// TODO (#5060): Implement.
|
cfg.attrValLenLim = newLimit(limit)
|
||||||
return cfg
|
return cfg
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,126 @@
|
|||||||
|
// Copyright The OpenTelemetry Authors
|
||||||
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
|
package log // import "go.opentelemetry.io/otel/sdk/log"
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"strconv"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
|
|
||||||
|
"go.opentelemetry.io/otel"
|
||||||
|
"go.opentelemetry.io/otel/attribute"
|
||||||
|
"go.opentelemetry.io/otel/sdk/resource"
|
||||||
|
)
|
||||||
|
|
||||||
|
type processor struct {
|
||||||
|
name string
|
||||||
|
}
|
||||||
|
|
||||||
|
func (processor) OnEmit(context.Context, Record) error { return nil }
|
||||||
|
func (processor) Enabled(context.Context, Record) bool { return true }
|
||||||
|
func (processor) Shutdown(context.Context) error { return nil }
|
||||||
|
func (processor) ForceFlush(context.Context) error { return nil }
|
||||||
|
|
||||||
|
func TestNewLoggerProviderConfiguration(t *testing.T) {
|
||||||
|
t.Cleanup(func(orig otel.ErrorHandler) func() {
|
||||||
|
otel.SetErrorHandler(otel.ErrorHandlerFunc(func(err error) {
|
||||||
|
t.Log(err)
|
||||||
|
}))
|
||||||
|
return func() { otel.SetErrorHandler(orig) }
|
||||||
|
}(otel.GetErrorHandler()))
|
||||||
|
|
||||||
|
res := resource.NewSchemaless(attribute.String("key", "value"))
|
||||||
|
p0, p1 := processor{name: "0"}, processor{name: "1"}
|
||||||
|
attrCntLim := 12
|
||||||
|
attrValLenLim := 21
|
||||||
|
|
||||||
|
testcases := []struct {
|
||||||
|
name string
|
||||||
|
envars map[string]string
|
||||||
|
options []LoggerProviderOption
|
||||||
|
want *LoggerProvider
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
name: "Defaults",
|
||||||
|
want: &LoggerProvider{
|
||||||
|
resource: resource.Default(),
|
||||||
|
attributeCountLimit: defaultAttrCntLim,
|
||||||
|
attributeValueLengthLimit: defaultAttrValLenLim,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Options",
|
||||||
|
options: []LoggerProviderOption{
|
||||||
|
WithResource(res),
|
||||||
|
WithProcessor(p0),
|
||||||
|
WithProcessor(p1),
|
||||||
|
WithAttributeCountLimit(attrCntLim),
|
||||||
|
WithAttributeValueLengthLimit(attrValLenLim),
|
||||||
|
},
|
||||||
|
want: &LoggerProvider{
|
||||||
|
resource: res,
|
||||||
|
processors: []Processor{p0, p1},
|
||||||
|
attributeCountLimit: attrCntLim,
|
||||||
|
attributeValueLengthLimit: attrValLenLim,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Environment",
|
||||||
|
envars: map[string]string{
|
||||||
|
envarAttrCntLim: strconv.Itoa(attrCntLim),
|
||||||
|
envarAttrValLenLim: strconv.Itoa(attrValLenLim),
|
||||||
|
},
|
||||||
|
want: &LoggerProvider{
|
||||||
|
resource: resource.Default(),
|
||||||
|
attributeCountLimit: attrCntLim,
|
||||||
|
attributeValueLengthLimit: attrValLenLim,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "InvalidEnvironment",
|
||||||
|
envars: map[string]string{
|
||||||
|
envarAttrCntLim: "invalid attributeCountLimit",
|
||||||
|
envarAttrValLenLim: "invalid attributeValueLengthLimit",
|
||||||
|
},
|
||||||
|
want: &LoggerProvider{
|
||||||
|
resource: resource.Default(),
|
||||||
|
attributeCountLimit: defaultAttrCntLim,
|
||||||
|
attributeValueLengthLimit: defaultAttrValLenLim,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Precedence",
|
||||||
|
envars: map[string]string{
|
||||||
|
envarAttrCntLim: strconv.Itoa(100),
|
||||||
|
envarAttrValLenLim: strconv.Itoa(101),
|
||||||
|
},
|
||||||
|
options: []LoggerProviderOption{
|
||||||
|
// These override the environment variables.
|
||||||
|
WithAttributeCountLimit(attrCntLim),
|
||||||
|
WithAttributeValueLengthLimit(attrValLenLim),
|
||||||
|
},
|
||||||
|
want: &LoggerProvider{
|
||||||
|
resource: resource.Default(),
|
||||||
|
attributeCountLimit: attrCntLim,
|
||||||
|
attributeValueLengthLimit: attrValLenLim,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, tc := range testcases {
|
||||||
|
t.Run(tc.name, func(t *testing.T) {
|
||||||
|
for key, value := range tc.envars {
|
||||||
|
t.Setenv(key, value)
|
||||||
|
}
|
||||||
|
assert.Equal(t, tc.want, NewLoggerProvider(tc.options...))
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestLimitValueFailsOpen(t *testing.T) {
|
||||||
|
var l limit
|
||||||
|
assert.Equal(t, -1, l.Value(), "limit value should default to unlimited")
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user