From 44819cc17b48da441ec8949da2c0796f86d4b9a4 Mon Sep 17 00:00:00 2001 From: Santosh Cheler Date: Fri, 24 Jun 2022 05:10:04 +0530 Subject: [PATCH 01/29] Events and Logs API spec --- specification/logs/events-and-logs-api.md | 141 ++++++++++++++++++ .../logs/img/events-and-logs-api.png | Bin 0 -> 30927 bytes 2 files changed, 141 insertions(+) create mode 100644 specification/logs/events-and-logs-api.md create mode 100644 specification/logs/img/events-and-logs-api.png diff --git a/specification/logs/events-and-logs-api.md b/specification/logs/events-and-logs-api.md new file mode 100644 index 00000000000..c26a9bdcdc7 --- /dev/null +++ b/specification/logs/events-and-logs-api.md @@ -0,0 +1,141 @@ +## Events and Logs API Interface + +For reference, a prototype of the Events and Logs API in Java is [here](https://github.com/scheler/opentelemetry-java/pull/1/files) + +Client-side telemetry is one of the initial clients that will use the Events API and so the API will be made available in JavaScript, Java and Swift first to be able to use in the SDKs for Browser, Android and iOS. It may also be added in Go since there is a Kubernetes events receiver implemented in Collector based on Logs data-model. + +The Events and Logs API consist of these main classes: + +* LoggerProvider is the entry point of the API. It provides access to Loggers. +* Logger is the class responsible for creating events using Log records. + +LoggerProvider/Logger are analogous to TracerProvider/Tracer. + +![Events and Logs API classes](img/-events-and-logs-api.png) + +### LoggerProvider + +Logger can be accessed with an LoggerProvider. + +In implementations of the API, the LoggerProvider is expected to be the stateful object that holds any configuration. (Note: The SDK implementation of this is what we currently call the [LogEmitterProvider](https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/logs/logging-library-sdk.md#logemitterprovider)) + +Normally, the LoggerProvider is expected to be accessed from a central place. Thus, the API SHOULD provide a way to set/register and access a global default LoggerProvider. + +Notwithstanding any global LoggerProvider, some applications may want to or have to use multiple LoggerProvider instances, e.g. to have different configuration (like LogRecordProcessors) for each (and consequently for the Loggers obtained from them), or because it's easier with dependency injection frameworks. Thus, implementations of LoggerProvider SHOULD allow creating an arbitrary number of instances. + +#### LoggerProvider operations + +The LoggerProvider MUST provide the following functions: + +* Get an Logger + +##### Get an Logger + +This API MUST accept the following parameters that determine the scope for the `Logger` returned. Most of these are common with the scope parameters for `Tracer` and `Meter`, except for `event_domain` and `include_trace_context` which is specific to `Logger`. + +- `name` (required): This name SHOULD uniquely identify the [instrumentation scope](../glossary.md#instrumentation-scope), such as the [instrumentation library](../glossary.md#instrumentation-library) (e.g. `io.opentelemetry.contrib.mongodb`), package, module or class name. If an application or library has built-in OpenTelemetry instrumentation, both [Instrumented library](../glossary.md#instrumented-library) and [Instrumentation library](../glossary.md#instrumentation-library) may refer to the same library. In that scenario, the `name` denotes a module name or component name within that library or application. In case an invalid name (null or empty string) is specified, a working Logger implementation MUST be returned as a fallback rather than returning null or throwing an exception, its `name` property SHOULD be set to an empty string, and a message reporting that the specified value is invalid SHOULD be logged. A library implementing the OpenTelemetry API may also ignore this name and return a default instance for all calls, if it does not support "named" functionality (e.g. an implementation which is not even observability-related). A LoggerProvider could also return a no-op Logger here if application owners configure the SDK to suppress telemetry produced by this library. + +- `version` (optional): Specifies the version of the instrumentation scope if the scope has a version (e.g. a library version). Example value: 1.0.0. +- `schema_url` (optional): Specifies the Schema URL that should be recorded in the emitted telemetry +- `event_domain` (optional): Specifies the domain for the events created, which should be added in the attribute `event.domain` in the instrumentation scope. +- `include_trace_context` (optional): Specifies whether the Trace Context should automatically be passed on to the events and logs created by the Logger. This SHOULD be false by default. +- `attributes` (optional): Specifies the instrumentation scope attributes to associate with emitted telemetry. + +Implementations MUST return different `Logger` instances when called repeatedly with different values of parameters. Note that always returning a new `Logger` instance is a valid implementation. The only exception to this rule is the no-op `Logger`: implementations MAY return the same instance regardless of parameter values. + +Implementations MUST NOT require users to repeatedly obtain an Logger again with the same name+version+schema_url+event_domain+include_trace_context+attributes to pick up configuration changes. This can be achieved either by allowing to work with an outdated configuration or by ensuring that new configuration applies also to previously returned Loggers. + +Note: This could, for example, be implemented by storing any mutable configuration in the LoggerProvider and having Logger implementation objects have a reference to the LoggerProvider from which they were obtained. If configuration must be stored per-Logger (such as disabling a certain Logger), the Logger could, for example, do a look-up with its name+version+schema_url+event_domain+include_trace_context+attributes in a map in the LoggerProvider, or the LoggerProvider could maintain a registry of all returned Loggers and actively update their configuration if it changes. + +The effect of associating a Schema URL with a Logger MUST be that the telemetry emitted using the Logger will be associated with the Schema URL, provided that the emitted data format is capable of representing such association. + +### Logger + +The Logger is responsible for creating Events and Logs. + +Note that Loggers should not be responsible for configuration. This should be the responsibility of the LoggerProvider instead. + +#### Logger operations + +The Logger MUST provide functions to: + +- Create an `Event` and emit it to the processing pipeline. + - The API MUST accept an event name as a parameter. The event name provided should be inserted as an attribute with key `event.name`. Care MUST be taken to not override or delete this attribute while the `Event` is created. This function MAY be named `logEvent`. +- Create a `Log Record` and emit it to the processing pipeline. + - This function MAY be named `logRecord`. + - The intended users of this API is Log Appenders. + +### Usage + +```java +OpenTelemetry openTelemetry = OpenTelemetry.noop(); +Logger logger = openTelemetry.getLogger("my-scope"); + +// Using the convenience method to log an event directly +logger.logEvent("network-changed", + Attributes.builder().put("type", "wifi").build()); + +// Using the event builder to log an event +logger.eventBuilder("page-navigated").build().setAttribute("url", "http://foo.com/bar#new").emit(); + +// Using the logRecord builder to log a record +Logger logger = openTelemetry.getLogger("another-scope"); +logger.logRecordBuilder().build().setBody("I am a log message").emit(); + +``` + +### Usage in Client-side telemetry + +Some Events in a browser application occur when there is no span in progress, for example, errors, user interaction events and web-vitals. They can be recorded as standalone Events as follows. + +```java +public void addBrowserEvent(String name, Attributes attributes) { + Logger logger = openTelemetry.getLogger("my-scope", "1.0", "browser"); + logger.logEvent(name, attributes); +} + +public void addMobileEvent(String name, Attributes attributes) { + Logger logger = openTelemetry.getLogger("my-scope", "1.0", "mobile"); + logger.logEvent(name, attributes); +} +``` + +## Semantic Convention for event attributes + +We introduce the concept of an event domain as a mechanism to avoid conflicts with event names. + +**type:** `event` + +**Description:** Event attributes. + +| Attribute | Type | Description | Examples | Required | +|---|---|---|---|---| +| `event.name` | string | Name or type of the event. | `network-change`; `button-click`; `exception` | Yes | +| `event.domain` | string | Domain or scope for the event. | `profiling`; `browser`, `db`, `k8s` | No | + +An `event.name` is supposed to be unique only in the context of an `event.domain`, so this allows for two events in different domains to have same `event.name`, yet be unrelated events. No claim is made about the uniqueness of `event.name`s in the absence of `event.domain`. + +Note that Scope attributes are equivalent to the attributes at Span and LogRecord level, so recording the attribute `event.domain` on the Scope is equivalent to recording it on Spans and LogRecords within the Scope. + +## Causality on Events + +It is sometimes desired to indicate one event led to another. Since spans in a trace are better suited to represent causality, we can create wrapper spans to represent causality between events. Note that the events themselves are represented using LogRecords and not as Span Events. + +```java + +Logger logger = openTelemetry.getLogger("my-scope", "1.0", "mobile", /* include_trace_context */ true); + +Span span1 = tracer.spanBuilder(event1).startSpan(); + logger.logEvent(event1, attributes) + Span span2 = tracer.spanBuilder(event2).startSpan(); + logger.logEvent(event2, attributes) + span2.end() +span1.end() +``` + +## Comparing with Span Events + +- Span Events are events recorded within spans using Trace API. It is not possible to create standalone Events using Trace API. The Events API must be used instead. +- Span Events were added in the Trace spec when Logs spec was in early stages. Ideally, Events should only be recorded using LogRecords and correlated with Spans by adding Span Context in the LogRecords. However, since Trace API spec is stable Span Events MUST continue to be supported. +- We may add a configuration option to the `TracerProvider` to create LogRecords for the Span Events and associate them with the Span using Span Context in the LogRecords. Note that in this case, if a noop TracerProvider is used it will not produce LogRecords for the Span Events. + diff --git a/specification/logs/img/events-and-logs-api.png b/specification/logs/img/events-and-logs-api.png new file mode 100644 index 0000000000000000000000000000000000000000..55582dadf4ca5779be7a35a972c17d8b3248e48b GIT binary patch literal 30927 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 Date: Wed, 13 Jul 2022 16:49:11 +0530 Subject: [PATCH 02/29] API spec for events and logs --- specification/logs/api.md | 63 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 63 insertions(+) create mode 100644 specification/logs/api.md diff --git a/specification/logs/api.md b/specification/logs/api.md new file mode 100644 index 00000000000..cb56de08124 --- /dev/null +++ b/specification/logs/api.md @@ -0,0 +1,63 @@ +## Events and Logs API Interface + +The Events and Logs API consist of these main classes: + +* LoggerProvider is the entry point of the API. It provides access to Loggers. +* Logger is the class responsible for creating events using Log records. + +LoggerProvider/Logger are analogous to TracerProvider/Tracer. + +![Events and Logs API classes](img/events-and-logs-api.png) + +### LoggerProvider + +Logger can be accessed with an LoggerProvider. + +In implementations of the API, the LoggerProvider is expected to be the stateful object that holds any configuration. (Note: The SDK implementation of this is what we currently call the [LogEmitterProvider](https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/logs/logging-library-sdk.md#logemitterprovider)) + +Normally, the LoggerProvider is expected to be accessed from a central place. Thus, the API SHOULD provide a way to set/register and access a global default LoggerProvider. + +Notwithstanding any global LoggerProvider, some applications may want to or have to use multiple LoggerProvider instances, e.g. to have different configuration (like LogRecordProcessors) for each (and consequently for the Loggers obtained from them), or because it's easier with dependency injection frameworks. Thus, implementations of LoggerProvider SHOULD allow creating an arbitrary number of instances. + +#### LoggerProvider operations + +The LoggerProvider MUST provide the following functions: + +* Get an Logger + +##### Get an Logger + +This API MUST accept the following parameters that determine the scope for the `Logger` returned. Most of these are common with the scope parameters for `Tracer` and `Meter`, except for `event_domain` and `include_trace_context` which is specific to `Logger`. + +- `name` (required): This name SHOULD uniquely identify the [instrumentation scope](../glossary.md#instrumentation-scope), such as the [instrumentation library](../glossary.md#instrumentation-library) (e.g. `io.opentelemetry.contrib.mongodb`), package, module or class name. If an application or library has built-in OpenTelemetry instrumentation, both [Instrumented library](../glossary.md#instrumented-library) and [Instrumentation library](../glossary.md#instrumentation-library) may refer to the same library. In that scenario, the `name` denotes a module name or component name within that library or application. In case an invalid name (null or empty string) is specified, a working Logger implementation MUST be returned as a fallback rather than returning null or throwing an exception, its `name` property SHOULD be set to an empty string, and a message reporting that the specified value is invalid SHOULD be logged. A library implementing the OpenTelemetry API may also ignore this name and return a default instance for all calls, if it does not support "named" functionality (e.g. an implementation which is not even observability-related). A LoggerProvider could also return a no-op Logger here if application owners configure the SDK to suppress telemetry produced by this library. + +- `version` (optional): Specifies the version of the instrumentation scope if the scope has a version (e.g. a library version). Example value: 1.0.0. +- `schema_url` (optional): Specifies the Schema URL that should be recorded in the emitted telemetry +- `event_domain` (optional): Specifies the domain for the events created, which should be added in the attribute `event.domain` in the instrumentation scope. +- `include_trace_context` (optional): Specifies whether the Trace Context should automatically be passed on to the events and logs created by the Logger. This SHOULD be false by default. +- `attributes` (optional): Specifies the instrumentation scope attributes to associate with emitted telemetry. + +Implementations MUST return different `Logger` instances when called repeatedly with different values of parameters. Note that always returning a new `Logger` instance is a valid implementation. The only exception to this rule is the no-op `Logger`: implementations MAY return the same instance regardless of parameter values. + +Implementations MUST NOT require users to repeatedly obtain an Logger again with the same name+version+schema_url+event_domain+include_trace_context+attributes to pick up configuration changes. This can be achieved either by allowing to work with an outdated configuration or by ensuring that new configuration applies also to previously returned Loggers. + +Note: This could, for example, be implemented by storing any mutable configuration in the LoggerProvider and having Logger implementation objects have a reference to the LoggerProvider from which they were obtained. If configuration must be stored per-Logger (such as disabling a certain Logger), the Logger could, for example, do a look-up with its name+version+schema_url+event_domain+include_trace_context+attributes in a map in the LoggerProvider, or the LoggerProvider could maintain a registry of all returned Loggers and actively update their configuration if it changes. + +The effect of associating a Schema URL with a Logger MUST be that the telemetry emitted using the Logger will be associated with the Schema URL, provided that the emitted data format is capable of representing such association. + +### Logger + +The Logger is responsible for creating Events and Logs. + +Note that Loggers should not be responsible for configuration. This should be the responsibility of the LoggerProvider instead. + +#### Logger operations + +The Logger MUST provide functions to: + +- Create an `Event` and emit it to the processing pipeline. + - The API MUST accept an event name as a parameter. The event name provided should be inserted as an attribute with key `event.name`. Care MUST be taken to not override or delete this attribute while the `Event` is created. This function MAY be named `logEvent`. +- Create a `Log Record` and emit it to the processing pipeline. + - This function MAY be named `logRecord`. + - The intended users of this API is Log Appenders. + From e97b6ff2121d43fcdf55658f33cdd9c830fb2ed7 Mon Sep 17 00:00:00 2001 From: Santosh Cheler Date: Wed, 13 Jul 2022 17:04:50 +0530 Subject: [PATCH 03/29] Semantic conventions for events --- specification/logs/api.md | 2 +- .../logs/semantic_conventions/events.md | 19 +++++++++++++++++++ 2 files changed, 20 insertions(+), 1 deletion(-) create mode 100644 specification/logs/semantic_conventions/events.md diff --git a/specification/logs/api.md b/specification/logs/api.md index cb56de08124..d00512a36ce 100644 --- a/specification/logs/api.md +++ b/specification/logs/api.md @@ -3,7 +3,7 @@ The Events and Logs API consist of these main classes: * LoggerProvider is the entry point of the API. It provides access to Loggers. -* Logger is the class responsible for creating events using Log records. +* Logger is the class responsible for creating events and logs using Log records. LoggerProvider/Logger are analogous to TracerProvider/Tracer. diff --git a/specification/logs/semantic_conventions/events.md b/specification/logs/semantic_conventions/events.md new file mode 100644 index 00000000000..76be6014eb3 --- /dev/null +++ b/specification/logs/semantic_conventions/events.md @@ -0,0 +1,19 @@ +# Semantic Convention for event attributes + +**Status**: [Experimental](../../document-status.md) + +This document describes the attributes of standalone Events that are represented by `LogRecord`s. All standalone Events have a name and a domain. The Event domain is used as a mechanism to avoid conflicts with event names. + +**type:** `event` + +**Description:** Event attributes. + +| Attribute | Type | Description | Examples | Required | +|---|---|---|---|---| +| `event.name` | string | Name or type of the event. | `network-change`; `button-click`; `exception` | Yes | +| `event.domain` | string | Domain or scope for the event. | `profiling`; `browser`, `db`, `k8s` | No | + +An `event.name` is supposed to be unique only in the context of an `event.domain`, so this allows for two events in different domains to have same `event.name`, yet be unrelated events. No claim is made about the uniqueness of `event.name`s in the absence of `event.domain`. + +Note that Scope attributes are equivalent to the attributes at Span and LogRecord level, so recording the attribute `event.domain` on the Scope is equivalent to recording it on Spans and LogRecords within the Scope. + From 00cf1f222a901c92579a3355d28c31c27510288d Mon Sep 17 00:00:00 2001 From: Santosh Cheler Date: Wed, 13 Jul 2022 17:05:49 +0530 Subject: [PATCH 04/29] Deleting file --- specification/logs/events-and-logs-api.md | 141 ---------------------- 1 file changed, 141 deletions(-) delete mode 100644 specification/logs/events-and-logs-api.md diff --git a/specification/logs/events-and-logs-api.md b/specification/logs/events-and-logs-api.md deleted file mode 100644 index c26a9bdcdc7..00000000000 --- a/specification/logs/events-and-logs-api.md +++ /dev/null @@ -1,141 +0,0 @@ -## Events and Logs API Interface - -For reference, a prototype of the Events and Logs API in Java is [here](https://github.com/scheler/opentelemetry-java/pull/1/files) - -Client-side telemetry is one of the initial clients that will use the Events API and so the API will be made available in JavaScript, Java and Swift first to be able to use in the SDKs for Browser, Android and iOS. It may also be added in Go since there is a Kubernetes events receiver implemented in Collector based on Logs data-model. - -The Events and Logs API consist of these main classes: - -* LoggerProvider is the entry point of the API. It provides access to Loggers. -* Logger is the class responsible for creating events using Log records. - -LoggerProvider/Logger are analogous to TracerProvider/Tracer. - -![Events and Logs API classes](img/-events-and-logs-api.png) - -### LoggerProvider - -Logger can be accessed with an LoggerProvider. - -In implementations of the API, the LoggerProvider is expected to be the stateful object that holds any configuration. (Note: The SDK implementation of this is what we currently call the [LogEmitterProvider](https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/logs/logging-library-sdk.md#logemitterprovider)) - -Normally, the LoggerProvider is expected to be accessed from a central place. Thus, the API SHOULD provide a way to set/register and access a global default LoggerProvider. - -Notwithstanding any global LoggerProvider, some applications may want to or have to use multiple LoggerProvider instances, e.g. to have different configuration (like LogRecordProcessors) for each (and consequently for the Loggers obtained from them), or because it's easier with dependency injection frameworks. Thus, implementations of LoggerProvider SHOULD allow creating an arbitrary number of instances. - -#### LoggerProvider operations - -The LoggerProvider MUST provide the following functions: - -* Get an Logger - -##### Get an Logger - -This API MUST accept the following parameters that determine the scope for the `Logger` returned. Most of these are common with the scope parameters for `Tracer` and `Meter`, except for `event_domain` and `include_trace_context` which is specific to `Logger`. - -- `name` (required): This name SHOULD uniquely identify the [instrumentation scope](../glossary.md#instrumentation-scope), such as the [instrumentation library](../glossary.md#instrumentation-library) (e.g. `io.opentelemetry.contrib.mongodb`), package, module or class name. If an application or library has built-in OpenTelemetry instrumentation, both [Instrumented library](../glossary.md#instrumented-library) and [Instrumentation library](../glossary.md#instrumentation-library) may refer to the same library. In that scenario, the `name` denotes a module name or component name within that library or application. In case an invalid name (null or empty string) is specified, a working Logger implementation MUST be returned as a fallback rather than returning null or throwing an exception, its `name` property SHOULD be set to an empty string, and a message reporting that the specified value is invalid SHOULD be logged. A library implementing the OpenTelemetry API may also ignore this name and return a default instance for all calls, if it does not support "named" functionality (e.g. an implementation which is not even observability-related). A LoggerProvider could also return a no-op Logger here if application owners configure the SDK to suppress telemetry produced by this library. - -- `version` (optional): Specifies the version of the instrumentation scope if the scope has a version (e.g. a library version). Example value: 1.0.0. -- `schema_url` (optional): Specifies the Schema URL that should be recorded in the emitted telemetry -- `event_domain` (optional): Specifies the domain for the events created, which should be added in the attribute `event.domain` in the instrumentation scope. -- `include_trace_context` (optional): Specifies whether the Trace Context should automatically be passed on to the events and logs created by the Logger. This SHOULD be false by default. -- `attributes` (optional): Specifies the instrumentation scope attributes to associate with emitted telemetry. - -Implementations MUST return different `Logger` instances when called repeatedly with different values of parameters. Note that always returning a new `Logger` instance is a valid implementation. The only exception to this rule is the no-op `Logger`: implementations MAY return the same instance regardless of parameter values. - -Implementations MUST NOT require users to repeatedly obtain an Logger again with the same name+version+schema_url+event_domain+include_trace_context+attributes to pick up configuration changes. This can be achieved either by allowing to work with an outdated configuration or by ensuring that new configuration applies also to previously returned Loggers. - -Note: This could, for example, be implemented by storing any mutable configuration in the LoggerProvider and having Logger implementation objects have a reference to the LoggerProvider from which they were obtained. If configuration must be stored per-Logger (such as disabling a certain Logger), the Logger could, for example, do a look-up with its name+version+schema_url+event_domain+include_trace_context+attributes in a map in the LoggerProvider, or the LoggerProvider could maintain a registry of all returned Loggers and actively update their configuration if it changes. - -The effect of associating a Schema URL with a Logger MUST be that the telemetry emitted using the Logger will be associated with the Schema URL, provided that the emitted data format is capable of representing such association. - -### Logger - -The Logger is responsible for creating Events and Logs. - -Note that Loggers should not be responsible for configuration. This should be the responsibility of the LoggerProvider instead. - -#### Logger operations - -The Logger MUST provide functions to: - -- Create an `Event` and emit it to the processing pipeline. - - The API MUST accept an event name as a parameter. The event name provided should be inserted as an attribute with key `event.name`. Care MUST be taken to not override or delete this attribute while the `Event` is created. This function MAY be named `logEvent`. -- Create a `Log Record` and emit it to the processing pipeline. - - This function MAY be named `logRecord`. - - The intended users of this API is Log Appenders. - -### Usage - -```java -OpenTelemetry openTelemetry = OpenTelemetry.noop(); -Logger logger = openTelemetry.getLogger("my-scope"); - -// Using the convenience method to log an event directly -logger.logEvent("network-changed", - Attributes.builder().put("type", "wifi").build()); - -// Using the event builder to log an event -logger.eventBuilder("page-navigated").build().setAttribute("url", "http://foo.com/bar#new").emit(); - -// Using the logRecord builder to log a record -Logger logger = openTelemetry.getLogger("another-scope"); -logger.logRecordBuilder().build().setBody("I am a log message").emit(); - -``` - -### Usage in Client-side telemetry - -Some Events in a browser application occur when there is no span in progress, for example, errors, user interaction events and web-vitals. They can be recorded as standalone Events as follows. - -```java -public void addBrowserEvent(String name, Attributes attributes) { - Logger logger = openTelemetry.getLogger("my-scope", "1.0", "browser"); - logger.logEvent(name, attributes); -} - -public void addMobileEvent(String name, Attributes attributes) { - Logger logger = openTelemetry.getLogger("my-scope", "1.0", "mobile"); - logger.logEvent(name, attributes); -} -``` - -## Semantic Convention for event attributes - -We introduce the concept of an event domain as a mechanism to avoid conflicts with event names. - -**type:** `event` - -**Description:** Event attributes. - -| Attribute | Type | Description | Examples | Required | -|---|---|---|---|---| -| `event.name` | string | Name or type of the event. | `network-change`; `button-click`; `exception` | Yes | -| `event.domain` | string | Domain or scope for the event. | `profiling`; `browser`, `db`, `k8s` | No | - -An `event.name` is supposed to be unique only in the context of an `event.domain`, so this allows for two events in different domains to have same `event.name`, yet be unrelated events. No claim is made about the uniqueness of `event.name`s in the absence of `event.domain`. - -Note that Scope attributes are equivalent to the attributes at Span and LogRecord level, so recording the attribute `event.domain` on the Scope is equivalent to recording it on Spans and LogRecords within the Scope. - -## Causality on Events - -It is sometimes desired to indicate one event led to another. Since spans in a trace are better suited to represent causality, we can create wrapper spans to represent causality between events. Note that the events themselves are represented using LogRecords and not as Span Events. - -```java - -Logger logger = openTelemetry.getLogger("my-scope", "1.0", "mobile", /* include_trace_context */ true); - -Span span1 = tracer.spanBuilder(event1).startSpan(); - logger.logEvent(event1, attributes) - Span span2 = tracer.spanBuilder(event2).startSpan(); - logger.logEvent(event2, attributes) - span2.end() -span1.end() -``` - -## Comparing with Span Events - -- Span Events are events recorded within spans using Trace API. It is not possible to create standalone Events using Trace API. The Events API must be used instead. -- Span Events were added in the Trace spec when Logs spec was in early stages. Ideally, Events should only be recorded using LogRecords and correlated with Spans by adding Span Context in the LogRecords. However, since Trace API spec is stable Span Events MUST continue to be supported. -- We may add a configuration option to the `TracerProvider` to create LogRecords for the Span Events and associate them with the Span using Span Context in the LogRecords. Note that in this case, if a noop TracerProvider is used it will not produce LogRecords for the Span Events. - From 90fd8195ee4ab59e2246880f4627941e63916454 Mon Sep 17 00:00:00 2001 From: Santosh Cheler Date: Wed, 13 Jul 2022 17:06:58 +0530 Subject: [PATCH 05/29] Adding experimental status --- specification/logs/api.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/specification/logs/api.md b/specification/logs/api.md index d00512a36ce..df800ae05d8 100644 --- a/specification/logs/api.md +++ b/specification/logs/api.md @@ -1,5 +1,7 @@ ## Events and Logs API Interface +**Status**: [Experimental](../document-status.md) + The Events and Logs API consist of these main classes: * LoggerProvider is the entry point of the API. It provides access to Loggers. From 89942b1c17d7ee644df7110cdb85a5cc24ab0bc6 Mon Sep 17 00:00:00 2001 From: Santosh Cheler Date: Tue, 19 Jul 2022 02:33:03 -0700 Subject: [PATCH 06/29] Adding event semantinc convention yaml --- semantic_conventions/logs/events.yaml | 17 +++++++++++++++++ .../logs/semantic_conventions/README.md | 5 +++++ 2 files changed, 22 insertions(+) create mode 100644 semantic_conventions/logs/events.yaml diff --git a/semantic_conventions/logs/events.yaml b/semantic_conventions/logs/events.yaml new file mode 100644 index 00000000000..edac7ce6d4b --- /dev/null +++ b/semantic_conventions/logs/events.yaml @@ -0,0 +1,17 @@ +groups: + - id: event + prefix: event + brief: > + This document defines attributes for Events represented using Log Records. + attributes: + - id: name + type: string + requirement_level: required + brief: > + The name identifies the event. + examples: ['click', 'exception'] + - id: domain + type: string + brief: > + The domain identifies the context in which an event happened. An event name is unique only within a domain. + examples: ['browser', 'mobile', 'kubernetes'] diff --git a/specification/logs/semantic_conventions/README.md b/specification/logs/semantic_conventions/README.md index a4c866cc19b..67bba65cc43 100644 --- a/specification/logs/semantic_conventions/README.md +++ b/specification/logs/semantic_conventions/README.md @@ -6,6 +6,11 @@ The following semantic conventions for logs are defined: * [Log Media](media.md): Semantic attributes that may be used in describing the source of a log. +The following semantic conventions for events are defined: + +* [Events](events.md): Semantic attributes that must be used to represent Events using log data model. + + Apart from semantic conventions for logs, [traces](../../trace/semantic_conventions/README.md), and [metrics](../../metrics/semantic_conventions/README.md), OpenTelemetry also defines the concept of overarching [Resources](../../resource/sdk.md) with their own [Resource Semantic Conventions](../../resource/semantic_conventions/README.md). From 6cc131dd48135634a53dbc09d25da44663523e03 Mon Sep 17 00:00:00 2001 From: Santosh Cheler Date: Tue, 19 Jul 2022 02:43:07 -0700 Subject: [PATCH 07/29] Updating events-and-logs-api.png --- .../logs/img/events-and-logs-api.png | Bin 30927 -> 6383 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/specification/logs/img/events-and-logs-api.png b/specification/logs/img/events-and-logs-api.png index 55582dadf4ca5779be7a35a972c17d8b3248e48b..486ef640e4f5c1d795264865bcb5aaad8d17b591 100644 GIT binary patch literal 6383 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 AC;$Ke literal 30927 zcmd42b97}v*FG5Awr$(C&5mu`=olT_olerR*)ck{ZQIH3rr+;-XXgJ|v*zA)*Qt9> z)vl^jyK3+K)KlM;6eQtcaA1IdfZ(O2#8iNQfGq*P1Skl=oe;8@0>A~#LRelH2>5 z_RR*~&ykQUnNyD>hbL-x5z9O`zSyf|P7R z)s`*H^`{^_IefAPTR}rx!1_9eeX2Ca3dxb_!^K4U$OIQ_`+I?+xRNjPNfugvcXJ>S z)ji^>Km%h64Ef3&5tTs0Q;5=0bm?gZFKdQXTkVF~h3{?7WvC3 zjLhHkm@GRk5%H1yvjNFZ(MgPvQ+~$HvaD32$pPH7gNW5F%l1BeS{``BF@;auxDdS6*>dV-&IfVJOEf z-41=^BYt^GU&#a6f86_<*>!Gic)@zUx9MhH4>`Zuspj4s?w_z{j`?_ry}fjJ zNj>;E=W(AO`ySnfrqV;cm8AU$LGKTV3@DHgemLCus9lpm0>!q**_RGrNGd|mW!%-b zD?OT&g~Q~WBb3EBeF;*@{}ii_b`Gr8hNw`EiB(*oZ#_AERvwtZ^v&}POwR;W(4USIM34fT2xU2B(tt(!A<>Bin8YiJPyQhp zuMXAp@?}ZJR@{J(bK$)shE=6BOMIQXp*{cGCo7Gdp6X&H9YRw$=@|7ZxPIr`pkb}v zF&(FJ(++k{o94u`;q&Pm%LDD3b@5ifp5}G4^N`Np_By$~Gg~be4|N5PHz z1NgU2*L#|X68@ZRQL6e$!auoR!D|}ck&QdjE#ZCto{Bq+i{w|B99T8QRK{ERluBS`z z`s|fqC$0e~6)!Moh}0fyaujj{oa;7prEc{Pexj5w?AF}l*+cgWi>Lql-0@n!OXVSb zU?V4QPWR@e>wX+3Je7TdI8)DJOTo8 zV*&y?`33~UlMV!g>6qQ7%m;YjX{IG@E-w#614u&wfdiuefdW#%fG-d*4iI3;`APxF z0OS5QtpZH-KY2iafFi7b!2TzX4&eIr$p`$t%KYaFk`MB~Ie;zmLI0ah0OSC2DQ%Sm zT%aALv|WIJu(G~>z|w9ZKL8T6t<La_|7sU$+@ai2h}9wc#hxl2;-Ub#OK#VrO7uU?LHKAtEB;b2c^S zQ4y2)pW=Xj{3MpHu8us6j2<2y3?8fu4$c;g%-r1Ej7%(yEG+bZ9P}<;_O3>r^!6^K z{}J-Pa>UGBOq{J8U9BAKiN53-89TVS@{^E!RrKG_f7z5l6)kMXPW|661J)6;)<0bLb<;bZ*o zYZHKx>!s8N0ulm}786$U1U}P;{DwYoO8`|sen-FqLenXoh%keUgj5p<6`3E&X2pRf zj8^&c=aJ$k3=~Y18oF`~5Xg+rWoKzZ?qi;V0S6xOck0XiM(yGD_D=fx%?m$H&egi5 zr9>WaA!H>mG~i}YqKZ}NVi0POs6di@C@2t_sTCwNV8ByHRj?oV>kYt6{fVH?~pLE=5~$V$QPvr)>m|B5RGFL2~TeU-=}$p?4trv8nQHEqDuZ1M`>vKYK{`v8X7RU zC1({Dy6nG}lUv$>{%b)CHOTUs8Us2lI#hZmhU-w6THt;Ukv12-txIBu`ez&UX*hG$WnekSja%#3G{Qbg z?>NB-u&`yeA0H&#!`wC+`1Hq_)(sw$2V+_BA|j%Cq`?O#^H4|0=gRXol%bXWI(8Ro zcAnDKkOjQ+k&nZLifxn&B@d@<+ErG9?OE!Pi;+cO=j`g`;L3mzbPxp$=c={ZSP@{@ z3_<{7xTscwAqE($4tT)8IaDaq#{AFix85j~aPO;G?{$^dKNHAO{5&8oy2u}ZhPmxQ1m_~V!09jmM=MiJM(FQZJghQ&B&48<3ohU=OTM8Sa9c0=lh1_-Q?i7a~x)< zG$O&m6N*p(8Zf8u*PNv3)i!35{0>TezSbITtYssACZs`JP~duSraf)zWH(GtcLt%~ z?yg@bCN56?B+0aG*ygMKW@2ni#lgW51UH%2EtK{w{!MCXEj}_P;R^G~zp3r;Y{0`{cj@N=-_+OCVeQ&Tc`HsDaO*(+W1z2T1UJw{qZ$Y*{y%BQ2wJB`wZ}&W| zJHOC*TxqgjCH^1`coAGR0gYH8AtAAg&1`I}(s^%xQuOj`t8#n&%|SM_XPI?Ba=7z3 z9vsGTLu&`y?$r12jA^(m5r@tAQ5n0!<8f-YTJMo(*Ec9XrEjV@v<|D}KLq-Jd(!1o`7b$A~&N3)62_g0)Q$zg?@4kU&@`o^qL(!2&-P)*mKNWB)=PnmHT(L?Q9nK>Av`#Z=#{#kv!@&;xT;K zUD}ABuWpJO6&SgmJwZ>89*%#e?ilYLojuFCzAZV?DAf?%6W*zb5VSh)7jkZ7$-h3} z=WB6vf*p*AZU)>VuPYbu*-W?p^m#O&%lGG(4j6mTXS>NDb~Y&VWImZ|BFE?V{=wsB zt+<<)Cl&&6SLSxgp)}-PMa`MTytE=bU8zjS<(b}i{(w^L+gf+0)NNo)!|ieaw?BNL zD9E5qVTg*!pjUYG6RYjd!4CxbQ3LGfXZCxJjeC(mx6Jtj3Wm zSk4I%p?^H8ExSIPs)*JR7}s4(D;?=uDxLN+nh_xeWN>UuR56|HW$bn$HqkUsqs^^U z6w=GdEn>OK0I%gaVSviENEn&?ThAM_(Oxo}`(G((RuB7h0~CAJ-+J5w_HfH}-?QDl zkVtqaG6DM4-w^a#DL?y=(~c^KQi>;q$byTBj!kYBO1Pt5ZIDx_b%8Tqp{z7QL~%?t znn()yY*8wjm74?cW`Azy4WdjJ^X1g+R*si38u{1_S z9|VFT<2N^@YJ0n5s*c{AoMjhNN{(46tYW(^Cdc0j$d2d$7vVqFz-EE&2crW4&H%m< z6L=sK?B1keoLkOFZSKg=4t<&Q>vsP zliRe|#ZlJH3mnedT>acHan)bCy9~r{8=c-rgSZ~&*GL`>=q2qfMaV0T0A={WXt)uI za%d`#9^g1-$-Dxh!;QywAOa2>*%W;`^ujMPyWyKfaKW2kh?ID@@B_0L6!lT3$x@++ zLaqRMGPb9rSUraKqp-!+Zl$3#&tF^qQE)0Elha17PcjZ2B>Z?UR&#K+=g*{)l9CgR zRz6THE-Q(EePXDuS51C#xgcO@k%xOTd&e&&HDwCDJ}E)4>>&!*-!3)U2=M+Ep=44b ztp!LN01=rX6{>N4_P`~uS||{cTh6x-Vqv8xpm|6n39j1M%>PvAetW^CH++Wed|Y5# z>9in3b*7r{E+cRnB8ac{&**x7aT(3!Z|@ItN057PS!2>B66EqF58T^^jMxtGYLSzI#p&+u)~6KKMqd1}nCoz7 zcPvXX@@Co~kR+|qi5>(7rWT?Q*!!x8lAJ|dODrpzPDDFx{cLtM81wj3Vf^Io^wP!( z0-93`Z$U2Hg&QO@^cvjt?#p!vt2m85Xjf z2ws%!zm0lV@rlcNhmir&>5fDeT*ctd94x@FA&_rp&l@ry6!QEuAiqU~*ex}Q^WuE* z3u=Q{3%Ik2)Zs*}uUHTNRJIZb`2H9|PfKJT3-9P_Ewcao2w_RZ+Ks82=x=;6yW?wR zOQwlnuio1smXmp`v?BAkh_Etatv2 zDJBFa2XyhUH+@NMDs0(iAz0|`!l*7l3qz(w#T5-Wf*8;QCMs6ef~OoqR#w^ZQx34d zyet$H;l{=$_U+XKQ9=^PQ}op=QQs&AIdO}P+sj*)v_`l!;wrnn3RUc|Ci;FTMn+fR zm}LB@H@`2l(X3Ya{**KBMq4B2OXN#LJD<;AlSHfeTk6w(S)#zmXz%iJk_JKiIO->6*VmWaOjYg&7B9X9pTCTm)9=;K6zCm_%Oqa2Y+ zrz`DdJ)i#u4x`j$`^LP-tZubQ&*$SFK&_#s=E_&=C8cWmW@2J|?0x07Qs>6&cCi%q zOTCJOH=kBGEA^M8T3ZG3Idjy$asT$l5w{VdFaUuPlX5`&S0gSuT&lf zmHmeK-2Z*odFJOfKY=a;l)XVZfj$)a2K|@%j9EWB6#Ok?8wL)@-80q>d9X;9Gc`30 zUYh1Z>75K=vuxjTU+pfB4(&bqPO?SxrL70z1M;+k?E`hyjMh0ndry13JQ5pSql9<> zft3QJB@THJ)KXdL(BPmpN*lMn{$f*2PhpurEMPh)Y6cu&2ryqC{LLU02CCqQz3n$b z1vvrqOBCwJxkx~5`8VA!Vm+5oI%Q?$x_+vKx`2edJ9THgCQO+E-oYbqk(A5*|X((ahily9`T+uz>9v^ zUzzN$3wT(zn5)v|?5#B!igP_%V&?ICVS~r#`2m4|CncLoS0EaJFnz~aHv3b#$nySV zUgTh^@~hIQz)UXR#sk)ZwZUwsoqlK<-6lG_<+`xn`t1@`I*o+Qww2dAFN0d(y2NzhTtSZqH^Y^D# zElCc)PwK~G_vdsrx64sa5GcU13Ro}I6u2UASj~jOpwoyAM4_WrdCmV)M?*m&akpv| zEsLq$xVHyrQD?iqz7CJ*6gVtKafxi2jKw#A4=ENBZr5tq?XOm)!=B0KRcAQ~3=BN? zTc4NsbUcf*UCn)557`kCY!2cap>b=U<909D>|iiBtmXMi;}2R*25K)` z+sc@OD`%_*&nTfxWF>f>@dT^T1|lF-@bFo;;~DX@Nv_X_Rfn)_;lESG%ySdzEPt8l zy)3oFdvpQ0S9EO_#>c=(I4F=#TeG68cBnxzq5uXV1E%@X90Dc0DMrw8g6L2_>$Bt@ zm*d3KV$%*o=jKyL2>L}3Xl6A|7$`KReC>(V9^ei)_&gG{s?CNAi^oUx$b-4!-O1D4 z(aj>&Fw$G|K%Xz4I2UC=ber!ne_;f2>R!qD59}P@E?SOV*JHD^jxtET0hVj8x39v5egV@2SDbtg$LHRj?Vr+V84^JbQ&L z@ooJj;OOQ4w83kPLz-4`ql4xCbwdK4CA*0N09l}daJJ8NmaFMtG>i2tWyj+SD&X@r z6oo}=4iipnLt6BxKuO&vytBU%^u>FU zzkrb9l^YOkqh28BX6xw~1^iYLK$g5r&W`-xMkoYvAzo;Fm@>M<>V)CG&1JTTgSXCQg4YNQ%8Y;@+XMn8-#OW9=l~ozVB8A|VNu z#?>cbn7hr$+12_P7^tUK;Ok{j&r>#>wt*S(hwxiow`0&mUbmFTrg}!rWg(9^5j)fo zQ~O;0UXT$S_u1b3PAcPP#>qmtxVD#(uQ?u76@y2DVr107_qgv0Q#blFSR3#$@^Y?h z@9h990tm7JRwRibiQ_3EG<4?e5<}Vj(^f4h0-3{ZE!}x<_+rM``XDz1pt-rKnpR0@ zI)5<$#DB4GSxQBB?3q7P4NT-#!ViF{P8_brLmi2sSKGq42alYT&1WT^fR~pxhg<>TXf;3> zIU>+$Wh&+#dx{TrgnEX5pYBRMMf{Ti6sj0s5Y!8RQkjjF7O}GcbxD{3n$U<%1)?AX zq{I3b{{$^424Hw|knh-jlO)iA$W7QYWixAE--Z9P$H?==A~YZw5kPDKnpU3=9XYBR znkm$zCCb4QP~JG2$iqY+PIBQ3>Tix0G97%FYP=PV^ELPv1NO{n=9qq{_m7-Hj$rAP{8%^zJq(CdjE28ZOQ`f)Tx8sRKHWOxp4e|Ps+ev`L4jKIrgxwWu|J|l zG>;~5;qL)AA4L$Bs}C6fjF?laf|Yja=jh_F-;Y@kYSPci?x#$VK9O^)+iGc00ttH; z*4nqL=5WsK?5|dF^k#OEBtQWt0JH6jM#L+9QsyR>Xi~=E%7eZL%E)TI$*CITF)$-h zL^Xr=rJvw(+LI-anTPcPKph1DqKF<~8JU=vxZ~hoSXf9d5D6ZwoO4h$NWv9EOjryb zaW4X}iMdRP$A5AWl~y^b_6Y`qAt57b;4H*p#q|;hXTsZkpJjq=!$Y?T@$h0qMGPW6 z_D9iqJT82LyNShpxQmVt4gHHa4X|Y!trw8Iw1-k^h9@n%C=5yKsiV2WLqo3?r5b*a z^YLYGd~Tuk#^{{ke6G+kDt-7qquvaek_;n8JUvBy-yf(8+#iTeE6%3S4-GoQWYq61 z=OXQHbsto=K;Z#ZmsdrW0tYelXHSFRe?W2z$d3+XP-#K(<2mJD0ia8IyUD(L>EG1~ zM6`LF_rPND1VVWl9As}X>5A!B-LI^DS}idnj;GK4Pd2Jx`I+yqy-&x>>-?}H&#ozR z3)2j-C`~zi=RB?F@(IqDS|dt3UPzL^xp_anYr8(IacehN4^6DkRXY%Rw>*a24Wt>W zCW?TUTTEWCIed8B-LHYG)l0DRc-^3ld%D1&)2pP1^RZ{sXtaeW)Kl->Ww@|ywAB3)dwi5syW|nCrDkU(g!{GbQRrP<+g~Q7}^7AqL#hG#dJyv7VYdo&ALA z*SHp+;5N5Tvp=Zc^*oJB%D#DaS;t4|o>R&=<3JQfL7HK<(6Sap z8LvO=&s!ESE!YGUyOoZChf@cez3fI1M%t3wsAS|f72LE&eceR@#MOthz7 z>4h#A#8pj~uEbYd&Uc#%jrLl48lDx7*IP#0oVJI$S`8~+pNH%!_xA%13fxuNYWe!{ zjAo%;z-x}KTI_qbGcw||J?C+2-o`;VcD=lh%ogOl0AE$@lNf#ez3yXskJI?$ws|wh z>h+;LjAP-K9s3D;eGZ?S%-iSV{$dj*Whcd<@P5TAU@rxg+wf|gWHq5oa`?Fhd2;#V z^3=<@%W>LxHC|S8$^Bx*&Ss@8`P|zv@~NBSUVim2qF}0vO$KGx(=WTzCVY+`o$>$x zlp+B7_A=G3DHrkHA|MN%1u=FKmSxewH!t+LyZT^dP{EU#_zib#CBWwJ9+FrDLejuQf z_&z(U)rlb+SiFL){`F9rym(+lrgIMKhB6puj$0()G>_u*0_j()b6GSvnX9cTR?Zjl zKbb9J&EfJ74wgwR_K!y_kU_sp@QKBlBlibZi9Q&&bc}cJXC!8D!HrwZy*U_3R?R?G?M7eHttlMkK1$cJrP4XCOEMj4kpYWfyh3yw@$%3DDXnhY#PI5ZT za!bo~*B0#cJcdyr<7^gjcxc$j((FrcLFDF$tce#J_3;EJ^QsF?5aoYt6F40Rh%4go zS5&^`3Q=GcnZlBSSBIy5`|Ql74X|&AiqH$+7871 z*gCr|%J^%-t$?A;1Xq`lW@tPMb~BnZ@86A-PnULCy7n}fLCp) zuk9iIu+Gl?)+rc0pT~t>gUcbqjY(4Mo`MJ|?2Jemv5NQ#(aUHG?ex6O9~4O3*YMiT z2S5-bGGWV;xNd=jh>+v%3EZRcJ|2A8e>pqZm5=Bp4+v{)X0MYi(tq5l@+%zn4!~9l z8zPG|A0Ubh5e~CCbon;0`;(0T5MQYXDwF|p7z%_@*jPc2i?z8*E7D9}2jDSW1pHLjK6|mNLFf;)&s?6n`L*XH3flw2iPzkVj$4J=d0k!|;Wh5% zkC;TFn(vww-kh;G*D;pYr7p@aC;f!;`8iO(DXO5z!hqP6628e_WWN|~*uGrtPNwS# z?kaxD&eeIL;yj-*edjP*v-CbrDQ|d~>@J=?x4Xy>=~G~167C5qhC!zzGKbdVv~yXQ637CyU}$pPlzDmsAxU%gm5E zA8xpC?)K`{qQ=>tZw^YBN%In~h9_J2vh!L2Gmc9>;MGs(dX|Qn+p#$ciPZqa_yXYm z;Px{XNG<%HmX4~1XsSkS*xFVUq&CD*gvXYuR>%=%RKSu~zx@3-6o0}z>cRG6S@s=* zkD63qFcwS1V_iE#GD9x~L5Nh5Xg82=)VXYXDDNYFq0&!d__}m zQ$Zf$jva%blH$fKwZSujlS1CGJ0&po;?Ba%NVL`XiSk04FVtxKP0Xc++$mUdtYgO| zWL`tsXW|-`r~Ld0ac&yO?)4Q0z_kW331vGHL32HA;~7;xI@&>rg4`(X@FUbJ2RcE; zyCxVIEa+{^wMqDd6ZZc34QC-wXyjz~CZ~srv7Oi?J+`JOH*pnFg%{vRk*(MNskJ}o zmrlxM0&O$HDJfPvYC9tvgWj9r3U9UAH$&gzY@L)#O}UfdlI-rxh!N_Rs*2lCpD^!= z9;8MD7nTLCu`ra1B0eWQ5(-cX#ES~DzIwXI6)BD4J?UsXi%k{aY#q9?)R z1toHO+m5A}0e_lRr2lwWp@<6^0K8HLpPozK;?X?Q4JA|+>pACTjrdVe5E7J^owEv3 zd$9~n{%$Q49sNB}DxeuMMs7g3bI-X^Se|T%(q41SBqk%B(}%c%|50N;EBtWH=qlX8r5x?p7{4zKyR3Z@2q74SFP@_aL}JvM1JQ zd-CES6PGT#aW*boj9?rDXAB$G+h0$DAv^{z5_mZ^W~&TG2nVp`IOEzud&sJ8z|e1p4@ zbl{aBOy5@Zys9>6r|8SSx#EX&5@F5q_zFen<$N+HHhCIf**uL8W6EcQzY z_|sdIw8ftgili5ltS6qt1eu@fj~#Vd@Dvoh2I-o8D62`QEx#bxt*_OXY{4wWn`$MBd)$#=}bxeS9Bb3 zW?7Hp&Hd4c)9nuOMWB!fD$N_9mal`G>153_HnSTg)t`^V=c^up1pY_DI59$U^rwYE%2h8Tn(x7>{QN;>f4&8$9I)KMvK4s@9-uALBH=@&VF9^ipB6V^{}0rjRmAK{-Cq{=)oK# zt@PsDOWRrZ(Ad*?Jb*qRalh-zhEMP00XS6$e$oNvN_ z$7hL5gBX|e^MY7k5nQZ=*a!hY!XhOy5Yqmh(CIh2Fa>1@0MK#;n8+IC8eidB=xn_? zp1^m@Ut1E>fS=%qOqVLm1yW;@;oQ^@>M0&qK*~JLX!|AnO&b9o5%J|chj*BgpY1F? z-BOzn+lUDk-UiW76cP(n*~0)5I~h_>9x2`I@s_b0g;7>|z^ijtnKZXlj}M)f`h58* zjP;peci`Db!gB5^R}2iEw*1hc1-3zZb3FQN+DhPJQZjofpT6@yLW1sry- zNSZNLF&!a}sZ_Q4+^@=VEY*&$q?M}LBRi|6X(+G5U0g~E>wLZ0P>%fmWUdgfxjv$U zo_=9RVViHy;J~Fbc%5d3QtS&d4-pNx^5YH1Pd2G)+TY5>+6j8XQ4$Me1@ zJH|S@Ht_1Vg*J6qVxl5H-ol-k5JDzk>@0=e?nS$NN(g~ehMnFW0j(XBQ}Nx?9lFb~ zM@B~9uz}~xa!tvb9+d(uAwrWWS>|v>LEi9Od=9auy56>d?HIy|AEKcqCR&%%S z(bMc&OrH~@=%{;r&Ly8$Jabs^Gl8$*Okzlk8zyVWy4P_xD2T6w5Reh0KM|1b6*dH5 z8D)o4HZT)OPsXxl0qA@0iag?Zp*=x zUGkgVTP)#BANNNL+yOyvmJf<@0A3sbT1SYOyN5Ox1C^_|I{=p8J8f+poaUS2iU4&o zf<%ZJZ_K2qX~uK^-u3!>lqGyIGxvTiH|o}(H8{_!;I01JaO0dbbfv+)0~&%{5hlL) zZ6-J=alJT?%YMgO&UbTq@dadS90?EpSLvZHlop}RDYuf8FT7v^RD<9yT=|w(Oryfv zAM5~BhVq8L{Es{u!0G+$|n zf2(<;CgY^Qc*^pWuve8RHd&L&y;6(gC9ds6>&3Mg4LL2IVczc8{t0#t-*{wXRwEFq zF@27hJ3r(x8T$YwCuFRl0zxy0ct}w>Pq@uoG0Tg)G=Mm~1i_gC*hSg%X`2C+~|yK9R_nO>EG<#<^(9>YU|C z(eb@IEJDY4@(*BrN;L!f`w>FXK}L`#u!9qj9M^hDF9{&`mP^w|ED{AyGx&I-z?i?{ zb9<|WQya8+CN5MytF|O(hnG7RW{4sNXhV!ac-H`@O z99G^KjSA&XHRw%cUdrmb6QnszBn8L%UTKu#p2nS+U7P_7wiOGWg$i2H&%jxG0u`;y z+s|kVQ4P}!CWy_fwQxkLMTrn5Q)?N9}j;N<9F77Zj${y;dObyyC-~NV+?lH zF7-mh;*)z*>X)uo*q5ddoOU9pepA{Mo_TI_nl-ncE`W4E!Ihv5Fc9yPx?yk5BcQ$_b~9J{({_#Qn2*De>b>iM(W}+ftERf6he$Sp;N5cc zbk++*9u1z5J<)&XrdL~@WM{iT@RzWUkj1Q9}B_h60B2VO;;a#>xEvrsaomOWi))m6PNNB2s2^e)8gsMN6en8>B<GX494X%xDDvj@Ddf)*ijT2>b=p zjTx$n-xg2#HF^Lv6qmP`5syx07c=u`v$`Un47TIrE;_mNDw8Hrj|W%XXclteQDOsN z(vq&QXaUSrb&t6gP#0H|fG>T*4qB;?ts$oDB)fJl6HOIXh-_t@C z5&z5-rmMuWbJl40Hhv+8nKt0L<_3`#J{t|LWAxA3gQ&3*@%VC*o;*An*r8Qes@K&w z3@naQJCoOUu1MzF!OvEMS*oTGR14OBG(n{>Ps51t@P=P+Qcmj(pybfa?*-^mqS7?% z7h(V`0CJ;i)ZT07+Bd3tSCqk3!>gM4kW$KAUh3;9vh7e-%I0< zFdL;}jx-kZbceQT=Ic3%PMvEQT{>IL;(FjnAv2?`>(i0b%g$J}*)QKoNr+Ll*NqO7 zQL@~W@8bvncTQBy6s#IsU%tT{i3N}6VC!+^)M2I#{&R{l?>)W=kB|B>LC{?#2%^Ju z8K%}LpxLt4m1T$g>gESF+j9!06;buC#egZM@3WWN26u0=)lNfu9Nya{npV%FhCe^} z-A3}xM=mGdB0V;^MNkdW#VWYu|AO34rltsFybCrlJCt%-boAA!rGzyBVhGNTkiTZR z+Ay~;3vlHDll%=vvl^MK4qb5IzJ4#Sb3x-+So+RKSJz;#T)m{ZoZQ{gXC382Iv73? z2yB$D4BIYsBG1k@HMr;U%re-(2b9x%vmu5$JHb$~qU&0xWkA)(dX3iT*waeIjz-q& zg|!K&Jn+0t-SHkN< zJw0oM0~`l-%{RC9v;l98aTn#f5d zY3fN5z(6#5fw@D9;iPv7Y^z%aTb%|87u{7v`FLANJD{UIr3V^cNa=pZ%KF+}XphVe zTlQx1ImSw}Ea~H|aGRE^SA^R>nwiQ|JA`stk#-ah`5&y|VERjNKyPgWwo3>Mf@r!t zND|Ubg;WN$FUdXZd$SaT`y0dMeeF6UTu$9~YFaoZ_Cjo2>|<@@$I=yQR>vBst4BR8 zZ1}Qu`*v5jk~w~(mO1oly~pO25jrfim8FU8e{neDg@KZlzgQD8Q=hSk;r}^dM*ej$ z2F!h2?H_gWQvyIF>Smrn`p2Sc0RupPX+6I)yahq{Kz0s*U@sYer%q9Su`R(h=QY3vn(`n%}cGC!z@wM*Plz=q49;;FTzp-j%-Lr zI2nm&HK#2})H-hs0&}XFYe`=(XAp2uN7uD8MxVqNNAq>kf~2+WJw)IR}mX- zHYAPx;u#jx(`quhBiq7kdTKT~ckr73iwxH>QAM_GFaBLJOeR{B>Gz=UEYypG-E7FuQ-h`0) z?0-nSz+Y+wBqlHNkF{y>MNEZLW0(KO1;+cLLV*g+k$s(NM0SJ#sPO;q3bGQ**LOKm zn3iZ4g8)~>s|6Md&%^-OaGAs|&Y`C6MKW?gZCy3Vr^Eu!{ViE~sINr=D6bhc-fCbo z(SU5;i7q01UOn||nM`k27EnD2J^N#64)90cH9fHh9H95(c66OMZ?NB#374=T7k0TV0rQme7cbu(fSp2uOz?5^wElaW5Wsr`3%u=%K%5N(20a37(U^>-0A6V{Pla&8^EY1S(@yl=y2mE8GMmGO-VTl(1MA+nCBag}RJ;e~W|v>tmTr-EBiPND zBFV>D{Un%82OFhAwv>D(Tfxt_u`A)#W6dez z2l)Aza-As|{%}y;&s#Y#SItY)6L>^%b52{N9#KSoF@B$iVt|R5{iR+(#l)0=!)`4G zi^+f%faLNWh5V<@;&0cxBjwR#N<|iOM~BO;EhHTF2QQ2n35Ra(l$!&$YUgZTk5ngw zLVDe%;WU{FjVjB}k9QTs(}k)c0)Fpd&A$LXttEhL>Uw{oPVD3%wvKMMjPGdi;xeakIi_aO`t!_PlA>D#B!qNx= zsKq43XA~>^ivTbuMq*xo7fWM%HTtu~qyop1TTbEi@@af5jWKInY^*d2=$v019`{ji z*zKFKtrWZU98w2>j!x%((CPE2qNIdmLLjbMrjXJUgg**UfbaI-@zX79CdW z+IAHCnN6GHy>91{jR4*`;OI&eN8U1wq;>He6ZO}LUnoM+iB|_FtgOR0ltp%dn8NVvsSpa93ij6LY!(l`2JXuU~ES zNlU=_OG+*1`;Z0{Ny#gfAU%x!2KO_JNIP89AX_L51|99r(8~%0z%a^sdj>ZS@FM$# zCaE{5N$A)Mi@;&VYrfz;APZ|wUwC5c9u)g|J1L0Sfq=&)^nA0Q?7h_HR*}y7Eva`5 z&GWZ*ed@{jY~U%2#Ec})Z&#}S)7)D|wH0>jqJ>i2-HJO!3IU2+aVuJ+K%uz1TXC0S z#ex=hcPK8!-JRg>dRD%@#~$aL`}f{4?$4Q#m1HGv-ZkfAOUDRzqC|Byuby{-5!V(&T?Z+1|uph zW{Tm^h+STMo*$5!l)wThsa%$lPziFox90;S)0Y9X&3C=G%9Xpo2lA=OkJ{h)nm;Kw z786g9W4?tx@)^gG7}g@7Uc{2`@CDG%HIKGk-MSu7U{LebrXOd$>uzs#geX#epZ}dL z(Y*}=OybzX27CxOk1dZ}Ab}Qm&l=7VU8CS{><0gSe+)n-VEvFE1!y70fn5V|XMdwI zQMrb>;ADI6${=TDMd}-5oC{C{zuF`5N74r5;H?!hfc=`-3Hy2*lB{sl()iB7#U+3n z!+9!S!T4^r-TM*oy)uRA<+wOH4mzB_BWVVU4))onWt5%H%$85zQ5?S{v+6=c=Z5$X z|ItRDiv^bE3)$Hmbgc{-oCR8w?{YYULx5cp+Zmp}&`E>VevC*@Oi>=0u<4`SdZ$ix zrO*{N>r46dQxc*_oBNs5oUWxR~667G6MkB$j9Kl%=Rf7&A?ccoNV1{M^ zlw1lxwV@?7|1|bCxjr5S7|{l7_o(?oDE*q*uVJuVT&WcCk!pAT*^CV$=kiSYL&eSG z4i1_zbTITkw!*jTgueZ3-ZhsH@kA*#157vn@!AIh*D4bA;P9OPIAx%|6=q_O|M*?} zNC10DhMKWih^tCrVJ1Cwmh~dFr4kZfkwrY2?eUEwGV%50XShZdOUIj@aBAAUykfM) zU_hRTOay&=JV`y^rYDv9y-D)tx}bAIiMZCyR6yiUf+?aiik;6?3s}i5#*?%;54G0` z`ws~_iG=0Y1=ZmMU}2_QCX#SQo2*MNNrCpKej0D~I;h+KlgaGw^BTA*Rf$e&Om=I6 zW1^N0;Gh@=Kjb1hbW0M=jt%l=j~yoKg?e#~s)&e)?59@T-8M85&47KtVT6TPx^?3f zwUoS7K@Ic3Tw0u712fTO5@@$Tm^n4BK)Z= zIrzjZKr=iZB=>cHbH~yFUHB7@BQ)zfwQ~JyfX|vcb-)}Y8TG{mpWDL&83r)mM(O35Ove#;T@{yk2{8CUFi0w?9WX_^jBLmjCF!@gWFk+PeAFfEbV2`Af*5;VrlgYVW1p z15NwaLqL9sNTS|Ng8T_t-CbRbX&oJEL<2-q1v5>sFrKa&?XC9=G@u?lST`qda8{jQ ziyYU3ji(D{z#`1Q14!2P@*iEdMp9@vgMkN=@{*&+7e^OTeXFr(W3~P(9=;Z^H-q<8 zb)g*KW&uy3WjInj=y|$)5aln>0IC0{P4&VC{_L5hE-bacPT&R$bgAGka!k2EaYq9b zLR!b#X228A;DB96Fgr<25?aVWyX5M{x^ZCUT1SFENNex^J~1DN=fpcE^Pg^V$@!_NE+ z6!ay!C}qID1co-$^wYnF3V}i>3@DT|TJW`j)>{AuCdA4;G1cFYgz|~kkfao_fXNKE z>ozL5pxJ+JE@G70WM{zHt{U>!m3N|#?~&fGE1>Y>wsw}OGY*s)S|e5(qONtZ;YSY;E#7( zrybzTX-r#-t~;`eXtt^;q(x8?(3mK@eTF(Y4!M89W2H#OPxC&FQ=B0f>RcaMG<)5L zXTjur&@UI@vQo>e?zhz>36TtKAze)cn`hE!8M@t5}W zZDS*G3d>b&8DEaT&N2&~;9s(Q9K^KC&DSJm_u-k_%i7szmE4N_M2jSq=lv6EUVz&m zitv(3x7kT+(|9;33ZF$!tUEY{ZaMy{G0q;2QawJ{{2Luhyq?Ov9Mw|*JDt!k5M;m+ zQr`A!Erk}fy;POSu|CLbfD;$rg<90a(&JPATi&a|pK5@aMz_@|ESgM^ zRW#PezwaNW)ml^9S@q9u!E|xDCnD65I=D%4z|Au~^UIjI&@|HrWOxNf%)QC$;WGWn z!)jf%*7{K~Zb^W7R&4zcd33r)W|+8dk?aihXvtT^M&H=M`(fcD$Y@^L!+jDr6?E^c z0S_cAwC#}YcLG!Qy9@#M)cVtT8QZqUpLe3%j<4(4)S!*tL0pnoE0Tp$2Wgt;L3UWh zxvVDhuvnmT0xV(eOK_3_I`v+(&!au?{)dxIZ@JnVvIBL_r^aecM%JL}LovUd;lylD z60STZSM@x41gPQLL8eiP>_q(5)i;#e`X%|4CkxPtkGn?TqsYvbsYZ|;O+<+lXFu(} z8l0=}IqrU#DbWehZm?iI_ccLtyARiA@Qgm1&bGF^u@#kyCe0nush@}$_5!r9wo@T?u3YTo$_YIzal6 zDkT;3zQF(8#Z)fFZ9WjAQN8;@qKko^k3ztv0zp46`e4Z?BiKpx`=t>TW*TYWu;(0S z*@byxPq~}%N%E8Npv70JF9pg^{$pT4Pyfhquk$~N)Kcgga5?*3K@kbUzCOr^11tuB z6@s@_cxAmF3yTaYpZ!ms#0060_*8zY7%-1I`E~RNJ-X2WQ9IQtRcU0t4m8izMldV( zQtsjFY}$Dk3nHBqx1>*~s6iomswcz9s^1-ji?z4r! zgw%iWj%EOInyFy4zA5*p#E=foBZeuk9N%?BM|*=d`YD&C^x>K(^<^~V>h4F33JKj` z^fvg5rN;zNzG94^oM5wSHlS<{N?_%{`kSo`uxT>HxRY>1WS^WO!$6^8;@yDuC%5QF z3-{HK9M1lj@GHKdMC&<@KK7J!L;3BLC%Knc+Uts#PQ!6l_LyQ;d(2f17{e+1r;@M~ zd%uXz@$))6pYsDq-83hI(^klv)0a|^%Lr4q%_F1zafj_v z1Y1Ww*$N*r?^>gMfX{Ti!hNw3i@OLU#fR$8>vM88(jLJvbu)c$H zh7y^e2@-`sips?%n{F}9jvrj~%QZu0$(?6BPX zp9ttasiU0d-N%b<$>8^bii^8xQ)_>sN{`?;7B(ed8a6VcuHbx$+RrX5OF#TG?xo^q zR$FL9BTKIEzZHH8B=fea+>SVN>_}0{?N`kEt0Xu)*6ZRnC?}$LML&aRV09zR;tN>4K-!m+fVH>96f7Vk-BpjK!A@aNyzXU3`w#CMw4HTCb@jvpgQx>(Uxc=RGDy#vbg`mLi)qS`V*0T9}{4>L-?Aoy}1? zqcTF~l#F|O26nvXw1Y%lyp!6t3PP@g*-fHH;>E&UhNHBfV?azA%BSpHQ8ZKr&^ z`pa+oCB84pY&WFFY^^u|+og}6v&hudbG6{kc(UxPu*E`7lh^(8)gk#+e=+SvIu$z@ z&)Hm@0tazXu}7oo=re5Qhh=+0nI^3O_HyYsvGZ+w#>~q;;n3qcNt_@?!+(XQg$}*p zSN)m36Qv9KU;1y3X&8w02z|rf3%E%mR>R>qU79HLm_#YDlUNp4hC_zazIKV@RJcj; z^7bpipa+bN{N6KT!czN21~)*`o9W9gHJ=eh()z55PV6<)!W>Z#j^eUt{HmWOssFM@ zdN2hMow$ffLAWu##QTZxb{FgEb~q_fOib*a6NJ%w5dgax+(iHNBpr7ovzoW5)y+&? zOl;fnDvj56u)qlJN65ur$`!cBy1TuYCCbiYM7npsVV<7uCUE@gh5e5gSEah8q9CK2 z203N*)+^sY^IPHyC4N8$Y&DoJXZ`K7l$yd9PPT69#nsq_%r|A z`XFwt_HSD5eGdZj8Tzo6y>Oa!Lo1V`sFG&F1c(w%$=wGnX>k~#!r*2z72?PR~iT;&0-?v(^7!$T!)%mFxm?#-;~ z;{~m-yl*KgwIK?~ZkOH9wFj;q_FaS%$h*}t8)2d`!%Ht)Y#o0pNLHy0VilV>jC-yo zihg)Lc&@;wzTC8cUYe9S!eQ&1vX#((RT8B5O^iF#9H0DKxHKe2Vp9Glsh41=(5QG! zT7q zNvcYo5C?inA*=xLuK5Ie39AsmRK63Ps7a@F#vv?tbVdu~X?VUV@#hCT_fC#P_!-JB zMG#!b7m763oD?seIy1UOl+B}smP~!jqcJut@w;7GzsG}R9GFN$i=jo^$NJk9Itt0p z39MTF{JSnP1(dZau`~%$9DigZMhLY}s!t(9g~(nRe-%*?d~Nb`&U3tpbhzb7?+g#m z{o1UlKP>LkmyWk`ZaIIGCF%P}MfGjb>M4Y!^@vrkqZ(phTjNHz=>|f!+S@~w@|7-2 z<Af6)n_2vQCpr^SqWPU<{E=s9+g| zFQjb`7HilnN0cXJG+NEDipNZ%ET3kBGu-Y5stko&8f+5bIFMsP4WqdEvO{yF&@fvT!tYvlWr=HKXbCpcRT4jpGTq)~@p`p#=9h@+?5=NvEW+o*q>-T3f2P>0U_$(mF)pvg zrMf-_GUqRn!KoXobSIVKN{#`Z2jTF3JU4@?rg=aAp70wlI#~?#psB146K}siLQq&} z%}`1gpzR5XBO7>I{jJ$6#oDtja6PJ0r?DH><6|ReiYcji96@* zAF=ytB-_^jt4r|^BOnB!aYM2?Uq`wxxr-c)s2UC)-cITZ?Sxt^{SyVsS<$y9?05PY z*}qB|4NA=!g(S}+kl1n^BHu}SzO^KCt2{#rSCYGX%a(wFfy3UthuNrFFg6gNk3VLA>9E}MU+_vV&F#Md`{m?I8ucOv0>R#l z5yC$c$uf=uQ)9A^jM}vfY0{gGzIk*pR0p*BnP!%@RcJ)H39=V!0LfwgP&>B=z^Pv# zipM*-Mkrp~Q-%m58|2<+a z-929wCDSv&oRWXpuXP=#XwSi=P51lL5nQOGpRhZN9M-W5W3KVi>4K++ylOUf@skQQ6qza$n8)n9c2_Of{1TdJXl+)XJAfwR7{8jsZBx^<1iz0@b!+#e` z?A`Lu5D+G7`D)oLAFFmv2WAdTLy7OTr#S9O+}R!RN58#({BmA@ohU_6{`l>ETzs-(B?hOj^Q;HhmCsnfGLyJVM57pE?*M$E0A{F0;a8 zo|cQ0siwIs$8_3buR!eKqz{MPu(4F3Jjb)c<80NHa+pT>@)+5~MX6xT0W-{^Du^v+3I_Ht5|^7}%kjs)!>+u4*PC>-Mj2h);0B!yhk`(G^Se@9oS zXhC710w^X_bTHcmMScK`67E>0?oai9U?6CrI#U*;4uyfl0OTj$Le3akWI~IAVjYwc zC=3L}s_AEvhKivuP!JRbQg6W5fWkmX0F516nXbajoL!x=JXNB?HB^RIH0ip@k|G*HUw~G=QE% zJfplwg%IXBN?-Lv>q~l`>HCHm@0=J$qKSUwKV*= zvjZ3PDS4fCOagwkehx;{kprc#SA57J+?;T zc&YkW^et^g(<_n^q>ym6_HP+AAX_2! z9TY%{q<~-MplT>GwtXJ_UUs~Y=8_SO{Tw30n#5)1%RTs6Qj#w8{RlPXlYn$UJ&H|( zR9dq%LnJtl2qqvKKxxGxorvvA;P;B-`5NPu3R~PhCq5uH+>+%<;+&gsV9c@}RjO^1D2{ zWElHgEMo4jGg?Gb5JWDSHICeMonSpqW3m1nal@1SJUf5G2VD-al)i|*NJr2Y(rlTm ziIc@T9Yc*0jYN9yp71q&-{;<3D%c{8GHnNpjl{xu7|k}_a1j-2&Z;DVAAP7ys`;n@ zyA?58t}6#X-bs{IGQG~`23`V=V?@Hco#C)m{s|)!AXy-RE|kdEuJ06x&A}xjWA(}O zx#Ga6#|T6t@#w4#YE0K@5keYoV>!xjp9^!KK)D%dqOJs34r(vuD4xN1R%p~CiUX+ zX6Hlbss{j1Eg(~Y4H^^K{`%r+u~^HxLMNN<@Xxb+*xsBZLtj{M8!| z215D0cJumhZVKR7m2Ou(*+x=0L$XAk&ilzh9#>`uD=j?FH%q5pM-qU}AmOIjVMq4i z;jrRQ6ak~kXE>-+xr-q0l4dqx3P7*T$0e8E3<3nT%8~6jRhGKQ5@1+=l=yKnRe&*) z&a3*51c*M&USI!iK5ljefP7-pfW=$YLDAB3>I_|?b3U4YO;27T0)MBX-2w!>^di9Y zG7zn_xDr(N1^xjz)$pWNk82A)mm@;F51L;V9lC?jihxrCeeZl@{S=!wJz^#)4c?BxZ57)irsIQZM#A_pz{pVgRulsW=34bQWVxSys|6X1m-^l-KLDh94F}>q7JJcf z3#4xu%(r9nX@9OzPOMuA(17!?>7dO$IKK z5q(ZJX72&u8ZYXti-{S{{UwAT2i^cOnvuq;*UC^2&0;}}1ju{pbo~~WDA~$;YLxg! zfcwkA)HGlo&tYWGEDu{c!XP)X>b4(p307l(6h*V9k;#bi5`+Yq)nY zrcMppufFGV`V0u$Yf25}nH!VBWYU;*2E$vE659g455mLe9ta&85b<~t{zl%>u9~~0 z1-Zz9Hq39#Co{loggo|d6Yt4Ffar@S&QoLuS0rz;G!P2aNC_($p$DWfbdjf@JBr(@ z=h0xE6@@X$B)sCYf%H&?9}Z8QH}!)E+IV~#;HFXj!x`!aVPWwkk8$~sQM88-KsT#N z)FW+BU&5-BOGnzAM?Rt(GVD$LA;k3g%k0e&V;ur-VirrCagD(@^I4r>lK-9JEi*ye zf?&P-LYbIVX5HzOv%P(u(?=xiSSBUWsS12gUzchMrst0xis7yQ8Ug8CMjA7_EK5B+ z7;LG5_G7o)7T=Nn6omT$RQ~Y-=K&)vV_9EOLYMos;3bmV(VhLleD-^mZ>?f4c2E|z zujJ==m-{=|{4xvAo2P@T1^e;YV(~HV;F15y=xTLC{f4d=^JBxmqEKxxYl*HwbL$Y` zjTI5iJY5PF2Y!Dj7UlFYk#`)-!d5GAL2GupPkq`T{XdA^;^T!VX2wJ)HTyPbOzi)l zW;rt>i+a=o7-3m~3sTK+Nhc+&8NGo(q~u|tP6M}kF)>X$U?#cU76VeaF+@6RwXDa; zzGyLq?y2~5*QDB%hsXKnjke=;a7+C+NBfIplrr~;m;V)avVR&jG-P3K_pcmf8Uh9@4b|8t}#V11alN#|SF6&uh07;;uGfPhYljfNLE;9+=> z=OW8cYDPe>qu+ZGC^pdOI7g<{C@hB$vLYDjE8~q00w8w@yrE>sb%|rR*U4EH?;j?C z56Z6AV;`$N;u2y?18Qij&#uR-QrQOC2_qOWZS|%~W+o}XmGLF?ynfq{PWo!Zh{zyF@v?WaRadxVwC6)I2fU`6Ai-&rTY#$}Iy(9U z5-8d-bzgQ+cd2H9Yo|pbqR2QR-|6AWd9mJ`K!KF!SFuLL;E!iZI?;b>N5}wEQE}NcJ9pnP0z>Gc1$5{Sq`scn)=ns zO3Wz4@$TgINadOl1naiza)}Na@yUEZB`X zflcamx=8ddrNIUC*c5h$jZJdvvB9q*bU03}6nmIz$uMxZ9jJbgyF#0J@W*(};i!7+ zsqkph4jO1O-Q!5)%uV{Y+<$5~QVwE;9YFK_3E`(Umn9HU?oMl;UUK;X+I^R_t7%J6 zs3Q{M!1HY$&XqIS+o7AD3J;q;D|asY&}6MW}XVYnYZ^>=w9pq;52n>IFx z%H$s|t6l-PvJAK<8Hjs+WMuO$ON*JWpVyrs!cfH14N4`PyLth7|L|> z!>B2!0P_Vdj1-i^M#SYp115(raOqHX8b@S?1{e?kx#$0@2To7Zg#}rj6(~aA_h%k3 zL2(zdE1T>p;+Uv^tT8CZ5(hGJ`6*&k#{Bsc=5&qE3VVNvSeSj9@BYAOT07D6cul(# z<7D__>k|=)@y=Cc*1y*VSGsjxU2{@j3G9WQcEOvvo3cMi8blT)x?E~`hq;T{vep<9 zO9rU9W%~!&@^Y$CntUm}zq7e43b4X7CX!O6r~^M^8{KaL0Vsz($x2jf1o4l9*TUe( z49_w5Q!O7z+o|^{@7Hn+U)^Qiz01(o)N(nEpT1we4!6v*8Owqd=N?VRUSy5$aXxcd zs*NR|F2f%M_;JEayuY_-nB^LbH?6D|D(#l=I#kWfy&kXo261|t;Wy=5U1Gz7*CwgO zq4&)hV9POoNhi9GbP^3O7@MeK-b^f+8~@7hqOv24=U(!8=jpjfrvag8%odPF%w1kp zMb~j0{&;`r@hwI|Z<1!uaZW;ld5cuY<)5{!K(l<$Eh~&YLys9*xS)JQ(udsCnG%(g zs8e)+{ht`d=~o>i!>A#v>fUfH$))5gxE@u<2r3?(3dD)_Q7Y5s?$4y35oyIuW_s%l zs4Dq}!gKNDIj4r48EJ#6YpRRjJ@fb!HWL!mu8qThR&Z$Z$zkVdf4+*`?0bh0$m#4y zLR_4v@UvHV{=amo;Wf1E(G0RL5K|MANgx#s=!==W6q~&CY_zqB6M@)JeZiulqJ)$b z2|zNY8gA{e-?R;ZNST}O;}UD@aRG)06j?e328L6w^GPg`EC$%YK>|hwcE8QhPkNr z9dH_*7=w1(+GBy3ah77O8WUv&F&`vs2H?lI)lZO$OyxEi)jQz#^~iKNT2@eJinstG z$9qxSJFvYQpMES>G6pxh9+pPd9HE%Fp zFHhI=MtS-nY6ync`GKIgFM5C+zr6_jVM`0rq1h1z_T=^-3JKhHR1CMGfqU_Vn;+1^ zcN_gW<9zm|wCcFzy+!8fs>E!C@n$p);g3E++e-U?t|upgkCFM-&BQV?5cP*))qE22 zikE3=KHtBE8WnZ+56PU8CK^dt+&AVw`bwK*P5AmVOYi?lx4TVzvcHhpT3hPiUKAMb z4pq8S+!3C(^uzMJ3tcpo;0}%=F1aa?PqVK4sPXtZUp=EqQ1^GeUo_VsLa~@^(Cs-Y z2wwk#Y`)@FeP6L~h4Nz>cR%6V5FrC2Q%GUGN+MlfvVLEoKuGsdJRie$LE{rLBl@7L zbm!3d_*`c_VA794C$#xow)WktomJL4vpftmIXQ*aR4y6iE_*Gzjev&23Eb7hT>54C zzC(3?uH2Z|`_60P-un?_C_U|bOG%jI$eKi45{M)9sgX;Zd9A{N7p^LHq^Y3sPkfTi zdDckKDi+vFYoK*xolCc+hDQHNM3Uv_qkYczT@$LceWeVK5tfa)KF)4cm+|$w!(42# ztT-w*kM^}$8CAs~x_YkKs(lKm1M;EqEvA}j!+0pcLmQ2sSgC)utvUUYk~;?j_i5S3 zyAh&6-CO(GJ3+!d5&GBr@?d|Zg}}SfkZUkOK7@Ou=rp%2ahcJ^bbcWFXz;GMUJ;di zG$u=n2}77-9UW%ED}@7PbDxj9>j1Y2eLJjNJj5koP}R-US7E!TULF|1jaPVZ!7Jaq6xcX@KO3QeYBg8Fr+s6lUQgp|`w08^fS)ukn%tSh*w2EpNwubPy-ccD3 zwANA2i7F8DXk7kNnXSwYU<_mnk7WMp%vEeP$gJ8ILW+KA7$;w(sxf2CBpF$yr%S-q zVY6&iP%Aph^_JD2gaUIV*e?JQwbWp#5CDI}_NCZ$ECh%v7I(T{()&>~ zhT?PUx+hZIVR9W(x`ehb%u5o2b z?66ET26$|hg}>2zlP+{^>_N3j+uR9uc$<>8E0N4>RcnmS7fWEgxfxwqg`RyQfbmS^ zNrgQtS)SXl>YmK!Vx>g#+N?gpDA%MsK~kiXjNsNT5IZ@=IsZLvRT_}`?#0(BTL`6+ ze>9&7zfIuDLmq}y{bsy-_tPJ7z#qK4Eb)3xHx~rwuC4Rv4wA5q+~E1;QB+%w;X*ah zusf2*=pC&j-FP0(xWh|J#X#0%W%zrHUVpQo*YUvXhUy<-M-t9>gY+=-O{tiw=+i=M z{u%P+9RYon>3WGqnsKVZq^*9|!W7-)c2Uj1*jmhDow4IC+a}t;_JL3E_1`C2{*55u zK2YiRAigIei|I<3HqeH<9$~41EnBJ-r^$%wHIL;Y5C~J^SS_oUE6JtdHZ^rRbBVP$ z5)l&<5~Yd~$EJ`vL>95Y^E?|?3@1$S1@R}QUM0UBLsFm8@4_n$FrDh%arVpezr(D1 z?~!?CboGc(z!sqVCs3G3vXxA{TPjEu$Oug=M}SLERZ78Q3f!HcvE>aTd${Dn#Uhie zVAGTzPGVJ2jB=Y9pAb+>I!=fSvnjFQghURHQ~E@Ru3GG^9LBYp!@4d~s3I&pEymhZ z_vB<`MUrF@P&A!U^?3B|c?Bo4N&RcZVNHYxW-mEQw0p3nF1Elqcl_7f<|#V7Nk z9whB+@ZO!SFn0LMNm$q;x&096=}si+*h>Pt#d<>yMe;AUg>_|8x6N1L_t7R?Cv1^& zJae{kGO_c%39``l=d@hxA`qxk{Uv#l&7-E(G-Eu^Qh+t2d27=;wLkP3R~a(c4(F~W zr>K}e;Cwg(yL!GwZ@#b;p$<+`M^F^rl#q@EKCG7XME~L^xzebb_BS+1Bth+3drsa* z--7=cAFh|%&t8O{TEiMT8Mo-h&IvmYOlc{`&h5~I+Q`NpcJrF)PB)jJHPoQql+nie z29}n!Xx4?~Iwm+U=_??U2z6kZvZuy#a)8_&YfqGWB|~aC!d;`0H=d$x|}eKcga^ z;fe`gBddvQUIby4hJOkm`n^HaROq~c*Y;~ZG|)sNzyA3K(GL(EB$VG~+0Nl?LrcFA z#7>bVE0Kx!m~UVnG5vnlk7?%6Q@nxYrhfC*x&}tVRpbrak@y?zFfX59$BAH)u7=y01}t zpr*eu(ApFneEdz|ODp+8xy%BWHP%ZMCV&Ld&c5Y%yvVGT8#A?;pGZj0=v|FuwbAFyX zoq!8ihmx@SA+5-{8W;QHkj;<5LM>w>%w$eb&->E+r=doNpr@y&`Muxdj@JfJ{VvRJ zKX!FVYa-RmH@Y>)5Xt)ebkSdslf{1UDj8ip;R6n@2s6Hmn0t`vey%wYQ7Mjx;d@xQ z#l37`nXdBIDb_5)zJI9Zw6#_}$s)kd9BOrV-{i!5%+X6GBnDhZa%ao5iz^blMRWx4 zS!YBub^RJ05xrePe*LOi7LhB{F5=|m+`kJWXWV~!cfq2QG>690_O%gh-v$%cWJg@A zP< Date: Tue, 19 Jul 2022 10:32:22 -0700 Subject: [PATCH 08/29] Update specification/logs/api.md Co-authored-by: Sam <370182+plantfansam@users.noreply.github.com> --- specification/logs/api.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/specification/logs/api.md b/specification/logs/api.md index df800ae05d8..a0cca2f2157 100644 --- a/specification/logs/api.md +++ b/specification/logs/api.md @@ -25,7 +25,7 @@ Notwithstanding any global LoggerProvider, some applications may want to or have The LoggerProvider MUST provide the following functions: -* Get an Logger +* Get a Logger ##### Get an Logger From 4df048e8308c5e8335953ce399cb1249d3129d59 Mon Sep 17 00:00:00 2001 From: Santosh Cheler Date: Tue, 19 Jul 2022 10:33:02 -0700 Subject: [PATCH 09/29] Update specification/logs/api.md Co-authored-by: Sam <370182+plantfansam@users.noreply.github.com> --- specification/logs/api.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/specification/logs/api.md b/specification/logs/api.md index a0cca2f2157..83f0d07d5c7 100644 --- a/specification/logs/api.md +++ b/specification/logs/api.md @@ -27,7 +27,7 @@ The LoggerProvider MUST provide the following functions: * Get a Logger -##### Get an Logger +##### Get a Logger This API MUST accept the following parameters that determine the scope for the `Logger` returned. Most of these are common with the scope parameters for `Tracer` and `Meter`, except for `event_domain` and `include_trace_context` which is specific to `Logger`. From 47609efd6b3c0d07ef240fe0ed96978e55755250 Mon Sep 17 00:00:00 2001 From: Santosh Cheler Date: Thu, 28 Jul 2022 19:22:35 -0700 Subject: [PATCH 10/29] Update specification/logs/semantic_conventions/events.md Co-authored-by: Tigran Najaryan <4194920+tigrannajaryan@users.noreply.github.com> --- specification/logs/semantic_conventions/events.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/specification/logs/semantic_conventions/events.md b/specification/logs/semantic_conventions/events.md index 76be6014eb3..ad84ecc3649 100644 --- a/specification/logs/semantic_conventions/events.md +++ b/specification/logs/semantic_conventions/events.md @@ -2,7 +2,7 @@ **Status**: [Experimental](../../document-status.md) -This document describes the attributes of standalone Events that are represented by `LogRecord`s. All standalone Events have a name and a domain. The Event domain is used as a mechanism to avoid conflicts with event names. +This document describes the attributes of standalone Events that are represented by `LogRecord`s. All standalone Events have a name and a domain. The Event domain is a namespace for event names and is used as a mechanism to avoid conflicts of event names. **type:** `event` From ad9a7050ac593e112ee1a08ee28ee5bc0c5cc120 Mon Sep 17 00:00:00 2001 From: Santosh Cheler Date: Thu, 28 Jul 2022 19:24:36 -0700 Subject: [PATCH 11/29] Update specification/logs/api.md Co-authored-by: Tigran Najaryan <4194920+tigrannajaryan@users.noreply.github.com> --- specification/logs/api.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/specification/logs/api.md b/specification/logs/api.md index 83f0d07d5c7..73c29c501f2 100644 --- a/specification/logs/api.md +++ b/specification/logs/api.md @@ -36,7 +36,7 @@ This API MUST accept the following parameters that determine the scope for the ` - `version` (optional): Specifies the version of the instrumentation scope if the scope has a version (e.g. a library version). Example value: 1.0.0. - `schema_url` (optional): Specifies the Schema URL that should be recorded in the emitted telemetry - `event_domain` (optional): Specifies the domain for the events created, which should be added in the attribute `event.domain` in the instrumentation scope. -- `include_trace_context` (optional): Specifies whether the Trace Context should automatically be passed on to the events and logs created by the Logger. This SHOULD be false by default. +- `include_trace_context` (optional): Specifies whether the Trace Context should automatically be passed on to the events and logs created by the Logger. This SHOULD be true by default. - `attributes` (optional): Specifies the instrumentation scope attributes to associate with emitted telemetry. Implementations MUST return different `Logger` instances when called repeatedly with different values of parameters. Note that always returning a new `Logger` instance is a valid implementation. The only exception to this rule is the no-op `Logger`: implementations MAY return the same instance regardless of parameter values. From 73c5a062ad1386da4ebf4634818df11b425ca62b Mon Sep 17 00:00:00 2001 From: Santosh Cheler Date: Fri, 29 Jul 2022 06:30:56 -0700 Subject: [PATCH 12/29] Apply suggestions from code review Co-authored-by: Tigran Najaryan <4194920+tigrannajaryan@users.noreply.github.com> --- specification/logs/api.md | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/specification/logs/api.md b/specification/logs/api.md index 73c29c501f2..df2c8e534df 100644 --- a/specification/logs/api.md +++ b/specification/logs/api.md @@ -13,7 +13,7 @@ LoggerProvider/Logger are analogous to TracerProvider/Tracer. ### LoggerProvider -Logger can be accessed with an LoggerProvider. +`Logger`s can be accessed with a `LoggerProvider`. In implementations of the API, the LoggerProvider is expected to be the stateful object that holds any configuration. (Note: The SDK implementation of this is what we currently call the [LogEmitterProvider](https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/logs/logging-library-sdk.md#logemitterprovider)) @@ -29,13 +29,12 @@ The LoggerProvider MUST provide the following functions: ##### Get a Logger -This API MUST accept the following parameters that determine the scope for the `Logger` returned. Most of these are common with the scope parameters for `Tracer` and `Meter`, except for `event_domain` and `include_trace_context` which is specific to `Logger`. +This API MUST accept the following parameters: - `name` (required): This name SHOULD uniquely identify the [instrumentation scope](../glossary.md#instrumentation-scope), such as the [instrumentation library](../glossary.md#instrumentation-library) (e.g. `io.opentelemetry.contrib.mongodb`), package, module or class name. If an application or library has built-in OpenTelemetry instrumentation, both [Instrumented library](../glossary.md#instrumented-library) and [Instrumentation library](../glossary.md#instrumentation-library) may refer to the same library. In that scenario, the `name` denotes a module name or component name within that library or application. In case an invalid name (null or empty string) is specified, a working Logger implementation MUST be returned as a fallback rather than returning null or throwing an exception, its `name` property SHOULD be set to an empty string, and a message reporting that the specified value is invalid SHOULD be logged. A library implementing the OpenTelemetry API may also ignore this name and return a default instance for all calls, if it does not support "named" functionality (e.g. an implementation which is not even observability-related). A LoggerProvider could also return a no-op Logger here if application owners configure the SDK to suppress telemetry produced by this library. - - `version` (optional): Specifies the version of the instrumentation scope if the scope has a version (e.g. a library version). Example value: 1.0.0. -- `schema_url` (optional): Specifies the Schema URL that should be recorded in the emitted telemetry -- `event_domain` (optional): Specifies the domain for the events created, which should be added in the attribute `event.domain` in the instrumentation scope. +- `schema_url` (optional): Specifies the Schema URL that should be recorded in the emitted telemetry. +- `event_domain` (optional): Specifies the domain for the events created, which should be added as `event.domain` attribute of the instrumentation scope. - `include_trace_context` (optional): Specifies whether the Trace Context should automatically be passed on to the events and logs created by the Logger. This SHOULD be true by default. - `attributes` (optional): Specifies the instrumentation scope attributes to associate with emitted telemetry. @@ -57,9 +56,9 @@ Note that Loggers should not be responsible for configuration. This should be th The Logger MUST provide functions to: -- Create an `Event` and emit it to the processing pipeline. - - The API MUST accept an event name as a parameter. The event name provided should be inserted as an attribute with key `event.name`. Care MUST be taken to not override or delete this attribute while the `Event` is created. This function MAY be named `logEvent`. -- Create a `Log Record` and emit it to the processing pipeline. +- Create a `LogRecord`, representing an `Event` and emit it to the processing pipeline. + - The API MUST accept an event name as a parameter. The event name provided should be recorded as an attribute with key `event.name`. Care MUST be taken to not override or delete this attribute while the `Event` is created. This function MAY be named `logEvent`. +- Create a `LogRecord` and emit it to the processing pipeline. - This function MAY be named `logRecord`. - The intended users of this API is Log Appenders. From d5b46976cc61a90d4864e73b3bc27449b9cb70a4 Mon Sep 17 00:00:00 2001 From: Santosh Cheler Date: Fri, 29 Jul 2022 07:34:29 -0700 Subject: [PATCH 13/29] Apply review suggestions --- semantic_conventions/logs/events.yaml | 5 + specification/logs/api.md | 118 ++++++++++++++---- .../logs/semantic_conventions/events.md | 27 ++-- 3 files changed, 110 insertions(+), 40 deletions(-) diff --git a/semantic_conventions/logs/events.yaml b/semantic_conventions/logs/events.yaml index edac7ce6d4b..88d2a9e814f 100644 --- a/semantic_conventions/logs/events.yaml +++ b/semantic_conventions/logs/events.yaml @@ -15,3 +15,8 @@ groups: brief: > The domain identifies the context in which an event happened. An event name is unique only within a domain. examples: ['browser', 'mobile', 'kubernetes'] + note: | + An `event.name` is supposed to be unique only in the context of an + `event.domain`, so this allows for two events in different domains to + have same `event.name`, yet be unrelated events. No claim is made + about the uniqueness of `event.name`s in the absence of `event.domain`. diff --git a/specification/logs/api.md b/specification/logs/api.md index df2c8e534df..23905b8ed9b 100644 --- a/specification/logs/api.md +++ b/specification/logs/api.md @@ -1,7 +1,19 @@ -## Events and Logs API Interface +# Events and Logs API Interface **Status**: [Experimental](../document-status.md) + + + + +- [LoggerProvider](#loggerprovider) + * [LoggerProvider operations](#loggerprovider-operations) + + [Get a Logger](#get-a-logger) +- [Logger](#logger) + * [Logger operations](#logger-operations) + + + The Events and Logs API consist of these main classes: * LoggerProvider is the entry point of the API. It provides access to Loggers. @@ -11,53 +23,105 @@ LoggerProvider/Logger are analogous to TracerProvider/Tracer. ![Events and Logs API classes](img/events-and-logs-api.png) -### LoggerProvider +## LoggerProvider `Logger`s can be accessed with a `LoggerProvider`. -In implementations of the API, the LoggerProvider is expected to be the stateful object that holds any configuration. (Note: The SDK implementation of this is what we currently call the [LogEmitterProvider](https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/logs/logging-library-sdk.md#logemitterprovider)) +In implementations of the API, the LoggerProvider is expected to be the stateful +object that holds any configuration. (Note: The SDK implementation of this is +what we currently call the [LogEmitterProvider](https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/logs/logging-library-sdk.md#logemitterprovider)) -Normally, the LoggerProvider is expected to be accessed from a central place. Thus, the API SHOULD provide a way to set/register and access a global default LoggerProvider. +Normally, the LoggerProvider is expected to be accessed from a central place. +Thus, the API SHOULD provide a way to set/register and access a global default +LoggerProvider. -Notwithstanding any global LoggerProvider, some applications may want to or have to use multiple LoggerProvider instances, e.g. to have different configuration (like LogRecordProcessors) for each (and consequently for the Loggers obtained from them), or because it's easier with dependency injection frameworks. Thus, implementations of LoggerProvider SHOULD allow creating an arbitrary number of instances. +Notwithstanding any global LoggerProvider, some applications may want to or have +to use multiple LoggerProvider instances, e.g. to have different configuration +(like LogRecordProcessors) for each (and consequently for the Loggers obtained +from them), or because it's easier with dependency injection frameworks. Thus, +implementations of LoggerProvider SHOULD allow creating an arbitrary number of +instances. -#### LoggerProvider operations +### LoggerProvider operations The LoggerProvider MUST provide the following functions: * Get a Logger -##### Get a Logger +#### Get a Logger This API MUST accept the following parameters: -- `name` (required): This name SHOULD uniquely identify the [instrumentation scope](../glossary.md#instrumentation-scope), such as the [instrumentation library](../glossary.md#instrumentation-library) (e.g. `io.opentelemetry.contrib.mongodb`), package, module or class name. If an application or library has built-in OpenTelemetry instrumentation, both [Instrumented library](../glossary.md#instrumented-library) and [Instrumentation library](../glossary.md#instrumentation-library) may refer to the same library. In that scenario, the `name` denotes a module name or component name within that library or application. In case an invalid name (null or empty string) is specified, a working Logger implementation MUST be returned as a fallback rather than returning null or throwing an exception, its `name` property SHOULD be set to an empty string, and a message reporting that the specified value is invalid SHOULD be logged. A library implementing the OpenTelemetry API may also ignore this name and return a default instance for all calls, if it does not support "named" functionality (e.g. an implementation which is not even observability-related). A LoggerProvider could also return a no-op Logger here if application owners configure the SDK to suppress telemetry produced by this library. -- `version` (optional): Specifies the version of the instrumentation scope if the scope has a version (e.g. a library version). Example value: 1.0.0. -- `schema_url` (optional): Specifies the Schema URL that should be recorded in the emitted telemetry. -- `event_domain` (optional): Specifies the domain for the events created, which should be added as `event.domain` attribute of the instrumentation scope. -- `include_trace_context` (optional): Specifies whether the Trace Context should automatically be passed on to the events and logs created by the Logger. This SHOULD be true by default. -- `attributes` (optional): Specifies the instrumentation scope attributes to associate with emitted telemetry. - -Implementations MUST return different `Logger` instances when called repeatedly with different values of parameters. Note that always returning a new `Logger` instance is a valid implementation. The only exception to this rule is the no-op `Logger`: implementations MAY return the same instance regardless of parameter values. - -Implementations MUST NOT require users to repeatedly obtain an Logger again with the same name+version+schema_url+event_domain+include_trace_context+attributes to pick up configuration changes. This can be achieved either by allowing to work with an outdated configuration or by ensuring that new configuration applies also to previously returned Loggers. - -Note: This could, for example, be implemented by storing any mutable configuration in the LoggerProvider and having Logger implementation objects have a reference to the LoggerProvider from which they were obtained. If configuration must be stored per-Logger (such as disabling a certain Logger), the Logger could, for example, do a look-up with its name+version+schema_url+event_domain+include_trace_context+attributes in a map in the LoggerProvider, or the LoggerProvider could maintain a registry of all returned Loggers and actively update their configuration if it changes. - -The effect of associating a Schema URL with a Logger MUST be that the telemetry emitted using the Logger will be associated with the Schema URL, provided that the emitted data format is capable of representing such association. - -### Logger +- `name` (required): This name SHOULD uniquely identify the [instrumentation scope](../glossary.md#instrumentation-scope), +such as the [instrumentation library](../glossary.md#instrumentation-library) +(e.g. `io.opentelemetry.contrib.mongodb`), package, module or class name. +If an application or library has built-in OpenTelemetry instrumentation, both +[Instrumented library](../glossary.md#instrumented-library) and +[Instrumentation library](../glossary.md#instrumentation-library) may refer to +the same library. In that scenario, the `name` denotes a module name or component +name within that library or application. In case an invalid name +(null or empty string) is specified, a working Logger implementation MUST be +returned as a fallback rather than returning null or throwing an exception, its +`name` property SHOULD be set to an empty string, and a message reporting that +the specified value is invalid SHOULD be logged. A library implementing the +OpenTelemetry API may also ignore this name and return a default instance for +all calls, if it does not support "named" functionality (e.g. an implementation +which is not even observability-related). A LoggerProvider could also return a +no-op Logger here if application owners configure the SDK to suppress telemetry +produced by this library. +- `version` (optional): Specifies the version of the instrumentation scope if +the scope has a version (e.g. a library version). Example value: 1.0.0. +- `schema_url` (optional): Specifies the Schema URL that should be recorded in +the emitted telemetry. +- `event_domain` (optional): Specifies the domain for the events created, which +should be added as `event.domain` attribute of the instrumentation scope. +- `include_trace_context` (optional): Specifies whether the Trace Context should +automatically be passed on to the events and logs created by the Logger. This +SHOULD be true by default. +- `attributes` (optional): Specifies the instrumentation scope attributes to +associate with emitted telemetry. + +Implementations MUST return different `Logger` instances when called repeatedly +with different values of parameters. Note that always returning a new `Logger` +instance is a valid implementation. The only exception to this rule is the no-op +`Logger`: implementations MAY return the same instance regardless of parameter +values. + +Implementations MUST NOT require users to repeatedly obtain an Logger again with +the same name+version+schema_url+event_domain+include_trace_context+attributes +to pick up configuration changes. This can be achieved either by allowing to +work with an outdated configuration or by ensuring that new configuration +applies also to previously returned Loggers. + +Note: This could, for example, be implemented by storing any mutable +configuration in the LoggerProvider and having Logger implementation objects +have a reference to the LoggerProvider from which they were obtained. +If configuration must be stored per-Logger (such as disabling a certain Logger), +the Logger could, for example, do a look-up with its name+version+schema_url+event_domain+include_trace_context+attributes +in a map in the LoggerProvider, or the LoggerProvider could maintain a registry +of all returned Loggers and actively update their configuration if it changes. + +The effect of associating a Schema URL with a Logger MUST be that the telemetry +emitted using the Logger will be associated with the Schema URL, provided that +the emitted data format is capable of representing such association. + +## Logger The Logger is responsible for creating Events and Logs. -Note that Loggers should not be responsible for configuration. This should be the responsibility of the LoggerProvider instead. +Note that Loggers should not be responsible for configuration. This should be +the responsibility of the LoggerProvider instead. -#### Logger operations +### Logger operations The Logger MUST provide functions to: -- Create a `LogRecord`, representing an `Event` and emit it to the processing pipeline. - - The API MUST accept an event name as a parameter. The event name provided should be recorded as an attribute with key `event.name`. Care MUST be taken to not override or delete this attribute while the `Event` is created. This function MAY be named `logEvent`. +- Create a `LogRecord`, representing an `Event` and emit it to the processing +pipeline. + - The API MUST accept an event name as a parameter. The event name provided + should be recorded as an attribute with key `event.name`. Care MUST be taken + to not override or delete this attribute while the `Event` is created. + This function MAY be named `logEvent`. - Create a `LogRecord` and emit it to the processing pipeline. - This function MAY be named `logRecord`. - The intended users of this API is Log Appenders. diff --git a/specification/logs/semantic_conventions/events.md b/specification/logs/semantic_conventions/events.md index ad84ecc3649..7b3a87d1d07 100644 --- a/specification/logs/semantic_conventions/events.md +++ b/specification/logs/semantic_conventions/events.md @@ -2,18 +2,19 @@ **Status**: [Experimental](../../document-status.md) -This document describes the attributes of standalone Events that are represented by `LogRecord`s. All standalone Events have a name and a domain. The Event domain is a namespace for event names and is used as a mechanism to avoid conflicts of event names. +This document describes the attributes of standalone Events that are represented +by `LogRecord`s. All standalone Events have a name and a domain.The Event domain +is a namespace for event names and is used as a mechanism to avoid conflicts of +event names. -**type:** `event` - -**Description:** Event attributes. - -| Attribute | Type | Description | Examples | Required | + +| Attribute | Type | Description | Examples | Requirement Level | |---|---|---|---|---| -| `event.name` | string | Name or type of the event. | `network-change`; `button-click`; `exception` | Yes | -| `event.domain` | string | Domain or scope for the event. | `profiling`; `browser`, `db`, `k8s` | No | - -An `event.name` is supposed to be unique only in the context of an `event.domain`, so this allows for two events in different domains to have same `event.name`, yet be unrelated events. No claim is made about the uniqueness of `event.name`s in the absence of `event.domain`. - -Note that Scope attributes are equivalent to the attributes at Span and LogRecord level, so recording the attribute `event.domain` on the Scope is equivalent to recording it on Spans and LogRecords within the Scope. - +| `event.name` | string | The name identifies the event. | `click`; `exception` | Required | +| `event.domain` | string | The domain identifies the context in which an event happened. An event name is unique only within a domain. [1] | `browser`; `mobile`; `kubernetes` | Recommended | + +**[1]:** An `event.name` is supposed to be unique only in the context of an +`event.domain`, so this allows for two events in different domains to +have same `event.name`, yet be unrelated events. No claim is made +about the uniqueness of `event.name`s in the absence of `event.domain`. + \ No newline at end of file From 4d688dbf2aa59c0e25e2f87fc85e2c8be4e3f921 Mon Sep 17 00:00:00 2001 From: Santosh Cheler Date: Fri, 29 Jul 2022 14:55:09 -0700 Subject: [PATCH 14/29] Add clarification on event name attribute handling --- specification/logs/api.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/specification/logs/api.md b/specification/logs/api.md index 23905b8ed9b..4016f5379f6 100644 --- a/specification/logs/api.md +++ b/specification/logs/api.md @@ -120,9 +120,9 @@ The Logger MUST provide functions to: pipeline. - The API MUST accept an event name as a parameter. The event name provided should be recorded as an attribute with key `event.name`. Care MUST be taken - to not override or delete this attribute while the `Event` is created. + by the implementation to not override or delete this attribute while the + `Event` is created to preserve its identity. This function MAY be named `logEvent`. - Create a `LogRecord` and emit it to the processing pipeline. - This function MAY be named `logRecord`. - The intended users of this API is Log Appenders. - From ab7dab86cd9d4e762c9374cff9ed97b710029fae Mon Sep 17 00:00:00 2001 From: Santosh Cheler Date: Fri, 29 Jul 2022 15:07:45 -0700 Subject: [PATCH 15/29] Replace with mermaid diagram --- specification/logs/api.md | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/specification/logs/api.md b/specification/logs/api.md index 4016f5379f6..8c8cd5eff9f 100644 --- a/specification/logs/api.md +++ b/specification/logs/api.md @@ -21,15 +21,19 @@ The Events and Logs API consist of these main classes: LoggerProvider/Logger are analogous to TracerProvider/Tracer. -![Events and Logs API classes](img/events-and-logs-api.png) +```mermaid +graph TD + A[LoggerProvider] -->|Get| B(Logger) + B --> C(Event) + B --> D(Log) +``` ## LoggerProvider `Logger`s can be accessed with a `LoggerProvider`. In implementations of the API, the LoggerProvider is expected to be the stateful -object that holds any configuration. (Note: The SDK implementation of this is -what we currently call the [LogEmitterProvider](https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/logs/logging-library-sdk.md#logemitterprovider)) +object that holds any configuration. Normally, the LoggerProvider is expected to be accessed from a central place. Thus, the API SHOULD provide a way to set/register and access a global default From b9f33130a4e735e70b43a7201362b2d97701f314 Mon Sep 17 00:00:00 2001 From: Santosh Cheler Date: Fri, 29 Jul 2022 15:11:08 -0700 Subject: [PATCH 16/29] Remove image, it's replacced with mermaid diagram --- specification/logs/img/events-and-logs-api.png | Bin 6383 -> 0 bytes 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100644 specification/logs/img/events-and-logs-api.png diff --git a/specification/logs/img/events-and-logs-api.png b/specification/logs/img/events-and-logs-api.png deleted file mode 100644 index 486ef640e4f5c1d795264865bcb5aaad8d17b591..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 6383 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 AC;$Ke From cc74ab6f80653e9d925e7090cc432316cb9b41bc Mon Sep 17 00:00:00 2001 From: Santosh Cheler Date: Fri, 29 Jul 2022 15:14:01 -0700 Subject: [PATCH 17/29] Remove blank line --- specification/logs/semantic_conventions/README.md | 1 - 1 file changed, 1 deletion(-) diff --git a/specification/logs/semantic_conventions/README.md b/specification/logs/semantic_conventions/README.md index 67bba65cc43..931e1a7af27 100644 --- a/specification/logs/semantic_conventions/README.md +++ b/specification/logs/semantic_conventions/README.md @@ -10,7 +10,6 @@ The following semantic conventions for events are defined: * [Events](events.md): Semantic attributes that must be used to represent Events using log data model. - Apart from semantic conventions for logs, [traces](../../trace/semantic_conventions/README.md), and [metrics](../../metrics/semantic_conventions/README.md), OpenTelemetry also defines the concept of overarching [Resources](../../resource/sdk.md) with their own [Resource Semantic Conventions](../../resource/semantic_conventions/README.md). From 3895624b853d361e9666eb36d36cb9f5263b9bfb Mon Sep 17 00:00:00 2001 From: Santosh Cheler Date: Tue, 2 Aug 2022 07:19:02 -0700 Subject: [PATCH 18/29] Using enum type for event.domain --- semantic_conventions/logs/events.yaml | 14 ++++++++++++-- specification/logs/semantic_conventions/events.md | 10 +++++++++- 2 files changed, 21 insertions(+), 3 deletions(-) diff --git a/semantic_conventions/logs/events.yaml b/semantic_conventions/logs/events.yaml index 88d2a9e814f..503892797f2 100644 --- a/semantic_conventions/logs/events.yaml +++ b/semantic_conventions/logs/events.yaml @@ -11,10 +11,20 @@ groups: The name identifies the event. examples: ['click', 'exception'] - id: domain - type: string brief: > The domain identifies the context in which an event happened. An event name is unique only within a domain. - examples: ['browser', 'mobile', 'kubernetes'] + type: + allow_custom_values: true + members: + - id: browser + value: 'browser' + brief: 'Evens from browser apps' + - id: mobile + value: 'mobile' + brief: 'Events from mobile apps' + - id: kubernetes + value: 'kubernetes' + brief: 'Events from Kubernetes' note: | An `event.name` is supposed to be unique only in the context of an `event.domain`, so this allows for two events in different domains to diff --git a/specification/logs/semantic_conventions/events.md b/specification/logs/semantic_conventions/events.md index 7b3a87d1d07..c628fd90330 100644 --- a/specification/logs/semantic_conventions/events.md +++ b/specification/logs/semantic_conventions/events.md @@ -11,10 +11,18 @@ event names. | Attribute | Type | Description | Examples | Requirement Level | |---|---|---|---|---| | `event.name` | string | The name identifies the event. | `click`; `exception` | Required | -| `event.domain` | string | The domain identifies the context in which an event happened. An event name is unique only within a domain. [1] | `browser`; `mobile`; `kubernetes` | Recommended | +| `event.domain` | string | The domain identifies the context in which an event happened. An event name is unique only within a domain. [1] | `browser` | Recommended | **[1]:** An `event.name` is supposed to be unique only in the context of an `event.domain`, so this allows for two events in different domains to have same `event.name`, yet be unrelated events. No claim is made about the uniqueness of `event.name`s in the absence of `event.domain`. + +`event.domain` has the following list of well-known values. If one of them applies, then the respective value MUST be used, otherwise a custom value MAY be used. + +| Value | Description | +|---|---| +| `browser` | Evens from browser apps | +| `mobile` | Events from mobile apps | +| `kubernetes` | Events from Kubernetes | \ No newline at end of file From 16de49caf55052db37ec34d5f1c1ba965a94fdb0 Mon Sep 17 00:00:00 2001 From: Santosh Cheler Date: Wed, 3 Aug 2022 11:57:03 -0700 Subject: [PATCH 19/29] Requiring event.domain attribute --- semantic_conventions/logs/events.yaml | 12 ++++++------ specification/logs/api.md | 4 +++- specification/logs/semantic_conventions/events.md | 9 ++++----- 3 files changed, 13 insertions(+), 12 deletions(-) diff --git a/semantic_conventions/logs/events.yaml b/semantic_conventions/logs/events.yaml index 503892797f2..9df6a63ee5c 100644 --- a/semantic_conventions/logs/events.yaml +++ b/semantic_conventions/logs/events.yaml @@ -19,14 +19,14 @@ groups: - id: browser value: 'browser' brief: 'Evens from browser apps' - - id: mobile - value: 'mobile' + - id: device + value: 'device' brief: 'Events from mobile apps' - - id: kubernetes - value: 'kubernetes' + - id: k8s + value: 'k8s' brief: 'Events from Kubernetes' + requirement_level: required note: | An `event.name` is supposed to be unique only in the context of an `event.domain`, so this allows for two events in different domains to - have same `event.name`, yet be unrelated events. No claim is made - about the uniqueness of `event.name`s in the absence of `event.domain`. + have same `event.name`, yet be unrelated events. diff --git a/specification/logs/api.md b/specification/logs/api.md index 8c8cd5eff9f..12633128b3d 100644 --- a/specification/logs/api.md +++ b/specification/logs/api.md @@ -126,7 +126,9 @@ pipeline. should be recorded as an attribute with key `event.name`. Care MUST be taken by the implementation to not override or delete this attribute while the `Event` is created to preserve its identity. - This function MAY be named `logEvent`. + - Events require the `event.domain` attribute. The API MUST not allow creating + an event if the Logger instance doesn't have `event.domain` scope attribute. + - This function MAY be named `logEvent`. - Create a `LogRecord` and emit it to the processing pipeline. - This function MAY be named `logRecord`. - The intended users of this API is Log Appenders. diff --git a/specification/logs/semantic_conventions/events.md b/specification/logs/semantic_conventions/events.md index c628fd90330..c5ce068016d 100644 --- a/specification/logs/semantic_conventions/events.md +++ b/specification/logs/semantic_conventions/events.md @@ -11,18 +11,17 @@ event names. | Attribute | Type | Description | Examples | Requirement Level | |---|---|---|---|---| | `event.name` | string | The name identifies the event. | `click`; `exception` | Required | -| `event.domain` | string | The domain identifies the context in which an event happened. An event name is unique only within a domain. [1] | `browser` | Recommended | +| `event.domain` | string | The domain identifies the context in which an event happened. An event name is unique only within a domain. [1] | `browser` | Required | **[1]:** An `event.name` is supposed to be unique only in the context of an `event.domain`, so this allows for two events in different domains to -have same `event.name`, yet be unrelated events. No claim is made -about the uniqueness of `event.name`s in the absence of `event.domain`. +have same `event.name`, yet be unrelated events. `event.domain` has the following list of well-known values. If one of them applies, then the respective value MUST be used, otherwise a custom value MAY be used. | Value | Description | |---|---| | `browser` | Evens from browser apps | -| `mobile` | Events from mobile apps | -| `kubernetes` | Events from Kubernetes | +| `device` | Events from mobile apps | +| `k8s` | Events from Kubernetes | \ No newline at end of file From 5d060e566039b387cc29216103e2c9d57e4b206a Mon Sep 17 00:00:00 2001 From: Santosh Cheler Date: Thu, 4 Aug 2022 07:39:54 -0700 Subject: [PATCH 20/29] Fix typo Co-authored-by: Cedric Ziel --- specification/logs/semantic_conventions/events.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/specification/logs/semantic_conventions/events.md b/specification/logs/semantic_conventions/events.md index c5ce068016d..36c893e7f1c 100644 --- a/specification/logs/semantic_conventions/events.md +++ b/specification/logs/semantic_conventions/events.md @@ -21,7 +21,7 @@ have same `event.name`, yet be unrelated events. | Value | Description | |---|---| -| `browser` | Evens from browser apps | +| `browser` | Events from browser apps | | `device` | Events from mobile apps | | `k8s` | Events from Kubernetes | \ No newline at end of file From 97b7b692216b64ee6cfa52ddd005648dd8ebfbc9 Mon Sep 17 00:00:00 2001 From: Santosh Cheler Date: Thu, 4 Aug 2022 07:56:18 -0700 Subject: [PATCH 21/29] Update events.md after yaml change. --- specification/logs/semantic_conventions/events.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/specification/logs/semantic_conventions/events.md b/specification/logs/semantic_conventions/events.md index 36c893e7f1c..c5ce068016d 100644 --- a/specification/logs/semantic_conventions/events.md +++ b/specification/logs/semantic_conventions/events.md @@ -21,7 +21,7 @@ have same `event.name`, yet be unrelated events. | Value | Description | |---|---| -| `browser` | Events from browser apps | +| `browser` | Evens from browser apps | | `device` | Events from mobile apps | | `k8s` | Events from Kubernetes | \ No newline at end of file From 4c02cb1b8d4fed8015517b0f9eb875ba94f02832 Mon Sep 17 00:00:00 2001 From: Santosh Cheler Date: Fri, 19 Aug 2022 17:47:07 -0700 Subject: [PATCH 22/29] Apply review suggestions --- specification/logs/api.md | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/specification/logs/api.md b/specification/logs/api.md index 12633128b3d..50f8307d871 100644 --- a/specification/logs/api.md +++ b/specification/logs/api.md @@ -2,6 +2,9 @@ **Status**: [Experimental](../document-status.md) +
+Table of Contents + @@ -13,6 +16,7 @@ * [Logger operations](#logger-operations) +
The Events and Logs API consist of these main classes: @@ -41,7 +45,7 @@ LoggerProvider. Notwithstanding any global LoggerProvider, some applications may want to or have to use multiple LoggerProvider instances, e.g. to have different configuration -(like LogRecordProcessors) for each (and consequently for the Loggers obtained +(like LogProcessors) for each (and consequently for the Loggers obtained from them), or because it's easier with dependency injection frameworks. Thus, implementations of LoggerProvider SHOULD allow creating an arbitrary number of instances. @@ -131,4 +135,5 @@ pipeline. - This function MAY be named `logEvent`. - Create a `LogRecord` and emit it to the processing pipeline. - This function MAY be named `logRecord`. - - The intended users of this API is Log Appenders. + - This API is intended for use by Log Appenders, and SHOULD not be used by end + users or other instrumentation. From 0422aefc9d54ebb876f119341f0554098e5870d2 Mon Sep 17 00:00:00 2001 From: Santosh Cheler Date: Mon, 22 Aug 2022 09:12:50 -0700 Subject: [PATCH 23/29] Add a reference to LogRecord data model --- specification/logs/api.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/specification/logs/api.md b/specification/logs/api.md index 50f8307d871..89200c12aaf 100644 --- a/specification/logs/api.md +++ b/specification/logs/api.md @@ -16,6 +16,7 @@ * [Logger operations](#logger-operations) + The Events and Logs API consist of these main classes: @@ -32,6 +33,10 @@ graph TD B --> D(Log) ``` +## Data Model + +The API creates Events and Logs using the `LogRecord` data model. See `LogRecord` [data model](data-model.md) for the list of fields. + ## LoggerProvider `Logger`s can be accessed with a `LoggerProvider`. From 14720a815f24c0de5ad0e01514a4e622f683f0df Mon Sep 17 00:00:00 2001 From: Santosh Cheler Date: Wed, 24 Aug 2022 09:43:24 -0700 Subject: [PATCH 24/29] Updating TOC --- specification/logs/api.md | 1 + 1 file changed, 1 insertion(+) diff --git a/specification/logs/api.md b/specification/logs/api.md index 89200c12aaf..9924b04bd8b 100644 --- a/specification/logs/api.md +++ b/specification/logs/api.md @@ -9,6 +9,7 @@ +- [Data Model](#data-model) - [LoggerProvider](#loggerprovider) * [LoggerProvider operations](#loggerprovider-operations) + [Get a Logger](#get-a-logger) From 5f87b5ee0aa1516388251007f5f957d4abfefe28 Mon Sep 17 00:00:00 2001 From: Santosh Cheler Date: Wed, 24 Aug 2022 09:58:15 -0700 Subject: [PATCH 25/29] Add changelog entry --- CHANGELOG.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index b539f9ab2c9..350f8135d1d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -29,6 +29,8 @@ release. ### Logs + - Add experimental Events and Logs API specification + ([#2676](https://github.com/open-telemetry/opentelemetry-specification/pull/2676)) ### Resource - Update the version of the W3C Baggage specification used for `OTEL_RESOURCE_ATTRIBUTES`. From 554fe00a78df2608fa27d83c699d2186ad7b7377 Mon Sep 17 00:00:00 2001 From: Santosh Cheler Date: Wed, 24 Aug 2022 10:23:44 -0700 Subject: [PATCH 26/29] Add a required blank line after a section --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 350f8135d1d..bc8e7364183 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -31,6 +31,7 @@ release. - Add experimental Events and Logs API specification ([#2676](https://github.com/open-telemetry/opentelemetry-specification/pull/2676)) + ### Resource - Update the version of the W3C Baggage specification used for `OTEL_RESOURCE_ATTRIBUTES`. From 8da45f0cdb01506cfce8864021f10fefb5f28929 Mon Sep 17 00:00:00 2001 From: Santosh Cheler Date: Wed, 24 Aug 2022 10:25:45 -0700 Subject: [PATCH 27/29] Fix indentatation in the changelog entry --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index bc8e7364183..1a0c7a3693e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -29,7 +29,7 @@ release. ### Logs - - Add experimental Events and Logs API specification +- Add experimental Events and Logs API specification ([#2676](https://github.com/open-telemetry/opentelemetry-specification/pull/2676)) ### Resource From 8cd9fb84a1fa7c4094b681015b67dc0a67041a99 Mon Sep 17 00:00:00 2001 From: Santosh Cheler Date: Thu, 25 Aug 2022 00:12:26 -0700 Subject: [PATCH 28/29] Apply suggestions on formatting Co-authored-by: Tigran Najaryan <4194920+tigrannajaryan@users.noreply.github.com> --- specification/logs/api.md | 24 +++++++++---------- .../logs/semantic_conventions/events.md | 2 +- 2 files changed, 13 insertions(+), 13 deletions(-) diff --git a/specification/logs/api.md b/specification/logs/api.md index 9924b04bd8b..44ff8a4b9e9 100644 --- a/specification/logs/api.md +++ b/specification/logs/api.md @@ -108,23 +108,23 @@ work with an outdated configuration or by ensuring that new configuration applies also to previously returned Loggers. Note: This could, for example, be implemented by storing any mutable -configuration in the LoggerProvider and having Logger implementation objects -have a reference to the LoggerProvider from which they were obtained. -If configuration must be stored per-Logger (such as disabling a certain Logger), -the Logger could, for example, do a look-up with its name+version+schema_url+event_domain+include_trace_context+attributes -in a map in the LoggerProvider, or the LoggerProvider could maintain a registry -of all returned Loggers and actively update their configuration if it changes. - -The effect of associating a Schema URL with a Logger MUST be that the telemetry -emitted using the Logger will be associated with the Schema URL, provided that +configuration in the `LoggerProvider` and having `Logger` implementation objects +have a reference to the `LoggerProvider` from which they were obtained. +If configuration must be stored per-Logger (such as disabling a certain `Logger`), +the `Logger` could, for example, do a look-up with its name+version+schema_url+event_domain+include_trace_context+attributes +in a map in the `LoggerProvider`, or the `LoggerProvider` could maintain a registry +of all returned `Logger`s and actively update their configuration if it changes. + +The effect of associating a Schema URL with a `Logger` MUST be that the telemetry +emitted using the `Logger` will be associated with the Schema URL, provided that the emitted data format is capable of representing such association. ## Logger -The Logger is responsible for creating Events and Logs. +The `Logger` is responsible for creating Events and Logs. -Note that Loggers should not be responsible for configuration. This should be -the responsibility of the LoggerProvider instead. +Note that `Logger`s should not be responsible for configuration. This should be +the responsibility of the `LoggerProvider` instead. ### Logger operations diff --git a/specification/logs/semantic_conventions/events.md b/specification/logs/semantic_conventions/events.md index c5ce068016d..252a9af4fce 100644 --- a/specification/logs/semantic_conventions/events.md +++ b/specification/logs/semantic_conventions/events.md @@ -3,7 +3,7 @@ **Status**: [Experimental](../../document-status.md) This document describes the attributes of standalone Events that are represented -by `LogRecord`s. All standalone Events have a name and a domain.The Event domain +by `LogRecord`s. All standalone Events have a name and a domain. The Event domain is a namespace for event names and is used as a mechanism to avoid conflicts of event names. From cc59dad1b78b21c7730e824528b0f8a19c5d5a99 Mon Sep 17 00:00:00 2001 From: Santosh Cheler Date: Mon, 29 Aug 2022 18:15:40 -0700 Subject: [PATCH 29/29] Fix typo with events --- semantic_conventions/logs/events.yaml | 2 +- specification/logs/semantic_conventions/events.md | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/semantic_conventions/logs/events.yaml b/semantic_conventions/logs/events.yaml index 9df6a63ee5c..246cfb551a0 100644 --- a/semantic_conventions/logs/events.yaml +++ b/semantic_conventions/logs/events.yaml @@ -18,7 +18,7 @@ groups: members: - id: browser value: 'browser' - brief: 'Evens from browser apps' + brief: 'Events from browser apps' - id: device value: 'device' brief: 'Events from mobile apps' diff --git a/specification/logs/semantic_conventions/events.md b/specification/logs/semantic_conventions/events.md index 252a9af4fce..16c132923a4 100644 --- a/specification/logs/semantic_conventions/events.md +++ b/specification/logs/semantic_conventions/events.md @@ -21,7 +21,7 @@ have same `event.name`, yet be unrelated events. | Value | Description | |---|---| -| `browser` | Evens from browser apps | +| `browser` | Events from browser apps | | `device` | Events from mobile apps | | `k8s` | Events from Kubernetes | \ No newline at end of file