You've already forked opentelemetry-go
mirror of
https://github.com/open-telemetry/opentelemetry-go.git
synced 2025-08-10 22:31:50 +02:00
sdk/log: Add FilterProcessor and EnabledParameters (#6317)
Per https://github.com/open-telemetry/opentelemetry-go/pull/6271#issuecomment-2657554647 > We agreed that we can move `FilterProcessor` directly to `sdk/log` as Logs SDK does not look to be stabilized soon. - Add the possibility to filter based on the resource and scope which is available for the SDK. The scope information is the most important as it gives the possibility to e.g. filter out logs emitted for a given logger. Thus e.g. https://github.com/open-telemetry/opentelemetry-specification/issues/4364 is not necessary. See https://github.com/open-telemetry/opentelemetry-specification/pull/4290#discussion_r1927546170 for more context. - It is going be an example for https://github.com/open-telemetry/opentelemetry-specification/issues/4363 There is a little overhead (IMO totally acceptable) because of data transformation. Most importantly, there is no new heap allocation. ``` goos: linux goarch: amd64 pkg: go.opentelemetry.io/otel/sdk/log cpu: 13th Gen Intel(R) Core(TM) i7-13800H │ old.txt │ new.txt │ │ sec/op │ sec/op vs base │ LoggerEnabled-20 4.589n ± 1% 319.750n ± 16% +6867.75% (p=0.000 n=10) │ old.txt │ new.txt │ │ B/op │ B/op vs base │ LoggerEnabled-20 0.000Ki ± 0% 1.093Ki ± 13% ? (p=0.000 n=10) │ old.txt │ new.txt │ │ allocs/op │ allocs/op vs base │ LoggerEnabled-20 0.000 ± 0% 0.000 ± 0% ~ (p=1.000 n=10) ¹ ¹ all samples are equal ``` `Logger.Enabled` is still more efficient than `Logger.Emit` (benchmarks from https://github.com/open-telemetry/opentelemetry-go/pull/6315). ``` goos: linux goarch: amd64 pkg: go.opentelemetry.io/otel/sdk/log cpu: 13th Gen Intel(R) Core(TM) i7-13800H BenchmarkLoggerEmit/5_attributes-20 559934 2391 ns/op 39088 B/op 1 allocs/op BenchmarkLoggerEmit/10_attributes-20 1000000 5910 ns/op 49483 B/op 5 allocs/op BenchmarkLoggerEnabled-20 1605697 968.7 ns/op 1272 B/op 0 allocs/op PASS ok go.opentelemetry.io/otel/sdk/log 10.789s ``` Prior art: - https://github.com/open-telemetry/opentelemetry-go/pull/6271 - https://github.com/open-telemetry/opentelemetry-go/pull/6286 I also created for tracking purposes: - https://github.com/open-telemetry/opentelemetry-go/issues/6328
This commit is contained in:
@@ -31,6 +31,9 @@ The next release will require at least [Go 1.23].
|
|||||||
- Document the pitfalls of using `Resource` as a comparable type.
|
- Document the pitfalls of using `Resource` as a comparable type.
|
||||||
`Resource.Equal` and `Resource.Equivalent` should be used instead. (#6272)
|
`Resource.Equal` and `Resource.Equivalent` should be used instead. (#6272)
|
||||||
- Support [Go 1.24]. (#6304)
|
- Support [Go 1.24]. (#6304)
|
||||||
|
- Add `FilterProcessor` and `EnabledParameters` in `go.opentelemetry.io/otel/sdk/log`.
|
||||||
|
It replaces `go.opentelemetry.io/otel/sdk/log/internal/x.FilterProcessor`.
|
||||||
|
Compared to previous version it additionally gives the possibility to filter by resource and instrumentation scope. (#6317)
|
||||||
|
|
||||||
### Changed
|
### Changed
|
||||||
|
|
||||||
|
@@ -33,9 +33,13 @@ type Logger interface {
|
|||||||
// Enabled returns whether the Logger emits for the given context and
|
// Enabled returns whether the Logger emits for the given context and
|
||||||
// param.
|
// param.
|
||||||
//
|
//
|
||||||
// The passed param is likely to be a partial record with only the
|
// This is useful for users that want to know if a [Record]
|
||||||
// bridge-relevant information being provided (e.g a param with only the
|
// will be processed or dropped before they perform complex operations to
|
||||||
// Severity set). If a Logger needs more information than is provided, it
|
// construct the [Record].
|
||||||
|
//
|
||||||
|
// The passed param is likely to be a partial record information being
|
||||||
|
// provided (e.g a param with only the 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
|
||||||
@@ -46,7 +50,7 @@ type Logger interface {
|
|||||||
// exist (e.g. performance, correctness).
|
// exist (e.g. performance, correctness).
|
||||||
//
|
//
|
||||||
// The param 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 param 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.
|
||||||
|
@@ -32,8 +32,5 @@ at a single endpoint their origin is decipherable.
|
|||||||
|
|
||||||
See [go.opentelemetry.io/otel/log] for more information about
|
See [go.opentelemetry.io/otel/log] for more information about
|
||||||
the OpenTelemetry Logs Bridge API.
|
the OpenTelemetry Logs Bridge API.
|
||||||
|
|
||||||
See [go.opentelemetry.io/otel/sdk/log/internal/x] for information about the
|
|
||||||
experimental features.
|
|
||||||
*/
|
*/
|
||||||
package log // import "go.opentelemetry.io/otel/sdk/log"
|
package log // import "go.opentelemetry.io/otel/sdk/log"
|
||||||
|
@@ -52,7 +52,7 @@ func Example() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Use a processor that filters out records based on the provided context.
|
// Use a processor that filters out records based on the provided context.
|
||||||
func ExampleProcessor_filtering() {
|
func ExampleFilterProcessor() {
|
||||||
// Existing processor that emits telemetry.
|
// Existing processor that emits telemetry.
|
||||||
var processor log.Processor = log.NewBatchProcessor(nil)
|
var processor log.Processor = log.NewBatchProcessor(nil)
|
||||||
|
|
||||||
@@ -84,14 +84,12 @@ type ContextFilterProcessor struct {
|
|||||||
log.Processor
|
log.Processor
|
||||||
|
|
||||||
lazyFilter sync.Once
|
lazyFilter sync.Once
|
||||||
// Use the experimental FilterProcessor interface
|
// Support the FilterProcessor interface for the embedded processor.
|
||||||
// (go.opentelemetry.io/otel/sdk/log/internal/x).
|
filter log.FilterProcessor
|
||||||
filter filter
|
|
||||||
}
|
}
|
||||||
|
|
||||||
type filter interface {
|
// Compile time check.
|
||||||
Enabled(ctx context.Context, param logapi.EnabledParameters) bool
|
var _ log.FilterProcessor = (*ContextFilterProcessor)(nil)
|
||||||
}
|
|
||||||
|
|
||||||
func (p *ContextFilterProcessor) OnEmit(ctx context.Context, record *log.Record) error {
|
func (p *ContextFilterProcessor) OnEmit(ctx context.Context, record *log.Record) error {
|
||||||
if ignoreLogs(ctx) {
|
if ignoreLogs(ctx) {
|
||||||
@@ -100,9 +98,9 @@ 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, param logapi.EnabledParameters) bool {
|
func (p *ContextFilterProcessor) Enabled(ctx context.Context, param log.EnabledParameters) bool {
|
||||||
p.lazyFilter.Do(func() {
|
p.lazyFilter.Do(func() {
|
||||||
if f, ok := p.Processor.(filter); ok {
|
if f, ok := p.Processor.(log.FilterProcessor); ok {
|
||||||
p.filter = f
|
p.filter = f
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
@@ -115,7 +113,7 @@ func ignoreLogs(ctx context.Context) bool {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Use a processor which redacts sensitive data from some attributes.
|
// Use a processor which redacts sensitive data from some attributes.
|
||||||
func ExampleProcessor_redact() {
|
func ExampleProcessor() {
|
||||||
// Existing processor that emits telemetry.
|
// Existing processor that emits telemetry.
|
||||||
var processor log.Processor = log.NewBatchProcessor(nil)
|
var processor log.Processor = log.NewBatchProcessor(nil)
|
||||||
|
|
||||||
|
62
sdk/log/filter_processor.go
Normal file
62
sdk/log/filter_processor.go
Normal file
@@ -0,0 +1,62 @@
|
|||||||
|
// Copyright The OpenTelemetry Authors
|
||||||
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
|
package log // import "go.opentelemetry.io/otel/sdk/log"
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
|
||||||
|
"go.opentelemetry.io/otel/log"
|
||||||
|
"go.opentelemetry.io/otel/sdk/instrumentation"
|
||||||
|
"go.opentelemetry.io/otel/sdk/resource"
|
||||||
|
)
|
||||||
|
|
||||||
|
// FilterProcessor is a [Processor] that knows, and can identify, what [Record]
|
||||||
|
// it will process or drop when it is passed to [Processor.OnEmit].
|
||||||
|
//
|
||||||
|
// This is useful for users that want to know if a [log.Record]
|
||||||
|
// will be processed or dropped before they perform complex operations to
|
||||||
|
// construct the [log.Record].
|
||||||
|
//
|
||||||
|
// The SDK's Logger.Enabled returns false
|
||||||
|
// if all the registered Processors implement FilterProcessor
|
||||||
|
// and they all return false.
|
||||||
|
//
|
||||||
|
// Processor implementations that choose to support this by satisfying this
|
||||||
|
// interface are expected to re-evaluate the [Record] passed to [Processor.OnEmit],
|
||||||
|
// it is not expected that the caller to OnEmit will use the functionality
|
||||||
|
// from this interface prior to calling OnEmit.
|
||||||
|
//
|
||||||
|
// See the [go.opentelemetry.io/contrib/processors/minsev] for an example use-case.
|
||||||
|
// It provides a Processor used to filter out [Record]
|
||||||
|
// that has a [log.Severity] below a threshold.
|
||||||
|
type FilterProcessor interface {
|
||||||
|
// Enabled returns whether the Processor will process for the given context
|
||||||
|
// and param.
|
||||||
|
//
|
||||||
|
// The passed param is likely to be a partial record information being
|
||||||
|
// provided (e.g a param with only the Severity set).
|
||||||
|
// If a Processor needs more information than is provided, it
|
||||||
|
// is said to be in an indeterminate state (see below).
|
||||||
|
//
|
||||||
|
// The returned value will be true when the Processor will process for the
|
||||||
|
// 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.
|
||||||
|
// An implementation should default to returning true for an indeterminate
|
||||||
|
// state, but may return false if valid reasons in particular circumstances
|
||||||
|
// exist (e.g. performance, correctness).
|
||||||
|
//
|
||||||
|
// The param should not be held by the implementation. A copy should be
|
||||||
|
// made if the param needs to be held after the call returns.
|
||||||
|
//
|
||||||
|
// Implementations of this method need to be safe for a user to call
|
||||||
|
// concurrently.
|
||||||
|
Enabled(ctx context.Context, param EnabledParameters) bool
|
||||||
|
}
|
||||||
|
|
||||||
|
// EnabledParameters represents payload for [FilterProcessor]'s Enabled method.
|
||||||
|
type EnabledParameters struct {
|
||||||
|
Resource resource.Resource
|
||||||
|
InstrumentationScope instrumentation.Scope
|
||||||
|
Severity log.Severity
|
||||||
|
}
|
@@ -1,35 +0,0 @@
|
|||||||
# Experimental Features
|
|
||||||
|
|
||||||
The Logs SDK contains features that have not yet stabilized.
|
|
||||||
These features are added to the OpenTelemetry Go Logs SDK prior to stabilization so that users can start experimenting with them and provide feedback.
|
|
||||||
|
|
||||||
These feature may change in backwards incompatible ways as feedback is applied.
|
|
||||||
See the [Compatibility and Stability](#compatibility-and-stability) section for more information.
|
|
||||||
|
|
||||||
## Features
|
|
||||||
|
|
||||||
- [Filter Processors](#filter-processor)
|
|
||||||
|
|
||||||
### Filter Processor
|
|
||||||
|
|
||||||
Users of logging libraries often want to know if a log `Record` will be processed or dropped before they perform complex operations to construct the `Record`.
|
|
||||||
The [`Logger`] in the Logs Bridge API provides the `Enabled` method for just this use-case.
|
|
||||||
In order for the Logs Bridge SDK to effectively implement this API, it needs to be known if the registered [`Processor`]s are enabled for the `Record` within a context.
|
|
||||||
A [`Processor`] that knows, and can identify, what `Record` it will process or drop when it is passed to `OnEmit` can communicate this to the SDK `Logger` by implementing the `FilterProcessor`.
|
|
||||||
|
|
||||||
By default, the SDK `Logger.Enabled` will return true when called.
|
|
||||||
Only if all the registered [`Processor`]s implement `FilterProcessor` and they all return `false` will `Logger.Enabled` return `false`.
|
|
||||||
|
|
||||||
See the [`minsev`] [`Processor`] for an example use-case.
|
|
||||||
It is used to filter `Record`s out that a have a `Severity` below a threshold.
|
|
||||||
|
|
||||||
[`Logger`]: https://pkg.go.dev/go.opentelemetry.io/otel/log#Logger
|
|
||||||
[`Processor`]: https://pkg.go.dev/go.opentelemetry.io/otel/sdk/log#Processor
|
|
||||||
[`minsev`]: https://pkg.go.dev/go.opentelemetry.io/contrib/processors/minsev
|
|
||||||
|
|
||||||
## Compatibility and Stability
|
|
||||||
|
|
||||||
Experimental features do not fall within the scope of the OpenTelemetry Go versioning and stability [policy](../../../../VERSIONING.md).
|
|
||||||
These features may be removed or modified in successive version releases, including patch versions.
|
|
||||||
|
|
||||||
When an experimental feature is promoted to a stable feature, a migration path will be included in the changelog entry of the release.
|
|
@@ -1,47 +0,0 @@
|
|||||||
// Copyright The OpenTelemetry Authors
|
|
||||||
// SPDX-License-Identifier: Apache-2.0
|
|
||||||
|
|
||||||
// Package x contains support for Logs SDK experimental features.
|
|
||||||
package x // import "go.opentelemetry.io/otel/sdk/log/internal/x"
|
|
||||||
|
|
||||||
import (
|
|
||||||
"context"
|
|
||||||
|
|
||||||
"go.opentelemetry.io/otel/log"
|
|
||||||
)
|
|
||||||
|
|
||||||
// FilterProcessor is a [go.opentelemetry.io/otel/sdk/log.Processor] that knows,
|
|
||||||
// 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]
|
|
||||||
// will be processed or dropped before they perform complex operations to
|
|
||||||
// construct the [log.Record].
|
|
||||||
//
|
|
||||||
// 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
|
|
||||||
// not expected that the caller to OnEmit will use the functionality from this
|
|
||||||
// interface prior to calling OnEmit.
|
|
||||||
//
|
|
||||||
// This should only be implemented for Processors that can make reliable
|
|
||||||
// enough determination of this prior to processing a [log.Record] and where
|
|
||||||
// the result is dynamic.
|
|
||||||
//
|
|
||||||
// [Processor]: https://pkg.go.dev/go.opentelemetry.io/otel/sdk/log#Processor
|
|
||||||
type FilterProcessor interface {
|
|
||||||
// Enabled returns whether the Processor will process for the given context
|
|
||||||
// and param.
|
|
||||||
//
|
|
||||||
// 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
|
|
||||||
// Severity set). If a Logger needs more information than is provided, it
|
|
||||||
// is said to be in an indeterminate state (see below).
|
|
||||||
//
|
|
||||||
// The returned value will be true when the Processor will process for the
|
|
||||||
// provided context and param, and will be false if the Processor will not
|
|
||||||
// process. An implementation should default to returning true for an
|
|
||||||
// indeterminate state.
|
|
||||||
//
|
|
||||||
// Implementations should not modify the param.
|
|
||||||
Enabled(ctx context.Context, param log.EnabledParameters) bool
|
|
||||||
}
|
|
@@ -11,7 +11,6 @@ import (
|
|||||||
"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/instrumentation"
|
"go.opentelemetry.io/otel/sdk/instrumentation"
|
||||||
"go.opentelemetry.io/otel/sdk/log/internal/x"
|
|
||||||
"go.opentelemetry.io/otel/trace"
|
"go.opentelemetry.io/otel/trace"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -50,14 +49,22 @@ func (l *logger) Emit(ctx context.Context, r log.Record) {
|
|||||||
// 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.
|
// returned if it can be positively verified that no Processor will process.
|
||||||
func (l *logger) Enabled(ctx context.Context, param log.EnabledParameters) bool {
|
func (l *logger) Enabled(ctx context.Context, param log.EnabledParameters) bool {
|
||||||
// If there are more Processors than FilterProcessors we cannot be sure
|
p := EnabledParameters{
|
||||||
// that all Processors will drop the record. Therefore, return true.
|
Resource: *l.provider.resource,
|
||||||
|
InstrumentationScope: l.instrumentationScope,
|
||||||
|
Severity: param.Severity,
|
||||||
|
}
|
||||||
|
|
||||||
|
// If there are more Processors than FilterProcessors,
|
||||||
|
// which means not all Processors are FilterProcessors,
|
||||||
|
// we cannot be sure 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(l.provider.fltrProcessors) || anyEnabled(ctx, param, l.provider.fltrProcessors)
|
return len(l.provider.processors) > len(l.provider.fltrProcessors) || anyEnabled(ctx, p, l.provider.fltrProcessors)
|
||||||
}
|
}
|
||||||
|
|
||||||
func anyEnabled(ctx context.Context, param log.EnabledParameters, fltrs []x.FilterProcessor) bool {
|
func anyEnabled(ctx context.Context, param EnabledParameters, fltrs []FilterProcessor) bool {
|
||||||
for _, f := range fltrs {
|
for _, f := range fltrs {
|
||||||
if f.Enabled(ctx, param) {
|
if f.Enabled(ctx, param) {
|
||||||
// At least one Processor will process the Record.
|
// At least one Processor will process the Record.
|
||||||
|
@@ -224,11 +224,17 @@ func TestLoggerEnabled(t *testing.T) {
|
|||||||
p1 := newFltrProcessor("1", true)
|
p1 := newFltrProcessor("1", true)
|
||||||
p2WithDisabled := newFltrProcessor("2", false)
|
p2WithDisabled := newFltrProcessor("2", false)
|
||||||
|
|
||||||
|
emptyResource := resource.Empty()
|
||||||
|
res := resource.NewSchemaless(attribute.String("key", "value"))
|
||||||
|
|
||||||
testCases := []struct {
|
testCases := []struct {
|
||||||
name string
|
name string
|
||||||
logger *logger
|
logger *logger
|
||||||
ctx context.Context
|
ctx context.Context
|
||||||
expected bool
|
expected bool
|
||||||
|
expectedP0Params []EnabledParameters
|
||||||
|
expectedP1Params []EnabledParameters
|
||||||
|
expectedP2Params []EnabledParameters
|
||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
name: "NoProcessors",
|
name: "NoProcessors",
|
||||||
@@ -241,41 +247,63 @@ func TestLoggerEnabled(t *testing.T) {
|
|||||||
logger: newLogger(NewLoggerProvider(
|
logger: newLogger(NewLoggerProvider(
|
||||||
WithProcessor(p0),
|
WithProcessor(p0),
|
||||||
WithProcessor(p1),
|
WithProcessor(p1),
|
||||||
), instrumentation.Scope{}),
|
WithResource(res),
|
||||||
|
), instrumentation.Scope{Name: "scope"}),
|
||||||
ctx: context.Background(),
|
ctx: context.Background(),
|
||||||
expected: true,
|
expected: true,
|
||||||
|
expectedP0Params: []EnabledParameters{{
|
||||||
|
Resource: *res,
|
||||||
|
InstrumentationScope: instrumentation.Scope{Name: "scope"},
|
||||||
|
}},
|
||||||
|
expectedP1Params: nil,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "WithDisabledProcessors",
|
name: "WithDisabledProcessors",
|
||||||
logger: newLogger(NewLoggerProvider(
|
logger: newLogger(NewLoggerProvider(
|
||||||
WithProcessor(p2WithDisabled),
|
WithProcessor(p2WithDisabled),
|
||||||
|
WithResource(emptyResource),
|
||||||
), instrumentation.Scope{}),
|
), instrumentation.Scope{}),
|
||||||
ctx: context.Background(),
|
ctx: context.Background(),
|
||||||
expected: false,
|
expected: false,
|
||||||
|
expectedP2Params: []EnabledParameters{{}},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "ContainsDisabledProcessor",
|
name: "ContainsDisabledProcessor",
|
||||||
logger: newLogger(NewLoggerProvider(
|
logger: newLogger(NewLoggerProvider(
|
||||||
WithProcessor(p2WithDisabled),
|
WithProcessor(p2WithDisabled),
|
||||||
WithProcessor(p0),
|
WithProcessor(p0),
|
||||||
|
WithResource(emptyResource),
|
||||||
), instrumentation.Scope{}),
|
), instrumentation.Scope{}),
|
||||||
ctx: context.Background(),
|
ctx: context.Background(),
|
||||||
expected: true,
|
expected: true,
|
||||||
|
expectedP2Params: []EnabledParameters{{}},
|
||||||
|
expectedP0Params: []EnabledParameters{{}},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "WithNilContext",
|
name: "WithNilContext",
|
||||||
logger: newLogger(NewLoggerProvider(
|
logger: newLogger(NewLoggerProvider(
|
||||||
WithProcessor(p0),
|
WithProcessor(p0),
|
||||||
WithProcessor(p1),
|
WithProcessor(p1),
|
||||||
|
WithResource(emptyResource),
|
||||||
), instrumentation.Scope{}),
|
), instrumentation.Scope{}),
|
||||||
ctx: nil,
|
ctx: nil,
|
||||||
expected: true,
|
expected: true,
|
||||||
|
expectedP0Params: []EnabledParameters{{}},
|
||||||
|
expectedP1Params: nil,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, tc := range testCases {
|
for _, tc := range testCases {
|
||||||
t.Run(tc.name, func(t *testing.T) {
|
t.Run(tc.name, func(t *testing.T) {
|
||||||
|
// Clean up the records before the test.
|
||||||
|
p0.params = nil
|
||||||
|
p1.params = nil
|
||||||
|
p2WithDisabled.params = nil
|
||||||
|
|
||||||
assert.Equal(t, tc.expected, tc.logger.Enabled(tc.ctx, log.EnabledParameters{}))
|
assert.Equal(t, tc.expected, tc.logger.Enabled(tc.ctx, log.EnabledParameters{}))
|
||||||
|
assert.Equal(t, tc.expectedP0Params, p0.params)
|
||||||
|
assert.Equal(t, tc.expectedP1Params, p1.params)
|
||||||
|
assert.Equal(t, tc.expectedP2Params, p2WithDisabled.params)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -13,8 +13,7 @@ import (
|
|||||||
// or with other methods. It is the responsibility of the Processor to manage
|
// or with other methods. It is the responsibility of the Processor to manage
|
||||||
// this concurrency.
|
// this concurrency.
|
||||||
//
|
//
|
||||||
// See [go.opentelemetry.io/otel/sdk/log/internal/x] for information about how
|
// See [FilterProcessor] for information about how a Processor can support filtering.
|
||||||
// a Processor can be extended to support experimental features.
|
|
||||||
type Processor interface {
|
type Processor interface {
|
||||||
// OnEmit is called when a Record is emitted.
|
// OnEmit is called when a Record is emitted.
|
||||||
//
|
//
|
||||||
@@ -30,11 +29,11 @@ type Processor interface {
|
|||||||
// Handler.
|
// Handler.
|
||||||
//
|
//
|
||||||
// The SDK invokes the processors sequentially in the same order as
|
// The SDK invokes the processors sequentially in the same order as
|
||||||
// they were registered using [WithProcessor].
|
// they were registered using WithProcessor.
|
||||||
// Implementations may synchronously modify the record so that the changes
|
// Implementations may synchronously modify the record so that the changes
|
||||||
// are visible in the next registered processor.
|
// are visible in the next registered processor.
|
||||||
// Notice that [Record] is not concurrent safe. Therefore, asynchronous
|
// Notice that Record is not concurrent safe. Therefore, asynchronous
|
||||||
// processing may cause race conditions. Use [Record.Clone]
|
// processing may cause race conditions. Use Record.Clone
|
||||||
// to create a copy that shares no state with the original.
|
// to create a copy that shares no state with the original.
|
||||||
OnEmit(ctx context.Context, record *Record) error
|
OnEmit(ctx context.Context, record *Record) error
|
||||||
|
|
||||||
|
@@ -15,7 +15,6 @@ import (
|
|||||||
"go.opentelemetry.io/otel/log/embedded"
|
"go.opentelemetry.io/otel/log/embedded"
|
||||||
"go.opentelemetry.io/otel/log/noop"
|
"go.opentelemetry.io/otel/log/noop"
|
||||||
"go.opentelemetry.io/otel/sdk/instrumentation"
|
"go.opentelemetry.io/otel/sdk/instrumentation"
|
||||||
"go.opentelemetry.io/otel/sdk/log/internal/x"
|
|
||||||
"go.opentelemetry.io/otel/sdk/resource"
|
"go.opentelemetry.io/otel/sdk/resource"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -30,7 +29,7 @@ const (
|
|||||||
type providerConfig struct {
|
type providerConfig struct {
|
||||||
resource *resource.Resource
|
resource *resource.Resource
|
||||||
processors []Processor
|
processors []Processor
|
||||||
fltrProcessors []x.FilterProcessor
|
fltrProcessors []FilterProcessor
|
||||||
attrCntLim setting[int]
|
attrCntLim setting[int]
|
||||||
attrValLenLim setting[int]
|
attrValLenLim setting[int]
|
||||||
}
|
}
|
||||||
@@ -65,7 +64,7 @@ type LoggerProvider struct {
|
|||||||
|
|
||||||
resource *resource.Resource
|
resource *resource.Resource
|
||||||
processors []Processor
|
processors []Processor
|
||||||
fltrProcessors []x.FilterProcessor
|
fltrProcessors []FilterProcessor
|
||||||
attributeCountLimit int
|
attributeCountLimit int
|
||||||
attributeValueLengthLimit int
|
attributeValueLengthLimit int
|
||||||
|
|
||||||
@@ -206,10 +205,12 @@ func WithResource(res *resource.Resource) LoggerProviderOption {
|
|||||||
//
|
//
|
||||||
// For production, use [NewBatchProcessor] to batch log records before they are exported.
|
// For production, use [NewBatchProcessor] to batch log records before they are exported.
|
||||||
// For testing and debugging, use [NewSimpleProcessor] to synchronously export log records.
|
// For testing and debugging, use [NewSimpleProcessor] to synchronously export log records.
|
||||||
|
//
|
||||||
|
// See [FilterProcessor] for information about how a Processor can support filtering.
|
||||||
func WithProcessor(processor Processor) LoggerProviderOption {
|
func WithProcessor(processor Processor) LoggerProviderOption {
|
||||||
return loggerProviderOptionFunc(func(cfg providerConfig) providerConfig {
|
return loggerProviderOptionFunc(func(cfg providerConfig) providerConfig {
|
||||||
cfg.processors = append(cfg.processors, processor)
|
cfg.processors = append(cfg.processors, processor)
|
||||||
if f, ok := processor.(x.FilterProcessor); ok {
|
if f, ok := processor.(FilterProcessor); ok {
|
||||||
cfg.fltrProcessors = append(cfg.fltrProcessors, f)
|
cfg.fltrProcessors = append(cfg.fltrProcessors, f)
|
||||||
}
|
}
|
||||||
return cfg
|
return cfg
|
||||||
|
@@ -22,7 +22,6 @@ import (
|
|||||||
"go.opentelemetry.io/otel/log"
|
"go.opentelemetry.io/otel/log"
|
||||||
"go.opentelemetry.io/otel/log/noop"
|
"go.opentelemetry.io/otel/log/noop"
|
||||||
ottest "go.opentelemetry.io/otel/sdk/internal/internaltest"
|
ottest "go.opentelemetry.io/otel/sdk/internal/internaltest"
|
||||||
"go.opentelemetry.io/otel/sdk/log/internal/x"
|
|
||||||
"go.opentelemetry.io/otel/sdk/resource"
|
"go.opentelemetry.io/otel/sdk/resource"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -65,9 +64,10 @@ type fltrProcessor struct {
|
|||||||
*processor
|
*processor
|
||||||
|
|
||||||
enabled bool
|
enabled bool
|
||||||
|
params []EnabledParameters
|
||||||
}
|
}
|
||||||
|
|
||||||
var _ x.FilterProcessor = (*fltrProcessor)(nil)
|
var _ FilterProcessor = (*fltrProcessor)(nil)
|
||||||
|
|
||||||
func newFltrProcessor(name string, enabled bool) *fltrProcessor {
|
func newFltrProcessor(name string, enabled bool) *fltrProcessor {
|
||||||
return &fltrProcessor{
|
return &fltrProcessor{
|
||||||
@@ -76,7 +76,8 @@ func newFltrProcessor(name string, enabled bool) *fltrProcessor {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *fltrProcessor) Enabled(context.Context, log.EnabledParameters) bool {
|
func (p *fltrProcessor) Enabled(_ context.Context, params EnabledParameters) bool {
|
||||||
|
p.params = append(p.params, params)
|
||||||
return p.enabled
|
return p.enabled
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user