diff --git a/OpenTelemetry.sln b/OpenTelemetry.sln index 337b5953028..f4d72580bb3 100644 --- a/OpenTelemetry.sln +++ b/OpenTelemetry.sln @@ -32,7 +32,6 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "build", "build", "{7CB2F02E build\docfx.cmd = build\docfx.cmd build\docker-compose.net6.0.yml = build\docker-compose.net6.0.yml build\docker-compose.net7.0.yml = build\docker-compose.net7.0.yml - build\docker-compose.net8.0.yml = build\docker-compose.net8.0.yml build\finalize-publicapi.ps1 = build\finalize-publicapi.ps1 build\GlobalAttrExclusions.txt = build\GlobalAttrExclusions.txt build\opentelemetry-icon-color.png = build\opentelemetry-icon-color.png @@ -92,8 +91,8 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "workflows", "workflows", "{ ProjectSection(SolutionItems) = preProject .github\workflows\ci-aot-md.yml = .github\workflows\ci-aot-md.yml .github\workflows\ci-aot.yml = .github\workflows\ci-aot.yml - .github\workflows\ci-concurrency.yml = .github\workflows\ci-concurrency.yml .github\workflows\ci-concurrency-md.yml = .github\workflows\ci-concurrency-md.yml + .github\workflows\ci-concurrency.yml = .github\workflows\ci-concurrency.yml .github\workflows\ci-instrumentation-libraries-md.yml = .github\workflows\ci-instrumentation-libraries-md.yml .github\workflows\ci-instrumentation-libraries.yml = .github\workflows\ci-instrumentation-libraries.yml .github\workflows\ci-md.yml = .github\workflows\ci-md.yml @@ -266,6 +265,7 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Shared", "Shared", "{A49299 ProjectSection(SolutionItems) = preProject src\Shared\ActivityHelperExtensions.cs = src\Shared\ActivityHelperExtensions.cs src\Shared\ActivityInstrumentationHelper.cs = src\Shared\ActivityInstrumentationHelper.cs + src\Shared\DiagnosticDefinitions.cs = src\Shared\DiagnosticDefinitions.cs src\Shared\ExceptionExtensions.cs = src\Shared\ExceptionExtensions.cs src\Shared\Guard.cs = src\Shared\Guard.cs src\Shared\HttpSemanticConventionHelper.cs = src\Shared\HttpSemanticConventionHelper.cs @@ -323,6 +323,18 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "getting-started-aspnetcore" EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "links-creation", "docs\trace\links-creation-with-new-activities\links-creation.csproj", "{B4856711-6D4C-4246-A686-49458D4C1301}" EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "diagnostics", "diagnostics", "{52AF6D7D-9E66-4234-9A2C-5D16C6F22B40}" + ProjectSection(SolutionItems) = preProject + docs\diagnostics\README.md = docs\diagnostics\README.md + EndProjectSection +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "experimental-apis", "experimental-apis", "{17A22B0E-6EC3-4A39-B955-0A486AD06699}" + ProjectSection(SolutionItems) = preProject + docs\diagnostics\experimental-apis\OTEL1000.md = docs\diagnostics\experimental-apis\OTEL1000.md + docs\diagnostics\experimental-apis\OTEL1001.md = docs\diagnostics\experimental-apis\OTEL1001.md + docs\diagnostics\experimental-apis\README.md = docs\diagnostics\experimental-apis\README.md + EndProjectSection +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -650,6 +662,8 @@ Global {1C459B5B-C702-46FF-BF1A-EE795E420FFA} = {A49299FB-C5CD-4E0E-B7E1-B7867BBD67CC} {99B4D965-8782-4694-8DFA-B7A3630CEF60} = {3862190B-E2C5-418E-AFDC-DB281FB5C705} {B4856711-6D4C-4246-A686-49458D4C1301} = {5B7FB835-3FFF-4BC2-99C5-A5B5FAE3C818} + {52AF6D7D-9E66-4234-9A2C-5D16C6F22B40} = {7C87CAF9-79D7-4C26-9FFB-F3F1FB6911F1} + {17A22B0E-6EC3-4A39-B955-0A486AD06699} = {52AF6D7D-9E66-4234-9A2C-5D16C6F22B40} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {55639B5C-0770-4A22-AB56-859604650521} diff --git a/build/Common.props b/build/Common.props index 8a0a062ca07..758306e5571 100644 --- a/build/Common.props +++ b/build/Common.props @@ -9,6 +9,8 @@ true enable enable + + $(NoWarn);OTEL1000;OTEL1001 diff --git a/docs/diagnostics/README.md b/docs/diagnostics/README.md new file mode 100644 index 00000000000..2c959a6278e --- /dev/null +++ b/docs/diagnostics/README.md @@ -0,0 +1,23 @@ +# OpenTelemetry Diagnostics + +This document describes the diagnostic categories used in OpenTelemetry .NET +components. Diagnostics are used by the compiler to report information to users +about experimental and/or obsolete code being invoked or to suggest improvements +to specific code patterns identified through static analysis. + +## Experimental APIs + +Range: OTEL1XXX + +Experimental APIs exposed in OpenTelemetry .NET pre-relase builds. APIs are +exposed experimentally when either the OpenTelemetry Specification has +explicitly marked some feature as +[experimental](https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/document-status.md) +or when the SIG members are still working through the design for a feature and +want to solicit feedback from the community. + +> **Note** Experimental APIs are exposed as `public` in pre-release builds and +> `internal` in stable builds. + +For defined diagnostics see: [OpenTelemetry .NET Experimental +APIs](./experimental-apis/README.md) diff --git a/docs/diagnostics/experimental-apis/OTEL1000.md b/docs/diagnostics/experimental-apis/OTEL1000.md new file mode 100644 index 00000000000..5febb4f7ab4 --- /dev/null +++ b/docs/diagnostics/experimental-apis/OTEL1000.md @@ -0,0 +1,42 @@ +# OpenTelemetry .NET Diagnostic: OTEL1000 + +## Overview + +This is an Experimental API diagnostic covering the following APIs: + +* `LoggerProviderBuilder` +* `LoggerProvider` +* `IDeferredLoggerProviderBuilder` + +Experimental APIs may be changed or removed in the future. + +## Details + +The OpenTelemetry Specification defines a `LoggerProvider` as part of its +[API](https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/logs/bridge-api.md) +& +[SDK](https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/logs/sdk.md) +components. + +The SDK allows calling `Shutdown` and `ForceFlush` on the `LoggerProvider` and +also allows processors to be added dynamically to a pipeline after its creation. + +Today the OpenTelemetry .NET log pipeline is built on top of the +Microsoft.Extensions.Logging `ILogger` \ `ILoggerProvider` \ `ILoggerFactory` +APIs which do not expose such features. + +We also have an issue with the `ILoggingBuilder.AddOpenTelemetry` API in that it +interacts with the `OpenTelemetryLoggerOptions` class. Options classes are NOT +available until the `IServiceProvider` is available and services can no longer +be registered at that point. This prevents the current logging pipeline from +exposing the same dependency injection surface we have for traces and metrics. + +We are exposing these APIs to solve these issues and gather feedback about their +usefulness. + +## Log Bridge API + +The OpenTelemetry Specification defines a Log Bridge API which is rooted off of +the `LoggerProvider` (`GetLogger`) and exposes a `Logger` API to submit log +records. See [OTEL1001](./OTEL1001.md) for details about the Log Bridge API +implementation status. diff --git a/docs/diagnostics/experimental-apis/OTEL1001.md b/docs/diagnostics/experimental-apis/OTEL1001.md new file mode 100644 index 00000000000..66c1f7627ec --- /dev/null +++ b/docs/diagnostics/experimental-apis/OTEL1001.md @@ -0,0 +1,35 @@ +# OpenTelemetry .NET Diagnostic: OTEL1001 + +## Overview + +This is an Experimental API diagnostic covering the following APIs: + +* `LoggerProvider.GetLogger` +* `Logger` +* `LogRecordAttributeList` +* `LogRecordData` +* `LogRecordSeverity` + +Experimental APIs may be changed or removed in the future. + +## Details + +The OpenTelemetry Specification defines a [Logs Bridge +API](https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/logs/bridge-api.md). + +The log bridge API is used by library authors to build log appenders which route +messages from different log frameworks into OpenTelemetry. + +Today the OpenTelemetry .NET log pipeline is built on top of the +Microsoft.Extensions.Logging `ILogger` \ `ILoggerProvider` \ `ILoggerFactory` +APIs. + +We are exposing these APIs gather feedback about their usefulness. An +alternative approach may be taken which would be to append into `ILogger` +instead of OpenTelemetry directly. + +## LoggerProvider API + +The OpenTelemetry Specification defines a `LoggerProvider` API. See +[OTEL1000](./OTEL1000.md) for details about the `LoggerProvider` implementation +status. diff --git a/docs/diagnostics/experimental-apis/README.md b/docs/diagnostics/experimental-apis/README.md new file mode 100644 index 00000000000..6333099f527 --- /dev/null +++ b/docs/diagnostics/experimental-apis/README.md @@ -0,0 +1,42 @@ +# OpenTelemetry .NET Experimental APIs + +This document describes experimental APIs exposed in OpenTelemetry .NET +pre-relase builds. APIs are exposed experimentally when either the OpenTelemetry +Specification has explicitly marked some feature as +[experimental](https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/document-status.md) +or when the SIG members are still working through the design for a feature and +want to solicit feedback from the community. + +> **Note** +> Experimental APIs are exposed as `public` in pre-release builds and `internal` +> in stable builds. + +## Active + +Experimental APIs available in the pre-release builds: + +### OTEL1000 + +Description: `LoggerProvider` and `LoggerProviderBuilder` + +Details: [OTEL1000](./OTEL1000.md) + +### OTEL1001 + +Description: Log Bridge API + +Details: [OTEL1001](./OTEL1001.md) + +## Inactive + +Experimental APIs which have been released stable or removed: + + + +None diff --git a/docs/metrics/exemplars/docker-compose.yaml b/docs/metrics/exemplars/docker-compose.yaml index 87cd7a6c6d6..c8cc94fa4b1 100644 --- a/docs/metrics/exemplars/docker-compose.yaml +++ b/docs/metrics/exemplars/docker-compose.yaml @@ -48,4 +48,3 @@ services: - GF_FEATURE_TOGGLES_ENABLE=traceqlEditor ports: - "3000:3000" - diff --git a/src/OpenTelemetry.Api/Logs/IDeferredLoggerProviderBuilder.cs b/src/OpenTelemetry.Api/Logs/IDeferredLoggerProviderBuilder.cs index b7f5f3b0811..70528fe6cb7 100644 --- a/src/OpenTelemetry.Api/Logs/IDeferredLoggerProviderBuilder.cs +++ b/src/OpenTelemetry.Api/Logs/IDeferredLoggerProviderBuilder.cs @@ -3,6 +3,11 @@ #nullable enable +#if NET8_0_OR_GREATER && EXPOSE_EXPERIMENTAL_FEATURES +using System.Diagnostics.CodeAnalysis; +using OpenTelemetry.Internal; +#endif + namespace OpenTelemetry.Logs; #if EXPOSE_EXPERIMENTAL_FEATURES @@ -12,6 +17,9 @@ namespace OpenTelemetry.Logs; /// dependency injection. /// /// +#if NET8_0_OR_GREATER +[Experimental(DiagnosticDefinitions.LoggerProviderExperimentalApi, UrlFormat = DiagnosticDefinitions.ExperimentalApiUrlFormat)] +#endif public #else /// @@ -21,7 +29,7 @@ namespace OpenTelemetry.Logs; /// internal #endif - interface IDeferredLoggerProviderBuilder +interface IDeferredLoggerProviderBuilder { /// /// Register a callback action to configure the /// +#if NET8_0_OR_GREATER +[Experimental(DiagnosticDefinitions.LogBridgeApiExperimentalApi, UrlFormat = DiagnosticDefinitions.ExperimentalApiUrlFormat)] +#endif public #else /// diff --git a/src/OpenTelemetry.Api/Logs/LogRecordData.cs b/src/OpenTelemetry.Api/Logs/LogRecordData.cs index ab5af385266..cf7cc550dec 100644 --- a/src/OpenTelemetry.Api/Logs/LogRecordData.cs +++ b/src/OpenTelemetry.Api/Logs/LogRecordData.cs @@ -4,6 +4,10 @@ #nullable enable using System.Diagnostics; +#if NET8_0_OR_GREATER && EXPOSE_EXPERIMENTAL_FEATURES +using System.Diagnostics.CodeAnalysis; +using OpenTelemetry.Internal; +#endif namespace OpenTelemetry.Logs; @@ -12,6 +16,9 @@ namespace OpenTelemetry.Logs; /// Stores details about a log message. /// /// +#if NET8_0_OR_GREATER +[Experimental(DiagnosticDefinitions.LogBridgeApiExperimentalApi, UrlFormat = DiagnosticDefinitions.ExperimentalApiUrlFormat)] +#endif public #else /// diff --git a/src/OpenTelemetry.Api/Logs/LogRecordSeverity.cs b/src/OpenTelemetry.Api/Logs/LogRecordSeverity.cs index 760f6882997..d3a0442cabb 100644 --- a/src/OpenTelemetry.Api/Logs/LogRecordSeverity.cs +++ b/src/OpenTelemetry.Api/Logs/LogRecordSeverity.cs @@ -3,6 +3,11 @@ #nullable enable +#if NET8_0_OR_GREATER && EXPOSE_EXPERIMENTAL_FEATURES +using System.Diagnostics.CodeAnalysis; +using OpenTelemetry.Internal; +#endif + namespace OpenTelemetry.Logs; #if EXPOSE_EXPERIMENTAL_FEATURES @@ -10,6 +15,9 @@ namespace OpenTelemetry.Logs; /// Describes the severity level of a log record. /// /// +#if NET8_0_OR_GREATER +[Experimental(DiagnosticDefinitions.LogBridgeApiExperimentalApi, UrlFormat = DiagnosticDefinitions.ExperimentalApiUrlFormat)] +#endif public #else /// diff --git a/src/OpenTelemetry.Api/Logs/LogRecordSeverityExtensions.cs b/src/OpenTelemetry.Api/Logs/LogRecordSeverityExtensions.cs index c7f180294b7..cf22c26a23f 100644 --- a/src/OpenTelemetry.Api/Logs/LogRecordSeverityExtensions.cs +++ b/src/OpenTelemetry.Api/Logs/LogRecordSeverityExtensions.cs @@ -3,6 +3,11 @@ #nullable enable +#if NET8_0_OR_GREATER && EXPOSE_EXPERIMENTAL_FEATURES +using System.Diagnostics.CodeAnalysis; +using OpenTelemetry.Internal; +#endif + namespace OpenTelemetry.Logs; #if EXPOSE_EXPERIMENTAL_FEATURES @@ -10,6 +15,9 @@ namespace OpenTelemetry.Logs; /// Contains extension methods for the enum. /// /// +#if NET8_0_OR_GREATER +[Experimental(DiagnosticDefinitions.LogBridgeApiExperimentalApi, UrlFormat = DiagnosticDefinitions.ExperimentalApiUrlFormat)] +#endif public #else /// diff --git a/src/OpenTelemetry.Api/Logs/Logger.cs b/src/OpenTelemetry.Api/Logs/Logger.cs index 6db679016fb..b112a81cdbb 100644 --- a/src/OpenTelemetry.Api/Logs/Logger.cs +++ b/src/OpenTelemetry.Api/Logs/Logger.cs @@ -3,6 +3,11 @@ #nullable enable +#if NET8_0_OR_GREATER && EXPOSE_EXPERIMENTAL_FEATURES +using System.Diagnostics.CodeAnalysis; +using OpenTelemetry.Internal; +#endif + namespace OpenTelemetry.Logs; #if EXPOSE_EXPERIMENTAL_FEATURES @@ -10,6 +15,9 @@ namespace OpenTelemetry.Logs; /// Logger is the class responsible for creating log records. /// /// WARNING: This is an experimental API which might change or be removed in the future. Use at your own risk. +#if NET8_0_OR_GREATER +[Experimental(DiagnosticDefinitions.LogBridgeApiExperimentalApi, UrlFormat = DiagnosticDefinitions.ExperimentalApiUrlFormat)] +#endif public #else /// @@ -17,7 +25,7 @@ namespace OpenTelemetry.Logs; /// internal #endif - abstract class Logger +abstract class Logger { /// /// Initializes a new instance of the class. diff --git a/src/OpenTelemetry.Api/Logs/LoggerProvider.cs b/src/OpenTelemetry.Api/Logs/LoggerProvider.cs index fd8099715cf..f29ec12d38c 100644 --- a/src/OpenTelemetry.Api/Logs/LoggerProvider.cs +++ b/src/OpenTelemetry.Api/Logs/LoggerProvider.cs @@ -6,6 +6,9 @@ #if NETSTANDARD2_1_OR_GREATER || NET6_0_OR_GREATER using System.Diagnostics.CodeAnalysis; #endif +#if NET8_0_OR_GREATER +using OpenTelemetry.Internal; +#endif namespace OpenTelemetry.Logs; @@ -14,6 +17,9 @@ namespace OpenTelemetry.Logs; /// LoggerProvider is the entry point of the OpenTelemetry API. It provides access to . /// /// +#if NET8_0_OR_GREATER +[Experimental(DiagnosticDefinitions.LoggerProviderExperimentalApi, UrlFormat = DiagnosticDefinitions.ExperimentalApiUrlFormat)] +#endif public #else /// @@ -36,6 +42,9 @@ protected LoggerProvider() /// Gets a logger. /// /// instance. +#if NET8_0_OR_GREATER + [Experimental(DiagnosticDefinitions.LogBridgeApiExperimentalApi, UrlFormat = DiagnosticDefinitions.ExperimentalApiUrlFormat)] +#endif public Logger GetLogger() => this.GetLogger(name: null, version: null); @@ -44,6 +53,9 @@ public Logger GetLogger() /// /// Optional name identifying the instrumentation library. /// instance. +#if NET8_0_OR_GREATER + [Experimental(DiagnosticDefinitions.LogBridgeApiExperimentalApi, UrlFormat = DiagnosticDefinitions.ExperimentalApiUrlFormat)] +#endif public Logger GetLogger(string? name) => this.GetLogger(name, version: null); @@ -53,6 +65,9 @@ public Logger GetLogger(string? name) /// Optional name identifying the instrumentation library. /// Optional version of the instrumentation library. /// instance. +#if NET8_0_OR_GREATER + [Experimental(DiagnosticDefinitions.LogBridgeApiExperimentalApi, UrlFormat = DiagnosticDefinitions.ExperimentalApiUrlFormat)] +#endif public Logger GetLogger(string? name, string? version) { if (!this.TryCreateLogger(name, out var logger)) @@ -71,6 +86,9 @@ public Logger GetLogger(string? name, string? version) /// Optional name identifying the instrumentation library. /// . /// if the logger was created. +#if NET8_0_OR_GREATER + [Experimental(DiagnosticDefinitions.LogBridgeApiExperimentalApi, UrlFormat = DiagnosticDefinitions.ExperimentalApiUrlFormat)] +#endif protected virtual bool TryCreateLogger( string? name, #if NETSTANDARD2_1_OR_GREATER || NET6_0_OR_GREATER diff --git a/src/OpenTelemetry.Api/Logs/LoggerProviderBuilder.cs b/src/OpenTelemetry.Api/Logs/LoggerProviderBuilder.cs index 617a51ead09..3fa9c6fc743 100644 --- a/src/OpenTelemetry.Api/Logs/LoggerProviderBuilder.cs +++ b/src/OpenTelemetry.Api/Logs/LoggerProviderBuilder.cs @@ -3,6 +3,11 @@ #nullable enable +#if NET8_0_OR_GREATER && EXPOSE_EXPERIMENTAL_FEATURES +using System.Diagnostics.CodeAnalysis; +using OpenTelemetry.Internal; +#endif + namespace OpenTelemetry.Logs; #if EXPOSE_EXPERIMENTAL_FEATURES @@ -10,6 +15,9 @@ namespace OpenTelemetry.Logs; /// LoggerProviderBuilder base class. /// /// +#if NET8_0_OR_GREATER +[Experimental(DiagnosticDefinitions.LoggerProviderExperimentalApi, UrlFormat = DiagnosticDefinitions.ExperimentalApiUrlFormat)] +#endif public #else /// diff --git a/src/OpenTelemetry.Api/OpenTelemetry.Api.csproj b/src/OpenTelemetry.Api/OpenTelemetry.Api.csproj index 27aa7389a8d..0a781a94173 100644 --- a/src/OpenTelemetry.Api/OpenTelemetry.Api.csproj +++ b/src/OpenTelemetry.Api/OpenTelemetry.Api.csproj @@ -15,6 +15,7 @@ + diff --git a/src/Shared/DiagnosticDefinitions.cs b/src/Shared/DiagnosticDefinitions.cs new file mode 100644 index 00000000000..7e6fb6af6cf --- /dev/null +++ b/src/Shared/DiagnosticDefinitions.cs @@ -0,0 +1,14 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +#nullable enable + +namespace OpenTelemetry.Internal; + +internal static class DiagnosticDefinitions +{ + public const string ExperimentalApiUrlFormat = "https://github.com/open-telemetry/opentelemetry-dotnet/tree/main/docs/diagnostics/experimental-apis/README.md#{0}"; + + public const string LoggerProviderExperimentalApi = "OTEL1000"; + public const string LogBridgeApiExperimentalApi = "OTEL1001"; +}