You've already forked opentelemetry-go
mirror of
https://github.com/open-telemetry/opentelemetry-go.git
synced 2025-11-25 22:41:46 +02:00
log: Introduce EnabledParameters (#5791)
Fixes https://github.com/open-telemetry/opentelemetry-go/issues/5769 Related spec PR: https://github.com/open-telemetry/opentelemetry-specification/pull/4203 Remark: A follow-up in contrib is required and afterwards here to fix the `example/dice`. Benchstat results for `sdk/log` (`log` has no benchmarks related to Enabled): ``` goos: linux goarch: amd64 pkg: go.opentelemetry.io/otel/sdk/log cpu: Intel(R) Core(TM) i9-10885H CPU @ 2.40GHz │ old.txt │ new.txt │ │ sec/op │ sec/op vs base │ BatchProcessorOnEmit-16 398.8n ± 10% 395.6n ± 12% ~ (p=0.971 n=10) Processor/Simple-16 882.2n ± 8% 869.8n ± 9% ~ (p=0.811 n=10) Processor/Batch-16 1.478µ ± 3% 1.485µ ± 5% ~ (p=0.646 n=10) Processor/SetTimestampSimple-16 847.8n ± 1% 844.6n ± 3% ~ (p=0.247 n=10) Processor/SetTimestampBatch-16 1.480µ ± 3% 1.473µ ± 4% ~ (p=0.700 n=10) Processor/AddAttributesSimple-16 930.0n ± 1% 933.8n ± 1% ~ (p=0.172 n=10) Processor/AddAttributesBatch-16 1.624µ ± 2% 1.639µ ± 2% ~ (p=0.839 n=10) Processor/SetAttributesSimple-16 903.4n ± 1% 895.1n ± 1% ~ (p=0.190 n=10) Processor/SetAttributesBatch-16 1.554µ ± 4% 1.529µ ± 3% ~ (p=0.159 n=10) LoggerNewRecord/5_attributes-16 346.0n ± 2% 343.3n ± 2% ~ (p=0.448 n=10) LoggerNewRecord/10_attributes-16 1.608µ ± 6% 1.503µ ± 2% -6.53% (p=0.007 n=10) LoggerEnabled-16 34.305n ± 8% 6.706n ± 1% -80.45% (p=0.000 n=10) LoggerProviderLogger-16 636.9n ± 10% 605.8n ± 3% ~ (p=0.105 n=10) WalkAttributes/1_attributes-16 5.363n ± 3% 4.540n ± 14% -15.34% (p=0.002 n=10) WalkAttributes/10_attributes-16 5.436n ± 7% 4.461n ± 2% -17.95% (p=0.000 n=10) WalkAttributes/100_attributes-16 5.126n ± 9% 4.465n ± 1% -12.90% (p=0.000 n=10) WalkAttributes/1000_attributes-16 5.316n ± 9% 4.502n ± 5% -15.32% (p=0.002 n=10) SetAddAttributes/SetAttributes-16 220.5n ± 18% 192.6n ± 11% -12.67% (p=0.007 n=10) SetAddAttributes/AddAttributes-16 165.3n ± 21% 127.3n ± 22% -22.96% (p=0.011 n=10) SimpleProcessorOnEmit-16 2.159n ± 9% 2.167n ± 9% ~ (p=0.739 n=10) geomean 178.3n 154.5n -13.31% │ old.txt │ new.txt │ │ B/s │ B/s vs base │ BatchProcessorOnEmit-16 76.52Mi ± 11% 77.14Mi ± 14% ~ (p=0.971 n=10) │ old.txt │ new.txt │ │ B/op │ B/op vs base │ BatchProcessorOnEmit-16 0.000 ± 0% 0.000 ± 0% ~ (p=1.000 n=10) ¹ Processor/Simple-16 417.0 ± 0% 417.0 ± 0% ~ (p=1.000 n=10) ¹ Processor/Batch-16 1.093Ki ± 1% 1.088Ki ± 1% ~ (p=0.254 n=10) Processor/SetTimestampSimple-16 417.0 ± 0% 417.0 ± 0% ~ (p=1.000 n=10) ¹ Processor/SetTimestampBatch-16 1.095Ki ± 1% 1.084Ki ± 2% ~ (p=0.361 n=10) Processor/AddAttributesSimple-16 417.0 ± 0% 417.0 ± 0% ~ (p=1.000 n=10) ¹ Processor/AddAttributesBatch-16 1.085Ki ± 1% 1.086Ki ± 1% ~ (p=1.000 n=10) Processor/SetAttributesSimple-16 465.0 ± 0% 465.0 ± 0% ~ (p=1.000 n=10) ¹ Processor/SetAttributesBatch-16 1.129Ki ± 1% 1.125Ki ± 1% ~ (p=0.084 n=10) LoggerNewRecord/5_attributes-16 0.000 ± 0% 0.000 ± 0% ~ (p=1.000 n=10) ¹ LoggerNewRecord/10_attributes-16 610.0 ± 0% 610.0 ± 0% ~ (p=1.000 n=10) ¹ LoggerEnabled-16 0.000 ± 0% 0.000 ± 0% ~ (p=1.000 n=10) ¹ LoggerProviderLogger-16 359.0 ± 6% 346.0 ± 3% ~ (p=0.117 n=10) WalkAttributes/1_attributes-16 0.000 ± 0% 0.000 ± 0% ~ (p=1.000 n=10) ¹ WalkAttributes/10_attributes-16 0.000 ± 0% 0.000 ± 0% ~ (p=1.000 n=10) ¹ WalkAttributes/100_attributes-16 0.000 ± 0% 0.000 ± 0% ~ (p=1.000 n=10) ¹ WalkAttributes/1000_attributes-16 0.000 ± 0% 0.000 ± 0% ~ (p=1.000 n=10) ¹ SetAddAttributes/SetAttributes-16 48.00 ± 0% 48.00 ± 0% ~ (p=1.000 n=10) ¹ SetAddAttributes/AddAttributes-16 0.000 ± 0% 0.000 ± 0% ~ (p=1.000 n=10) ¹ SimpleProcessorOnEmit-16 0.000 ± 0% 0.000 ± 0% ~ (p=1.000 n=10) ¹ geomean ² -0.27% ² ¹ all samples are equal ² summaries must be >0 to compute geomean │ old.txt │ new.txt │ │ allocs/op │ allocs/op vs base │ BatchProcessorOnEmit-16 0.000 ± 0% 0.000 ± 0% ~ (p=1.000 n=10) ¹ Processor/Simple-16 1.000 ± 0% 1.000 ± 0% ~ (p=1.000 n=10) ¹ Processor/Batch-16 1.000 ± 0% 1.000 ± 0% ~ (p=1.000 n=10) ¹ Processor/SetTimestampSimple-16 1.000 ± 0% 1.000 ± 0% ~ (p=1.000 n=10) ¹ Processor/SetTimestampBatch-16 1.000 ± 0% 1.000 ± 0% ~ (p=1.000 n=10) ¹ Processor/AddAttributesSimple-16 1.000 ± 0% 1.000 ± 0% ~ (p=1.000 n=10) ¹ Processor/AddAttributesBatch-16 1.000 ± 0% 1.000 ± 0% ~ (p=1.000 n=10) ¹ Processor/SetAttributesSimple-16 2.000 ± 0% 2.000 ± 0% ~ (p=1.000 n=10) ¹ Processor/SetAttributesBatch-16 2.000 ± 0% 2.000 ± 0% ~ (p=1.000 n=10) ¹ LoggerNewRecord/5_attributes-16 0.000 ± 0% 0.000 ± 0% ~ (p=1.000 n=10) ¹ LoggerNewRecord/10_attributes-16 4.000 ± 0% 4.000 ± 0% ~ (p=1.000 n=10) ¹ LoggerEnabled-16 0.000 ± 0% 0.000 ± 0% ~ (p=1.000 n=10) ¹ LoggerProviderLogger-16 1.000 ± 0% 1.000 ± 0% ~ (p=1.000 n=10) ¹ WalkAttributes/1_attributes-16 0.000 ± 0% 0.000 ± 0% ~ (p=1.000 n=10) ¹ WalkAttributes/10_attributes-16 0.000 ± 0% 0.000 ± 0% ~ (p=1.000 n=10) ¹ WalkAttributes/100_attributes-16 0.000 ± 0% 0.000 ± 0% ~ (p=1.000 n=10) ¹ WalkAttributes/1000_attributes-16 0.000 ± 0% 0.000 ± 0% ~ (p=1.000 n=10) ¹ SetAddAttributes/SetAttributes-16 1.000 ± 0% 1.000 ± 0% ~ (p=1.000 n=10) ¹ SetAddAttributes/AddAttributes-16 0.000 ± 0% 0.000 ± 0% ~ (p=1.000 n=10) ¹ SimpleProcessorOnEmit-16 0.000 ± 0% 0.000 ± 0% ~ (p=1.000 n=10) ¹ geomean ² +0.00% ² ¹ all samples are equal ² summaries must be >0 to compute geomean ```
This commit is contained in:
@@ -11,6 +11,8 @@ This project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.htm
|
|||||||
### Changed
|
### Changed
|
||||||
|
|
||||||
- Enable exemplars by default in `go.opentelemetry.io/otel/sdk/metric`. Exemplars can be disabled by setting `OTEL_METRICS_EXEMPLAR_FILTER=always_off` (#5778)
|
- Enable exemplars by default in `go.opentelemetry.io/otel/sdk/metric`. Exemplars can be disabled by setting `OTEL_METRICS_EXEMPLAR_FILTER=always_off` (#5778)
|
||||||
|
- `Logger.Enabled` in `go.opentelemetry.io/otel/log` now accepts a newly introduced `EnabledParameters` type instead of `Record`. (#5791)
|
||||||
|
- `FilterProcessor.Enabled` in `go.opentelemetry.io/otel/sdk/log/internal/x` now accepts `EnabledParameters` instead of `Record`. (#5791)
|
||||||
|
|
||||||
<!-- Released section -->
|
<!-- Released section -->
|
||||||
<!-- Don't change this section unless doing release -->
|
<!-- Don't change this section unless doing release -->
|
||||||
|
|||||||
@@ -3,7 +3,6 @@ module go.opentelemetry.io/otel/example/dice
|
|||||||
go 1.22
|
go 1.22
|
||||||
|
|
||||||
require (
|
require (
|
||||||
go.opentelemetry.io/contrib/bridges/otelslog v0.5.0
|
|
||||||
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.55.0
|
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.55.0
|
||||||
go.opentelemetry.io/otel v1.30.0
|
go.opentelemetry.io/otel v1.30.0
|
||||||
go.opentelemetry.io/otel/exporters/stdout/stdoutlog v0.6.0
|
go.opentelemetry.io/otel/exporters/stdout/stdoutlog v0.6.0
|
||||||
|
|||||||
@@ -15,8 +15,6 @@ github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZb
|
|||||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||||
github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg=
|
github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg=
|
||||||
github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
|
github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
|
||||||
go.opentelemetry.io/contrib/bridges/otelslog v0.5.0 h1:lU3F57OSLK5mQ1PDBVAfDDaKCPv37MrEbCfTzsF4bz0=
|
|
||||||
go.opentelemetry.io/contrib/bridges/otelslog v0.5.0/go.mod h1:I84u06zJFr8T5D73fslEUbnRBimVVSBhuVw8L8I92AU=
|
|
||||||
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.55.0 h1:ZIg3ZT/aQ7AfKqdwp7ECpOK6vHqquXXuyTjIO8ZdmPs=
|
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.55.0 h1:ZIg3ZT/aQ7AfKqdwp7ECpOK6vHqquXXuyTjIO8ZdmPs=
|
||||||
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.55.0/go.mod h1:DQAwmETtZV00skUwgD6+0U89g80NKsJE3DCKeLLPQMI=
|
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.55.0/go.mod h1:DQAwmETtZV00skUwgD6+0U89g80NKsJE3DCKeLLPQMI=
|
||||||
golang.org/x/sys v0.25.0 h1:r+8e+loiHxRqhXVl6ML1nO3l1+oFoWbnlu2Ehimmi34=
|
golang.org/x/sys v0.25.0 h1:r+8e+loiHxRqhXVl6ML1nO3l1+oFoWbnlu2Ehimmi34=
|
||||||
|
|||||||
@@ -6,11 +6,14 @@ package main
|
|||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
|
"log/slog"
|
||||||
"math/rand"
|
"math/rand"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
"os"
|
||||||
"strconv"
|
"strconv"
|
||||||
|
|
||||||
"go.opentelemetry.io/contrib/bridges/otelslog"
|
// TODO: https://github.com/open-telemetry/opentelemetry-go/issues/5801
|
||||||
|
// "go.opentelemetry.io/contrib/bridges/otelslog".
|
||||||
"go.opentelemetry.io/otel"
|
"go.opentelemetry.io/otel"
|
||||||
"go.opentelemetry.io/otel/attribute"
|
"go.opentelemetry.io/otel/attribute"
|
||||||
"go.opentelemetry.io/otel/metric"
|
"go.opentelemetry.io/otel/metric"
|
||||||
@@ -21,7 +24,7 @@ const name = "go.opentelemetry.io/otel/example/dice"
|
|||||||
var (
|
var (
|
||||||
tracer = otel.Tracer(name)
|
tracer = otel.Tracer(name)
|
||||||
meter = otel.Meter(name)
|
meter = otel.Meter(name)
|
||||||
logger = otelslog.NewLogger(name)
|
logger = slog.New(slog.NewJSONHandler(os.Stdout, nil)) // TODO: logger = otelslog.NewLogger(name).
|
||||||
rollCnt metric.Int64Counter
|
rollCnt metric.Int64Counter
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
@@ -253,6 +253,23 @@ Rejected alternatives:
|
|||||||
- [Add XYZ method to Logger](#add-xyz-method-to-logger)
|
- [Add XYZ method to Logger](#add-xyz-method-to-logger)
|
||||||
- [Rename KeyValue to Attr](#rename-keyvalue-to-attr)
|
- [Rename KeyValue to Attr](#rename-keyvalue-to-attr)
|
||||||
|
|
||||||
|
### Logger.Enabled
|
||||||
|
|
||||||
|
The `Enabled` method implements the [`Enabled` operation](https://opentelemetry.io/docs/specs/otel/logs/bridge-api/#enabled).
|
||||||
|
|
||||||
|
[`Context` associated with the `LogRecord`](https://opentelemetry.io/docs/specs/otel/context/)
|
||||||
|
is accepted as a `context.Context` method argument.
|
||||||
|
|
||||||
|
Calls to `Enabled` are supposed to be on the hot path and the list of arguments
|
||||||
|
can be extendend in future. Therefore, in order to reduce the number of heap
|
||||||
|
allocations and make it possible to handle new arguments, `Enabled` accepts
|
||||||
|
a `EnabledParameters` struct, defined in [logger.go](logger.go), as the second
|
||||||
|
method argument.
|
||||||
|
|
||||||
|
The `EnabledParameters` getters are returning values using the `(value, ok)`
|
||||||
|
idiom in order to indicate if the values were actually set by the caller or if
|
||||||
|
there are unspecified.
|
||||||
|
|
||||||
### noop package
|
### noop package
|
||||||
|
|
||||||
The `go.opentelemetry.io/otel/log/noop` package provides
|
The `go.opentelemetry.io/otel/log/noop` package provides
|
||||||
|
|||||||
@@ -87,10 +87,10 @@ func (l *logger) Emit(ctx context.Context, r log.Record) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (l *logger) Enabled(ctx context.Context, r log.Record) bool {
|
func (l *logger) Enabled(ctx context.Context, param log.EnabledParameters) bool {
|
||||||
var enabled bool
|
var enabled bool
|
||||||
if del, ok := l.delegate.Load().(log.Logger); ok {
|
if del, ok := l.delegate.Load().(log.Logger); ok {
|
||||||
enabled = del.Enabled(ctx, r)
|
enabled = del.Enabled(ctx, param)
|
||||||
}
|
}
|
||||||
return enabled
|
return enabled
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -51,11 +51,12 @@ func TestLoggerConcurrentSafe(t *testing.T) {
|
|||||||
|
|
||||||
ctx := context.Background()
|
ctx := context.Background()
|
||||||
var r log.Record
|
var r log.Record
|
||||||
|
var param log.EnabledParameters
|
||||||
|
|
||||||
var enabled bool
|
var enabled bool
|
||||||
for {
|
for {
|
||||||
l.Emit(ctx, r)
|
l.Emit(ctx, r)
|
||||||
enabled = l.Enabled(ctx, r)
|
enabled = l.Enabled(ctx, param)
|
||||||
|
|
||||||
select {
|
select {
|
||||||
case <-stop:
|
case <-stop:
|
||||||
@@ -103,16 +104,17 @@ type testLogger struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (l *testLogger) Emit(context.Context, log.Record) { l.emitN++ }
|
func (l *testLogger) Emit(context.Context, log.Record) { l.emitN++ }
|
||||||
func (l *testLogger) Enabled(context.Context, log.Record) bool {
|
func (l *testLogger) Enabled(context.Context, log.EnabledParameters) bool {
|
||||||
l.enabledN++
|
l.enabledN++
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
func emitRecord(l log.Logger) {
|
func emitRecord(l log.Logger) {
|
||||||
ctx := context.Background()
|
ctx := context.Background()
|
||||||
|
var param log.EnabledParameters
|
||||||
var r log.Record
|
var r log.Record
|
||||||
|
|
||||||
_ = l.Enabled(ctx, r)
|
_ = l.Enabled(ctx, param)
|
||||||
l.Emit(ctx, r)
|
l.Emit(ctx, r)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -31,26 +31,26 @@ type Logger interface {
|
|||||||
Emit(ctx context.Context, record Record)
|
Emit(ctx context.Context, record Record)
|
||||||
|
|
||||||
// Enabled returns whether the Logger emits for the given context and
|
// Enabled returns whether the Logger emits for the given context and
|
||||||
// record.
|
// param.
|
||||||
//
|
//
|
||||||
// The passed record is likely to be a partial record with only the
|
// The passed param is likely to be a partial record with only the
|
||||||
// bridge-relevant information being provided (e.g a record with only the
|
// bridge-relevant information being provided (e.g a param with only the
|
||||||
// Severity set). If a Logger needs more information than is provided, it
|
// Severity set). If a Logger needs more information than is provided, it
|
||||||
// is said to be in an indeterminate state (see below).
|
// is said to be in an indeterminate state (see below).
|
||||||
//
|
//
|
||||||
// The returned value will be true when the Logger will emit for the
|
// The returned value will be true when the Logger will emit for the
|
||||||
// provided context and record, and will be false if the Logger will not
|
// provided context and param, and will be false if the Logger will not
|
||||||
// emit. The returned value may be true or false in an indeterminate state.
|
// emit. The returned value may be true or false in an indeterminate state.
|
||||||
// An implementation should default to returning true for an indeterminate
|
// An implementation should default to returning true for an indeterminate
|
||||||
// state, but may return false if valid reasons in particular circumstances
|
// state, but may return false if valid reasons in particular circumstances
|
||||||
// exist (e.g. performance, correctness).
|
// exist (e.g. performance, correctness).
|
||||||
//
|
//
|
||||||
// The record should not be held by the implementation. A copy should be
|
// The param should not be held by the implementation. A copy should be
|
||||||
// made if the record needs to be held after the call returns.
|
// made if the record needs to be held after the call returns.
|
||||||
//
|
//
|
||||||
// Implementations of this method need to be safe for a user to call
|
// Implementations of this method need to be safe for a user to call
|
||||||
// concurrently.
|
// concurrently.
|
||||||
Enabled(ctx context.Context, record Record) bool
|
Enabled(ctx context.Context, param EnabledParameters) bool
|
||||||
}
|
}
|
||||||
|
|
||||||
// LoggerOption applies configuration options to a [Logger].
|
// LoggerOption applies configuration options to a [Logger].
|
||||||
@@ -129,3 +129,21 @@ func WithSchemaURL(schemaURL string) LoggerOption {
|
|||||||
return config
|
return config
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// EnabledParameters represents payload for [Logger]'s Enabled method.
|
||||||
|
type EnabledParameters struct {
|
||||||
|
severity Severity
|
||||||
|
severitySet bool
|
||||||
|
}
|
||||||
|
|
||||||
|
// Severity returns the [Severity] level value, or [SeverityUndefined] if no value was set.
|
||||||
|
// The ok result indicates whether the value was set.
|
||||||
|
func (r *EnabledParameters) Severity() (value Severity, ok bool) {
|
||||||
|
return r.severity, r.severitySet
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetSeverity sets the [Severity] level.
|
||||||
|
func (r *EnabledParameters) SetSeverity(level Severity) {
|
||||||
|
r.severity = level
|
||||||
|
r.severitySet = true
|
||||||
|
}
|
||||||
|
|||||||
@@ -11,9 +11,9 @@ import (
|
|||||||
"go.opentelemetry.io/otel/log/embedded"
|
"go.opentelemetry.io/otel/log/embedded"
|
||||||
)
|
)
|
||||||
|
|
||||||
type enabledFn func(context.Context, log.Record) bool
|
type enabledFn func(context.Context, log.EnabledParameters) bool
|
||||||
|
|
||||||
var defaultEnabledFunc = func(context.Context, log.Record) bool {
|
var defaultEnabledFunc = func(context.Context, log.EnabledParameters) bool {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -42,7 +42,7 @@ func (f optFunc) apply(c config) config { return f(c) }
|
|||||||
// WithEnabledFunc allows configuring whether the [Recorder] is enabled for specific log entries or not.
|
// WithEnabledFunc allows configuring whether the [Recorder] is enabled for specific log entries or not.
|
||||||
//
|
//
|
||||||
// By default, the Recorder is enabled for every log entry.
|
// By default, the Recorder is enabled for every log entry.
|
||||||
func WithEnabledFunc(fn func(context.Context, log.Record) bool) Option {
|
func WithEnabledFunc(fn func(context.Context, log.EnabledParameters) bool) Option {
|
||||||
return optFunc(func(c config) config {
|
return optFunc(func(c config) config {
|
||||||
c.enabledFn = fn
|
c.enabledFn = fn
|
||||||
return c
|
return c
|
||||||
@@ -155,12 +155,12 @@ type logger struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Enabled indicates whether a specific record should be stored.
|
// Enabled indicates whether a specific record should be stored.
|
||||||
func (l *logger) Enabled(ctx context.Context, record log.Record) bool {
|
func (l *logger) Enabled(ctx context.Context, opts log.EnabledParameters) bool {
|
||||||
if l.enabledFn == nil {
|
if l.enabledFn == nil {
|
||||||
return defaultEnabledFunc(ctx, record)
|
return defaultEnabledFunc(ctx, opts)
|
||||||
}
|
}
|
||||||
|
|
||||||
return l.enabledFn(ctx, record)
|
return l.enabledFn(ctx, opts)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Emit stores the log record.
|
// Emit stores the log record.
|
||||||
|
|||||||
@@ -68,15 +68,15 @@ func TestLoggerEnabled(t *testing.T) {
|
|||||||
name string
|
name string
|
||||||
options []Option
|
options []Option
|
||||||
ctx context.Context
|
ctx context.Context
|
||||||
buildRecord func() log.Record
|
buildEnabledParameters func() log.EnabledParameters
|
||||||
|
|
||||||
isEnabled bool
|
isEnabled bool
|
||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
name: "the default option enables every log entry",
|
name: "the default option enables every log entry",
|
||||||
ctx: context.Background(),
|
ctx: context.Background(),
|
||||||
buildRecord: func() log.Record {
|
buildEnabledParameters: func() log.EnabledParameters {
|
||||||
return log.Record{}
|
return log.EnabledParameters{}
|
||||||
},
|
},
|
||||||
|
|
||||||
isEnabled: true,
|
isEnabled: true,
|
||||||
@@ -84,20 +84,20 @@ func TestLoggerEnabled(t *testing.T) {
|
|||||||
{
|
{
|
||||||
name: "with everything disabled",
|
name: "with everything disabled",
|
||||||
options: []Option{
|
options: []Option{
|
||||||
WithEnabledFunc(func(context.Context, log.Record) bool {
|
WithEnabledFunc(func(context.Context, log.EnabledParameters) bool {
|
||||||
return false
|
return false
|
||||||
}),
|
}),
|
||||||
},
|
},
|
||||||
ctx: context.Background(),
|
ctx: context.Background(),
|
||||||
buildRecord: func() log.Record {
|
buildEnabledParameters: func() log.EnabledParameters {
|
||||||
return log.Record{}
|
return log.EnabledParameters{}
|
||||||
},
|
},
|
||||||
|
|
||||||
isEnabled: false,
|
isEnabled: false,
|
||||||
},
|
},
|
||||||
} {
|
} {
|
||||||
t.Run(tt.name, func(t *testing.T) {
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
e := NewRecorder(tt.options...).Logger("test").Enabled(tt.ctx, tt.buildRecord())
|
e := NewRecorder(tt.options...).Logger("test").Enabled(tt.ctx, tt.buildEnabledParameters())
|
||||||
assert.Equal(t, tt.isEnabled, e)
|
assert.Equal(t, tt.isEnabled, e)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@@ -105,7 +105,7 @@ func TestLoggerEnabled(t *testing.T) {
|
|||||||
|
|
||||||
func TestLoggerEnabledFnUnset(t *testing.T) {
|
func TestLoggerEnabledFnUnset(t *testing.T) {
|
||||||
r := &logger{}
|
r := &logger{}
|
||||||
assert.True(t, r.Enabled(context.Background(), log.Record{}))
|
assert.True(t, r.Enabled(context.Background(), log.EnabledParameters{}))
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestRecorderEmitAndReset(t *testing.T) {
|
func TestRecorderEmitAndReset(t *testing.T) {
|
||||||
@@ -158,7 +158,7 @@ func TestRecorderConcurrentSafe(t *testing.T) {
|
|||||||
defer wg.Done()
|
defer wg.Done()
|
||||||
|
|
||||||
nr := r.Logger("test")
|
nr := r.Logger("test")
|
||||||
nr.Enabled(context.Background(), log.Record{})
|
nr.Enabled(context.Background(), log.EnabledParameters{})
|
||||||
nr.Emit(context.Background(), log.Record{})
|
nr.Emit(context.Background(), log.Record{})
|
||||||
|
|
||||||
r.Result()
|
r.Result()
|
||||||
|
|||||||
@@ -47,4 +47,4 @@ type Logger struct{ embedded.Logger }
|
|||||||
func (Logger) Emit(context.Context, log.Record) {}
|
func (Logger) Emit(context.Context, log.Record) {}
|
||||||
|
|
||||||
// Enabled returns false. No log records are ever emitted.
|
// Enabled returns false. No log records are ever emitted.
|
||||||
func (Logger) Enabled(context.Context, log.Record) bool { return false }
|
func (Logger) Enabled(context.Context, log.EnabledParameters) bool { return false }
|
||||||
|
|||||||
@@ -90,7 +90,7 @@ type ContextFilterProcessor struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type filter interface {
|
type filter interface {
|
||||||
Enabled(ctx context.Context, record log.Record) bool
|
Enabled(ctx context.Context, param logapi.EnabledParameters) bool
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *ContextFilterProcessor) OnEmit(ctx context.Context, record *log.Record) error {
|
func (p *ContextFilterProcessor) OnEmit(ctx context.Context, record *log.Record) error {
|
||||||
@@ -100,13 +100,13 @@ func (p *ContextFilterProcessor) OnEmit(ctx context.Context, record *log.Record)
|
|||||||
return p.Processor.OnEmit(ctx, record)
|
return p.Processor.OnEmit(ctx, record)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *ContextFilterProcessor) Enabled(ctx context.Context, record log.Record) bool {
|
func (p *ContextFilterProcessor) Enabled(ctx context.Context, param logapi.EnabledParameters) bool {
|
||||||
p.lazyFilter.Do(func() {
|
p.lazyFilter.Do(func() {
|
||||||
if f, ok := p.Processor.(filter); ok {
|
if f, ok := p.Processor.(filter); ok {
|
||||||
p.filter = f
|
p.filter = f
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
return !ignoreLogs(ctx) && (p.filter == nil || p.filter.Enabled(ctx, record))
|
return !ignoreLogs(ctx) && (p.filter == nil || p.filter.Enabled(ctx, param))
|
||||||
}
|
}
|
||||||
|
|
||||||
func ignoreLogs(ctx context.Context) bool {
|
func ignoreLogs(ctx context.Context) bool {
|
||||||
@@ -147,11 +147,6 @@ func (p *RedactTokensProcessor) OnEmit(ctx context.Context, record *log.Record)
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Enabled returns true.
|
|
||||||
func (p *RedactTokensProcessor) Enabled(context.Context, log.Record) bool {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
// Shutdown returns nil.
|
// Shutdown returns nil.
|
||||||
func (p *RedactTokensProcessor) Shutdown(ctx context.Context) error {
|
func (p *RedactTokensProcessor) Shutdown(ctx context.Context) error {
|
||||||
return nil
|
return nil
|
||||||
|
|||||||
@@ -10,37 +10,38 @@ import (
|
|||||||
"go.opentelemetry.io/otel/log"
|
"go.opentelemetry.io/otel/log"
|
||||||
)
|
)
|
||||||
|
|
||||||
// FilterProcessor is a [Processor] that knows, and can identify, what
|
// FilterProcessor is a [go.opentelemetry.io/otel/sdk/log.Processor] that knows,
|
||||||
// [log.Record] it will process or drop when it is passed to OnEmit.
|
// and can identify, what [log.Record] it will process or drop when it is
|
||||||
|
// passed to OnEmit.
|
||||||
//
|
//
|
||||||
// This is useful for users of logging libraries that want to know if a [log.Record]
|
// This is useful for users of logging libraries that want to know if a [log.Record]
|
||||||
// will be processed or dropped before they perform complex operations to
|
// will be processed or dropped before they perform complex operations to
|
||||||
// construct the [log.Record].
|
// construct the [log.Record].
|
||||||
//
|
//
|
||||||
// [Processor] implementations that choose to support this by satisfying this
|
// Processor implementations that choose to support this by satisfying this
|
||||||
// interface are expected to re-evaluate the [log.Record]s passed to OnEmit, it is
|
// interface are expected to re-evaluate the [log.Record]s passed to OnEmit, it is
|
||||||
// not expected that the caller to OnEmit will use the functionality from this
|
// not expected that the caller to OnEmit will use the functionality from this
|
||||||
// interface prior to calling OnEmit.
|
// interface prior to calling OnEmit.
|
||||||
//
|
//
|
||||||
// This should only be implemented for [Processor]s that can make reliable
|
// This should only be implemented for Processors that can make reliable
|
||||||
// enough determination of this prior to processing a [log.Record] and where
|
// enough determination of this prior to processing a [log.Record] and where
|
||||||
// the result is dynamic.
|
// the result is dynamic.
|
||||||
//
|
//
|
||||||
// [Processor]: https://pkg.go.dev/go.opentelemetry.io/otel/sdk/log#Processor
|
// [Processor]: https://pkg.go.dev/go.opentelemetry.io/otel/sdk/log#Processor
|
||||||
type FilterProcessor interface {
|
type FilterProcessor interface {
|
||||||
// Enabled returns whether the Processor will process for the given context
|
// Enabled returns whether the Processor will process for the given context
|
||||||
// and record.
|
// and param.
|
||||||
//
|
//
|
||||||
// The passed record is likely to be a partial record with only the
|
// The passed param is likely to be a partial record with only the
|
||||||
// bridge-relevant information being provided (e.g a record with only the
|
// bridge-relevant information being provided (e.g a record with only the
|
||||||
// Severity set). If a Logger needs more information than is provided, it
|
// Severity set). If a Logger needs more information than is provided, it
|
||||||
// is said to be in an indeterminate state (see below).
|
// is said to be in an indeterminate state (see below).
|
||||||
//
|
//
|
||||||
// The returned value will be true when the Processor will process for the
|
// The returned value will be true when the Processor will process for the
|
||||||
// provided context and record, and will be false if the Processor will not
|
// provided context and param, and will be false if the Processor will not
|
||||||
// process. An implementation should default to returning true for an
|
// process. An implementation should default to returning true for an
|
||||||
// indeterminate state.
|
// indeterminate state.
|
||||||
//
|
//
|
||||||
// Implementations should not modify the record.
|
// Implementations should not modify the param.
|
||||||
Enabled(ctx context.Context, record log.Record) bool
|
Enabled(ctx context.Context, param log.EnabledParameters) bool
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -44,24 +44,23 @@ func (l *logger) Emit(ctx context.Context, r log.Record) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Enabled returns true if at least one Processor held by the LoggerProvider
|
// Enabled returns true if at least one Processor held by the LoggerProvider
|
||||||
// that created the logger will process the record for the provided context.
|
// that created the logger will process param for the provided context and param.
|
||||||
//
|
//
|
||||||
// If it is not possible to definitively determine the record will be
|
// If it is not possible to definitively determine the param will be
|
||||||
// processed, true will be returned by default. A value of false will only be
|
// processed, true will be returned by default. A value of false will only be
|
||||||
// returned if it can be positively verified that no Processor will process the
|
// returned if it can be positively verified that no Processor will process.
|
||||||
// record.
|
func (l *logger) Enabled(ctx context.Context, param log.EnabledParameters) bool {
|
||||||
func (l *logger) Enabled(ctx context.Context, record log.Record) bool {
|
|
||||||
fltrs := l.provider.filterProcessors()
|
fltrs := l.provider.filterProcessors()
|
||||||
// If there are more Processors than FilterProcessors we cannot be sure
|
// If there are more Processors than FilterProcessors we cannot be sure
|
||||||
// that all Processors will drop the record. Therefore, return true.
|
// that all Processors will drop the record. Therefore, return true.
|
||||||
//
|
//
|
||||||
// If all Processors are FilterProcessors, check if any is enabled.
|
// If all Processors are FilterProcessors, check if any is enabled.
|
||||||
return len(l.provider.processors) > len(fltrs) || anyEnabled(ctx, record, fltrs)
|
return len(l.provider.processors) > len(fltrs) || anyEnabled(ctx, param, fltrs)
|
||||||
}
|
}
|
||||||
|
|
||||||
func anyEnabled(ctx context.Context, r log.Record, fltrs []x.FilterProcessor) bool {
|
func anyEnabled(ctx context.Context, param log.EnabledParameters, fltrs []x.FilterProcessor) bool {
|
||||||
for _, f := range fltrs {
|
for _, f := range fltrs {
|
||||||
if f.Enabled(ctx, r) {
|
if f.Enabled(ctx, param) {
|
||||||
// At least one Processor will process the Record.
|
// At least one Processor will process the Record.
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -270,7 +270,7 @@ func TestLoggerEnabled(t *testing.T) {
|
|||||||
|
|
||||||
for _, tc := range testCases {
|
for _, tc := range testCases {
|
||||||
t.Run(tc.name, func(t *testing.T) {
|
t.Run(tc.name, func(t *testing.T) {
|
||||||
assert.Equal(t, tc.expected, tc.logger.Enabled(tc.ctx, log.Record{}))
|
assert.Equal(t, tc.expected, tc.logger.Enabled(tc.ctx, log.EnabledParameters{}))
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -281,8 +281,8 @@ func BenchmarkLoggerEnabled(b *testing.B) {
|
|||||||
WithProcessor(newFltrProcessor("1", true)),
|
WithProcessor(newFltrProcessor("1", true)),
|
||||||
)
|
)
|
||||||
logger := provider.Logger("BenchmarkLoggerEnabled")
|
logger := provider.Logger("BenchmarkLoggerEnabled")
|
||||||
ctx, r := context.Background(), log.Record{}
|
ctx, param := context.Background(), log.EnabledParameters{}
|
||||||
r.SetSeverityText("test")
|
param.SetSeverity(log.SeverityDebug)
|
||||||
|
|
||||||
var enabled bool
|
var enabled bool
|
||||||
|
|
||||||
@@ -290,7 +290,7 @@ func BenchmarkLoggerEnabled(b *testing.B) {
|
|||||||
b.ResetTimer()
|
b.ResetTimer()
|
||||||
|
|
||||||
for n := 0; n < b.N; n++ {
|
for n := 0; n < b.N; n++ {
|
||||||
enabled = logger.Enabled(ctx, r)
|
enabled = logger.Enabled(ctx, param)
|
||||||
}
|
}
|
||||||
|
|
||||||
_ = enabled
|
_ = enabled
|
||||||
|
|||||||
@@ -76,7 +76,7 @@ func newFltrProcessor(name string, enabled bool) *fltrProcessor {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *fltrProcessor) Enabled(context.Context, log.Record) bool {
|
func (p *fltrProcessor) Enabled(context.Context, log.EnabledParameters) bool {
|
||||||
return p.enabled
|
return p.enabled
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -384,5 +384,5 @@ func BenchmarkLoggerProviderLogger(b *testing.B) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
b.StopTimer()
|
b.StopTimer()
|
||||||
loggers[0].Enabled(context.Background(), log.Record{})
|
loggers[0].Enabled(context.Background(), log.EnabledParameters{})
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user