Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,9 @@ release.

### Logs

- Add `Enabled` opt-in operation to the `LogRecordProcessor`.
([#4439](https://github.com/open-telemetry/opentelemetry-specification/pull/4439))

### Baggage

### Resource
Expand Down
1 change: 1 addition & 0 deletions spec-compliance-matrix.md
Original file line number Diff line number Diff line change
Expand Up @@ -203,6 +203,7 @@ Disclaimer: this list of features is still a work in progress, please refer to t
| SimpleLogRecordProcessor | | | + | | + | | | + | | + | | |
| BatchLogRecordProcessor | | | + | | + | | | + | | + | | |
| Can plug custom LogRecordProcessor | | | + | | + | | | + | | + | | |
| LogRecordProcessor.Enabled | X | + | | | | | | | | | | |
| OTLP/gRPC exporter | | | + | | + | | | + | | + | + | |
| OTLP/HTTP exporter | | | + | | + | | | + | | + | + | |
| OTLP File exporter | | | - | | - | | | | | + | - | |
Expand Down
45 changes: 44 additions & 1 deletion specification/logs/sdk.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
- [LogRecordProcessor](#logrecordprocessor)
* [LogRecordProcessor operations](#logrecordprocessor-operations)
+ [OnEmit](#onemit)
+ [Enabled](#enabled-1)
+ [ShutDown](#shutdown)
+ [ForceFlush](#forceflush-1)
* [Built-in processors](#built-in-processors)
Expand Down Expand Up @@ -198,7 +199,9 @@ It consists of the following parameters:
`Enabled` MUST return `false` when:

- there are no registered [`LogRecordProcessors`](#logrecordprocessor),
- `Logger` is disabled ([`LoggerConfig.disabled`](#loggerconfig) is `true`).
- `Logger` is disabled ([`LoggerConfig.disabled`](#loggerconfig) is `true`),
- all registered `LogRecordProcessors` implement [`Enabled`](#enabled-1),
and a call to `Enabled` on each of them returns `false`.

Otherwise, it SHOULD return `true`.
It MAY return `false` to support additional optimizations and features.
Expand Down Expand Up @@ -345,6 +348,46 @@ A `LogRecordProcessor` may freely modify `logRecord` for the duration of
the `OnEmit` call. If `logRecord` is needed after `OnEmit` returns (i.e. for
asynchronous processing) only reads are permitted.

#### Enabled

**Status**: [Development](../document-status.md)

`Enabled` is an operation that a `LogRecordProcessor` MAY implement
in order to support filtering via [`Logger.Enabled`](api.md#enabled).

**Parameters:**

* [Context](../context/README.md) explicitly passed by the caller or the current
Context
* [Instrumentation Scope](./data-model.md#field-instrumentationscope) associated
with the `Logger`
* [Severity Number](./data-model.md#field-severitynumber) passed by the caller

**Returns:** `Boolean`

An implementation should return `false` if a `LogRecord` (if ever created)
is supposed to be filtered out for the given parameters.
It should default to returning `true` for any indeterminate state, for example,
when awaiting configuration.

Any modifications to parameters inside `Enabled` MUST NOT be propagated to the
caller. Parameters are immutable or passed by value.

This operation is usually called synchronously, therefore it should not block
or throw exceptions.

`LogRecordProcessor` implementations responsible for filtering and supporting
the `Enable` operation should ensure that [`OnEmit`](#onemit) handles filtering
independently. API users cannot be expected to call [`Enabled`](api.md#enabled)
before invoking [`Emit a LogRecord`](api.md#emit-a-logrecord).
Moreover, the filtering logic in `OnEmit` and `Enabled` may differ.

`LogRecordProcessor` implementations that wrap other `LogRecordProcessor`
(which may perform filtering) can implement `Enabled` and delegate to
the wrapped processor’s `Enabled`, if available. However, the `OnEmit`
implementation of such processors should never call the wrapped processor’s
`Enabled`, as `OnEmit` is responsible for handling filtering independently.

#### ShutDown

Shuts down the processor. Called when the SDK is shut down. This is an
Expand Down
59 changes: 59 additions & 0 deletions specification/logs/supplementary-guidelines.md
Original file line number Diff line number Diff line change
Expand Up @@ -203,6 +203,19 @@ func (p *SeverityProcessor) OnEmit(ctx context.Context, record *sdklog.Record) e
}
return p.Processor.OnEmit(ctx, record)
}

// Enabled returns false if the severity is lower than p.Min.
func (p *SeverityProcessor) Enabled(ctx context.Context, param sdklog.EnabledParameters) bool {
sev := param.Severity
if sev != log.SeverityUndefined && sev < p.Min {
return false
}
if fp, ok := p.Processor.(sdklog.FilterProcessor); ok {
// The wrapped processor is also a filtering processor.
return p.Processor.Enabled(ctx, param)
}
return true
}
```

> [!NOTE]
Expand Down Expand Up @@ -242,6 +255,29 @@ func (p *IsolatedProcessor) OnEmit(ctx context.Context, record *log.Record) erro
}
return rErr
}

// Enabled honors Enabled of the wrapped processors.
func (p *IsolatedProcessor) Enabled(ctx context.Context, param sdklog.EnabledParameters) bool {
fltrProcessors := make([]sdklog.FilterProcessor, len(p.Processors))
for i, proc := range p.Processors {
fp, ok := proc.(sdklog.FilterProcessor)
if !ok {
// Processor not implementing Enabled.
// We assume it will be processed.
return true
}
fltrProcessors[i] = fp
}

for _, proc := range fltrProcessors {
if proc.Enabled(ctx, param) {
// At least one Processor will process the Record.
return true
}
}
// No processor will process the record.
return false
}
```

#### Routing
Expand Down Expand Up @@ -271,6 +307,29 @@ func (p *LogEventRouteProcessor) OnEmit(ctx context.Context, record *log.Record)
}
return p.LogProcessor.OnEmit(ctx, record)
}

// Enabled honors Enabled of the wrapped processors.
func (p *LogEventRouteProcessor) Enabled(ctx context.Context, param sdklog.EnabledParameters) bool {
fp1, ok := p.EventProcessor.(sdklog.FilterProcessor)
if !ok {
// Processor not implementing Enabled.
return true
}
fp2, ok := p.LogProcessor.(sdklog.FilterProcessor)
if !ok {
// Processor not implementing Enabled.
return true
}

if fp1.Enabled(ctx, param) {
return true
}
if fp2.Enabled(ctx, param) {
return true
}
// No processor will process the record.
return false
}
```

#### Setup
Expand Down