1
0
mirror of https://github.com/open-telemetry/opentelemetry-go.git synced 2025-08-10 22:31:50 +02:00

chore: Update Logs API design doc (#6206)

There were some changes in the design that should be updated. Most
importantly:

- Logs Bridge API -> Logs API that can be called directly:
https://github.com/open-telemetry/opentelemetry-go/pull/6167
- addition of converting functions:
https://github.com/open-telemetry/opentelemetry-go/pull/6180
- event support:
https://github.com/open-telemetry/opentelemetry-go/pull/6187
This commit is contained in:
Robert Pająk
2025-01-27 18:48:18 +01:00
committed by GitHub
parent ae7ac48ebf
commit a027f1142b

View File

@@ -1,16 +1,16 @@
# Logs Bridge API # Logs API
## Abstract ## Abstract
`go.opentelemetry.io/otel/log` provides `go.opentelemetry.io/otel/log` provides
[Logs Bridge API](https://opentelemetry.io/docs/specs/otel/logs/bridge-api/). [Logs API](https://opentelemetry.io/docs/specs/otel/logs/api/).
The prototype was created in The prototype was created in
[#4725](https://github.com/open-telemetry/opentelemetry-go/pull/4725). [#4725](https://github.com/open-telemetry/opentelemetry-go/pull/4725).
## Background ## Background
The key challenge is to create a performant API compliant with the [specification](https://opentelemetry.io/docs/specs/otel/logs/bridge-api/) The key challenge is to create a performant API compliant with the [specification](https://opentelemetry.io/docs/specs/otel/logs/api/)
with an intuitive and user friendly design. with an intuitive and user friendly design.
Performance is seen as one of the most important characteristics of logging libraries in Go. Performance is seen as one of the most important characteristics of logging libraries in Go.
@@ -40,7 +40,7 @@ Rejected alternative:
### LoggerProvider ### LoggerProvider
The [`LoggerProvider` abstraction](https://opentelemetry.io/docs/specs/otel/logs/bridge-api/#loggerprovider) The [`LoggerProvider` abstraction](https://opentelemetry.io/docs/specs/otel/logs/api/#loggerprovider)
is defined as `LoggerProvider` interface in [provider.go](provider.go). is defined as `LoggerProvider` interface in [provider.go](provider.go).
The specification may add new operations to `LoggerProvider`. The specification may add new operations to `LoggerProvider`.
@@ -51,7 +51,7 @@ This approach is already used in Trace API and Metrics API.
#### LoggerProvider.Logger #### LoggerProvider.Logger
The `Logger` method implements the [`Get a Logger` operation](https://opentelemetry.io/docs/specs/otel/logs/bridge-api/#get-a-logger). The `Logger` method implements the [`Get a Logger` operation](https://opentelemetry.io/docs/specs/otel/logs/api/#get-a-logger).
The required `name` parameter is accepted as a `string` method argument. The required `name` parameter is accepted as a `string` method argument.
@@ -59,7 +59,7 @@ The `LoggerOption` options are defined to support optional parameters.
Implementation requirements: Implementation requirements:
- The [specification requires](https://opentelemetry.io/docs/specs/otel/logs/bridge-api/#concurrency-requirements) - The [specification requires](https://opentelemetry.io/docs/specs/otel/logs/api/#concurrency-requirements)
the method to be safe to be called concurrently. the method to be safe to be called concurrently.
- The method should use some default name if the passed name is empty - The method should use some default name if the passed name is empty
@@ -78,7 +78,7 @@ Rejected alternative:
### Logger ### Logger
The [`Logger` abstraction](https://opentelemetry.io/docs/specs/otel/logs/bridge-api/#logger) The [`Logger` abstraction](https://opentelemetry.io/docs/specs/otel/logs/api/#logger)
is defined as `Logger` interface in [logger.go](logger.go). is defined as `Logger` interface in [logger.go](logger.go).
The specification may add new operations to `Logger`. The specification may add new operations to `Logger`.
@@ -89,14 +89,14 @@ This approach is already used in Trace API and Metrics API.
### Logger.Emit ### Logger.Emit
The `Emit` method implements the [`Emit a LogRecord` operation](https://opentelemetry.io/docs/specs/otel/logs/bridge-api/#emit-a-logrecord). The `Emit` method implements the [`Emit a LogRecord` operation](https://opentelemetry.io/docs/specs/otel/logs/api/#emit-a-logrecord).
[`Context` associated with the `LogRecord`](https://opentelemetry.io/docs/specs/otel/context/) [`Context` associated with the `LogRecord`](https://opentelemetry.io/docs/specs/otel/context/)
is accepted as a `context.Context` method argument. is accepted as a `context.Context` method argument.
Calls to `Emit` are supposed to be on the hot path. Calls to `Emit` are supposed to be on the hot path.
Therefore, in order to reduce the number of heap allocations, Therefore, in order to reduce the number of heap allocations,
the [`LogRecord` abstraction](https://opentelemetry.io/docs/specs/otel/logs/bridge-api/#emit-a-logrecord), the [`LogRecord` abstraction](https://opentelemetry.io/docs/specs/otel/logs/api/#emit-a-logrecord),
is defined as `Record` struct in [record.go](record.go). is defined as `Record` struct in [record.go](record.go).
[`Timestamp`](https://opentelemetry.io/docs/specs/otel/logs/data-model/#field-timestamp) [`Timestamp`](https://opentelemetry.io/docs/specs/otel/logs/data-model/#field-timestamp)
@@ -115,6 +115,14 @@ func (r *Record) ObservedTimestamp() time.Time
func (r *Record) SetObservedTimestamp(t time.Time) func (r *Record) SetObservedTimestamp(t time.Time)
``` ```
[`EventName`](https://opentelemetry.io/docs/specs/otel/logs/data-model/#field-eventname)
is accessed using following methods:
```go
func (r *Record) EventName() string
func (r *Record) SetEventName(s string)
```
[`SeverityNumber`](https://opentelemetry.io/docs/specs/otel/logs/data-model/#field-severitynumber) [`SeverityNumber`](https://opentelemetry.io/docs/specs/otel/logs/data-model/#field-severitynumber)
is accessed using following methods: is accessed using following methods:
@@ -222,13 +230,13 @@ after the call (even when the documentation says that the caller must not do it)
Implementation requirements: Implementation requirements:
- The [specification requires](https://opentelemetry.io/docs/specs/otel/logs/bridge-api/#concurrency-requirements) - The [specification requires](https://opentelemetry.io/docs/specs/otel/logs/api/#concurrency-requirements)
the method to be safe to be called concurrently. the method to be safe to be called concurrently.
- The method must not interrupt the record processing if the context is canceled - The method must not interrupt the record processing if the context is canceled
per ["ignoring context cancellation" guideline](../CONTRIBUTING.md#ignoring-context-cancellation). per ["ignoring context cancellation" guideline](../CONTRIBUTING.md#ignoring-context-cancellation).
- The [specification requires](https://opentelemetry.io/docs/specs/otel/logs/bridge-api/#emit-a-logrecord) - The [specification requires](https://opentelemetry.io/docs/specs/otel/logs/api/#emit-a-logrecord)
use the current time as observed timestamp if the passed is empty. use the current time as observed timestamp if the passed is empty.
- The method should handle the trace context passed via `ctx` argument in order to meet the - The method should handle the trace context passed via `ctx` argument in order to meet the
@@ -253,7 +261,7 @@ Rejected alternatives:
### Logger.Enabled ### Logger.Enabled
The `Enabled` method implements the [`Enabled` operation](https://opentelemetry.io/docs/specs/otel/logs/bridge-api/#enabled). The `Enabled` method implements the [`Enabled` operation](https://opentelemetry.io/docs/specs/otel/logs/api/#enabled).
[`Context` associated with the `LogRecord`](https://opentelemetry.io/docs/specs/otel/context/) [`Context` associated with the `LogRecord`](https://opentelemetry.io/docs/specs/otel/context/)
is accepted as a `context.Context` method argument. is accepted as a `context.Context` method argument.
@@ -271,7 +279,7 @@ where `Enabled` is called.
### noop package ### noop package
The `go.opentelemetry.io/otel/log/noop` package provides The `go.opentelemetry.io/otel/log/noop` package provides
[Logs Bridge API No-Op Implementation](https://opentelemetry.io/docs/specs/otel/logs/noop/). [Logs API No-Op Implementation](https://opentelemetry.io/docs/specs/otel/logs/noop/).
### Trace context correlation ### Trace context correlation
@@ -319,7 +327,7 @@ nor any other logging library.
The API needs to evolve orthogonally to `slog`. The API needs to evolve orthogonally to `slog`.
`slog` is not compliant with the [Logs Bridge API](https://opentelemetry.io/docs/specs/otel/logs/bridge-api/). `slog` is not compliant with the [Logs API](https://opentelemetry.io/docs/specs/otel/logs/api/).
and we cannot expect the Go team to make `slog` compliant with it. and we cannot expect the Go team to make `slog` compliant with it.
The interoperability can be achieved using [a log bridge](https://opentelemetry.io/docs/specs/otel/glossary/#log-appender--bridge). The interoperability can be achieved using [a log bridge](https://opentelemetry.io/docs/specs/otel/glossary/#log-appender--bridge).
@@ -423,10 +431,12 @@ One of the proposals[^6] was to have `Record` as a simple struct:
type Record struct { type Record struct {
Timestamp time.Time Timestamp time.Time
ObservedTimestamp time.Time ObservedTimestamp time.Time
EventName string
Severity Severity Severity Severity
SeverityText string SeverityText string
Body Value Body Value
Attributes []KeyValue Attributes []KeyValue
}
``` ```
The bridge implementations could use [`sync.Pool`](https://pkg.go.dev/sync#Pool) The bridge implementations could use [`sync.Pool`](https://pkg.go.dev/sync#Pool)
@@ -508,7 +518,7 @@ It should be more user friendly to have them separated.
Especially when having getter and setter methods, setting one value Especially when having getter and setter methods, setting one value
when the other is already set would be unpleasant. when the other is already set would be unpleasant.
## Reuse attribute package ### Reuse attribute package
It was tempting to reuse the existing It was tempting to reuse the existing
[https://pkg.go.dev/go.opentelemetry.io/otel/attribute] package [https://pkg.go.dev/go.opentelemetry.io/otel/attribute] package
@@ -523,7 +533,7 @@ has anything in common with a common attribute value.
Therefore, we define new types representing the abstract types defined Therefore, we define new types representing the abstract types defined
in the [Logs Data Model](https://opentelemetry.io/docs/specs/otel/logs/data-model/#definitions-used-in-this-document). in the [Logs Data Model](https://opentelemetry.io/docs/specs/otel/logs/data-model/#definitions-used-in-this-document).
## Mix receiver types for Record ### Mix receiver types for Record
Methods of [`slog.Record`](https://pkg.go.dev/log/slog#Record) Methods of [`slog.Record`](https://pkg.go.dev/log/slog#Record)
have different receiver types. have different receiver types.
@@ -577,17 +587,9 @@ we decided to use pointer receivers for all `Record` methods.
### Add XYZ method to Logger ### Add XYZ method to Logger
The `Logger` does not have methods like `Enabled`, `SetSeverity`, etc. The `Logger` does not have methods like `SetSeverity`, etc.
as the Bridge API needs to follow (be compliant with) as the Logs API needs to follow (be compliant with)
the [specification](https://opentelemetry.io/docs/specs/otel/logs/bridge-api/) the [specification](https://opentelemetry.io/docs/specs/otel/logs/api/)
Moreover, the Bridge API is intended to be used to implement bridges.
Applications should not use it directly. The applications should use logging packages
such as [`slog`](https://pkg.go.dev/log/slog),
[`logrus`](https://pkg.go.dev/github.com/sirupsen/logrus),
[`zap`](https://pkg.go.dev/go.uber.org/zap),
[`zerolog`](https://pkg.go.dev/github.com/rs/zerolog),
[`logr`](https://pkg.go.dev/github.com/go-logr/logr).
### Rename KeyValue to Attr ### Rename KeyValue to Attr
@@ -597,16 +599,17 @@ the OpenTelemetry parlance.
During the discussion we agreed to keep the `KeyValue` name. During the discussion we agreed to keep the `KeyValue` name.
The type is used in two semantics: The type is used in multiple semantics:
- as a log attribute - as a log attribute,
- as a map item - as a map item,
- as a log record Body.
As for map item semantics, this type is a key-value pair, not an attribute. As for map item semantics, this type is a key-value pair, not an attribute.
Naming the type as `Attr` would convey semantical meaning Naming the type as `Attr` would convey semantical meaning
that would not be correct for a map. that would not be correct for a map.
We expect that most of the Bridge API users will be OpenTelemetry contributors. We expect that most of the Logs API users will be OpenTelemetry contributors.
We plan to implement bridges for the most popular logging libraries ourselves. We plan to implement bridges for the most popular logging libraries ourselves.
Given we will all have the context needed to disambiguate these overlapping Given we will all have the context needed to disambiguate these overlapping
names, developers' confusion should not be an issue. names, developers' confusion should not be an issue.
@@ -615,10 +618,8 @@ For bridges not developed by us,
developers will likely look at our existing bridges for inspiration. developers will likely look at our existing bridges for inspiration.
Our correct use of these types will be a reference to them. Our correct use of these types will be a reference to them.
At last, we could consider a design defining both types: `KeyValue` and `Attr`. At last, we provide `ValueFromAttribute` and `KeyValueFromAttribute`
However, in this approach we would need have factory functions for both types. to offer reuse of `attribute.Value` and `attribute.KeyValue`.
It would make the API surface unnecessarily big,
and we may even have problems naming the functions.
[^1]: [Handle structured body and attributes](https://github.com/pellared/opentelemetry-go/pull/7) [^1]: [Handle structured body and attributes](https://github.com/pellared/opentelemetry-go/pull/7)
[^2]: Jonathan Amsterdam, [The Go Blog: Structured Logging with slog](https://go.dev/blog/slog) [^2]: Jonathan Amsterdam, [The Go Blog: Structured Logging with slog](https://go.dev/blog/slog)