From bd87bfc92497d12738036b0a964f8e700656b8cf Mon Sep 17 00:00:00 2001 From: Tigran Najaryan Date: Wed, 5 Jul 2023 13:03:42 -0400 Subject: [PATCH 1/2] Clarify how log appender use Scope name and attributes Resolves https://github.com/open-telemetry/opentelemetry-specification/issues/3562 I moved the recommendations for appenders to a separate file named supplementary-guidelines.md. Similar to other signals this file will contain non-normative recommendations. --- CHANGELOG.md | 2 + specification/logs/bridge-api.md | 90 +------------ .../logs/supplementary-guidelines.md | 119 ++++++++++++++++++ 3 files changed, 127 insertions(+), 84 deletions(-) create mode 100644 specification/logs/supplementary-guidelines.md diff --git a/CHANGELOG.md b/CHANGELOG.md index f60d04b1b17..486860bccac 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -29,6 +29,8 @@ release. - Make SDK Logger Creation more normative. ([#3529](https://github.com/open-telemetry/opentelemetry-specification/pull/3529)) +- Clarify how log appender use Scope name and attributes. + ([#3583](https://github.com/open-telemetry/opentelemetry-specification/pull/3583)) ### Resource diff --git a/specification/logs/bridge-api.md b/specification/logs/bridge-api.md index dff8555b7d9..9ab3e418b18 100644 --- a/specification/logs/bridge-api.md +++ b/specification/logs/bridge-api.md @@ -18,20 +18,17 @@ - [Optional and required parameters](#optional-and-required-parameters) - [Concurrency requirements](#concurrency-requirements) - [Artifact Naming](#artifact-naming) -- [Usage](#usage) - * [How to Create a Log4J Log Appender](#how-to-create-a-log4j-log-appender) - * [Implicit Context Injection](#implicit-context-injection) - * [Explicit Context Injection](#explicit-context-injection) -Note: this document defines a log *backend* API. The API is not intended to be called -by application developers directly. It is provided for logging library authors -to build [log appenders](#how-to-create-a-log4j-log-appender), which use -this API to bridge between existing logging libraries and the OpenTelemetry log -data model. +Note: this document defines a log *backend* API. The API is not intended +to be called by application developers directly. It is provided for logging +library authors to build +[log appenders](./supplementary-guidelines.md#how-to-create-a-log4j-log-appender), +which use this API to bridge between existing logging libraries and the +OpenTelemetry log data model. The Logs Bridge API consist of these main classes: @@ -156,78 +153,3 @@ in the event OpenTelemetry were to add a user facing API, the Logs Bridge API wo be a natural starting point. Therefore, Log Bridge API artifact, package, and class names MUST NOT include the terms "bridge", "appender", or any other qualifier that would prevent evolution into a user facing API. - -## Usage - -### How to Create a Log4J Log Appender - -A [log appender](../glossary.md#log-appender--bridge) implementation can be used -to bridge logs into the [Log SDK](./sdk.md) -OpenTelemetry [LogRecordExporters](sdk.md#logrecordexporter). This approach is -typically used for applications which are fine with changing the log transport -and is [one of the supported](README.md#direct-to-collector) log collection -approaches. - -The log appender implementation will typically acquire a [Logger](#logger) from the -global [LoggerProvider](#loggerprovider) at startup time, then -call [Emit LogRecord](#emit-a-logrecord) for `LogRecord`s received from the -application. - -[Implicit Context Injection](#implicit-context-injection) -and [Explicit Context Injection](#explicit-context-injection) describe how an -Appender injects `TraceContext` into `LogRecord`s. - -![Appender](img/appender.png) - -This same approach can be also used for example for: - -- Python logging library by creating a Handler. -- Go zap logging library by implementing the Core interface. Note that since - there is no implicit Context in Go it is not possible to get and use the - active Span. - -Log appenders can be created in OpenTelemetry language libraries by OpenTelemetry -maintainers, or by 3rd parties for any logging library that supports a similar -extension mechanism. This specification recommends each OpenTelemetry language -library to include out-of-the-box Appender implementation for at least one -popular logging library. - -### Implicit Context Injection - -When Context is implicitly available (e.g. in Java) the Appender can rely on -automatic context propagation by NOT explicitly setting `Context` when -calling [emit a LogRecord](#emit-a-logrecord). - -Some log libraries have mechanisms specifically tailored for injecting -contextual information info logs, such as MDC in Log4j. When available, it may -be preferable to use these mechanisms to set the Context. A log appender can -then fetch the Context and explicitly set it when -calling [emit a LogRecord](#emit-a-logrecord). This allows the correct Context -to be included even when log records are emitted asynchronously, which can -otherwise lead the Context to be incorrect. - -TODO: clarify how works or doesn't work when the log statement call site and the -log appender are executed on different threads. - -### Explicit Context Injection - -In order for `TraceContext` to be recorded in `LogRecord`s in languages where -the Context must be provided explicitly (e.g. Go), the end user must capture the -Context and explicitly pass it to the logging subsystem. The log appender must -take this Context and explicitly set it when -calling [emit a LogRecord](#emit-a-logrecord). - -Support for OpenTelemetry for logging libraries in these languages typically can -be implemented in the form of logger wrappers that can capture the context once, -when the span is created and then use the wrapped logger to execute log -statements in a normal way. The wrapper will be responsible for injecting the -captured context in the logs. - -This specification does not define how exactly it is achieved since the actual -mechanism depends on the language and the particular logging library used. In -any case the wrappers are expected to make use of the Trace Context API to get -the current active span. - -See -[an example](https://docs.google.com/document/d/15vR7D1x2tKd7u3zaTF0yH1WaHkUr2T4hhr7OyiZgmBg/edit#heading=h.4xuru5ljcups) -of how it can be done for zap logging library for Go. diff --git a/specification/logs/supplementary-guidelines.md b/specification/logs/supplementary-guidelines.md new file mode 100644 index 00000000000..6ae47dda34a --- /dev/null +++ b/specification/logs/supplementary-guidelines.md @@ -0,0 +1,119 @@ +# Supplementary Guidelines + +Note: this document is NOT a spec, it is provided to support the Logs +[API](./bridge-api.md) and [SDK](./sdk.md) specifications, it does NOT add any +extra requirements to the existing specifications. + +
+Table of Contents + + + + + +- [Usage](#usage) + * [How to Create a Log4J Log Appender](#how-to-create-a-log4j-log-appender) + * [Logger Name](#logger-name) + * [Context](#context) + + [Implicit Context Injection](#implicit-context-injection) + + [Explicit Context Injection](#explicit-context-injection) + + + +
+ +## Usage + +### How to Create a Log4J Log Appender + +A [log appender](../glossary.md#log-appender--bridge) implementation can be used +to bridge logs into the [Log SDK](./sdk.md) +OpenTelemetry [LogRecordExporters](sdk.md#logrecordexporter). This approach is +typically used for applications which are fine with changing the log transport +and is [one of the supported](README.md#direct-to-collector) log collection +approaches. + +The log appender implementation will typically acquire a +[Logger](./bridge-api.md#logger) from the global +[LoggerProvider](./bridge-api.md#loggerprovider) at startup time, then +call [Emit LogRecord](./bridge-api.md#emit-a-logrecord) for `LogRecord`s +received from the application. + +[Implicit Context Injection](#implicit-context-injection) +and [Explicit Context Injection](#explicit-context-injection) describe how an +Appender injects `TraceContext` into `LogRecord`s. + +![Appender](img/appender.png) + +This same approach can be also used for example for: + +- Python logging library by creating a Handler. +- Go zap logging library by implementing the Core interface. Note that since + there is no implicit Context in Go it is not possible to get and use the + active Span. + +Log appenders can be created in OpenTelemetry language libraries by OpenTelemetry +maintainers, or by 3rd parties for any logging library that supports a similar +extension mechanism. This specification recommends each OpenTelemetry language +library to include out-of-the-box Appender implementation for at least one +popular logging library. + +### Logger Name + +If the logging library has a concept that is similar to OpenTelemetry's +definition of the [Instrumentation Scope's](../glossary.md#instrumentation-scope) +name then the appender's implementation should use that value as the +name parameter when [obtaining the Logger](./bridge-api.md#get-a-logger). + +This is for example applicable to: + +- Logger name in [Log4J](https://javadoc.io/doc/org.apache.logging.log4j/log4j-api/latest/org.apache.logging.log4j/org/apache/logging/log4j/Logger.html) +- Channel name in [Monolog](https://github.com/Seldaek/monolog/blob/main/doc/01-usage.md#leveraging-channels) + +Appender's should avoid setting other attributes of the Instrumentation Scope. +Doing so may result in different appenders setting different attributes on the +same Instrumentation Scope, obtained with the same identity of the +[Logger](./bridge-api.md#get-a-logger), which according to the specification +is an error. + +### Context + +#### Implicit Context Injection + +When Context is implicitly available (e.g. in Java) the Appender can rely on +automatic context propagation by NOT explicitly setting `Context` when +calling [emit a LogRecord](./bridge-api.md#emit-a-logrecord). + +Some log libraries have mechanisms specifically tailored for injecting +contextual information info logs, such as MDC in Log4j. When available, it may +be preferable to use these mechanisms to set the Context. A log appender can +then fetch the Context and explicitly set it when +calling [emit a LogRecord](./bridge-api.md#emit-a-logrecord). This allows the correct Context +to be included even when log records are emitted asynchronously, which can +otherwise lead the Context to be incorrect. + +TODO: clarify how works or doesn't work when the log statement call site and the +log appender are executed on different threads. + +#### Explicit Context Injection + +In order for `TraceContext` to be recorded in `LogRecord`s in languages where +the Context must be provided explicitly (e.g. Go), the end user must capture the +Context and explicitly pass it to the logging subsystem. The log appender must +take this Context and explicitly set it when +calling [emit a LogRecord](./bridge-api.md#emit-a-logrecord). + +Support for OpenTelemetry for logging libraries in these languages typically can +be implemented in the form of logger wrappers that can capture the context once, +when the span is created and then use the wrapped logger to execute log +statements in a normal way. The wrapper will be responsible for injecting the +captured context in the logs. + +This specification does not define how exactly it is achieved since the actual +mechanism depends on the language and the particular logging library used. In +any case the wrappers are expected to make use of the Trace Context API to get +the current active span. + +See +[an example](https://docs.google.com/document/d/15vR7D1x2tKd7u3zaTF0yH1WaHkUr2T4hhr7OyiZgmBg/edit#heading=h.4xuru5ljcups) +of how it can be done for zap logging library for Go. From 80b13fa48895b2522d8b1de670936c3080a7d379 Mon Sep 17 00:00:00 2001 From: Tigran Najaryan Date: Mon, 31 Jul 2023 11:03:46 -0400 Subject: [PATCH 2/2] Address PR comments --- specification/logs/supplementary-guidelines.md | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/specification/logs/supplementary-guidelines.md b/specification/logs/supplementary-guidelines.md index 6ae47dda34a..47284e45d79 100644 --- a/specification/logs/supplementary-guidelines.md +++ b/specification/logs/supplementary-guidelines.md @@ -34,8 +34,7 @@ and is [one of the supported](README.md#direct-to-collector) log collection approaches. The log appender implementation will typically acquire a -[Logger](./bridge-api.md#logger) from the global -[LoggerProvider](./bridge-api.md#loggerprovider) at startup time, then +[Logger](./bridge-api.md#logger), then call [Emit LogRecord](./bridge-api.md#emit-a-logrecord) for `LogRecord`s received from the application. @@ -62,18 +61,18 @@ popular logging library. If the logging library has a concept that is similar to OpenTelemetry's definition of the [Instrumentation Scope's](../glossary.md#instrumentation-scope) -name then the appender's implementation should use that value as the +name, then the appender's implementation should use that value as the name parameter when [obtaining the Logger](./bridge-api.md#get-a-logger). This is for example applicable to: - Logger name in [Log4J](https://javadoc.io/doc/org.apache.logging.log4j/log4j-api/latest/org.apache.logging.log4j/org/apache/logging/log4j/Logger.html) -- Channel name in [Monolog](https://github.com/Seldaek/monolog/blob/main/doc/01-usage.md#leveraging-channels) +- Channel name in [Monolog](https://github.com/Seldaek/monolog/blob/3.4.0/doc/01-usage.md#leveraging-channels) -Appender's should avoid setting other attributes of the Instrumentation Scope. +Appenders should avoid setting any attributes of the Instrumentation Scope. Doing so may result in different appenders setting different attributes on the same Instrumentation Scope, obtained with the same identity of the -[Logger](./bridge-api.md#get-a-logger), which according to the specification +[Logger](./bridge-api.md#get-a-logger), which, according to the specification, is an error. ### Context