diff --git a/.github/workflows/apicompatibility.yml b/.github/workflows/apicompatibility.yml index 9ab30cf3734..ebfa6c3c638 100644 --- a/.github/workflows/apicompatibility.yml +++ b/.github/workflows/apicompatibility.yml @@ -11,13 +11,12 @@ jobs: runs-on: windows-latest env: CheckAPICompatibility: true - # https://github.com/actions/setup-dotnet/issues/122 - DOTNET_MULTILEVEL_LOOKUP: 1 + steps: - uses: actions/checkout@v3 with: fetch-depth: 0 # fetching all - - uses: actions/setup-dotnet@v3.0.1 + - uses: actions/setup-dotnet@v3.0.2 with: dotnet-version: '7.0.x' include-prerelease: true diff --git a/.github/workflows/code-coverage.yml b/.github/workflows/code-coverage.yml index e2e8dceef06..a8709473587 100644 --- a/.github/workflows/code-coverage.yml +++ b/.github/workflows/code-coverage.yml @@ -18,16 +18,12 @@ jobs: fail-fast: false matrix: os: [windows-latest] - env: - OS: ${{ matrix.os }} - # https://github.com/actions/setup-dotnet/issues/122 - DOTNET_MULTILEVEL_LOOKUP: 1 steps: - uses: actions/checkout@v3 with: fetch-depth: 0 # fetching all - - uses: actions/setup-dotnet@v3.0.1 + - uses: actions/setup-dotnet@v3.0.2 with: dotnet-version: '7.0.x' include-prerelease: true diff --git a/.github/workflows/dotnet-format.yml b/.github/workflows/dotnet-format.yml index d07b4e5ce93..37d7b78bffd 100644 --- a/.github/workflows/dotnet-format.yml +++ b/.github/workflows/dotnet-format.yml @@ -21,7 +21,7 @@ jobs: uses: actions/checkout@v3 - name: Setup .NET Core 7.0 - uses: actions/setup-dotnet@v3.0.1 + uses: actions/setup-dotnet@v3.0.2 with: dotnet-version: '7.0.x' include-prerelease: true diff --git a/.github/workflows/linux-ci.yml b/.github/workflows/linux-ci.yml index 82e30af9ff9..afe2c61192a 100644 --- a/.github/workflows/linux-ci.yml +++ b/.github/workflows/linux-ci.yml @@ -23,11 +23,11 @@ jobs: with: fetch-depth: 0 # fetching all - - uses: actions/setup-dotnet@v3.0.1 + - uses: actions/setup-dotnet@v3.0.2 with: dotnet-version: '6.0.x' - - uses: actions/setup-dotnet@v3.0.1 + - uses: actions/setup-dotnet@v3.0.2 with: dotnet-version: '7.0.x' include-prerelease: true diff --git a/.github/workflows/publish-packages-1.0.yml b/.github/workflows/publish-packages-1.0.yml index ca27a4311f2..8f6f423b58d 100644 --- a/.github/workflows/publish-packages-1.0.yml +++ b/.github/workflows/publish-packages-1.0.yml @@ -23,7 +23,7 @@ jobs: fetch-depth: 0 # fetching all ref: ${{ github.ref || 'main' }} - - uses: actions/setup-dotnet@v3.0.1 + - uses: actions/setup-dotnet@v3.0.2 with: dotnet-version: '7.0.x' include-prerelease: true diff --git a/.github/workflows/windows-ci-md.yml b/.github/workflows/windows-ci-md.yml index 2a241f170be..894773ddb37 100644 --- a/.github/workflows/windows-ci-md.yml +++ b/.github/workflows/windows-ci-md.yml @@ -19,7 +19,7 @@ jobs: strategy: matrix: - version: [net462,net6.0] + version: [net462,net6.0,net7.0] steps: - run: 'echo "No build required"' diff --git a/.github/workflows/windows-ci.yml b/.github/workflows/windows-ci.yml index bc0cad6336f..f7178bd09f3 100644 --- a/.github/workflows/windows-ci.yml +++ b/.github/workflows/windows-ci.yml @@ -13,9 +13,6 @@ on: jobs: build-test: runs-on: windows-latest - env: - # https://github.com/actions/setup-dotnet/issues/122 - DOTNET_MULTILEVEL_LOOKUP: 1 strategy: matrix: @@ -26,7 +23,7 @@ jobs: with: fetch-depth: 0 # fetching all - - uses: actions/setup-dotnet@v3.0.1 + - uses: actions/setup-dotnet@v3.0.2 with: dotnet-version: '7.0.x' include-prerelease: true diff --git a/.vscode/settings.json b/.vscode/settings.json index 0fa40070760..0815e2dfa70 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -41,6 +41,7 @@ "tracestate", "Tracestate", "triager", + "typeparam", "umesan", "unencrypted", "unvalidated", diff --git a/OpenTelemetry.proj b/OpenTelemetry.proj index 2cc1c23a6e1..cc9df72af37 100644 --- a/OpenTelemetry.proj +++ b/OpenTelemetry.proj @@ -4,6 +4,13 @@ + + + + + + + diff --git a/OpenTelemetry.sln b/OpenTelemetry.sln index 5d57b8fb892..28e667ebfaf 100644 --- a/OpenTelemetry.sln +++ b/OpenTelemetry.sln @@ -212,6 +212,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "source-generation", "docs\l EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "getting-started-prometheus-grafana", "docs\metrics\getting-started-prometheus-grafana\getting-started-prometheus-grafana.csproj", "{41B784AA-3301-4126-AF9F-1D59BD04B0BF}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "OpenTelemetry.SemanticConventions", "src\OpenTelemetry.SemanticConventions\OpenTelemetry.SemanticConventions.csproj", "{D4519DF6-CC72-4AC4-A851-E21383098D11}" +EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "customizing-the-sdk", "docs\logs\customizing-the-sdk\customizing-the-sdk.csproj", "{6C7A1595-36D6-4229-BBB5-5A6B5791791D}" EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "OpenTelemetry.Extensions.Propagators", "src\OpenTelemetry.Extensions.Propagators\OpenTelemetry.Extensions.Propagators.csproj", "{E91B2E40-E428-43B3-8A43-09709F0E69E4}" @@ -244,6 +246,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "OpenTelemetry.Extensions.Ev EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "OpenTelemetry.Extensions.Serilog.Tests", "test\OpenTelemetry.Extensions.Serilog.Tests\OpenTelemetry.Extensions.Serilog.Tests.csproj", "{3B3C3571-6116-49D6-B28F-2A541E003577}" EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "redaction", "docs\logs\redaction\redaction.csproj", "{A2DF46DE-50D7-4887-8C9D-4BD79CA19FAA}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -442,6 +446,10 @@ Global {41B784AA-3301-4126-AF9F-1D59BD04B0BF}.Debug|Any CPU.Build.0 = Debug|Any CPU {41B784AA-3301-4126-AF9F-1D59BD04B0BF}.Release|Any CPU.ActiveCfg = Release|Any CPU {41B784AA-3301-4126-AF9F-1D59BD04B0BF}.Release|Any CPU.Build.0 = Release|Any CPU + {D4519DF6-CC72-4AC4-A851-E21383098D11}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {D4519DF6-CC72-4AC4-A851-E21383098D11}.Debug|Any CPU.Build.0 = Debug|Any CPU + {D4519DF6-CC72-4AC4-A851-E21383098D11}.Release|Any CPU.ActiveCfg = Release|Any CPU + {D4519DF6-CC72-4AC4-A851-E21383098D11}.Release|Any CPU.Build.0 = Release|Any CPU {6C7A1595-36D6-4229-BBB5-5A6B5791791D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {6C7A1595-36D6-4229-BBB5-5A6B5791791D}.Debug|Any CPU.Build.0 = Debug|Any CPU {6C7A1595-36D6-4229-BBB5-5A6B5791791D}.Release|Any CPU.ActiveCfg = Release|Any CPU @@ -506,6 +514,10 @@ Global {3B3C3571-6116-49D6-B28F-2A541E003577}.Debug|Any CPU.Build.0 = Debug|Any CPU {3B3C3571-6116-49D6-B28F-2A541E003577}.Release|Any CPU.ActiveCfg = Release|Any CPU {3B3C3571-6116-49D6-B28F-2A541E003577}.Release|Any CPU.Build.0 = Release|Any CPU + {A2DF46DE-50D7-4887-8C9D-4BD79CA19FAA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {A2DF46DE-50D7-4887-8C9D-4BD79CA19FAA}.Debug|Any CPU.Build.0 = Debug|Any CPU + {A2DF46DE-50D7-4887-8C9D-4BD79CA19FAA}.Release|Any CPU.ActiveCfg = Release|Any CPU + {A2DF46DE-50D7-4887-8C9D-4BD79CA19FAA}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -543,6 +555,7 @@ Global {9A07D215-90AC-4BAF-BCDB-73D74FD3A5C5} = {3862190B-E2C5-418E-AFDC-DB281FB5C705} {5FDAF679-DE5A-4C73-A49B-8ABCF2399229} = {77C7929A-2EED-4AA6-8705-B5C443C8AA0F} {7642798D-12D4-403A-BB92-B6BEF67C9D4F} = {E359BB2B-9AEC-497D-B321-7DF2450C3B8E} + {A2DF46DE-50D7-4887-8C9D-4BD79CA19FAA} = {3862190B-E2C5-418E-AFDC-DB281FB5C705} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {55639B5C-0770-4A22-AB56-859604650521} diff --git a/README.md b/README.md index 442df7a4c5f..5ef0b03e1a7 100644 --- a/README.md +++ b/README.md @@ -118,6 +118,7 @@ If you have trouble accessing the doc, please get in touch on * [Reiley Yang](https://github.com/reyang), Microsoft * [Robert Pająk](https://github.com/pellared), Splunk +* [Vishwesh Bankwar](https://github.com/vishweshbankwar), Microsoft [Emeritus Maintainer/Approver/Triager](https://github.com/open-telemetry/community/blob/main/community-membership.md#emeritus-maintainerapprovertriager): diff --git a/build/Common.prod.props b/build/Common.prod.props index 915644b7755..90119d36dab 100644 --- a/build/Common.prod.props +++ b/build/Common.prod.props @@ -13,11 +13,17 @@ - + - - + + + diff --git a/build/Common.props b/build/Common.props index deed26cd9ca..ea961e63739 100644 --- a/build/Common.props +++ b/build/Common.props @@ -31,10 +31,11 @@ [2.1.1,6.0) [3.3.3] [17.3.0] + [3.1.0,) [2.1.0,) [3.1.0,) [3.1.0,) - [3.1.0,) + [5.0.0,) [1.0.0,2.0) [1.0.0,2.0) [0.12.1,0.13) @@ -42,10 +43,10 @@ [2.8.0,3.0) [1.2.0-beta.435,2.0) 1.4.0 - 7.0.0-rc.1.22426.10 + 7.0.0-rc.2.22472.3 4.7.0 - 4.7.0 - 4.5.3 + 4.7.2 + 4.5.4 diff --git a/build/PreBuild.ps1 b/build/PreBuild.ps1 index 847c4d52c70..64d51872e34 100644 --- a/build/PreBuild.ps1 +++ b/build/PreBuild.ps1 @@ -1,26 +1,31 @@ -param([string]$package, [string]$version) +param( + [string]$package, + [string]$version, + [string]$workDir = ".\LastMajorVersionBinaries" +) -$workDir = "..\LastMajorVersionBinaries" if (-Not (Test-Path $workDir)) { - Write-Host "Working directory for previous package versions not found, creating..." + Write-Host "Working directory for compatibility check packages '$workDir' not found, creating..." New-Item -Path $workDir -ItemType "directory" | Out-Null } if (Test-Path -Path "$workDir\$package.$version.zip") { - Write-Debug "Previous package version already downloaded" + Write-Debug "Previous package $package@$version already downloaded for compatibility check" } else { - Write-Host "Retrieving $package @$version for compatibility check" + Write-Host "Retrieving package $package@$version for compatibility check" Invoke-WebRequest -Uri https://www.nuget.org/api/v2/package/$package/$version -Outfile "$workDir\$package.$version.zip" } + if (Test-Path -Path "$workDir\$package\$version\lib") { - Write-Debug "Previous package version already extracted" + Write-Debug "Previous package $package@$version already extracted to '$workDir\$package\$version\lib'" } else { + Write-Host "Extracting package $package@$version from '$workDir\$package.$version.zip' to '$workDir\$package\$version' for compatibility check" Expand-Archive -LiteralPath "$workDir\$package.$version.zip" -DestinationPath "$workDir\$package\$version" -Force } diff --git a/docs/logs/extending-the-sdk/Program.cs b/docs/logs/extending-the-sdk/Program.cs index d5ab961fe1c..5144ff82d83 100644 --- a/docs/logs/extending-the-sdk/Program.cs +++ b/docs/logs/extending-the-sdk/Program.cs @@ -27,7 +27,6 @@ public static void Main() { using var loggerFactory = LoggerFactory.Create(builder => builder .AddOpenTelemetry(options => options.IncludeScopes = true) - .AddProcessor(new MyRedactionProcessor()) .AddProcessor(new MyProcessor("ProcessorA")) .AddProcessor(new MyProcessor("ProcessorB")) .AddProcessor(new SimpleLogRecordExportProcessor(new MyExporter("ExporterX"))) diff --git a/docs/logs/extending-the-sdk/MyRedactedAttributeList.cs b/docs/logs/redaction/MyRedactedAttributeList.cs similarity index 100% rename from docs/logs/extending-the-sdk/MyRedactedAttributeList.cs rename to docs/logs/redaction/MyRedactedAttributeList.cs diff --git a/docs/logs/extending-the-sdk/MyRedactionProcessor.cs b/docs/logs/redaction/MyRedactionProcessor.cs similarity index 100% rename from docs/logs/extending-the-sdk/MyRedactionProcessor.cs rename to docs/logs/redaction/MyRedactionProcessor.cs diff --git a/docs/logs/redaction/Program.cs b/docs/logs/redaction/Program.cs new file mode 100644 index 00000000000..f5250a625f9 --- /dev/null +++ b/docs/logs/redaction/Program.cs @@ -0,0 +1,36 @@ +// +// Copyright The OpenTelemetry Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +using Microsoft.Extensions.Logging; +using OpenTelemetry.Logs; + +namespace Redaction; + +public class Program +{ + public static void Main() + { + using var loggerFactory = LoggerFactory.Create(builder => builder + .AddOpenTelemetry() + .AddProcessor(new MyRedactionProcessor()) + .AddConsoleExporter()); + + var logger = loggerFactory.CreateLogger(); + + // message will be redacted by MyRedactionProcessor + logger.LogInformation("OpenTelemetry {sensitiveString}.", ""); + } +} diff --git a/docs/logs/redaction/README.md b/docs/logs/redaction/README.md new file mode 100644 index 00000000000..07fe87b94bc --- /dev/null +++ b/docs/logs/redaction/README.md @@ -0,0 +1,6 @@ +# Redaction + +This example shows how to redact sensitive information from Logs. +In this example, we attach a custom `Processor` called `MyRedactionProcessor` +which is responsible for replacing any instance of the word "<secret>" +with the value "newRedactedValueHere". diff --git a/docs/logs/redaction/redaction.csproj b/docs/logs/redaction/redaction.csproj new file mode 100644 index 00000000000..a0d4b1e148b --- /dev/null +++ b/docs/logs/redaction/redaction.csproj @@ -0,0 +1,6 @@ + + + + + + diff --git a/docs/metrics/customizing-the-sdk/Program.cs b/docs/metrics/customizing-the-sdk/Program.cs index 4172602fc2b..26dddcb2b7b 100644 --- a/docs/metrics/customizing-the-sdk/Program.cs +++ b/docs/metrics/customizing-the-sdk/Program.cs @@ -18,6 +18,7 @@ using System.Diagnostics.Metrics; using OpenTelemetry; using OpenTelemetry.Metrics; +using OpenTelemetry.Resources; namespace CustomizingTheSdk; @@ -29,6 +30,7 @@ public class Program public static void Main() { using var meterProvider = Sdk.CreateMeterProviderBuilder() + .ConfigureResource(res => res.AddService("example-service")) .AddMeter(Meter1.Name) .AddMeter(Meter2.Name) diff --git a/docs/metrics/customizing-the-sdk/README.md b/docs/metrics/customizing-the-sdk/README.md index eeeb64ef819..647a0cf95e4 100644 --- a/docs/metrics/customizing-the-sdk/README.md +++ b/docs/metrics/customizing-the-sdk/README.md @@ -235,8 +235,7 @@ with the metric are of interest to you. #### Specify custom boundaries for Histogram By default, the boundaries used for a Histogram are [`{ 0, 5, 10, 25, 50, 75, -100, 250, 500, -1000}`](https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/metrics/sdk.md#explicit-bucket-histogram-aggregation). +100, 250, 500, 750, 1000, 2500, 5000, 7500, 10000}`](https://github.com/open-telemetry/opentelemetry-specification/blob/v1.14.0/specification/metrics/sdk.md#explicit-bucket-histogram-aggregation). Views can be used to provide custom boundaries for a Histogram. The measurements are then aggregated using the custom boundaries provided instead of the the default boundaries. This requires the use of @@ -428,4 +427,37 @@ Refer to the individual exporter docs to learn how to use them: ### Resource -// TODO +[Resource](https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/resource/sdk.md) +is the immutable representation of the entity producing the telemetry. If no +`Resource` is explicitly configured, the +[default](https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/resource/semantic_conventions/README.md#semantic-attributes-with-sdk-provided-default-value) +is to use a resource indicating this +[Service](https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/resource/semantic_conventions/README.md#service). +The `ConfigureResource` method on `MeterProviderBuilder` can be used to set a +configure the resource on the provider. When the provider is built, it +automatically builds the final `Resource` from the configured `ResourceBuilder`. +There can only be a single `Resource` associated with a +provider. It is not possible to change the resource builder *after* the provider +is built, by calling the `Build()` method on the `MeterProviderBuilder`. +`ResourceBuilder` offers various methods to construct resource comprising of +multiple attributes from various sources. + +The snippet below shows configuring the `Resource` associated with the provider. + +```csharp +using OpenTelemetry; +using OpenTelemetry.Metrics; +using OpenTelemetry.Resources; + +using var meterProvider = Sdk.CreateMeterProviderBuilder() + .ConfigureResource(r => r.AddService("MyServiceName")) + .Build(); +``` + +It is also possible to configure the `Resource` by using following +environmental variables: + +| Environment variable | Description | +| -------------------------- | -------------------------------------------------- | +| `OTEL_RESOURCE_ATTRIBUTES` | Key-value pairs to be used as resource attributes. See the [Resource SDK specification](https://github.com/open-telemetry/opentelemetry-specification/blob/v1.5.0/specification/resource/sdk.md#specifying-resource-information-via-an-environment-variable) for more details. | +| `OTEL_SERVICE_NAME` | Sets the value of the `service.name` resource attribute. If `service.name` is also provided in `OTEL_RESOURCE_ATTRIBUTES`, then `OTEL_SERVICE_NAME` takes precedence. | diff --git a/docs/trace/customizing-the-sdk/Program.cs b/docs/trace/customizing-the-sdk/Program.cs index 8b07ac2470b..20f0f9df73e 100644 --- a/docs/trace/customizing-the-sdk/Program.cs +++ b/docs/trace/customizing-the-sdk/Program.cs @@ -16,6 +16,7 @@ using System.Diagnostics; using OpenTelemetry; +using OpenTelemetry.Resources; using OpenTelemetry.Trace; namespace CustomizingTheSdk; @@ -36,7 +37,7 @@ public class Program public static void Main() { - using var tracerProvider = Sdk.CreateTracerProviderBuilder() + var tracerProvider = Sdk.CreateTracerProviderBuilder() // The following adds subscription to activities from Activity Source // named "MyCompany.MyProduct.MyLibrary" only. @@ -45,6 +46,8 @@ public static void Main() // The following adds subscription to activities from all Activity Sources // whose name starts with "AbcCompany.XyzProduct.". .AddSource("AbcCompany.XyzProduct.*") + .ConfigureResource(resourceBuilder => resourceBuilder.AddTelemetrySdk()) + .ConfigureResource(r => r.AddService("MyServiceName")) .AddConsoleExporter() .Build(); @@ -76,5 +79,7 @@ public static void Main() activity?.SetTag("foo", 1); activity?.SetTag("bar", "Hello, World!"); } + + tracerProvider.Dispose(); } } diff --git a/docs/trace/customizing-the-sdk/README.md b/docs/trace/customizing-the-sdk/README.md index 1bac8017d9b..5530993acce 100644 --- a/docs/trace/customizing-the-sdk/README.md +++ b/docs/trace/customizing-the-sdk/README.md @@ -1,7 +1,5 @@ # Customizing OpenTelemetry .NET SDK -**This doc is work-in-progress.** - ## TracerProvider As shown in the [getting-started](../getting-started/README.md) doc, a valid @@ -23,15 +21,21 @@ Once built, changes to its configuration is not allowed, with the exception of adding more processors. In most cases, a single `TracerProvider` is created at the application startup, and is disposed when application shuts down. -The snippet below shows how to build a basic `TracerProvider`. This will create -a provider with default configuration, and is not particularly useful. The -subsequent sections shows how to build a more useful provider. +The snippet below shows how to build a basic `TracerProvider` and dispose it at +the end of the application. This will create a provider with default +configuration, and is not particularly useful. The subsequent sections shows how +to build a more useful provider. ```csharp using OpenTelemetry; using OpenTelemetry.Trace; -using var tracerProvider = Sdk.CreateTracerProviderBuilder().Build(); +var tracerProvider = Sdk.CreateTracerProviderBuilder().Build(); +// .... + +// Dispose at application shutdown +tracerProvider.Dispose() + ``` In a typical application, a single `TracerProvider` is created at application @@ -67,7 +71,7 @@ leveraging the built-in Dependency Injection container as shown `ActivitySource` denotes a [`Tracer`](https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/trace/api.md#tracer), -which is used to start activities. The SDK follows an explicit opt-in model for +which is used to create activities. The SDK follows an explicit opt-in model for listening to activity sources. i.e, by default, it listens to no sources. Every activity source which produce telemetry must be explicitly added to the tracer provider to start collecting traces from them. @@ -87,7 +91,7 @@ The snippet below shows how to add activity sources to the provider. using OpenTelemetry; using OpenTelemetry.Trace; -using var tracerProvider = Sdk.CreateTracerProviderBuilder() +var tracerProvider = Sdk.CreateTracerProviderBuilder() // The following subscribes to activities from Activity Source // named "MyCompany.MyProduct.MyLibrary" only. .AddSource("MyCompany.MyProduct.MyLibrary") @@ -108,21 +112,175 @@ name starts with "Abc.". ### Instrumentation -// TODO +While the OpenTelemetry API can be used to instrument any library manually, +[Instrumentation +Libraries](https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/overview.md#instrumentation-libraries) +are available for a lot of commonly used libraries. Such instrumentations can be +added to the `TracerProvider`. It is not required to attach the instrumentation +to the provider, unless the life cycle of the instrumentation must be managed by +the provider. If the instrumentation must be activated/shutdown/disposed along +with the provider, then the instrumentation must be added to the provider. + +Typically, the instrumentation libraries provide extension methods on +`TracerProviderBuilder` to allow adding them to the `TracerProvider`. Please +refer to corresponding documentation of the instrumentation library to know the +exact method name. + +Follow [this](../extending-the-sdk/README.md#instrumentation-library) document +to learn about the instrumentation libraries shipped from this repo. ### Processor -// TODO +[Processors](https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/trace/sdk.md#span-processor) +allows hooks for start and end of `Activity`. If no processors are configured, +then traces are simply dropped by the SDK. `AddProcessor` method on +`TracerProviderBuilder` should be used to add a processor. There can be any +number of processors added to the provider, and they are invoked in the same +order as they are added. Unlike `Sampler` or `Resource`, processors can be added +to the provider even *after* it is built. + +The snippet below shows how to add processors to the provider before and after +it is built. + +```csharp +using OpenTelemetry; +using OpenTelemetry.Trace; + +var tracerProvider = Sdk.CreateTracerProviderBuilder() + .AddProcessor(new MyProcessor1()) + .AddProcessor(new MyProcessor2())) + .Build(); + +// Processors can be added to provider even after it is built. +// Only those traces which are emitted after this line, will be sent to it. +tracerProvider.AddProcessor(new MyProcessor3()); +``` + +A `TracerProvider` assumes ownership of any processors added to it. This means +that, provider will call `Shutdown` method on the processor, when it is +shutdown, and disposes the processor when it is disposed. If multiple providers +are being setup in an application, then separate instances of processors must be +configured on them. Otherwise, shutting down one provider can cause the +processor in other provider to be shut down as well, leading to undesired +results. + +Processors can be used for enriching the telemetry and exporting the telemetry +to an exporter. For enriching purposes, one must write a custom processor, and +override the `OnStart` or `OnEnd` method with logic to enrich the telemetry. For +exporting purposes, the SDK provides the following built-in processors: + +* [BatchExportProcessor<T>](https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/trace/sdk.md#batching-processor) + : This is an exporting processor which batches the telemetry before sending to + the configured exporter. + + The following environment variables can be used to override the default + values of the `BatchExportActivityProcessorOptions`. + + | Environment variable | `BatchExportActivityProcessorOptions` property | + | -------------------------------- | ---------------------------------------------- | + | `OTEL_BSP_SCHEDULE_DELAY` | `ScheduledDelayMilliseconds` | + | `OTEL_BSP_EXPORT_TIMEOUT` | `ExporterTimeoutMilliseconds` | + | `OTEL_BSP_MAX_QUEUE_SIZE` | `MaxQueueSize` | + | `OTEL_BSP_MAX_EXPORT_BATCH_SIZE` | `MaxExportBatchSizeEnvVarKey` | + + `FormatException` is thrown in case of an invalid value for any of the + supported environment variables. + +* [CompositeProcessor<T>](../../../src/OpenTelemetry/CompositeProcessor.cs) + : This is a processor which can be composed from multiple processors. This is + typically used to construct multiple processing pipelines, each ending with + its own exporter. + +* [SimpleExportProcessor<T>](https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/trace/sdk.md#simple-processor) + : This is an exporting processor which passes telemetry to the configured + exporter without any batching. + +Follow [this](../extending-the-sdk/README.md#processor) document +to learn about how to write own processors. + +*The processors shipped from this SDK are generics, and supports tracing and +logging, by supporting `Activity` and `LogRecord` respectively.* ### Resource -// TODO +[Resource](https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/resource/sdk.md) +is the immutable representation of the entity producing the telemetry. If no +`Resource` is explicitly configured, the +[default](https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/resource/semantic_conventions/README.md#semantic-attributes-with-sdk-provided-default-value) +resource is used to indicate the +[Service](https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/resource/semantic_conventions/README.md#service). +The `ConfigureResource` method on `TracerProviderBuilder` can be used to +configure the resource on the provider. `ConfigureResource` accepts an `Action` +to configure the `ResourceBuilder`. Multiple calls to `ConfigureResource` can be +made. When the provider is built, it builds the final `Resource` combining all +the `ConfigureResource` calls. There can only be a single `Resource` associated +with a provider. It is not possible to change the resource builder *after* the +provider is built, by calling the `Build()` method on the +`TracerProviderBuilder`. + +`ResourceBuilder` offers various methods to construct resource comprising of +multiple attributes from various sources. Examples include `AddTelemetrySdk()` +which adds [Telemetry +Sdk](https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/resource/semantic_conventions/README.md#telemetry-sdk) +resource, and `AddService()` which adds +[Service](https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/resource/semantic_conventions/README.md#service) +resource. It also allows adding `ResourceDetector`s. + +Follow [this](../extending-the-sdk/README.md#resource-detector) document +to learn about how to write own resource detectors. + +The snippet below shows configuring the `Resource` associated with the provider. + +```csharp +using OpenTelemetry; +using OpenTelemetry.Resources; +using OpenTelemetry.Trace; + +var tracerProvider = Sdk.CreateTracerProviderBuilder() + .ConfigureResource(resourceBuilder => resourceBuilder.AddTelemetrySdk()) + .ConfigureResource(resourceBuilder => resourceBuilder.AddService("service-name")) + .Build(); +``` + +It is also possible to configure the `Resource` by using following +environmental variables: + +| Environment variable | Description | +| -------------------------- | -------------------------------------------------- | +| `OTEL_RESOURCE_ATTRIBUTES` | Key-value pairs to be used as resource attributes. See the [Resource SDK specification](https://github.com/open-telemetry/opentelemetry-specification/blob/v1.5.0/specification/resource/sdk.md#specifying-resource-information-via-an-environment-variable) for more details. | +| `OTEL_SERVICE_NAME` | Sets the value of the `service.name` resource attribute. If `service.name` is also provided in `OTEL_RESOURCE_ATTRIBUTES`, then `OTEL_SERVICE_NAME` takes precedence. | ### Sampler -// TODO +[Samplers](https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/trace/sdk.md#sampler) +are used to control the noise and overhead introduced by OpenTelemetry by +reducing the number of samples of traces collected and sent to the processors. +If no sampler is explicitly configured, the default is to use +`ParentBased(root=AlwaysOn)`. `SetSampler` method on `TracerProviderBuilder` can +be used to set sampler. Only one sampler can be associated with a provider. If +multiple `SetSampler` is called, the last one wins. Also, it is not possible to +change the sampler *after* the provider is built, by calling the `Build()` +method on the `TracerProviderBuilder`. + +The snippet below shows configuring a custom sampler to the provider. + +```csharp +using OpenTelemetry; +using OpenTelemetry.Trace; + +var tracerProvider = Sdk.CreateTracerProviderBuilder() + .SetSampler(new TraceIdRatioBasedSampler(0.25)) + .Build(); +``` + +Follow [this](../extending-the-sdk/README.md#sampler) document +to learn about how to write own samplers. ## Context Propagation // TODO: OpenTelemetry Sdk contents about Context. // TODO: Links to built-in instrumentations doing Propagation. + +## Configuration using Dependency Injection + +// TODO: Placeholder diff --git a/src/OpenTelemetry.Api/Baggage.cs b/src/OpenTelemetry.Api/Baggage.cs index 087dead3342..3dddf60ef89 100644 --- a/src/OpenTelemetry.Api/Baggage.cs +++ b/src/OpenTelemetry.Api/Baggage.cs @@ -377,7 +377,7 @@ private static BaggageHolder EnsureBaggageHolder() return baggageHolder; } - private class BaggageHolder + private sealed class BaggageHolder { public Baggage Baggage; } diff --git a/src/OpenTelemetry.Api/CHANGELOG.md b/src/OpenTelemetry.Api/CHANGELOG.md index bfe8768bffa..4ef56689b54 100644 --- a/src/OpenTelemetry.Api/CHANGELOG.md +++ b/src/OpenTelemetry.Api/CHANGELOG.md @@ -7,6 +7,12 @@ ## Unreleased +* Updated to System.Diagnostics.DiagnosticSource version `7.0.0-rc.2.22472.3`. + +## 1.4.0-beta.2 + +Released 2022-Oct-17 + ## 1.4.0-beta.1 Released 2022-Sep-29 diff --git a/src/OpenTelemetry.Api/Internal/Guard.cs b/src/OpenTelemetry.Api/Internal/Guard.cs index e07fcfbe09a..7ff9b57d8b4 100644 --- a/src/OpenTelemetry.Api/Internal/Guard.cs +++ b/src/OpenTelemetry.Api/Internal/Guard.cs @@ -16,6 +16,7 @@ using System; using System.Diagnostics; +using System.Globalization; using System.Runtime.CompilerServices; using System.Threading; @@ -198,7 +199,13 @@ private static void Range(T value, string? paramName, T min, T max, string? m { var minMessage = minName != null ? $": {minName}" : string.Empty; var maxMessage = maxName != null ? $": {maxName}" : string.Empty; - var exMessage = message ?? $"Must be in the range: [{min}{minMessage}, {max}{maxMessage}]"; + var exMessage = message ?? string.Format( + CultureInfo.InvariantCulture, + "Must be in the range: [{0}{1}, {2}{3}]", + min, + minMessage, + max, + maxMessage); throw new ArgumentOutOfRangeException(paramName, value, exMessage); } } diff --git a/src/OpenTelemetry.Api/Internal/OpenTelemetryApiEventSource.cs b/src/OpenTelemetry.Api/Internal/OpenTelemetryApiEventSource.cs index 0c802e3c2c0..55f1bd54c09 100644 --- a/src/OpenTelemetry.Api/Internal/OpenTelemetryApiEventSource.cs +++ b/src/OpenTelemetry.Api/Internal/OpenTelemetryApiEventSource.cs @@ -24,7 +24,7 @@ namespace OpenTelemetry.Internal /// This is used for internal logging of this library. /// [EventSource(Name = "OpenTelemetry-Api")] - internal class OpenTelemetryApiEventSource : EventSource + internal sealed class OpenTelemetryApiEventSource : EventSource { public static OpenTelemetryApiEventSource Log = new(); diff --git a/src/OpenTelemetry.Exporter.Console/CHANGELOG.md b/src/OpenTelemetry.Exporter.Console/CHANGELOG.md index 1953013a33e..2075ac7fe91 100644 --- a/src/OpenTelemetry.Exporter.Console/CHANGELOG.md +++ b/src/OpenTelemetry.Exporter.Console/CHANGELOG.md @@ -9,6 +9,20 @@ ## Unreleased +* Bumped the minimum required version of `System.Text.Json` to 4.7.2 in response +to [CVE-2021-26701](https://github.com/dotnet/runtime/issues/49377). +([#3789](https://github.com/open-telemetry/opentelemetry-dotnet/pull/3789)) + +LogRecordExporter to print full exception details instead of just Message, when +using `ILogger` to log exception. +([#3784](https://github.com/open-telemetry/opentelemetry-dotnet/pull/3784)) + +Added support to print Histogram Min, Max in MetricExporter. + +## 1.4.0-beta.2 + +Released 2022-Oct-17 + ## 1.4.0-beta.1 Released 2022-Sep-29 diff --git a/src/OpenTelemetry.Exporter.Console/ConsoleLogRecordExporter.cs b/src/OpenTelemetry.Exporter.Console/ConsoleLogRecordExporter.cs index cd10c40a003..c40dd5f9f01 100644 --- a/src/OpenTelemetry.Exporter.Console/ConsoleLogRecordExporter.cs +++ b/src/OpenTelemetry.Exporter.Console/ConsoleLogRecordExporter.cs @@ -16,6 +16,7 @@ using System; using System.Collections.Generic; +using OpenTelemetry.Internal; using OpenTelemetry.Logs; using OpenTelemetry.Resources; @@ -125,7 +126,7 @@ public override ExportResult Export(in Batch batch) if (logRecord.Exception != null) { - this.WriteLine($"{"LogRecord.Exception:",-RightPaddingLength}{logRecord.Exception?.Message}"); + this.WriteLine($"{"LogRecord.Exception:",-RightPaddingLength}{logRecord.Exception.ToInvariantString()}"); } int scopeDepth = -1; diff --git a/src/OpenTelemetry.Exporter.Console/ConsoleMetricExporter.cs b/src/OpenTelemetry.Exporter.Console/ConsoleMetricExporter.cs index f5833362d79..3f4076b5f78 100644 --- a/src/OpenTelemetry.Exporter.Console/ConsoleMetricExporter.cs +++ b/src/OpenTelemetry.Exporter.Console/ConsoleMetricExporter.cs @@ -97,7 +97,13 @@ public override ExportResult Export(in Batch batch) var bucketsBuilder = new StringBuilder(); var sum = metricPoint.GetHistogramSum(); var count = metricPoint.GetHistogramCount(); - bucketsBuilder.Append($"Sum: {sum} Count: {count} \n"); + bucketsBuilder.Append($"Sum: {sum} Count: {count} "); + if (metricPoint.HasMinMax()) + { + bucketsBuilder.Append($"Min: {metricPoint.GetHistogramMin()} Max: {metricPoint.GetHistogramMax()} "); + } + + bucketsBuilder.AppendLine(); bool isFirstIteration = true; double previousExplicitBound = default; diff --git a/src/OpenTelemetry.Exporter.Console/OpenTelemetry.Exporter.Console.csproj b/src/OpenTelemetry.Exporter.Console/OpenTelemetry.Exporter.Console.csproj index e91623caf6b..02f8ed650bc 100644 --- a/src/OpenTelemetry.Exporter.Console/OpenTelemetry.Exporter.Console.csproj +++ b/src/OpenTelemetry.Exporter.Console/OpenTelemetry.Exporter.Console.csproj @@ -21,7 +21,6 @@ - diff --git a/src/OpenTelemetry.Exporter.InMemory/CHANGELOG.md b/src/OpenTelemetry.Exporter.InMemory/CHANGELOG.md index 9fbaf36b75f..0dc162cf2ec 100644 --- a/src/OpenTelemetry.Exporter.InMemory/CHANGELOG.md +++ b/src/OpenTelemetry.Exporter.InMemory/CHANGELOG.md @@ -7,6 +7,10 @@ ## Unreleased +## 1.4.0-beta.2 + +Released 2022-Oct-17 + ## 1.4.0-beta.1 Released 2022-Sep-29 diff --git a/src/OpenTelemetry.Exporter.Jaeger/ApacheThrift/Protocol/TProtocolException.cs b/src/OpenTelemetry.Exporter.Jaeger/ApacheThrift/Protocol/TProtocolException.cs index f2f47895190..8e6d3a8121f 100644 --- a/src/OpenTelemetry.Exporter.Jaeger/ApacheThrift/Protocol/TProtocolException.cs +++ b/src/OpenTelemetry.Exporter.Jaeger/ApacheThrift/Protocol/TProtocolException.cs @@ -1,4 +1,4 @@ -// (Turns off StyleCop analysis in this file.) +// (Turns off StyleCop analysis in this file.) // Licensed to the Apache Software Foundation(ASF) under one // or more contributor license agreements.See the NOTICE file diff --git a/src/OpenTelemetry.Exporter.Jaeger/ApacheThrift/TException.cs b/src/OpenTelemetry.Exporter.Jaeger/ApacheThrift/TException.cs index a7040f0153e..14d46fe6ad4 100644 --- a/src/OpenTelemetry.Exporter.Jaeger/ApacheThrift/TException.cs +++ b/src/OpenTelemetry.Exporter.Jaeger/ApacheThrift/TException.cs @@ -1,4 +1,4 @@ -// (Turns off StyleCop analysis in this file.) +// (Turns off StyleCop analysis in this file.) // Licensed to the Apache Software Foundation(ASF) under one // or more contributor license agreements.See the NOTICE file diff --git a/src/OpenTelemetry.Exporter.Jaeger/CHANGELOG.md b/src/OpenTelemetry.Exporter.Jaeger/CHANGELOG.md index 041b2df43eb..78c6c7bbddd 100644 --- a/src/OpenTelemetry.Exporter.Jaeger/CHANGELOG.md +++ b/src/OpenTelemetry.Exporter.Jaeger/CHANGELOG.md @@ -2,6 +2,18 @@ ## Unreleased +* Bumped the minimum required version of `System.Text.Json` to 4.7.2 in response +to [CVE-2021-26701](https://github.com/dotnet/runtime/issues/49377). +([#3789](https://github.com/open-telemetry/opentelemetry-dotnet/pull/3789)) + +## 1.4.0-beta.2 + +Released 2022-Oct-17 + +* Added support for loading environment variables from `IConfiguration` when + using the `AddJaegerExporter` extension + ([#3720](https://github.com/open-telemetry/opentelemetry-dotnet/pull/3720)) + ## 1.4.0-beta.1 Released 2022-Sep-29 diff --git a/src/OpenTelemetry.Exporter.Jaeger/Implementation/JaegerExporterEventSource.cs b/src/OpenTelemetry.Exporter.Jaeger/Implementation/JaegerExporterEventSource.cs index c22dd408b65..f3fee3b9da3 100644 --- a/src/OpenTelemetry.Exporter.Jaeger/Implementation/JaegerExporterEventSource.cs +++ b/src/OpenTelemetry.Exporter.Jaeger/Implementation/JaegerExporterEventSource.cs @@ -24,7 +24,7 @@ namespace OpenTelemetry.Exporter.Jaeger.Implementation /// EventSource events emitted from the project. /// [EventSource(Name = "OpenTelemetry-Exporter-Jaeger")] - internal class JaegerExporterEventSource : EventSource + internal sealed class JaegerExporterEventSource : EventSource { public static JaegerExporterEventSource Log = new(); diff --git a/src/OpenTelemetry.Exporter.Jaeger/Implementation/Process.cs b/src/OpenTelemetry.Exporter.Jaeger/Implementation/Process.cs index 1d76584748e..0f0da694d08 100644 --- a/src/OpenTelemetry.Exporter.Jaeger/Implementation/Process.cs +++ b/src/OpenTelemetry.Exporter.Jaeger/Implementation/Process.cs @@ -23,14 +23,9 @@ namespace OpenTelemetry.Exporter.Jaeger.Implementation { internal sealed class Process { - public Process(string serviceName) - { - this.ServiceName = serviceName; - } - - public string ServiceName { get; internal set; } + public string ServiceName { get; set; } - internal Dictionary Tags { get; set; } + public Dictionary Tags { get; set; } public override string ToString() { @@ -48,7 +43,7 @@ public override string ToString() return sb.ToString(); } - internal void Write(TProtocol oprot) + public void Write(TProtocol oprot) { oprot.IncrementRecursionDepth(); diff --git a/src/OpenTelemetry.Exporter.Jaeger/JaegerExporter.cs b/src/OpenTelemetry.Exporter.Jaeger/JaegerExporter.cs index 4a26ce813d4..462d67ffb4f 100644 --- a/src/OpenTelemetry.Exporter.Jaeger/JaegerExporter.cs +++ b/src/OpenTelemetry.Exporter.Jaeger/JaegerExporter.cs @@ -78,14 +78,12 @@ internal JaegerExporter(JaegerExporterOptions options, TProtocolFactory protocol this.batchWriter = protocolFactory.GetProtocol(this.maxPayloadSizeInBytes * 2); this.spanWriter = protocolFactory.GetProtocol(this.maxPayloadSizeInBytes); - string serviceName = (string)this.ParentProvider.GetDefaultResource().Attributes.FirstOrDefault( - pair => pair.Key == ResourceSemanticConventions.AttributeServiceName).Value; - this.Process = new Process(serviceName); + this.Process = new(); client.Connect(); } - internal Process Process { get; set; } + internal Process Process { get; } internal EmitBatchArgs EmitBatchArgs { get; private set; } @@ -156,19 +154,21 @@ internal void SetResourceAndInitializeBatch(Resource resource) } } - if (serviceName != null) + if (!string.IsNullOrWhiteSpace(serviceName)) { serviceName = string.IsNullOrEmpty(serviceNamespace) ? serviceName : serviceNamespace + "." + serviceName; } - - if (!string.IsNullOrEmpty(serviceName)) + else { - process.ServiceName = serviceName; + serviceName = (string)this.ParentProvider.GetDefaultResource().Attributes.FirstOrDefault( + pair => pair.Key == ResourceSemanticConventions.AttributeServiceName).Value; } - this.Batch = new Batch(this.Process, this.batchWriter); + process.ServiceName = serviceName; + + this.Batch = new Batch(process, this.batchWriter); if (this.sendUsingEmitBatchArgs) { this.EmitBatchArgs = new EmitBatchArgs(this.batchWriter); diff --git a/src/OpenTelemetry.Exporter.Jaeger/JaegerExporterHelperExtensions.cs b/src/OpenTelemetry.Exporter.Jaeger/JaegerExporterHelperExtensions.cs index c9da743562d..6a6bd83efc0 100644 --- a/src/OpenTelemetry.Exporter.Jaeger/JaegerExporterHelperExtensions.cs +++ b/src/OpenTelemetry.Exporter.Jaeger/JaegerExporterHelperExtensions.cs @@ -62,10 +62,15 @@ public static TracerProviderBuilder AddJaegerExporter( name ??= Options.DefaultName; - if (configure != null) + builder.ConfigureServices(services => { - builder.ConfigureServices(services => services.Configure(name, configure)); - } + if (configure != null) + { + services.Configure(name, configure); + } + + services.RegisterOptionsFactory(configuration => new JaegerExporterOptions(configuration)); + }); return builder.ConfigureBuilder((sp, builder) => { diff --git a/src/OpenTelemetry.Exporter.Jaeger/JaegerExporterOptions.cs b/src/OpenTelemetry.Exporter.Jaeger/JaegerExporterOptions.cs index b992048d338..592fd554330 100644 --- a/src/OpenTelemetry.Exporter.Jaeger/JaegerExporterOptions.cs +++ b/src/OpenTelemetry.Exporter.Jaeger/JaegerExporterOptions.cs @@ -17,6 +17,7 @@ using System; using System.Diagnostics; using System.Net.Http; +using Microsoft.Extensions.Configuration; using OpenTelemetry.Internal; using OpenTelemetry.Trace; @@ -43,37 +44,47 @@ public class JaegerExporterOptions internal static readonly Func DefaultHttpClientFactory = () => new HttpClient(); + /// + /// Initializes a new instance of the class. + /// public JaegerExporterOptions() + : this(new ConfigurationBuilder().AddEnvironmentVariables().Build()) + { + } + + internal JaegerExporterOptions(IConfiguration configuration) { - if (EnvironmentVariableHelper.LoadString(OTelProtocolEnvVarKey, out string protocolEnvVar)) + if (configuration.TryGetValue( + OTelProtocolEnvVarKey, + JaegerExporterProtocolParser.TryParse, + out var protocol)) { - if (JaegerExporterProtocolParser.TryParse(protocolEnvVar, out var protocol)) - { - this.Protocol = protocol; - } - else - { - throw new FormatException($"{OTelProtocolEnvVarKey} environment variable has an invalid value: '{protocolEnvVar}'"); - } + this.Protocol = protocol; } - if (EnvironmentVariableHelper.LoadString(OTelAgentHostEnvVarKey, out string agentHostEnvVar)) + if (configuration.TryGetStringValue(OTelAgentHostEnvVarKey, out var agentHost)) { - this.AgentHost = agentHostEnvVar; + this.AgentHost = agentHost; } - if (EnvironmentVariableHelper.LoadNumeric(OTelAgentPortEnvVarKey, out int agentPortEnvVar)) + if (configuration.TryGetIntValue(OTelAgentPortEnvVarKey, out var agentPort)) { - this.AgentPort = agentPortEnvVar; + this.AgentPort = agentPort; } - if (EnvironmentVariableHelper.LoadString(OTelEndpointEnvVarKey, out string endpointEnvVar) - && Uri.TryCreate(endpointEnvVar, UriKind.Absolute, out Uri endpoint)) + if (configuration.TryGetUriValue(OTelEndpointEnvVarKey, out var endpoint)) { this.Endpoint = endpoint; } + + this.BatchExportProcessorOptions = new BatchExportActivityProcessorOptions(configuration); } + /// + /// Gets or sets the to use when + /// communicating to Jaeger. Default value: . + /// public JaegerExportProtocol Protocol { get; set; } = JaegerExportProtocol.UdpCompactThrift; /// @@ -105,7 +116,7 @@ public JaegerExporterOptions() /// /// Gets or sets the BatchExportProcessor options. Ignored unless ExportProcessorType is BatchExporter. /// - public BatchExportProcessorOptions BatchExportProcessorOptions { get; set; } = new BatchExportActivityProcessorOptions(); + public BatchExportProcessorOptions BatchExportProcessorOptions { get; set; } /// /// Gets or sets the factory function called to create the - + diff --git a/src/OpenTelemetry.Exporter.OpenTelemetryProtocol.Logs/CHANGELOG.md b/src/OpenTelemetry.Exporter.OpenTelemetryProtocol.Logs/CHANGELOG.md index 185de14b2d6..3e65833fffe 100644 --- a/src/OpenTelemetry.Exporter.OpenTelemetryProtocol.Logs/CHANGELOG.md +++ b/src/OpenTelemetry.Exporter.OpenTelemetryProtocol.Logs/CHANGELOG.md @@ -9,6 +9,10 @@ ## Unreleased +## 1.4.0-beta.2 + +Released 2022-Oct-17 + ## 1.4.0-beta.1 Released 2022-Sep-29 diff --git a/src/OpenTelemetry.Exporter.OpenTelemetryProtocol/CHANGELOG.md b/src/OpenTelemetry.Exporter.OpenTelemetryProtocol/CHANGELOG.md index 3232e5d8a24..878fadd3638 100644 --- a/src/OpenTelemetry.Exporter.OpenTelemetryProtocol/CHANGELOG.md +++ b/src/OpenTelemetry.Exporter.OpenTelemetryProtocol/CHANGELOG.md @@ -2,6 +2,24 @@ ## Unreleased +## 1.4.0-beta.2 + +Released 2022-Oct-17 + +* OTLP histogram data points will now include `Min` and `Max` values when + they are present. + ([#2735](https://github.com/open-telemetry/opentelemetry-dotnet/pull/2735)) + +* Adds support for limiting the length and count of attributes exported from + the OTLP log exporter. These + [Attribute Limits](https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/sdk-environment-variables.md#attribute-limits) + are configured via the environment variables defined in the specification. + ([#3684](https://github.com/open-telemetry/opentelemetry-dotnet/pull/3684)) + +* Added support for loading environment variables from `IConfiguration` when + using the `AddOtlpExporter` extensions + ([#3760](https://github.com/open-telemetry/opentelemetry-dotnet/pull/3760)) + ## 1.4.0-beta.1 Released 2022-Sep-29 diff --git a/src/OpenTelemetry.Exporter.OpenTelemetryProtocol/Configuration/EnvironmentVariableConfiguration.cs b/src/OpenTelemetry.Exporter.OpenTelemetryProtocol/Configuration/EnvironmentVariableConfiguration.cs deleted file mode 100644 index dd6cbc7ee9e..00000000000 --- a/src/OpenTelemetry.Exporter.OpenTelemetryProtocol/Configuration/EnvironmentVariableConfiguration.cs +++ /dev/null @@ -1,46 +0,0 @@ -// -// Copyright The OpenTelemetry Authors -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -// - -using System; -using OpenTelemetry.Internal; - -namespace OpenTelemetry.Configuration; - -internal class EnvironmentVariableConfiguration -{ - public static void InitializeDefaultConfigurationFromEnvironment(SdkConfiguration sdkConfiguration) - { - // https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/sdk-environment-variables.md#attribute-limits - SetIntConfigValue("OTEL_ATTRIBUTE_VALUE_LENGTH_LIMIT", value => sdkConfiguration.AttributeValueLengthLimit = value); - SetIntConfigValue("OTEL_ATTRIBUTE_COUNT_LIMIT", value => sdkConfiguration.AttributeCountLimit = value); - - // https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/sdk-environment-variables.md#span-limits - SetIntConfigValue("OTEL_SPAN_ATTRIBUTE_VALUE_LENGTH_LIMIT", value => sdkConfiguration.SpanAttributeValueLengthLimit = value); - SetIntConfigValue("OTEL_SPAN_ATTRIBUTE_COUNT_LIMIT", value => sdkConfiguration.SpanAttributeCountLimit = value); - SetIntConfigValue("OTEL_SPAN_EVENT_COUNT_LIMIT", value => sdkConfiguration.SpanEventCountLimit = value); - SetIntConfigValue("OTEL_SPAN_LINK_COUNT_LIMIT", value => sdkConfiguration.SpanLinkCountLimit = value); - SetIntConfigValue("OTEL_EVENT_ATTRIBUTE_COUNT_LIMIT", value => sdkConfiguration.EventAttributeCountLimit = value); - SetIntConfigValue("OTEL_LINK_ATTRIBUTE_COUNT_LIMIT", value => sdkConfiguration.LinkAttributeCountLimit = value); - } - - private static void SetIntConfigValue(string key, Action setter) - { - if (EnvironmentVariableHelper.LoadNumeric(key, out var result)) - { - setter(result); - } - } -} diff --git a/src/OpenTelemetry.Exporter.OpenTelemetryProtocol/Configuration/SdkConfiguration.cs b/src/OpenTelemetry.Exporter.OpenTelemetryProtocol/Configuration/SdkConfiguration.cs deleted file mode 100644 index a7772bcd532..00000000000 --- a/src/OpenTelemetry.Exporter.OpenTelemetryProtocol/Configuration/SdkConfiguration.cs +++ /dev/null @@ -1,69 +0,0 @@ -// -// Copyright The OpenTelemetry Authors -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -// - -namespace OpenTelemetry.Configuration; - -internal class SdkConfiguration -{ - private int? spanAttributeValueLengthLimit; - private int? spanAttributeCountLimit; - private int? eventAttributeCountLimit; - private int? linkAttributeCountLimit; - - private SdkConfiguration() - { - EnvironmentVariableConfiguration.InitializeDefaultConfigurationFromEnvironment(this); - } - - public static SdkConfiguration Instance { get; private set; } = new SdkConfiguration(); - - public int? AttributeValueLengthLimit { get; set; } - - public int? AttributeCountLimit { get; set; } - - public int? SpanAttributeValueLengthLimit - { - get => this.spanAttributeValueLengthLimit ?? this.AttributeValueLengthLimit; - set => this.spanAttributeValueLengthLimit = value; - } - - public int? SpanAttributeCountLimit - { - get => this.spanAttributeCountLimit ?? this.AttributeCountLimit; - set => this.spanAttributeCountLimit = value; - } - - public int? SpanEventCountLimit { get; set; } - - public int? SpanLinkCountLimit { get; set; } - - public int? EventAttributeCountLimit - { - get => this.eventAttributeCountLimit ?? this.SpanAttributeCountLimit; - set => this.eventAttributeCountLimit = value; - } - - public int? LinkAttributeCountLimit - { - get => this.linkAttributeCountLimit ?? this.SpanAttributeCountLimit; - set => this.linkAttributeCountLimit = value; - } - - internal static void Reset() - { - Instance = new SdkConfiguration(); - } -} diff --git a/src/OpenTelemetry.Exporter.OpenTelemetryProtocol/Implementation/ActivityExtensions.cs b/src/OpenTelemetry.Exporter.OpenTelemetryProtocol/Implementation/ActivityExtensions.cs index 90a2007a669..9cd89366009 100644 --- a/src/OpenTelemetry.Exporter.OpenTelemetryProtocol/Implementation/ActivityExtensions.cs +++ b/src/OpenTelemetry.Exporter.OpenTelemetryProtocol/Implementation/ActivityExtensions.cs @@ -24,7 +24,6 @@ using System.Runtime.CompilerServices; using Google.Protobuf; using Google.Protobuf.Collections; -using OpenTelemetry.Configuration; using OpenTelemetry.Internal; using OpenTelemetry.Proto.Collector.Trace.V1; using OpenTelemetry.Proto.Common.V1; @@ -42,6 +41,7 @@ internal static class ActivityExtensions internal static void AddBatch( this ExportTraceServiceRequest request, + SdkLimitOptions sdkLimitOptions, Resource processResource, in Batch activityBatch) { @@ -54,7 +54,7 @@ internal static void AddBatch( foreach (var activity in activityBatch) { - Span span = activity.ToOtlpSpan(); + Span span = activity.ToOtlpSpan(sdkLimitOptions); if (span == null) { OpenTelemetryProtocolExporterEventSource.Log.CouldNotTranslateActivity( @@ -116,7 +116,7 @@ internal static ScopeSpans GetSpanListFromPool(string name, string version) } [MethodImpl(MethodImplOptions.AggressiveInlining)] - internal static Span ToOtlpSpan(this Activity activity) + internal static Span ToOtlpSpan(this Activity activity, SdkLimitOptions sdkLimitOptions) { if (activity.IdFormat != ActivityIdFormat.W3C) { @@ -157,9 +157,10 @@ internal static Span ToOtlpSpan(this Activity activity) TagEnumerationState otlpTags = new() { + SdkLimitOptions = sdkLimitOptions, Span = otlpSpan, }; - otlpTags.EnumerateTags(activity, SdkConfiguration.Instance.SpanAttributeCountLimit ?? int.MaxValue); + otlpTags.EnumerateTags(activity, sdkLimitOptions.SpanAttributeCountLimit ?? int.MaxValue); if (activity.Kind == ActivityKind.Client || activity.Kind == ActivityKind.Producer) { @@ -180,15 +181,17 @@ internal static Span ToOtlpSpan(this Activity activity) EventEnumerationState otlpEvents = new() { + SdkLimitOptions = sdkLimitOptions, Span = otlpSpan, }; - otlpEvents.EnumerateEvents(activity, SdkConfiguration.Instance.SpanEventCountLimit ?? int.MaxValue); + otlpEvents.EnumerateEvents(activity, sdkLimitOptions.SpanEventCountLimit ?? int.MaxValue); LinkEnumerationState otlpLinks = new() { + SdkLimitOptions = sdkLimitOptions, Span = otlpSpan, }; - otlpLinks.EnumerateLinks(activity, SdkConfiguration.Instance.SpanLinkCountLimit ?? int.MaxValue); + otlpLinks.EnumerateLinks(activity, sdkLimitOptions.SpanLinkCountLimit ?? int.MaxValue); return otlpSpan; } @@ -236,7 +239,7 @@ private static OtlpTrace.Status ToOtlpStatus(this Activity activity, ref TagEnum } [MethodImpl(MethodImplOptions.AggressiveInlining)] - private static Span.Types.Link ToOtlpLink(in ActivityLink activityLink) + private static Span.Types.Link ToOtlpLink(in ActivityLink activityLink, SdkLimitOptions sdkLimitOptions) { byte[] traceIdBytes = new byte[16]; byte[] spanIdBytes = new byte[8]; @@ -250,10 +253,10 @@ private static Span.Types.Link ToOtlpLink(in ActivityLink activityLink) SpanId = UnsafeByteOperations.UnsafeWrap(spanIdBytes), }; - int maxTags = SdkConfiguration.Instance.LinkAttributeCountLimit ?? int.MaxValue; + int maxTags = sdkLimitOptions.SpanLinkAttributeCountLimit ?? int.MaxValue; foreach (ref readonly var tag in activityLink.EnumerateTagObjects()) { - if (OtlpKeyValueTransformer.Instance.TryTransformTag(tag, out var attribute, SdkConfiguration.Instance.AttributeValueLengthLimit)) + if (OtlpKeyValueTransformer.Instance.TryTransformTag(tag, out var attribute, sdkLimitOptions.AttributeValueLengthLimit)) { if (otlpLink.Attributes.Count < maxTags) { @@ -270,7 +273,7 @@ private static Span.Types.Link ToOtlpLink(in ActivityLink activityLink) } [MethodImpl(MethodImplOptions.AggressiveInlining)] - private static Span.Types.Event ToOtlpEvent(in ActivityEvent activityEvent) + private static Span.Types.Event ToOtlpEvent(in ActivityEvent activityEvent, SdkLimitOptions sdkLimitOptions) { var otlpEvent = new Span.Types.Event { @@ -278,10 +281,10 @@ private static Span.Types.Event ToOtlpEvent(in ActivityEvent activityEvent) TimeUnixNano = (ulong)activityEvent.Timestamp.ToUnixTimeNanoseconds(), }; - int maxTags = SdkConfiguration.Instance.EventAttributeCountLimit ?? int.MaxValue; + int maxTags = sdkLimitOptions.SpanEventAttributeCountLimit ?? int.MaxValue; foreach (ref readonly var tag in activityEvent.EnumerateTagObjects()) { - if (OtlpKeyValueTransformer.Instance.TryTransformTag(tag, out var attribute, SdkConfiguration.Instance.AttributeValueLengthLimit)) + if (OtlpKeyValueTransformer.Instance.TryTransformTag(tag, out var attribute, sdkLimitOptions.AttributeValueLengthLimit)) { if (otlpEvent.Attributes.Count < maxTags) { @@ -320,6 +323,8 @@ private static Action, int> CreateRepeatedFieldOfSpanSetCoun private struct TagEnumerationState : PeerServiceResolver.IPeerServiceState { + public SdkLimitOptions SdkLimitOptions; + public Span Span; public string StatusCode; @@ -357,7 +362,7 @@ public void EnumerateTags(Activity activity, int maxTags) continue; } - if (OtlpKeyValueTransformer.Instance.TryTransformTag(tag, out var attribute, SdkConfiguration.Instance.AttributeValueLengthLimit)) + if (OtlpKeyValueTransformer.Instance.TryTransformTag(tag, out var attribute, this.SdkLimitOptions.AttributeValueLengthLimit)) { if (this.Span.Attributes.Count < maxTags) { @@ -384,6 +389,8 @@ public void EnumerateTags(Activity activity, int maxTags) private struct EventEnumerationState { + public SdkLimitOptions SdkLimitOptions; + public Span Span; public void EnumerateEvents(Activity activity, int maxEvents) @@ -392,7 +399,7 @@ public void EnumerateEvents(Activity activity, int maxEvents) { if (this.Span.Events.Count < maxEvents) { - this.Span.Events.Add(ToOtlpEvent(in @event)); + this.Span.Events.Add(ToOtlpEvent(in @event, this.SdkLimitOptions)); } else { @@ -404,6 +411,8 @@ public void EnumerateEvents(Activity activity, int maxEvents) private struct LinkEnumerationState { + public SdkLimitOptions SdkLimitOptions; + public Span Span; public void EnumerateLinks(Activity activity, int maxLinks) @@ -412,7 +421,7 @@ public void EnumerateLinks(Activity activity, int maxLinks) { if (this.Span.Links.Count < maxLinks) { - this.Span.Links.Add(ToOtlpLink(in link)); + this.Span.Links.Add(ToOtlpLink(in link, this.SdkLimitOptions)); } else { diff --git a/src/OpenTelemetry.Exporter.OpenTelemetryProtocol/Implementation/LogRecordExtensions.cs b/src/OpenTelemetry.Exporter.OpenTelemetryProtocol/Implementation/LogRecordExtensions.cs index b7f0d206dc6..404b878cd71 100644 --- a/src/OpenTelemetry.Exporter.OpenTelemetryProtocol/Implementation/LogRecordExtensions.cs +++ b/src/OpenTelemetry.Exporter.OpenTelemetryProtocol/Implementation/LogRecordExtensions.cs @@ -18,7 +18,6 @@ using System.Collections.Generic; using System.Runtime.CompilerServices; using Google.Protobuf; -using Google.Protobuf.Collections; using OpenTelemetry.Internal; using OpenTelemetry.Logs; using OpenTelemetry.Trace; @@ -38,6 +37,7 @@ internal static class LogRecordExtensions internal static void AddBatch( this OtlpCollector.ExportLogsServiceRequest request, + SdkLimitOptions sdkLimitOptions, OtlpResource.Resource processResource, in Batch logRecordBatch) { @@ -52,7 +52,7 @@ internal static void AddBatch( foreach (var logRecord in logRecordBatch) { - var otlpLogRecord = logRecord.ToOtlpLog(); + var otlpLogRecord = logRecord.ToOtlpLog(sdkLimitOptions); if (otlpLogRecord != null) { var instrumentationScope = logRecord.InstrumentationScope; @@ -105,7 +105,7 @@ internal static void AddBatch( } [MethodImpl(MethodImplOptions.AggressiveInlining)] - internal static OtlpLogs.LogRecord ToOtlpLog(this LogRecord logRecord) + internal static OtlpLogs.LogRecord ToOtlpLog(this LogRecord logRecord, SdkLimitOptions sdkLimitOptions) { OtlpLogs.LogRecord otlpLogRecord = null; @@ -130,6 +130,11 @@ internal static OtlpLogs.LogRecord ToOtlpLog(this LogRecord logRecord) } } + var attributeValueLengthLimit = sdkLimitOptions.AttributeValueLengthLimit; + var attributeCountLimit = sdkLimitOptions.AttributeCountLimit ?? int.MaxValue; + + // First add the generic attributes like category, eventid and exception, so they are less likely being dropped because of AttributeCountLimit + if (!string.IsNullOrEmpty(logRecord.CategoryName)) { // TODO: @@ -137,7 +142,24 @@ internal static OtlpLogs.LogRecord ToOtlpLog(this LogRecord logRecord) // if it makes it to log data model. // https://github.com/open-telemetry/opentelemetry-specification/issues/2398 // 2. Confirm if this name for attribute is good. - otlpLogRecord.Attributes.AddStringAttribute("dotnet.ilogger.category", logRecord.CategoryName); + otlpLogRecord.AddStringAttribute("dotnet.ilogger.category", logRecord.CategoryName, attributeValueLengthLimit, attributeCountLimit); + } + + if (logRecord.EventId.Id != default) + { + otlpLogRecord.AddIntAttribute(nameof(logRecord.EventId.Id), logRecord.EventId.Id, attributeCountLimit); + } + + if (!string.IsNullOrEmpty(logRecord.EventId.Name)) + { + otlpLogRecord.AddStringAttribute(nameof(logRecord.EventId.Name), logRecord.EventId.Name, attributeValueLengthLimit, attributeCountLimit); + } + + if (logRecord.Exception != null) + { + otlpLogRecord.AddStringAttribute(SemanticConventions.AttributeExceptionType, logRecord.Exception.GetType().Name, attributeValueLengthLimit, attributeCountLimit); + otlpLogRecord.AddStringAttribute(SemanticConventions.AttributeExceptionMessage, logRecord.Exception.Message, attributeValueLengthLimit, attributeCountLimit); + otlpLogRecord.AddStringAttribute(SemanticConventions.AttributeExceptionStacktrace, logRecord.Exception.ToInvariantString(), attributeValueLengthLimit, attributeCountLimit); } bool bodyPopulatedFromFormattedMessage = false; @@ -158,30 +180,13 @@ internal static OtlpLogs.LogRecord ToOtlpLog(this LogRecord logRecord) { otlpLogRecord.Body = new OtlpCommon.AnyValue { StringValue = attribute.Value as string }; } - else if (OtlpKeyValueTransformer.Instance.TryTransformTag(attribute, out var result)) + else if (OtlpKeyValueTransformer.Instance.TryTransformTag(attribute, out var result, attributeValueLengthLimit)) { - otlpLogRecord.Attributes.Add(result); + otlpLogRecord.AddAttribute(result, attributeCountLimit); } } } - if (logRecord.EventId.Id != default) - { - otlpLogRecord.Attributes.AddIntAttribute(nameof(logRecord.EventId.Id), logRecord.EventId.Id); - } - - if (!string.IsNullOrEmpty(logRecord.EventId.Name)) - { - otlpLogRecord.Attributes.AddStringAttribute(nameof(logRecord.EventId.Name), logRecord.EventId.Name); - } - - if (logRecord.Exception != null) - { - otlpLogRecord.Attributes.AddStringAttribute(SemanticConventions.AttributeExceptionType, logRecord.Exception.GetType().Name); - otlpLogRecord.Attributes.AddStringAttribute(SemanticConventions.AttributeExceptionMessage, logRecord.Exception.Message); - otlpLogRecord.Attributes.AddStringAttribute(SemanticConventions.AttributeExceptionStacktrace, logRecord.Exception.ToInvariantString()); - } - if (logRecord.TraceId != default && logRecord.SpanId != default) { byte[] traceIdBytes = new byte[16]; @@ -204,9 +209,9 @@ void ProcessScope(LogRecordScope scope, OtlpLogs.LogRecord otlpLog) foreach (var scopeItem in scope) { var scopeItemWithDepthInfo = new KeyValuePair($"[Scope.{scopeDepth}]:{scopeItem.Key}", scopeItem.Value); - if (OtlpKeyValueTransformer.Instance.TryTransformTag(scopeItemWithDepthInfo, out var result)) + if (OtlpKeyValueTransformer.Instance.TryTransformTag(scopeItemWithDepthInfo, out var result, attributeValueLengthLimit)) { - otlpLog.Attributes.Add(result); + otlpLog.AddAttribute(result, attributeCountLimit); } } } @@ -219,22 +224,37 @@ void ProcessScope(LogRecordScope scope, OtlpLogs.LogRecord otlpLog) return otlpLogRecord; } - private static void AddStringAttribute(this RepeatedField repeatedField, string key, string value) + [MethodImpl(MethodImplOptions.AggressiveInlining)] + private static void AddAttribute(this OtlpLogs.LogRecord logRecord, OtlpCommon.KeyValue attribute, int maxAttributeCount) { - repeatedField.Add(new OtlpCommon.KeyValue + if (logRecord.Attributes.Count < maxAttributeCount) + { + logRecord.Attributes.Add(attribute); + } + else { - Key = key, - Value = new OtlpCommon.AnyValue { StringValue = value }, - }); + logRecord.DroppedAttributesCount++; + } } - private static void AddIntAttribute(this RepeatedField repeatedField, string key, int value) + [MethodImpl(MethodImplOptions.AggressiveInlining)] + private static void AddStringAttribute(this OtlpLogs.LogRecord logRecord, string key, string value, int? maxValueLength, int maxAttributeCount) { - repeatedField.Add(new OtlpCommon.KeyValue + var attributeItem = new KeyValuePair(key, value); + if (OtlpKeyValueTransformer.Instance.TryTransformTag(attributeItem, out var result, maxValueLength)) { - Key = key, - Value = new OtlpCommon.AnyValue { IntValue = value }, - }); + logRecord.AddAttribute(result, maxAttributeCount); + } + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + private static void AddIntAttribute(this OtlpLogs.LogRecord logRecord, string key, int value, int maxAttributeCount) + { + var attributeItem = new KeyValuePair(key, value); + if (OtlpKeyValueTransformer.Instance.TryTransformTag(attributeItem, out var result)) + { + logRecord.AddAttribute(result, maxAttributeCount); + } } [MethodImpl(MethodImplOptions.AggressiveInlining)] diff --git a/src/OpenTelemetry.Exporter.OpenTelemetryProtocol/Implementation/MetricItemExtensions.cs b/src/OpenTelemetry.Exporter.OpenTelemetryProtocol/Implementation/MetricItemExtensions.cs index 4933871e7b2..50ad352ddfc 100644 --- a/src/OpenTelemetry.Exporter.OpenTelemetryProtocol/Implementation/MetricItemExtensions.cs +++ b/src/OpenTelemetry.Exporter.OpenTelemetryProtocol/Implementation/MetricItemExtensions.cs @@ -257,6 +257,12 @@ internal static OtlpMetrics.Metric ToOtlpMetric(this Metric metric) dataPoint.Count = (ulong)metricPoint.GetHistogramCount(); dataPoint.Sum = metricPoint.GetHistogramSum(); + if (metricPoint.HasMinMax()) + { + dataPoint.Min = metricPoint.GetHistogramMin(); + dataPoint.Max = metricPoint.GetHistogramMax(); + } + foreach (var histogramMeasurement in metricPoint.GetHistogramBuckets()) { dataPoint.BucketCounts.Add((ulong)histogramMeasurement.BucketCount); diff --git a/src/OpenTelemetry.Exporter.OpenTelemetryProtocol/Implementation/OpenTelemetryProtocolExporterEventSource.cs b/src/OpenTelemetry.Exporter.OpenTelemetryProtocol/Implementation/OpenTelemetryProtocolExporterEventSource.cs index 17db6324a1b..80351d19f28 100644 --- a/src/OpenTelemetry.Exporter.OpenTelemetryProtocol/Implementation/OpenTelemetryProtocolExporterEventSource.cs +++ b/src/OpenTelemetry.Exporter.OpenTelemetryProtocol/Implementation/OpenTelemetryProtocolExporterEventSource.cs @@ -21,7 +21,7 @@ namespace OpenTelemetry.Exporter.OpenTelemetryProtocol.Implementation { [EventSource(Name = "OpenTelemetry-Exporter-OpenTelemetryProtocol")] - internal class OpenTelemetryProtocolExporterEventSource : EventSource + internal sealed class OpenTelemetryProtocolExporterEventSource : EventSource { public static readonly OpenTelemetryProtocolExporterEventSource Log = new(); diff --git a/src/OpenTelemetry.Exporter.OpenTelemetryProtocol/Implementation/SdkLimitOptions.cs b/src/OpenTelemetry.Exporter.OpenTelemetryProtocol/Implementation/SdkLimitOptions.cs new file mode 100644 index 00000000000..305af1780d5 --- /dev/null +++ b/src/OpenTelemetry.Exporter.OpenTelemetryProtocol/Implementation/SdkLimitOptions.cs @@ -0,0 +1,125 @@ +// +// Copyright The OpenTelemetry Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +using System; +using Microsoft.Extensions.Configuration; +using OpenTelemetry.Internal; + +namespace OpenTelemetry.Exporter.OpenTelemetryProtocol.Implementation; + +internal sealed class SdkLimitOptions +{ + private int? spanAttributeValueLengthLimit; + private int? spanAttributeCountLimit; + private int? spanEventAttributeCountLimit; + private int? spanLinkAttributeCountLimit; + + internal SdkLimitOptions() + : this(new ConfigurationBuilder().AddEnvironmentVariables().Build()) + { + } + + internal SdkLimitOptions(IConfiguration configuration) + { + // https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/sdk-environment-variables.md#attribute-limits + SetIntConfigValue(configuration, "OTEL_ATTRIBUTE_VALUE_LENGTH_LIMIT", value => this.AttributeValueLengthLimit = value); + SetIntConfigValue(configuration, "OTEL_ATTRIBUTE_COUNT_LIMIT", value => this.AttributeCountLimit = value); + + // https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/sdk-environment-variables.md#span-limits + SetIntConfigValue(configuration, "OTEL_SPAN_ATTRIBUTE_VALUE_LENGTH_LIMIT", value => this.SpanAttributeValueLengthLimit = value); + SetIntConfigValue(configuration, "OTEL_SPAN_ATTRIBUTE_COUNT_LIMIT", value => this.SpanAttributeCountLimit = value); + SetIntConfigValue(configuration, "OTEL_SPAN_EVENT_COUNT_LIMIT", value => this.SpanEventCountLimit = value); + SetIntConfigValue(configuration, "OTEL_SPAN_LINK_COUNT_LIMIT", value => this.SpanLinkCountLimit = value); + SetIntConfigValue(configuration, "OTEL_EVENT_ATTRIBUTE_COUNT_LIMIT", value => this.SpanEventAttributeCountLimit = value); + SetIntConfigValue(configuration, "OTEL_LINK_ATTRIBUTE_COUNT_LIMIT", value => this.SpanLinkAttributeCountLimit = value); + } + + /// + /// Gets or sets the maximum allowed attribute value size. + /// + public int? AttributeValueLengthLimit { get; set; } + + /// + /// Gets or sets the maximum allowed attribute count. + /// + public int? AttributeCountLimit { get; set; } + + /// + /// Gets or sets the maximum allowed span attribute value size. + /// + /// + /// Note: Overrides the setting for spans if specified. + /// + public int? SpanAttributeValueLengthLimit + { + get => this.spanAttributeValueLengthLimit ?? this.AttributeValueLengthLimit; + set => this.spanAttributeValueLengthLimit = value; + } + + /// + /// Gets or sets the maximum allowed span attribute count. + /// + /// + /// Note: Overrides the setting for spans if specified. + /// + public int? SpanAttributeCountLimit + { + get => this.spanAttributeCountLimit ?? this.AttributeCountLimit; + set => this.spanAttributeCountLimit = value; + } + + /// + /// Gets or sets the maximum allowed span event count. + /// + public int? SpanEventCountLimit { get; set; } + + /// + /// Gets or sets the maximum allowed span link count. + /// + public int? SpanLinkCountLimit { get; set; } + + /// + /// Gets or sets the maximum allowed span event attribute count. + /// + /// + /// Note: Overrides the setting for span events if specified. + /// + public int? SpanEventAttributeCountLimit + { + get => this.spanEventAttributeCountLimit ?? this.SpanAttributeCountLimit; + set => this.spanEventAttributeCountLimit = value; + } + + /// + /// Gets or sets the maximum allowed span link attribute count. + /// + /// + /// Note: Overrides the setting for span links if specified. + /// + public int? SpanLinkAttributeCountLimit + { + get => this.spanLinkAttributeCountLimit ?? this.SpanAttributeCountLimit; + set => this.spanLinkAttributeCountLimit = value; + } + + private static void SetIntConfigValue(IConfiguration configuration, string key, Action setter) + { + if (configuration.TryGetIntValue(key, out var result)) + { + setter(result); + } + } +} diff --git a/src/OpenTelemetry.Exporter.OpenTelemetryProtocol/OpenTelemetry.Exporter.OpenTelemetryProtocol.csproj b/src/OpenTelemetry.Exporter.OpenTelemetryProtocol/OpenTelemetry.Exporter.OpenTelemetryProtocol.csproj index 529e72b586f..995d2b02298 100644 --- a/src/OpenTelemetry.Exporter.OpenTelemetryProtocol/OpenTelemetry.Exporter.OpenTelemetryProtocol.csproj +++ b/src/OpenTelemetry.Exporter.OpenTelemetryProtocol/OpenTelemetry.Exporter.OpenTelemetryProtocol.csproj @@ -34,7 +34,7 @@ - + diff --git a/src/OpenTelemetry.Exporter.OpenTelemetryProtocol/OtlpExporterOptions.cs b/src/OpenTelemetry.Exporter.OpenTelemetryProtocol/OtlpExporterOptions.cs index 936da811fa4..2bf0f7e980f 100644 --- a/src/OpenTelemetry.Exporter.OpenTelemetryProtocol/OtlpExporterOptions.cs +++ b/src/OpenTelemetry.Exporter.OpenTelemetryProtocol/OtlpExporterOptions.cs @@ -17,6 +17,7 @@ using System; using System.Diagnostics; using System.Net.Http; +using Microsoft.Extensions.Configuration; using OpenTelemetry.Internal; using OpenTelemetry.Metrics; using OpenTelemetry.Trace; @@ -51,32 +52,33 @@ public class OtlpExporterOptions /// Initializes a new instance of the class. /// public OtlpExporterOptions() + : this(new ConfigurationBuilder().AddEnvironmentVariables().Build()) { - if (EnvironmentVariableHelper.LoadUri(EndpointEnvVarName, out Uri parsedEndpoint)) + } + + internal OtlpExporterOptions(IConfiguration configuration) + { + if (configuration.TryGetUriValue(EndpointEnvVarName, out var endpoint)) { - this.endpoint = parsedEndpoint; + this.endpoint = endpoint; } - if (EnvironmentVariableHelper.LoadString(HeadersEnvVarName, out string headersEnvVar)) + if (configuration.TryGetStringValue(HeadersEnvVarName, out var headers)) { - this.Headers = headersEnvVar; + this.Headers = headers; } - if (EnvironmentVariableHelper.LoadNumeric(TimeoutEnvVarName, out int timeout)) + if (configuration.TryGetIntValue(TimeoutEnvVarName, out var timeout)) { this.TimeoutMilliseconds = timeout; } - if (EnvironmentVariableHelper.LoadString(ProtocolEnvVarName, out string protocolEnvVar)) + if (configuration.TryGetValue( + ProtocolEnvVarName, + OtlpExportProtocolParser.TryParse, + out var protocol)) { - if (OtlpExportProtocolParser.TryParse(protocolEnvVar, out var protocol)) - { - this.Protocol = protocol; - } - else - { - throw new FormatException($"{ProtocolEnvVarName} environment variable has an invalid value: '{protocolEnvVar}'"); - } + this.Protocol = protocol; } this.HttpClientFactory = this.DefaultHttpClientFactory = () => @@ -86,6 +88,8 @@ public OtlpExporterOptions() Timeout = TimeSpan.FromMilliseconds(this.TimeoutMilliseconds), }; }; + + this.BatchExportProcessorOptions = new BatchExportActivityProcessorOptions(configuration); } /// @@ -140,7 +144,7 @@ public Uri Endpoint /// /// Gets or sets the BatchExportProcessor options. Ignored unless ExportProcessorType is Batch. /// - public BatchExportProcessorOptions BatchExportProcessorOptions { get; set; } = new BatchExportActivityProcessorOptions(); + public BatchExportProcessorOptions BatchExportProcessorOptions { get; set; } /// /// Gets or sets the factory function called to create the using System; +using System.Diagnostics; using OpenTelemetry.Exporter.OpenTelemetryProtocol.Implementation; using OpenTelemetry.Exporter.OpenTelemetryProtocol.Implementation.ExportClient; using OpenTelemetry.Logs; @@ -27,8 +28,9 @@ namespace OpenTelemetry.Exporter /// Exporter consuming and exporting the data using /// the OpenTelemetry protocol (OTLP). /// - internal class OtlpLogExporter : BaseExporter + internal sealed class OtlpLogExporter : BaseExporter { + private readonly SdkLimitOptions sdkLimitOptions; private readonly IExportClient exportClient; private OtlpResource.Resource processResource; @@ -38,24 +40,33 @@ internal class OtlpLogExporter : BaseExporter /// /// Configuration options for the exporter. public OtlpLogExporter(OtlpExporterOptions options) - : this(options, null) + : this(options, new(), null) { } /// /// Initializes a new instance of the class. /// - /// Configuration options for the exporter. + /// Configuration options for the exporter. + /// . /// Client used for sending export request. - internal OtlpLogExporter(OtlpExporterOptions options, IExportClient exportClient = null) + internal OtlpLogExporter( + OtlpExporterOptions exporterOptions, + SdkLimitOptions sdkLimitOptions, + IExportClient exportClient = null) { + Debug.Assert(exporterOptions != null, "exporterOptions was null"); + Debug.Assert(sdkLimitOptions != null, "sdkLimitOptions was null"); + + this.sdkLimitOptions = sdkLimitOptions; + if (exportClient != null) { this.exportClient = exportClient; } else { - this.exportClient = options.GetLogExportClient(); + this.exportClient = exporterOptions.GetLogExportClient(); } } @@ -71,7 +82,7 @@ public override ExportResult Export(in Batch logRecordBatch) try { - request.AddBatch(this.ProcessResource, logRecordBatch); + request.AddBatch(this.sdkLimitOptions, this.ProcessResource, logRecordBatch); if (!this.exportClient.SendExportRequest(request)) { diff --git a/src/OpenTelemetry.Exporter.OpenTelemetryProtocol/OtlpMetricExporterExtensions.cs b/src/OpenTelemetry.Exporter.OpenTelemetryProtocol/OtlpMetricExporterExtensions.cs index d3d45402c19..741314ab8b4 100644 --- a/src/OpenTelemetry.Exporter.OpenTelemetryProtocol/OtlpMetricExporterExtensions.cs +++ b/src/OpenTelemetry.Exporter.OpenTelemetryProtocol/OtlpMetricExporterExtensions.cs @@ -60,10 +60,15 @@ public static MeterProviderBuilder AddOtlpExporter( name ??= Options.DefaultName; - if (configureExporter != null) + builder.ConfigureServices(services => { - builder.ConfigureServices(services => services.Configure(name, configureExporter)); - } + if (configureExporter != null) + { + services.Configure(name, configureExporter); + } + + services.RegisterOptionsFactory(configuration => new OtlpExporterOptions(configuration)); + }); return builder.ConfigureBuilder((sp, builder) => { @@ -106,6 +111,11 @@ public static MeterProviderBuilder AddOtlpExporter( name ??= Options.DefaultName; + builder.ConfigureServices(services => + { + services.RegisterOptionsFactory(configuration => new OtlpExporterOptions(configuration)); + }); + return builder.ConfigureBuilder((sp, builder) => { var exporterOptions = sp.GetRequiredService>().Get(name); diff --git a/src/OpenTelemetry.Exporter.OpenTelemetryProtocol/OtlpTraceExporter.cs b/src/OpenTelemetry.Exporter.OpenTelemetryProtocol/OtlpTraceExporter.cs index 01cb49bd4f8..156c366e6c9 100644 --- a/src/OpenTelemetry.Exporter.OpenTelemetryProtocol/OtlpTraceExporter.cs +++ b/src/OpenTelemetry.Exporter.OpenTelemetryProtocol/OtlpTraceExporter.cs @@ -29,6 +29,7 @@ namespace OpenTelemetry.Exporter /// public class OtlpTraceExporter : BaseExporter { + private readonly SdkLimitOptions sdkLimitOptions; private readonly IExportClient exportClient; private OtlpResource.Resource processResource; @@ -38,24 +39,33 @@ public class OtlpTraceExporter : BaseExporter /// /// Configuration options for the export. public OtlpTraceExporter(OtlpExporterOptions options) - : this(options, null) + : this(options, new(), null) { } /// /// Initializes a new instance of the class. /// - /// Configuration options for the export. + /// . + /// . /// Client used for sending export request. - internal OtlpTraceExporter(OtlpExporterOptions options, IExportClient exportClient = null) + internal OtlpTraceExporter( + OtlpExporterOptions exporterOptions, + SdkLimitOptions sdkLimitOptions, + IExportClient exportClient = null) { + Debug.Assert(exporterOptions != null, "exporterOptions was null"); + Debug.Assert(sdkLimitOptions != null, "sdkLimitOptions was null"); + + this.sdkLimitOptions = sdkLimitOptions; + if (exportClient != null) { this.exportClient = exportClient; } else { - this.exportClient = options.GetTraceExportClient(); + this.exportClient = exporterOptions.GetTraceExportClient(); } } @@ -71,7 +81,7 @@ public override ExportResult Export(in Batch activityBatch) try { - request.AddBatch(this.ProcessResource, activityBatch); + request.AddBatch(this.sdkLimitOptions, this.ProcessResource, activityBatch); if (!this.exportClient.SendExportRequest(request)) { diff --git a/src/OpenTelemetry.Exporter.OpenTelemetryProtocol/OtlpTraceExporterHelperExtensions.cs b/src/OpenTelemetry.Exporter.OpenTelemetryProtocol/OtlpTraceExporterHelperExtensions.cs index 807b7633f2a..889fe7fca5d 100644 --- a/src/OpenTelemetry.Exporter.OpenTelemetryProtocol/OtlpTraceExporterHelperExtensions.cs +++ b/src/OpenTelemetry.Exporter.OpenTelemetryProtocol/OtlpTraceExporterHelperExtensions.cs @@ -19,6 +19,7 @@ using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Options; using OpenTelemetry.Exporter; +using OpenTelemetry.Exporter.OpenTelemetryProtocol.Implementation; using OpenTelemetry.Internal; namespace OpenTelemetry.Trace @@ -61,28 +62,40 @@ public static TracerProviderBuilder AddOtlpExporter( name ??= Options.DefaultName; - if (configure != null) + builder.ConfigureServices(services => { - builder.ConfigureServices(services => services.Configure(name, configure)); - } + if (configure != null) + { + services.Configure(name, configure); + } + + services.RegisterOptionsFactory(configuration => new SdkLimitOptions(configuration)); + services.RegisterOptionsFactory(configuration => new OtlpExporterOptions(configuration)); + }); return builder.ConfigureBuilder((sp, builder) => { - var options = sp.GetRequiredService>().Get(name); + var exporterOptions = sp.GetRequiredService>().Get(name); + + // Note: Not using name here for SdkLimitOptions. There should + // only be one provider for a given service collection so + // SdkLimitOptions is treated as a single default instance. + var sdkOptionsManager = sp.GetRequiredService>().CurrentValue; - AddOtlpExporter(builder, options, sp); + AddOtlpExporter(builder, exporterOptions, sdkOptionsManager, sp); }); } internal static TracerProviderBuilder AddOtlpExporter( TracerProviderBuilder builder, OtlpExporterOptions exporterOptions, + SdkLimitOptions sdkLimitOptions, IServiceProvider serviceProvider, Func, BaseExporter> configureExporterInstance = null) { exporterOptions.TryEnableIHttpClientFactoryIntegration(serviceProvider, "OtlpTraceExporter"); - BaseExporter otlpExporter = new OtlpTraceExporter(exporterOptions); + BaseExporter otlpExporter = new OtlpTraceExporter(exporterOptions, sdkLimitOptions); if (configureExporterInstance != null) { diff --git a/src/OpenTelemetry.Exporter.OpenTelemetryProtocol/README.md b/src/OpenTelemetry.Exporter.OpenTelemetryProtocol/README.md index 5a2630438f7..b992147f196 100644 --- a/src/OpenTelemetry.Exporter.OpenTelemetryProtocol/README.md +++ b/src/OpenTelemetry.Exporter.OpenTelemetryProtocol/README.md @@ -77,14 +77,15 @@ supported environment variables. ## OTLP Logs -This package currently only supports exporting traces and metrics. Once the -[OTLP log data model](https://github.com/open-telemetry/opentelemetry-proto#maturity-level) -is deemed stable, the OTLP log exporter will be folded into this package. - -In the meantime, support for exporting logs is provided by installing the +This package currently only supports exporting traces and metrics. Support for +exporting logs is provided by installing the [`OpenTelemetry.Exporter.OpenTelemetryProtocol.Logs`](../OpenTelemetry.Exporter.OpenTelemetryProtocol.Logs/README.md) package. +Once the OTLP log exporter is stable, it'll be folded into this package. Check +[this](https://github.com/open-telemetry/opentelemetry-dotnet/milestone/35) +milestone for tracking. + ## Special case when using insecure channel If your application is targeting .NET Core 3.1, and you are using an insecure diff --git a/src/OpenTelemetry.Exporter.Prometheus.AspNetCore/.publicApi/net6.0/PublicAPI.Unshipped.txt b/src/OpenTelemetry.Exporter.Prometheus.AspNetCore/.publicApi/net6.0/PublicAPI.Unshipped.txt index 99bf4292632..0dd120b12da 100644 --- a/src/OpenTelemetry.Exporter.Prometheus.AspNetCore/.publicApi/net6.0/PublicAPI.Unshipped.txt +++ b/src/OpenTelemetry.Exporter.Prometheus.AspNetCore/.publicApi/net6.0/PublicAPI.Unshipped.txt @@ -8,12 +8,12 @@ OpenTelemetry.Exporter.PrometheusAspNetCoreOptions.ScrapeResponseCacheDurationMi OpenTelemetry.Exporter.PrometheusAspNetCoreOptions.ScrapeResponseCacheDurationMilliseconds.set -> void OpenTelemetry.Metrics.PrometheusExporterMeterProviderBuilderExtensions static Microsoft.AspNetCore.Builder.PrometheusExporterApplicationBuilderExtensions.UseOpenTelemetryPrometheusScrapingEndpoint(this Microsoft.AspNetCore.Builder.IApplicationBuilder app) -> Microsoft.AspNetCore.Builder.IApplicationBuilder -static Microsoft.AspNetCore.Builder.PrometheusExporterApplicationBuilderExtensions.UseOpenTelemetryPrometheusScrapingEndpoint(this Microsoft.AspNetCore.Builder.IApplicationBuilder app, OpenTelemetry.Metrics.MeterProvider meterProvider, System.Func predicate, string path, System.Action configureBranchedPipeline) -> Microsoft.AspNetCore.Builder.IApplicationBuilder +static Microsoft.AspNetCore.Builder.PrometheusExporterApplicationBuilderExtensions.UseOpenTelemetryPrometheusScrapingEndpoint(this Microsoft.AspNetCore.Builder.IApplicationBuilder app, OpenTelemetry.Metrics.MeterProvider meterProvider, System.Func predicate, string path, System.Action configureBranchedPipeline, string optionsName) -> Microsoft.AspNetCore.Builder.IApplicationBuilder static Microsoft.AspNetCore.Builder.PrometheusExporterApplicationBuilderExtensions.UseOpenTelemetryPrometheusScrapingEndpoint(this Microsoft.AspNetCore.Builder.IApplicationBuilder app, string path) -> Microsoft.AspNetCore.Builder.IApplicationBuilder static Microsoft.AspNetCore.Builder.PrometheusExporterApplicationBuilderExtensions.UseOpenTelemetryPrometheusScrapingEndpoint(this Microsoft.AspNetCore.Builder.IApplicationBuilder app, System.Func predicate) -> Microsoft.AspNetCore.Builder.IApplicationBuilder static Microsoft.AspNetCore.Builder.PrometheusExporterEndpointRouteBuilderExtensions.MapPrometheusScrapingEndpoint(this Microsoft.AspNetCore.Routing.IEndpointRouteBuilder endpoints) -> Microsoft.AspNetCore.Builder.IEndpointConventionBuilder -static Microsoft.AspNetCore.Builder.PrometheusExporterEndpointRouteBuilderExtensions.MapPrometheusScrapingEndpoint(this Microsoft.AspNetCore.Routing.IEndpointRouteBuilder endpoints, string path = null, OpenTelemetry.Metrics.MeterProvider meterProvider = null, System.Action configureBranchedPipeline = null) -> Microsoft.AspNetCore.Builder.IEndpointConventionBuilder static Microsoft.AspNetCore.Builder.PrometheusExporterEndpointRouteBuilderExtensions.MapPrometheusScrapingEndpoint(this Microsoft.AspNetCore.Routing.IEndpointRouteBuilder endpoints, string path) -> Microsoft.AspNetCore.Builder.IEndpointConventionBuilder +static Microsoft.AspNetCore.Builder.PrometheusExporterEndpointRouteBuilderExtensions.MapPrometheusScrapingEndpoint(this Microsoft.AspNetCore.Routing.IEndpointRouteBuilder endpoints, string path, OpenTelemetry.Metrics.MeterProvider meterProvider, System.Action configureBranchedPipeline, string optionsName) -> Microsoft.AspNetCore.Builder.IEndpointConventionBuilder static OpenTelemetry.Metrics.PrometheusExporterMeterProviderBuilderExtensions.AddPrometheusExporter(this OpenTelemetry.Metrics.MeterProviderBuilder builder) -> OpenTelemetry.Metrics.MeterProviderBuilder static OpenTelemetry.Metrics.PrometheusExporterMeterProviderBuilderExtensions.AddPrometheusExporter(this OpenTelemetry.Metrics.MeterProviderBuilder builder, string name, System.Action configure) -> OpenTelemetry.Metrics.MeterProviderBuilder static OpenTelemetry.Metrics.PrometheusExporterMeterProviderBuilderExtensions.AddPrometheusExporter(this OpenTelemetry.Metrics.MeterProviderBuilder builder, System.Action configure) -> OpenTelemetry.Metrics.MeterProviderBuilder diff --git a/src/OpenTelemetry.Exporter.Prometheus.AspNetCore/CHANGELOG.md b/src/OpenTelemetry.Exporter.Prometheus.AspNetCore/CHANGELOG.md index 14f0c046661..89f34d18923 100644 --- a/src/OpenTelemetry.Exporter.Prometheus.AspNetCore/CHANGELOG.md +++ b/src/OpenTelemetry.Exporter.Prometheus.AspNetCore/CHANGELOG.md @@ -2,6 +2,14 @@ ## Unreleased +* Support named options in `UseOpenTelemetryPrometheusScrapingEndpoint` & + `MapPrometheusScrapingEndpoint` extensions + ([#3780](https://github.com/open-telemetry/opentelemetry-dotnet/pull/3780)) + +## 1.4.0-beta.2 + +Released 2022-Oct-17 + * Changed configuration class name from `PrometheusExporterOptions` to `PrometheusAspNetCoreOptions` ([#3717](https://github.com/open-telemetry/opentelemetry-dotnet/pull/3717)) diff --git a/src/OpenTelemetry.Exporter.Prometheus.AspNetCore/PrometheusExporterApplicationBuilderExtensions.cs b/src/OpenTelemetry.Exporter.Prometheus.AspNetCore/PrometheusExporterApplicationBuilderExtensions.cs index 91678fa0ef8..d3bb6666a6a 100644 --- a/src/OpenTelemetry.Exporter.Prometheus.AspNetCore/PrometheusExporterApplicationBuilderExtensions.cs +++ b/src/OpenTelemetry.Exporter.Prometheus.AspNetCore/PrometheusExporterApplicationBuilderExtensions.cs @@ -42,7 +42,7 @@ public static class PrometheusExporterApplicationBuilderExtensions /// A reference to the original for chaining calls. public static IApplicationBuilder UseOpenTelemetryPrometheusScrapingEndpoint(this IApplicationBuilder app) - => UseOpenTelemetryPrometheusScrapingEndpoint(app, meterProvider: null, predicate: null, path: null, configureBranchedPipeline: null); + => UseOpenTelemetryPrometheusScrapingEndpoint(app, meterProvider: null, predicate: null, path: null, configureBranchedPipeline: null, optionsName: null); /// /// Adds OpenTelemetry Prometheus scraping endpoint middleware to an @@ -58,7 +58,7 @@ public static IApplicationBuilder UseOpenTelemetryPrometheusScrapingEndpoint(thi public static IApplicationBuilder UseOpenTelemetryPrometheusScrapingEndpoint(this IApplicationBuilder app, string path) { Guard.ThrowIfNull(path); - return UseOpenTelemetryPrometheusScrapingEndpoint(app, meterProvider: null, predicate: null, path: path, configureBranchedPipeline: null); + return UseOpenTelemetryPrometheusScrapingEndpoint(app, meterProvider: null, predicate: null, path: path, configureBranchedPipeline: null, optionsName: null); } /// @@ -76,7 +76,7 @@ public static IApplicationBuilder UseOpenTelemetryPrometheusScrapingEndpoint(thi public static IApplicationBuilder UseOpenTelemetryPrometheusScrapingEndpoint(this IApplicationBuilder app, Func predicate) { Guard.ThrowIfNull(predicate); - return UseOpenTelemetryPrometheusScrapingEndpoint(app, meterProvider: null, predicate: predicate, path: null, configureBranchedPipeline: null); + return UseOpenTelemetryPrometheusScrapingEndpoint(app, meterProvider: null, predicate: predicate, path: null, configureBranchedPipeline: null, optionsName: null); } /// @@ -101,6 +101,8 @@ public static IApplicationBuilder UseOpenTelemetryPrometheusScrapingEndpoint(thi /// Optional callback to /// configure the branched pipeline. Called before registration of the /// Prometheus middleware. + /// Optional name used to retrieve . /// A reference to the original for chaining calls. public static IApplicationBuilder UseOpenTelemetryPrometheusScrapingEndpoint( @@ -108,7 +110,8 @@ public static IApplicationBuilder UseOpenTelemetryPrometheusScrapingEndpoint( MeterProvider meterProvider, Func predicate, string path, - Action configureBranchedPipeline) + Action configureBranchedPipeline, + string optionsName) { // Note: Order is important here. MeterProvider is accessed before // GetOptions so that any changes made to @@ -120,7 +123,7 @@ public static IApplicationBuilder UseOpenTelemetryPrometheusScrapingEndpoint( { if (path == null) { - var options = app.ApplicationServices.GetRequiredService>().Value; + var options = app.ApplicationServices.GetRequiredService>().Get(optionsName ?? Options.DefaultName); path = options.ScrapeEndpointPath ?? PrometheusAspNetCoreOptions.DefaultScrapeEndpointPath; } diff --git a/src/OpenTelemetry.Exporter.Prometheus.AspNetCore/PrometheusExporterEndpointRouteBuilderExtensions.cs b/src/OpenTelemetry.Exporter.Prometheus.AspNetCore/PrometheusExporterEndpointRouteBuilderExtensions.cs index 95546da47b8..39e043afdfc 100644 --- a/src/OpenTelemetry.Exporter.Prometheus.AspNetCore/PrometheusExporterEndpointRouteBuilderExtensions.cs +++ b/src/OpenTelemetry.Exporter.Prometheus.AspNetCore/PrometheusExporterEndpointRouteBuilderExtensions.cs @@ -42,7 +42,7 @@ public static class PrometheusExporterEndpointRouteBuilderExtensions /// middleware to. /// A convention routes for the Prometheus scraping endpoint. public static IEndpointConventionBuilder MapPrometheusScrapingEndpoint(this IEndpointRouteBuilder endpoints) - => MapPrometheusScrapingEndpoint(endpoints, path: null, meterProvider: null, configureBranchedPipeline: null); + => MapPrometheusScrapingEndpoint(endpoints, path: null, meterProvider: null, configureBranchedPipeline: null, optionsName: null); /// /// Adds OpenTelemetry Prometheus scraping endpoint middleware to an @@ -55,7 +55,7 @@ public static IEndpointConventionBuilder MapPrometheusScrapingEndpoint(this IEnd public static IEndpointConventionBuilder MapPrometheusScrapingEndpoint(this IEndpointRouteBuilder endpoints, string path) { Guard.ThrowIfNull(path); - return MapPrometheusScrapingEndpoint(endpoints, path, meterProvider: null, configureBranchedPipeline: null); + return MapPrometheusScrapingEndpoint(endpoints, path, meterProvider: null, configureBranchedPipeline: null, optionsName: null); } /// @@ -73,12 +73,15 @@ public static IEndpointConventionBuilder MapPrometheusScrapingEndpoint(this IEnd /// Optional callback to /// configure the branched pipeline. Called before registration of the /// Prometheus middleware. + /// Optional name used to retrieve . /// A convention routes for the Prometheus scraping endpoint. public static IEndpointConventionBuilder MapPrometheusScrapingEndpoint( this IEndpointRouteBuilder endpoints, - string path = null, - MeterProvider meterProvider = null, - Action configureBranchedPipeline = null) + string path, + MeterProvider meterProvider, + Action configureBranchedPipeline, + string optionsName) { var builder = endpoints.CreateApplicationBuilder(); @@ -90,7 +93,7 @@ public static IEndpointConventionBuilder MapPrometheusScrapingEndpoint( if (path == null) { - var options = endpoints.ServiceProvider.GetRequiredService>().Value; + var options = endpoints.ServiceProvider.GetRequiredService>().Get(optionsName ?? Options.DefaultName); path = options.ScrapeEndpointPath ?? PrometheusAspNetCoreOptions.DefaultScrapeEndpointPath; } diff --git a/src/OpenTelemetry.Exporter.Prometheus.AspNetCore/README.md b/src/OpenTelemetry.Exporter.Prometheus.AspNetCore/README.md index f4d4dbe4d17..1387fb09736 100644 --- a/src/OpenTelemetry.Exporter.Prometheus.AspNetCore/README.md +++ b/src/OpenTelemetry.Exporter.Prometheus.AspNetCore/README.md @@ -66,6 +66,10 @@ dotnet add package --prerelease OpenTelemetry.Exporter.Prometheus.AspNetCore && context.Connection.LocalPort == 5067); ``` + This can be used in combination with + [configuring multiple ports on the ASP.NET application](https://learn.microsoft.com/aspnet/core/fundamentals/servers/kestrel/endpoints) + to expose the scraping endpoint on a different port. + ## Configuration The `PrometheusExporter` can be configured using the `PrometheusAspNetCoreOptions` diff --git a/src/OpenTelemetry.Exporter.Prometheus.HttpListener/CHANGELOG.md b/src/OpenTelemetry.Exporter.Prometheus.HttpListener/CHANGELOG.md index 9cd72885912..57270498735 100644 --- a/src/OpenTelemetry.Exporter.Prometheus.HttpListener/CHANGELOG.md +++ b/src/OpenTelemetry.Exporter.Prometheus.HttpListener/CHANGELOG.md @@ -2,6 +2,10 @@ ## Unreleased +## 1.4.0-beta.2 + +Released 2022-Oct-17 + ## 1.4.0-beta.1 Released 2022-Sep-29 diff --git a/src/OpenTelemetry.Exporter.Prometheus.HttpListener/README.md b/src/OpenTelemetry.Exporter.Prometheus.HttpListener/README.md index 882203b2d77..8f3877fb312 100644 --- a/src/OpenTelemetry.Exporter.Prometheus.HttpListener/README.md +++ b/src/OpenTelemetry.Exporter.Prometheus.HttpListener/README.md @@ -7,6 +7,14 @@ An [OpenTelemetry Prometheus exporter](https://github.com/open-telemetry/opentel that configures an [HttpListener](https://docs.microsoft.com/dotnet/api/system.net.httplistener) instance for Prometheus to scrape. +**Warning**: this component is intended for dev inner-loop, there is no plan to +make it production ready. Production environments should use +[OpenTelemetry.Exporter.Prometheus.AspNetCore](../OpenTelemetry.Exporter.Prometheus.AspNetCore/README.md), +or a combination of +[OpenTelemetry.Exporter.OpenTelemetryProtocol](../OpenTelemetry.Exporter.OpenTelemetryProtocol/README.md) +and [OpenTelemetry +Collector](https://github.com/open-telemetry/opentelemetry-collector). + ## Prerequisite * [Get Prometheus](https://prometheus.io/docs/introduction/first_steps/) diff --git a/src/OpenTelemetry.Exporter.ZPages/CHANGELOG.md b/src/OpenTelemetry.Exporter.ZPages/CHANGELOG.md index 8ffc00815af..27760d5ac4e 100644 --- a/src/OpenTelemetry.Exporter.ZPages/CHANGELOG.md +++ b/src/OpenTelemetry.Exporter.ZPages/CHANGELOG.md @@ -2,6 +2,10 @@ ## Unreleased +## 1.0.0-rc9.8 + +Released 2022-Oct-17 + ## 1.0.0-rc9.7 Released 2022-Sep-29 diff --git a/src/OpenTelemetry.Exporter.ZPages/Implementation/ZPagesActivityAggregate.cs b/src/OpenTelemetry.Exporter.ZPages/Implementation/ZPagesActivityAggregate.cs index 842210b2473..2887989bbc0 100644 --- a/src/OpenTelemetry.Exporter.ZPages/Implementation/ZPagesActivityAggregate.cs +++ b/src/OpenTelemetry.Exporter.ZPages/Implementation/ZPagesActivityAggregate.cs @@ -22,7 +22,7 @@ namespace OpenTelemetry.Exporter.ZPages.Implementation /// /// Stores the activity information aggregated according to activity name. /// - internal class ZPagesActivityAggregate + internal sealed class ZPagesActivityAggregate { /// /// Initializes a new instance of the class. diff --git a/src/OpenTelemetry.Exporter.ZPages/Implementation/ZPagesExporterEventSource.cs b/src/OpenTelemetry.Exporter.ZPages/Implementation/ZPagesExporterEventSource.cs index f0b8dec0b5b..cba2dbffa2d 100644 --- a/src/OpenTelemetry.Exporter.ZPages/Implementation/ZPagesExporterEventSource.cs +++ b/src/OpenTelemetry.Exporter.ZPages/Implementation/ZPagesExporterEventSource.cs @@ -24,7 +24,7 @@ namespace OpenTelemetry.Exporter.ZPages.Implementation /// EventSource events emitted from the project. /// [EventSource(Name = "OpenTelemetry-Exporter-ZPages")] - internal class ZPagesExporterEventSource : EventSource + internal sealed class ZPagesExporterEventSource : EventSource { public static ZPagesExporterEventSource Log = new(); diff --git a/src/OpenTelemetry.Exporter.ZPages/Implementation/ZPagesStatsBuilder.cs b/src/OpenTelemetry.Exporter.ZPages/Implementation/ZPagesStatsBuilder.cs index 03648422ef3..2409d02ef86 100644 --- a/src/OpenTelemetry.Exporter.ZPages/Implementation/ZPagesStatsBuilder.cs +++ b/src/OpenTelemetry.Exporter.ZPages/Implementation/ZPagesStatsBuilder.cs @@ -16,7 +16,7 @@ namespace OpenTelemetry.Exporter.ZPages.Implementation { - internal class ZPagesStatsBuilder + internal sealed class ZPagesStatsBuilder { public const string ContentType = "text/html"; } diff --git a/src/OpenTelemetry.Exporter.Zipkin/CHANGELOG.md b/src/OpenTelemetry.Exporter.Zipkin/CHANGELOG.md index 352288c42a8..4ea2b381680 100644 --- a/src/OpenTelemetry.Exporter.Zipkin/CHANGELOG.md +++ b/src/OpenTelemetry.Exporter.Zipkin/CHANGELOG.md @@ -2,6 +2,18 @@ ## Unreleased +* Bumped the minimum required version of `System.Text.Json` to 4.7.2 in response +to [CVE-2021-26701](https://github.com/dotnet/runtime/issues/49377). +([#3789](https://github.com/open-telemetry/opentelemetry-dotnet/pull/3789)) + +## 1.4.0-beta.2 + +Released 2022-Oct-17 + +* Added support for loading environment variables from `IConfiguration` when + using the `AddZipkinExporter` extension + ([#3759](https://github.com/open-telemetry/opentelemetry-dotnet/pull/3759)) + ## 1.4.0-beta.1 Released 2022-Sep-29 diff --git a/src/OpenTelemetry.Exporter.Zipkin/Implementation/ZipkinEndpoint.cs b/src/OpenTelemetry.Exporter.Zipkin/Implementation/ZipkinEndpoint.cs index db850fc3f5c..0d4fc8705d3 100644 --- a/src/OpenTelemetry.Exporter.Zipkin/Implementation/ZipkinEndpoint.cs +++ b/src/OpenTelemetry.Exporter.Zipkin/Implementation/ZipkinEndpoint.cs @@ -19,7 +19,7 @@ namespace OpenTelemetry.Exporter.Zipkin.Implementation { - internal class ZipkinEndpoint + internal sealed class ZipkinEndpoint { public ZipkinEndpoint(string serviceName) : this(serviceName, null, null, null, null) diff --git a/src/OpenTelemetry.Exporter.Zipkin/Implementation/ZipkinExporterEventSource.cs b/src/OpenTelemetry.Exporter.Zipkin/Implementation/ZipkinExporterEventSource.cs index a7c4d317b3e..c60bc053a01 100644 --- a/src/OpenTelemetry.Exporter.Zipkin/Implementation/ZipkinExporterEventSource.cs +++ b/src/OpenTelemetry.Exporter.Zipkin/Implementation/ZipkinExporterEventSource.cs @@ -24,7 +24,7 @@ namespace OpenTelemetry.Exporter.Zipkin.Implementation /// EventSource events emitted from the project. /// [EventSource(Name = "OpenTelemetry-Exporter-Zipkin")] - internal class ZipkinExporterEventSource : EventSource + internal sealed class ZipkinExporterEventSource : EventSource { public static ZipkinExporterEventSource Log = new(); diff --git a/src/OpenTelemetry.Exporter.Zipkin/OpenTelemetry.Exporter.Zipkin.csproj b/src/OpenTelemetry.Exporter.Zipkin/OpenTelemetry.Exporter.Zipkin.csproj index 0aee4bd6334..c5e14a100de 100644 --- a/src/OpenTelemetry.Exporter.Zipkin/OpenTelemetry.Exporter.Zipkin.csproj +++ b/src/OpenTelemetry.Exporter.Zipkin/OpenTelemetry.Exporter.Zipkin.csproj @@ -14,7 +14,7 @@ - + diff --git a/src/OpenTelemetry.Exporter.Zipkin/ZipkinExporterHelperExtensions.cs b/src/OpenTelemetry.Exporter.Zipkin/ZipkinExporterHelperExtensions.cs index 261cecd1a64..93a43014874 100644 --- a/src/OpenTelemetry.Exporter.Zipkin/ZipkinExporterHelperExtensions.cs +++ b/src/OpenTelemetry.Exporter.Zipkin/ZipkinExporterHelperExtensions.cs @@ -62,10 +62,15 @@ public static TracerProviderBuilder AddZipkinExporter( name ??= Options.DefaultName; - if (configure != null) + builder.ConfigureServices(services => { - builder.ConfigureServices(services => services.Configure(name, configure)); - } + if (configure != null) + { + services.Configure(name, configure); + } + + services.RegisterOptionsFactory(configuration => new ZipkinExporterOptions(configuration)); + }); return builder.ConfigureBuilder((sp, builder) => { diff --git a/src/OpenTelemetry.Exporter.Zipkin/ZipkinExporterOptions.cs b/src/OpenTelemetry.Exporter.Zipkin/ZipkinExporterOptions.cs index 9c354574a72..f9d8e7c62c4 100644 --- a/src/OpenTelemetry.Exporter.Zipkin/ZipkinExporterOptions.cs +++ b/src/OpenTelemetry.Exporter.Zipkin/ZipkinExporterOptions.cs @@ -17,6 +17,7 @@ using System; using System.Diagnostics; using System.Net.Http; +using Microsoft.Extensions.Configuration; using OpenTelemetry.Internal; using OpenTelemetry.Trace; @@ -44,11 +45,18 @@ public sealed class ZipkinExporterOptions /// Initializes zipkin endpoint. /// public ZipkinExporterOptions() + : this(new ConfigurationBuilder().AddEnvironmentVariables().Build()) { - if (EnvironmentVariableHelper.LoadUri(ZipkinEndpointEnvVar, out Uri endpoint)) + } + + internal ZipkinExporterOptions(IConfiguration configuration) + { + if (configuration.TryGetUriValue(ZipkinEndpointEnvVar, out var endpoint)) { this.Endpoint = endpoint; } + + this.BatchExportProcessorOptions = new BatchExportActivityProcessorOptions(configuration); } /// @@ -75,7 +83,7 @@ public ZipkinExporterOptions() /// /// Gets or sets the BatchExportProcessor options. Ignored unless ExportProcessorType is BatchExporter. /// - public BatchExportProcessorOptions BatchExportProcessorOptions { get; set; } = new BatchExportActivityProcessorOptions(); + public BatchExportProcessorOptions BatchExportProcessorOptions { get; set; } /// /// Gets or sets the factory function called to create the [EventSource(Name = "OpenTelemetry-Extensions-Hosting")] - internal class HostingExtensionsEventSource : EventSource + internal sealed class HostingExtensionsEventSource : EventSource { public static HostingExtensionsEventSource Log = new(); diff --git a/src/OpenTelemetry.Extensions.Propagators/CHANGELOG.md b/src/OpenTelemetry.Extensions.Propagators/CHANGELOG.md index d4ed827c04f..130ef3aa83a 100644 --- a/src/OpenTelemetry.Extensions.Propagators/CHANGELOG.md +++ b/src/OpenTelemetry.Extensions.Propagators/CHANGELOG.md @@ -2,6 +2,10 @@ ## Unreleased +## 1.4.0-beta.2 + +Released 2022-Oct-17 + ## 1.4.0-beta.1 Released 2022-Sep-29 diff --git a/src/OpenTelemetry.Extensions.Propagators/OpenTelemetryPropagatorsEventSource.cs b/src/OpenTelemetry.Extensions.Propagators/OpenTelemetryPropagatorsEventSource.cs index fc22c92e87f..1e3163a0b12 100644 --- a/src/OpenTelemetry.Extensions.Propagators/OpenTelemetryPropagatorsEventSource.cs +++ b/src/OpenTelemetry.Extensions.Propagators/OpenTelemetryPropagatorsEventSource.cs @@ -24,7 +24,7 @@ namespace OpenTelemetry.Internal /// This is used for internal logging of this library. /// [EventSource(Name = "OpenTelemetry.Extensions.Propagators")] - internal class OpenTelemetryPropagatorsEventSource : EventSource + internal sealed class OpenTelemetryPropagatorsEventSource : EventSource { public static OpenTelemetryPropagatorsEventSource Log = new(); diff --git a/src/OpenTelemetry.Instrumentation.AspNetCore/.publicApi/net6.0/PublicAPI.Unshipped.txt b/src/OpenTelemetry.Instrumentation.AspNetCore/.publicApi/net6.0/PublicAPI.Unshipped.txt index 0327c2bb195..b3b24c45be9 100644 --- a/src/OpenTelemetry.Instrumentation.AspNetCore/.publicApi/net6.0/PublicAPI.Unshipped.txt +++ b/src/OpenTelemetry.Instrumentation.AspNetCore/.publicApi/net6.0/PublicAPI.Unshipped.txt @@ -2,8 +2,12 @@ OpenTelemetry.Instrumentation.AspNetCore.AspNetCoreInstrumentationOptions OpenTelemetry.Instrumentation.AspNetCore.AspNetCoreInstrumentationOptions.AspNetCoreInstrumentationOptions() -> void OpenTelemetry.Instrumentation.AspNetCore.AspNetCoreInstrumentationOptions.EnableGrpcAspNetCoreSupport.get -> bool OpenTelemetry.Instrumentation.AspNetCore.AspNetCoreInstrumentationOptions.EnableGrpcAspNetCoreSupport.set -> void -OpenTelemetry.Instrumentation.AspNetCore.AspNetCoreInstrumentationOptions.Enrich.get -> System.Action -OpenTelemetry.Instrumentation.AspNetCore.AspNetCoreInstrumentationOptions.Enrich.set -> void +OpenTelemetry.Instrumentation.AspNetCore.AspNetCoreInstrumentationOptions.EnrichWithException.get -> System.Action +OpenTelemetry.Instrumentation.AspNetCore.AspNetCoreInstrumentationOptions.EnrichWithException.set -> void +OpenTelemetry.Instrumentation.AspNetCore.AspNetCoreInstrumentationOptions.EnrichWithHttpRequest.get -> System.Action +OpenTelemetry.Instrumentation.AspNetCore.AspNetCoreInstrumentationOptions.EnrichWithHttpRequest.set -> void +OpenTelemetry.Instrumentation.AspNetCore.AspNetCoreInstrumentationOptions.EnrichWithHttpResponse.get -> System.Action +OpenTelemetry.Instrumentation.AspNetCore.AspNetCoreInstrumentationOptions.EnrichWithHttpResponse.set -> void OpenTelemetry.Instrumentation.AspNetCore.AspNetCoreInstrumentationOptions.Filter.get -> System.Func OpenTelemetry.Instrumentation.AspNetCore.AspNetCoreInstrumentationOptions.Filter.set -> void OpenTelemetry.Instrumentation.AspNetCore.AspNetCoreInstrumentationOptions.RecordException.get -> bool @@ -13,4 +17,4 @@ OpenTelemetry.Trace.TracerProviderBuilderExtensions static OpenTelemetry.Metrics.MeterProviderBuilderExtensions.AddAspNetCoreInstrumentation(this OpenTelemetry.Metrics.MeterProviderBuilder builder) -> OpenTelemetry.Metrics.MeterProviderBuilder static OpenTelemetry.Trace.TracerProviderBuilderExtensions.AddAspNetCoreInstrumentation(this OpenTelemetry.Trace.TracerProviderBuilder builder) -> OpenTelemetry.Trace.TracerProviderBuilder static OpenTelemetry.Trace.TracerProviderBuilderExtensions.AddAspNetCoreInstrumentation(this OpenTelemetry.Trace.TracerProviderBuilder builder, string name, System.Action configureAspNetCoreInstrumentationOptions) -> OpenTelemetry.Trace.TracerProviderBuilder -static OpenTelemetry.Trace.TracerProviderBuilderExtensions.AddAspNetCoreInstrumentation(this OpenTelemetry.Trace.TracerProviderBuilder builder, System.Action configureAspNetCoreInstrumentationOptions) -> OpenTelemetry.Trace.TracerProviderBuilder \ No newline at end of file +static OpenTelemetry.Trace.TracerProviderBuilderExtensions.AddAspNetCoreInstrumentation(this OpenTelemetry.Trace.TracerProviderBuilder builder, System.Action configureAspNetCoreInstrumentationOptions) -> OpenTelemetry.Trace.TracerProviderBuilder diff --git a/src/OpenTelemetry.Instrumentation.AspNetCore/.publicApi/net7.0/PublicAPI.Unshipped.txt b/src/OpenTelemetry.Instrumentation.AspNetCore/.publicApi/net7.0/PublicAPI.Unshipped.txt index 0327c2bb195..b3b24c45be9 100644 --- a/src/OpenTelemetry.Instrumentation.AspNetCore/.publicApi/net7.0/PublicAPI.Unshipped.txt +++ b/src/OpenTelemetry.Instrumentation.AspNetCore/.publicApi/net7.0/PublicAPI.Unshipped.txt @@ -2,8 +2,12 @@ OpenTelemetry.Instrumentation.AspNetCore.AspNetCoreInstrumentationOptions OpenTelemetry.Instrumentation.AspNetCore.AspNetCoreInstrumentationOptions.AspNetCoreInstrumentationOptions() -> void OpenTelemetry.Instrumentation.AspNetCore.AspNetCoreInstrumentationOptions.EnableGrpcAspNetCoreSupport.get -> bool OpenTelemetry.Instrumentation.AspNetCore.AspNetCoreInstrumentationOptions.EnableGrpcAspNetCoreSupport.set -> void -OpenTelemetry.Instrumentation.AspNetCore.AspNetCoreInstrumentationOptions.Enrich.get -> System.Action -OpenTelemetry.Instrumentation.AspNetCore.AspNetCoreInstrumentationOptions.Enrich.set -> void +OpenTelemetry.Instrumentation.AspNetCore.AspNetCoreInstrumentationOptions.EnrichWithException.get -> System.Action +OpenTelemetry.Instrumentation.AspNetCore.AspNetCoreInstrumentationOptions.EnrichWithException.set -> void +OpenTelemetry.Instrumentation.AspNetCore.AspNetCoreInstrumentationOptions.EnrichWithHttpRequest.get -> System.Action +OpenTelemetry.Instrumentation.AspNetCore.AspNetCoreInstrumentationOptions.EnrichWithHttpRequest.set -> void +OpenTelemetry.Instrumentation.AspNetCore.AspNetCoreInstrumentationOptions.EnrichWithHttpResponse.get -> System.Action +OpenTelemetry.Instrumentation.AspNetCore.AspNetCoreInstrumentationOptions.EnrichWithHttpResponse.set -> void OpenTelemetry.Instrumentation.AspNetCore.AspNetCoreInstrumentationOptions.Filter.get -> System.Func OpenTelemetry.Instrumentation.AspNetCore.AspNetCoreInstrumentationOptions.Filter.set -> void OpenTelemetry.Instrumentation.AspNetCore.AspNetCoreInstrumentationOptions.RecordException.get -> bool @@ -13,4 +17,4 @@ OpenTelemetry.Trace.TracerProviderBuilderExtensions static OpenTelemetry.Metrics.MeterProviderBuilderExtensions.AddAspNetCoreInstrumentation(this OpenTelemetry.Metrics.MeterProviderBuilder builder) -> OpenTelemetry.Metrics.MeterProviderBuilder static OpenTelemetry.Trace.TracerProviderBuilderExtensions.AddAspNetCoreInstrumentation(this OpenTelemetry.Trace.TracerProviderBuilder builder) -> OpenTelemetry.Trace.TracerProviderBuilder static OpenTelemetry.Trace.TracerProviderBuilderExtensions.AddAspNetCoreInstrumentation(this OpenTelemetry.Trace.TracerProviderBuilder builder, string name, System.Action configureAspNetCoreInstrumentationOptions) -> OpenTelemetry.Trace.TracerProviderBuilder -static OpenTelemetry.Trace.TracerProviderBuilderExtensions.AddAspNetCoreInstrumentation(this OpenTelemetry.Trace.TracerProviderBuilder builder, System.Action configureAspNetCoreInstrumentationOptions) -> OpenTelemetry.Trace.TracerProviderBuilder \ No newline at end of file +static OpenTelemetry.Trace.TracerProviderBuilderExtensions.AddAspNetCoreInstrumentation(this OpenTelemetry.Trace.TracerProviderBuilder builder, System.Action configureAspNetCoreInstrumentationOptions) -> OpenTelemetry.Trace.TracerProviderBuilder diff --git a/src/OpenTelemetry.Instrumentation.AspNetCore/.publicApi/netstandard2.0/PublicAPI.Unshipped.txt b/src/OpenTelemetry.Instrumentation.AspNetCore/.publicApi/netstandard2.0/PublicAPI.Unshipped.txt index 87ab1614549..6033fda11cc 100644 --- a/src/OpenTelemetry.Instrumentation.AspNetCore/.publicApi/netstandard2.0/PublicAPI.Unshipped.txt +++ b/src/OpenTelemetry.Instrumentation.AspNetCore/.publicApi/netstandard2.0/PublicAPI.Unshipped.txt @@ -1,7 +1,11 @@ OpenTelemetry.Instrumentation.AspNetCore.AspNetCoreInstrumentationOptions OpenTelemetry.Instrumentation.AspNetCore.AspNetCoreInstrumentationOptions.AspNetCoreInstrumentationOptions() -> void -OpenTelemetry.Instrumentation.AspNetCore.AspNetCoreInstrumentationOptions.Enrich.get -> System.Action -OpenTelemetry.Instrumentation.AspNetCore.AspNetCoreInstrumentationOptions.Enrich.set -> void +OpenTelemetry.Instrumentation.AspNetCore.AspNetCoreInstrumentationOptions.EnrichWithException.get -> System.Action +OpenTelemetry.Instrumentation.AspNetCore.AspNetCoreInstrumentationOptions.EnrichWithException.set -> void +OpenTelemetry.Instrumentation.AspNetCore.AspNetCoreInstrumentationOptions.EnrichWithHttpRequest.get -> System.Action +OpenTelemetry.Instrumentation.AspNetCore.AspNetCoreInstrumentationOptions.EnrichWithHttpRequest.set -> void +OpenTelemetry.Instrumentation.AspNetCore.AspNetCoreInstrumentationOptions.EnrichWithHttpResponse.get -> System.Action +OpenTelemetry.Instrumentation.AspNetCore.AspNetCoreInstrumentationOptions.EnrichWithHttpResponse.set -> void OpenTelemetry.Instrumentation.AspNetCore.AspNetCoreInstrumentationOptions.Filter.get -> System.Func OpenTelemetry.Instrumentation.AspNetCore.AspNetCoreInstrumentationOptions.Filter.set -> void OpenTelemetry.Instrumentation.AspNetCore.AspNetCoreInstrumentationOptions.RecordException.get -> bool @@ -9,4 +13,6 @@ OpenTelemetry.Instrumentation.AspNetCore.AspNetCoreInstrumentationOptions.Record OpenTelemetry.Metrics.MeterProviderBuilderExtensions OpenTelemetry.Trace.TracerProviderBuilderExtensions static OpenTelemetry.Metrics.MeterProviderBuilderExtensions.AddAspNetCoreInstrumentation(this OpenTelemetry.Metrics.MeterProviderBuilder builder) -> OpenTelemetry.Metrics.MeterProviderBuilder -static OpenTelemetry.Trace.TracerProviderBuilderExtensions.AddAspNetCoreInstrumentation(this OpenTelemetry.Trace.TracerProviderBuilder builder, System.Action configureAspNetCoreInstrumentationOptions = null) -> OpenTelemetry.Trace.TracerProviderBuilder +static OpenTelemetry.Trace.TracerProviderBuilderExtensions.AddAspNetCoreInstrumentation(this OpenTelemetry.Trace.TracerProviderBuilder builder) -> OpenTelemetry.Trace.TracerProviderBuilder +static OpenTelemetry.Trace.TracerProviderBuilderExtensions.AddAspNetCoreInstrumentation(this OpenTelemetry.Trace.TracerProviderBuilder builder, string name, System.Action configureAspNetCoreInstrumentationOptions) -> OpenTelemetry.Trace.TracerProviderBuilder +static OpenTelemetry.Trace.TracerProviderBuilderExtensions.AddAspNetCoreInstrumentation(this OpenTelemetry.Trace.TracerProviderBuilder builder, System.Action configureAspNetCoreInstrumentationOptions) -> OpenTelemetry.Trace.TracerProviderBuilder diff --git a/src/OpenTelemetry.Instrumentation.AspNetCore/.publicApi/netstandard2.1/PublicAPI.Unshipped.txt b/src/OpenTelemetry.Instrumentation.AspNetCore/.publicApi/netstandard2.1/PublicAPI.Unshipped.txt index fb182712e2b..b3b24c45be9 100644 --- a/src/OpenTelemetry.Instrumentation.AspNetCore/.publicApi/netstandard2.1/PublicAPI.Unshipped.txt +++ b/src/OpenTelemetry.Instrumentation.AspNetCore/.publicApi/netstandard2.1/PublicAPI.Unshipped.txt @@ -2,8 +2,12 @@ OpenTelemetry.Instrumentation.AspNetCore.AspNetCoreInstrumentationOptions OpenTelemetry.Instrumentation.AspNetCore.AspNetCoreInstrumentationOptions.AspNetCoreInstrumentationOptions() -> void OpenTelemetry.Instrumentation.AspNetCore.AspNetCoreInstrumentationOptions.EnableGrpcAspNetCoreSupport.get -> bool OpenTelemetry.Instrumentation.AspNetCore.AspNetCoreInstrumentationOptions.EnableGrpcAspNetCoreSupport.set -> void -OpenTelemetry.Instrumentation.AspNetCore.AspNetCoreInstrumentationOptions.Enrich.get -> System.Action -OpenTelemetry.Instrumentation.AspNetCore.AspNetCoreInstrumentationOptions.Enrich.set -> void +OpenTelemetry.Instrumentation.AspNetCore.AspNetCoreInstrumentationOptions.EnrichWithException.get -> System.Action +OpenTelemetry.Instrumentation.AspNetCore.AspNetCoreInstrumentationOptions.EnrichWithException.set -> void +OpenTelemetry.Instrumentation.AspNetCore.AspNetCoreInstrumentationOptions.EnrichWithHttpRequest.get -> System.Action +OpenTelemetry.Instrumentation.AspNetCore.AspNetCoreInstrumentationOptions.EnrichWithHttpRequest.set -> void +OpenTelemetry.Instrumentation.AspNetCore.AspNetCoreInstrumentationOptions.EnrichWithHttpResponse.get -> System.Action +OpenTelemetry.Instrumentation.AspNetCore.AspNetCoreInstrumentationOptions.EnrichWithHttpResponse.set -> void OpenTelemetry.Instrumentation.AspNetCore.AspNetCoreInstrumentationOptions.Filter.get -> System.Func OpenTelemetry.Instrumentation.AspNetCore.AspNetCoreInstrumentationOptions.Filter.set -> void OpenTelemetry.Instrumentation.AspNetCore.AspNetCoreInstrumentationOptions.RecordException.get -> bool @@ -11,4 +15,6 @@ OpenTelemetry.Instrumentation.AspNetCore.AspNetCoreInstrumentationOptions.Record OpenTelemetry.Metrics.MeterProviderBuilderExtensions OpenTelemetry.Trace.TracerProviderBuilderExtensions static OpenTelemetry.Metrics.MeterProviderBuilderExtensions.AddAspNetCoreInstrumentation(this OpenTelemetry.Metrics.MeterProviderBuilder builder) -> OpenTelemetry.Metrics.MeterProviderBuilder -static OpenTelemetry.Trace.TracerProviderBuilderExtensions.AddAspNetCoreInstrumentation(this OpenTelemetry.Trace.TracerProviderBuilder builder, System.Action configureAspNetCoreInstrumentationOptions = null) -> OpenTelemetry.Trace.TracerProviderBuilder +static OpenTelemetry.Trace.TracerProviderBuilderExtensions.AddAspNetCoreInstrumentation(this OpenTelemetry.Trace.TracerProviderBuilder builder) -> OpenTelemetry.Trace.TracerProviderBuilder +static OpenTelemetry.Trace.TracerProviderBuilderExtensions.AddAspNetCoreInstrumentation(this OpenTelemetry.Trace.TracerProviderBuilder builder, string name, System.Action configureAspNetCoreInstrumentationOptions) -> OpenTelemetry.Trace.TracerProviderBuilder +static OpenTelemetry.Trace.TracerProviderBuilderExtensions.AddAspNetCoreInstrumentation(this OpenTelemetry.Trace.TracerProviderBuilder builder, System.Action configureAspNetCoreInstrumentationOptions) -> OpenTelemetry.Trace.TracerProviderBuilder diff --git a/src/OpenTelemetry.Instrumentation.AspNetCore/AspNetCoreInstrumentation.cs b/src/OpenTelemetry.Instrumentation.AspNetCore/AspNetCoreInstrumentation.cs index 0503813e69c..190a305aedf 100644 --- a/src/OpenTelemetry.Instrumentation.AspNetCore/AspNetCoreInstrumentation.cs +++ b/src/OpenTelemetry.Instrumentation.AspNetCore/AspNetCoreInstrumentation.cs @@ -22,7 +22,7 @@ namespace OpenTelemetry.Instrumentation.AspNetCore /// /// Asp.Net Core Requests instrumentation. /// - internal class AspNetCoreInstrumentation : IDisposable + internal sealed class AspNetCoreInstrumentation : IDisposable { private static readonly HashSet DiagnosticSourceEvents = new() { diff --git a/src/OpenTelemetry.Instrumentation.AspNetCore/AspNetCoreInstrumentationOptions.cs b/src/OpenTelemetry.Instrumentation.AspNetCore/AspNetCoreInstrumentationOptions.cs index 3b6ecc676c1..9c51fb5eb25 100644 --- a/src/OpenTelemetry.Instrumentation.AspNetCore/AspNetCoreInstrumentationOptions.cs +++ b/src/OpenTelemetry.Instrumentation.AspNetCore/AspNetCoreInstrumentationOptions.cs @@ -38,11 +38,27 @@ public class AspNetCoreInstrumentationOptions /// /// /// : the activity being enriched. - /// string: the name of the event. - /// object: the raw object from which additional information can be extracted to enrich the activity. - /// The type of this object depends on the event, which is given by the above parameter. + /// : the HttpRequest object from which additional information can be extracted to enrich the activity. /// - public Action Enrich { get; set; } + public Action EnrichWithHttpRequest { get; set; } + + /// + /// Gets or sets an action to enrich an Activity. + /// + /// + /// : the activity being enriched. + /// : the HttpResponse object from which additional information can be extracted to enrich the activity. + /// + public Action EnrichWithHttpResponse { get; set; } + + /// + /// Gets or sets an action to enrich an Activity. + /// + /// + /// : the activity being enriched. + /// : the Exception object from which additional information can be extracted to enrich the activity. + /// + public Action EnrichWithException { get; set; } /// /// Gets or sets a value indicating whether the exception will be recorded as ActivityEvent or not. diff --git a/src/OpenTelemetry.Instrumentation.AspNetCore/AspNetCoreMetrics.cs b/src/OpenTelemetry.Instrumentation.AspNetCore/AspNetCoreMetrics.cs index 7f4c2292091..c14b6628eca 100644 --- a/src/OpenTelemetry.Instrumentation.AspNetCore/AspNetCoreMetrics.cs +++ b/src/OpenTelemetry.Instrumentation.AspNetCore/AspNetCoreMetrics.cs @@ -24,7 +24,7 @@ namespace OpenTelemetry.Instrumentation.AspNetCore /// /// Asp.Net Core Requests instrumentation. /// - internal class AspNetCoreMetrics : IDisposable + internal sealed class AspNetCoreMetrics : IDisposable { internal static readonly AssemblyName AssemblyName = typeof(HttpInListener).Assembly.GetName(); internal static readonly string InstrumentationName = AssemblyName.Name; diff --git a/src/OpenTelemetry.Instrumentation.AspNetCore/CHANGELOG.md b/src/OpenTelemetry.Instrumentation.AspNetCore/CHANGELOG.md index 1308cce0313..5b3b1e04bf1 100644 --- a/src/OpenTelemetry.Instrumentation.AspNetCore/CHANGELOG.md +++ b/src/OpenTelemetry.Instrumentation.AspNetCore/CHANGELOG.md @@ -2,6 +2,24 @@ ## Unreleased +* **Breaking change** The `Enrich` callback option has been removed. + For better usability, it has been replaced by three separate options: + `EnrichWithHttpRequest`, `EnrichWithHttpResponse` and `EnrichWithException`. + Previously, the single `Enrich` callback required the consumer to detect + which event triggered the callback to be invoked (e.g., request start, + response end, or an exception) and then cast the object received to the + appropriate type: `HttpRequest`, `HttpResponse`, or `Exception`. The separate + callbacks make it clear what event triggers them and there is no longer the + need to cast the argument to the expected type. + ([#3749](https://github.com/open-telemetry/opentelemetry-dotnet/pull/3749)) + +* Added back `netstandard2.0` and `netstandard2.1` targets. +([#3755](https://github.com/open-telemetry/opentelemetry-dotnet/pull/3755)) + +## 1.0.0-rc9.8 + +Released 2022-Oct-17 + ## 1.0.0-rc9.7 Released 2022-Sep-29 diff --git a/src/OpenTelemetry.Instrumentation.AspNetCore/Implementation/AspNetCoreInstrumentationEventSource.cs b/src/OpenTelemetry.Instrumentation.AspNetCore/Implementation/AspNetCoreInstrumentationEventSource.cs index c3929f6845b..b78ab6953d0 100644 --- a/src/OpenTelemetry.Instrumentation.AspNetCore/Implementation/AspNetCoreInstrumentationEventSource.cs +++ b/src/OpenTelemetry.Instrumentation.AspNetCore/Implementation/AspNetCoreInstrumentationEventSource.cs @@ -24,7 +24,7 @@ namespace OpenTelemetry.Instrumentation.AspNetCore.Implementation /// EventSource events emitted from the project. /// [EventSource(Name = "OpenTelemetry-Instrumentation-AspNetCore")] - internal class AspNetCoreInstrumentationEventSource : EventSource + internal sealed class AspNetCoreInstrumentationEventSource : EventSource { public static AspNetCoreInstrumentationEventSource Log = new(); diff --git a/src/OpenTelemetry.Instrumentation.AspNetCore/Implementation/HttpInListener.cs b/src/OpenTelemetry.Instrumentation.AspNetCore/Implementation/HttpInListener.cs index e8a214203b3..3be0d4065ef 100644 --- a/src/OpenTelemetry.Instrumentation.AspNetCore/Implementation/HttpInListener.cs +++ b/src/OpenTelemetry.Instrumentation.AspNetCore/Implementation/HttpInListener.cs @@ -19,11 +19,17 @@ using System.Diagnostics; using System.Linq; using System.Reflection; +#if !NETSTANDARD2_0 using System.Runtime.CompilerServices; +#endif using Microsoft.AspNetCore.Http; +#if NET6_0_OR_GREATER using Microsoft.AspNetCore.Mvc.Diagnostics; +#endif using OpenTelemetry.Context.Propagation; +#if !NETSTANDARD2_0 using OpenTelemetry.Instrumentation.GrpcNetClient; +#endif using OpenTelemetry.Internal; using OpenTelemetry.Trace; @@ -52,6 +58,11 @@ internal class HttpInListener : ListenerHandler private const string UnknownHostName = "UNKNOWN-HOST"; private static readonly Func> HttpRequestHeaderValuesGetter = (request, name) => request.Headers[name]; +#if !NET6_0_OR_GREATER + private readonly PropertyFetcher beforeActionActionDescriptorFetcher = new("actionDescriptor"); + private readonly PropertyFetcher beforeActionAttributeRouteInfoFetcher = new("AttributeRouteInfo"); + private readonly PropertyFetcher beforeActionTemplateFetcher = new("Template"); +#endif private readonly PropertyFetcher stopExceptionFetcher = new("Exception"); private readonly AspNetCoreInstrumentationOptions options; @@ -211,7 +222,7 @@ public void OnStartActivity(Activity activity, object payload) try { - this.options.Enrich?.Invoke(activity, "OnStartActivity", request); + this.options.EnrichWithHttpRequest?.Invoke(activity, request); } catch (Exception ex) { @@ -235,6 +246,7 @@ public void OnStopActivity(Activity activity, object payload) activity.SetTag(SemanticConventions.AttributeHttpStatusCode, response.StatusCode); +#if !NETSTANDARD2_0 if (this.options.EnableGrpcAspNetCoreSupport && TryGetGrpcMethod(activity, out var grpcMethod)) { AddGrpcAttributes(activity, grpcMethod, context); @@ -243,10 +255,16 @@ public void OnStopActivity(Activity activity, object payload) { activity.SetStatus(SpanHelper.ResolveSpanStatusForHttpStatusCode(activity.Kind, response.StatusCode)); } +#else + if (activity.Status == ActivityStatusCode.Unset) + { + activity.SetStatus(SpanHelper.ResolveSpanStatusForHttpStatusCode(activity.Kind, response.StatusCode)); + } +#endif try { - this.options.Enrich?.Invoke(activity, "OnStopActivity", response); + this.options.EnrichWithHttpResponse?.Invoke(activity, response); } catch (Exception ex) { @@ -310,8 +328,14 @@ public void OnMvcBeforeAction(Activity activity, object payload) if (activity.IsAllDataRequested) { +#if !NET6_0_OR_GREATER + _ = this.beforeActionActionDescriptorFetcher.TryFetch(payload, out var actionDescriptor); + _ = this.beforeActionAttributeRouteInfoFetcher.TryFetch(actionDescriptor, out var attributeRouteInfo); + _ = this.beforeActionTemplateFetcher.TryFetch(attributeRouteInfo, out var template); +#else var beforeActionEventData = payload as BeforeActionEventData; var template = beforeActionEventData.ActionDescriptor?.AttributeRouteInfo?.Template; +#endif if (!string.IsNullOrEmpty(template)) { // override the span name that was previously set to the path part of URL. @@ -345,7 +369,7 @@ public void OnException(Activity activity, object payload) try { - this.options.Enrich?.Invoke(activity, "OnException", exc); + this.options.EnrichWithException?.Invoke(activity, exc); } catch (Exception ex) { @@ -368,6 +392,7 @@ private static string GetUri(HttpRequest request) var length = scheme.Length + Uri.SchemeDelimiter.Length + host.Length + pathBase.Length + path.Length + queryString.Length; +#if NETSTANDARD2_1_OR_GREATER || NET6_0_OR_GREATER return string.Create(length, (scheme, host, pathBase, path, queryString), (span, parts) => { CopyTo(ref span, parts.scheme); @@ -386,8 +411,19 @@ static void CopyTo(ref Span buffer, ReadOnlySpan text) } } }); +#else + return new System.Text.StringBuilder(length) + .Append(scheme) + .Append(Uri.SchemeDelimiter) + .Append(host) + .Append(pathBase) + .Append(path) + .Append(queryString) + .ToString(); +#endif } +#if !NETSTANDARD2_0 [MethodImpl(MethodImplOptions.AggressiveInlining)] private static bool TryGetGrpcMethod(Activity activity, out string grpcMethod) { @@ -435,5 +471,6 @@ private static void AddGrpcAttributes(Activity activity, string grpcMethod, Http } } } +#endif } } diff --git a/src/OpenTelemetry.Instrumentation.AspNetCore/Implementation/HttpInMetricsListener.cs b/src/OpenTelemetry.Instrumentation.AspNetCore/Implementation/HttpInMetricsListener.cs index 5bcae334616..802feedec04 100644 --- a/src/OpenTelemetry.Instrumentation.AspNetCore/Implementation/HttpInMetricsListener.cs +++ b/src/OpenTelemetry.Instrumentation.AspNetCore/Implementation/HttpInMetricsListener.cs @@ -17,12 +17,14 @@ using System.Diagnostics; using System.Diagnostics.Metrics; using Microsoft.AspNetCore.Http; +#if NET6_0_OR_GREATER using Microsoft.AspNetCore.Routing; +#endif using OpenTelemetry.Trace; namespace OpenTelemetry.Instrumentation.AspNetCore.Implementation { - internal class HttpInMetricsListener : ListenerHandler + internal sealed class HttpInMetricsListener : ListenerHandler { private const string OnStopEvent = "Microsoft.AspNetCore.Hosting.HttpRequestIn.Stop"; @@ -67,7 +69,7 @@ public override void OnEventWritten(string name, object payload) } TagList tags; - +#if NET6_0_OR_GREATER var target = (context.GetEndpoint() as RouteEndpoint)?.RoutePattern.RawText; // TODO: This is just a minimal set of attributes. See the spec for additional attributes: @@ -95,6 +97,17 @@ public override void OnEventWritten(string name, object payload) { SemanticConventions.AttributeHttpStatusCode, context.Response.StatusCode.ToString() }, }; } +#else + tags = new TagList + { + { SemanticConventions.AttributeHttpFlavor, context.Request.Protocol }, + { SemanticConventions.AttributeHttpScheme, context.Request.Scheme }, + { SemanticConventions.AttributeHttpMethod, context.Request.Method }, + { SemanticConventions.AttributeHttpHost, host }, + { SemanticConventions.AttributeHttpStatusCode, context.Response.StatusCode.ToString() }, + }; + +#endif this.httpServerDuration.Record(Activity.Current.Duration.TotalMilliseconds, tags); } diff --git a/src/OpenTelemetry.Instrumentation.AspNetCore/OpenTelemetry.Instrumentation.AspNetCore.csproj b/src/OpenTelemetry.Instrumentation.AspNetCore/OpenTelemetry.Instrumentation.AspNetCore.csproj index b97f1adf0da..87277efb242 100644 --- a/src/OpenTelemetry.Instrumentation.AspNetCore/OpenTelemetry.Instrumentation.AspNetCore.csproj +++ b/src/OpenTelemetry.Instrumentation.AspNetCore/OpenTelemetry.Instrumentation.AspNetCore.csproj @@ -1,7 +1,7 @@ - net7.0;net6.0 + net7.0;net6.0;netstandard2.1;netstandard2.0 ASP.NET Core instrumentation for OpenTelemetry .NET $(PackageTags);distributed-tracing;AspNetCore true @@ -17,6 +17,16 @@ + + + + + + + + + + diff --git a/src/OpenTelemetry.Instrumentation.AspNetCore/README.md b/src/OpenTelemetry.Instrumentation.AspNetCore/README.md index 7df6a2adb09..d27566f0419 100644 --- a/src/OpenTelemetry.Instrumentation.AspNetCore/README.md +++ b/src/OpenTelemetry.Instrumentation.AspNetCore/README.md @@ -120,36 +120,33 @@ and the `Filter` option does the filtering *after* the Sampler is invoked. ### Enrich -This option allows one to enrich the activity with additional information -from the raw `HttpRequest`, `HttpResponse` objects. The `Enrich` action is -called only when `activity.IsAllDataRequested` is `true`. It contains the -activity itself (which can be enriched), the name of the event, and the -actual raw object. -For event name "OnStartActivity", the actual object will be `HttpRequest`. -For event name "OnStopActivity", the actual object will be `HttpResponse` +This instrumentation library provides `EnrichWithHttpRequest`, +`EnrichWithHttpResponse` and `EnrichWithException` options that can be used to +enrich the activity with additional information from the raw `HttpRequest`, +`HttpResponse` and `Exception` objects respectively. These actions are called +only when `activity.IsAllDataRequested` is `true`. It contains the activity +itself (which can be enriched) and the actual raw object. -The following code snippet shows how to add additional tags using `Enrich`. +The following code snippet shows how to enrich the activity using all 3 +different options. ```csharp services.AddOpenTelemetryTracing((builder) => { - builder.AddAspNetCoreInstrumentation((options) => options.Enrich - = (activity, eventName, rawObject) => + builder.AddAspNetCoreInstrumentation(o => { - if (eventName.Equals("OnStartActivity")) + o.EnrichWithHttpRequest = (activity, httpRequest) => { - if (rawObject is HttpRequest httpRequest) - { - activity.SetTag("requestProtocol", httpRequest.Protocol); - } - } - else if (eventName.Equals("OnStopActivity")) + activity.SetTag("requestProtocol", httpRequest.Protocol); + }; + o.EnrichWithHttpResponse = (activity, httpResponse) => { - if (rawObject is HttpResponse httpResponse) - { - activity.SetTag("responseLength", httpResponse.ContentLength); - } - } + activity.SetTag("responseLength", httpResponse.ContentLength); + }; + o.EnrichWithException = (activity, exception) => + { + activity.SetTag("exceptionType", exception.GetType().ToString()); + }; }) }); ``` diff --git a/src/OpenTelemetry.Instrumentation.GrpcNetClient/.publicApi/netstandard2.0/PublicAPI.Unshipped.txt b/src/OpenTelemetry.Instrumentation.GrpcNetClient/.publicApi/netstandard2.0/PublicAPI.Unshipped.txt index 82eecf60816..db708294cc8 100644 --- a/src/OpenTelemetry.Instrumentation.GrpcNetClient/.publicApi/netstandard2.0/PublicAPI.Unshipped.txt +++ b/src/OpenTelemetry.Instrumentation.GrpcNetClient/.publicApi/netstandard2.0/PublicAPI.Unshipped.txt @@ -1,6 +1,8 @@ OpenTelemetry.Instrumentation.GrpcNetClient.GrpcClientInstrumentationOptions -OpenTelemetry.Instrumentation.GrpcNetClient.GrpcClientInstrumentationOptions.Enrich.get -> System.Action -OpenTelemetry.Instrumentation.GrpcNetClient.GrpcClientInstrumentationOptions.Enrich.set -> void +OpenTelemetry.Instrumentation.GrpcNetClient.GrpcClientInstrumentationOptions.EnrichWithHttpRequestMessage.get -> System.Action +OpenTelemetry.Instrumentation.GrpcNetClient.GrpcClientInstrumentationOptions.EnrichWithHttpRequestMessage.set -> void +OpenTelemetry.Instrumentation.GrpcNetClient.GrpcClientInstrumentationOptions.EnrichWithHttpResponseMessage.get -> System.Action +OpenTelemetry.Instrumentation.GrpcNetClient.GrpcClientInstrumentationOptions.EnrichWithHttpResponseMessage.set -> void OpenTelemetry.Instrumentation.GrpcNetClient.GrpcClientInstrumentationOptions.GrpcClientInstrumentationOptions() -> void OpenTelemetry.Instrumentation.GrpcNetClient.GrpcClientInstrumentationOptions.SuppressDownstreamInstrumentation.get -> bool OpenTelemetry.Instrumentation.GrpcNetClient.GrpcClientInstrumentationOptions.SuppressDownstreamInstrumentation.set -> void diff --git a/src/OpenTelemetry.Instrumentation.GrpcNetClient/.publicApi/netstandard2.1/PublicAPI.Unshipped.txt b/src/OpenTelemetry.Instrumentation.GrpcNetClient/.publicApi/netstandard2.1/PublicAPI.Unshipped.txt index 82eecf60816..db708294cc8 100644 --- a/src/OpenTelemetry.Instrumentation.GrpcNetClient/.publicApi/netstandard2.1/PublicAPI.Unshipped.txt +++ b/src/OpenTelemetry.Instrumentation.GrpcNetClient/.publicApi/netstandard2.1/PublicAPI.Unshipped.txt @@ -1,6 +1,8 @@ OpenTelemetry.Instrumentation.GrpcNetClient.GrpcClientInstrumentationOptions -OpenTelemetry.Instrumentation.GrpcNetClient.GrpcClientInstrumentationOptions.Enrich.get -> System.Action -OpenTelemetry.Instrumentation.GrpcNetClient.GrpcClientInstrumentationOptions.Enrich.set -> void +OpenTelemetry.Instrumentation.GrpcNetClient.GrpcClientInstrumentationOptions.EnrichWithHttpRequestMessage.get -> System.Action +OpenTelemetry.Instrumentation.GrpcNetClient.GrpcClientInstrumentationOptions.EnrichWithHttpRequestMessage.set -> void +OpenTelemetry.Instrumentation.GrpcNetClient.GrpcClientInstrumentationOptions.EnrichWithHttpResponseMessage.get -> System.Action +OpenTelemetry.Instrumentation.GrpcNetClient.GrpcClientInstrumentationOptions.EnrichWithHttpResponseMessage.set -> void OpenTelemetry.Instrumentation.GrpcNetClient.GrpcClientInstrumentationOptions.GrpcClientInstrumentationOptions() -> void OpenTelemetry.Instrumentation.GrpcNetClient.GrpcClientInstrumentationOptions.SuppressDownstreamInstrumentation.get -> bool OpenTelemetry.Instrumentation.GrpcNetClient.GrpcClientInstrumentationOptions.SuppressDownstreamInstrumentation.set -> void diff --git a/src/OpenTelemetry.Instrumentation.GrpcNetClient/CHANGELOG.md b/src/OpenTelemetry.Instrumentation.GrpcNetClient/CHANGELOG.md index 3a7cdbfdea3..08545533222 100644 --- a/src/OpenTelemetry.Instrumentation.GrpcNetClient/CHANGELOG.md +++ b/src/OpenTelemetry.Instrumentation.GrpcNetClient/CHANGELOG.md @@ -2,6 +2,21 @@ ## Unreleased + **Breaking change** The `Enrich` callback option has been removed. For better + usability, it has been replaced by two separate options: + `EnrichWithHttpRequestMessage`and `EnrichWithHttpResponseMessage`. Previously, + the single `Enrich` callback required the consumer to detect which event + triggered the callback to be invoked (e.g., request start or response end) and + then cast the object received to the appropriate type: `HttpRequestMessage` + and `HttpResponseMessage`. The separate callbacks make it clear what event + triggers them and there is no longer the need to cast the argument to the + expected type. + ([#3804](https://github.com/open-telemetry/opentelemetry-dotnet/pull/3804)) + +## 1.0.0-rc9.8 + +Released 2022-Oct-17 + ## 1.0.0-rc9.7 Released 2022-Sep-29 diff --git a/src/OpenTelemetry.Instrumentation.GrpcNetClient/GrpcClientInstrumentation.cs b/src/OpenTelemetry.Instrumentation.GrpcNetClient/GrpcClientInstrumentation.cs index 75242e5a876..df827346111 100644 --- a/src/OpenTelemetry.Instrumentation.GrpcNetClient/GrpcClientInstrumentation.cs +++ b/src/OpenTelemetry.Instrumentation.GrpcNetClient/GrpcClientInstrumentation.cs @@ -21,7 +21,7 @@ namespace OpenTelemetry.Instrumentation.GrpcNetClient /// /// GrpcClient instrumentation. /// - internal class GrpcClientInstrumentation : IDisposable + internal sealed class GrpcClientInstrumentation : IDisposable { private readonly DiagnosticSourceSubscriber diagnosticSourceSubscriber; diff --git a/src/OpenTelemetry.Instrumentation.GrpcNetClient/GrpcClientInstrumentationOptions.cs b/src/OpenTelemetry.Instrumentation.GrpcNetClient/GrpcClientInstrumentationOptions.cs index 91735e3a864..8a055128b03 100644 --- a/src/OpenTelemetry.Instrumentation.GrpcNetClient/GrpcClientInstrumentationOptions.cs +++ b/src/OpenTelemetry.Instrumentation.GrpcNetClient/GrpcClientInstrumentationOptions.cs @@ -16,6 +16,7 @@ using System; using System.Diagnostics; +using System.Net.Http; namespace OpenTelemetry.Instrumentation.GrpcNetClient { @@ -30,14 +31,21 @@ public class GrpcClientInstrumentationOptions public bool SuppressDownstreamInstrumentation { get; set; } /// - /// Gets or sets an action to enrich an Activity. + /// Gets or sets an action to enrich the Activity with . /// /// /// : the activity being enriched. - /// string: the name of the event. - /// object: the raw object from which additional information can be extracted to enrich the activity. - /// The type of this object depends on the event, which is given by the above parameter. + /// object from which additional information can be extracted to enrich the activity. /// - public Action Enrich { get; set; } + public Action EnrichWithHttpRequestMessage { get; set; } + + /// + /// Gets or sets an action to enrich an Activity with . + /// + /// + /// : the activity being enriched. + /// object from which additional information can be extracted to enrich the activity. + /// + public Action EnrichWithHttpResponseMessage { get; set; } } } diff --git a/src/OpenTelemetry.Instrumentation.GrpcNetClient/Implementation/GrpcClientDiagnosticListener.cs b/src/OpenTelemetry.Instrumentation.GrpcNetClient/Implementation/GrpcClientDiagnosticListener.cs index 299d9ff9f8e..179831d2a67 100644 --- a/src/OpenTelemetry.Instrumentation.GrpcNetClient/Implementation/GrpcClientDiagnosticListener.cs +++ b/src/OpenTelemetry.Instrumentation.GrpcNetClient/Implementation/GrpcClientDiagnosticListener.cs @@ -150,7 +150,7 @@ public void OnStartActivity(Activity activity, object payload) try { - this.options.Enrich?.Invoke(activity, "OnStartActivity", request); + this.options.EnrichWithHttpRequestMessage?.Invoke(activity, request); } catch (Exception ex) { @@ -182,7 +182,7 @@ public void OnStopActivity(Activity activity, object payload) { try { - this.options.Enrich?.Invoke(activity, "OnStopActivity", response); + this.options.EnrichWithHttpResponseMessage?.Invoke(activity, response); } catch (Exception ex) { diff --git a/src/OpenTelemetry.Instrumentation.GrpcNetClient/Implementation/GrpcInstrumentationEventSource.cs b/src/OpenTelemetry.Instrumentation.GrpcNetClient/Implementation/GrpcInstrumentationEventSource.cs index 340ddb73603..c171c21c59b 100644 --- a/src/OpenTelemetry.Instrumentation.GrpcNetClient/Implementation/GrpcInstrumentationEventSource.cs +++ b/src/OpenTelemetry.Instrumentation.GrpcNetClient/Implementation/GrpcInstrumentationEventSource.cs @@ -24,7 +24,7 @@ namespace OpenTelemetry.Instrumentation.GrpcNetClient.Implementation /// EventSource events emitted from the project. /// [EventSource(Name = "OpenTelemetry-Instrumentation-Grpc")] - internal class GrpcInstrumentationEventSource : EventSource + internal sealed class GrpcInstrumentationEventSource : EventSource { public static GrpcInstrumentationEventSource Log = new(); diff --git a/src/OpenTelemetry.Instrumentation.GrpcNetClient/README.md b/src/OpenTelemetry.Instrumentation.GrpcNetClient/README.md index 7dcb2d2c98c..462f5439321 100644 --- a/src/OpenTelemetry.Instrumentation.GrpcNetClient/README.md +++ b/src/OpenTelemetry.Instrumentation.GrpcNetClient/README.md @@ -99,31 +99,29 @@ using var tracerProvider = Sdk.CreateTracerProviderBuilder() ### Enrich -This option allows one to enrich the activity with additional information -from the raw `HttpRequestMessage` object. The `Enrich` action is called only -when `activity.IsAllDataRequested` is `true`. It contains the activity itself -(which can be enriched), the name of the event, and the actual raw object. -For event name "OnStartActivity", the actual object will be -`HttpRequestMessage`. - -The following code snippet shows how to add additional tags using `Enrich`. +This instrumentation library provides `EnrichWithHttpRequestMessage` and +`EnrichWithHttpResponseMessage` options that can be used to enrich the activity +with additional information from the raw `HttpRequestMessage` and +`HttpResponseMessage` objects respectively. These actions are called only when +`activity.IsAllDataRequested` is `true`. It contains the activity itself (which +can be enriched), the name of the event, and the actual raw object. The +following code snippet shows how to add additional tags using these options. ```csharp services.AddOpenTelemetryTracing((builder) => { builder - .AddGrpcClientInstrumentation(opt => opt.Enrich - = (activity, eventName, rawObject) => + .AddGrpcClientInstrumentation((options) => { - if (eventName.Equals("OnStartActivity")) + options.EnrichWithHttpRequestMessage = (activity, httpRequestMessage) => + { + activity.SetTag("requestVersion", httpRequestMessage.Version); + }; + options.EnrichWithHttpResponseMessage = (activity, httpResponseMessage) => { - if (rawObject is HttpRequestMessage request) - { - activity.SetTag("requestVersion", request.Version); - } - } + activity.SetTag("responseVersion", httpResponseMessage.Version); + }; }) -}); ``` [Processor](../../docs/trace/extending-the-sdk/README.md#processor), diff --git a/src/OpenTelemetry.Instrumentation.Http/.publicApi/net462/PublicAPI.Unshipped.txt b/src/OpenTelemetry.Instrumentation.Http/.publicApi/net462/PublicAPI.Unshipped.txt index 2a3aa89a04a..dd82537749e 100644 --- a/src/OpenTelemetry.Instrumentation.Http/.publicApi/net462/PublicAPI.Unshipped.txt +++ b/src/OpenTelemetry.Instrumentation.Http/.publicApi/net462/PublicAPI.Unshipped.txt @@ -1,14 +1,22 @@ OpenTelemetry.Instrumentation.Http.HttpClientInstrumentationOptions -OpenTelemetry.Instrumentation.Http.HttpClientInstrumentationOptions.Enrich.get -> System.Action -OpenTelemetry.Instrumentation.Http.HttpClientInstrumentationOptions.Enrich.set -> void +OpenTelemetry.Instrumentation.Http.HttpClientInstrumentationOptions.EnrichWithException.get -> System.Action +OpenTelemetry.Instrumentation.Http.HttpClientInstrumentationOptions.EnrichWithException.set -> void +OpenTelemetry.Instrumentation.Http.HttpClientInstrumentationOptions.EnrichWithHttpRequestMessage.get -> System.Action +OpenTelemetry.Instrumentation.Http.HttpClientInstrumentationOptions.EnrichWithHttpRequestMessage.set -> void +OpenTelemetry.Instrumentation.Http.HttpClientInstrumentationOptions.EnrichWithHttpResponseMessage.get -> System.Action +OpenTelemetry.Instrumentation.Http.HttpClientInstrumentationOptions.EnrichWithHttpResponseMessage.set -> void OpenTelemetry.Instrumentation.Http.HttpClientInstrumentationOptions.Filter.get -> System.Func OpenTelemetry.Instrumentation.Http.HttpClientInstrumentationOptions.Filter.set -> void OpenTelemetry.Instrumentation.Http.HttpClientInstrumentationOptions.HttpClientInstrumentationOptions() -> void OpenTelemetry.Instrumentation.Http.HttpClientInstrumentationOptions.RecordException.get -> bool OpenTelemetry.Instrumentation.Http.HttpClientInstrumentationOptions.RecordException.set -> void OpenTelemetry.Instrumentation.Http.HttpWebRequestInstrumentationOptions -OpenTelemetry.Instrumentation.Http.HttpWebRequestInstrumentationOptions.Enrich.get -> System.Action -OpenTelemetry.Instrumentation.Http.HttpWebRequestInstrumentationOptions.Enrich.set -> void +OpenTelemetry.Instrumentation.Http.HttpWebRequestInstrumentationOptions.EnrichWithException.get -> System.Action +OpenTelemetry.Instrumentation.Http.HttpWebRequestInstrumentationOptions.EnrichWithException.set -> void +OpenTelemetry.Instrumentation.Http.HttpWebRequestInstrumentationOptions.EnrichWithHttpWebRequest.get -> System.Action +OpenTelemetry.Instrumentation.Http.HttpWebRequestInstrumentationOptions.EnrichWithHttpWebRequest.set -> void +OpenTelemetry.Instrumentation.Http.HttpWebRequestInstrumentationOptions.EnrichWithHttpWebResponse.get -> System.Action +OpenTelemetry.Instrumentation.Http.HttpWebRequestInstrumentationOptions.EnrichWithHttpWebResponse.set -> void OpenTelemetry.Instrumentation.Http.HttpWebRequestInstrumentationOptions.Filter.get -> System.Func OpenTelemetry.Instrumentation.Http.HttpWebRequestInstrumentationOptions.Filter.set -> void OpenTelemetry.Instrumentation.Http.HttpWebRequestInstrumentationOptions.HttpWebRequestInstrumentationOptions() -> void diff --git a/src/OpenTelemetry.Instrumentation.Http/.publicApi/net6.0/PublicAPI.Unshipped.txt b/src/OpenTelemetry.Instrumentation.Http/.publicApi/net6.0/PublicAPI.Unshipped.txt index 0224a11a2e5..1590f0c3d90 100644 --- a/src/OpenTelemetry.Instrumentation.Http/.publicApi/net6.0/PublicAPI.Unshipped.txt +++ b/src/OpenTelemetry.Instrumentation.Http/.publicApi/net6.0/PublicAPI.Unshipped.txt @@ -1,6 +1,10 @@ OpenTelemetry.Instrumentation.Http.HttpClientInstrumentationOptions -OpenTelemetry.Instrumentation.Http.HttpClientInstrumentationOptions.Enrich.get -> System.Action -OpenTelemetry.Instrumentation.Http.HttpClientInstrumentationOptions.Enrich.set -> void +OpenTelemetry.Instrumentation.Http.HttpClientInstrumentationOptions.EnrichWithException.get -> System.Action +OpenTelemetry.Instrumentation.Http.HttpClientInstrumentationOptions.EnrichWithException.set -> void +OpenTelemetry.Instrumentation.Http.HttpClientInstrumentationOptions.EnrichWithHttpRequestMessage.get -> System.Action +OpenTelemetry.Instrumentation.Http.HttpClientInstrumentationOptions.EnrichWithHttpRequestMessage.set -> void +OpenTelemetry.Instrumentation.Http.HttpClientInstrumentationOptions.EnrichWithHttpResponseMessage.get -> System.Action +OpenTelemetry.Instrumentation.Http.HttpClientInstrumentationOptions.EnrichWithHttpResponseMessage.set -> void OpenTelemetry.Instrumentation.Http.HttpClientInstrumentationOptions.Filter.get -> System.Func OpenTelemetry.Instrumentation.Http.HttpClientInstrumentationOptions.Filter.set -> void OpenTelemetry.Instrumentation.Http.HttpClientInstrumentationOptions.HttpClientInstrumentationOptions() -> void diff --git a/src/OpenTelemetry.Instrumentation.Http/.publicApi/netstandard2.0/PublicAPI.Shipped.txt b/src/OpenTelemetry.Instrumentation.Http/.publicApi/netstandard2.0/PublicAPI.Shipped.txt new file mode 100644 index 00000000000..e69de29bb2d diff --git a/src/OpenTelemetry.Instrumentation.Http/.publicApi/netstandard2.0/PublicAPI.Unshipped.txt b/src/OpenTelemetry.Instrumentation.Http/.publicApi/netstandard2.0/PublicAPI.Unshipped.txt new file mode 100644 index 00000000000..1590f0c3d90 --- /dev/null +++ b/src/OpenTelemetry.Instrumentation.Http/.publicApi/netstandard2.0/PublicAPI.Unshipped.txt @@ -0,0 +1,18 @@ +OpenTelemetry.Instrumentation.Http.HttpClientInstrumentationOptions +OpenTelemetry.Instrumentation.Http.HttpClientInstrumentationOptions.EnrichWithException.get -> System.Action +OpenTelemetry.Instrumentation.Http.HttpClientInstrumentationOptions.EnrichWithException.set -> void +OpenTelemetry.Instrumentation.Http.HttpClientInstrumentationOptions.EnrichWithHttpRequestMessage.get -> System.Action +OpenTelemetry.Instrumentation.Http.HttpClientInstrumentationOptions.EnrichWithHttpRequestMessage.set -> void +OpenTelemetry.Instrumentation.Http.HttpClientInstrumentationOptions.EnrichWithHttpResponseMessage.get -> System.Action +OpenTelemetry.Instrumentation.Http.HttpClientInstrumentationOptions.EnrichWithHttpResponseMessage.set -> void +OpenTelemetry.Instrumentation.Http.HttpClientInstrumentationOptions.Filter.get -> System.Func +OpenTelemetry.Instrumentation.Http.HttpClientInstrumentationOptions.Filter.set -> void +OpenTelemetry.Instrumentation.Http.HttpClientInstrumentationOptions.HttpClientInstrumentationOptions() -> void +OpenTelemetry.Instrumentation.Http.HttpClientInstrumentationOptions.RecordException.get -> bool +OpenTelemetry.Instrumentation.Http.HttpClientInstrumentationOptions.RecordException.set -> void +OpenTelemetry.Metrics.MeterProviderBuilderExtensions +OpenTelemetry.Trace.TracerProviderBuilderExtensions +static OpenTelemetry.Metrics.MeterProviderBuilderExtensions.AddHttpClientInstrumentation(this OpenTelemetry.Metrics.MeterProviderBuilder builder) -> OpenTelemetry.Metrics.MeterProviderBuilder +static OpenTelemetry.Trace.TracerProviderBuilderExtensions.AddHttpClientInstrumentation(this OpenTelemetry.Trace.TracerProviderBuilder builder) -> OpenTelemetry.Trace.TracerProviderBuilder +static OpenTelemetry.Trace.TracerProviderBuilderExtensions.AddHttpClientInstrumentation(this OpenTelemetry.Trace.TracerProviderBuilder builder, string name, System.Action configureHttpClientInstrumentationOptions) -> OpenTelemetry.Trace.TracerProviderBuilder +static OpenTelemetry.Trace.TracerProviderBuilderExtensions.AddHttpClientInstrumentation(this OpenTelemetry.Trace.TracerProviderBuilder builder, System.Action configureHttpClientInstrumentationOptions) -> OpenTelemetry.Trace.TracerProviderBuilder diff --git a/src/OpenTelemetry.Instrumentation.Http/CHANGELOG.md b/src/OpenTelemetry.Instrumentation.Http/CHANGELOG.md index d3158da9348..ce0ac8eb52c 100644 --- a/src/OpenTelemetry.Instrumentation.Http/CHANGELOG.md +++ b/src/OpenTelemetry.Instrumentation.Http/CHANGELOG.md @@ -2,6 +2,33 @@ ## Unreleased +* *Breaking change** The `Enrich` callback option has been removed. For better + usability, it has been replaced by three separate options: In case of + `HttpClient` the new options are `EnrichWithHttpRequestMessage`, + `EnrichWithHttpResponseMessage` and `EnrichWithException` and in case of + `HttpWebRequest` the new options are `EnrichWithHttpWebRequest`, + `EnrichWithHttpWebResponse` and `EnrichWithException`. Previously, the single + `Enrich` callback required the consumer to detect which event triggered the + callback to be invoked (e.g., request start, response end, or an exception) + and then cast the object received to the appropriate type: + `HttpRequestMessage`, `HttpResponsemessage`, or `Exception` in case of + `HttpClient` and `HttpWebRequest`,`HttpWebResponse` and `Exception` in case of + `HttpWebRequest`. The separate callbacks make it clear what event triggers + them and there is no longer the need to cast the argument to the expected +type. +([#3792](https://github.com/open-telemetry/opentelemetry-dotnet/pull/3792)) + +* Added back `netstandard2.0` target. +([#3787](https://github.com/open-telemetry/opentelemetry-dotnet/pull/3787)) + +## 1.0.0-rc9.8 + +Released 2022-Oct-17 + +* In case of .NET Core, additional spans created during retries will now be +exported. +([[#3729](https://github.com/open-telemetry/opentelemetry-dotnet/issues/3729)]) + ## 1.0.0-rc9.7 Released 2022-Sep-29 diff --git a/src/OpenTelemetry.Instrumentation.Http/HttpClientInstrumentation.cs b/src/OpenTelemetry.Instrumentation.Http/HttpClientInstrumentation.cs index 09fc1f3c0ae..4c7a42a0cb4 100644 --- a/src/OpenTelemetry.Instrumentation.Http/HttpClientInstrumentation.cs +++ b/src/OpenTelemetry.Instrumentation.Http/HttpClientInstrumentation.cs @@ -21,7 +21,7 @@ namespace OpenTelemetry.Instrumentation.Http /// /// HttpClient instrumentation. /// - internal class HttpClientInstrumentation : IDisposable + internal sealed class HttpClientInstrumentation : IDisposable { private readonly DiagnosticSourceSubscriber diagnosticSourceSubscriber; diff --git a/src/OpenTelemetry.Instrumentation.Http/HttpClientInstrumentationOptions.cs b/src/OpenTelemetry.Instrumentation.Http/HttpClientInstrumentationOptions.cs index 6206cfee3c8..8bf9a96be78 100644 --- a/src/OpenTelemetry.Instrumentation.Http/HttpClientInstrumentationOptions.cs +++ b/src/OpenTelemetry.Instrumentation.Http/HttpClientInstrumentationOptions.cs @@ -36,15 +36,31 @@ public class HttpClientInstrumentationOptions public Func Filter { get; set; } /// - /// Gets or sets an action to enrich an Activity. + /// Gets or sets an action to enrich an Activity with . /// /// /// : the activity being enriched. - /// string: the name of the event. - /// object: the raw object from which additional information can be extracted to enrich the activity. - /// The type of this object depends on the event, which is given by the above parameter. + /// object from which additional information can be extracted to enrich the activity. /// - public Action Enrich { get; set; } + public Action EnrichWithHttpRequestMessage { get; set; } + + /// + /// Gets or sets an action to enrich an Activity with . + /// + /// + /// : the activity being enriched. + /// object from which additional information can be extracted to enrich the activity. + /// + public Action EnrichWithHttpResponseMessage { get; set; } + + /// + /// Gets or sets an action to enrich an Activity with . + /// + /// + /// : the activity being enriched. + /// object from which additional information can be extracted to enrich the activity. + /// + public Action EnrichWithException { get; set; } /// /// Gets or sets a value indicating whether exception will be recorded as ActivityEvent or not. diff --git a/src/OpenTelemetry.Instrumentation.Http/HttpClientMetrics.cs b/src/OpenTelemetry.Instrumentation.Http/HttpClientMetrics.cs index c0502219e3b..27b39f5da17 100644 --- a/src/OpenTelemetry.Instrumentation.Http/HttpClientMetrics.cs +++ b/src/OpenTelemetry.Instrumentation.Http/HttpClientMetrics.cs @@ -24,7 +24,7 @@ namespace OpenTelemetry.Instrumentation.Http /// /// HttpClient instrumentation. /// - internal class HttpClientMetrics : IDisposable + internal sealed class HttpClientMetrics : IDisposable { internal static readonly AssemblyName AssemblyName = typeof(HttpClientMetrics).Assembly.GetName(); internal static readonly string InstrumentationName = AssemblyName.Name; diff --git a/src/OpenTelemetry.Instrumentation.Http/HttpRequestMessageContextPropagation.cs b/src/OpenTelemetry.Instrumentation.Http/HttpRequestMessageContextPropagation.cs index 16999593811..14b26850e97 100644 --- a/src/OpenTelemetry.Instrumentation.Http/HttpRequestMessageContextPropagation.cs +++ b/src/OpenTelemetry.Instrumentation.Http/HttpRequestMessageContextPropagation.cs @@ -34,6 +34,7 @@ internal static class HttpRequestMessageContextPropagation internal static Action HeaderValueSetter => (request, name, value) => { + request.Headers.Remove(name); request.Headers.Add(name, value); }; } diff --git a/src/OpenTelemetry.Instrumentation.Http/HttpWebRequestInstrumentationOptions.netfx.cs b/src/OpenTelemetry.Instrumentation.Http/HttpWebRequestInstrumentationOptions.netfx.cs index b695aebf367..11243d151a9 100644 --- a/src/OpenTelemetry.Instrumentation.Http/HttpWebRequestInstrumentationOptions.netfx.cs +++ b/src/OpenTelemetry.Instrumentation.Http/HttpWebRequestInstrumentationOptions.netfx.cs @@ -36,15 +36,31 @@ public class HttpWebRequestInstrumentationOptions public Func Filter { get; set; } /// - /// Gets or sets an action to enrich an Activity. + /// Gets or sets an action to enrich an Activity with . /// /// /// : the activity being enriched. - /// string: the name of the event. - /// object: the raw object from which additional information can be extracted to enrich the activity. - /// The type of this object depends on the event, which is given by the above parameter. + /// object from which additional information can be extracted to enrich the activity. /// - public Action Enrich { get; set; } + public Action EnrichWithHttpWebRequest { get; set; } + + /// + /// Gets or sets an action to enrich an Activity with . + /// + /// + /// : the activity being enriched. + /// object from which additional information can be extracted to enrich the activity. + /// + public Action EnrichWithHttpWebResponse { get; set; } + + /// + /// Gets or sets an action to enrich an Activity with . + /// + /// + /// : the activity being enriched. + /// object from which additional information can be extracted to enrich the activity. + /// + public Action EnrichWithException { get; set; } /// /// Gets or sets a value indicating whether exception will be recorded as ActivityEvent or not. diff --git a/src/OpenTelemetry.Instrumentation.Http/Implementation/HttpHandlerDiagnosticListener.cs b/src/OpenTelemetry.Instrumentation.Http/Implementation/HttpHandlerDiagnosticListener.cs index 2b1e741906d..4a0ed555d9c 100644 --- a/src/OpenTelemetry.Instrumentation.Http/Implementation/HttpHandlerDiagnosticListener.cs +++ b/src/OpenTelemetry.Instrumentation.Http/Implementation/HttpHandlerDiagnosticListener.cs @@ -115,14 +115,6 @@ public void OnStartActivity(Activity activity, object payload) return; } - // TODO: Investigate why this check is needed. - if (Propagators.DefaultTextMapPropagator.Extract(default, request, HttpRequestMessageContextPropagation.HeaderValuesGetter) != default) - { - // this request is already instrumented, we should back off - activity.IsAllDataRequested = false; - return; - } - // Propagate context irrespective of sampling decision var textMapPropagator = Propagators.DefaultTextMapPropagator; if (textMapPropagator is not TraceContextPropagator) @@ -168,7 +160,7 @@ public void OnStartActivity(Activity activity, object payload) try { - this.options.Enrich?.Invoke(activity, "OnStartActivity", request); + this.options.EnrichWithHttpRequestMessage?.Invoke(activity, request); } catch (Exception ex) { @@ -225,7 +217,7 @@ public void OnStopActivity(Activity activity, object payload) try { - this.options.Enrich?.Invoke(activity, "OnStopActivity", response); + this.options.EnrichWithHttpResponseMessage?.Invoke(activity, response); } catch (Exception ex) { @@ -266,7 +258,7 @@ public void OnException(Activity activity, object payload) try { - this.options.Enrich?.Invoke(activity, "OnException", exc); + this.options.EnrichWithException?.Invoke(activity, exc); } catch (Exception ex) { diff --git a/src/OpenTelemetry.Instrumentation.Http/Implementation/HttpHandlerMetricsDiagnosticListener.cs b/src/OpenTelemetry.Instrumentation.Http/Implementation/HttpHandlerMetricsDiagnosticListener.cs index 2e8234f00db..8b2ebf0a678 100644 --- a/src/OpenTelemetry.Instrumentation.Http/Implementation/HttpHandlerMetricsDiagnosticListener.cs +++ b/src/OpenTelemetry.Instrumentation.Http/Implementation/HttpHandlerMetricsDiagnosticListener.cs @@ -22,7 +22,7 @@ namespace OpenTelemetry.Instrumentation.Http.Implementation { - internal class HttpHandlerMetricsDiagnosticListener : ListenerHandler + internal sealed class HttpHandlerMetricsDiagnosticListener : ListenerHandler { internal const string OnStopEvent = "System.Net.Http.HttpRequestOut.Stop"; diff --git a/src/OpenTelemetry.Instrumentation.Http/Implementation/HttpInstrumentationEventSource.cs b/src/OpenTelemetry.Instrumentation.Http/Implementation/HttpInstrumentationEventSource.cs index 746d4d873a0..a0a5e6fa967 100644 --- a/src/OpenTelemetry.Instrumentation.Http/Implementation/HttpInstrumentationEventSource.cs +++ b/src/OpenTelemetry.Instrumentation.Http/Implementation/HttpInstrumentationEventSource.cs @@ -24,7 +24,7 @@ namespace OpenTelemetry.Instrumentation.Http.Implementation /// EventSource events emitted from the project. /// [EventSource(Name = "OpenTelemetry-Instrumentation-Http")] - internal class HttpInstrumentationEventSource : EventSource + internal sealed class HttpInstrumentationEventSource : EventSource { public static HttpInstrumentationEventSource Log = new(); diff --git a/src/OpenTelemetry.Instrumentation.Http/Implementation/HttpWebRequestActivitySource.netfx.cs b/src/OpenTelemetry.Instrumentation.Http/Implementation/HttpWebRequestActivitySource.netfx.cs index 1eb7c9cd2dc..26c34cbd789 100644 --- a/src/OpenTelemetry.Instrumentation.Http/Implementation/HttpWebRequestActivitySource.netfx.cs +++ b/src/OpenTelemetry.Instrumentation.Http/Implementation/HttpWebRequestActivitySource.netfx.cs @@ -104,7 +104,7 @@ private static void AddRequestTagsAndInstrumentRequest(HttpWebRequest request, A try { - Options.Enrich?.Invoke(activity, "OnStartActivity", request); + Options.EnrichWithHttpWebRequest?.Invoke(activity, request); } catch (Exception ex) { @@ -124,7 +124,7 @@ private static void AddResponseTags(HttpWebResponse response, Activity activity) try { - Options.Enrich?.Invoke(activity, "OnStopActivity", response); + Options.EnrichWithHttpWebResponse?.Invoke(activity, response); } catch (Exception ex) { @@ -190,7 +190,7 @@ private static void AddExceptionTags(Exception exception, Activity activity) try { - Options.Enrich?.Invoke(activity, "OnException", exception); + Options.EnrichWithException?.Invoke(activity, exception); } catch (Exception ex) { diff --git a/src/OpenTelemetry.Instrumentation.Http/OpenTelemetry.Instrumentation.Http.csproj b/src/OpenTelemetry.Instrumentation.Http/OpenTelemetry.Instrumentation.Http.csproj index 621422a822b..297a6ff0bcc 100644 --- a/src/OpenTelemetry.Instrumentation.Http/OpenTelemetry.Instrumentation.Http.csproj +++ b/src/OpenTelemetry.Instrumentation.Http/OpenTelemetry.Instrumentation.Http.csproj @@ -2,7 +2,7 @@ - net6.0;net462 + net6.0;netstandard2.0;net462 Http instrumentation for OpenTelemetry .NET $(PackageTags);distributed-tracing true diff --git a/src/OpenTelemetry.Instrumentation.Http/README.md b/src/OpenTelemetry.Instrumentation.Http/README.md index 41994615b26..6dcd670597b 100644 --- a/src/OpenTelemetry.Instrumentation.Http/README.md +++ b/src/OpenTelemetry.Instrumentation.Http/README.md @@ -112,22 +112,19 @@ and the `Filter` option does the filtering *after* the Sampler is invoked. ### Enrich -This option allows one to enrich the activity with additional information from -the raw request and response objects. The `Enrich` action is called only when -`activity.IsAllDataRequested` is `true`. It contains the activity itself (which -can be enriched), the name of the event, and the actual raw object. The object -type is different for `HttpClientInstrumentationOptions` vs +This instrumentation library provides options that can be used to +enrich the activity with additional information. These actions are called +only when `activity.IsAllDataRequested` is `true`. It contains the activity +itself (which can be enriched) and the actual raw object. The options +are different for `HttpClientInstrumentationOptions` vs `HttpWebRequestInstrumentationOptions` and is detailed below. #### HttpClientInstrumentationOptions -For event name "OnStartActivity", the actual object will be -`HttpRequestMessage`. - -For event name "OnStopActivity", the actual object will be -`HttpResponseMessage`. - -For event name "OnException", the actual object will be `Exception`. +HttpClientInstrumentationOptions provides 3 enrich options, +`EnrichWithHttpRequestMessage`, `EnrichWithHttpResponseMessage` and +`EnrichWithException`. These are based on the raw object that is passed in to +the action to enrich the activity. Example: @@ -135,40 +132,30 @@ Example: using System.Net.Http; var tracerProvider = Sdk.CreateTracerProviderBuilder() - .AddHttpClientInstrumentation((options) => options.Enrich - = (activity, eventName, rawObject) => + .AddHttpClientInstrumentation((options) => { - if (eventName.Equals("OnStartActivity")) + options.EnrichWithHttpRequestMessage = (activity, httpRequestMessage) => { - if (rawObject is HttpRequestMessage request) - { - activity.SetTag("requestVersion", request.Version); - } - } - else if (eventName.Equals("OnStopActivity")) + activity.SetTag("requestVersion", httpRequestMessage.Version); + }; + options.EnrichWithHttpResponseMessage = (activity, httpResponseMessage) => { - if (rawObject is HttpResponseMessage response) - { - activity.SetTag("responseVersion", response.Version); - } - } - else if (eventName.Equals("OnException")) + activity.SetTag("responseVersion", httpResponseMessage.Version); + }; + options.EnrichWithException = (activity, exception) => { - if (rawObject is Exception exception) - { - activity.SetTag("stackTrace", exception.StackTrace); - } - } - }).Build(); + activity.SetTag("stackTrace", exception.StackTrace); + }; + }) + .Build(); ``` #### HttpWebRequestInstrumentationOptions -For event name "OnStartActivity", the actual object will be `HttpWebRequest`. - -For event name "OnStopActivity", the actual object will be `HttpWebResponse`. - -For event name "OnException", the actual object will be `Exception`. +HttpClientInstrumentationOptions provides 3 enrich options, +`EnrichWithHttpWebRequest`, `EnrichWithHttpWebResponse` and +`EnrichWithException`. These are based on the raw object that is passed in to +the action to enrich the activity. Example: @@ -176,31 +163,22 @@ Example: using System.Net; var tracerProvider = Sdk.CreateTracerProviderBuilder() - .AddHttpClientInstrumentation((options) => options.Enrich - = (activity, eventName, rawObject) => + .AddHttpClientInstrumentation((options) => { - if (eventName.Equals("OnStartActivity")) + options.EnrichWithHttpWebRequest = (activity, httpWebRequest) => { - if (rawObject is HttpWebRequest request) - { - activity.SetTag("requestVersion", request.ProtocolVersion); - } - } - else if (eventName.Equals("OnStopActivity")) + activity.SetTag("requestVersion", httpWebRequest.Version); + }; + options.EnrichWithHttpWebResponse = (activity, httpWebResponse) => { - if (rawObject is HttpWebResponse response) - { - activity.SetTag("responseVersion", response.ProtocolVersion); - } - } - else if (eventName.Equals("OnException")) + activity.SetTag("responseVersion", httpWebResponse.Version); + }; + options.EnrichWithException = (activity, exception) => { - if (rawObject is Exception exception) - { - activity.SetTag("stackTrace", exception.StackTrace); - } - } - }).Build(); + activity.SetTag("stackTrace", exception.StackTrace); + }; + }) + .Build(); ``` [Processor](../../docs/trace/extending-the-sdk/README.md#processor), is the diff --git a/src/OpenTelemetry.Instrumentation.SqlClient/.publicApi/netstandard2.0/PublicAPI.Unshipped.txt b/src/OpenTelemetry.Instrumentation.SqlClient/.publicApi/netstandard2.0/PublicAPI.Unshipped.txt index 097e255db3b..efaab3dc114 100644 --- a/src/OpenTelemetry.Instrumentation.SqlClient/.publicApi/netstandard2.0/PublicAPI.Unshipped.txt +++ b/src/OpenTelemetry.Instrumentation.SqlClient/.publicApi/netstandard2.0/PublicAPI.Unshipped.txt @@ -3,6 +3,8 @@ OpenTelemetry.Instrumentation.SqlClient.SqlClientInstrumentationOptions.EnableCo OpenTelemetry.Instrumentation.SqlClient.SqlClientInstrumentationOptions.EnableConnectionLevelAttributes.set -> void OpenTelemetry.Instrumentation.SqlClient.SqlClientInstrumentationOptions.Enrich.get -> System.Action OpenTelemetry.Instrumentation.SqlClient.SqlClientInstrumentationOptions.Enrich.set -> void +OpenTelemetry.Instrumentation.SqlClient.SqlClientInstrumentationOptions.Filter.get -> System.Func +OpenTelemetry.Instrumentation.SqlClient.SqlClientInstrumentationOptions.Filter.set -> void OpenTelemetry.Instrumentation.SqlClient.SqlClientInstrumentationOptions.RecordException.get -> bool OpenTelemetry.Instrumentation.SqlClient.SqlClientInstrumentationOptions.RecordException.set -> void OpenTelemetry.Instrumentation.SqlClient.SqlClientInstrumentationOptions.SetDbStatementForStoredProcedure.get -> bool diff --git a/src/OpenTelemetry.Instrumentation.SqlClient/CHANGELOG.md b/src/OpenTelemetry.Instrumentation.SqlClient/CHANGELOG.md index 23af195b8d5..63b5dec1c1c 100644 --- a/src/OpenTelemetry.Instrumentation.SqlClient/CHANGELOG.md +++ b/src/OpenTelemetry.Instrumentation.SqlClient/CHANGELOG.md @@ -2,6 +2,18 @@ ## Unreleased +## 1.0.0-rc9.8 + +Released 2022-Oct-17 + +* Use `Activity.Status` and `Activity.StatusDescription` properties instead of + `OpenTelemetry.Trace.Status` and `OpenTelemetry.Trace.Status.Description` + respectively to set activity status. + ([#3118](https://github.com/open-telemetry/opentelemetry-dotnet/issues/3118)) + ([#3751](https://github.com/open-telemetry/opentelemetry-dotnet/pull/3751)) +* Add support for Filter option for non .NET Framework Targets + ([#3743](https://github.com/open-telemetry/opentelemetry-dotnet/pull/3743)) + ## 1.0.0-rc9.7 Released 2022-Sep-29 diff --git a/src/OpenTelemetry.Instrumentation.SqlClient/Implementation/SqlActivitySourceHelper.cs b/src/OpenTelemetry.Instrumentation.SqlClient/Implementation/SqlActivitySourceHelper.cs index 95c68fda943..fbf4fb7d83a 100644 --- a/src/OpenTelemetry.Instrumentation.SqlClient/Implementation/SqlActivitySourceHelper.cs +++ b/src/OpenTelemetry.Instrumentation.SqlClient/Implementation/SqlActivitySourceHelper.cs @@ -25,7 +25,7 @@ namespace OpenTelemetry.Instrumentation.SqlClient.Implementation /// Helper class to hold common properties used by both SqlClientDiagnosticListener on .NET Core /// and SqlEventSourceListener on .NET Framework. /// - internal class SqlActivitySourceHelper + internal sealed class SqlActivitySourceHelper { public const string MicrosoftSqlServerDatabaseSystemName = "mssql"; diff --git a/src/OpenTelemetry.Instrumentation.SqlClient/Implementation/SqlClientDiagnosticListener.cs b/src/OpenTelemetry.Instrumentation.SqlClient/Implementation/SqlClientDiagnosticListener.cs index 4f360bcbf18..b383ab03896 100644 --- a/src/OpenTelemetry.Instrumentation.SqlClient/Implementation/SqlClientDiagnosticListener.cs +++ b/src/OpenTelemetry.Instrumentation.SqlClient/Implementation/SqlClientDiagnosticListener.cs @@ -80,6 +80,24 @@ public override void OnEventWritten(string name, object payload) if (activity.IsAllDataRequested) { + try + { + if (this.options.Filter?.Invoke(command) == false) + { + SqlClientInstrumentationEventSource.Log.CommandIsFilteredOut(activity.OperationName); + activity.IsAllDataRequested = false; + activity.ActivityTraceFlags &= ~ActivityTraceFlags.Recorded; + return; + } + } + catch (Exception ex) + { + SqlClientInstrumentationEventSource.Log.CommandFilterException(ex); + activity.IsAllDataRequested = false; + activity.ActivityTraceFlags &= ~ActivityTraceFlags.Recorded; + return; + } + _ = this.connectionFetcher.TryFetch(command, out var connection); _ = this.databaseFetcher.TryFetch(connection, out var database); @@ -146,17 +164,7 @@ public override void OnEventWritten(string name, object payload) return; } - try - { - if (activity.IsAllDataRequested) - { - activity.SetStatus(Status.Unset); - } - } - finally - { - activity.Stop(); - } + activity.Stop(); } break; @@ -180,7 +188,7 @@ public override void OnEventWritten(string name, object payload) { if (this.exceptionFetcher.TryFetch(payload, out Exception exception) && exception != null) { - activity.SetStatus(Status.Error.WithDescription(exception.Message)); + activity.SetStatus(ActivityStatusCode.Error, exception.Message); if (this.options.RecordException) { diff --git a/src/OpenTelemetry.Instrumentation.SqlClient/Implementation/SqlClientInstrumentationEventSource.cs b/src/OpenTelemetry.Instrumentation.SqlClient/Implementation/SqlClientInstrumentationEventSource.cs index 75e4c7f55af..31a7a9737bf 100644 --- a/src/OpenTelemetry.Instrumentation.SqlClient/Implementation/SqlClientInstrumentationEventSource.cs +++ b/src/OpenTelemetry.Instrumentation.SqlClient/Implementation/SqlClientInstrumentationEventSource.cs @@ -24,7 +24,7 @@ namespace OpenTelemetry.Instrumentation.SqlClient.Implementation /// EventSource events emitted from the project. /// [EventSource(Name = "OpenTelemetry-Instrumentation-SqlClient")] - internal class SqlClientInstrumentationEventSource : EventSource + internal sealed class SqlClientInstrumentationEventSource : EventSource { public static SqlClientInstrumentationEventSource Log = new(); @@ -75,5 +75,26 @@ public void EnrichmentException(string exception) { this.WriteEvent(5, exception); } + + [Event(6, Message = "Command is filtered out. Activity {0}", Level = EventLevel.Verbose)] + public void CommandIsFilteredOut(string activityName) + { + this.WriteEvent(6, activityName); + } + + [NonEvent] + public void CommandFilterException(Exception ex) + { + if (this.IsEnabled(EventLevel.Error, EventKeywords.All)) + { + this.CommandFilterException(ex.ToInvariantString()); + } + } + + [Event(7, Message = "Command filter threw exception. Command will not be collected. Exception {0}.", Level = EventLevel.Error)] + public void CommandFilterException(string exception) + { + this.WriteEvent(7, exception); + } } } diff --git a/src/OpenTelemetry.Instrumentation.SqlClient/Implementation/SqlEventSourceListener.netfx.cs b/src/OpenTelemetry.Instrumentation.SqlClient/Implementation/SqlEventSourceListener.netfx.cs index 9417df4798d..fde30c97575 100644 --- a/src/OpenTelemetry.Instrumentation.SqlClient/Implementation/SqlEventSourceListener.netfx.cs +++ b/src/OpenTelemetry.Instrumentation.SqlClient/Implementation/SqlEventSourceListener.netfx.cs @@ -181,18 +181,17 @@ private void OnEndExecute(EventWrittenEventArgs eventData) if (activity.IsAllDataRequested) { int compositeState = (int)eventData.Payload[1]; - if ((compositeState & 0b001) == 0b001) + if ((compositeState & 0b001) != 0b001) { - activity.SetStatus(Status.Unset); - } - else if ((compositeState & 0b010) == 0b010) - { - var errorText = $"SqlExceptionNumber {eventData.Payload[2]} thrown."; - activity.SetStatus(Status.Error.WithDescription(errorText)); - } - else - { - activity.SetStatus(Status.Error.WithDescription("Unknown Sql failure.")); + if ((compositeState & 0b010) == 0b010) + { + var errorText = $"SqlExceptionNumber {eventData.Payload[2]} thrown."; + activity.SetStatus(ActivityStatusCode.Error, errorText); + } + else + { + activity.SetStatus(ActivityStatusCode.Error, "Unknown Sql failure."); + } } } } diff --git a/src/OpenTelemetry.Instrumentation.SqlClient/README.md b/src/OpenTelemetry.Instrumentation.SqlClient/README.md index 82005adc737..7999dfe91a5 100644 --- a/src/OpenTelemetry.Instrumentation.SqlClient/README.md +++ b/src/OpenTelemetry.Instrumentation.SqlClient/README.md @@ -221,6 +221,37 @@ using var tracerProvider = Sdk.CreateTracerProviderBuilder() .Build(); ``` +## Filter + +This option allows to filter out activities based on the properties of the +`SqlCommand` object being instrumented using a `Func`. +The function receives an instance of the raw `SqlCommand` and should return +`true` if the telemetry is to be collected, and `false` if it should not. +The parameter of the Func delegate is of type `object` and needs to +be cast to the appropriate type of `SqlCommand`, either +`Microsoft.Data.SqlClient.SqlCommand` or `System.Data.SqlClient.SqlCommand`. +The example below filters out all commands that are not stored procedures. + +```csharp +using var traceProvider = Sdk.CreateTracerProviderBuilder() + .AddSqlClientInstrumentation( + opt => + { + opt.Filter = cmd => + { + if (cmd is SqlCommand command) + { + return command.CommandType == CommandType.StoredProcedure; + } + + return false; + }; + }) + .AddConsoleExporter() + .Build(); +{ +``` + ## References * [OpenTelemetry Project](https://opentelemetry.io/) diff --git a/src/OpenTelemetry.Instrumentation.SqlClient/SqlClientInstrumentation.cs b/src/OpenTelemetry.Instrumentation.SqlClient/SqlClientInstrumentation.cs index 5b293bf76d0..0b4469aefe3 100644 --- a/src/OpenTelemetry.Instrumentation.SqlClient/SqlClientInstrumentation.cs +++ b/src/OpenTelemetry.Instrumentation.SqlClient/SqlClientInstrumentation.cs @@ -21,7 +21,7 @@ namespace OpenTelemetry.Instrumentation.SqlClient /// /// SqlClient instrumentation. /// - internal class SqlClientInstrumentation : IDisposable + internal sealed class SqlClientInstrumentation : IDisposable { internal const string SqlClientDiagnosticListenerName = "SqlClientDiagnosticListener"; diff --git a/src/OpenTelemetry.Instrumentation.SqlClient/SqlClientInstrumentationOptions.cs b/src/OpenTelemetry.Instrumentation.SqlClient/SqlClientInstrumentationOptions.cs index d3f2fd1ab1f..b413952e6cf 100644 --- a/src/OpenTelemetry.Instrumentation.SqlClient/SqlClientInstrumentationOptions.cs +++ b/src/OpenTelemetry.Instrumentation.SqlClient/SqlClientInstrumentationOptions.cs @@ -130,6 +130,18 @@ public class SqlClientInstrumentationOptions public Action Enrich { get; set; } #if !NETFRAMEWORK + /// + /// Gets or sets a Filter function that determines whether or not to collect telemetry about a command + /// The Filter gets the SqlCommand, and should return a boolean. + /// If Filter returns true, the request is collected. + /// If Filter returns false or throw exception, the request is filtered out. + /// + /// + /// object: the raw SqlCommand object to interrogate for a decision on whether to trace or not. + /// + /// true to collect request, false to filter out. + public Func Filter { get; set; } + /// /// Gets or sets a value indicating whether the exception will be recorded as ActivityEvent or not. Default value: False. /// @@ -258,7 +270,7 @@ internal void AddConnectionLevelDetailsToActivity(string dataSource, Activity sq } } - internal class SqlConnectionDetails + internal sealed class SqlConnectionDetails { public string ServerHostName { get; set; } diff --git a/src/OpenTelemetry.SemanticConventions/.publicApi/net462/PublicAPI.Shipped.txt b/src/OpenTelemetry.SemanticConventions/.publicApi/net462/PublicAPI.Shipped.txt new file mode 100644 index 00000000000..e69de29bb2d diff --git a/src/OpenTelemetry.SemanticConventions/.publicApi/net462/PublicAPI.Unshipped.txt b/src/OpenTelemetry.SemanticConventions/.publicApi/net462/PublicAPI.Unshipped.txt new file mode 100644 index 00000000000..17864093bcd --- /dev/null +++ b/src/OpenTelemetry.SemanticConventions/.publicApi/net462/PublicAPI.Unshipped.txt @@ -0,0 +1,526 @@ +const OpenTelemetry.Resources.ResourceSemanticConventions.AttributeAwsEcsClusterArn = "aws.ecs.cluster.arn" -> string +const OpenTelemetry.Resources.ResourceSemanticConventions.AttributeAwsEcsContainerArn = "aws.ecs.container.arn" -> string +const OpenTelemetry.Resources.ResourceSemanticConventions.AttributeAwsEcsLaunchtype = "aws.ecs.launchtype" -> string +const OpenTelemetry.Resources.ResourceSemanticConventions.AttributeAwsEcsTaskArn = "aws.ecs.task.arn" -> string +const OpenTelemetry.Resources.ResourceSemanticConventions.AttributeAwsEcsTaskFamily = "aws.ecs.task.family" -> string +const OpenTelemetry.Resources.ResourceSemanticConventions.AttributeAwsEcsTaskRevision = "aws.ecs.task.revision" -> string +const OpenTelemetry.Resources.ResourceSemanticConventions.AttributeAwsEksClusterArn = "aws.eks.cluster.arn" -> string +const OpenTelemetry.Resources.ResourceSemanticConventions.AttributeAwsLogGroupArns = "aws.log.group.arns" -> string +const OpenTelemetry.Resources.ResourceSemanticConventions.AttributeAwsLogGroupNames = "aws.log.group.names" -> string +const OpenTelemetry.Resources.ResourceSemanticConventions.AttributeAwsLogStreamArns = "aws.log.stream.arns" -> string +const OpenTelemetry.Resources.ResourceSemanticConventions.AttributeAwsLogStreamNames = "aws.log.stream.names" -> string +const OpenTelemetry.Resources.ResourceSemanticConventions.AttributeBrowserBrands = "browser.brands" -> string +const OpenTelemetry.Resources.ResourceSemanticConventions.AttributeBrowserPlatform = "browser.platform" -> string +const OpenTelemetry.Resources.ResourceSemanticConventions.AttributeBrowserUserAgent = "browser.user_agent" -> string +const OpenTelemetry.Resources.ResourceSemanticConventions.AttributeCloudAccountId = "cloud.account.id" -> string +const OpenTelemetry.Resources.ResourceSemanticConventions.AttributeCloudAvailabilityZone = "cloud.availability_zone" -> string +const OpenTelemetry.Resources.ResourceSemanticConventions.AttributeCloudPlatform = "cloud.platform" -> string +const OpenTelemetry.Resources.ResourceSemanticConventions.AttributeCloudProvider = "cloud.provider" -> string +const OpenTelemetry.Resources.ResourceSemanticConventions.AttributeCloudRegion = "cloud.region" -> string +const OpenTelemetry.Resources.ResourceSemanticConventions.AttributeContainerId = "container.id" -> string +const OpenTelemetry.Resources.ResourceSemanticConventions.AttributeContainerImageName = "container.image.name" -> string +const OpenTelemetry.Resources.ResourceSemanticConventions.AttributeContainerImageTag = "container.image.tag" -> string +const OpenTelemetry.Resources.ResourceSemanticConventions.AttributeContainerName = "container.name" -> string +const OpenTelemetry.Resources.ResourceSemanticConventions.AttributeContainerRuntime = "container.runtime" -> string +const OpenTelemetry.Resources.ResourceSemanticConventions.AttributeDeploymentEnvironment = "deployment.environment" -> string +const OpenTelemetry.Resources.ResourceSemanticConventions.AttributeDeviceId = "device.id" -> string +const OpenTelemetry.Resources.ResourceSemanticConventions.AttributeDeviceManufacturer = "device.manufacturer" -> string +const OpenTelemetry.Resources.ResourceSemanticConventions.AttributeDeviceModelIdentifier = "device.model.identifier" -> string +const OpenTelemetry.Resources.ResourceSemanticConventions.AttributeDeviceModelName = "device.model.name" -> string +const OpenTelemetry.Resources.ResourceSemanticConventions.AttributeFaasId = "faas.id" -> string +const OpenTelemetry.Resources.ResourceSemanticConventions.AttributeFaasInstance = "faas.instance" -> string +const OpenTelemetry.Resources.ResourceSemanticConventions.AttributeFaasMaxMemory = "faas.max_memory" -> string +const OpenTelemetry.Resources.ResourceSemanticConventions.AttributeFaasName = "faas.name" -> string +const OpenTelemetry.Resources.ResourceSemanticConventions.AttributeFaasVersion = "faas.version" -> string +const OpenTelemetry.Resources.ResourceSemanticConventions.AttributeHostArch = "host.arch" -> string +const OpenTelemetry.Resources.ResourceSemanticConventions.AttributeHostId = "host.id" -> string +const OpenTelemetry.Resources.ResourceSemanticConventions.AttributeHostImageId = "host.image.id" -> string +const OpenTelemetry.Resources.ResourceSemanticConventions.AttributeHostImageName = "host.image.name" -> string +const OpenTelemetry.Resources.ResourceSemanticConventions.AttributeHostImageVersion = "host.image.version" -> string +const OpenTelemetry.Resources.ResourceSemanticConventions.AttributeHostName = "host.name" -> string +const OpenTelemetry.Resources.ResourceSemanticConventions.AttributeHostType = "host.type" -> string +const OpenTelemetry.Resources.ResourceSemanticConventions.AttributeK8sClusterName = "k8s.cluster.name" -> string +const OpenTelemetry.Resources.ResourceSemanticConventions.AttributeK8sContainerName = "k8s.container.name" -> string +const OpenTelemetry.Resources.ResourceSemanticConventions.AttributeK8sContainerRestartCount = "k8s.container.restart_count" -> string +const OpenTelemetry.Resources.ResourceSemanticConventions.AttributeK8sCronjobName = "k8s.cronjob.name" -> string +const OpenTelemetry.Resources.ResourceSemanticConventions.AttributeK8sCronjobUid = "k8s.cronjob.uid" -> string +const OpenTelemetry.Resources.ResourceSemanticConventions.AttributeK8sDaemonsetName = "k8s.daemonset.name" -> string +const OpenTelemetry.Resources.ResourceSemanticConventions.AttributeK8sDaemonsetUid = "k8s.daemonset.uid" -> string +const OpenTelemetry.Resources.ResourceSemanticConventions.AttributeK8sDeploymentName = "k8s.deployment.name" -> string +const OpenTelemetry.Resources.ResourceSemanticConventions.AttributeK8sDeploymentUid = "k8s.deployment.uid" -> string +const OpenTelemetry.Resources.ResourceSemanticConventions.AttributeK8sJobName = "k8s.job.name" -> string +const OpenTelemetry.Resources.ResourceSemanticConventions.AttributeK8sJobUid = "k8s.job.uid" -> string +const OpenTelemetry.Resources.ResourceSemanticConventions.AttributeK8sNamespaceName = "k8s.namespace.name" -> string +const OpenTelemetry.Resources.ResourceSemanticConventions.AttributeK8sNodeName = "k8s.node.name" -> string +const OpenTelemetry.Resources.ResourceSemanticConventions.AttributeK8sNodeUid = "k8s.node.uid" -> string +const OpenTelemetry.Resources.ResourceSemanticConventions.AttributeK8sPodName = "k8s.pod.name" -> string +const OpenTelemetry.Resources.ResourceSemanticConventions.AttributeK8sPodUid = "k8s.pod.uid" -> string +const OpenTelemetry.Resources.ResourceSemanticConventions.AttributeK8sReplicasetName = "k8s.replicaset.name" -> string +const OpenTelemetry.Resources.ResourceSemanticConventions.AttributeK8sReplicasetUid = "k8s.replicaset.uid" -> string +const OpenTelemetry.Resources.ResourceSemanticConventions.AttributeK8sStatefulsetName = "k8s.statefulset.name" -> string +const OpenTelemetry.Resources.ResourceSemanticConventions.AttributeK8sStatefulsetUid = "k8s.statefulset.uid" -> string +const OpenTelemetry.Resources.ResourceSemanticConventions.AttributeOsDescription = "os.description" -> string +const OpenTelemetry.Resources.ResourceSemanticConventions.AttributeOsName = "os.name" -> string +const OpenTelemetry.Resources.ResourceSemanticConventions.AttributeOsType = "os.type" -> string +const OpenTelemetry.Resources.ResourceSemanticConventions.AttributeOsVersion = "os.version" -> string +const OpenTelemetry.Resources.ResourceSemanticConventions.AttributeProcessCommand = "process.command" -> string +const OpenTelemetry.Resources.ResourceSemanticConventions.AttributeProcessCommandArgs = "process.command_args" -> string +const OpenTelemetry.Resources.ResourceSemanticConventions.AttributeProcessCommandLine = "process.command_line" -> string +const OpenTelemetry.Resources.ResourceSemanticConventions.AttributeProcessExecutableName = "process.executable.name" -> string +const OpenTelemetry.Resources.ResourceSemanticConventions.AttributeProcessExecutablePath = "process.executable.path" -> string +const OpenTelemetry.Resources.ResourceSemanticConventions.AttributeProcessOwner = "process.owner" -> string +const OpenTelemetry.Resources.ResourceSemanticConventions.AttributeProcessParentPid = "process.parent_pid" -> string +const OpenTelemetry.Resources.ResourceSemanticConventions.AttributeProcessPid = "process.pid" -> string +const OpenTelemetry.Resources.ResourceSemanticConventions.AttributeProcessRuntimeDescription = "process.runtime.description" -> string +const OpenTelemetry.Resources.ResourceSemanticConventions.AttributeProcessRuntimeName = "process.runtime.name" -> string +const OpenTelemetry.Resources.ResourceSemanticConventions.AttributeProcessRuntimeVersion = "process.runtime.version" -> string +const OpenTelemetry.Resources.ResourceSemanticConventions.AttributeServiceInstanceId = "service.instance.id" -> string +const OpenTelemetry.Resources.ResourceSemanticConventions.AttributeServiceName = "service.name" -> string +const OpenTelemetry.Resources.ResourceSemanticConventions.AttributeServiceNamespace = "service.namespace" -> string +const OpenTelemetry.Resources.ResourceSemanticConventions.AttributeServiceVersion = "service.version" -> string +const OpenTelemetry.Resources.ResourceSemanticConventions.AttributeTelemetryAutoVersion = "telemetry.auto.version" -> string +const OpenTelemetry.Resources.ResourceSemanticConventions.AttributeTelemetrySdkLanguage = "telemetry.sdk.language" -> string +const OpenTelemetry.Resources.ResourceSemanticConventions.AttributeTelemetrySdkName = "telemetry.sdk.name" -> string +const OpenTelemetry.Resources.ResourceSemanticConventions.AttributeTelemetrySdkVersion = "telemetry.sdk.version" -> string +const OpenTelemetry.Resources.ResourceSemanticConventions.AttributeWebengineDescription = "webengine.description" -> string +const OpenTelemetry.Resources.ResourceSemanticConventions.AttributeWebengineName = "webengine.name" -> string +const OpenTelemetry.Resources.ResourceSemanticConventions.AttributeWebengineVersion = "webengine.version" -> string +const OpenTelemetry.Resources.ResourceSemanticConventions.AwsEcsLaunchtypeValues.Ec2 = "ec2" -> string +const OpenTelemetry.Resources.ResourceSemanticConventions.AwsEcsLaunchtypeValues.Fargate = "fargate" -> string +const OpenTelemetry.Resources.ResourceSemanticConventions.CloudPlatformValues.AlibabaCloudEcs = "alibaba_cloud_ecs" -> string +const OpenTelemetry.Resources.ResourceSemanticConventions.CloudPlatformValues.AlibabaCloudFc = "alibaba_cloud_fc" -> string +const OpenTelemetry.Resources.ResourceSemanticConventions.CloudPlatformValues.AwsAppRunner = "aws_app_runner" -> string +const OpenTelemetry.Resources.ResourceSemanticConventions.CloudPlatformValues.AwsEc2 = "aws_ec2" -> string +const OpenTelemetry.Resources.ResourceSemanticConventions.CloudPlatformValues.AwsEcs = "aws_ecs" -> string +const OpenTelemetry.Resources.ResourceSemanticConventions.CloudPlatformValues.AwsEks = "aws_eks" -> string +const OpenTelemetry.Resources.ResourceSemanticConventions.CloudPlatformValues.AwsElasticBeanstalk = "aws_elastic_beanstalk" -> string +const OpenTelemetry.Resources.ResourceSemanticConventions.CloudPlatformValues.AwsLambda = "aws_lambda" -> string +const OpenTelemetry.Resources.ResourceSemanticConventions.CloudPlatformValues.AzureAks = "azure_aks" -> string +const OpenTelemetry.Resources.ResourceSemanticConventions.CloudPlatformValues.AzureAppService = "azure_app_service" -> string +const OpenTelemetry.Resources.ResourceSemanticConventions.CloudPlatformValues.AzureContainerInstances = "azure_container_instances" -> string +const OpenTelemetry.Resources.ResourceSemanticConventions.CloudPlatformValues.AzureFunctions = "azure_functions" -> string +const OpenTelemetry.Resources.ResourceSemanticConventions.CloudPlatformValues.AzureVm = "azure_vm" -> string +const OpenTelemetry.Resources.ResourceSemanticConventions.CloudPlatformValues.GcpAppEngine = "gcp_app_engine" -> string +const OpenTelemetry.Resources.ResourceSemanticConventions.CloudPlatformValues.GcpCloudFunctions = "gcp_cloud_functions" -> string +const OpenTelemetry.Resources.ResourceSemanticConventions.CloudPlatformValues.GcpCloudRun = "gcp_cloud_run" -> string +const OpenTelemetry.Resources.ResourceSemanticConventions.CloudPlatformValues.GcpComputeEngine = "gcp_compute_engine" -> string +const OpenTelemetry.Resources.ResourceSemanticConventions.CloudPlatformValues.GcpKubernetesEngine = "gcp_kubernetes_engine" -> string +const OpenTelemetry.Resources.ResourceSemanticConventions.CloudPlatformValues.TencentCloudCvm = "tencent_cloud_cvm" -> string +const OpenTelemetry.Resources.ResourceSemanticConventions.CloudPlatformValues.TencentCloudEks = "tencent_cloud_eks" -> string +const OpenTelemetry.Resources.ResourceSemanticConventions.CloudPlatformValues.TencentCloudScf = "tencent_cloud_scf" -> string +const OpenTelemetry.Resources.ResourceSemanticConventions.CloudProviderValues.AlibabaCloud = "alibaba_cloud" -> string +const OpenTelemetry.Resources.ResourceSemanticConventions.CloudProviderValues.Aws = "aws" -> string +const OpenTelemetry.Resources.ResourceSemanticConventions.CloudProviderValues.Azure = "azure" -> string +const OpenTelemetry.Resources.ResourceSemanticConventions.CloudProviderValues.Gcp = "gcp" -> string +const OpenTelemetry.Resources.ResourceSemanticConventions.CloudProviderValues.TencentCloud = "tencent_cloud" -> string +const OpenTelemetry.Resources.ResourceSemanticConventions.HostArchValues.Amd64 = "amd64" -> string +const OpenTelemetry.Resources.ResourceSemanticConventions.HostArchValues.Arm32 = "arm32" -> string +const OpenTelemetry.Resources.ResourceSemanticConventions.HostArchValues.Arm64 = "arm64" -> string +const OpenTelemetry.Resources.ResourceSemanticConventions.HostArchValues.Ia64 = "ia64" -> string +const OpenTelemetry.Resources.ResourceSemanticConventions.HostArchValues.Ppc32 = "ppc32" -> string +const OpenTelemetry.Resources.ResourceSemanticConventions.HostArchValues.Ppc64 = "ppc64" -> string +const OpenTelemetry.Resources.ResourceSemanticConventions.HostArchValues.S390x = "s390x" -> string +const OpenTelemetry.Resources.ResourceSemanticConventions.HostArchValues.X86 = "x86" -> string +const OpenTelemetry.Resources.ResourceSemanticConventions.OsTypeValues.Aix = "aix" -> string +const OpenTelemetry.Resources.ResourceSemanticConventions.OsTypeValues.Darwin = "darwin" -> string +const OpenTelemetry.Resources.ResourceSemanticConventions.OsTypeValues.Dragonflybsd = "dragonflybsd" -> string +const OpenTelemetry.Resources.ResourceSemanticConventions.OsTypeValues.Freebsd = "freebsd" -> string +const OpenTelemetry.Resources.ResourceSemanticConventions.OsTypeValues.Hpux = "hpux" -> string +const OpenTelemetry.Resources.ResourceSemanticConventions.OsTypeValues.Linux = "linux" -> string +const OpenTelemetry.Resources.ResourceSemanticConventions.OsTypeValues.Netbsd = "netbsd" -> string +const OpenTelemetry.Resources.ResourceSemanticConventions.OsTypeValues.Openbsd = "openbsd" -> string +const OpenTelemetry.Resources.ResourceSemanticConventions.OsTypeValues.Solaris = "solaris" -> string +const OpenTelemetry.Resources.ResourceSemanticConventions.OsTypeValues.Windows = "windows" -> string +const OpenTelemetry.Resources.ResourceSemanticConventions.OsTypeValues.ZOs = "z_os" -> string +const OpenTelemetry.Resources.ResourceSemanticConventions.TelemetrySdkLanguageValues.Cpp = "cpp" -> string +const OpenTelemetry.Resources.ResourceSemanticConventions.TelemetrySdkLanguageValues.Dotnet = "dotnet" -> string +const OpenTelemetry.Resources.ResourceSemanticConventions.TelemetrySdkLanguageValues.Erlang = "erlang" -> string +const OpenTelemetry.Resources.ResourceSemanticConventions.TelemetrySdkLanguageValues.Go = "go" -> string +const OpenTelemetry.Resources.ResourceSemanticConventions.TelemetrySdkLanguageValues.Java = "java" -> string +const OpenTelemetry.Resources.ResourceSemanticConventions.TelemetrySdkLanguageValues.Nodejs = "nodejs" -> string +const OpenTelemetry.Resources.ResourceSemanticConventions.TelemetrySdkLanguageValues.Php = "php" -> string +const OpenTelemetry.Resources.ResourceSemanticConventions.TelemetrySdkLanguageValues.Python = "python" -> string +const OpenTelemetry.Resources.ResourceSemanticConventions.TelemetrySdkLanguageValues.Ruby = "ruby" -> string +const OpenTelemetry.Resources.ResourceSemanticConventions.TelemetrySdkLanguageValues.Swift = "swift" -> string +const OpenTelemetry.Resources.ResourceSemanticConventions.TelemetrySdkLanguageValues.Webjs = "webjs" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.AttributeAwsDynamodbAttributeDefinitions = "aws.dynamodb.attribute_definitions" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.AttributeAwsDynamodbAttributesToGet = "aws.dynamodb.attributes_to_get" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.AttributeAwsDynamodbConsistentRead = "aws.dynamodb.consistent_read" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.AttributeAwsDynamodbConsumedCapacity = "aws.dynamodb.consumed_capacity" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.AttributeAwsDynamodbCount = "aws.dynamodb.count" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.AttributeAwsDynamodbExclusiveStartTable = "aws.dynamodb.exclusive_start_table" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.AttributeAwsDynamodbGlobalSecondaryIndexes = "aws.dynamodb.global_secondary_indexes" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.AttributeAwsDynamodbGlobalSecondaryIndexUpdates = "aws.dynamodb.global_secondary_index_updates" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.AttributeAwsDynamodbIndexName = "aws.dynamodb.index_name" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.AttributeAwsDynamodbItemCollectionMetrics = "aws.dynamodb.item_collection_metrics" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.AttributeAwsDynamodbLimit = "aws.dynamodb.limit" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.AttributeAwsDynamodbLocalSecondaryIndexes = "aws.dynamodb.local_secondary_indexes" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.AttributeAwsDynamodbProjection = "aws.dynamodb.projection" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.AttributeAwsDynamodbProvisionedReadCapacity = "aws.dynamodb.provisioned_read_capacity" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.AttributeAwsDynamodbProvisionedWriteCapacity = "aws.dynamodb.provisioned_write_capacity" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.AttributeAwsDynamodbScanForward = "aws.dynamodb.scan_forward" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.AttributeAwsDynamodbScannedCount = "aws.dynamodb.scanned_count" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.AttributeAwsDynamodbSegment = "aws.dynamodb.segment" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.AttributeAwsDynamodbSelect = "aws.dynamodb.select" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.AttributeAwsDynamodbTableCount = "aws.dynamodb.table_count" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.AttributeAwsDynamodbTableNames = "aws.dynamodb.table_names" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.AttributeAwsDynamodbTotalSegments = "aws.dynamodb.total_segments" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.AttributeAwsLambdaInvokedArn = "aws.lambda.invoked_arn" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.AttributeCloudeventsEventId = "cloudevents.event_id" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.AttributeCloudeventsEventSource = "cloudevents.event_source" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.AttributeCloudeventsEventSpecVersion = "cloudevents.event_spec_version" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.AttributeCloudeventsEventSubject = "cloudevents.event_subject" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.AttributeCloudeventsEventType = "cloudevents.event_type" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.AttributeCodeFilepath = "code.filepath" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.AttributeCodeFunction = "code.function" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.AttributeCodeLineno = "code.lineno" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.AttributeCodeNamespace = "code.namespace" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.AttributeDbCassandraConsistencyLevel = "db.cassandra.consistency_level" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.AttributeDbCassandraCoordinatorDc = "db.cassandra.coordinator.dc" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.AttributeDbCassandraCoordinatorId = "db.cassandra.coordinator.id" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.AttributeDbCassandraIdempotence = "db.cassandra.idempotence" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.AttributeDbCassandraPageSize = "db.cassandra.page_size" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.AttributeDbCassandraSpeculativeExecutionCount = "db.cassandra.speculative_execution_count" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.AttributeDbCassandraTable = "db.cassandra.table" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.AttributeDbConnectionString = "db.connection_string" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.AttributeDbInstance = "db.instance" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.AttributeDbJdbcDriverClassname = "db.jdbc.driver_classname" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.AttributeDbMongodbCollection = "db.mongodb.collection" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.AttributeDbMssqlInstanceName = "db.mssql.instance_name" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.AttributeDbName = "db.name" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.AttributeDbOperation = "db.operation" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.AttributeDbRedisDatabaseIndex = "db.redis.database_index" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.AttributeDbSqlTable = "db.sql.table" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.AttributeDbStatement = "db.statement" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.AttributeDbSystem = "db.system" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.AttributeDbUser = "db.user" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.AttributeEnduserId = "enduser.id" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.AttributeEnduserRole = "enduser.role" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.AttributeEnduserScope = "enduser.scope" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.AttributeExceptionEscaped = "exception.escaped" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.AttributeExceptionMessage = "exception.message" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.AttributeExceptionStacktrace = "exception.stacktrace" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.AttributeExceptionType = "exception.type" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.AttributeFaasColdstart = "faas.coldstart" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.AttributeFaasCron = "faas.cron" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.AttributeFaasDocumentCollection = "faas.document.collection" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.AttributeFaasDocumentName = "faas.document.name" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.AttributeFaasDocumentOperation = "faas.document.operation" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.AttributeFaasDocumentTime = "faas.document.time" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.AttributeFaasExecution = "faas.execution" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.AttributeFaasInvokedName = "faas.invoked_name" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.AttributeFaasInvokedProvider = "faas.invoked_provider" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.AttributeFaasInvokedRegion = "faas.invoked_region" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.AttributeFaasTime = "faas.time" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.AttributeFaasTrigger = "faas.trigger" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.AttributeGraphqlDocument = "graphql.document" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.AttributeGraphqlOperationName = "graphql.operation.name" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.AttributeGraphqlOperationType = "graphql.operation.type" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.AttributeHttpClientIp = "http.client_ip" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.AttributeHttpFlavor = "http.flavor" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.AttributeHttpMethod = "http.method" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.AttributeHttpRequestContentLength = "http.request_content_length" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.AttributeHttpResponseContentLength = "http.response_content_length" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.AttributeHttpRetryCount = "http.retry_count" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.AttributeHttpRoute = "http.route" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.AttributeHttpScheme = "http.scheme" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.AttributeHttpStatusCode = "http.status_code" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.AttributeHttpTarget = "http.target" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.AttributeHttpUrl = "http.url" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.AttributeHttpUserAgent = "http.user_agent" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.AttributeMessageCompressedSize = "message.compressed_size" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.AttributeMessageId = "message.id" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.AttributeMessageType = "message.type" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.AttributeMessageUncompressedSize = "message.uncompressed_size" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.AttributeMessagingConsumerId = "messaging.consumer_id" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.AttributeMessagingConversationId = "messaging.conversation_id" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.AttributeMessagingDestination = "messaging.destination" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.AttributeMessagingDestinationKind = "messaging.destination_kind" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.AttributeMessagingKafkaClientId = "messaging.kafka.client_id" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.AttributeMessagingKafkaConsumerGroup = "messaging.kafka.consumer_group" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.AttributeMessagingKafkaMessageKey = "messaging.kafka.message_key" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.AttributeMessagingKafkaPartition = "messaging.kafka.partition" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.AttributeMessagingKafkaTombstone = "messaging.kafka.tombstone" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.AttributeMessagingMessageId = "messaging.message_id" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.AttributeMessagingMessagePayloadCompressedSizeBytes = "messaging.message_payload_compressed_size_bytes" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.AttributeMessagingMessagePayloadSizeBytes = "messaging.message_payload_size_bytes" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.AttributeMessagingOperation = "messaging.operation" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.AttributeMessagingProtocol = "messaging.protocol" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.AttributeMessagingProtocolVersion = "messaging.protocol_version" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.AttributeMessagingRabbitmqRoutingKey = "messaging.rabbitmq.routing_key" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.AttributeMessagingRocketmqClientGroup = "messaging.rocketmq.client_group" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.AttributeMessagingRocketmqClientId = "messaging.rocketmq.client_id" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.AttributeMessagingRocketmqConsumptionModel = "messaging.rocketmq.consumption_model" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.AttributeMessagingRocketmqMessageKeys = "messaging.rocketmq.message_keys" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.AttributeMessagingRocketmqMessageTag = "messaging.rocketmq.message_tag" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.AttributeMessagingRocketmqMessageType = "messaging.rocketmq.message_type" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.AttributeMessagingRocketmqNamespace = "messaging.rocketmq.namespace" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.AttributeMessagingSystem = "messaging.system" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.AttributeMessagingTempDestination = "messaging.temp_destination" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.AttributeMessagingUrl = "messaging.url" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.AttributeNetAppProtocolName = "net.app.protocol.name" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.AttributeNetAppProtocolVersion = "net.app.protocol.version" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.AttributeNetHostCarrierIcc = "net.host.carrier.icc" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.AttributeNetHostCarrierMcc = "net.host.carrier.mcc" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.AttributeNetHostCarrierMnc = "net.host.carrier.mnc" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.AttributeNetHostCarrierName = "net.host.carrier.name" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.AttributeNetHostConnectionSubtype = "net.host.connection.subtype" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.AttributeNetHostConnectionType = "net.host.connection.type" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.AttributeNetHostName = "net.host.name" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.AttributeNetHostPort = "net.host.port" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.AttributeNetPeerName = "net.peer.name" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.AttributeNetPeerPort = "net.peer.port" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.AttributeNetSockFamily = "net.sock.family" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.AttributeNetSockHostAddr = "net.sock.host.addr" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.AttributeNetSockHostPort = "net.sock.host.port" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.AttributeNetSockPeerAddr = "net.sock.peer.addr" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.AttributeNetSockPeerName = "net.sock.peer.name" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.AttributeNetSockPeerPort = "net.sock.peer.port" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.AttributeNetTransport = "net.transport" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.AttributeOpentracingRefType = "opentracing.ref_type" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.AttributePeerService = "peer.service" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.AttributeRpcGrpcStatusCode = "rpc.grpc.status_code" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.AttributeRpcJsonrpcErrorCode = "rpc.jsonrpc.error_code" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.AttributeRpcJsonrpcErrorMessage = "rpc.jsonrpc.error_message" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.AttributeRpcJsonrpcRequestId = "rpc.jsonrpc.request_id" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.AttributeRpcJsonrpcVersion = "rpc.jsonrpc.version" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.AttributeRpcMethod = "rpc.method" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.AttributeRpcService = "rpc.service" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.AttributeRpcSystem = "rpc.system" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.AttributeThreadId = "thread.id" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.AttributeThreadName = "thread.name" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.DbCassandraConsistencyLevelValues.All = "all" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.DbCassandraConsistencyLevelValues.Any = "any" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.DbCassandraConsistencyLevelValues.EachQuorum = "each_quorum" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.DbCassandraConsistencyLevelValues.LocalOne = "local_one" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.DbCassandraConsistencyLevelValues.LocalQuorum = "local_quorum" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.DbCassandraConsistencyLevelValues.LocalSerial = "local_serial" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.DbCassandraConsistencyLevelValues.One = "one" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.DbCassandraConsistencyLevelValues.Quorum = "quorum" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.DbCassandraConsistencyLevelValues.Serial = "serial" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.DbCassandraConsistencyLevelValues.Three = "three" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.DbCassandraConsistencyLevelValues.Two = "two" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.DbSystemValues.Adabas = "adabas" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.DbSystemValues.Cache = "cache" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.DbSystemValues.Cassandra = "cassandra" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.DbSystemValues.Cloudscape = "cloudscape" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.DbSystemValues.Cockroachdb = "cockroachdb" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.DbSystemValues.Coldfusion = "coldfusion" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.DbSystemValues.Cosmosdb = "cosmosdb" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.DbSystemValues.Couchbase = "couchbase" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.DbSystemValues.Couchdb = "couchdb" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.DbSystemValues.Db2 = "db2" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.DbSystemValues.Derby = "derby" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.DbSystemValues.Dynamodb = "dynamodb" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.DbSystemValues.Edb = "edb" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.DbSystemValues.Elasticsearch = "elasticsearch" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.DbSystemValues.Filemaker = "filemaker" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.DbSystemValues.Firebird = "firebird" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.DbSystemValues.Firstsql = "firstsql" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.DbSystemValues.Geode = "geode" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.DbSystemValues.H2 = "h2" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.DbSystemValues.Hanadb = "hanadb" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.DbSystemValues.Hbase = "hbase" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.DbSystemValues.Hive = "hive" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.DbSystemValues.Hsqldb = "hsqldb" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.DbSystemValues.Informix = "informix" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.DbSystemValues.Ingres = "ingres" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.DbSystemValues.Instantdb = "instantdb" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.DbSystemValues.Interbase = "interbase" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.DbSystemValues.Mariadb = "mariadb" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.DbSystemValues.Maxdb = "maxdb" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.DbSystemValues.Memcached = "memcached" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.DbSystemValues.Mongodb = "mongodb" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.DbSystemValues.Mssql = "mssql" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.DbSystemValues.Mysql = "mysql" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.DbSystemValues.Neo4j = "neo4j" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.DbSystemValues.Netezza = "netezza" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.DbSystemValues.Opensearch = "opensearch" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.DbSystemValues.Oracle = "oracle" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.DbSystemValues.OtherSql = "other_sql" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.DbSystemValues.Pervasive = "pervasive" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.DbSystemValues.Pointbase = "pointbase" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.DbSystemValues.Postgresql = "postgresql" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.DbSystemValues.Progress = "progress" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.DbSystemValues.Redis = "redis" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.DbSystemValues.Redshift = "redshift" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.DbSystemValues.Sqlite = "sqlite" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.DbSystemValues.Sybase = "sybase" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.DbSystemValues.Teradata = "teradata" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.DbSystemValues.Vertica = "vertica" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.FaasDocumentOperationValues.Delete = "delete" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.FaasDocumentOperationValues.Edit = "edit" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.FaasDocumentOperationValues.Insert = "insert" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.FaasInvokedProviderValues.AlibabaCloud = "alibaba_cloud" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.FaasInvokedProviderValues.Aws = "aws" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.FaasInvokedProviderValues.Azure = "azure" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.FaasInvokedProviderValues.Gcp = "gcp" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.FaasInvokedProviderValues.TencentCloud = "tencent_cloud" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.FaasTriggerValues.Datasource = "datasource" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.FaasTriggerValues.Http = "http" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.FaasTriggerValues.Other = "other" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.FaasTriggerValues.Pubsub = "pubsub" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.FaasTriggerValues.Timer = "timer" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.GraphqlOperationTypeValues.Mutation = "mutation" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.GraphqlOperationTypeValues.Query = "query" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.GraphqlOperationTypeValues.Subscription = "subscription" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.HttpFlavorValues.Http10 = "1.0" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.HttpFlavorValues.Http11 = "1.1" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.HttpFlavorValues.Http20 = "2.0" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.HttpFlavorValues.Http30 = "3.0" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.HttpFlavorValues.Quic = "QUIC" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.HttpFlavorValues.Spdy = "SPDY" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.MessageTypeValues.Received = "RECEIVED" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.MessageTypeValues.Sent = "SENT" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.MessagingDestinationKindValues.Queue = "queue" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.MessagingDestinationKindValues.Topic = "topic" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.MessagingOperationValues.Process = "process" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.MessagingOperationValues.Receive = "receive" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.MessagingRocketmqConsumptionModelValues.Broadcasting = "broadcasting" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.MessagingRocketmqConsumptionModelValues.Clustering = "clustering" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.MessagingRocketmqMessageTypeValues.Delay = "delay" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.MessagingRocketmqMessageTypeValues.Fifo = "fifo" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.MessagingRocketmqMessageTypeValues.Normal = "normal" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.MessagingRocketmqMessageTypeValues.Transaction = "transaction" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.NetHostConnectionSubtypeValues.Cdma = "cdma" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.NetHostConnectionSubtypeValues.Cdma20001xrtt = "cdma2000_1xrtt" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.NetHostConnectionSubtypeValues.Edge = "edge" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.NetHostConnectionSubtypeValues.Ehrpd = "ehrpd" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.NetHostConnectionSubtypeValues.Evdo0 = "evdo_0" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.NetHostConnectionSubtypeValues.EvdoA = "evdo_a" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.NetHostConnectionSubtypeValues.EvdoB = "evdo_b" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.NetHostConnectionSubtypeValues.Gprs = "gprs" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.NetHostConnectionSubtypeValues.Gsm = "gsm" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.NetHostConnectionSubtypeValues.Hsdpa = "hsdpa" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.NetHostConnectionSubtypeValues.Hspa = "hspa" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.NetHostConnectionSubtypeValues.Hspap = "hspap" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.NetHostConnectionSubtypeValues.Hsupa = "hsupa" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.NetHostConnectionSubtypeValues.Iden = "iden" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.NetHostConnectionSubtypeValues.Iwlan = "iwlan" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.NetHostConnectionSubtypeValues.Lte = "lte" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.NetHostConnectionSubtypeValues.LteCa = "lte_ca" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.NetHostConnectionSubtypeValues.Nr = "nr" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.NetHostConnectionSubtypeValues.Nrnsa = "nrnsa" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.NetHostConnectionSubtypeValues.TdScdma = "td_scdma" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.NetHostConnectionSubtypeValues.Umts = "umts" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.NetHostConnectionTypeValues.Cell = "cell" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.NetHostConnectionTypeValues.Unavailable = "unavailable" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.NetHostConnectionTypeValues.Unknown = "unknown" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.NetHostConnectionTypeValues.Wifi = "wifi" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.NetHostConnectionTypeValues.Wired = "wired" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.NetSockFamilyValues.Inet = "inet" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.NetSockFamilyValues.Inet6 = "inet6" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.NetSockFamilyValues.Unix = "unix" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.NetTransportValues.Inproc = "inproc" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.NetTransportValues.IpTcp = "ip_tcp" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.NetTransportValues.IpUdp = "ip_udp" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.NetTransportValues.Other = "other" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.NetTransportValues.Pipe = "pipe" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.OpentracingRefTypeValues.ChildOf = "child_of" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.OpentracingRefTypeValues.FollowsFrom = "follows_from" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.RpcGrpcStatusCodeValues.Aborted = 10 -> int +const OpenTelemetry.Trace.TraceSemanticConventions.RpcGrpcStatusCodeValues.AlreadyExists = 6 -> int +const OpenTelemetry.Trace.TraceSemanticConventions.RpcGrpcStatusCodeValues.Cancelled = 1 -> int +const OpenTelemetry.Trace.TraceSemanticConventions.RpcGrpcStatusCodeValues.DataLoss = 15 -> int +const OpenTelemetry.Trace.TraceSemanticConventions.RpcGrpcStatusCodeValues.DeadlineExceeded = 4 -> int +const OpenTelemetry.Trace.TraceSemanticConventions.RpcGrpcStatusCodeValues.FailedPrecondition = 9 -> int +const OpenTelemetry.Trace.TraceSemanticConventions.RpcGrpcStatusCodeValues.Internal = 13 -> int +const OpenTelemetry.Trace.TraceSemanticConventions.RpcGrpcStatusCodeValues.InvalidArgument = 3 -> int +const OpenTelemetry.Trace.TraceSemanticConventions.RpcGrpcStatusCodeValues.NotFound = 5 -> int +const OpenTelemetry.Trace.TraceSemanticConventions.RpcGrpcStatusCodeValues.Ok = 0 -> int +const OpenTelemetry.Trace.TraceSemanticConventions.RpcGrpcStatusCodeValues.OutOfRange = 11 -> int +const OpenTelemetry.Trace.TraceSemanticConventions.RpcGrpcStatusCodeValues.PermissionDenied = 7 -> int +const OpenTelemetry.Trace.TraceSemanticConventions.RpcGrpcStatusCodeValues.ResourceExhausted = 8 -> int +const OpenTelemetry.Trace.TraceSemanticConventions.RpcGrpcStatusCodeValues.Unauthenticated = 16 -> int +const OpenTelemetry.Trace.TraceSemanticConventions.RpcGrpcStatusCodeValues.Unavailable = 14 -> int +const OpenTelemetry.Trace.TraceSemanticConventions.RpcGrpcStatusCodeValues.Unimplemented = 12 -> int +const OpenTelemetry.Trace.TraceSemanticConventions.RpcGrpcStatusCodeValues.Unknown = 2 -> int +const OpenTelemetry.Trace.TraceSemanticConventions.RpcSystemValues.ApacheDubbo = "apache_dubbo" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.RpcSystemValues.DotnetWcf = "dotnet_wcf" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.RpcSystemValues.Grpc = "grpc" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.RpcSystemValues.JavaRmi = "java_rmi" -> string +OpenTelemetry.Resources.ResourceSemanticConventions +OpenTelemetry.Resources.ResourceSemanticConventions.AwsEcsLaunchtypeValues +OpenTelemetry.Resources.ResourceSemanticConventions.CloudPlatformValues +OpenTelemetry.Resources.ResourceSemanticConventions.CloudProviderValues +OpenTelemetry.Resources.ResourceSemanticConventions.HostArchValues +OpenTelemetry.Resources.ResourceSemanticConventions.OsTypeValues +OpenTelemetry.Resources.ResourceSemanticConventions.TelemetrySdkLanguageValues +OpenTelemetry.Trace.TraceSemanticConventions +OpenTelemetry.Trace.TraceSemanticConventions.DbCassandraConsistencyLevelValues +OpenTelemetry.Trace.TraceSemanticConventions.DbSystemValues +OpenTelemetry.Trace.TraceSemanticConventions.FaasDocumentOperationValues +OpenTelemetry.Trace.TraceSemanticConventions.FaasInvokedProviderValues +OpenTelemetry.Trace.TraceSemanticConventions.FaasTriggerValues +OpenTelemetry.Trace.TraceSemanticConventions.GraphqlOperationTypeValues +OpenTelemetry.Trace.TraceSemanticConventions.HttpFlavorValues +OpenTelemetry.Trace.TraceSemanticConventions.MessageTypeValues +OpenTelemetry.Trace.TraceSemanticConventions.MessagingDestinationKindValues +OpenTelemetry.Trace.TraceSemanticConventions.MessagingOperationValues +OpenTelemetry.Trace.TraceSemanticConventions.MessagingRocketmqConsumptionModelValues +OpenTelemetry.Trace.TraceSemanticConventions.MessagingRocketmqMessageTypeValues +OpenTelemetry.Trace.TraceSemanticConventions.NetHostConnectionSubtypeValues +OpenTelemetry.Trace.TraceSemanticConventions.NetHostConnectionTypeValues +OpenTelemetry.Trace.TraceSemanticConventions.NetSockFamilyValues +OpenTelemetry.Trace.TraceSemanticConventions.NetTransportValues +OpenTelemetry.Trace.TraceSemanticConventions.OpentracingRefTypeValues +OpenTelemetry.Trace.TraceSemanticConventions.RpcGrpcStatusCodeValues +OpenTelemetry.Trace.TraceSemanticConventions.RpcSystemValues +static readonly OpenTelemetry.Resources.ResourceSemanticConventions.PrefixAwsEcs -> string +static readonly OpenTelemetry.Resources.ResourceSemanticConventions.PrefixAwsEks -> string +static readonly OpenTelemetry.Resources.ResourceSemanticConventions.PrefixAwsLog -> string +static readonly OpenTelemetry.Resources.ResourceSemanticConventions.PrefixBrowser -> string +static readonly OpenTelemetry.Resources.ResourceSemanticConventions.PrefixCloud -> string +static readonly OpenTelemetry.Resources.ResourceSemanticConventions.PrefixContainer -> string +static readonly OpenTelemetry.Resources.ResourceSemanticConventions.PrefixDeployment -> string +static readonly OpenTelemetry.Resources.ResourceSemanticConventions.PrefixDevice -> string +static readonly OpenTelemetry.Resources.ResourceSemanticConventions.PrefixFaasResource -> string +static readonly OpenTelemetry.Resources.ResourceSemanticConventions.PrefixHost -> string +static readonly OpenTelemetry.Resources.ResourceSemanticConventions.PrefixK8sCluster -> string +static readonly OpenTelemetry.Resources.ResourceSemanticConventions.PrefixK8sContainer -> string +static readonly OpenTelemetry.Resources.ResourceSemanticConventions.PrefixK8sCronjob -> string +static readonly OpenTelemetry.Resources.ResourceSemanticConventions.PrefixK8sDaemonset -> string +static readonly OpenTelemetry.Resources.ResourceSemanticConventions.PrefixK8sDeployment -> string +static readonly OpenTelemetry.Resources.ResourceSemanticConventions.PrefixK8sJob -> string +static readonly OpenTelemetry.Resources.ResourceSemanticConventions.PrefixK8sNamespace -> string +static readonly OpenTelemetry.Resources.ResourceSemanticConventions.PrefixK8sNode -> string +static readonly OpenTelemetry.Resources.ResourceSemanticConventions.PrefixK8sPod -> string +static readonly OpenTelemetry.Resources.ResourceSemanticConventions.PrefixK8sReplicaset -> string +static readonly OpenTelemetry.Resources.ResourceSemanticConventions.PrefixK8sStatefulset -> string +static readonly OpenTelemetry.Resources.ResourceSemanticConventions.PrefixOs -> string +static readonly OpenTelemetry.Resources.ResourceSemanticConventions.PrefixProcess -> string +static readonly OpenTelemetry.Resources.ResourceSemanticConventions.PrefixProcessRuntime -> string +static readonly OpenTelemetry.Resources.ResourceSemanticConventions.PrefixService -> string +static readonly OpenTelemetry.Resources.ResourceSemanticConventions.PrefixTelemetry -> string +static readonly OpenTelemetry.Resources.ResourceSemanticConventions.PrefixWebengineResource -> string +static readonly OpenTelemetry.Trace.TraceSemanticConventions.EventException -> string +static readonly OpenTelemetry.Trace.TraceSemanticConventions.EventRpcMessage -> string +static readonly OpenTelemetry.Trace.TraceSemanticConventions.PrefixAws -> string +static readonly OpenTelemetry.Trace.TraceSemanticConventions.PrefixAwsLambda -> string +static readonly OpenTelemetry.Trace.TraceSemanticConventions.PrefixCloudevents -> string +static readonly OpenTelemetry.Trace.TraceSemanticConventions.PrefixCode -> string +static readonly OpenTelemetry.Trace.TraceSemanticConventions.PrefixDb -> string +static readonly OpenTelemetry.Trace.TraceSemanticConventions.PrefixDbCassandra -> string +static readonly OpenTelemetry.Trace.TraceSemanticConventions.PrefixDbMongodb -> string +static readonly OpenTelemetry.Trace.TraceSemanticConventions.PrefixDbMssql -> string +static readonly OpenTelemetry.Trace.TraceSemanticConventions.PrefixDbRedis -> string +static readonly OpenTelemetry.Trace.TraceSemanticConventions.PrefixDbSql -> string +static readonly OpenTelemetry.Trace.TraceSemanticConventions.PrefixDynamodbShared -> string +static readonly OpenTelemetry.Trace.TraceSemanticConventions.PrefixException -> string +static readonly OpenTelemetry.Trace.TraceSemanticConventions.PrefixFaasSpan -> string +static readonly OpenTelemetry.Trace.TraceSemanticConventions.PrefixFaasSpanDatasource -> string +static readonly OpenTelemetry.Trace.TraceSemanticConventions.PrefixGraphql -> string +static readonly OpenTelemetry.Trace.TraceSemanticConventions.PrefixHttp -> string +static readonly OpenTelemetry.Trace.TraceSemanticConventions.PrefixIdentity -> string +static readonly OpenTelemetry.Trace.TraceSemanticConventions.PrefixMessaging -> string +static readonly OpenTelemetry.Trace.TraceSemanticConventions.PrefixMessagingKafka -> string +static readonly OpenTelemetry.Trace.TraceSemanticConventions.PrefixMessagingRabbitmq -> string +static readonly OpenTelemetry.Trace.TraceSemanticConventions.PrefixMessagingRocketmq -> string +static readonly OpenTelemetry.Trace.TraceSemanticConventions.PrefixNetwork -> string +static readonly OpenTelemetry.Trace.TraceSemanticConventions.PrefixOpentracing -> string +static readonly OpenTelemetry.Trace.TraceSemanticConventions.PrefixPeer -> string +static readonly OpenTelemetry.Trace.TraceSemanticConventions.PrefixRpc -> string +static readonly OpenTelemetry.Trace.TraceSemanticConventions.PrefixRpcGrpc -> string +static readonly OpenTelemetry.Trace.TraceSemanticConventions.PrefixRpcJsonrpc -> string +static readonly OpenTelemetry.Trace.TraceSemanticConventions.PrefixRpcMessage -> string +static readonly OpenTelemetry.Trace.TraceSemanticConventions.PrefixThread -> string \ No newline at end of file diff --git a/src/OpenTelemetry.SemanticConventions/.publicApi/netstandard2.0/PublicAPI.Shipped.txt b/src/OpenTelemetry.SemanticConventions/.publicApi/netstandard2.0/PublicAPI.Shipped.txt new file mode 100644 index 00000000000..e69de29bb2d diff --git a/src/OpenTelemetry.SemanticConventions/.publicApi/netstandard2.0/PublicAPI.Unshipped.txt b/src/OpenTelemetry.SemanticConventions/.publicApi/netstandard2.0/PublicAPI.Unshipped.txt new file mode 100644 index 00000000000..17864093bcd --- /dev/null +++ b/src/OpenTelemetry.SemanticConventions/.publicApi/netstandard2.0/PublicAPI.Unshipped.txt @@ -0,0 +1,526 @@ +const OpenTelemetry.Resources.ResourceSemanticConventions.AttributeAwsEcsClusterArn = "aws.ecs.cluster.arn" -> string +const OpenTelemetry.Resources.ResourceSemanticConventions.AttributeAwsEcsContainerArn = "aws.ecs.container.arn" -> string +const OpenTelemetry.Resources.ResourceSemanticConventions.AttributeAwsEcsLaunchtype = "aws.ecs.launchtype" -> string +const OpenTelemetry.Resources.ResourceSemanticConventions.AttributeAwsEcsTaskArn = "aws.ecs.task.arn" -> string +const OpenTelemetry.Resources.ResourceSemanticConventions.AttributeAwsEcsTaskFamily = "aws.ecs.task.family" -> string +const OpenTelemetry.Resources.ResourceSemanticConventions.AttributeAwsEcsTaskRevision = "aws.ecs.task.revision" -> string +const OpenTelemetry.Resources.ResourceSemanticConventions.AttributeAwsEksClusterArn = "aws.eks.cluster.arn" -> string +const OpenTelemetry.Resources.ResourceSemanticConventions.AttributeAwsLogGroupArns = "aws.log.group.arns" -> string +const OpenTelemetry.Resources.ResourceSemanticConventions.AttributeAwsLogGroupNames = "aws.log.group.names" -> string +const OpenTelemetry.Resources.ResourceSemanticConventions.AttributeAwsLogStreamArns = "aws.log.stream.arns" -> string +const OpenTelemetry.Resources.ResourceSemanticConventions.AttributeAwsLogStreamNames = "aws.log.stream.names" -> string +const OpenTelemetry.Resources.ResourceSemanticConventions.AttributeBrowserBrands = "browser.brands" -> string +const OpenTelemetry.Resources.ResourceSemanticConventions.AttributeBrowserPlatform = "browser.platform" -> string +const OpenTelemetry.Resources.ResourceSemanticConventions.AttributeBrowserUserAgent = "browser.user_agent" -> string +const OpenTelemetry.Resources.ResourceSemanticConventions.AttributeCloudAccountId = "cloud.account.id" -> string +const OpenTelemetry.Resources.ResourceSemanticConventions.AttributeCloudAvailabilityZone = "cloud.availability_zone" -> string +const OpenTelemetry.Resources.ResourceSemanticConventions.AttributeCloudPlatform = "cloud.platform" -> string +const OpenTelemetry.Resources.ResourceSemanticConventions.AttributeCloudProvider = "cloud.provider" -> string +const OpenTelemetry.Resources.ResourceSemanticConventions.AttributeCloudRegion = "cloud.region" -> string +const OpenTelemetry.Resources.ResourceSemanticConventions.AttributeContainerId = "container.id" -> string +const OpenTelemetry.Resources.ResourceSemanticConventions.AttributeContainerImageName = "container.image.name" -> string +const OpenTelemetry.Resources.ResourceSemanticConventions.AttributeContainerImageTag = "container.image.tag" -> string +const OpenTelemetry.Resources.ResourceSemanticConventions.AttributeContainerName = "container.name" -> string +const OpenTelemetry.Resources.ResourceSemanticConventions.AttributeContainerRuntime = "container.runtime" -> string +const OpenTelemetry.Resources.ResourceSemanticConventions.AttributeDeploymentEnvironment = "deployment.environment" -> string +const OpenTelemetry.Resources.ResourceSemanticConventions.AttributeDeviceId = "device.id" -> string +const OpenTelemetry.Resources.ResourceSemanticConventions.AttributeDeviceManufacturer = "device.manufacturer" -> string +const OpenTelemetry.Resources.ResourceSemanticConventions.AttributeDeviceModelIdentifier = "device.model.identifier" -> string +const OpenTelemetry.Resources.ResourceSemanticConventions.AttributeDeviceModelName = "device.model.name" -> string +const OpenTelemetry.Resources.ResourceSemanticConventions.AttributeFaasId = "faas.id" -> string +const OpenTelemetry.Resources.ResourceSemanticConventions.AttributeFaasInstance = "faas.instance" -> string +const OpenTelemetry.Resources.ResourceSemanticConventions.AttributeFaasMaxMemory = "faas.max_memory" -> string +const OpenTelemetry.Resources.ResourceSemanticConventions.AttributeFaasName = "faas.name" -> string +const OpenTelemetry.Resources.ResourceSemanticConventions.AttributeFaasVersion = "faas.version" -> string +const OpenTelemetry.Resources.ResourceSemanticConventions.AttributeHostArch = "host.arch" -> string +const OpenTelemetry.Resources.ResourceSemanticConventions.AttributeHostId = "host.id" -> string +const OpenTelemetry.Resources.ResourceSemanticConventions.AttributeHostImageId = "host.image.id" -> string +const OpenTelemetry.Resources.ResourceSemanticConventions.AttributeHostImageName = "host.image.name" -> string +const OpenTelemetry.Resources.ResourceSemanticConventions.AttributeHostImageVersion = "host.image.version" -> string +const OpenTelemetry.Resources.ResourceSemanticConventions.AttributeHostName = "host.name" -> string +const OpenTelemetry.Resources.ResourceSemanticConventions.AttributeHostType = "host.type" -> string +const OpenTelemetry.Resources.ResourceSemanticConventions.AttributeK8sClusterName = "k8s.cluster.name" -> string +const OpenTelemetry.Resources.ResourceSemanticConventions.AttributeK8sContainerName = "k8s.container.name" -> string +const OpenTelemetry.Resources.ResourceSemanticConventions.AttributeK8sContainerRestartCount = "k8s.container.restart_count" -> string +const OpenTelemetry.Resources.ResourceSemanticConventions.AttributeK8sCronjobName = "k8s.cronjob.name" -> string +const OpenTelemetry.Resources.ResourceSemanticConventions.AttributeK8sCronjobUid = "k8s.cronjob.uid" -> string +const OpenTelemetry.Resources.ResourceSemanticConventions.AttributeK8sDaemonsetName = "k8s.daemonset.name" -> string +const OpenTelemetry.Resources.ResourceSemanticConventions.AttributeK8sDaemonsetUid = "k8s.daemonset.uid" -> string +const OpenTelemetry.Resources.ResourceSemanticConventions.AttributeK8sDeploymentName = "k8s.deployment.name" -> string +const OpenTelemetry.Resources.ResourceSemanticConventions.AttributeK8sDeploymentUid = "k8s.deployment.uid" -> string +const OpenTelemetry.Resources.ResourceSemanticConventions.AttributeK8sJobName = "k8s.job.name" -> string +const OpenTelemetry.Resources.ResourceSemanticConventions.AttributeK8sJobUid = "k8s.job.uid" -> string +const OpenTelemetry.Resources.ResourceSemanticConventions.AttributeK8sNamespaceName = "k8s.namespace.name" -> string +const OpenTelemetry.Resources.ResourceSemanticConventions.AttributeK8sNodeName = "k8s.node.name" -> string +const OpenTelemetry.Resources.ResourceSemanticConventions.AttributeK8sNodeUid = "k8s.node.uid" -> string +const OpenTelemetry.Resources.ResourceSemanticConventions.AttributeK8sPodName = "k8s.pod.name" -> string +const OpenTelemetry.Resources.ResourceSemanticConventions.AttributeK8sPodUid = "k8s.pod.uid" -> string +const OpenTelemetry.Resources.ResourceSemanticConventions.AttributeK8sReplicasetName = "k8s.replicaset.name" -> string +const OpenTelemetry.Resources.ResourceSemanticConventions.AttributeK8sReplicasetUid = "k8s.replicaset.uid" -> string +const OpenTelemetry.Resources.ResourceSemanticConventions.AttributeK8sStatefulsetName = "k8s.statefulset.name" -> string +const OpenTelemetry.Resources.ResourceSemanticConventions.AttributeK8sStatefulsetUid = "k8s.statefulset.uid" -> string +const OpenTelemetry.Resources.ResourceSemanticConventions.AttributeOsDescription = "os.description" -> string +const OpenTelemetry.Resources.ResourceSemanticConventions.AttributeOsName = "os.name" -> string +const OpenTelemetry.Resources.ResourceSemanticConventions.AttributeOsType = "os.type" -> string +const OpenTelemetry.Resources.ResourceSemanticConventions.AttributeOsVersion = "os.version" -> string +const OpenTelemetry.Resources.ResourceSemanticConventions.AttributeProcessCommand = "process.command" -> string +const OpenTelemetry.Resources.ResourceSemanticConventions.AttributeProcessCommandArgs = "process.command_args" -> string +const OpenTelemetry.Resources.ResourceSemanticConventions.AttributeProcessCommandLine = "process.command_line" -> string +const OpenTelemetry.Resources.ResourceSemanticConventions.AttributeProcessExecutableName = "process.executable.name" -> string +const OpenTelemetry.Resources.ResourceSemanticConventions.AttributeProcessExecutablePath = "process.executable.path" -> string +const OpenTelemetry.Resources.ResourceSemanticConventions.AttributeProcessOwner = "process.owner" -> string +const OpenTelemetry.Resources.ResourceSemanticConventions.AttributeProcessParentPid = "process.parent_pid" -> string +const OpenTelemetry.Resources.ResourceSemanticConventions.AttributeProcessPid = "process.pid" -> string +const OpenTelemetry.Resources.ResourceSemanticConventions.AttributeProcessRuntimeDescription = "process.runtime.description" -> string +const OpenTelemetry.Resources.ResourceSemanticConventions.AttributeProcessRuntimeName = "process.runtime.name" -> string +const OpenTelemetry.Resources.ResourceSemanticConventions.AttributeProcessRuntimeVersion = "process.runtime.version" -> string +const OpenTelemetry.Resources.ResourceSemanticConventions.AttributeServiceInstanceId = "service.instance.id" -> string +const OpenTelemetry.Resources.ResourceSemanticConventions.AttributeServiceName = "service.name" -> string +const OpenTelemetry.Resources.ResourceSemanticConventions.AttributeServiceNamespace = "service.namespace" -> string +const OpenTelemetry.Resources.ResourceSemanticConventions.AttributeServiceVersion = "service.version" -> string +const OpenTelemetry.Resources.ResourceSemanticConventions.AttributeTelemetryAutoVersion = "telemetry.auto.version" -> string +const OpenTelemetry.Resources.ResourceSemanticConventions.AttributeTelemetrySdkLanguage = "telemetry.sdk.language" -> string +const OpenTelemetry.Resources.ResourceSemanticConventions.AttributeTelemetrySdkName = "telemetry.sdk.name" -> string +const OpenTelemetry.Resources.ResourceSemanticConventions.AttributeTelemetrySdkVersion = "telemetry.sdk.version" -> string +const OpenTelemetry.Resources.ResourceSemanticConventions.AttributeWebengineDescription = "webengine.description" -> string +const OpenTelemetry.Resources.ResourceSemanticConventions.AttributeWebengineName = "webengine.name" -> string +const OpenTelemetry.Resources.ResourceSemanticConventions.AttributeWebengineVersion = "webengine.version" -> string +const OpenTelemetry.Resources.ResourceSemanticConventions.AwsEcsLaunchtypeValues.Ec2 = "ec2" -> string +const OpenTelemetry.Resources.ResourceSemanticConventions.AwsEcsLaunchtypeValues.Fargate = "fargate" -> string +const OpenTelemetry.Resources.ResourceSemanticConventions.CloudPlatformValues.AlibabaCloudEcs = "alibaba_cloud_ecs" -> string +const OpenTelemetry.Resources.ResourceSemanticConventions.CloudPlatformValues.AlibabaCloudFc = "alibaba_cloud_fc" -> string +const OpenTelemetry.Resources.ResourceSemanticConventions.CloudPlatformValues.AwsAppRunner = "aws_app_runner" -> string +const OpenTelemetry.Resources.ResourceSemanticConventions.CloudPlatformValues.AwsEc2 = "aws_ec2" -> string +const OpenTelemetry.Resources.ResourceSemanticConventions.CloudPlatformValues.AwsEcs = "aws_ecs" -> string +const OpenTelemetry.Resources.ResourceSemanticConventions.CloudPlatformValues.AwsEks = "aws_eks" -> string +const OpenTelemetry.Resources.ResourceSemanticConventions.CloudPlatformValues.AwsElasticBeanstalk = "aws_elastic_beanstalk" -> string +const OpenTelemetry.Resources.ResourceSemanticConventions.CloudPlatformValues.AwsLambda = "aws_lambda" -> string +const OpenTelemetry.Resources.ResourceSemanticConventions.CloudPlatformValues.AzureAks = "azure_aks" -> string +const OpenTelemetry.Resources.ResourceSemanticConventions.CloudPlatformValues.AzureAppService = "azure_app_service" -> string +const OpenTelemetry.Resources.ResourceSemanticConventions.CloudPlatformValues.AzureContainerInstances = "azure_container_instances" -> string +const OpenTelemetry.Resources.ResourceSemanticConventions.CloudPlatformValues.AzureFunctions = "azure_functions" -> string +const OpenTelemetry.Resources.ResourceSemanticConventions.CloudPlatformValues.AzureVm = "azure_vm" -> string +const OpenTelemetry.Resources.ResourceSemanticConventions.CloudPlatformValues.GcpAppEngine = "gcp_app_engine" -> string +const OpenTelemetry.Resources.ResourceSemanticConventions.CloudPlatformValues.GcpCloudFunctions = "gcp_cloud_functions" -> string +const OpenTelemetry.Resources.ResourceSemanticConventions.CloudPlatformValues.GcpCloudRun = "gcp_cloud_run" -> string +const OpenTelemetry.Resources.ResourceSemanticConventions.CloudPlatformValues.GcpComputeEngine = "gcp_compute_engine" -> string +const OpenTelemetry.Resources.ResourceSemanticConventions.CloudPlatformValues.GcpKubernetesEngine = "gcp_kubernetes_engine" -> string +const OpenTelemetry.Resources.ResourceSemanticConventions.CloudPlatformValues.TencentCloudCvm = "tencent_cloud_cvm" -> string +const OpenTelemetry.Resources.ResourceSemanticConventions.CloudPlatformValues.TencentCloudEks = "tencent_cloud_eks" -> string +const OpenTelemetry.Resources.ResourceSemanticConventions.CloudPlatformValues.TencentCloudScf = "tencent_cloud_scf" -> string +const OpenTelemetry.Resources.ResourceSemanticConventions.CloudProviderValues.AlibabaCloud = "alibaba_cloud" -> string +const OpenTelemetry.Resources.ResourceSemanticConventions.CloudProviderValues.Aws = "aws" -> string +const OpenTelemetry.Resources.ResourceSemanticConventions.CloudProviderValues.Azure = "azure" -> string +const OpenTelemetry.Resources.ResourceSemanticConventions.CloudProviderValues.Gcp = "gcp" -> string +const OpenTelemetry.Resources.ResourceSemanticConventions.CloudProviderValues.TencentCloud = "tencent_cloud" -> string +const OpenTelemetry.Resources.ResourceSemanticConventions.HostArchValues.Amd64 = "amd64" -> string +const OpenTelemetry.Resources.ResourceSemanticConventions.HostArchValues.Arm32 = "arm32" -> string +const OpenTelemetry.Resources.ResourceSemanticConventions.HostArchValues.Arm64 = "arm64" -> string +const OpenTelemetry.Resources.ResourceSemanticConventions.HostArchValues.Ia64 = "ia64" -> string +const OpenTelemetry.Resources.ResourceSemanticConventions.HostArchValues.Ppc32 = "ppc32" -> string +const OpenTelemetry.Resources.ResourceSemanticConventions.HostArchValues.Ppc64 = "ppc64" -> string +const OpenTelemetry.Resources.ResourceSemanticConventions.HostArchValues.S390x = "s390x" -> string +const OpenTelemetry.Resources.ResourceSemanticConventions.HostArchValues.X86 = "x86" -> string +const OpenTelemetry.Resources.ResourceSemanticConventions.OsTypeValues.Aix = "aix" -> string +const OpenTelemetry.Resources.ResourceSemanticConventions.OsTypeValues.Darwin = "darwin" -> string +const OpenTelemetry.Resources.ResourceSemanticConventions.OsTypeValues.Dragonflybsd = "dragonflybsd" -> string +const OpenTelemetry.Resources.ResourceSemanticConventions.OsTypeValues.Freebsd = "freebsd" -> string +const OpenTelemetry.Resources.ResourceSemanticConventions.OsTypeValues.Hpux = "hpux" -> string +const OpenTelemetry.Resources.ResourceSemanticConventions.OsTypeValues.Linux = "linux" -> string +const OpenTelemetry.Resources.ResourceSemanticConventions.OsTypeValues.Netbsd = "netbsd" -> string +const OpenTelemetry.Resources.ResourceSemanticConventions.OsTypeValues.Openbsd = "openbsd" -> string +const OpenTelemetry.Resources.ResourceSemanticConventions.OsTypeValues.Solaris = "solaris" -> string +const OpenTelemetry.Resources.ResourceSemanticConventions.OsTypeValues.Windows = "windows" -> string +const OpenTelemetry.Resources.ResourceSemanticConventions.OsTypeValues.ZOs = "z_os" -> string +const OpenTelemetry.Resources.ResourceSemanticConventions.TelemetrySdkLanguageValues.Cpp = "cpp" -> string +const OpenTelemetry.Resources.ResourceSemanticConventions.TelemetrySdkLanguageValues.Dotnet = "dotnet" -> string +const OpenTelemetry.Resources.ResourceSemanticConventions.TelemetrySdkLanguageValues.Erlang = "erlang" -> string +const OpenTelemetry.Resources.ResourceSemanticConventions.TelemetrySdkLanguageValues.Go = "go" -> string +const OpenTelemetry.Resources.ResourceSemanticConventions.TelemetrySdkLanguageValues.Java = "java" -> string +const OpenTelemetry.Resources.ResourceSemanticConventions.TelemetrySdkLanguageValues.Nodejs = "nodejs" -> string +const OpenTelemetry.Resources.ResourceSemanticConventions.TelemetrySdkLanguageValues.Php = "php" -> string +const OpenTelemetry.Resources.ResourceSemanticConventions.TelemetrySdkLanguageValues.Python = "python" -> string +const OpenTelemetry.Resources.ResourceSemanticConventions.TelemetrySdkLanguageValues.Ruby = "ruby" -> string +const OpenTelemetry.Resources.ResourceSemanticConventions.TelemetrySdkLanguageValues.Swift = "swift" -> string +const OpenTelemetry.Resources.ResourceSemanticConventions.TelemetrySdkLanguageValues.Webjs = "webjs" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.AttributeAwsDynamodbAttributeDefinitions = "aws.dynamodb.attribute_definitions" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.AttributeAwsDynamodbAttributesToGet = "aws.dynamodb.attributes_to_get" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.AttributeAwsDynamodbConsistentRead = "aws.dynamodb.consistent_read" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.AttributeAwsDynamodbConsumedCapacity = "aws.dynamodb.consumed_capacity" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.AttributeAwsDynamodbCount = "aws.dynamodb.count" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.AttributeAwsDynamodbExclusiveStartTable = "aws.dynamodb.exclusive_start_table" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.AttributeAwsDynamodbGlobalSecondaryIndexes = "aws.dynamodb.global_secondary_indexes" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.AttributeAwsDynamodbGlobalSecondaryIndexUpdates = "aws.dynamodb.global_secondary_index_updates" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.AttributeAwsDynamodbIndexName = "aws.dynamodb.index_name" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.AttributeAwsDynamodbItemCollectionMetrics = "aws.dynamodb.item_collection_metrics" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.AttributeAwsDynamodbLimit = "aws.dynamodb.limit" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.AttributeAwsDynamodbLocalSecondaryIndexes = "aws.dynamodb.local_secondary_indexes" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.AttributeAwsDynamodbProjection = "aws.dynamodb.projection" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.AttributeAwsDynamodbProvisionedReadCapacity = "aws.dynamodb.provisioned_read_capacity" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.AttributeAwsDynamodbProvisionedWriteCapacity = "aws.dynamodb.provisioned_write_capacity" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.AttributeAwsDynamodbScanForward = "aws.dynamodb.scan_forward" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.AttributeAwsDynamodbScannedCount = "aws.dynamodb.scanned_count" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.AttributeAwsDynamodbSegment = "aws.dynamodb.segment" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.AttributeAwsDynamodbSelect = "aws.dynamodb.select" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.AttributeAwsDynamodbTableCount = "aws.dynamodb.table_count" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.AttributeAwsDynamodbTableNames = "aws.dynamodb.table_names" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.AttributeAwsDynamodbTotalSegments = "aws.dynamodb.total_segments" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.AttributeAwsLambdaInvokedArn = "aws.lambda.invoked_arn" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.AttributeCloudeventsEventId = "cloudevents.event_id" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.AttributeCloudeventsEventSource = "cloudevents.event_source" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.AttributeCloudeventsEventSpecVersion = "cloudevents.event_spec_version" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.AttributeCloudeventsEventSubject = "cloudevents.event_subject" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.AttributeCloudeventsEventType = "cloudevents.event_type" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.AttributeCodeFilepath = "code.filepath" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.AttributeCodeFunction = "code.function" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.AttributeCodeLineno = "code.lineno" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.AttributeCodeNamespace = "code.namespace" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.AttributeDbCassandraConsistencyLevel = "db.cassandra.consistency_level" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.AttributeDbCassandraCoordinatorDc = "db.cassandra.coordinator.dc" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.AttributeDbCassandraCoordinatorId = "db.cassandra.coordinator.id" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.AttributeDbCassandraIdempotence = "db.cassandra.idempotence" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.AttributeDbCassandraPageSize = "db.cassandra.page_size" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.AttributeDbCassandraSpeculativeExecutionCount = "db.cassandra.speculative_execution_count" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.AttributeDbCassandraTable = "db.cassandra.table" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.AttributeDbConnectionString = "db.connection_string" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.AttributeDbInstance = "db.instance" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.AttributeDbJdbcDriverClassname = "db.jdbc.driver_classname" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.AttributeDbMongodbCollection = "db.mongodb.collection" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.AttributeDbMssqlInstanceName = "db.mssql.instance_name" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.AttributeDbName = "db.name" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.AttributeDbOperation = "db.operation" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.AttributeDbRedisDatabaseIndex = "db.redis.database_index" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.AttributeDbSqlTable = "db.sql.table" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.AttributeDbStatement = "db.statement" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.AttributeDbSystem = "db.system" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.AttributeDbUser = "db.user" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.AttributeEnduserId = "enduser.id" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.AttributeEnduserRole = "enduser.role" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.AttributeEnduserScope = "enduser.scope" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.AttributeExceptionEscaped = "exception.escaped" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.AttributeExceptionMessage = "exception.message" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.AttributeExceptionStacktrace = "exception.stacktrace" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.AttributeExceptionType = "exception.type" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.AttributeFaasColdstart = "faas.coldstart" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.AttributeFaasCron = "faas.cron" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.AttributeFaasDocumentCollection = "faas.document.collection" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.AttributeFaasDocumentName = "faas.document.name" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.AttributeFaasDocumentOperation = "faas.document.operation" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.AttributeFaasDocumentTime = "faas.document.time" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.AttributeFaasExecution = "faas.execution" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.AttributeFaasInvokedName = "faas.invoked_name" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.AttributeFaasInvokedProvider = "faas.invoked_provider" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.AttributeFaasInvokedRegion = "faas.invoked_region" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.AttributeFaasTime = "faas.time" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.AttributeFaasTrigger = "faas.trigger" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.AttributeGraphqlDocument = "graphql.document" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.AttributeGraphqlOperationName = "graphql.operation.name" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.AttributeGraphqlOperationType = "graphql.operation.type" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.AttributeHttpClientIp = "http.client_ip" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.AttributeHttpFlavor = "http.flavor" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.AttributeHttpMethod = "http.method" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.AttributeHttpRequestContentLength = "http.request_content_length" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.AttributeHttpResponseContentLength = "http.response_content_length" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.AttributeHttpRetryCount = "http.retry_count" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.AttributeHttpRoute = "http.route" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.AttributeHttpScheme = "http.scheme" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.AttributeHttpStatusCode = "http.status_code" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.AttributeHttpTarget = "http.target" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.AttributeHttpUrl = "http.url" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.AttributeHttpUserAgent = "http.user_agent" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.AttributeMessageCompressedSize = "message.compressed_size" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.AttributeMessageId = "message.id" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.AttributeMessageType = "message.type" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.AttributeMessageUncompressedSize = "message.uncompressed_size" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.AttributeMessagingConsumerId = "messaging.consumer_id" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.AttributeMessagingConversationId = "messaging.conversation_id" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.AttributeMessagingDestination = "messaging.destination" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.AttributeMessagingDestinationKind = "messaging.destination_kind" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.AttributeMessagingKafkaClientId = "messaging.kafka.client_id" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.AttributeMessagingKafkaConsumerGroup = "messaging.kafka.consumer_group" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.AttributeMessagingKafkaMessageKey = "messaging.kafka.message_key" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.AttributeMessagingKafkaPartition = "messaging.kafka.partition" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.AttributeMessagingKafkaTombstone = "messaging.kafka.tombstone" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.AttributeMessagingMessageId = "messaging.message_id" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.AttributeMessagingMessagePayloadCompressedSizeBytes = "messaging.message_payload_compressed_size_bytes" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.AttributeMessagingMessagePayloadSizeBytes = "messaging.message_payload_size_bytes" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.AttributeMessagingOperation = "messaging.operation" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.AttributeMessagingProtocol = "messaging.protocol" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.AttributeMessagingProtocolVersion = "messaging.protocol_version" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.AttributeMessagingRabbitmqRoutingKey = "messaging.rabbitmq.routing_key" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.AttributeMessagingRocketmqClientGroup = "messaging.rocketmq.client_group" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.AttributeMessagingRocketmqClientId = "messaging.rocketmq.client_id" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.AttributeMessagingRocketmqConsumptionModel = "messaging.rocketmq.consumption_model" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.AttributeMessagingRocketmqMessageKeys = "messaging.rocketmq.message_keys" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.AttributeMessagingRocketmqMessageTag = "messaging.rocketmq.message_tag" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.AttributeMessagingRocketmqMessageType = "messaging.rocketmq.message_type" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.AttributeMessagingRocketmqNamespace = "messaging.rocketmq.namespace" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.AttributeMessagingSystem = "messaging.system" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.AttributeMessagingTempDestination = "messaging.temp_destination" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.AttributeMessagingUrl = "messaging.url" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.AttributeNetAppProtocolName = "net.app.protocol.name" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.AttributeNetAppProtocolVersion = "net.app.protocol.version" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.AttributeNetHostCarrierIcc = "net.host.carrier.icc" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.AttributeNetHostCarrierMcc = "net.host.carrier.mcc" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.AttributeNetHostCarrierMnc = "net.host.carrier.mnc" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.AttributeNetHostCarrierName = "net.host.carrier.name" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.AttributeNetHostConnectionSubtype = "net.host.connection.subtype" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.AttributeNetHostConnectionType = "net.host.connection.type" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.AttributeNetHostName = "net.host.name" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.AttributeNetHostPort = "net.host.port" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.AttributeNetPeerName = "net.peer.name" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.AttributeNetPeerPort = "net.peer.port" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.AttributeNetSockFamily = "net.sock.family" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.AttributeNetSockHostAddr = "net.sock.host.addr" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.AttributeNetSockHostPort = "net.sock.host.port" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.AttributeNetSockPeerAddr = "net.sock.peer.addr" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.AttributeNetSockPeerName = "net.sock.peer.name" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.AttributeNetSockPeerPort = "net.sock.peer.port" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.AttributeNetTransport = "net.transport" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.AttributeOpentracingRefType = "opentracing.ref_type" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.AttributePeerService = "peer.service" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.AttributeRpcGrpcStatusCode = "rpc.grpc.status_code" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.AttributeRpcJsonrpcErrorCode = "rpc.jsonrpc.error_code" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.AttributeRpcJsonrpcErrorMessage = "rpc.jsonrpc.error_message" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.AttributeRpcJsonrpcRequestId = "rpc.jsonrpc.request_id" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.AttributeRpcJsonrpcVersion = "rpc.jsonrpc.version" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.AttributeRpcMethod = "rpc.method" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.AttributeRpcService = "rpc.service" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.AttributeRpcSystem = "rpc.system" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.AttributeThreadId = "thread.id" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.AttributeThreadName = "thread.name" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.DbCassandraConsistencyLevelValues.All = "all" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.DbCassandraConsistencyLevelValues.Any = "any" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.DbCassandraConsistencyLevelValues.EachQuorum = "each_quorum" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.DbCassandraConsistencyLevelValues.LocalOne = "local_one" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.DbCassandraConsistencyLevelValues.LocalQuorum = "local_quorum" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.DbCassandraConsistencyLevelValues.LocalSerial = "local_serial" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.DbCassandraConsistencyLevelValues.One = "one" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.DbCassandraConsistencyLevelValues.Quorum = "quorum" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.DbCassandraConsistencyLevelValues.Serial = "serial" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.DbCassandraConsistencyLevelValues.Three = "three" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.DbCassandraConsistencyLevelValues.Two = "two" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.DbSystemValues.Adabas = "adabas" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.DbSystemValues.Cache = "cache" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.DbSystemValues.Cassandra = "cassandra" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.DbSystemValues.Cloudscape = "cloudscape" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.DbSystemValues.Cockroachdb = "cockroachdb" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.DbSystemValues.Coldfusion = "coldfusion" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.DbSystemValues.Cosmosdb = "cosmosdb" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.DbSystemValues.Couchbase = "couchbase" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.DbSystemValues.Couchdb = "couchdb" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.DbSystemValues.Db2 = "db2" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.DbSystemValues.Derby = "derby" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.DbSystemValues.Dynamodb = "dynamodb" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.DbSystemValues.Edb = "edb" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.DbSystemValues.Elasticsearch = "elasticsearch" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.DbSystemValues.Filemaker = "filemaker" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.DbSystemValues.Firebird = "firebird" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.DbSystemValues.Firstsql = "firstsql" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.DbSystemValues.Geode = "geode" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.DbSystemValues.H2 = "h2" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.DbSystemValues.Hanadb = "hanadb" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.DbSystemValues.Hbase = "hbase" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.DbSystemValues.Hive = "hive" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.DbSystemValues.Hsqldb = "hsqldb" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.DbSystemValues.Informix = "informix" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.DbSystemValues.Ingres = "ingres" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.DbSystemValues.Instantdb = "instantdb" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.DbSystemValues.Interbase = "interbase" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.DbSystemValues.Mariadb = "mariadb" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.DbSystemValues.Maxdb = "maxdb" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.DbSystemValues.Memcached = "memcached" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.DbSystemValues.Mongodb = "mongodb" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.DbSystemValues.Mssql = "mssql" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.DbSystemValues.Mysql = "mysql" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.DbSystemValues.Neo4j = "neo4j" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.DbSystemValues.Netezza = "netezza" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.DbSystemValues.Opensearch = "opensearch" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.DbSystemValues.Oracle = "oracle" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.DbSystemValues.OtherSql = "other_sql" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.DbSystemValues.Pervasive = "pervasive" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.DbSystemValues.Pointbase = "pointbase" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.DbSystemValues.Postgresql = "postgresql" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.DbSystemValues.Progress = "progress" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.DbSystemValues.Redis = "redis" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.DbSystemValues.Redshift = "redshift" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.DbSystemValues.Sqlite = "sqlite" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.DbSystemValues.Sybase = "sybase" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.DbSystemValues.Teradata = "teradata" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.DbSystemValues.Vertica = "vertica" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.FaasDocumentOperationValues.Delete = "delete" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.FaasDocumentOperationValues.Edit = "edit" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.FaasDocumentOperationValues.Insert = "insert" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.FaasInvokedProviderValues.AlibabaCloud = "alibaba_cloud" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.FaasInvokedProviderValues.Aws = "aws" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.FaasInvokedProviderValues.Azure = "azure" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.FaasInvokedProviderValues.Gcp = "gcp" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.FaasInvokedProviderValues.TencentCloud = "tencent_cloud" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.FaasTriggerValues.Datasource = "datasource" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.FaasTriggerValues.Http = "http" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.FaasTriggerValues.Other = "other" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.FaasTriggerValues.Pubsub = "pubsub" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.FaasTriggerValues.Timer = "timer" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.GraphqlOperationTypeValues.Mutation = "mutation" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.GraphqlOperationTypeValues.Query = "query" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.GraphqlOperationTypeValues.Subscription = "subscription" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.HttpFlavorValues.Http10 = "1.0" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.HttpFlavorValues.Http11 = "1.1" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.HttpFlavorValues.Http20 = "2.0" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.HttpFlavorValues.Http30 = "3.0" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.HttpFlavorValues.Quic = "QUIC" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.HttpFlavorValues.Spdy = "SPDY" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.MessageTypeValues.Received = "RECEIVED" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.MessageTypeValues.Sent = "SENT" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.MessagingDestinationKindValues.Queue = "queue" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.MessagingDestinationKindValues.Topic = "topic" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.MessagingOperationValues.Process = "process" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.MessagingOperationValues.Receive = "receive" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.MessagingRocketmqConsumptionModelValues.Broadcasting = "broadcasting" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.MessagingRocketmqConsumptionModelValues.Clustering = "clustering" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.MessagingRocketmqMessageTypeValues.Delay = "delay" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.MessagingRocketmqMessageTypeValues.Fifo = "fifo" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.MessagingRocketmqMessageTypeValues.Normal = "normal" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.MessagingRocketmqMessageTypeValues.Transaction = "transaction" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.NetHostConnectionSubtypeValues.Cdma = "cdma" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.NetHostConnectionSubtypeValues.Cdma20001xrtt = "cdma2000_1xrtt" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.NetHostConnectionSubtypeValues.Edge = "edge" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.NetHostConnectionSubtypeValues.Ehrpd = "ehrpd" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.NetHostConnectionSubtypeValues.Evdo0 = "evdo_0" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.NetHostConnectionSubtypeValues.EvdoA = "evdo_a" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.NetHostConnectionSubtypeValues.EvdoB = "evdo_b" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.NetHostConnectionSubtypeValues.Gprs = "gprs" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.NetHostConnectionSubtypeValues.Gsm = "gsm" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.NetHostConnectionSubtypeValues.Hsdpa = "hsdpa" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.NetHostConnectionSubtypeValues.Hspa = "hspa" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.NetHostConnectionSubtypeValues.Hspap = "hspap" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.NetHostConnectionSubtypeValues.Hsupa = "hsupa" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.NetHostConnectionSubtypeValues.Iden = "iden" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.NetHostConnectionSubtypeValues.Iwlan = "iwlan" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.NetHostConnectionSubtypeValues.Lte = "lte" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.NetHostConnectionSubtypeValues.LteCa = "lte_ca" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.NetHostConnectionSubtypeValues.Nr = "nr" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.NetHostConnectionSubtypeValues.Nrnsa = "nrnsa" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.NetHostConnectionSubtypeValues.TdScdma = "td_scdma" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.NetHostConnectionSubtypeValues.Umts = "umts" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.NetHostConnectionTypeValues.Cell = "cell" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.NetHostConnectionTypeValues.Unavailable = "unavailable" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.NetHostConnectionTypeValues.Unknown = "unknown" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.NetHostConnectionTypeValues.Wifi = "wifi" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.NetHostConnectionTypeValues.Wired = "wired" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.NetSockFamilyValues.Inet = "inet" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.NetSockFamilyValues.Inet6 = "inet6" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.NetSockFamilyValues.Unix = "unix" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.NetTransportValues.Inproc = "inproc" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.NetTransportValues.IpTcp = "ip_tcp" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.NetTransportValues.IpUdp = "ip_udp" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.NetTransportValues.Other = "other" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.NetTransportValues.Pipe = "pipe" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.OpentracingRefTypeValues.ChildOf = "child_of" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.OpentracingRefTypeValues.FollowsFrom = "follows_from" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.RpcGrpcStatusCodeValues.Aborted = 10 -> int +const OpenTelemetry.Trace.TraceSemanticConventions.RpcGrpcStatusCodeValues.AlreadyExists = 6 -> int +const OpenTelemetry.Trace.TraceSemanticConventions.RpcGrpcStatusCodeValues.Cancelled = 1 -> int +const OpenTelemetry.Trace.TraceSemanticConventions.RpcGrpcStatusCodeValues.DataLoss = 15 -> int +const OpenTelemetry.Trace.TraceSemanticConventions.RpcGrpcStatusCodeValues.DeadlineExceeded = 4 -> int +const OpenTelemetry.Trace.TraceSemanticConventions.RpcGrpcStatusCodeValues.FailedPrecondition = 9 -> int +const OpenTelemetry.Trace.TraceSemanticConventions.RpcGrpcStatusCodeValues.Internal = 13 -> int +const OpenTelemetry.Trace.TraceSemanticConventions.RpcGrpcStatusCodeValues.InvalidArgument = 3 -> int +const OpenTelemetry.Trace.TraceSemanticConventions.RpcGrpcStatusCodeValues.NotFound = 5 -> int +const OpenTelemetry.Trace.TraceSemanticConventions.RpcGrpcStatusCodeValues.Ok = 0 -> int +const OpenTelemetry.Trace.TraceSemanticConventions.RpcGrpcStatusCodeValues.OutOfRange = 11 -> int +const OpenTelemetry.Trace.TraceSemanticConventions.RpcGrpcStatusCodeValues.PermissionDenied = 7 -> int +const OpenTelemetry.Trace.TraceSemanticConventions.RpcGrpcStatusCodeValues.ResourceExhausted = 8 -> int +const OpenTelemetry.Trace.TraceSemanticConventions.RpcGrpcStatusCodeValues.Unauthenticated = 16 -> int +const OpenTelemetry.Trace.TraceSemanticConventions.RpcGrpcStatusCodeValues.Unavailable = 14 -> int +const OpenTelemetry.Trace.TraceSemanticConventions.RpcGrpcStatusCodeValues.Unimplemented = 12 -> int +const OpenTelemetry.Trace.TraceSemanticConventions.RpcGrpcStatusCodeValues.Unknown = 2 -> int +const OpenTelemetry.Trace.TraceSemanticConventions.RpcSystemValues.ApacheDubbo = "apache_dubbo" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.RpcSystemValues.DotnetWcf = "dotnet_wcf" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.RpcSystemValues.Grpc = "grpc" -> string +const OpenTelemetry.Trace.TraceSemanticConventions.RpcSystemValues.JavaRmi = "java_rmi" -> string +OpenTelemetry.Resources.ResourceSemanticConventions +OpenTelemetry.Resources.ResourceSemanticConventions.AwsEcsLaunchtypeValues +OpenTelemetry.Resources.ResourceSemanticConventions.CloudPlatformValues +OpenTelemetry.Resources.ResourceSemanticConventions.CloudProviderValues +OpenTelemetry.Resources.ResourceSemanticConventions.HostArchValues +OpenTelemetry.Resources.ResourceSemanticConventions.OsTypeValues +OpenTelemetry.Resources.ResourceSemanticConventions.TelemetrySdkLanguageValues +OpenTelemetry.Trace.TraceSemanticConventions +OpenTelemetry.Trace.TraceSemanticConventions.DbCassandraConsistencyLevelValues +OpenTelemetry.Trace.TraceSemanticConventions.DbSystemValues +OpenTelemetry.Trace.TraceSemanticConventions.FaasDocumentOperationValues +OpenTelemetry.Trace.TraceSemanticConventions.FaasInvokedProviderValues +OpenTelemetry.Trace.TraceSemanticConventions.FaasTriggerValues +OpenTelemetry.Trace.TraceSemanticConventions.GraphqlOperationTypeValues +OpenTelemetry.Trace.TraceSemanticConventions.HttpFlavorValues +OpenTelemetry.Trace.TraceSemanticConventions.MessageTypeValues +OpenTelemetry.Trace.TraceSemanticConventions.MessagingDestinationKindValues +OpenTelemetry.Trace.TraceSemanticConventions.MessagingOperationValues +OpenTelemetry.Trace.TraceSemanticConventions.MessagingRocketmqConsumptionModelValues +OpenTelemetry.Trace.TraceSemanticConventions.MessagingRocketmqMessageTypeValues +OpenTelemetry.Trace.TraceSemanticConventions.NetHostConnectionSubtypeValues +OpenTelemetry.Trace.TraceSemanticConventions.NetHostConnectionTypeValues +OpenTelemetry.Trace.TraceSemanticConventions.NetSockFamilyValues +OpenTelemetry.Trace.TraceSemanticConventions.NetTransportValues +OpenTelemetry.Trace.TraceSemanticConventions.OpentracingRefTypeValues +OpenTelemetry.Trace.TraceSemanticConventions.RpcGrpcStatusCodeValues +OpenTelemetry.Trace.TraceSemanticConventions.RpcSystemValues +static readonly OpenTelemetry.Resources.ResourceSemanticConventions.PrefixAwsEcs -> string +static readonly OpenTelemetry.Resources.ResourceSemanticConventions.PrefixAwsEks -> string +static readonly OpenTelemetry.Resources.ResourceSemanticConventions.PrefixAwsLog -> string +static readonly OpenTelemetry.Resources.ResourceSemanticConventions.PrefixBrowser -> string +static readonly OpenTelemetry.Resources.ResourceSemanticConventions.PrefixCloud -> string +static readonly OpenTelemetry.Resources.ResourceSemanticConventions.PrefixContainer -> string +static readonly OpenTelemetry.Resources.ResourceSemanticConventions.PrefixDeployment -> string +static readonly OpenTelemetry.Resources.ResourceSemanticConventions.PrefixDevice -> string +static readonly OpenTelemetry.Resources.ResourceSemanticConventions.PrefixFaasResource -> string +static readonly OpenTelemetry.Resources.ResourceSemanticConventions.PrefixHost -> string +static readonly OpenTelemetry.Resources.ResourceSemanticConventions.PrefixK8sCluster -> string +static readonly OpenTelemetry.Resources.ResourceSemanticConventions.PrefixK8sContainer -> string +static readonly OpenTelemetry.Resources.ResourceSemanticConventions.PrefixK8sCronjob -> string +static readonly OpenTelemetry.Resources.ResourceSemanticConventions.PrefixK8sDaemonset -> string +static readonly OpenTelemetry.Resources.ResourceSemanticConventions.PrefixK8sDeployment -> string +static readonly OpenTelemetry.Resources.ResourceSemanticConventions.PrefixK8sJob -> string +static readonly OpenTelemetry.Resources.ResourceSemanticConventions.PrefixK8sNamespace -> string +static readonly OpenTelemetry.Resources.ResourceSemanticConventions.PrefixK8sNode -> string +static readonly OpenTelemetry.Resources.ResourceSemanticConventions.PrefixK8sPod -> string +static readonly OpenTelemetry.Resources.ResourceSemanticConventions.PrefixK8sReplicaset -> string +static readonly OpenTelemetry.Resources.ResourceSemanticConventions.PrefixK8sStatefulset -> string +static readonly OpenTelemetry.Resources.ResourceSemanticConventions.PrefixOs -> string +static readonly OpenTelemetry.Resources.ResourceSemanticConventions.PrefixProcess -> string +static readonly OpenTelemetry.Resources.ResourceSemanticConventions.PrefixProcessRuntime -> string +static readonly OpenTelemetry.Resources.ResourceSemanticConventions.PrefixService -> string +static readonly OpenTelemetry.Resources.ResourceSemanticConventions.PrefixTelemetry -> string +static readonly OpenTelemetry.Resources.ResourceSemanticConventions.PrefixWebengineResource -> string +static readonly OpenTelemetry.Trace.TraceSemanticConventions.EventException -> string +static readonly OpenTelemetry.Trace.TraceSemanticConventions.EventRpcMessage -> string +static readonly OpenTelemetry.Trace.TraceSemanticConventions.PrefixAws -> string +static readonly OpenTelemetry.Trace.TraceSemanticConventions.PrefixAwsLambda -> string +static readonly OpenTelemetry.Trace.TraceSemanticConventions.PrefixCloudevents -> string +static readonly OpenTelemetry.Trace.TraceSemanticConventions.PrefixCode -> string +static readonly OpenTelemetry.Trace.TraceSemanticConventions.PrefixDb -> string +static readonly OpenTelemetry.Trace.TraceSemanticConventions.PrefixDbCassandra -> string +static readonly OpenTelemetry.Trace.TraceSemanticConventions.PrefixDbMongodb -> string +static readonly OpenTelemetry.Trace.TraceSemanticConventions.PrefixDbMssql -> string +static readonly OpenTelemetry.Trace.TraceSemanticConventions.PrefixDbRedis -> string +static readonly OpenTelemetry.Trace.TraceSemanticConventions.PrefixDbSql -> string +static readonly OpenTelemetry.Trace.TraceSemanticConventions.PrefixDynamodbShared -> string +static readonly OpenTelemetry.Trace.TraceSemanticConventions.PrefixException -> string +static readonly OpenTelemetry.Trace.TraceSemanticConventions.PrefixFaasSpan -> string +static readonly OpenTelemetry.Trace.TraceSemanticConventions.PrefixFaasSpanDatasource -> string +static readonly OpenTelemetry.Trace.TraceSemanticConventions.PrefixGraphql -> string +static readonly OpenTelemetry.Trace.TraceSemanticConventions.PrefixHttp -> string +static readonly OpenTelemetry.Trace.TraceSemanticConventions.PrefixIdentity -> string +static readonly OpenTelemetry.Trace.TraceSemanticConventions.PrefixMessaging -> string +static readonly OpenTelemetry.Trace.TraceSemanticConventions.PrefixMessagingKafka -> string +static readonly OpenTelemetry.Trace.TraceSemanticConventions.PrefixMessagingRabbitmq -> string +static readonly OpenTelemetry.Trace.TraceSemanticConventions.PrefixMessagingRocketmq -> string +static readonly OpenTelemetry.Trace.TraceSemanticConventions.PrefixNetwork -> string +static readonly OpenTelemetry.Trace.TraceSemanticConventions.PrefixOpentracing -> string +static readonly OpenTelemetry.Trace.TraceSemanticConventions.PrefixPeer -> string +static readonly OpenTelemetry.Trace.TraceSemanticConventions.PrefixRpc -> string +static readonly OpenTelemetry.Trace.TraceSemanticConventions.PrefixRpcGrpc -> string +static readonly OpenTelemetry.Trace.TraceSemanticConventions.PrefixRpcJsonrpc -> string +static readonly OpenTelemetry.Trace.TraceSemanticConventions.PrefixRpcMessage -> string +static readonly OpenTelemetry.Trace.TraceSemanticConventions.PrefixThread -> string \ No newline at end of file diff --git a/src/OpenTelemetry.SemanticConventions/OpenTelemetry.SemanticConventions.csproj b/src/OpenTelemetry.SemanticConventions/OpenTelemetry.SemanticConventions.csproj new file mode 100644 index 00000000000..392f6d156c0 --- /dev/null +++ b/src/OpenTelemetry.SemanticConventions/OpenTelemetry.SemanticConventions.csproj @@ -0,0 +1,9 @@ + + + + netstandard2.0;net462 + OpenTelemetry Semantic Conventions + $(PackageTags);semantic-conventions + + + diff --git a/src/OpenTelemetry.SemanticConventions/README.md b/src/OpenTelemetry.SemanticConventions/README.md new file mode 100644 index 00000000000..fc016423c82 --- /dev/null +++ b/src/OpenTelemetry.SemanticConventions/README.md @@ -0,0 +1,34 @@ +# Semantic Conventions for OpenTelemetry .NET + +This project contains the generated code for the Semantic Conventions +defined by the OpenTelemetry specification. + +## Installation + +```shell +dotnet add package OpenTelemetry.SemanticConventions +``` + +## Generating the files + +This project uses the +[Semantic Convention Generator](https://github.com/open-telemetry/build-tools/blob/main/semantic-conventions/README.md). +The folder `scripts` at the top level of the project contains +the templates and the script file used in the process. + +To generate the code files, run: + +```shell +./scripts/semantic-conventions/generate.sh +``` + +Or, with PowerShell: + +```shell +./scripts/semantic-conventions/generate.ps1 +``` + +## References + +* [OpenTelemetry Project](https://opentelemetry.io/) +* [Build tools](https://github.com/open-telemetry/build-tools) diff --git a/src/OpenTelemetry.SemanticConventions/Resource/ResourceSemanticConventions.cs b/src/OpenTelemetry.SemanticConventions/Resource/ResourceSemanticConventions.cs new file mode 100644 index 00000000000..1da782284c0 --- /dev/null +++ b/src/OpenTelemetry.SemanticConventions/Resource/ResourceSemanticConventions.cs @@ -0,0 +1,1028 @@ +// +// Copyright The OpenTelemetry Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +// This file has been auto generated from buildscripts/semantic-conventions/templates/SemanticConventions.cs.j2 + +using System; + +namespace OpenTelemetry.Resources +{ + /// + /// Constants for semantic attribute names outlined by the OpenTelemetry specifications. + /// . + /// + /// + /// Schema and specification version: https://opentelemetry.io/schemas/v1.13.0. + /// + public static class ResourceSemanticConventions + { + /// + /// Array of brand name and version separated by a space. + /// + /// + /// This value is intended to be taken from the UA client hints API (navigator.userAgentData.brands). + /// + public const string AttributeBrowserBrands = "browser.brands"; + + /// + /// The platform on which the browser is running. + /// + /// + /// This value is intended to be taken from the UA client hints API (navigator.userAgentData.platform). If unavailable, the legacy navigator.platform API SHOULD NOT be used instead and this attribute SHOULD be left unset in order for the values to be consistent. + /// The list of possible values is defined in the W3C User-Agent Client Hints specification. Note that some (but not all) of these values can overlap with values in the os.type and os.name attributes. However, for consistency, the values in the browser.platform attribute should capture the exact value that the user agent provides. + /// + public const string AttributeBrowserPlatform = "browser.platform"; + + /// + /// Full user-agent string provided by the browser. + /// + /// + /// The user-agent value SHOULD be provided only from browsers that do not have a mechanism to retrieve brands and platform individually from the User-Agent Client Hints API. To retrieve the value, the legacy navigator.userAgent API can be used. + /// + public const string AttributeBrowserUserAgent = "browser.user_agent"; + + /// + /// Name of the cloud provider. + /// + public const string AttributeCloudProvider = "cloud.provider"; + + /// + /// The cloud account ID the resource is assigned to. + /// + public const string AttributeCloudAccountId = "cloud.account.id"; + + /// + /// The geographical region the resource is running. + /// + /// + /// Refer to your provider&#39;s docs to see the available regions, for example Alibaba Cloud regions, AWS regions, Azure regions, Google Cloud regions, or Tencent Cloud regions. + /// + public const string AttributeCloudRegion = "cloud.region"; + + /// + /// Cloud regions often have multiple, isolated locations known as zones to increase availability. Availability zone represents the zone where the resource is running. + /// + /// + /// Availability zones are called &#34;zones&#34; on Alibaba Cloud and Google Cloud. + /// + public const string AttributeCloudAvailabilityZone = "cloud.availability_zone"; + + /// + /// The cloud platform in use. + /// + /// + /// The prefix of the service SHOULD match the one specified in cloud.provider. + /// + public const string AttributeCloudPlatform = "cloud.platform"; + + /// + /// The Amazon Resource Name (ARN) of an ECS container instance. + /// + public const string AttributeAwsEcsContainerArn = "aws.ecs.container.arn"; + + /// + /// The ARN of an ECS cluster. + /// + public const string AttributeAwsEcsClusterArn = "aws.ecs.cluster.arn"; + + /// + /// The launch type for an ECS task. + /// + public const string AttributeAwsEcsLaunchtype = "aws.ecs.launchtype"; + + /// + /// The ARN of an ECS task definition. + /// + public const string AttributeAwsEcsTaskArn = "aws.ecs.task.arn"; + + /// + /// The task definition family this task definition is a member of. + /// + public const string AttributeAwsEcsTaskFamily = "aws.ecs.task.family"; + + /// + /// The revision for this task definition. + /// + public const string AttributeAwsEcsTaskRevision = "aws.ecs.task.revision"; + + /// + /// The ARN of an EKS cluster. + /// + public const string AttributeAwsEksClusterArn = "aws.eks.cluster.arn"; + + /// + /// The name(s) of the AWS log group(s) an application is writing to. + /// + /// + /// Multiple log groups must be supported for cases like multi-container applications, where a single application has sidecar containers, and each write to their own log group. + /// + public const string AttributeAwsLogGroupNames = "aws.log.group.names"; + + /// + /// The Amazon Resource Name(s) (ARN) of the AWS log group(s). + /// + /// + /// See the log group ARN format documentation. + /// + public const string AttributeAwsLogGroupArns = "aws.log.group.arns"; + + /// + /// The name(s) of the AWS log stream(s) an application is writing to. + /// + public const string AttributeAwsLogStreamNames = "aws.log.stream.names"; + + /// + /// The ARN(s) of the AWS log stream(s). + /// + /// + /// See the log stream ARN format documentation. One log group can contain several log streams, so these ARNs necessarily identify both a log group and a log stream. + /// + public const string AttributeAwsLogStreamArns = "aws.log.stream.arns"; + + /// + /// Container name used by container runtime. + /// + public const string AttributeContainerName = "container.name"; + + /// + /// Container ID. Usually a UUID, as for example used to identify Docker containers. The UUID might be abbreviated. + /// + public const string AttributeContainerId = "container.id"; + + /// + /// The container runtime managing this container. + /// + public const string AttributeContainerRuntime = "container.runtime"; + + /// + /// Name of the image the container was built on. + /// + public const string AttributeContainerImageName = "container.image.name"; + + /// + /// Container image tag. + /// + public const string AttributeContainerImageTag = "container.image.tag"; + + /// + /// Name of the deployment environment (aka deployment tier). + /// + public const string AttributeDeploymentEnvironment = "deployment.environment"; + + /// + /// A unique identifier representing the device. + /// + /// + /// The device identifier MUST only be defined using the values outlined below. This value is not an advertising identifier and MUST NOT be used as such. On iOS (Swift or Objective-C), this value MUST be equal to the vendor identifier. On Android (Java or Kotlin), this value MUST be equal to the Firebase Installation ID or a globally unique UUID which is persisted across sessions in your application. More information can be found here on best practices and exact implementation details. Caution should be taken when storing personal data or anything which can identify a user. GDPR and data protection laws may apply, ensure you do your own due diligence. + /// + public const string AttributeDeviceId = "device.id"; + + /// + /// The model identifier for the device. + /// + /// + /// It&#39;s recommended this value represents a machine readable version of the model identifier rather than the market or consumer-friendly name of the device. + /// + public const string AttributeDeviceModelIdentifier = "device.model.identifier"; + + /// + /// The marketing name for the device model. + /// + /// + /// It&#39;s recommended this value represents a human readable version of the device model rather than a machine readable alternative. + /// + public const string AttributeDeviceModelName = "device.model.name"; + + /// + /// The name of the device manufacturer. + /// + /// + /// The Android OS provides this field via Build. iOS apps SHOULD hardcode the value Apple. + /// + public const string AttributeDeviceManufacturer = "device.manufacturer"; + + /// + /// The name of the single function that this runtime instance executes. + /// + /// + /// This is the name of the function as configured/deployed on the FaaS + /// platform and is usually different from the name of the callback + /// function (which may be stored in the + /// code.namespace/code.function + /// span attributes).For some cloud providers, the above definition is ambiguous. The following + /// definition of function name MUST be used for this attribute + /// (and consequently the span name) for the listed cloud providers/products:
    + ///
  • Azure: The full name <FUNCAPP>/<FUNC>, i.e., function app name + /// followed by a forward slash followed by the function name (this form + /// can also be seen in the resource JSON for the function). + /// This means that a span attribute MUST be used, as an Azure function + /// app can host multiple functions that would usually share + /// a TracerProvider (see also the faas.id attribute)
  • + ///
. + ///
+ public const string AttributeFaasName = "faas.name"; + + /// + /// The unique ID of the single function that this runtime instance executes. + /// + /// + /// On some cloud providers, it may not be possible to determine the full ID at startup, + /// so consider setting faas.id as a span attribute instead.The exact value to use for faas.id depends on the cloud provider:
    + ///
  • AWS Lambda: The function ARN. + /// Take care not to use the &#34;invoked ARN&#34; directly but replace any + /// alias suffix + /// with the resolved function version, as the same runtime instance may be invokable with + /// multiple different aliases.
  • + ///
  • GCP: The URI of the resource
  • + ///
  • Azure: The Fully Qualified Resource ID of the invoked function, + /// not the function app, having the form + /// /subscriptions/<SUBSCIPTION_GUID>/resourceGroups/<RG>/providers/Microsoft.Web/sites/<FUNCAPP>/functions/<FUNC>. + /// This means that a span attribute MUST be used, as an Azure function app can host multiple functions that would usually share + /// a TracerProvider
  • + ///
. + ///
+ public const string AttributeFaasId = "faas.id"; + + /// + /// The immutable version of the function being executed. + /// + /// + /// Depending on the cloud provider and platform, use:
    + ///
  • AWS Lambda: The function version + /// (an integer represented as a decimal string).
  • + ///
  • Google Cloud Run: The revision + /// (i.e., the function name plus the revision suffix).
  • + ///
  • Google Cloud Functions: The value of the + /// K_REVISION environment variable.
  • + ///
  • Azure Functions: Not applicable. Do not set this attribute
  • + ///
. + ///
+ public const string AttributeFaasVersion = "faas.version"; + + /// + /// The execution environment ID as a string, that will be potentially reused for other invocations to the same function/function version. + /// + /// + ///
    + ///
  • AWS Lambda: Use the (full) log stream name
  • + ///
. + ///
+ public const string AttributeFaasInstance = "faas.instance"; + + /// + /// The amount of memory available to the serverless function in MiB. + /// + /// + /// It&#39;s recommended to set this attribute since e.g. too little memory can easily stop a Java AWS Lambda function from working correctly. On AWS Lambda, the environment variable AWS_LAMBDA_FUNCTION_MEMORY_SIZE provides this information. + /// + public const string AttributeFaasMaxMemory = "faas.max_memory"; + + /// + /// Unique host ID. For Cloud, this must be the instance_id assigned by the cloud provider. + /// + public const string AttributeHostId = "host.id"; + + /// + /// Name of the host. On Unix systems, it may contain what the hostname command returns, or the fully qualified hostname, or another name specified by the user. + /// + public const string AttributeHostName = "host.name"; + + /// + /// Type of host. For Cloud, this must be the machine type. + /// + public const string AttributeHostType = "host.type"; + + /// + /// The CPU architecture the host system is running on. + /// + public const string AttributeHostArch = "host.arch"; + + /// + /// Name of the VM image or OS install the host was instantiated from. + /// + public const string AttributeHostImageName = "host.image.name"; + + /// + /// VM image ID. For Cloud, this value is from the provider. + /// + public const string AttributeHostImageId = "host.image.id"; + + /// + /// The version string of the VM image as defined in Version Attributes. + /// + public const string AttributeHostImageVersion = "host.image.version"; + + /// + /// The name of the cluster. + /// + public const string AttributeK8sClusterName = "k8s.cluster.name"; + + /// + /// The name of the Node. + /// + public const string AttributeK8sNodeName = "k8s.node.name"; + + /// + /// The UID of the Node. + /// + public const string AttributeK8sNodeUid = "k8s.node.uid"; + + /// + /// The name of the namespace that the pod is running in. + /// + public const string AttributeK8sNamespaceName = "k8s.namespace.name"; + + /// + /// The UID of the Pod. + /// + public const string AttributeK8sPodUid = "k8s.pod.uid"; + + /// + /// The name of the Pod. + /// + public const string AttributeK8sPodName = "k8s.pod.name"; + + /// + /// The name of the Container from Pod specification, must be unique within a Pod. Container runtime usually uses different globally unique name (container.name). + /// + public const string AttributeK8sContainerName = "k8s.container.name"; + + /// + /// Number of times the container was restarted. This attribute can be used to identify a particular container (running or stopped) within a container spec. + /// + public const string AttributeK8sContainerRestartCount = "k8s.container.restart_count"; + + /// + /// The UID of the ReplicaSet. + /// + public const string AttributeK8sReplicasetUid = "k8s.replicaset.uid"; + + /// + /// The name of the ReplicaSet. + /// + public const string AttributeK8sReplicasetName = "k8s.replicaset.name"; + + /// + /// The UID of the Deployment. + /// + public const string AttributeK8sDeploymentUid = "k8s.deployment.uid"; + + /// + /// The name of the Deployment. + /// + public const string AttributeK8sDeploymentName = "k8s.deployment.name"; + + /// + /// The UID of the StatefulSet. + /// + public const string AttributeK8sStatefulsetUid = "k8s.statefulset.uid"; + + /// + /// The name of the StatefulSet. + /// + public const string AttributeK8sStatefulsetName = "k8s.statefulset.name"; + + /// + /// The UID of the DaemonSet. + /// + public const string AttributeK8sDaemonsetUid = "k8s.daemonset.uid"; + + /// + /// The name of the DaemonSet. + /// + public const string AttributeK8sDaemonsetName = "k8s.daemonset.name"; + + /// + /// The UID of the Job. + /// + public const string AttributeK8sJobUid = "k8s.job.uid"; + + /// + /// The name of the Job. + /// + public const string AttributeK8sJobName = "k8s.job.name"; + + /// + /// The UID of the CronJob. + /// + public const string AttributeK8sCronjobUid = "k8s.cronjob.uid"; + + /// + /// The name of the CronJob. + /// + public const string AttributeK8sCronjobName = "k8s.cronjob.name"; + + /// + /// The operating system type. + /// + public const string AttributeOsType = "os.type"; + + /// + /// Human readable (not intended to be parsed) OS version information, like e.g. reported by ver or lsb_release -a commands. + /// + public const string AttributeOsDescription = "os.description"; + + /// + /// Human readable operating system name. + /// + public const string AttributeOsName = "os.name"; + + /// + /// The version string of the operating system as defined in Version Attributes. + /// + public const string AttributeOsVersion = "os.version"; + + /// + /// Process identifier (PID). + /// + public const string AttributeProcessPid = "process.pid"; + + /// + /// Parent Process identifier (PID). + /// + public const string AttributeProcessParentPid = "process.parent_pid"; + + /// + /// The name of the process executable. On Linux based systems, can be set to the Name in proc/[pid]/status. On Windows, can be set to the base name of GetProcessImageFileNameW. + /// + public const string AttributeProcessExecutableName = "process.executable.name"; + + /// + /// The full path to the process executable. On Linux based systems, can be set to the target of proc/[pid]/exe. On Windows, can be set to the result of GetProcessImageFileNameW. + /// + public const string AttributeProcessExecutablePath = "process.executable.path"; + + /// + /// The command used to launch the process (i.e. the command name). On Linux based systems, can be set to the zeroth string in proc/[pid]/cmdline. On Windows, can be set to the first parameter extracted from GetCommandLineW. + /// + public const string AttributeProcessCommand = "process.command"; + + /// + /// The full command used to launch the process as a single string representing the full command. On Windows, can be set to the result of GetCommandLineW. Do not set this if you have to assemble it just for monitoring; use process.command_args instead. + /// + public const string AttributeProcessCommandLine = "process.command_line"; + + /// + /// All the command arguments (including the command/executable itself) as received by the process. On Linux-based systems (and some other Unixoid systems supporting procfs), can be set according to the list of null-delimited strings extracted from proc/[pid]/cmdline. For libc-based executables, this would be the full argv vector passed to main. + /// + public const string AttributeProcessCommandArgs = "process.command_args"; + + /// + /// The username of the user that owns the process. + /// + public const string AttributeProcessOwner = "process.owner"; + + /// + /// The name of the runtime of this process. For compiled native binaries, this SHOULD be the name of the compiler. + /// + public const string AttributeProcessRuntimeName = "process.runtime.name"; + + /// + /// The version of the runtime of this process, as returned by the runtime without modification. + /// + public const string AttributeProcessRuntimeVersion = "process.runtime.version"; + + /// + /// An additional description about the runtime of the process, for example a specific vendor customization of the runtime environment. + /// + public const string AttributeProcessRuntimeDescription = "process.runtime.description"; + + /// + /// Logical name of the service. + /// + /// + /// MUST be the same for all instances of horizontally scaled services. If the value was not specified, SDKs MUST fallback to unknown_service: concatenated with process.executable.name, e.g. unknown_service:bash. If process.executable.name is not available, the value MUST be set to unknown_service. + /// + public const string AttributeServiceName = "service.name"; + + /// + /// A namespace for service.name. + /// + /// + /// A string value having a meaning that helps to distinguish a group of services, for example the team name that owns a group of services. service.name is expected to be unique within the same namespace. If service.namespace is not specified in the Resource then service.name is expected to be unique for all services that have no explicit namespace defined (so the empty/unspecified namespace is simply one more valid namespace). Zero-length namespace string is assumed equal to unspecified namespace. + /// + public const string AttributeServiceNamespace = "service.namespace"; + + /// + /// The string ID of the service instance. + /// + /// + /// MUST be unique for each instance of the same service.namespace,service.name pair (in other words service.namespace,service.name,service.instance.id triplet MUST be globally unique). The ID helps to distinguish instances of the same service that exist at the same time (e.g. instances of a horizontally scaled service). It is preferable for the ID to be persistent and stay the same for the lifetime of the service instance, however it is acceptable that the ID is ephemeral and changes during important lifetime events for the service (e.g. service restarts). If the service has no inherent unique ID that can be used as the value of this attribute it is recommended to generate a random Version 1 or Version 4 RFC 4122 UUID (services aiming for reproducible UUIDs may also use Version 5, see RFC 4122 for more recommendations). + /// + public const string AttributeServiceInstanceId = "service.instance.id"; + + /// + /// The version string of the service API or implementation. + /// + public const string AttributeServiceVersion = "service.version"; + + /// + /// The name of the telemetry SDK as defined above. + /// + public const string AttributeTelemetrySdkName = "telemetry.sdk.name"; + + /// + /// The language of the telemetry SDK. + /// + public const string AttributeTelemetrySdkLanguage = "telemetry.sdk.language"; + + /// + /// The version string of the telemetry SDK. + /// + public const string AttributeTelemetrySdkVersion = "telemetry.sdk.version"; + + /// + /// The version string of the auto instrumentation agent, if used. + /// + public const string AttributeTelemetryAutoVersion = "telemetry.auto.version"; + + /// + /// The name of the web engine. + /// + public const string AttributeWebengineName = "webengine.name"; + + /// + /// The version of the web engine. + /// + public const string AttributeWebengineVersion = "webengine.version"; + + /// + /// Additional description of the web engine (e.g. detailed version and edition information). + /// + public const string AttributeWebengineDescription = "webengine.description"; + + /// + /// Prefix for 'browser'. + /// + public static readonly string PrefixBrowser = "browser"; + + /// + /// Prefix for 'cloud'. + /// + public static readonly string PrefixCloud = "cloud"; + + /// + /// Prefix for 'aws.ecs'. + /// + public static readonly string PrefixAwsEcs = "aws.ecs"; + + /// + /// Prefix for 'aws.eks'. + /// + public static readonly string PrefixAwsEks = "aws.eks"; + + /// + /// Prefix for 'aws.log'. + /// + public static readonly string PrefixAwsLog = "aws.log"; + + /// + /// Prefix for 'container'. + /// + public static readonly string PrefixContainer = "container"; + + /// + /// Prefix for 'deployment'. + /// + public static readonly string PrefixDeployment = "deployment"; + + /// + /// Prefix for 'device'. + /// + public static readonly string PrefixDevice = "device"; + + /// + /// Prefix for 'faas_resource'. + /// + public static readonly string PrefixFaasResource = "faas"; + + /// + /// Prefix for 'host'. + /// + public static readonly string PrefixHost = "host"; + + /// + /// Prefix for 'k8s.cluster'. + /// + public static readonly string PrefixK8sCluster = "k8s.cluster"; + + /// + /// Prefix for 'k8s.node'. + /// + public static readonly string PrefixK8sNode = "k8s.node"; + + /// + /// Prefix for 'k8s.namespace'. + /// + public static readonly string PrefixK8sNamespace = "k8s.namespace"; + + /// + /// Prefix for 'k8s.pod'. + /// + public static readonly string PrefixK8sPod = "k8s.pod"; + + /// + /// Prefix for 'k8s.container'. + /// + public static readonly string PrefixK8sContainer = "k8s.container"; + + /// + /// Prefix for 'k8s.replicaset'. + /// + public static readonly string PrefixK8sReplicaset = "k8s.replicaset"; + + /// + /// Prefix for 'k8s.deployment'. + /// + public static readonly string PrefixK8sDeployment = "k8s.deployment"; + + /// + /// Prefix for 'k8s.statefulset'. + /// + public static readonly string PrefixK8sStatefulset = "k8s.statefulset"; + + /// + /// Prefix for 'k8s.daemonset'. + /// + public static readonly string PrefixK8sDaemonset = "k8s.daemonset"; + + /// + /// Prefix for 'k8s.job'. + /// + public static readonly string PrefixK8sJob = "k8s.job"; + + /// + /// Prefix for 'k8s.cronjob'. + /// + public static readonly string PrefixK8sCronjob = "k8s.cronjob"; + + /// + /// Prefix for 'os'. + /// + public static readonly string PrefixOs = "os"; + + /// + /// Prefix for 'process'. + /// + public static readonly string PrefixProcess = "process"; + + /// + /// Prefix for 'process.runtime'. + /// + public static readonly string PrefixProcessRuntime = "process.runtime"; + + /// + /// Prefix for 'service'. + /// + public static readonly string PrefixService = "service"; + + /// + /// Prefix for 'telemetry'. + /// + public static readonly string PrefixTelemetry = "telemetry"; + + /// + /// Prefix for 'webengine_resource'. + /// + public static readonly string PrefixWebengineResource = "webengine"; + + /// + /// Name of the cloud provider. + /// + public static class CloudProviderValues + { + /// + /// Alibaba Cloud. + /// + public const string AlibabaCloud = "alibaba_cloud"; + + /// + /// Amazon Web Services. + /// + public const string Aws = "aws"; + + /// + /// Microsoft Azure. + /// + public const string Azure = "azure"; + + /// + /// Google Cloud Platform. + /// + public const string Gcp = "gcp"; + + /// + /// Tencent Cloud. + /// + public const string TencentCloud = "tencent_cloud"; + } + + /// + /// The cloud platform in use. + /// + public static class CloudPlatformValues + { + /// + /// Alibaba Cloud Elastic Compute Service. + /// + public const string AlibabaCloudEcs = "alibaba_cloud_ecs"; + + /// + /// Alibaba Cloud Function Compute. + /// + public const string AlibabaCloudFc = "alibaba_cloud_fc"; + + /// + /// AWS Elastic Compute Cloud. + /// + public const string AwsEc2 = "aws_ec2"; + + /// + /// AWS Elastic Container Service. + /// + public const string AwsEcs = "aws_ecs"; + + /// + /// AWS Elastic Kubernetes Service. + /// + public const string AwsEks = "aws_eks"; + + /// + /// AWS Lambda. + /// + public const string AwsLambda = "aws_lambda"; + + /// + /// AWS Elastic Beanstalk. + /// + public const string AwsElasticBeanstalk = "aws_elastic_beanstalk"; + + /// + /// AWS App Runner. + /// + public const string AwsAppRunner = "aws_app_runner"; + + /// + /// Azure Virtual Machines. + /// + public const string AzureVm = "azure_vm"; + + /// + /// Azure Container Instances. + /// + public const string AzureContainerInstances = "azure_container_instances"; + + /// + /// Azure Kubernetes Service. + /// + public const string AzureAks = "azure_aks"; + + /// + /// Azure Functions. + /// + public const string AzureFunctions = "azure_functions"; + + /// + /// Azure App Service. + /// + public const string AzureAppService = "azure_app_service"; + + /// + /// Google Cloud Compute Engine (GCE). + /// + public const string GcpComputeEngine = "gcp_compute_engine"; + + /// + /// Google Cloud Run. + /// + public const string GcpCloudRun = "gcp_cloud_run"; + + /// + /// Google Cloud Kubernetes Engine (GKE). + /// + public const string GcpKubernetesEngine = "gcp_kubernetes_engine"; + + /// + /// Google Cloud Functions (GCF). + /// + public const string GcpCloudFunctions = "gcp_cloud_functions"; + + /// + /// Google Cloud App Engine (GAE). + /// + public const string GcpAppEngine = "gcp_app_engine"; + + /// + /// Tencent Cloud Cloud Virtual Machine (CVM). + /// + public const string TencentCloudCvm = "tencent_cloud_cvm"; + + /// + /// Tencent Cloud Elastic Kubernetes Service (EKS). + /// + public const string TencentCloudEks = "tencent_cloud_eks"; + + /// + /// Tencent Cloud Serverless Cloud Function (SCF). + /// + public const string TencentCloudScf = "tencent_cloud_scf"; + } + + /// + /// The launch type for an ECS task. + /// + public static class AwsEcsLaunchtypeValues + { + /// + /// ec2. + /// + public const string Ec2 = "ec2"; + + /// + /// fargate. + /// + public const string Fargate = "fargate"; + } + + /// + /// The CPU architecture the host system is running on. + /// + public static class HostArchValues + { + /// + /// AMD64. + /// + public const string Amd64 = "amd64"; + + /// + /// ARM32. + /// + public const string Arm32 = "arm32"; + + /// + /// ARM64. + /// + public const string Arm64 = "arm64"; + + /// + /// Itanium. + /// + public const string Ia64 = "ia64"; + + /// + /// 32-bit PowerPC. + /// + public const string Ppc32 = "ppc32"; + + /// + /// 64-bit PowerPC. + /// + public const string Ppc64 = "ppc64"; + + /// + /// IBM z/Architecture. + /// + public const string S390x = "s390x"; + + /// + /// 32-bit x86. + /// + public const string X86 = "x86"; + } + + /// + /// The operating system type. + /// + public static class OsTypeValues + { + /// + /// Microsoft Windows. + /// + public const string Windows = "windows"; + + /// + /// Linux. + /// + public const string Linux = "linux"; + + /// + /// Apple Darwin. + /// + public const string Darwin = "darwin"; + + /// + /// FreeBSD. + /// + public const string Freebsd = "freebsd"; + + /// + /// NetBSD. + /// + public const string Netbsd = "netbsd"; + + /// + /// OpenBSD. + /// + public const string Openbsd = "openbsd"; + + /// + /// DragonFly BSD. + /// + public const string Dragonflybsd = "dragonflybsd"; + + /// + /// HP-UX (Hewlett Packard Unix). + /// + public const string Hpux = "hpux"; + + /// + /// AIX (Advanced Interactive eXecutive). + /// + public const string Aix = "aix"; + + /// + /// SunOS, Oracle Solaris. + /// + public const string Solaris = "solaris"; + + /// + /// IBM z/OS. + /// + public const string ZOs = "z_os"; + } + + /// + /// The language of the telemetry SDK. + /// + public static class TelemetrySdkLanguageValues + { + /// + /// cpp. + /// + public const string Cpp = "cpp"; + + /// + /// dotnet. + /// + public const string Dotnet = "dotnet"; + + /// + /// erlang. + /// + public const string Erlang = "erlang"; + + /// + /// go. + /// + public const string Go = "go"; + + /// + /// java. + /// + public const string Java = "java"; + + /// + /// nodejs. + /// + public const string Nodejs = "nodejs"; + + /// + /// php. + /// + public const string Php = "php"; + + /// + /// python. + /// + public const string Python = "python"; + + /// + /// ruby. + /// + public const string Ruby = "ruby"; + + /// + /// webjs. + /// + public const string Webjs = "webjs"; + + /// + /// swift. + /// + public const string Swift = "swift"; + } + } +} diff --git a/src/OpenTelemetry.SemanticConventions/Trace/TraceSemanticConventions.cs b/src/OpenTelemetry.SemanticConventions/Trace/TraceSemanticConventions.cs new file mode 100644 index 00000000000..10fe6322f62 --- /dev/null +++ b/src/OpenTelemetry.SemanticConventions/Trace/TraceSemanticConventions.cs @@ -0,0 +1,1878 @@ +// +// Copyright The OpenTelemetry Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +// This file has been auto generated from buildscripts/semantic-conventions/templates/SemanticConventions.cs.j2 + +using System; + +namespace OpenTelemetry.Trace +{ + /// + /// Constants for semantic attribute names outlined by the OpenTelemetry specifications. + /// . + /// + /// + /// Schema and specification version: https://opentelemetry.io/schemas/v1.13.0. + /// + public static class TraceSemanticConventions + { + /// + /// Attribute for db.instance. + /// + public const string AttributeDbInstance = "db.instance"; + + /// + /// The full invoked ARN as provided on the Context passed to the function (Lambda-Runtime-Invoked-Function-Arn header on the /runtime/invocation/next applicable). + /// + /// + /// This may be different from faas.id if an alias is involved. + /// + public const string AttributeAwsLambdaInvokedArn = "aws.lambda.invoked_arn"; + + /// + /// The event_id uniquely identifies the event. + /// + public const string AttributeCloudeventsEventId = "cloudevents.event_id"; + + /// + /// The source identifies the context in which an event happened. + /// + public const string AttributeCloudeventsEventSource = "cloudevents.event_source"; + + /// + /// The version of the CloudEvents specification which the event uses. + /// + public const string AttributeCloudeventsEventSpecVersion = "cloudevents.event_spec_version"; + + /// + /// The event_type contains a value describing the type of event related to the originating occurrence. + /// + public const string AttributeCloudeventsEventType = "cloudevents.event_type"; + + /// + /// The subject of the event in the context of the event producer (identified by source). + /// + public const string AttributeCloudeventsEventSubject = "cloudevents.event_subject"; + + /// + /// Parent-child Reference type. + /// + /// + /// The causal relationship between a child Span and a parent Span. + /// + public const string AttributeOpentracingRefType = "opentracing.ref_type"; + + /// + /// An identifier for the database management system (DBMS) product being used. See below for a list of well-known identifiers. + /// + public const string AttributeDbSystem = "db.system"; + + /// + /// The connection string used to connect to the database. It is recommended to remove embedded credentials. + /// + public const string AttributeDbConnectionString = "db.connection_string"; + + /// + /// Username for accessing the database. + /// + public const string AttributeDbUser = "db.user"; + + /// + /// The fully-qualified class name of the Java Database Connectivity (JDBC) driver used to connect. + /// + public const string AttributeDbJdbcDriverClassname = "db.jdbc.driver_classname"; + + /// + /// This attribute is used to report the name of the database being accessed. For commands that switch the database, this should be set to the target database (even if the command fails). + /// + /// + /// In some SQL databases, the database name to be used is called &#34;schema name&#34;. In case there are multiple layers that could be considered for database name (e.g. Oracle instance name and schema name), the database name to be used is the more specific layer (e.g. Oracle schema name). + /// + public const string AttributeDbName = "db.name"; + + /// + /// The database statement being executed. + /// + /// + /// The value may be sanitized to exclude sensitive information. + /// + public const string AttributeDbStatement = "db.statement"; + + /// + /// The name of the operation being executed, e.g. the MongoDB command name such as findAndModify, or the SQL keyword. + /// + /// + /// When setting this to an SQL keyword, it is not recommended to attempt any client-side parsing of db.statement just to get this property, but it should be set if the operation name is provided by the library being instrumented. If the SQL statement has an ambiguous operation, or performs more than one operation, this value may be omitted. + /// + public const string AttributeDbOperation = "db.operation"; + + /// + /// The Microsoft SQL Server instance name connecting to. This name is used to determine the port of a named instance. + /// + /// + /// If setting a db.mssql.instance_name, net.peer.port is no longer required (but still recommended if non-standard). + /// + public const string AttributeDbMssqlInstanceName = "db.mssql.instance_name"; + + /// + /// The fetch size used for paging, i.e. how many rows will be returned at once. + /// + public const string AttributeDbCassandraPageSize = "db.cassandra.page_size"; + + /// + /// The consistency level of the query. Based on consistency values from CQL. + /// + public const string AttributeDbCassandraConsistencyLevel = "db.cassandra.consistency_level"; + + /// + /// The name of the primary table that the operation is acting upon, including the keyspace name (if applicable). + /// + /// + /// This mirrors the db.sql.table attribute but references cassandra rather than sql. It is not recommended to attempt any client-side parsing of db.statement just to get this property, but it should be set if it is provided by the library being instrumented. If the operation is acting upon an anonymous table, or more than one table, this value MUST NOT be set. + /// + public const string AttributeDbCassandraTable = "db.cassandra.table"; + + /// + /// Whether or not the query is idempotent. + /// + public const string AttributeDbCassandraIdempotence = "db.cassandra.idempotence"; + + /// + /// The number of times a query was speculatively executed. Not set or 0 if the query was not executed speculatively. + /// + public const string AttributeDbCassandraSpeculativeExecutionCount = "db.cassandra.speculative_execution_count"; + + /// + /// The ID of the coordinating node for a query. + /// + public const string AttributeDbCassandraCoordinatorId = "db.cassandra.coordinator.id"; + + /// + /// The data center of the coordinating node for a query. + /// + public const string AttributeDbCassandraCoordinatorDc = "db.cassandra.coordinator.dc"; + + /// + /// The index of the database being accessed as used in the SELECT command, provided as an integer. To be used instead of the generic db.name attribute. + /// + public const string AttributeDbRedisDatabaseIndex = "db.redis.database_index"; + + /// + /// The collection being accessed within the database stated in db.name. + /// + public const string AttributeDbMongodbCollection = "db.mongodb.collection"; + + /// + /// The name of the primary table that the operation is acting upon, including the database name (if applicable). + /// + /// + /// It is not recommended to attempt any client-side parsing of db.statement just to get this property, but it should be set if it is provided by the library being instrumented. If the operation is acting upon an anonymous table, or more than one table, this value MUST NOT be set. + /// + public const string AttributeDbSqlTable = "db.sql.table"; + + /// + /// The type of the exception (its fully-qualified class name, if applicable). The dynamic type of the exception should be preferred over the static type in languages that support it. + /// + public const string AttributeExceptionType = "exception.type"; + + /// + /// The exception message. + /// + public const string AttributeExceptionMessage = "exception.message"; + + /// + /// A stacktrace as a string in the natural representation for the language runtime. The representation is to be determined and documented by each language SIG. + /// + public const string AttributeExceptionStacktrace = "exception.stacktrace"; + + /// + /// SHOULD be set to true if the exception event is recorded at a point where it is known that the exception is escaping the scope of the span. + /// + /// + /// An exception is considered to have escaped (or left) the scope of a span, + /// if that span is ended while the exception is still logically &#34;in flight&#34;. + /// This may be actually &#34;in flight&#34; in some languages (e.g. if the exception + /// is passed to a Context manager&#39;s __exit__ method in Python) but will + /// usually be caught at the point of recording the exception in most languages.It is usually not possible to determine at the point where an exception is thrown + /// whether it will escape the scope of a span. + /// However, it is trivial to know that an exception + /// will escape, if one checks for an active exception just before ending the span, + /// as done in the example above.It follows that an exception may still escape the scope of the span + /// even if the exception.escaped attribute was not set or set to false, + /// since the event might have been recorded at a time where it was not + /// clear whether the exception will escape. + /// + public const string AttributeExceptionEscaped = "exception.escaped"; + + /// + /// Type of the trigger which caused this function execution. + /// + /// + /// For the server/consumer span on the incoming side, + /// faas.trigger MUST be set.Clients invoking FaaS instances usually cannot set faas.trigger, + /// since they would typically need to look in the payload to determine + /// the event type. If clients set it, it should be the same as the + /// trigger that corresponding incoming would have (i.e., this has + /// nothing to do with the underlying transport used to make the API + /// call to invoke the lambda, which is often HTTP). + /// + public const string AttributeFaasTrigger = "faas.trigger"; + + /// + /// The execution ID of the current function execution. + /// + public const string AttributeFaasExecution = "faas.execution"; + + /// + /// The name of the source on which the triggering operation was performed. For example, in Cloud Storage or S3 corresponds to the bucket name, and in Cosmos DB to the database name. + /// + public const string AttributeFaasDocumentCollection = "faas.document.collection"; + + /// + /// Describes the type of the operation that was performed on the data. + /// + public const string AttributeFaasDocumentOperation = "faas.document.operation"; + + /// + /// A string containing the time when the data was accessed in the ISO 8601 format expressed in UTC. + /// + public const string AttributeFaasDocumentTime = "faas.document.time"; + + /// + /// The document name/table subjected to the operation. For example, in Cloud Storage or S3 is the name of the file, and in Cosmos DB the table name. + /// + public const string AttributeFaasDocumentName = "faas.document.name"; + + /// + /// A string containing the function invocation time in the ISO 8601 format expressed in UTC. + /// + public const string AttributeFaasTime = "faas.time"; + + /// + /// A string containing the schedule period as Cron Expression. + /// + public const string AttributeFaasCron = "faas.cron"; + + /// + /// A boolean that is true if the serverless function is executed for the first time (aka cold-start). + /// + public const string AttributeFaasColdstart = "faas.coldstart"; + + /// + /// The name of the invoked function. + /// + /// + /// SHOULD be equal to the faas.name resource attribute of the invoked function. + /// + public const string AttributeFaasInvokedName = "faas.invoked_name"; + + /// + /// The cloud provider of the invoked function. + /// + /// + /// SHOULD be equal to the cloud.provider resource attribute of the invoked function. + /// + public const string AttributeFaasInvokedProvider = "faas.invoked_provider"; + + /// + /// The cloud region of the invoked function. + /// + /// + /// SHOULD be equal to the cloud.region resource attribute of the invoked function. + /// + public const string AttributeFaasInvokedRegion = "faas.invoked_region"; + + /// + /// Transport protocol used. See note below. + /// + public const string AttributeNetTransport = "net.transport"; + + /// + /// Application layer protocol used. The value SHOULD be normalized to lowercase. + /// + public const string AttributeNetAppProtocolName = "net.app.protocol.name"; + + /// + /// Version of the application layer protocol used. See note below. + /// + /// + /// net.app.protocol.version refers to the version of the protocol used and might be different from the protocol client&#39;s version. If the HTTP client used has a version of 0.27.2, but sends HTTP version 1.1, this attribute should be set to 1.1. + /// + public const string AttributeNetAppProtocolVersion = "net.app.protocol.version"; + + /// + /// Remote socket peer name. + /// + public const string AttributeNetSockPeerName = "net.sock.peer.name"; + + /// + /// Remote socket peer address: IPv4 or IPv6 for internet protocols, path for local communication, etc. + /// + public const string AttributeNetSockPeerAddr = "net.sock.peer.addr"; + + /// + /// Remote socket peer port. + /// + public const string AttributeNetSockPeerPort = "net.sock.peer.port"; + + /// + /// Protocol address family which is used for communication. + /// + public const string AttributeNetSockFamily = "net.sock.family"; + + /// + /// Logical remote hostname, see note below. + /// + /// + /// net.peer.name SHOULD NOT be set if capturing it would require an extra DNS lookup. + /// + public const string AttributeNetPeerName = "net.peer.name"; + + /// + /// Logical remote port number. + /// + public const string AttributeNetPeerPort = "net.peer.port"; + + /// + /// Logical local hostname or similar, see note below. + /// + public const string AttributeNetHostName = "net.host.name"; + + /// + /// Logical local port number, preferably the one that the peer used to connect. + /// + public const string AttributeNetHostPort = "net.host.port"; + + /// + /// Local socket address. Useful in case of a multi-IP host. + /// + public const string AttributeNetSockHostAddr = "net.sock.host.addr"; + + /// + /// Local socket port number. + /// + public const string AttributeNetSockHostPort = "net.sock.host.port"; + + /// + /// The internet connection type currently being used by the host. + /// + public const string AttributeNetHostConnectionType = "net.host.connection.type"; + + /// + /// This describes more details regarding the connection.type. It may be the type of cell technology connection, but it could be used for describing details about a wifi connection. + /// + public const string AttributeNetHostConnectionSubtype = "net.host.connection.subtype"; + + /// + /// The name of the mobile carrier. + /// + public const string AttributeNetHostCarrierName = "net.host.carrier.name"; + + /// + /// The mobile carrier country code. + /// + public const string AttributeNetHostCarrierMcc = "net.host.carrier.mcc"; + + /// + /// The mobile carrier network code. + /// + public const string AttributeNetHostCarrierMnc = "net.host.carrier.mnc"; + + /// + /// The ISO 3166-1 alpha-2 2-character country code associated with the mobile carrier network. + /// + public const string AttributeNetHostCarrierIcc = "net.host.carrier.icc"; + + /// + /// The service.name of the remote service. SHOULD be equal to the actual service.name resource attribute of the remote service if any. + /// + public const string AttributePeerService = "peer.service"; + + /// + /// Username or client_id extracted from the access token or Authorization header in the inbound request from outside the system. + /// + public const string AttributeEnduserId = "enduser.id"; + + /// + /// Actual/assumed role the client is making the request under extracted from token or application security context. + /// + public const string AttributeEnduserRole = "enduser.role"; + + /// + /// Scopes or granted authorities the client currently possesses extracted from token or application security context. The value would come from the scope associated with an OAuth 2.0 Access Token or an attribute value in a SAML 2.0 Assertion. + /// + public const string AttributeEnduserScope = "enduser.scope"; + + /// + /// Current "managed" thread ID (as opposed to OS thread ID). + /// + public const string AttributeThreadId = "thread.id"; + + /// + /// Current thread name. + /// + public const string AttributeThreadName = "thread.name"; + + /// + /// The method or function name, or equivalent (usually rightmost part of the code unit's name). + /// + public const string AttributeCodeFunction = "code.function"; + + /// + /// The "namespace" within which code.function is defined. Usually the qualified class or module name, such that code.namespace + some separator + code.function form a unique identifier for the code unit. + /// + public const string AttributeCodeNamespace = "code.namespace"; + + /// + /// The source code file name that identifies the code unit as uniquely as possible (preferably an absolute file path). + /// + public const string AttributeCodeFilepath = "code.filepath"; + + /// + /// The line number in code.filepath best representing the operation. It SHOULD point within the code unit named in code.function. + /// + public const string AttributeCodeLineno = "code.lineno"; + + /// + /// HTTP request method. + /// + public const string AttributeHttpMethod = "http.method"; + + /// + /// HTTP response status code. + /// + public const string AttributeHttpStatusCode = "http.status_code"; + + /// + /// Kind of HTTP protocol used. + /// + /// + /// If net.transport is not specified, it can be assumed to be IP.TCP except if http.flavor is QUIC, in which case IP.UDP is assumed. + /// + public const string AttributeHttpFlavor = "http.flavor"; + + /// + /// Value of the HTTP User-Agent header sent by the client. + /// + public const string AttributeHttpUserAgent = "http.user_agent"; + + /// + /// The size of the request payload body in bytes. This is the number of bytes transferred excluding headers and is often, but not always, present as the Content-Length header. For requests using transport encoding, this should be the compressed size. + /// + public const string AttributeHttpRequestContentLength = "http.request_content_length"; + + /// + /// The size of the response payload body in bytes. This is the number of bytes transferred excluding headers and is often, but not always, present as the Content-Length header. For requests using transport encoding, this should be the compressed size. + /// + public const string AttributeHttpResponseContentLength = "http.response_content_length"; + + /// + /// Full HTTP request URL in the form scheme://host[:port]/path?query[#fragment]. Usually the fragment is not transmitted over HTTP, but if it is known, it should be included nevertheless. + /// + /// + /// http.url MUST NOT contain credentials passed via URL in form of https://username:password@www.example.com/. In such case the attribute&#39;s value should be https://www.example.com/. + /// + public const string AttributeHttpUrl = "http.url"; + + /// + /// The ordinal number of request re-sending attempt. + /// + public const string AttributeHttpRetryCount = "http.retry_count"; + + /// + /// The URI scheme identifying the used protocol. + /// + public const string AttributeHttpScheme = "http.scheme"; + + /// + /// The full request target as passed in a HTTP request line or equivalent. + /// + public const string AttributeHttpTarget = "http.target"; + + /// + /// The matched route (path template in the format used by the respective server framework). See note below. + /// + /// + /// &#39;http.route&#39; MUST NOT be populated when this is not supported by the HTTP server framework as the route attribute should have low-cardinality and the URI path can NOT substitute it. + /// + public const string AttributeHttpRoute = "http.route"; + + /// + /// The IP address of the original client behind all proxies, if known (e.g. from X-Forwarded-For). + /// + /// + /// This is not necessarily the same as net.sock.peer.addr, which would + /// identify the network-level peer, which may be a proxy.This attribute should be set when a source of information different + /// from the one used for net.sock.peer.addr, is available even if that other + /// source just confirms the same value as net.sock.peer.addr. + /// Rationale: For net.sock.peer.addr, one typically does not know if it + /// comes from a proxy, reverse proxy, or the actual client. Setting + /// http.client_ip when it&#39;s the same as net.sock.peer.addr means that + /// one is at least somewhat confident that the address is not that of + /// the closest proxy. + /// + public const string AttributeHttpClientIp = "http.client_ip"; + + /// + /// The keys in the RequestItems object field. + /// + public const string AttributeAwsDynamodbTableNames = "aws.dynamodb.table_names"; + + /// + /// The JSON-serialized value of each item in the ConsumedCapacity response field. + /// + public const string AttributeAwsDynamodbConsumedCapacity = "aws.dynamodb.consumed_capacity"; + + /// + /// The JSON-serialized value of the ItemCollectionMetrics response field. + /// + public const string AttributeAwsDynamodbItemCollectionMetrics = "aws.dynamodb.item_collection_metrics"; + + /// + /// The value of the ProvisionedThroughput.ReadCapacityUnits request parameter. + /// + public const string AttributeAwsDynamodbProvisionedReadCapacity = "aws.dynamodb.provisioned_read_capacity"; + + /// + /// The value of the ProvisionedThroughput.WriteCapacityUnits request parameter. + /// + public const string AttributeAwsDynamodbProvisionedWriteCapacity = "aws.dynamodb.provisioned_write_capacity"; + + /// + /// The value of the ConsistentRead request parameter. + /// + public const string AttributeAwsDynamodbConsistentRead = "aws.dynamodb.consistent_read"; + + /// + /// The value of the ProjectionExpression request parameter. + /// + public const string AttributeAwsDynamodbProjection = "aws.dynamodb.projection"; + + /// + /// The value of the Limit request parameter. + /// + public const string AttributeAwsDynamodbLimit = "aws.dynamodb.limit"; + + /// + /// The value of the AttributesToGet request parameter. + /// + public const string AttributeAwsDynamodbAttributesToGet = "aws.dynamodb.attributes_to_get"; + + /// + /// The value of the IndexName request parameter. + /// + public const string AttributeAwsDynamodbIndexName = "aws.dynamodb.index_name"; + + /// + /// The value of the Select request parameter. + /// + public const string AttributeAwsDynamodbSelect = "aws.dynamodb.select"; + + /// + /// The JSON-serialized value of each item of the GlobalSecondaryIndexes request field. + /// + public const string AttributeAwsDynamodbGlobalSecondaryIndexes = "aws.dynamodb.global_secondary_indexes"; + + /// + /// The JSON-serialized value of each item of the LocalSecondaryIndexes request field. + /// + public const string AttributeAwsDynamodbLocalSecondaryIndexes = "aws.dynamodb.local_secondary_indexes"; + + /// + /// The value of the ExclusiveStartTableName request parameter. + /// + public const string AttributeAwsDynamodbExclusiveStartTable = "aws.dynamodb.exclusive_start_table"; + + /// + /// The the number of items in the TableNames response parameter. + /// + public const string AttributeAwsDynamodbTableCount = "aws.dynamodb.table_count"; + + /// + /// The value of the ScanIndexForward request parameter. + /// + public const string AttributeAwsDynamodbScanForward = "aws.dynamodb.scan_forward"; + + /// + /// The value of the Segment request parameter. + /// + public const string AttributeAwsDynamodbSegment = "aws.dynamodb.segment"; + + /// + /// The value of the TotalSegments request parameter. + /// + public const string AttributeAwsDynamodbTotalSegments = "aws.dynamodb.total_segments"; + + /// + /// The value of the Count response parameter. + /// + public const string AttributeAwsDynamodbCount = "aws.dynamodb.count"; + + /// + /// The value of the ScannedCount response parameter. + /// + public const string AttributeAwsDynamodbScannedCount = "aws.dynamodb.scanned_count"; + + /// + /// The JSON-serialized value of each item in the AttributeDefinitions request field. + /// + public const string AttributeAwsDynamodbAttributeDefinitions = "aws.dynamodb.attribute_definitions"; + + /// + /// The JSON-serialized value of each item in the the GlobalSecondaryIndexUpdates request field. + /// + public const string AttributeAwsDynamodbGlobalSecondaryIndexUpdates = "aws.dynamodb.global_secondary_index_updates"; + + /// + /// The name of the operation being executed. + /// + public const string AttributeGraphqlOperationName = "graphql.operation.name"; + + /// + /// The type of the operation being executed. + /// + public const string AttributeGraphqlOperationType = "graphql.operation.type"; + + /// + /// The GraphQL document being executed. + /// + /// + /// The value may be sanitized to exclude sensitive information. + /// + public const string AttributeGraphqlDocument = "graphql.document"; + + /// + /// A string identifying the messaging system. + /// + public const string AttributeMessagingSystem = "messaging.system"; + + /// + /// The message destination name. This might be equal to the span name but is required nevertheless. + /// + public const string AttributeMessagingDestination = "messaging.destination"; + + /// + /// The kind of message destination. + /// + public const string AttributeMessagingDestinationKind = "messaging.destination_kind"; + + /// + /// A boolean that is true if the message destination is temporary. + /// + public const string AttributeMessagingTempDestination = "messaging.temp_destination"; + + /// + /// The name of the transport protocol. + /// + public const string AttributeMessagingProtocol = "messaging.protocol"; + + /// + /// The version of the transport protocol. + /// + public const string AttributeMessagingProtocolVersion = "messaging.protocol_version"; + + /// + /// Connection string. + /// + public const string AttributeMessagingUrl = "messaging.url"; + + /// + /// A value used by the messaging system as an identifier for the message, represented as a string. + /// + public const string AttributeMessagingMessageId = "messaging.message_id"; + + /// + /// The conversation ID identifying the conversation to which the message belongs, represented as a string. Sometimes called "Correlation ID". + /// + public const string AttributeMessagingConversationId = "messaging.conversation_id"; + + /// + /// The (uncompressed) size of the message payload in bytes. Also use this attribute if it is unknown whether the compressed or uncompressed payload size is reported. + /// + public const string AttributeMessagingMessagePayloadSizeBytes = "messaging.message_payload_size_bytes"; + + /// + /// The compressed size of the message payload in bytes. + /// + public const string AttributeMessagingMessagePayloadCompressedSizeBytes = "messaging.message_payload_compressed_size_bytes"; + + /// + /// A string identifying the kind of message consumption as defined in the Operation names section above. If the operation is "send", this attribute MUST NOT be set, since the operation can be inferred from the span kind in that case. + /// + public const string AttributeMessagingOperation = "messaging.operation"; + + /// + /// The identifier for the consumer receiving a message. For Kafka, set it to {messaging.kafka.consumer_group} - {messaging.kafka.client_id}, if both are present, or only messaging.kafka.consumer_group. For brokers, such as RabbitMQ and Artemis, set it to the client_id of the client consuming the message. + /// + public const string AttributeMessagingConsumerId = "messaging.consumer_id"; + + /// + /// RabbitMQ message routing key. + /// + public const string AttributeMessagingRabbitmqRoutingKey = "messaging.rabbitmq.routing_key"; + + /// + /// Message keys in Kafka are used for grouping alike messages to ensure they're processed on the same partition. They differ from messaging.message_id in that they're not unique. If the key is null, the attribute MUST NOT be set. + /// + /// + /// If the key type is not string, it&#39;s string representation has to be supplied for the attribute. If the key has no unambiguous, canonical string form, don&#39;t include its value. + /// + public const string AttributeMessagingKafkaMessageKey = "messaging.kafka.message_key"; + + /// + /// Name of the Kafka Consumer Group that is handling the message. Only applies to consumers, not producers. + /// + public const string AttributeMessagingKafkaConsumerGroup = "messaging.kafka.consumer_group"; + + /// + /// Client Id for the Consumer or Producer that is handling the message. + /// + public const string AttributeMessagingKafkaClientId = "messaging.kafka.client_id"; + + /// + /// Partition the message is sent to. + /// + public const string AttributeMessagingKafkaPartition = "messaging.kafka.partition"; + + /// + /// A boolean that is true if the message is a tombstone. + /// + public const string AttributeMessagingKafkaTombstone = "messaging.kafka.tombstone"; + + /// + /// Namespace of RocketMQ resources, resources in different namespaces are individual. + /// + public const string AttributeMessagingRocketmqNamespace = "messaging.rocketmq.namespace"; + + /// + /// Name of the RocketMQ producer/consumer group that is handling the message. The client type is identified by the SpanKind. + /// + public const string AttributeMessagingRocketmqClientGroup = "messaging.rocketmq.client_group"; + + /// + /// The unique identifier for each client. + /// + public const string AttributeMessagingRocketmqClientId = "messaging.rocketmq.client_id"; + + /// + /// Type of message. + /// + public const string AttributeMessagingRocketmqMessageType = "messaging.rocketmq.message_type"; + + /// + /// The secondary classifier of message besides topic. + /// + public const string AttributeMessagingRocketmqMessageTag = "messaging.rocketmq.message_tag"; + + /// + /// Key(s) of message, another way to mark message besides message id. + /// + public const string AttributeMessagingRocketmqMessageKeys = "messaging.rocketmq.message_keys"; + + /// + /// Model of message consumption. This only applies to consumer spans. + /// + public const string AttributeMessagingRocketmqConsumptionModel = "messaging.rocketmq.consumption_model"; + + /// + /// A string identifying the remoting system. See below for a list of well-known identifiers. + /// + public const string AttributeRpcSystem = "rpc.system"; + + /// + /// The full (logical) name of the service being called, including its package name, if applicable. + /// + /// + /// This is the logical name of the service from the RPC interface perspective, which can be different from the name of any implementing class. The code.namespace attribute may be used to store the latter (despite the attribute name, it may include a class name; e.g., class with method actually executing the call on the server side, RPC client stub class on the client side). + /// + public const string AttributeRpcService = "rpc.service"; + + /// + /// The name of the (logical) method being called, must be equal to the $method part in the span name. + /// + /// + /// This is the logical name of the method from the RPC interface perspective, which can be different from the name of any implementing method/function. The code.function attribute may be used to store the latter (e.g., method actually executing the call on the server side, RPC client stub method on the client side). + /// + public const string AttributeRpcMethod = "rpc.method"; + + /// + /// The numeric status code of the gRPC request. + /// + public const string AttributeRpcGrpcStatusCode = "rpc.grpc.status_code"; + + /// + /// Protocol version as in jsonrpc property of request/response. Since JSON-RPC 1.0 does not specify this, the value can be omitted. + /// + public const string AttributeRpcJsonrpcVersion = "rpc.jsonrpc.version"; + + /// + /// id property of request or response. Since protocol allows id to be int, string, null or missing (for notifications), value is expected to be cast to string for simplicity. Use empty string in case of null value. Omit entirely if this is a notification. + /// + public const string AttributeRpcJsonrpcRequestId = "rpc.jsonrpc.request_id"; + + /// + /// error.code property of response if it is an error response. + /// + public const string AttributeRpcJsonrpcErrorCode = "rpc.jsonrpc.error_code"; + + /// + /// error.message property of response if it is an error response. + /// + public const string AttributeRpcJsonrpcErrorMessage = "rpc.jsonrpc.error_message"; + + /// + /// Whether this is a received or sent message. + /// + public const string AttributeMessageType = "message.type"; + + /// + /// MUST be calculated as two different counters starting from 1 one for sent messages and one for received message. + /// + /// + /// This way we guarantee that the values will be consistent between different implementations. + /// + public const string AttributeMessageId = "message.id"; + + /// + /// Compressed size of the message in bytes. + /// + public const string AttributeMessageCompressedSize = "message.compressed_size"; + + /// + /// Uncompressed size of the message in bytes. + /// + public const string AttributeMessageUncompressedSize = "message.uncompressed_size"; + + /// + /// Prefix for 'aws.lambda'. + /// + public static readonly string PrefixAwsLambda = "aws.lambda"; + + /// + /// Prefix for 'cloudevents'. + /// + public static readonly string PrefixCloudevents = "cloudevents"; + + /// + /// Prefix for 'opentracing'. + /// + public static readonly string PrefixOpentracing = "opentracing"; + + /// + /// Prefix for 'db'. + /// + public static readonly string PrefixDb = "db"; + + /// + /// Prefix for 'db.mssql'. + /// + public static readonly string PrefixDbMssql = "db.mssql"; + + /// + /// Prefix for 'db.cassandra'. + /// + public static readonly string PrefixDbCassandra = "db.cassandra"; + + /// + /// Prefix for 'db.redis'. + /// + public static readonly string PrefixDbRedis = "db.redis"; + + /// + /// Prefix for 'db.mongodb'. + /// + public static readonly string PrefixDbMongodb = "db.mongodb"; + + /// + /// Prefix for 'db.sql'. + /// + public static readonly string PrefixDbSql = "db.sql"; + + /// + /// Prefix for 'exception'. + /// + public static readonly string PrefixException = "exception"; + + /// + /// Prefix for 'faas_span'. + /// + public static readonly string PrefixFaasSpan = "faas"; + + /// + /// Prefix for 'faas_span.datasource'. + /// + public static readonly string PrefixFaasSpanDatasource = "faas.document"; + + /// + /// Prefix for 'network'. + /// + public static readonly string PrefixNetwork = "net"; + + /// + /// Prefix for 'peer'. + /// + public static readonly string PrefixPeer = "peer"; + + /// + /// Prefix for 'identity'. + /// + public static readonly string PrefixIdentity = "enduser"; + + /// + /// Prefix for 'thread'. + /// + public static readonly string PrefixThread = "thread"; + + /// + /// Prefix for 'code'. + /// + public static readonly string PrefixCode = "code"; + + /// + /// Prefix for 'http'. + /// + public static readonly string PrefixHttp = "http"; + + /// + /// Prefix for 'aws'. + /// + public static readonly string PrefixAws = "aws"; + + /// + /// Prefix for 'dynamodb.shared'. + /// + public static readonly string PrefixDynamodbShared = "aws.dynamodb"; + + /// + /// Prefix for 'graphql'. + /// + public static readonly string PrefixGraphql = "graphql"; + + /// + /// Prefix for 'messaging'. + /// + public static readonly string PrefixMessaging = "messaging"; + + /// + /// Prefix for 'messaging.rabbitmq'. + /// + public static readonly string PrefixMessagingRabbitmq = "messaging.rabbitmq"; + + /// + /// Prefix for 'messaging.kafka'. + /// + public static readonly string PrefixMessagingKafka = "messaging.kafka"; + + /// + /// Prefix for 'messaging.rocketmq'. + /// + public static readonly string PrefixMessagingRocketmq = "messaging.rocketmq"; + + /// + /// Prefix for 'rpc'. + /// + public static readonly string PrefixRpc = "rpc"; + + /// + /// Prefix for 'rpc.grpc'. + /// + public static readonly string PrefixRpcGrpc = "rpc.grpc"; + + /// + /// Prefix for 'rpc.jsonrpc'. + /// + public static readonly string PrefixRpcJsonrpc = "rpc.jsonrpc"; + + /// + /// Prefix for 'rpc.message'. + /// + public static readonly string PrefixRpcMessage = "message"; + + /// + /// Event name for 'exception'. + /// + public static readonly string EventException = "exception"; + + /// + /// Event name for 'rpc.message'. + /// + public static readonly string EventRpcMessage = "message"; + + /// + /// Parent-child Reference type. + /// + public static class OpentracingRefTypeValues + { + /// + /// The parent Span depends on the child Span in some capacity. + /// + public const string ChildOf = "child_of"; + + /// + /// The parent Span does not depend in any way on the result of the child Span. + /// + public const string FollowsFrom = "follows_from"; + } + + /// + /// An identifier for the database management system (DBMS) product being used. See below for a list of well-known identifiers. + /// + public static class DbSystemValues + { + /// + /// Some other SQL database. Fallback only. See notes. + /// + public const string OtherSql = "other_sql"; + + /// + /// Microsoft SQL Server. + /// + public const string Mssql = "mssql"; + + /// + /// MySQL. + /// + public const string Mysql = "mysql"; + + /// + /// Oracle Database. + /// + public const string Oracle = "oracle"; + + /// + /// IBM Db2. + /// + public const string Db2 = "db2"; + + /// + /// PostgreSQL. + /// + public const string Postgresql = "postgresql"; + + /// + /// Amazon Redshift. + /// + public const string Redshift = "redshift"; + + /// + /// Apache Hive. + /// + public const string Hive = "hive"; + + /// + /// Cloudscape. + /// + public const string Cloudscape = "cloudscape"; + + /// + /// HyperSQL DataBase. + /// + public const string Hsqldb = "hsqldb"; + + /// + /// Progress Database. + /// + public const string Progress = "progress"; + + /// + /// SAP MaxDB. + /// + public const string Maxdb = "maxdb"; + + /// + /// SAP HANA. + /// + public const string Hanadb = "hanadb"; + + /// + /// Ingres. + /// + public const string Ingres = "ingres"; + + /// + /// FirstSQL. + /// + public const string Firstsql = "firstsql"; + + /// + /// EnterpriseDB. + /// + public const string Edb = "edb"; + + /// + /// InterSystems Caché. + /// + public const string Cache = "cache"; + + /// + /// Adabas (Adaptable Database System). + /// + public const string Adabas = "adabas"; + + /// + /// Firebird. + /// + public const string Firebird = "firebird"; + + /// + /// Apache Derby. + /// + public const string Derby = "derby"; + + /// + /// FileMaker. + /// + public const string Filemaker = "filemaker"; + + /// + /// Informix. + /// + public const string Informix = "informix"; + + /// + /// InstantDB. + /// + public const string Instantdb = "instantdb"; + + /// + /// InterBase. + /// + public const string Interbase = "interbase"; + + /// + /// MariaDB. + /// + public const string Mariadb = "mariadb"; + + /// + /// Netezza. + /// + public const string Netezza = "netezza"; + + /// + /// Pervasive PSQL. + /// + public const string Pervasive = "pervasive"; + + /// + /// PointBase. + /// + public const string Pointbase = "pointbase"; + + /// + /// SQLite. + /// + public const string Sqlite = "sqlite"; + + /// + /// Sybase. + /// + public const string Sybase = "sybase"; + + /// + /// Teradata. + /// + public const string Teradata = "teradata"; + + /// + /// Vertica. + /// + public const string Vertica = "vertica"; + + /// + /// H2. + /// + public const string H2 = "h2"; + + /// + /// ColdFusion IMQ. + /// + public const string Coldfusion = "coldfusion"; + + /// + /// Apache Cassandra. + /// + public const string Cassandra = "cassandra"; + + /// + /// Apache HBase. + /// + public const string Hbase = "hbase"; + + /// + /// MongoDB. + /// + public const string Mongodb = "mongodb"; + + /// + /// Redis. + /// + public const string Redis = "redis"; + + /// + /// Couchbase. + /// + public const string Couchbase = "couchbase"; + + /// + /// CouchDB. + /// + public const string Couchdb = "couchdb"; + + /// + /// Microsoft Azure Cosmos DB. + /// + public const string Cosmosdb = "cosmosdb"; + + /// + /// Amazon DynamoDB. + /// + public const string Dynamodb = "dynamodb"; + + /// + /// Neo4j. + /// + public const string Neo4j = "neo4j"; + + /// + /// Apache Geode. + /// + public const string Geode = "geode"; + + /// + /// Elasticsearch. + /// + public const string Elasticsearch = "elasticsearch"; + + /// + /// Memcached. + /// + public const string Memcached = "memcached"; + + /// + /// CockroachDB. + /// + public const string Cockroachdb = "cockroachdb"; + + /// + /// OpenSearch. + /// + public const string Opensearch = "opensearch"; + } + + /// + /// The consistency level of the query. Based on consistency values from CQL. + /// + public static class DbCassandraConsistencyLevelValues + { + /// + /// all. + /// + public const string All = "all"; + + /// + /// each_quorum. + /// + public const string EachQuorum = "each_quorum"; + + /// + /// quorum. + /// + public const string Quorum = "quorum"; + + /// + /// local_quorum. + /// + public const string LocalQuorum = "local_quorum"; + + /// + /// one. + /// + public const string One = "one"; + + /// + /// two. + /// + public const string Two = "two"; + + /// + /// three. + /// + public const string Three = "three"; + + /// + /// local_one. + /// + public const string LocalOne = "local_one"; + + /// + /// any. + /// + public const string Any = "any"; + + /// + /// serial. + /// + public const string Serial = "serial"; + + /// + /// local_serial. + /// + public const string LocalSerial = "local_serial"; + } + + /// + /// Type of the trigger which caused this function execution. + /// + public static class FaasTriggerValues + { + /// + /// A response to some data source operation such as a database or filesystem read/write. + /// + public const string Datasource = "datasource"; + + /// + /// To provide an answer to an inbound HTTP request. + /// + public const string Http = "http"; + + /// + /// A function is set to be executed when messages are sent to a messaging system. + /// + public const string Pubsub = "pubsub"; + + /// + /// A function is scheduled to be executed regularly. + /// + public const string Timer = "timer"; + + /// + /// If none of the others apply. + /// + public const string Other = "other"; + } + + /// + /// Describes the type of the operation that was performed on the data. + /// + public static class FaasDocumentOperationValues + { + /// + /// When a new object is created. + /// + public const string Insert = "insert"; + + /// + /// When an object is modified. + /// + public const string Edit = "edit"; + + /// + /// When an object is deleted. + /// + public const string Delete = "delete"; + } + + /// + /// The cloud provider of the invoked function. + /// + public static class FaasInvokedProviderValues + { + /// + /// Alibaba Cloud. + /// + public const string AlibabaCloud = "alibaba_cloud"; + + /// + /// Amazon Web Services. + /// + public const string Aws = "aws"; + + /// + /// Microsoft Azure. + /// + public const string Azure = "azure"; + + /// + /// Google Cloud Platform. + /// + public const string Gcp = "gcp"; + + /// + /// Tencent Cloud. + /// + public const string TencentCloud = "tencent_cloud"; + } + + /// + /// Transport protocol used. See note below. + /// + public static class NetTransportValues + { + /// + /// ip_tcp. + /// + public const string IpTcp = "ip_tcp"; + + /// + /// ip_udp. + /// + public const string IpUdp = "ip_udp"; + + /// + /// Named or anonymous pipe. See note below. + /// + public const string Pipe = "pipe"; + + /// + /// In-process communication. + /// + public const string Inproc = "inproc"; + + /// + /// Something else (non IP-based). + /// + public const string Other = "other"; + } + + /// + /// Protocol address family which is used for communication. + /// + public static class NetSockFamilyValues + { + /// + /// IPv4 address. + /// + public const string Inet = "inet"; + + /// + /// IPv6 address. + /// + public const string Inet6 = "inet6"; + + /// + /// Unix domain socket path. + /// + public const string Unix = "unix"; + } + + /// + /// The internet connection type currently being used by the host. + /// + public static class NetHostConnectionTypeValues + { + /// + /// wifi. + /// + public const string Wifi = "wifi"; + + /// + /// wired. + /// + public const string Wired = "wired"; + + /// + /// cell. + /// + public const string Cell = "cell"; + + /// + /// unavailable. + /// + public const string Unavailable = "unavailable"; + + /// + /// unknown. + /// + public const string Unknown = "unknown"; + } + + /// + /// This describes more details regarding the connection.type. It may be the type of cell technology connection, but it could be used for describing details about a wifi connection. + /// + public static class NetHostConnectionSubtypeValues + { + /// + /// GPRS. + /// + public const string Gprs = "gprs"; + + /// + /// EDGE. + /// + public const string Edge = "edge"; + + /// + /// UMTS. + /// + public const string Umts = "umts"; + + /// + /// CDMA. + /// + public const string Cdma = "cdma"; + + /// + /// EVDO Rel. 0. + /// + public const string Evdo0 = "evdo_0"; + + /// + /// EVDO Rev. A. + /// + public const string EvdoA = "evdo_a"; + + /// + /// CDMA2000 1XRTT. + /// + public const string Cdma20001xrtt = "cdma2000_1xrtt"; + + /// + /// HSDPA. + /// + public const string Hsdpa = "hsdpa"; + + /// + /// HSUPA. + /// + public const string Hsupa = "hsupa"; + + /// + /// HSPA. + /// + public const string Hspa = "hspa"; + + /// + /// IDEN. + /// + public const string Iden = "iden"; + + /// + /// EVDO Rev. B. + /// + public const string EvdoB = "evdo_b"; + + /// + /// LTE. + /// + public const string Lte = "lte"; + + /// + /// EHRPD. + /// + public const string Ehrpd = "ehrpd"; + + /// + /// HSPAP. + /// + public const string Hspap = "hspap"; + + /// + /// GSM. + /// + public const string Gsm = "gsm"; + + /// + /// TD-SCDMA. + /// + public const string TdScdma = "td_scdma"; + + /// + /// IWLAN. + /// + public const string Iwlan = "iwlan"; + + /// + /// 5G NR (New Radio). + /// + public const string Nr = "nr"; + + /// + /// 5G NRNSA (New Radio Non-Standalone). + /// + public const string Nrnsa = "nrnsa"; + + /// + /// LTE CA. + /// + public const string LteCa = "lte_ca"; + } + + /// + /// Kind of HTTP protocol used. + /// + public static class HttpFlavorValues + { + /// + /// HTTP/1.0. + /// + public const string Http10 = "1.0"; + + /// + /// HTTP/1.1. + /// + public const string Http11 = "1.1"; + + /// + /// HTTP/2. + /// + public const string Http20 = "2.0"; + + /// + /// HTTP/3. + /// + public const string Http30 = "3.0"; + + /// + /// SPDY protocol. + /// + public const string Spdy = "SPDY"; + + /// + /// QUIC protocol. + /// + public const string Quic = "QUIC"; + } + + /// + /// The type of the operation being executed. + /// + public static class GraphqlOperationTypeValues + { + /// + /// GraphQL query. + /// + public const string Query = "query"; + + /// + /// GraphQL mutation. + /// + public const string Mutation = "mutation"; + + /// + /// GraphQL subscription. + /// + public const string Subscription = "subscription"; + } + + /// + /// The kind of message destination. + /// + public static class MessagingDestinationKindValues + { + /// + /// A message sent to a queue. + /// + public const string Queue = "queue"; + + /// + /// A message sent to a topic. + /// + public const string Topic = "topic"; + } + + /// + /// A string identifying the kind of message consumption as defined in the Operation names section above. If the operation is "send", this attribute MUST NOT be set, since the operation can be inferred from the span kind in that case. + /// + public static class MessagingOperationValues + { + /// + /// receive. + /// + public const string Receive = "receive"; + + /// + /// process. + /// + public const string Process = "process"; + } + + /// + /// Type of message. + /// + public static class MessagingRocketmqMessageTypeValues + { + /// + /// Normal message. + /// + public const string Normal = "normal"; + + /// + /// FIFO message. + /// + public const string Fifo = "fifo"; + + /// + /// Delay message. + /// + public const string Delay = "delay"; + + /// + /// Transaction message. + /// + public const string Transaction = "transaction"; + } + + /// + /// Model of message consumption. This only applies to consumer spans. + /// + public static class MessagingRocketmqConsumptionModelValues + { + /// + /// Clustering consumption model. + /// + public const string Clustering = "clustering"; + + /// + /// Broadcasting consumption model. + /// + public const string Broadcasting = "broadcasting"; + } + + /// + /// A string identifying the remoting system. See below for a list of well-known identifiers. + /// + public static class RpcSystemValues + { + /// + /// gRPC. + /// + public const string Grpc = "grpc"; + + /// + /// Java RMI. + /// + public const string JavaRmi = "java_rmi"; + + /// + /// .NET WCF. + /// + public const string DotnetWcf = "dotnet_wcf"; + + /// + /// Apache Dubbo. + /// + public const string ApacheDubbo = "apache_dubbo"; + } + + /// + /// The numeric status code of the gRPC request. + /// + public static class RpcGrpcStatusCodeValues + { + /// + /// OK. + /// + public const int Ok = 0; + + /// + /// CANCELLED. + /// + public const int Cancelled = 1; + + /// + /// UNKNOWN. + /// + public const int Unknown = 2; + + /// + /// INVALID_ARGUMENT. + /// + public const int InvalidArgument = 3; + + /// + /// DEADLINE_EXCEEDED. + /// + public const int DeadlineExceeded = 4; + + /// + /// NOT_FOUND. + /// + public const int NotFound = 5; + + /// + /// ALREADY_EXISTS. + /// + public const int AlreadyExists = 6; + + /// + /// PERMISSION_DENIED. + /// + public const int PermissionDenied = 7; + + /// + /// RESOURCE_EXHAUSTED. + /// + public const int ResourceExhausted = 8; + + /// + /// FAILED_PRECONDITION. + /// + public const int FailedPrecondition = 9; + + /// + /// ABORTED. + /// + public const int Aborted = 10; + + /// + /// OUT_OF_RANGE. + /// + public const int OutOfRange = 11; + + /// + /// UNIMPLEMENTED. + /// + public const int Unimplemented = 12; + + /// + /// INTERNAL. + /// + public const int Internal = 13; + + /// + /// UNAVAILABLE. + /// + public const int Unavailable = 14; + + /// + /// DATA_LOSS. + /// + public const int DataLoss = 15; + + /// + /// UNAUTHENTICATED. + /// + public const int Unauthenticated = 16; + } + + /// + /// Whether this is a received or sent message. + /// + public static class MessageTypeValues + { + /// + /// sent. + /// + public const string Sent = "SENT"; + + /// + /// received. + /// + public const string Received = "RECEIVED"; + } + } +} diff --git a/src/OpenTelemetry.SemanticConventions/scripts/semantic-conventions/.gitignore b/src/OpenTelemetry.SemanticConventions/scripts/semantic-conventions/.gitignore new file mode 100644 index 00000000000..a93b221beb5 --- /dev/null +++ b/src/OpenTelemetry.SemanticConventions/scripts/semantic-conventions/.gitignore @@ -0,0 +1 @@ +opentelemetry-specification/ diff --git a/src/OpenTelemetry.SemanticConventions/scripts/semantic-conventions/generate.ps1 b/src/OpenTelemetry.SemanticConventions/scripts/semantic-conventions/generate.ps1 new file mode 100644 index 00000000000..942f499ee4e --- /dev/null +++ b/src/OpenTelemetry.SemanticConventions/scripts/semantic-conventions/generate.ps1 @@ -0,0 +1,51 @@ + +$SCRIPT_DIR=$PSScriptRoot +$ROOT_DIR="${SCRIPT_DIR}/../../" + +# freeze the spec & generator tools versions to make SemanticAttributes generation reproducible +$SPEC_VERSION="v1.13.0" +$SCHEMA_URL="https://opentelemetry.io/schemas/$SPEC_VERSION" +$GENERATOR_VERSION="0.14.0" + +Set-Location $SCRIPT_DIR + +Remove-Item -r -fo opentelemetry-specification +mkdir opentelemetry-specification +Set-Location opentelemetry-specification + +git init +git remote add origin https://github.com/open-telemetry/opentelemetry-specification.git +git fetch origin $SPEC_VERSION +git reset --hard FETCH_HEAD +Set-Location ${SCRIPT_DIR} + +docker run --rm ` + -v ${SCRIPT_DIR}/opentelemetry-specification/semantic_conventions/trace:/source ` + -v ${SCRIPT_DIR}/templates:/templates ` + -v ${ROOT_DIR}/Trace:/output ` + otel/semconvgen:$GENERATOR_VERSION ` + -f /source code ` + --template /templates/SemanticConventions.cs.j2 ` + --output /output/TraceSemanticConventions.cs ` + --trim-whitespace ` + -D class=TraceSemanticConventions ` + -D schemaUrl=$SCHEMA_URL ` + -D pkg=OpenTelemetry.Trace + +docker run --rm ` + -v ${SCRIPT_DIR}/opentelemetry-specification/semantic_conventions/resource:/source ` + -v ${SCRIPT_DIR}/templates:/templates ` + -v ${ROOT_DIR}/Resource:/output ` + otel/semconvgen:$GENERATOR_VERSION ` + -f /source code ` + --template /templates/SemanticConventions.cs.j2 ` + --output /output/ResourceSemanticConventions.cs ` + --trim-whitespace ` + -D class=ResourceSemanticConventions ` + -D schemaUrl=$SCHEMA_URL ` + -D pkg=OpenTelemetry.Resources + +Set-Location ${ROOT_DIR} + +# Write-Host "Running dotnet-format on the generated files" +# dotnet format --severity warn diff --git a/src/OpenTelemetry.SemanticConventions/scripts/semantic-conventions/generate.sh b/src/OpenTelemetry.SemanticConventions/scripts/semantic-conventions/generate.sh new file mode 100644 index 00000000000..76515a80bff --- /dev/null +++ b/src/OpenTelemetry.SemanticConventions/scripts/semantic-conventions/generate.sh @@ -0,0 +1,47 @@ +#!/bin/bash + +SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" +ROOT_DIR="${SCRIPT_DIR}/../../" + +# freeze the spec & generator tools versions to make SemanticAttributes generation reproducible +SPEC_VERSION=v1.13.0 +SCHEMA_URL=https://opentelemetry.io/schemas/$SPEC_VERSION +GENERATOR_VERSION=0.14.0 + +cd ${SCRIPT_DIR} + +rm -rf opentelemetry-specification || true +mkdir opentelemetry-specification +cd opentelemetry-specification + +git init +git remote add origin https://github.com/open-telemetry/opentelemetry-specification.git +git fetch origin "$SPEC_VERSION" +git reset --hard FETCH_HEAD +cd ${SCRIPT_DIR} + +docker run --rm \ + -v ${SCRIPT_DIR}/opentelemetry-specification/semantic_conventions/trace:/source \ + -v ${SCRIPT_DIR}/templates:/templates \ + -v ${ROOT_DIR}/Trace:/output \ + otel/semconvgen:$GENERATOR_VERSION \ + -f /source code \ + --template /templates/SemanticConventions.cs.j2 \ + --output /output/TraceSemanticConventions.cs \ + --trim-whitespace \ + -Dclass=TraceSemanticConventions \ + -DschemaUrl=$SCHEMA_URL \ + -Dpkg=OpenTelemetry.Trace + +docker run --rm \ + -v ${SCRIPT_DIR}/opentelemetry-specification/semantic_conventions/resource:/source \ + -v ${SCRIPT_DIR}/templates:/templates \ + -v ${ROOT_DIR}/Resource:/output \ + otel/semconvgen:$GENERATOR_VERSION \ + -f /source code \ + --template /templates/SemanticConventions.cs.j2 \ + --output /output/ResourceSemanticConventions.cs \ + --trim-whitespace \ + -Dclass=ResourceSemanticConventions \ + -DschemaUrl=$SCHEMA_URL \ + -Dpkg=OpenTelemetry.Resources diff --git a/src/OpenTelemetry.SemanticConventions/scripts/semantic-conventions/templates/SemanticConventions.cs.j2 b/src/OpenTelemetry.SemanticConventions/scripts/semantic-conventions/templates/SemanticConventions.cs.j2 new file mode 100644 index 00000000000..057c417379e --- /dev/null +++ b/src/OpenTelemetry.SemanticConventions/scripts/semantic-conventions/templates/SemanticConventions.cs.j2 @@ -0,0 +1,116 @@ +{%- macro print_value(type, value) -%} + {{ "\"" if type == "string"}}{{value}}{{ "\"" if type == "string"}} +{%- endmacro %} + +{%- macro format_remarks(text) -%} +{%- set notes = '\n /// '.join(text.splitlines()).encode('ascii', 'xmlcharrefreplace').decode() -%} +{{notes}} +{%- endmacro -%} + +{%- macro format_xml_doc(text) -%} +{%- set escaped = text.encode('ascii', 'xmlcharrefreplace').decode() -%} + {%- if not escaped.endswith('.')-%} + {{escaped + '.'}} + {%- else -%} + {{escaped}} + {%- endif -%} +{%- endmacro -%} + +// +// Copyright The OpenTelemetry Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +// This file has been auto generated from buildscripts/semantic-conventions{{template}} + +using System; + +namespace {{pkg | trim}} +{ + /// + /// Constants for semantic attribute names outlined by the OpenTelemetry specifications. + {% if class == "TraceSemanticConventions" %} + /// . + {% elif class == "ResourceSemanticConventions" %} + /// . + {% endif %} + /// + /// + /// Schema and specification version: {{schemaUrl}}. + /// + public static class {{class}} + { +{% if class == "TraceSemanticConventions" %} + /// + /// Attribute for db.instance. + /// + public const string AttributeDbInstance = "db.instance"; + +{% endif %} +{% for attribute in attributes if attribute.is_local and not attribute.ref %} + {% if not loop.first %}{{"\n"}}{% endif %} + /// + /// {{format_xml_doc(attribute.brief | render_markdown(code="{0}", paragraph="{0}"))}} + /// + {% if attribute.note %} + /// + /// {{format_remarks(attribute.note | to_doc_brief | escape | render_markdown(code="{0}", paragraph="{0}"))}}. + /// + {% endif %} + {% if attribute.deprecated %} + [Obsolete("{{attribute.deprecated | to_doc_brief}}")] + {% endif %} + public const string Attribute{{attribute.fqn | replace("-","_") | to_camelcase(True)}} = "{{attribute.fqn}}"; +{% endfor %} +{% for semconv in semconvs.values() | unique(attribute="prefix") %} + {% if semconv.prefix %} + + /// + /// Prefix for '{{semconv.semconv_id}}'. + /// + public static readonly string Prefix{{semconv.semconv_id | replace("-","_") | to_camelcase(True)}} = "{{semconv.prefix}}"; + {% endif %} +{% endfor %} +{% for semconv in semconvs.values() %} + {% if semconv.GROUP_TYPE_NAME == 'event' %} + + /// + /// Event name for '{{semconv.semconv_id}}'. + /// + public static readonly string Event{{semconv.semconv_id | replace("-","_") | to_camelcase(True)}} = "{{semconv.name}}"; + {% endif %} +{% endfor %} +{% for attribute in attributes if attribute.is_local and not attribute.ref %} + {% if attribute.is_enum %} + {% set class_name = attribute.fqn | to_camelcase(True) ~ "Values" %} + {% set type = attribute.attr_type.enum_type %} + + /// + /// {{format_xml_doc(attribute.brief | render_markdown(code="{0}", paragraph="{0}"))}} + /// + public static class {{class_name}} + { + {% for member in attribute.attr_type.members %} + /// + /// {{format_xml_doc(member.brief | render_markdown(code="{0}", paragraph="{0}"))}} + /// + public const {{ type }} {{ member.member_id | to_camelcase(True) }} = {{ print_value(type, member.value) }}; + {% if not loop.last %}{{"\n"}}{% endif %} + {% endfor %} + } + {% endif %} +{% endfor %} + } +} + diff --git a/src/OpenTelemetry.Shims.OpenTracing/CHANGELOG.md b/src/OpenTelemetry.Shims.OpenTracing/CHANGELOG.md index 3bed1d35d3d..4e7fceee7c8 100644 --- a/src/OpenTelemetry.Shims.OpenTracing/CHANGELOG.md +++ b/src/OpenTelemetry.Shims.OpenTracing/CHANGELOG.md @@ -2,6 +2,10 @@ ## Unreleased +## 1.0.0-rc9.8 + +Released 2022-Oct-17 + ## 1.0.0-rc9.7 Released 2022-Sep-29 diff --git a/src/OpenTelemetry.Shims.OpenTracing/ScopeManagerShim.cs b/src/OpenTelemetry.Shims.OpenTracing/ScopeManagerShim.cs index a4039d88a41..0617a16cbe7 100644 --- a/src/OpenTelemetry.Shims.OpenTracing/ScopeManagerShim.cs +++ b/src/OpenTelemetry.Shims.OpenTracing/ScopeManagerShim.cs @@ -95,7 +95,7 @@ public IScope Activate(ISpan span, bool finishSpanOnDispose) return instrumentation; } - private class ScopeInstrumentation : IScope + private sealed class ScopeInstrumentation : IScope { private readonly Action disposeAction; diff --git a/src/OpenTelemetry/.publicApi/net462/PublicAPI.Shipped.txt b/src/OpenTelemetry/.publicApi/net462/PublicAPI.Shipped.txt index e4585058956..a601fdd2439 100644 --- a/src/OpenTelemetry/.publicApi/net462/PublicAPI.Shipped.txt +++ b/src/OpenTelemetry/.publicApi/net462/PublicAPI.Shipped.txt @@ -10,10 +10,10 @@ OpenTelemetry.Batch OpenTelemetry.Batch.Batch(T![]! items, int count) -> void OpenTelemetry.Batch.Enumerator.Current.get -> T! ~OpenTelemetry.Batch.GetEnumerator() -> OpenTelemetry.Batch.Enumerator -~OpenTelemetry.BatchActivityExportProcessor.BatchActivityExportProcessor(OpenTelemetry.BaseExporter exporter, int maxQueueSize = 2048, int scheduledDelayMilliseconds = 5000, int exporterTimeoutMilliseconds = 30000, int maxExportBatchSize = 512) -> void +OpenTelemetry.BatchActivityExportProcessor.BatchActivityExportProcessor(OpenTelemetry.BaseExporter! exporter, int maxQueueSize = 2048, int scheduledDelayMilliseconds = 5000, int exporterTimeoutMilliseconds = 30000, int maxExportBatchSize = 512) -> void OpenTelemetry.BatchExportProcessor OpenTelemetry.BatchExportProcessor.BatchExportProcessor(OpenTelemetry.BaseExporter! exporter, int maxQueueSize = 2048, int scheduledDelayMilliseconds = 5000, int exporterTimeoutMilliseconds = 30000, int maxExportBatchSize = 512) -> void -~OpenTelemetry.BatchExportProcessorOptions +OpenTelemetry.BatchExportProcessorOptions OpenTelemetry.CompositeProcessor.AddProcessor(OpenTelemetry.BaseProcessor! processor) -> OpenTelemetry.CompositeProcessor! OpenTelemetry.CompositeProcessor.CompositeProcessor(System.Collections.Generic.IEnumerable!>! processors) -> void ~OpenTelemetry.Metrics.BaseExportingMetricReader.BaseExportingMetricReader(OpenTelemetry.BaseExporter exporter) -> void @@ -37,37 +37,37 @@ OpenTelemetry.Metrics.MetricReaderOptions.PeriodicExportingMetricReaderOptions.s ~OpenTelemetry.Metrics.MetricStreamConfiguration.TagKeys.get -> string[] ~OpenTelemetry.Metrics.MetricStreamConfiguration.TagKeys.set -> void ~OpenTelemetry.Metrics.PeriodicExportingMetricReader.PeriodicExportingMetricReader(OpenTelemetry.BaseExporter exporter, int exportIntervalMilliseconds = 60000, int exportTimeoutMilliseconds = 30000) -> void -~OpenTelemetry.ReadOnlyTagCollection.Enumerator.Current.get -> System.Collections.Generic.KeyValuePair -~OpenTelemetry.Resources.IResourceDetector.Detect() -> OpenTelemetry.Resources.Resource -~OpenTelemetry.Resources.Resource.Attributes.get -> System.Collections.Generic.IEnumerable> -~OpenTelemetry.Resources.Resource.Merge(OpenTelemetry.Resources.Resource other) -> OpenTelemetry.Resources.Resource -~OpenTelemetry.Resources.Resource.Resource(System.Collections.Generic.IEnumerable> attributes) -> void -~OpenTelemetry.Resources.ResourceBuilder.AddDetector(OpenTelemetry.Resources.IResourceDetector resourceDetector) -> OpenTelemetry.Resources.ResourceBuilder -~OpenTelemetry.Resources.ResourceBuilder.Build() -> OpenTelemetry.Resources.Resource -~OpenTelemetry.Resources.ResourceBuilder.Clear() -> OpenTelemetry.Resources.ResourceBuilder -~OpenTelemetry.SimpleActivityExportProcessor.SimpleActivityExportProcessor(OpenTelemetry.BaseExporter exporter) -> void +OpenTelemetry.ReadOnlyTagCollection.Enumerator.Current.get -> System.Collections.Generic.KeyValuePair +OpenTelemetry.Resources.IResourceDetector.Detect() -> OpenTelemetry.Resources.Resource! +OpenTelemetry.Resources.Resource.Attributes.get -> System.Collections.Generic.IEnumerable>! +OpenTelemetry.Resources.Resource.Merge(OpenTelemetry.Resources.Resource! other) -> OpenTelemetry.Resources.Resource! +OpenTelemetry.Resources.Resource.Resource(System.Collections.Generic.IEnumerable>! attributes) -> void +OpenTelemetry.Resources.ResourceBuilder.AddDetector(OpenTelemetry.Resources.IResourceDetector! resourceDetector) -> OpenTelemetry.Resources.ResourceBuilder! +OpenTelemetry.Resources.ResourceBuilder.Build() -> OpenTelemetry.Resources.Resource! +OpenTelemetry.Resources.ResourceBuilder.Clear() -> OpenTelemetry.Resources.ResourceBuilder! +OpenTelemetry.SimpleActivityExportProcessor.SimpleActivityExportProcessor(OpenTelemetry.BaseExporter! exporter) -> void OpenTelemetry.SimpleExportProcessor OpenTelemetry.SimpleExportProcessor.SimpleExportProcessor(OpenTelemetry.BaseExporter! exporter) -> void -~OpenTelemetry.Trace.ParentBasedSampler.ParentBasedSampler(OpenTelemetry.Trace.Sampler rootSampler) -> void -~OpenTelemetry.Trace.ParentBasedSampler.ParentBasedSampler(OpenTelemetry.Trace.Sampler rootSampler, OpenTelemetry.Trace.Sampler remoteParentSampled = null, OpenTelemetry.Trace.Sampler remoteParentNotSampled = null, OpenTelemetry.Trace.Sampler localParentSampled = null, OpenTelemetry.Trace.Sampler localParentNotSampled = null) -> void -~OpenTelemetry.Trace.Sampler.Description.get -> string -~OpenTelemetry.Trace.Sampler.Description.set -> void -~OpenTelemetry.Trace.SamplingParameters.Links.get -> System.Collections.Generic.IEnumerable -~OpenTelemetry.Trace.SamplingParameters.Name.get -> string -~OpenTelemetry.Trace.SamplingParameters.SamplingParameters(System.Diagnostics.ActivityContext parentContext, System.Diagnostics.ActivityTraceId traceId, string name, System.Diagnostics.ActivityKind kind, System.Collections.Generic.IEnumerable> tags = null, System.Collections.Generic.IEnumerable links = null) -> void -~OpenTelemetry.Trace.SamplingParameters.Tags.get -> System.Collections.Generic.IEnumerable> -~OpenTelemetry.Trace.SamplingResult.Attributes.get -> System.Collections.Generic.IEnumerable> -~OpenTelemetry.Trace.SamplingResult.SamplingResult(OpenTelemetry.Trace.SamplingDecision decision, System.Collections.Generic.IEnumerable> attributes) -> void +OpenTelemetry.Trace.ParentBasedSampler.ParentBasedSampler(OpenTelemetry.Trace.Sampler! rootSampler) -> void +OpenTelemetry.Trace.ParentBasedSampler.ParentBasedSampler(OpenTelemetry.Trace.Sampler! rootSampler, OpenTelemetry.Trace.Sampler? remoteParentSampled = null, OpenTelemetry.Trace.Sampler? remoteParentNotSampled = null, OpenTelemetry.Trace.Sampler? localParentSampled = null, OpenTelemetry.Trace.Sampler? localParentNotSampled = null) -> void +OpenTelemetry.Trace.Sampler.Description.get -> string! +OpenTelemetry.Trace.Sampler.Description.set -> void +OpenTelemetry.Trace.SamplingParameters.Links.get -> System.Collections.Generic.IEnumerable? +OpenTelemetry.Trace.SamplingParameters.Name.get -> string! +OpenTelemetry.Trace.SamplingParameters.SamplingParameters(System.Diagnostics.ActivityContext parentContext, System.Diagnostics.ActivityTraceId traceId, string! name, System.Diagnostics.ActivityKind kind, System.Collections.Generic.IEnumerable>? tags = null, System.Collections.Generic.IEnumerable? links = null) -> void +OpenTelemetry.Trace.SamplingParameters.Tags.get -> System.Collections.Generic.IEnumerable>? +OpenTelemetry.Trace.SamplingResult.Attributes.get -> System.Collections.Generic.IEnumerable>! +OpenTelemetry.Trace.SamplingResult.SamplingResult(OpenTelemetry.Trace.SamplingDecision decision, System.Collections.Generic.IEnumerable>! attributes) -> void OpenTelemetry.Trace.TracerProviderBuilderBase.AddInstrumentation(string! instrumentationName, string! instrumentationVersion, System.Func! instrumentationFactory) -> OpenTelemetry.Trace.TracerProviderBuilder! OpenTelemetry.Trace.TracerProviderBuilderBase.Build() -> OpenTelemetry.Trace.TracerProvider! override OpenTelemetry.BaseExportProcessor.OnEnd(T! data) -> void -~override OpenTelemetry.BatchActivityExportProcessor.OnEnd(System.Diagnostics.Activity data) -> void +override OpenTelemetry.BatchActivityExportProcessor.OnEnd(System.Diagnostics.Activity! data) -> void override OpenTelemetry.BatchExportProcessor.OnExport(T! data) -> void ~override OpenTelemetry.Metrics.MeterProviderBuilderBase.AddInstrumentation(System.Func! instrumentationFactory) -> OpenTelemetry.Metrics.MeterProviderBuilder! override OpenTelemetry.Metrics.MeterProviderBuilderBase.AddMeter(params string![]! names) -> OpenTelemetry.Metrics.MeterProviderBuilder! -~override OpenTelemetry.SimpleActivityExportProcessor.OnEnd(System.Diagnostics.Activity data) -> void +override OpenTelemetry.SimpleActivityExportProcessor.OnEnd(System.Diagnostics.Activity! data) -> void override OpenTelemetry.SimpleExportProcessor.OnExport(T! data) -> void -~override OpenTelemetry.Trace.SamplingResult.Equals(object obj) -> bool +override OpenTelemetry.Trace.SamplingResult.Equals(object? obj) -> bool ~override OpenTelemetry.Trace.TracerProviderBuilderBase.AddInstrumentation(System.Func! instrumentationFactory) -> OpenTelemetry.Trace.TracerProviderBuilder! override OpenTelemetry.Trace.TracerProviderBuilderBase.AddLegacySource(string! operationName) -> OpenTelemetry.Trace.TracerProviderBuilder! override OpenTelemetry.Trace.TracerProviderBuilderBase.AddSource(params string![]! names) -> OpenTelemetry.Trace.TracerProviderBuilder! @@ -87,17 +87,17 @@ static OpenTelemetry.Metrics.MeterProviderBuilderExtensions.SetResourceBuilder(t ~static OpenTelemetry.Metrics.MetricStreamConfiguration.Drop.get -> OpenTelemetry.Metrics.MetricStreamConfiguration static OpenTelemetry.ProviderExtensions.GetDefaultResource(this OpenTelemetry.BaseProvider! baseProvider) -> OpenTelemetry.Resources.Resource! static OpenTelemetry.ProviderExtensions.GetResource(this OpenTelemetry.BaseProvider! baseProvider) -> OpenTelemetry.Resources.Resource! -~static OpenTelemetry.Resources.Resource.Empty.get -> OpenTelemetry.Resources.Resource -~static OpenTelemetry.Resources.ResourceBuilder.CreateDefault() -> OpenTelemetry.Resources.ResourceBuilder -~static OpenTelemetry.Resources.ResourceBuilder.CreateEmpty() -> OpenTelemetry.Resources.ResourceBuilder -~static OpenTelemetry.Resources.ResourceBuilderExtensions.AddAttributes(this OpenTelemetry.Resources.ResourceBuilder resourceBuilder, System.Collections.Generic.IEnumerable> attributes) -> OpenTelemetry.Resources.ResourceBuilder -~static OpenTelemetry.Resources.ResourceBuilderExtensions.AddEnvironmentVariableDetector(this OpenTelemetry.Resources.ResourceBuilder resourceBuilder) -> OpenTelemetry.Resources.ResourceBuilder -~static OpenTelemetry.Resources.ResourceBuilderExtensions.AddService(this OpenTelemetry.Resources.ResourceBuilder resourceBuilder, string serviceName, string serviceNamespace = null, string serviceVersion = null, bool autoGenerateServiceInstanceId = true, string serviceInstanceId = null) -> OpenTelemetry.Resources.ResourceBuilder -~static OpenTelemetry.Resources.ResourceBuilderExtensions.AddTelemetrySdk(this OpenTelemetry.Resources.ResourceBuilder resourceBuilder) -> OpenTelemetry.Resources.ResourceBuilder +static OpenTelemetry.Resources.Resource.Empty.get -> OpenTelemetry.Resources.Resource! +static OpenTelemetry.Resources.ResourceBuilder.CreateDefault() -> OpenTelemetry.Resources.ResourceBuilder! +static OpenTelemetry.Resources.ResourceBuilder.CreateEmpty() -> OpenTelemetry.Resources.ResourceBuilder! +static OpenTelemetry.Resources.ResourceBuilderExtensions.AddAttributes(this OpenTelemetry.Resources.ResourceBuilder! resourceBuilder, System.Collections.Generic.IEnumerable>! attributes) -> OpenTelemetry.Resources.ResourceBuilder! +static OpenTelemetry.Resources.ResourceBuilderExtensions.AddEnvironmentVariableDetector(this OpenTelemetry.Resources.ResourceBuilder! resourceBuilder) -> OpenTelemetry.Resources.ResourceBuilder! +static OpenTelemetry.Resources.ResourceBuilderExtensions.AddService(this OpenTelemetry.Resources.ResourceBuilder! resourceBuilder, string! serviceName, string? serviceNamespace = null, string? serviceVersion = null, bool autoGenerateServiceInstanceId = true, string? serviceInstanceId = null) -> OpenTelemetry.Resources.ResourceBuilder! +static OpenTelemetry.Resources.ResourceBuilderExtensions.AddTelemetrySdk(this OpenTelemetry.Resources.ResourceBuilder! resourceBuilder) -> OpenTelemetry.Resources.ResourceBuilder! static OpenTelemetry.Sdk.CreateMeterProviderBuilder() -> OpenTelemetry.Metrics.MeterProviderBuilder! static OpenTelemetry.Sdk.CreateTracerProviderBuilder() -> OpenTelemetry.Trace.TracerProviderBuilder! static OpenTelemetry.Sdk.SetDefaultTextMapPropagator(OpenTelemetry.Context.Propagation.TextMapPropagator! textMapPropagator) -> void -~static OpenTelemetry.SuppressInstrumentationScope.Begin(bool value = true) -> System.IDisposable +static OpenTelemetry.SuppressInstrumentationScope.Begin(bool value = true) -> System.IDisposable! static OpenTelemetry.Trace.TracerProviderBuilderExtensions.AddProcessor(this OpenTelemetry.Trace.TracerProviderBuilder! tracerProviderBuilder, OpenTelemetry.BaseProcessor! processor) -> OpenTelemetry.Trace.TracerProviderBuilder! static OpenTelemetry.Trace.TracerProviderBuilderExtensions.Build(this OpenTelemetry.Trace.TracerProviderBuilder! tracerProviderBuilder) -> OpenTelemetry.Trace.TracerProvider? static OpenTelemetry.Trace.TracerProviderBuilderExtensions.SetErrorStatusOnException(this OpenTelemetry.Trace.TracerProviderBuilder! tracerProviderBuilder, bool enabled = true) -> OpenTelemetry.Trace.TracerProviderBuilder! diff --git a/src/OpenTelemetry/.publicApi/net462/PublicAPI.Unshipped.txt b/src/OpenTelemetry/.publicApi/net462/PublicAPI.Unshipped.txt index c029cfee537..1adc3849ac9 100644 --- a/src/OpenTelemetry/.publicApi/net462/PublicAPI.Unshipped.txt +++ b/src/OpenTelemetry/.publicApi/net462/PublicAPI.Unshipped.txt @@ -30,6 +30,15 @@ OpenTelemetry.Logs.LogRecord.TraceFlags.set -> void OpenTelemetry.Logs.LogRecord.TraceId.set -> void OpenTelemetry.Logs.LogRecord.TraceState.set -> void OpenTelemetry.Logs.OpenTelemetryLoggerOptions.ConfigureResource(System.Action! configure) -> OpenTelemetry.Logs.OpenTelemetryLoggerOptions! +OpenTelemetry.Metrics.HistogramConfiguration +OpenTelemetry.Metrics.HistogramConfiguration.HistogramConfiguration() -> void +OpenTelemetry.Metrics.HistogramConfiguration.RecordMinMax.get -> bool +OpenTelemetry.Metrics.HistogramConfiguration.RecordMinMax.set -> void +OpenTelemetry.Metrics.MetricPoint.GetHistogramMax() -> double +OpenTelemetry.Metrics.MetricPoint.GetHistogramMin() -> double +OpenTelemetry.Metrics.MetricPoint.HasMinMax() -> bool +OpenTelemetry.Resources.ResourceBuilder.AddDetector(System.Func! resourceDetectorFactory) -> OpenTelemetry.Resources.ResourceBuilder! +OpenTelemetry.Trace.BatchExportActivityProcessorOptions.BatchExportActivityProcessorOptions(Microsoft.Extensions.Configuration.IConfiguration! configuration) -> void OpenTelemetry.Logs.OpenTelemetryLoggerOptions.IncludeState.get -> bool OpenTelemetry.Logs.OpenTelemetryLoggerOptions.IncludeState.set -> void OpenTelemetry.Logs.OpenTelemetryLoggerOptions.IncludeTraceState.get -> bool @@ -70,9 +79,9 @@ static OpenTelemetry.Metrics.MeterProviderBuilderExtensions.ConfigureServices(th static OpenTelemetry.Sdk.CreateLoggerProviderBuilder() -> OpenTelemetry.Logs.LoggerProviderBuilder! static OpenTelemetry.Trace.TracerProviderBuilderExtensions.AddExporter(this OpenTelemetry.Trace.TracerProviderBuilder! tracerProviderBuilder, OpenTelemetry.ExportProcessorType exportProcessorType, OpenTelemetry.BaseExporter! exporter, string? name, System.Action? configure) -> OpenTelemetry.Trace.TracerProviderBuilder! static OpenTelemetry.Trace.TracerProviderBuilderExtensions.AddExporter(this OpenTelemetry.Trace.TracerProviderBuilder! tracerProviderBuilder, OpenTelemetry.ExportProcessorType exportProcessorType, string? name, System.Action? configure) -> OpenTelemetry.Trace.TracerProviderBuilder! -~OpenTelemetry.Trace.SamplingResult.TraceStateString.get -> string -~OpenTelemetry.Trace.SamplingResult.SamplingResult(OpenTelemetry.Trace.SamplingDecision decision, string traceStateString) -> void -~OpenTelemetry.Trace.SamplingResult.SamplingResult(OpenTelemetry.Trace.SamplingDecision decision, System.Collections.Generic.IEnumerable> attributes, string traceStateString) -> void +OpenTelemetry.Trace.SamplingResult.TraceStateString.get -> string? +OpenTelemetry.Trace.SamplingResult.SamplingResult(OpenTelemetry.Trace.SamplingDecision decision, string! traceStateString) -> void +OpenTelemetry.Trace.SamplingResult.SamplingResult(OpenTelemetry.Trace.SamplingDecision decision, System.Collections.Generic.IEnumerable>? attributes, string? traceStateString) -> void *REMOVED*static Microsoft.Extensions.Logging.OpenTelemetryLoggingExtensions.AddOpenTelemetry(this Microsoft.Extensions.Logging.ILoggingBuilder! builder, System.Action? configure = null) -> Microsoft.Extensions.Logging.ILoggingBuilder! OpenTelemetry.Trace.ExportActivityProcessorOptions OpenTelemetry.Trace.ExportActivityProcessorOptions.BatchExportProcessorOptions.get -> OpenTelemetry.Trace.BatchExportActivityProcessorOptions! diff --git a/src/OpenTelemetry/.publicApi/net6.0/PublicAPI.Shipped.txt b/src/OpenTelemetry/.publicApi/net6.0/PublicAPI.Shipped.txt index e4585058956..a601fdd2439 100644 --- a/src/OpenTelemetry/.publicApi/net6.0/PublicAPI.Shipped.txt +++ b/src/OpenTelemetry/.publicApi/net6.0/PublicAPI.Shipped.txt @@ -10,10 +10,10 @@ OpenTelemetry.Batch OpenTelemetry.Batch.Batch(T![]! items, int count) -> void OpenTelemetry.Batch.Enumerator.Current.get -> T! ~OpenTelemetry.Batch.GetEnumerator() -> OpenTelemetry.Batch.Enumerator -~OpenTelemetry.BatchActivityExportProcessor.BatchActivityExportProcessor(OpenTelemetry.BaseExporter exporter, int maxQueueSize = 2048, int scheduledDelayMilliseconds = 5000, int exporterTimeoutMilliseconds = 30000, int maxExportBatchSize = 512) -> void +OpenTelemetry.BatchActivityExportProcessor.BatchActivityExportProcessor(OpenTelemetry.BaseExporter! exporter, int maxQueueSize = 2048, int scheduledDelayMilliseconds = 5000, int exporterTimeoutMilliseconds = 30000, int maxExportBatchSize = 512) -> void OpenTelemetry.BatchExportProcessor OpenTelemetry.BatchExportProcessor.BatchExportProcessor(OpenTelemetry.BaseExporter! exporter, int maxQueueSize = 2048, int scheduledDelayMilliseconds = 5000, int exporterTimeoutMilliseconds = 30000, int maxExportBatchSize = 512) -> void -~OpenTelemetry.BatchExportProcessorOptions +OpenTelemetry.BatchExportProcessorOptions OpenTelemetry.CompositeProcessor.AddProcessor(OpenTelemetry.BaseProcessor! processor) -> OpenTelemetry.CompositeProcessor! OpenTelemetry.CompositeProcessor.CompositeProcessor(System.Collections.Generic.IEnumerable!>! processors) -> void ~OpenTelemetry.Metrics.BaseExportingMetricReader.BaseExportingMetricReader(OpenTelemetry.BaseExporter exporter) -> void @@ -37,37 +37,37 @@ OpenTelemetry.Metrics.MetricReaderOptions.PeriodicExportingMetricReaderOptions.s ~OpenTelemetry.Metrics.MetricStreamConfiguration.TagKeys.get -> string[] ~OpenTelemetry.Metrics.MetricStreamConfiguration.TagKeys.set -> void ~OpenTelemetry.Metrics.PeriodicExportingMetricReader.PeriodicExportingMetricReader(OpenTelemetry.BaseExporter exporter, int exportIntervalMilliseconds = 60000, int exportTimeoutMilliseconds = 30000) -> void -~OpenTelemetry.ReadOnlyTagCollection.Enumerator.Current.get -> System.Collections.Generic.KeyValuePair -~OpenTelemetry.Resources.IResourceDetector.Detect() -> OpenTelemetry.Resources.Resource -~OpenTelemetry.Resources.Resource.Attributes.get -> System.Collections.Generic.IEnumerable> -~OpenTelemetry.Resources.Resource.Merge(OpenTelemetry.Resources.Resource other) -> OpenTelemetry.Resources.Resource -~OpenTelemetry.Resources.Resource.Resource(System.Collections.Generic.IEnumerable> attributes) -> void -~OpenTelemetry.Resources.ResourceBuilder.AddDetector(OpenTelemetry.Resources.IResourceDetector resourceDetector) -> OpenTelemetry.Resources.ResourceBuilder -~OpenTelemetry.Resources.ResourceBuilder.Build() -> OpenTelemetry.Resources.Resource -~OpenTelemetry.Resources.ResourceBuilder.Clear() -> OpenTelemetry.Resources.ResourceBuilder -~OpenTelemetry.SimpleActivityExportProcessor.SimpleActivityExportProcessor(OpenTelemetry.BaseExporter exporter) -> void +OpenTelemetry.ReadOnlyTagCollection.Enumerator.Current.get -> System.Collections.Generic.KeyValuePair +OpenTelemetry.Resources.IResourceDetector.Detect() -> OpenTelemetry.Resources.Resource! +OpenTelemetry.Resources.Resource.Attributes.get -> System.Collections.Generic.IEnumerable>! +OpenTelemetry.Resources.Resource.Merge(OpenTelemetry.Resources.Resource! other) -> OpenTelemetry.Resources.Resource! +OpenTelemetry.Resources.Resource.Resource(System.Collections.Generic.IEnumerable>! attributes) -> void +OpenTelemetry.Resources.ResourceBuilder.AddDetector(OpenTelemetry.Resources.IResourceDetector! resourceDetector) -> OpenTelemetry.Resources.ResourceBuilder! +OpenTelemetry.Resources.ResourceBuilder.Build() -> OpenTelemetry.Resources.Resource! +OpenTelemetry.Resources.ResourceBuilder.Clear() -> OpenTelemetry.Resources.ResourceBuilder! +OpenTelemetry.SimpleActivityExportProcessor.SimpleActivityExportProcessor(OpenTelemetry.BaseExporter! exporter) -> void OpenTelemetry.SimpleExportProcessor OpenTelemetry.SimpleExportProcessor.SimpleExportProcessor(OpenTelemetry.BaseExporter! exporter) -> void -~OpenTelemetry.Trace.ParentBasedSampler.ParentBasedSampler(OpenTelemetry.Trace.Sampler rootSampler) -> void -~OpenTelemetry.Trace.ParentBasedSampler.ParentBasedSampler(OpenTelemetry.Trace.Sampler rootSampler, OpenTelemetry.Trace.Sampler remoteParentSampled = null, OpenTelemetry.Trace.Sampler remoteParentNotSampled = null, OpenTelemetry.Trace.Sampler localParentSampled = null, OpenTelemetry.Trace.Sampler localParentNotSampled = null) -> void -~OpenTelemetry.Trace.Sampler.Description.get -> string -~OpenTelemetry.Trace.Sampler.Description.set -> void -~OpenTelemetry.Trace.SamplingParameters.Links.get -> System.Collections.Generic.IEnumerable -~OpenTelemetry.Trace.SamplingParameters.Name.get -> string -~OpenTelemetry.Trace.SamplingParameters.SamplingParameters(System.Diagnostics.ActivityContext parentContext, System.Diagnostics.ActivityTraceId traceId, string name, System.Diagnostics.ActivityKind kind, System.Collections.Generic.IEnumerable> tags = null, System.Collections.Generic.IEnumerable links = null) -> void -~OpenTelemetry.Trace.SamplingParameters.Tags.get -> System.Collections.Generic.IEnumerable> -~OpenTelemetry.Trace.SamplingResult.Attributes.get -> System.Collections.Generic.IEnumerable> -~OpenTelemetry.Trace.SamplingResult.SamplingResult(OpenTelemetry.Trace.SamplingDecision decision, System.Collections.Generic.IEnumerable> attributes) -> void +OpenTelemetry.Trace.ParentBasedSampler.ParentBasedSampler(OpenTelemetry.Trace.Sampler! rootSampler) -> void +OpenTelemetry.Trace.ParentBasedSampler.ParentBasedSampler(OpenTelemetry.Trace.Sampler! rootSampler, OpenTelemetry.Trace.Sampler? remoteParentSampled = null, OpenTelemetry.Trace.Sampler? remoteParentNotSampled = null, OpenTelemetry.Trace.Sampler? localParentSampled = null, OpenTelemetry.Trace.Sampler? localParentNotSampled = null) -> void +OpenTelemetry.Trace.Sampler.Description.get -> string! +OpenTelemetry.Trace.Sampler.Description.set -> void +OpenTelemetry.Trace.SamplingParameters.Links.get -> System.Collections.Generic.IEnumerable? +OpenTelemetry.Trace.SamplingParameters.Name.get -> string! +OpenTelemetry.Trace.SamplingParameters.SamplingParameters(System.Diagnostics.ActivityContext parentContext, System.Diagnostics.ActivityTraceId traceId, string! name, System.Diagnostics.ActivityKind kind, System.Collections.Generic.IEnumerable>? tags = null, System.Collections.Generic.IEnumerable? links = null) -> void +OpenTelemetry.Trace.SamplingParameters.Tags.get -> System.Collections.Generic.IEnumerable>? +OpenTelemetry.Trace.SamplingResult.Attributes.get -> System.Collections.Generic.IEnumerable>! +OpenTelemetry.Trace.SamplingResult.SamplingResult(OpenTelemetry.Trace.SamplingDecision decision, System.Collections.Generic.IEnumerable>! attributes) -> void OpenTelemetry.Trace.TracerProviderBuilderBase.AddInstrumentation(string! instrumentationName, string! instrumentationVersion, System.Func! instrumentationFactory) -> OpenTelemetry.Trace.TracerProviderBuilder! OpenTelemetry.Trace.TracerProviderBuilderBase.Build() -> OpenTelemetry.Trace.TracerProvider! override OpenTelemetry.BaseExportProcessor.OnEnd(T! data) -> void -~override OpenTelemetry.BatchActivityExportProcessor.OnEnd(System.Diagnostics.Activity data) -> void +override OpenTelemetry.BatchActivityExportProcessor.OnEnd(System.Diagnostics.Activity! data) -> void override OpenTelemetry.BatchExportProcessor.OnExport(T! data) -> void ~override OpenTelemetry.Metrics.MeterProviderBuilderBase.AddInstrumentation(System.Func! instrumentationFactory) -> OpenTelemetry.Metrics.MeterProviderBuilder! override OpenTelemetry.Metrics.MeterProviderBuilderBase.AddMeter(params string![]! names) -> OpenTelemetry.Metrics.MeterProviderBuilder! -~override OpenTelemetry.SimpleActivityExportProcessor.OnEnd(System.Diagnostics.Activity data) -> void +override OpenTelemetry.SimpleActivityExportProcessor.OnEnd(System.Diagnostics.Activity! data) -> void override OpenTelemetry.SimpleExportProcessor.OnExport(T! data) -> void -~override OpenTelemetry.Trace.SamplingResult.Equals(object obj) -> bool +override OpenTelemetry.Trace.SamplingResult.Equals(object? obj) -> bool ~override OpenTelemetry.Trace.TracerProviderBuilderBase.AddInstrumentation(System.Func! instrumentationFactory) -> OpenTelemetry.Trace.TracerProviderBuilder! override OpenTelemetry.Trace.TracerProviderBuilderBase.AddLegacySource(string! operationName) -> OpenTelemetry.Trace.TracerProviderBuilder! override OpenTelemetry.Trace.TracerProviderBuilderBase.AddSource(params string![]! names) -> OpenTelemetry.Trace.TracerProviderBuilder! @@ -87,17 +87,17 @@ static OpenTelemetry.Metrics.MeterProviderBuilderExtensions.SetResourceBuilder(t ~static OpenTelemetry.Metrics.MetricStreamConfiguration.Drop.get -> OpenTelemetry.Metrics.MetricStreamConfiguration static OpenTelemetry.ProviderExtensions.GetDefaultResource(this OpenTelemetry.BaseProvider! baseProvider) -> OpenTelemetry.Resources.Resource! static OpenTelemetry.ProviderExtensions.GetResource(this OpenTelemetry.BaseProvider! baseProvider) -> OpenTelemetry.Resources.Resource! -~static OpenTelemetry.Resources.Resource.Empty.get -> OpenTelemetry.Resources.Resource -~static OpenTelemetry.Resources.ResourceBuilder.CreateDefault() -> OpenTelemetry.Resources.ResourceBuilder -~static OpenTelemetry.Resources.ResourceBuilder.CreateEmpty() -> OpenTelemetry.Resources.ResourceBuilder -~static OpenTelemetry.Resources.ResourceBuilderExtensions.AddAttributes(this OpenTelemetry.Resources.ResourceBuilder resourceBuilder, System.Collections.Generic.IEnumerable> attributes) -> OpenTelemetry.Resources.ResourceBuilder -~static OpenTelemetry.Resources.ResourceBuilderExtensions.AddEnvironmentVariableDetector(this OpenTelemetry.Resources.ResourceBuilder resourceBuilder) -> OpenTelemetry.Resources.ResourceBuilder -~static OpenTelemetry.Resources.ResourceBuilderExtensions.AddService(this OpenTelemetry.Resources.ResourceBuilder resourceBuilder, string serviceName, string serviceNamespace = null, string serviceVersion = null, bool autoGenerateServiceInstanceId = true, string serviceInstanceId = null) -> OpenTelemetry.Resources.ResourceBuilder -~static OpenTelemetry.Resources.ResourceBuilderExtensions.AddTelemetrySdk(this OpenTelemetry.Resources.ResourceBuilder resourceBuilder) -> OpenTelemetry.Resources.ResourceBuilder +static OpenTelemetry.Resources.Resource.Empty.get -> OpenTelemetry.Resources.Resource! +static OpenTelemetry.Resources.ResourceBuilder.CreateDefault() -> OpenTelemetry.Resources.ResourceBuilder! +static OpenTelemetry.Resources.ResourceBuilder.CreateEmpty() -> OpenTelemetry.Resources.ResourceBuilder! +static OpenTelemetry.Resources.ResourceBuilderExtensions.AddAttributes(this OpenTelemetry.Resources.ResourceBuilder! resourceBuilder, System.Collections.Generic.IEnumerable>! attributes) -> OpenTelemetry.Resources.ResourceBuilder! +static OpenTelemetry.Resources.ResourceBuilderExtensions.AddEnvironmentVariableDetector(this OpenTelemetry.Resources.ResourceBuilder! resourceBuilder) -> OpenTelemetry.Resources.ResourceBuilder! +static OpenTelemetry.Resources.ResourceBuilderExtensions.AddService(this OpenTelemetry.Resources.ResourceBuilder! resourceBuilder, string! serviceName, string? serviceNamespace = null, string? serviceVersion = null, bool autoGenerateServiceInstanceId = true, string? serviceInstanceId = null) -> OpenTelemetry.Resources.ResourceBuilder! +static OpenTelemetry.Resources.ResourceBuilderExtensions.AddTelemetrySdk(this OpenTelemetry.Resources.ResourceBuilder! resourceBuilder) -> OpenTelemetry.Resources.ResourceBuilder! static OpenTelemetry.Sdk.CreateMeterProviderBuilder() -> OpenTelemetry.Metrics.MeterProviderBuilder! static OpenTelemetry.Sdk.CreateTracerProviderBuilder() -> OpenTelemetry.Trace.TracerProviderBuilder! static OpenTelemetry.Sdk.SetDefaultTextMapPropagator(OpenTelemetry.Context.Propagation.TextMapPropagator! textMapPropagator) -> void -~static OpenTelemetry.SuppressInstrumentationScope.Begin(bool value = true) -> System.IDisposable +static OpenTelemetry.SuppressInstrumentationScope.Begin(bool value = true) -> System.IDisposable! static OpenTelemetry.Trace.TracerProviderBuilderExtensions.AddProcessor(this OpenTelemetry.Trace.TracerProviderBuilder! tracerProviderBuilder, OpenTelemetry.BaseProcessor! processor) -> OpenTelemetry.Trace.TracerProviderBuilder! static OpenTelemetry.Trace.TracerProviderBuilderExtensions.Build(this OpenTelemetry.Trace.TracerProviderBuilder! tracerProviderBuilder) -> OpenTelemetry.Trace.TracerProvider? static OpenTelemetry.Trace.TracerProviderBuilderExtensions.SetErrorStatusOnException(this OpenTelemetry.Trace.TracerProviderBuilder! tracerProviderBuilder, bool enabled = true) -> OpenTelemetry.Trace.TracerProviderBuilder! diff --git a/src/OpenTelemetry/.publicApi/net6.0/PublicAPI.Unshipped.txt b/src/OpenTelemetry/.publicApi/net6.0/PublicAPI.Unshipped.txt index c029cfee537..1adc3849ac9 100644 --- a/src/OpenTelemetry/.publicApi/net6.0/PublicAPI.Unshipped.txt +++ b/src/OpenTelemetry/.publicApi/net6.0/PublicAPI.Unshipped.txt @@ -30,6 +30,15 @@ OpenTelemetry.Logs.LogRecord.TraceFlags.set -> void OpenTelemetry.Logs.LogRecord.TraceId.set -> void OpenTelemetry.Logs.LogRecord.TraceState.set -> void OpenTelemetry.Logs.OpenTelemetryLoggerOptions.ConfigureResource(System.Action! configure) -> OpenTelemetry.Logs.OpenTelemetryLoggerOptions! +OpenTelemetry.Metrics.HistogramConfiguration +OpenTelemetry.Metrics.HistogramConfiguration.HistogramConfiguration() -> void +OpenTelemetry.Metrics.HistogramConfiguration.RecordMinMax.get -> bool +OpenTelemetry.Metrics.HistogramConfiguration.RecordMinMax.set -> void +OpenTelemetry.Metrics.MetricPoint.GetHistogramMax() -> double +OpenTelemetry.Metrics.MetricPoint.GetHistogramMin() -> double +OpenTelemetry.Metrics.MetricPoint.HasMinMax() -> bool +OpenTelemetry.Resources.ResourceBuilder.AddDetector(System.Func! resourceDetectorFactory) -> OpenTelemetry.Resources.ResourceBuilder! +OpenTelemetry.Trace.BatchExportActivityProcessorOptions.BatchExportActivityProcessorOptions(Microsoft.Extensions.Configuration.IConfiguration! configuration) -> void OpenTelemetry.Logs.OpenTelemetryLoggerOptions.IncludeState.get -> bool OpenTelemetry.Logs.OpenTelemetryLoggerOptions.IncludeState.set -> void OpenTelemetry.Logs.OpenTelemetryLoggerOptions.IncludeTraceState.get -> bool @@ -70,9 +79,9 @@ static OpenTelemetry.Metrics.MeterProviderBuilderExtensions.ConfigureServices(th static OpenTelemetry.Sdk.CreateLoggerProviderBuilder() -> OpenTelemetry.Logs.LoggerProviderBuilder! static OpenTelemetry.Trace.TracerProviderBuilderExtensions.AddExporter(this OpenTelemetry.Trace.TracerProviderBuilder! tracerProviderBuilder, OpenTelemetry.ExportProcessorType exportProcessorType, OpenTelemetry.BaseExporter! exporter, string? name, System.Action? configure) -> OpenTelemetry.Trace.TracerProviderBuilder! static OpenTelemetry.Trace.TracerProviderBuilderExtensions.AddExporter(this OpenTelemetry.Trace.TracerProviderBuilder! tracerProviderBuilder, OpenTelemetry.ExportProcessorType exportProcessorType, string? name, System.Action? configure) -> OpenTelemetry.Trace.TracerProviderBuilder! -~OpenTelemetry.Trace.SamplingResult.TraceStateString.get -> string -~OpenTelemetry.Trace.SamplingResult.SamplingResult(OpenTelemetry.Trace.SamplingDecision decision, string traceStateString) -> void -~OpenTelemetry.Trace.SamplingResult.SamplingResult(OpenTelemetry.Trace.SamplingDecision decision, System.Collections.Generic.IEnumerable> attributes, string traceStateString) -> void +OpenTelemetry.Trace.SamplingResult.TraceStateString.get -> string? +OpenTelemetry.Trace.SamplingResult.SamplingResult(OpenTelemetry.Trace.SamplingDecision decision, string! traceStateString) -> void +OpenTelemetry.Trace.SamplingResult.SamplingResult(OpenTelemetry.Trace.SamplingDecision decision, System.Collections.Generic.IEnumerable>? attributes, string? traceStateString) -> void *REMOVED*static Microsoft.Extensions.Logging.OpenTelemetryLoggingExtensions.AddOpenTelemetry(this Microsoft.Extensions.Logging.ILoggingBuilder! builder, System.Action? configure = null) -> Microsoft.Extensions.Logging.ILoggingBuilder! OpenTelemetry.Trace.ExportActivityProcessorOptions OpenTelemetry.Trace.ExportActivityProcessorOptions.BatchExportProcessorOptions.get -> OpenTelemetry.Trace.BatchExportActivityProcessorOptions! diff --git a/src/OpenTelemetry/.publicApi/netstandard2.0/PublicAPI.Shipped.txt b/src/OpenTelemetry/.publicApi/netstandard2.0/PublicAPI.Shipped.txt index e4585058956..a601fdd2439 100644 --- a/src/OpenTelemetry/.publicApi/netstandard2.0/PublicAPI.Shipped.txt +++ b/src/OpenTelemetry/.publicApi/netstandard2.0/PublicAPI.Shipped.txt @@ -10,10 +10,10 @@ OpenTelemetry.Batch OpenTelemetry.Batch.Batch(T![]! items, int count) -> void OpenTelemetry.Batch.Enumerator.Current.get -> T! ~OpenTelemetry.Batch.GetEnumerator() -> OpenTelemetry.Batch.Enumerator -~OpenTelemetry.BatchActivityExportProcessor.BatchActivityExportProcessor(OpenTelemetry.BaseExporter exporter, int maxQueueSize = 2048, int scheduledDelayMilliseconds = 5000, int exporterTimeoutMilliseconds = 30000, int maxExportBatchSize = 512) -> void +OpenTelemetry.BatchActivityExportProcessor.BatchActivityExportProcessor(OpenTelemetry.BaseExporter! exporter, int maxQueueSize = 2048, int scheduledDelayMilliseconds = 5000, int exporterTimeoutMilliseconds = 30000, int maxExportBatchSize = 512) -> void OpenTelemetry.BatchExportProcessor OpenTelemetry.BatchExportProcessor.BatchExportProcessor(OpenTelemetry.BaseExporter! exporter, int maxQueueSize = 2048, int scheduledDelayMilliseconds = 5000, int exporterTimeoutMilliseconds = 30000, int maxExportBatchSize = 512) -> void -~OpenTelemetry.BatchExportProcessorOptions +OpenTelemetry.BatchExportProcessorOptions OpenTelemetry.CompositeProcessor.AddProcessor(OpenTelemetry.BaseProcessor! processor) -> OpenTelemetry.CompositeProcessor! OpenTelemetry.CompositeProcessor.CompositeProcessor(System.Collections.Generic.IEnumerable!>! processors) -> void ~OpenTelemetry.Metrics.BaseExportingMetricReader.BaseExportingMetricReader(OpenTelemetry.BaseExporter exporter) -> void @@ -37,37 +37,37 @@ OpenTelemetry.Metrics.MetricReaderOptions.PeriodicExportingMetricReaderOptions.s ~OpenTelemetry.Metrics.MetricStreamConfiguration.TagKeys.get -> string[] ~OpenTelemetry.Metrics.MetricStreamConfiguration.TagKeys.set -> void ~OpenTelemetry.Metrics.PeriodicExportingMetricReader.PeriodicExportingMetricReader(OpenTelemetry.BaseExporter exporter, int exportIntervalMilliseconds = 60000, int exportTimeoutMilliseconds = 30000) -> void -~OpenTelemetry.ReadOnlyTagCollection.Enumerator.Current.get -> System.Collections.Generic.KeyValuePair -~OpenTelemetry.Resources.IResourceDetector.Detect() -> OpenTelemetry.Resources.Resource -~OpenTelemetry.Resources.Resource.Attributes.get -> System.Collections.Generic.IEnumerable> -~OpenTelemetry.Resources.Resource.Merge(OpenTelemetry.Resources.Resource other) -> OpenTelemetry.Resources.Resource -~OpenTelemetry.Resources.Resource.Resource(System.Collections.Generic.IEnumerable> attributes) -> void -~OpenTelemetry.Resources.ResourceBuilder.AddDetector(OpenTelemetry.Resources.IResourceDetector resourceDetector) -> OpenTelemetry.Resources.ResourceBuilder -~OpenTelemetry.Resources.ResourceBuilder.Build() -> OpenTelemetry.Resources.Resource -~OpenTelemetry.Resources.ResourceBuilder.Clear() -> OpenTelemetry.Resources.ResourceBuilder -~OpenTelemetry.SimpleActivityExportProcessor.SimpleActivityExportProcessor(OpenTelemetry.BaseExporter exporter) -> void +OpenTelemetry.ReadOnlyTagCollection.Enumerator.Current.get -> System.Collections.Generic.KeyValuePair +OpenTelemetry.Resources.IResourceDetector.Detect() -> OpenTelemetry.Resources.Resource! +OpenTelemetry.Resources.Resource.Attributes.get -> System.Collections.Generic.IEnumerable>! +OpenTelemetry.Resources.Resource.Merge(OpenTelemetry.Resources.Resource! other) -> OpenTelemetry.Resources.Resource! +OpenTelemetry.Resources.Resource.Resource(System.Collections.Generic.IEnumerable>! attributes) -> void +OpenTelemetry.Resources.ResourceBuilder.AddDetector(OpenTelemetry.Resources.IResourceDetector! resourceDetector) -> OpenTelemetry.Resources.ResourceBuilder! +OpenTelemetry.Resources.ResourceBuilder.Build() -> OpenTelemetry.Resources.Resource! +OpenTelemetry.Resources.ResourceBuilder.Clear() -> OpenTelemetry.Resources.ResourceBuilder! +OpenTelemetry.SimpleActivityExportProcessor.SimpleActivityExportProcessor(OpenTelemetry.BaseExporter! exporter) -> void OpenTelemetry.SimpleExportProcessor OpenTelemetry.SimpleExportProcessor.SimpleExportProcessor(OpenTelemetry.BaseExporter! exporter) -> void -~OpenTelemetry.Trace.ParentBasedSampler.ParentBasedSampler(OpenTelemetry.Trace.Sampler rootSampler) -> void -~OpenTelemetry.Trace.ParentBasedSampler.ParentBasedSampler(OpenTelemetry.Trace.Sampler rootSampler, OpenTelemetry.Trace.Sampler remoteParentSampled = null, OpenTelemetry.Trace.Sampler remoteParentNotSampled = null, OpenTelemetry.Trace.Sampler localParentSampled = null, OpenTelemetry.Trace.Sampler localParentNotSampled = null) -> void -~OpenTelemetry.Trace.Sampler.Description.get -> string -~OpenTelemetry.Trace.Sampler.Description.set -> void -~OpenTelemetry.Trace.SamplingParameters.Links.get -> System.Collections.Generic.IEnumerable -~OpenTelemetry.Trace.SamplingParameters.Name.get -> string -~OpenTelemetry.Trace.SamplingParameters.SamplingParameters(System.Diagnostics.ActivityContext parentContext, System.Diagnostics.ActivityTraceId traceId, string name, System.Diagnostics.ActivityKind kind, System.Collections.Generic.IEnumerable> tags = null, System.Collections.Generic.IEnumerable links = null) -> void -~OpenTelemetry.Trace.SamplingParameters.Tags.get -> System.Collections.Generic.IEnumerable> -~OpenTelemetry.Trace.SamplingResult.Attributes.get -> System.Collections.Generic.IEnumerable> -~OpenTelemetry.Trace.SamplingResult.SamplingResult(OpenTelemetry.Trace.SamplingDecision decision, System.Collections.Generic.IEnumerable> attributes) -> void +OpenTelemetry.Trace.ParentBasedSampler.ParentBasedSampler(OpenTelemetry.Trace.Sampler! rootSampler) -> void +OpenTelemetry.Trace.ParentBasedSampler.ParentBasedSampler(OpenTelemetry.Trace.Sampler! rootSampler, OpenTelemetry.Trace.Sampler? remoteParentSampled = null, OpenTelemetry.Trace.Sampler? remoteParentNotSampled = null, OpenTelemetry.Trace.Sampler? localParentSampled = null, OpenTelemetry.Trace.Sampler? localParentNotSampled = null) -> void +OpenTelemetry.Trace.Sampler.Description.get -> string! +OpenTelemetry.Trace.Sampler.Description.set -> void +OpenTelemetry.Trace.SamplingParameters.Links.get -> System.Collections.Generic.IEnumerable? +OpenTelemetry.Trace.SamplingParameters.Name.get -> string! +OpenTelemetry.Trace.SamplingParameters.SamplingParameters(System.Diagnostics.ActivityContext parentContext, System.Diagnostics.ActivityTraceId traceId, string! name, System.Diagnostics.ActivityKind kind, System.Collections.Generic.IEnumerable>? tags = null, System.Collections.Generic.IEnumerable? links = null) -> void +OpenTelemetry.Trace.SamplingParameters.Tags.get -> System.Collections.Generic.IEnumerable>? +OpenTelemetry.Trace.SamplingResult.Attributes.get -> System.Collections.Generic.IEnumerable>! +OpenTelemetry.Trace.SamplingResult.SamplingResult(OpenTelemetry.Trace.SamplingDecision decision, System.Collections.Generic.IEnumerable>! attributes) -> void OpenTelemetry.Trace.TracerProviderBuilderBase.AddInstrumentation(string! instrumentationName, string! instrumentationVersion, System.Func! instrumentationFactory) -> OpenTelemetry.Trace.TracerProviderBuilder! OpenTelemetry.Trace.TracerProviderBuilderBase.Build() -> OpenTelemetry.Trace.TracerProvider! override OpenTelemetry.BaseExportProcessor.OnEnd(T! data) -> void -~override OpenTelemetry.BatchActivityExportProcessor.OnEnd(System.Diagnostics.Activity data) -> void +override OpenTelemetry.BatchActivityExportProcessor.OnEnd(System.Diagnostics.Activity! data) -> void override OpenTelemetry.BatchExportProcessor.OnExport(T! data) -> void ~override OpenTelemetry.Metrics.MeterProviderBuilderBase.AddInstrumentation(System.Func! instrumentationFactory) -> OpenTelemetry.Metrics.MeterProviderBuilder! override OpenTelemetry.Metrics.MeterProviderBuilderBase.AddMeter(params string![]! names) -> OpenTelemetry.Metrics.MeterProviderBuilder! -~override OpenTelemetry.SimpleActivityExportProcessor.OnEnd(System.Diagnostics.Activity data) -> void +override OpenTelemetry.SimpleActivityExportProcessor.OnEnd(System.Diagnostics.Activity! data) -> void override OpenTelemetry.SimpleExportProcessor.OnExport(T! data) -> void -~override OpenTelemetry.Trace.SamplingResult.Equals(object obj) -> bool +override OpenTelemetry.Trace.SamplingResult.Equals(object? obj) -> bool ~override OpenTelemetry.Trace.TracerProviderBuilderBase.AddInstrumentation(System.Func! instrumentationFactory) -> OpenTelemetry.Trace.TracerProviderBuilder! override OpenTelemetry.Trace.TracerProviderBuilderBase.AddLegacySource(string! operationName) -> OpenTelemetry.Trace.TracerProviderBuilder! override OpenTelemetry.Trace.TracerProviderBuilderBase.AddSource(params string![]! names) -> OpenTelemetry.Trace.TracerProviderBuilder! @@ -87,17 +87,17 @@ static OpenTelemetry.Metrics.MeterProviderBuilderExtensions.SetResourceBuilder(t ~static OpenTelemetry.Metrics.MetricStreamConfiguration.Drop.get -> OpenTelemetry.Metrics.MetricStreamConfiguration static OpenTelemetry.ProviderExtensions.GetDefaultResource(this OpenTelemetry.BaseProvider! baseProvider) -> OpenTelemetry.Resources.Resource! static OpenTelemetry.ProviderExtensions.GetResource(this OpenTelemetry.BaseProvider! baseProvider) -> OpenTelemetry.Resources.Resource! -~static OpenTelemetry.Resources.Resource.Empty.get -> OpenTelemetry.Resources.Resource -~static OpenTelemetry.Resources.ResourceBuilder.CreateDefault() -> OpenTelemetry.Resources.ResourceBuilder -~static OpenTelemetry.Resources.ResourceBuilder.CreateEmpty() -> OpenTelemetry.Resources.ResourceBuilder -~static OpenTelemetry.Resources.ResourceBuilderExtensions.AddAttributes(this OpenTelemetry.Resources.ResourceBuilder resourceBuilder, System.Collections.Generic.IEnumerable> attributes) -> OpenTelemetry.Resources.ResourceBuilder -~static OpenTelemetry.Resources.ResourceBuilderExtensions.AddEnvironmentVariableDetector(this OpenTelemetry.Resources.ResourceBuilder resourceBuilder) -> OpenTelemetry.Resources.ResourceBuilder -~static OpenTelemetry.Resources.ResourceBuilderExtensions.AddService(this OpenTelemetry.Resources.ResourceBuilder resourceBuilder, string serviceName, string serviceNamespace = null, string serviceVersion = null, bool autoGenerateServiceInstanceId = true, string serviceInstanceId = null) -> OpenTelemetry.Resources.ResourceBuilder -~static OpenTelemetry.Resources.ResourceBuilderExtensions.AddTelemetrySdk(this OpenTelemetry.Resources.ResourceBuilder resourceBuilder) -> OpenTelemetry.Resources.ResourceBuilder +static OpenTelemetry.Resources.Resource.Empty.get -> OpenTelemetry.Resources.Resource! +static OpenTelemetry.Resources.ResourceBuilder.CreateDefault() -> OpenTelemetry.Resources.ResourceBuilder! +static OpenTelemetry.Resources.ResourceBuilder.CreateEmpty() -> OpenTelemetry.Resources.ResourceBuilder! +static OpenTelemetry.Resources.ResourceBuilderExtensions.AddAttributes(this OpenTelemetry.Resources.ResourceBuilder! resourceBuilder, System.Collections.Generic.IEnumerable>! attributes) -> OpenTelemetry.Resources.ResourceBuilder! +static OpenTelemetry.Resources.ResourceBuilderExtensions.AddEnvironmentVariableDetector(this OpenTelemetry.Resources.ResourceBuilder! resourceBuilder) -> OpenTelemetry.Resources.ResourceBuilder! +static OpenTelemetry.Resources.ResourceBuilderExtensions.AddService(this OpenTelemetry.Resources.ResourceBuilder! resourceBuilder, string! serviceName, string? serviceNamespace = null, string? serviceVersion = null, bool autoGenerateServiceInstanceId = true, string? serviceInstanceId = null) -> OpenTelemetry.Resources.ResourceBuilder! +static OpenTelemetry.Resources.ResourceBuilderExtensions.AddTelemetrySdk(this OpenTelemetry.Resources.ResourceBuilder! resourceBuilder) -> OpenTelemetry.Resources.ResourceBuilder! static OpenTelemetry.Sdk.CreateMeterProviderBuilder() -> OpenTelemetry.Metrics.MeterProviderBuilder! static OpenTelemetry.Sdk.CreateTracerProviderBuilder() -> OpenTelemetry.Trace.TracerProviderBuilder! static OpenTelemetry.Sdk.SetDefaultTextMapPropagator(OpenTelemetry.Context.Propagation.TextMapPropagator! textMapPropagator) -> void -~static OpenTelemetry.SuppressInstrumentationScope.Begin(bool value = true) -> System.IDisposable +static OpenTelemetry.SuppressInstrumentationScope.Begin(bool value = true) -> System.IDisposable! static OpenTelemetry.Trace.TracerProviderBuilderExtensions.AddProcessor(this OpenTelemetry.Trace.TracerProviderBuilder! tracerProviderBuilder, OpenTelemetry.BaseProcessor! processor) -> OpenTelemetry.Trace.TracerProviderBuilder! static OpenTelemetry.Trace.TracerProviderBuilderExtensions.Build(this OpenTelemetry.Trace.TracerProviderBuilder! tracerProviderBuilder) -> OpenTelemetry.Trace.TracerProvider? static OpenTelemetry.Trace.TracerProviderBuilderExtensions.SetErrorStatusOnException(this OpenTelemetry.Trace.TracerProviderBuilder! tracerProviderBuilder, bool enabled = true) -> OpenTelemetry.Trace.TracerProviderBuilder! diff --git a/src/OpenTelemetry/.publicApi/netstandard2.0/PublicAPI.Unshipped.txt b/src/OpenTelemetry/.publicApi/netstandard2.0/PublicAPI.Unshipped.txt index c029cfee537..1adc3849ac9 100644 --- a/src/OpenTelemetry/.publicApi/netstandard2.0/PublicAPI.Unshipped.txt +++ b/src/OpenTelemetry/.publicApi/netstandard2.0/PublicAPI.Unshipped.txt @@ -30,6 +30,15 @@ OpenTelemetry.Logs.LogRecord.TraceFlags.set -> void OpenTelemetry.Logs.LogRecord.TraceId.set -> void OpenTelemetry.Logs.LogRecord.TraceState.set -> void OpenTelemetry.Logs.OpenTelemetryLoggerOptions.ConfigureResource(System.Action! configure) -> OpenTelemetry.Logs.OpenTelemetryLoggerOptions! +OpenTelemetry.Metrics.HistogramConfiguration +OpenTelemetry.Metrics.HistogramConfiguration.HistogramConfiguration() -> void +OpenTelemetry.Metrics.HistogramConfiguration.RecordMinMax.get -> bool +OpenTelemetry.Metrics.HistogramConfiguration.RecordMinMax.set -> void +OpenTelemetry.Metrics.MetricPoint.GetHistogramMax() -> double +OpenTelemetry.Metrics.MetricPoint.GetHistogramMin() -> double +OpenTelemetry.Metrics.MetricPoint.HasMinMax() -> bool +OpenTelemetry.Resources.ResourceBuilder.AddDetector(System.Func! resourceDetectorFactory) -> OpenTelemetry.Resources.ResourceBuilder! +OpenTelemetry.Trace.BatchExportActivityProcessorOptions.BatchExportActivityProcessorOptions(Microsoft.Extensions.Configuration.IConfiguration! configuration) -> void OpenTelemetry.Logs.OpenTelemetryLoggerOptions.IncludeState.get -> bool OpenTelemetry.Logs.OpenTelemetryLoggerOptions.IncludeState.set -> void OpenTelemetry.Logs.OpenTelemetryLoggerOptions.IncludeTraceState.get -> bool @@ -70,9 +79,9 @@ static OpenTelemetry.Metrics.MeterProviderBuilderExtensions.ConfigureServices(th static OpenTelemetry.Sdk.CreateLoggerProviderBuilder() -> OpenTelemetry.Logs.LoggerProviderBuilder! static OpenTelemetry.Trace.TracerProviderBuilderExtensions.AddExporter(this OpenTelemetry.Trace.TracerProviderBuilder! tracerProviderBuilder, OpenTelemetry.ExportProcessorType exportProcessorType, OpenTelemetry.BaseExporter! exporter, string? name, System.Action? configure) -> OpenTelemetry.Trace.TracerProviderBuilder! static OpenTelemetry.Trace.TracerProviderBuilderExtensions.AddExporter(this OpenTelemetry.Trace.TracerProviderBuilder! tracerProviderBuilder, OpenTelemetry.ExportProcessorType exportProcessorType, string? name, System.Action? configure) -> OpenTelemetry.Trace.TracerProviderBuilder! -~OpenTelemetry.Trace.SamplingResult.TraceStateString.get -> string -~OpenTelemetry.Trace.SamplingResult.SamplingResult(OpenTelemetry.Trace.SamplingDecision decision, string traceStateString) -> void -~OpenTelemetry.Trace.SamplingResult.SamplingResult(OpenTelemetry.Trace.SamplingDecision decision, System.Collections.Generic.IEnumerable> attributes, string traceStateString) -> void +OpenTelemetry.Trace.SamplingResult.TraceStateString.get -> string? +OpenTelemetry.Trace.SamplingResult.SamplingResult(OpenTelemetry.Trace.SamplingDecision decision, string! traceStateString) -> void +OpenTelemetry.Trace.SamplingResult.SamplingResult(OpenTelemetry.Trace.SamplingDecision decision, System.Collections.Generic.IEnumerable>? attributes, string? traceStateString) -> void *REMOVED*static Microsoft.Extensions.Logging.OpenTelemetryLoggingExtensions.AddOpenTelemetry(this Microsoft.Extensions.Logging.ILoggingBuilder! builder, System.Action? configure = null) -> Microsoft.Extensions.Logging.ILoggingBuilder! OpenTelemetry.Trace.ExportActivityProcessorOptions OpenTelemetry.Trace.ExportActivityProcessorOptions.BatchExportProcessorOptions.get -> OpenTelemetry.Trace.BatchExportActivityProcessorOptions! diff --git a/src/OpenTelemetry/.publicApi/netstandard2.1/PublicAPI.Shipped.txt b/src/OpenTelemetry/.publicApi/netstandard2.1/PublicAPI.Shipped.txt index e4585058956..a601fdd2439 100644 --- a/src/OpenTelemetry/.publicApi/netstandard2.1/PublicAPI.Shipped.txt +++ b/src/OpenTelemetry/.publicApi/netstandard2.1/PublicAPI.Shipped.txt @@ -10,10 +10,10 @@ OpenTelemetry.Batch OpenTelemetry.Batch.Batch(T![]! items, int count) -> void OpenTelemetry.Batch.Enumerator.Current.get -> T! ~OpenTelemetry.Batch.GetEnumerator() -> OpenTelemetry.Batch.Enumerator -~OpenTelemetry.BatchActivityExportProcessor.BatchActivityExportProcessor(OpenTelemetry.BaseExporter exporter, int maxQueueSize = 2048, int scheduledDelayMilliseconds = 5000, int exporterTimeoutMilliseconds = 30000, int maxExportBatchSize = 512) -> void +OpenTelemetry.BatchActivityExportProcessor.BatchActivityExportProcessor(OpenTelemetry.BaseExporter! exporter, int maxQueueSize = 2048, int scheduledDelayMilliseconds = 5000, int exporterTimeoutMilliseconds = 30000, int maxExportBatchSize = 512) -> void OpenTelemetry.BatchExportProcessor OpenTelemetry.BatchExportProcessor.BatchExportProcessor(OpenTelemetry.BaseExporter! exporter, int maxQueueSize = 2048, int scheduledDelayMilliseconds = 5000, int exporterTimeoutMilliseconds = 30000, int maxExportBatchSize = 512) -> void -~OpenTelemetry.BatchExportProcessorOptions +OpenTelemetry.BatchExportProcessorOptions OpenTelemetry.CompositeProcessor.AddProcessor(OpenTelemetry.BaseProcessor! processor) -> OpenTelemetry.CompositeProcessor! OpenTelemetry.CompositeProcessor.CompositeProcessor(System.Collections.Generic.IEnumerable!>! processors) -> void ~OpenTelemetry.Metrics.BaseExportingMetricReader.BaseExportingMetricReader(OpenTelemetry.BaseExporter exporter) -> void @@ -37,37 +37,37 @@ OpenTelemetry.Metrics.MetricReaderOptions.PeriodicExportingMetricReaderOptions.s ~OpenTelemetry.Metrics.MetricStreamConfiguration.TagKeys.get -> string[] ~OpenTelemetry.Metrics.MetricStreamConfiguration.TagKeys.set -> void ~OpenTelemetry.Metrics.PeriodicExportingMetricReader.PeriodicExportingMetricReader(OpenTelemetry.BaseExporter exporter, int exportIntervalMilliseconds = 60000, int exportTimeoutMilliseconds = 30000) -> void -~OpenTelemetry.ReadOnlyTagCollection.Enumerator.Current.get -> System.Collections.Generic.KeyValuePair -~OpenTelemetry.Resources.IResourceDetector.Detect() -> OpenTelemetry.Resources.Resource -~OpenTelemetry.Resources.Resource.Attributes.get -> System.Collections.Generic.IEnumerable> -~OpenTelemetry.Resources.Resource.Merge(OpenTelemetry.Resources.Resource other) -> OpenTelemetry.Resources.Resource -~OpenTelemetry.Resources.Resource.Resource(System.Collections.Generic.IEnumerable> attributes) -> void -~OpenTelemetry.Resources.ResourceBuilder.AddDetector(OpenTelemetry.Resources.IResourceDetector resourceDetector) -> OpenTelemetry.Resources.ResourceBuilder -~OpenTelemetry.Resources.ResourceBuilder.Build() -> OpenTelemetry.Resources.Resource -~OpenTelemetry.Resources.ResourceBuilder.Clear() -> OpenTelemetry.Resources.ResourceBuilder -~OpenTelemetry.SimpleActivityExportProcessor.SimpleActivityExportProcessor(OpenTelemetry.BaseExporter exporter) -> void +OpenTelemetry.ReadOnlyTagCollection.Enumerator.Current.get -> System.Collections.Generic.KeyValuePair +OpenTelemetry.Resources.IResourceDetector.Detect() -> OpenTelemetry.Resources.Resource! +OpenTelemetry.Resources.Resource.Attributes.get -> System.Collections.Generic.IEnumerable>! +OpenTelemetry.Resources.Resource.Merge(OpenTelemetry.Resources.Resource! other) -> OpenTelemetry.Resources.Resource! +OpenTelemetry.Resources.Resource.Resource(System.Collections.Generic.IEnumerable>! attributes) -> void +OpenTelemetry.Resources.ResourceBuilder.AddDetector(OpenTelemetry.Resources.IResourceDetector! resourceDetector) -> OpenTelemetry.Resources.ResourceBuilder! +OpenTelemetry.Resources.ResourceBuilder.Build() -> OpenTelemetry.Resources.Resource! +OpenTelemetry.Resources.ResourceBuilder.Clear() -> OpenTelemetry.Resources.ResourceBuilder! +OpenTelemetry.SimpleActivityExportProcessor.SimpleActivityExportProcessor(OpenTelemetry.BaseExporter! exporter) -> void OpenTelemetry.SimpleExportProcessor OpenTelemetry.SimpleExportProcessor.SimpleExportProcessor(OpenTelemetry.BaseExporter! exporter) -> void -~OpenTelemetry.Trace.ParentBasedSampler.ParentBasedSampler(OpenTelemetry.Trace.Sampler rootSampler) -> void -~OpenTelemetry.Trace.ParentBasedSampler.ParentBasedSampler(OpenTelemetry.Trace.Sampler rootSampler, OpenTelemetry.Trace.Sampler remoteParentSampled = null, OpenTelemetry.Trace.Sampler remoteParentNotSampled = null, OpenTelemetry.Trace.Sampler localParentSampled = null, OpenTelemetry.Trace.Sampler localParentNotSampled = null) -> void -~OpenTelemetry.Trace.Sampler.Description.get -> string -~OpenTelemetry.Trace.Sampler.Description.set -> void -~OpenTelemetry.Trace.SamplingParameters.Links.get -> System.Collections.Generic.IEnumerable -~OpenTelemetry.Trace.SamplingParameters.Name.get -> string -~OpenTelemetry.Trace.SamplingParameters.SamplingParameters(System.Diagnostics.ActivityContext parentContext, System.Diagnostics.ActivityTraceId traceId, string name, System.Diagnostics.ActivityKind kind, System.Collections.Generic.IEnumerable> tags = null, System.Collections.Generic.IEnumerable links = null) -> void -~OpenTelemetry.Trace.SamplingParameters.Tags.get -> System.Collections.Generic.IEnumerable> -~OpenTelemetry.Trace.SamplingResult.Attributes.get -> System.Collections.Generic.IEnumerable> -~OpenTelemetry.Trace.SamplingResult.SamplingResult(OpenTelemetry.Trace.SamplingDecision decision, System.Collections.Generic.IEnumerable> attributes) -> void +OpenTelemetry.Trace.ParentBasedSampler.ParentBasedSampler(OpenTelemetry.Trace.Sampler! rootSampler) -> void +OpenTelemetry.Trace.ParentBasedSampler.ParentBasedSampler(OpenTelemetry.Trace.Sampler! rootSampler, OpenTelemetry.Trace.Sampler? remoteParentSampled = null, OpenTelemetry.Trace.Sampler? remoteParentNotSampled = null, OpenTelemetry.Trace.Sampler? localParentSampled = null, OpenTelemetry.Trace.Sampler? localParentNotSampled = null) -> void +OpenTelemetry.Trace.Sampler.Description.get -> string! +OpenTelemetry.Trace.Sampler.Description.set -> void +OpenTelemetry.Trace.SamplingParameters.Links.get -> System.Collections.Generic.IEnumerable? +OpenTelemetry.Trace.SamplingParameters.Name.get -> string! +OpenTelemetry.Trace.SamplingParameters.SamplingParameters(System.Diagnostics.ActivityContext parentContext, System.Diagnostics.ActivityTraceId traceId, string! name, System.Diagnostics.ActivityKind kind, System.Collections.Generic.IEnumerable>? tags = null, System.Collections.Generic.IEnumerable? links = null) -> void +OpenTelemetry.Trace.SamplingParameters.Tags.get -> System.Collections.Generic.IEnumerable>? +OpenTelemetry.Trace.SamplingResult.Attributes.get -> System.Collections.Generic.IEnumerable>! +OpenTelemetry.Trace.SamplingResult.SamplingResult(OpenTelemetry.Trace.SamplingDecision decision, System.Collections.Generic.IEnumerable>! attributes) -> void OpenTelemetry.Trace.TracerProviderBuilderBase.AddInstrumentation(string! instrumentationName, string! instrumentationVersion, System.Func! instrumentationFactory) -> OpenTelemetry.Trace.TracerProviderBuilder! OpenTelemetry.Trace.TracerProviderBuilderBase.Build() -> OpenTelemetry.Trace.TracerProvider! override OpenTelemetry.BaseExportProcessor.OnEnd(T! data) -> void -~override OpenTelemetry.BatchActivityExportProcessor.OnEnd(System.Diagnostics.Activity data) -> void +override OpenTelemetry.BatchActivityExportProcessor.OnEnd(System.Diagnostics.Activity! data) -> void override OpenTelemetry.BatchExportProcessor.OnExport(T! data) -> void ~override OpenTelemetry.Metrics.MeterProviderBuilderBase.AddInstrumentation(System.Func! instrumentationFactory) -> OpenTelemetry.Metrics.MeterProviderBuilder! override OpenTelemetry.Metrics.MeterProviderBuilderBase.AddMeter(params string![]! names) -> OpenTelemetry.Metrics.MeterProviderBuilder! -~override OpenTelemetry.SimpleActivityExportProcessor.OnEnd(System.Diagnostics.Activity data) -> void +override OpenTelemetry.SimpleActivityExportProcessor.OnEnd(System.Diagnostics.Activity! data) -> void override OpenTelemetry.SimpleExportProcessor.OnExport(T! data) -> void -~override OpenTelemetry.Trace.SamplingResult.Equals(object obj) -> bool +override OpenTelemetry.Trace.SamplingResult.Equals(object? obj) -> bool ~override OpenTelemetry.Trace.TracerProviderBuilderBase.AddInstrumentation(System.Func! instrumentationFactory) -> OpenTelemetry.Trace.TracerProviderBuilder! override OpenTelemetry.Trace.TracerProviderBuilderBase.AddLegacySource(string! operationName) -> OpenTelemetry.Trace.TracerProviderBuilder! override OpenTelemetry.Trace.TracerProviderBuilderBase.AddSource(params string![]! names) -> OpenTelemetry.Trace.TracerProviderBuilder! @@ -87,17 +87,17 @@ static OpenTelemetry.Metrics.MeterProviderBuilderExtensions.SetResourceBuilder(t ~static OpenTelemetry.Metrics.MetricStreamConfiguration.Drop.get -> OpenTelemetry.Metrics.MetricStreamConfiguration static OpenTelemetry.ProviderExtensions.GetDefaultResource(this OpenTelemetry.BaseProvider! baseProvider) -> OpenTelemetry.Resources.Resource! static OpenTelemetry.ProviderExtensions.GetResource(this OpenTelemetry.BaseProvider! baseProvider) -> OpenTelemetry.Resources.Resource! -~static OpenTelemetry.Resources.Resource.Empty.get -> OpenTelemetry.Resources.Resource -~static OpenTelemetry.Resources.ResourceBuilder.CreateDefault() -> OpenTelemetry.Resources.ResourceBuilder -~static OpenTelemetry.Resources.ResourceBuilder.CreateEmpty() -> OpenTelemetry.Resources.ResourceBuilder -~static OpenTelemetry.Resources.ResourceBuilderExtensions.AddAttributes(this OpenTelemetry.Resources.ResourceBuilder resourceBuilder, System.Collections.Generic.IEnumerable> attributes) -> OpenTelemetry.Resources.ResourceBuilder -~static OpenTelemetry.Resources.ResourceBuilderExtensions.AddEnvironmentVariableDetector(this OpenTelemetry.Resources.ResourceBuilder resourceBuilder) -> OpenTelemetry.Resources.ResourceBuilder -~static OpenTelemetry.Resources.ResourceBuilderExtensions.AddService(this OpenTelemetry.Resources.ResourceBuilder resourceBuilder, string serviceName, string serviceNamespace = null, string serviceVersion = null, bool autoGenerateServiceInstanceId = true, string serviceInstanceId = null) -> OpenTelemetry.Resources.ResourceBuilder -~static OpenTelemetry.Resources.ResourceBuilderExtensions.AddTelemetrySdk(this OpenTelemetry.Resources.ResourceBuilder resourceBuilder) -> OpenTelemetry.Resources.ResourceBuilder +static OpenTelemetry.Resources.Resource.Empty.get -> OpenTelemetry.Resources.Resource! +static OpenTelemetry.Resources.ResourceBuilder.CreateDefault() -> OpenTelemetry.Resources.ResourceBuilder! +static OpenTelemetry.Resources.ResourceBuilder.CreateEmpty() -> OpenTelemetry.Resources.ResourceBuilder! +static OpenTelemetry.Resources.ResourceBuilderExtensions.AddAttributes(this OpenTelemetry.Resources.ResourceBuilder! resourceBuilder, System.Collections.Generic.IEnumerable>! attributes) -> OpenTelemetry.Resources.ResourceBuilder! +static OpenTelemetry.Resources.ResourceBuilderExtensions.AddEnvironmentVariableDetector(this OpenTelemetry.Resources.ResourceBuilder! resourceBuilder) -> OpenTelemetry.Resources.ResourceBuilder! +static OpenTelemetry.Resources.ResourceBuilderExtensions.AddService(this OpenTelemetry.Resources.ResourceBuilder! resourceBuilder, string! serviceName, string? serviceNamespace = null, string? serviceVersion = null, bool autoGenerateServiceInstanceId = true, string? serviceInstanceId = null) -> OpenTelemetry.Resources.ResourceBuilder! +static OpenTelemetry.Resources.ResourceBuilderExtensions.AddTelemetrySdk(this OpenTelemetry.Resources.ResourceBuilder! resourceBuilder) -> OpenTelemetry.Resources.ResourceBuilder! static OpenTelemetry.Sdk.CreateMeterProviderBuilder() -> OpenTelemetry.Metrics.MeterProviderBuilder! static OpenTelemetry.Sdk.CreateTracerProviderBuilder() -> OpenTelemetry.Trace.TracerProviderBuilder! static OpenTelemetry.Sdk.SetDefaultTextMapPropagator(OpenTelemetry.Context.Propagation.TextMapPropagator! textMapPropagator) -> void -~static OpenTelemetry.SuppressInstrumentationScope.Begin(bool value = true) -> System.IDisposable +static OpenTelemetry.SuppressInstrumentationScope.Begin(bool value = true) -> System.IDisposable! static OpenTelemetry.Trace.TracerProviderBuilderExtensions.AddProcessor(this OpenTelemetry.Trace.TracerProviderBuilder! tracerProviderBuilder, OpenTelemetry.BaseProcessor! processor) -> OpenTelemetry.Trace.TracerProviderBuilder! static OpenTelemetry.Trace.TracerProviderBuilderExtensions.Build(this OpenTelemetry.Trace.TracerProviderBuilder! tracerProviderBuilder) -> OpenTelemetry.Trace.TracerProvider? static OpenTelemetry.Trace.TracerProviderBuilderExtensions.SetErrorStatusOnException(this OpenTelemetry.Trace.TracerProviderBuilder! tracerProviderBuilder, bool enabled = true) -> OpenTelemetry.Trace.TracerProviderBuilder! diff --git a/src/OpenTelemetry/.publicApi/netstandard2.1/PublicAPI.Unshipped.txt b/src/OpenTelemetry/.publicApi/netstandard2.1/PublicAPI.Unshipped.txt index c029cfee537..1adc3849ac9 100644 --- a/src/OpenTelemetry/.publicApi/netstandard2.1/PublicAPI.Unshipped.txt +++ b/src/OpenTelemetry/.publicApi/netstandard2.1/PublicAPI.Unshipped.txt @@ -30,6 +30,15 @@ OpenTelemetry.Logs.LogRecord.TraceFlags.set -> void OpenTelemetry.Logs.LogRecord.TraceId.set -> void OpenTelemetry.Logs.LogRecord.TraceState.set -> void OpenTelemetry.Logs.OpenTelemetryLoggerOptions.ConfigureResource(System.Action! configure) -> OpenTelemetry.Logs.OpenTelemetryLoggerOptions! +OpenTelemetry.Metrics.HistogramConfiguration +OpenTelemetry.Metrics.HistogramConfiguration.HistogramConfiguration() -> void +OpenTelemetry.Metrics.HistogramConfiguration.RecordMinMax.get -> bool +OpenTelemetry.Metrics.HistogramConfiguration.RecordMinMax.set -> void +OpenTelemetry.Metrics.MetricPoint.GetHistogramMax() -> double +OpenTelemetry.Metrics.MetricPoint.GetHistogramMin() -> double +OpenTelemetry.Metrics.MetricPoint.HasMinMax() -> bool +OpenTelemetry.Resources.ResourceBuilder.AddDetector(System.Func! resourceDetectorFactory) -> OpenTelemetry.Resources.ResourceBuilder! +OpenTelemetry.Trace.BatchExportActivityProcessorOptions.BatchExportActivityProcessorOptions(Microsoft.Extensions.Configuration.IConfiguration! configuration) -> void OpenTelemetry.Logs.OpenTelemetryLoggerOptions.IncludeState.get -> bool OpenTelemetry.Logs.OpenTelemetryLoggerOptions.IncludeState.set -> void OpenTelemetry.Logs.OpenTelemetryLoggerOptions.IncludeTraceState.get -> bool @@ -70,9 +79,9 @@ static OpenTelemetry.Metrics.MeterProviderBuilderExtensions.ConfigureServices(th static OpenTelemetry.Sdk.CreateLoggerProviderBuilder() -> OpenTelemetry.Logs.LoggerProviderBuilder! static OpenTelemetry.Trace.TracerProviderBuilderExtensions.AddExporter(this OpenTelemetry.Trace.TracerProviderBuilder! tracerProviderBuilder, OpenTelemetry.ExportProcessorType exportProcessorType, OpenTelemetry.BaseExporter! exporter, string? name, System.Action? configure) -> OpenTelemetry.Trace.TracerProviderBuilder! static OpenTelemetry.Trace.TracerProviderBuilderExtensions.AddExporter(this OpenTelemetry.Trace.TracerProviderBuilder! tracerProviderBuilder, OpenTelemetry.ExportProcessorType exportProcessorType, string? name, System.Action? configure) -> OpenTelemetry.Trace.TracerProviderBuilder! -~OpenTelemetry.Trace.SamplingResult.TraceStateString.get -> string -~OpenTelemetry.Trace.SamplingResult.SamplingResult(OpenTelemetry.Trace.SamplingDecision decision, string traceStateString) -> void -~OpenTelemetry.Trace.SamplingResult.SamplingResult(OpenTelemetry.Trace.SamplingDecision decision, System.Collections.Generic.IEnumerable> attributes, string traceStateString) -> void +OpenTelemetry.Trace.SamplingResult.TraceStateString.get -> string? +OpenTelemetry.Trace.SamplingResult.SamplingResult(OpenTelemetry.Trace.SamplingDecision decision, string! traceStateString) -> void +OpenTelemetry.Trace.SamplingResult.SamplingResult(OpenTelemetry.Trace.SamplingDecision decision, System.Collections.Generic.IEnumerable>? attributes, string? traceStateString) -> void *REMOVED*static Microsoft.Extensions.Logging.OpenTelemetryLoggingExtensions.AddOpenTelemetry(this Microsoft.Extensions.Logging.ILoggingBuilder! builder, System.Action? configure = null) -> Microsoft.Extensions.Logging.ILoggingBuilder! OpenTelemetry.Trace.ExportActivityProcessorOptions OpenTelemetry.Trace.ExportActivityProcessorOptions.BatchExportProcessorOptions.get -> OpenTelemetry.Trace.BatchExportActivityProcessorOptions! diff --git a/src/OpenTelemetry/BatchExportProcessorOptions.cs b/src/OpenTelemetry/BatchExportProcessorOptions.cs index 90abda8abbb..827d90cb5b8 100644 --- a/src/OpenTelemetry/BatchExportProcessorOptions.cs +++ b/src/OpenTelemetry/BatchExportProcessorOptions.cs @@ -14,6 +14,8 @@ // limitations under the License. // +#nullable enable + namespace OpenTelemetry { public class BatchExportProcessorOptions diff --git a/src/OpenTelemetry/CHANGELOG.md b/src/OpenTelemetry/CHANGELOG.md index 1b7d64f1804..c920ba0e7fa 100644 --- a/src/OpenTelemetry/CHANGELOG.md +++ b/src/OpenTelemetry/CHANGELOG.md @@ -7,11 +7,40 @@ ## Unreleased +* Added support for loading environment variables from `IConfiguration` when + using the `MetricReaderOptions` & `BatchExportActivityProcessorOptions` + classes. + ([#3760](https://github.com/open-telemetry/opentelemetry-dotnet/pull/3760), + [#3776](https://github.com/open-telemetry/opentelemetry-dotnet/pull/3776)) + +* Added dependency injection support in the `ResourceBuilder` class and added + support for loading environment variables from `IConfiguration` for the + `AddEnvironmentVariableDetector` extension + ([#3782](https://github.com/open-telemetry/opentelemetry-dotnet/pull/3782), + [#3798](https://github.com/open-telemetry/opentelemetry-dotnet/pull/3798)) + +## 1.4.0-beta.2 + +Released 2022-Oct-17 + +* Make recording of `Min` and `Max` for histograms configurable, enabled by + default. + ([#2735](https://github.com/open-telemetry/opentelemetry-dotnet/pull/2735)) + +* Changed default bucket boundaries for Explicit Bucket Histogram from [0, 5, + 10, 25, 50, 75, 100, 250, 500, 1000] to [0, 5, 10, 25, 50, 75, 100, 250, 500, + 750, 1000, 2500, 5000, 7500, 10000]. + ([#3722](https://github.com/open-telemetry/opentelemetry-dotnet/pull/3722)) + * Fixed an issue where `LogRecord.ForEachScope` may return scopes from a previous log if accessed in a custom processor before `BatchLogRecordExportProcessor.OnEnd` is fired. ([#3731](https://github.com/open-telemetry/opentelemetry-dotnet/pull/3731)) +* Added support for loading environment variables from `IConfiguration` when + using `TracerProviderBuilder` or `MeterProviderBuilder` + ([#3720](https://github.com/open-telemetry/opentelemetry-dotnet/pull/3720)) + ## 1.4.0-beta.1 Released 2022-Sep-29 diff --git a/src/OpenTelemetry/DiagnosticSourceInstrumentation/DiagnosticSourceListener.cs b/src/OpenTelemetry/DiagnosticSourceInstrumentation/DiagnosticSourceListener.cs index 43a78008272..9e8f68c2498 100644 --- a/src/OpenTelemetry/DiagnosticSourceInstrumentation/DiagnosticSourceListener.cs +++ b/src/OpenTelemetry/DiagnosticSourceInstrumentation/DiagnosticSourceListener.cs @@ -21,7 +21,7 @@ namespace OpenTelemetry.Instrumentation { - internal class DiagnosticSourceListener : IObserver> + internal sealed class DiagnosticSourceListener : IObserver> { private readonly ListenerHandler handler; diff --git a/src/OpenTelemetry/DiagnosticSourceInstrumentation/InstrumentationEventSource.cs b/src/OpenTelemetry/DiagnosticSourceInstrumentation/InstrumentationEventSource.cs index 0590edb5111..6e1760bfccd 100644 --- a/src/OpenTelemetry/DiagnosticSourceInstrumentation/InstrumentationEventSource.cs +++ b/src/OpenTelemetry/DiagnosticSourceInstrumentation/InstrumentationEventSource.cs @@ -24,7 +24,7 @@ namespace OpenTelemetry.Instrumentation /// EventSource events emitted from the project. /// [EventSource(Name = "OpenTelemetry-Instrumentation")] - internal class InstrumentationEventSource : EventSource + internal sealed class InstrumentationEventSource : EventSource { public static InstrumentationEventSource Log = new(); diff --git a/src/OpenTelemetry/DiagnosticSourceInstrumentation/PropertyFetcher.cs b/src/OpenTelemetry/DiagnosticSourceInstrumentation/PropertyFetcher.cs index d2ec900b051..6c1657fe657 100644 --- a/src/OpenTelemetry/DiagnosticSourceInstrumentation/PropertyFetcher.cs +++ b/src/OpenTelemetry/DiagnosticSourceInstrumentation/PropertyFetcher.cs @@ -25,7 +25,7 @@ namespace OpenTelemetry.Instrumentation /// PropertyFetcher fetches a property from an object. /// /// The type of the property being fetched. - internal class PropertyFetcher + internal sealed class PropertyFetcher { private readonly string propertyName; private PropertyFetch innerFetcher; diff --git a/src/OpenTelemetry/Internal/Builder/ProviderBuilderServiceCollectionCallbackHelper.cs b/src/OpenTelemetry/Internal/Builder/ProviderBuilderServiceCollectionCallbackHelper.cs index d3f020a180f..0e5d995a98e 100644 --- a/src/OpenTelemetry/Internal/Builder/ProviderBuilderServiceCollectionCallbackHelper.cs +++ b/src/OpenTelemetry/Internal/Builder/ProviderBuilderServiceCollectionCallbackHelper.cs @@ -43,7 +43,7 @@ public static IServiceCollection RegisterConfigureStateCallback( Debug.Assert(services != null, "services was null"); Debug.Assert(configure != null, "configure was null"); - return services.AddSingleton( + return services!.AddSingleton( new ConfigureProviderBuilderStateCallbackRegistration(configure!)); } @@ -54,7 +54,7 @@ public static void InvokeRegisteredConfigureStateCallbacks( Debug.Assert(serviceProvider != null, "serviceProvider was null"); Debug.Assert(state != null, "state was null"); - var callbackRegistrations = serviceProvider.GetServices(); + var callbackRegistrations = serviceProvider!.GetServices(); foreach (var callbackRegistration in callbackRegistrations) { diff --git a/src/OpenTelemetry/Internal/Builder/ProviderBuilderServiceCollectionExtensions.cs b/src/OpenTelemetry/Internal/Builder/ProviderBuilderServiceCollectionExtensions.cs new file mode 100644 index 00000000000..8ae5bd26e48 --- /dev/null +++ b/src/OpenTelemetry/Internal/Builder/ProviderBuilderServiceCollectionExtensions.cs @@ -0,0 +1,65 @@ +// +// Copyright The OpenTelemetry Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +#nullable enable + +using System.Diagnostics; +using Microsoft.Extensions.Configuration; +using Microsoft.Extensions.DependencyInjection.Extensions; +using OpenTelemetry.Internal; +using OpenTelemetry.Metrics; +using OpenTelemetry.Trace; + +namespace Microsoft.Extensions.DependencyInjection; + +internal static class ProviderBuilderServiceCollectionExtensions +{ + public static IServiceCollection AddOpenTelemetryMeterProviderBuilderServices(this IServiceCollection services) + { + services.AddOpenTelemetryProviderBuilderServices(); + + services.TryAddSingleton(); + services.RegisterOptionsFactory(configuration => new MetricReaderOptions(configuration)); + + return services; + } + + public static IServiceCollection AddOpenTelemetryTracerProviderBuilderServices(this IServiceCollection services) + { + services.AddOpenTelemetryProviderBuilderServices(); + + services.TryAddSingleton(); + services.RegisterOptionsFactory(configuration => new ExportActivityProcessorOptions(configuration)); + + return services; + } + + private static IServiceCollection AddOpenTelemetryProviderBuilderServices(this IServiceCollection services) + { + Debug.Assert(services != null, "services was null"); + + services.AddOptions(); + + // Note: When using a host builder IConfiguration is automatically + // registered and this registration will no-op. This only runs for + // Sdk.Create* style or when manually creating a ServiceCollection. The + // point of this registration is to make IConfiguration available in + // those cases. + services!.TryAddSingleton(sp => new ConfigurationBuilder().AddEnvironmentVariables().Build()); + + return services!; + } +} diff --git a/src/OpenTelemetry/Internal/Builder/ProviderBuilderState.cs b/src/OpenTelemetry/Internal/Builder/ProviderBuilderState.cs index 7fb6d96adf3..3862f7a2120 100644 --- a/src/OpenTelemetry/Internal/Builder/ProviderBuilderState.cs +++ b/src/OpenTelemetry/Internal/Builder/ProviderBuilderState.cs @@ -25,27 +25,40 @@ namespace OpenTelemetry; internal abstract class ProviderBuilderState { - protected ProviderBuilderState( - IServiceProvider serviceProvider, - TProvider provider) + private TProvider? provider; + + protected ProviderBuilderState(IServiceProvider serviceProvider) { Debug.Assert(serviceProvider != null, "serviceProvider was null"); - Debug.Assert(provider != null, "provider was null"); this.ServiceProvider = serviceProvider!; - this.Provider = provider; } public IServiceProvider ServiceProvider { get; } public abstract TBuilder Builder { get; } - public TProvider Provider { get; } + public TProvider Provider + { + get => this.provider ?? throw new InvalidOperationException("Provider has not been set on state."); + } public List Instrumentation { get; } = new(); public ResourceBuilder? ResourceBuilder { get; protected set; } + public void RegisterProvider(string providerTypeName, TProvider provider) + { + Debug.Assert(provider != null, "provider was null"); + + if (this.provider != null) + { + throw new NotSupportedException($"{providerTypeName} cannot be accessed while build is executing."); + } + + this.provider = provider; + } + public void AddInstrumentation( string instrumentationName, string instrumentationVersion, diff --git a/src/OpenTelemetry/Internal/ConfigurationExtensions.cs b/src/OpenTelemetry/Internal/ConfigurationExtensions.cs new file mode 100644 index 00000000000..dc22bbf673c --- /dev/null +++ b/src/OpenTelemetry/Internal/ConfigurationExtensions.cs @@ -0,0 +1,164 @@ +// +// Copyright The OpenTelemetry Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +#nullable enable + +using System; +using System.Collections.Generic; +using System.Diagnostics; +#if !NETFRAMEWORK && !NETSTANDARD2_0 +using System.Diagnostics.CodeAnalysis; +#endif +using System.Globalization; +using Microsoft.Extensions.Configuration; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.DependencyInjection.Extensions; +using Microsoft.Extensions.Options; + +namespace OpenTelemetry.Internal; + +internal static class ConfigurationExtensions +{ + public delegate bool TryParseFunc( + string value, +#if !NETFRAMEWORK && !NETSTANDARD2_0 + [NotNullWhen(true)] +#endif + out T? parsedValue); + + public static bool TryGetStringValue( + this IConfiguration configuration, + string key, +#if !NETFRAMEWORK && !NETSTANDARD2_0 + [NotNullWhen(true)] +#endif + out string? value) + { + value = configuration.GetValue(key, null); + + return !string.IsNullOrWhiteSpace(value); + } + + public static bool TryGetUriValue( + this IConfiguration configuration, + string key, +#if !NETFRAMEWORK && !NETSTANDARD2_0 + [NotNullWhen(true)] +#endif + out Uri? value) + { + if (!configuration.TryGetStringValue(key, out var stringValue)) + { + value = null; + return false; + } + + if (!Uri.TryCreate(stringValue, UriKind.Absolute, out value)) + { + throw new FormatException($"{key} environment variable has an invalid value: '{stringValue}'"); + } + + return true; + } + + public static bool TryGetIntValue( + this IConfiguration configuration, + string key, + out int value) + { + if (!configuration.TryGetStringValue(key, out var stringValue)) + { + value = default; + return false; + } + + if (!int.TryParse(stringValue, NumberStyles.None, CultureInfo.InvariantCulture, out value)) + { + throw new FormatException($"{key} environment variable has an invalid value: '{stringValue}'"); + } + + return true; + } + + public static bool TryGetValue( + this IConfiguration configuration, + string key, + TryParseFunc tryParseFunc, +#if !NETFRAMEWORK && !NETSTANDARD2_0 + [NotNullWhen(true)] +#endif + out T? value) + { + if (!configuration.TryGetStringValue(key, out var stringValue)) + { + value = default; + return false; + } + + if (!tryParseFunc(stringValue!, out value)) + { + throw new FormatException($"{key} environment variable has an invalid value: '{stringValue}'"); + } + + return true; + } + + public static IServiceCollection RegisterOptionsFactory( + this IServiceCollection services, + Func optionsFactoryFunc) + where T : class + { + Debug.Assert(services != null, "services was null"); + Debug.Assert(optionsFactoryFunc != null, "optionsFactoryFunc was null"); + + services!.TryAddSingleton>(sp => + { + return new DelegatingOptionsFactory( + optionsFactoryFunc!, + sp.GetRequiredService(), + sp.GetServices>(), + sp.GetServices>(), + sp.GetServices>()); + }); + + return services!; + } + + private sealed class DelegatingOptionsFactory : OptionsFactory + where T : class + { + private readonly Func optionsFactoryFunc; + private readonly IConfiguration configuration; + + public DelegatingOptionsFactory( + Func optionsFactoryFunc, + IConfiguration configuration, + IEnumerable> setups, + IEnumerable> postConfigures, + IEnumerable> validations) + : base(setups, postConfigures, validations) + { + Debug.Assert(optionsFactoryFunc != null, "optionsFactoryFunc was null"); + Debug.Assert(configuration != null, "configuration was null"); + + this.optionsFactoryFunc = optionsFactoryFunc!; + this.configuration = configuration!; + } + + protected override T CreateInstance(string name) + => this.optionsFactoryFunc(this.configuration); + } +} diff --git a/src/OpenTelemetry/Internal/EnvironmentVariableHelper.cs b/src/OpenTelemetry/Internal/EnvironmentVariableHelper.cs deleted file mode 100644 index f6ea9783590..00000000000 --- a/src/OpenTelemetry/Internal/EnvironmentVariableHelper.cs +++ /dev/null @@ -1,143 +0,0 @@ -// -// Copyright The OpenTelemetry Authors -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -// - -using System; -using System.Globalization; -using System.Security; - -namespace OpenTelemetry.Internal -{ - /// - /// EnvironmentVariableHelper facilitates parsing environment variable values as defined by - /// - /// the specification. - /// - internal static class EnvironmentVariableHelper - { - /// - /// Reads an environment variable without any parsing. - /// - /// The name of the environment variable. - /// The parsed value of the environment variable. - /// - /// Returns true when a non-empty value was read; otherwise, false. - /// - public static bool LoadString(string envVarKey, out string result) - { - result = null; - - try - { - result = Environment.GetEnvironmentVariable(envVarKey); - } - catch (SecurityException ex) - { - // The caller does not have the required permission to - // retrieve the value of an environment variable from the current process. - OpenTelemetrySdkEventSource.Log.MissingPermissionsToReadEnvironmentVariable(ex); - return false; - } - - return !string.IsNullOrEmpty(result); - } - - /// - /// Reads an environment variable and parses is as a - /// - /// numeric value - a non-negative decimal integer. - /// - /// The name of the environment variable. - /// The parsed value of the environment variable. - /// - /// Returns true when a non-empty value was read; otherwise, false. - /// - /// - /// Thrown when failed to parse the non-empty value. - /// - public static bool LoadNumeric(string envVarKey, out int result) - { - result = 0; - - if (!LoadString(envVarKey, out string value)) - { - return false; - } - - if (!int.TryParse(value, NumberStyles.None, CultureInfo.InvariantCulture, out result)) - { - throw new FormatException($"{envVarKey} environment variable has an invalid value: '{value}'"); - } - - return true; - } - - /// - /// Reads an environment variable and parses it as a . - /// - /// The name of the environment variable. - /// The parsed value of the environment variable. - /// - /// Returns true when a non-empty value was read; otherwise, false. - /// - /// - /// Thrown when failed to parse the non-empty value. - /// - public static bool LoadUri(string envVarKey, out Uri result) - { - result = null; - - if (!LoadString(envVarKey, out string value)) - { - return false; - } - - if (!Uri.TryCreate(value, UriKind.Absolute, out result)) - { - throw new FormatException($"{envVarKey} environment variable has an invalid value: '${value}'"); - } - - return true; - } - - /// - /// Reads an environment variable and parses it as a . - /// - /// The name of the environment variable. - /// The parsed value of the environment variable. - /// - /// Returns true when a non-empty value was read; otherwise, false. - /// - /// - /// Thrown when failed to parse the non-empty value. - /// - public static bool LoadBoolean(string envVarKey, out bool result) - { - result = default; - - if (!LoadString(envVarKey, out string value)) - { - return false; - } - - if (!bool.TryParse(value, out result)) - { - throw new FormatException($"{envVarKey} environment variable has an invalid value: '${value}'"); - } - - return true; - } - } -} diff --git a/src/OpenTelemetry/Internal/OpenTelemetrySdkEventSource.cs b/src/OpenTelemetry/Internal/OpenTelemetrySdkEventSource.cs index ee30b7fc68b..664675ff923 100644 --- a/src/OpenTelemetry/Internal/OpenTelemetrySdkEventSource.cs +++ b/src/OpenTelemetry/Internal/OpenTelemetrySdkEventSource.cs @@ -29,7 +29,7 @@ namespace OpenTelemetry.Internal /// EventSource implementation for OpenTelemetry SDK implementation. /// [EventSource(Name = "OpenTelemetry-Sdk")] - internal class OpenTelemetrySdkEventSource : EventSource + internal sealed class OpenTelemetrySdkEventSource : EventSource { public static OpenTelemetrySdkEventSource Log = new(); #if DEBUG @@ -432,6 +432,12 @@ public void LoggerProviderException(string methodName, string ex) this.WriteEvent(46, methodName, ex); } + [Event(47, Message = "TracerProviderSdk event: '{0}'", Level = EventLevel.Verbose)] + public void TracerProviderSdkEvent(string message) + { + this.WriteEvent(47, message); + } + #if DEBUG public class OpenTelemetryEventListener : EventListener { diff --git a/src/OpenTelemetry/Internal/PeriodicExportingMetricReaderHelper.cs b/src/OpenTelemetry/Internal/PeriodicExportingMetricReaderHelper.cs index 0fa1fc9058b..5514871993c 100644 --- a/src/OpenTelemetry/Internal/PeriodicExportingMetricReaderHelper.cs +++ b/src/OpenTelemetry/Internal/PeriodicExportingMetricReaderHelper.cs @@ -14,15 +14,11 @@ // limitations under the License. // -using OpenTelemetry.Internal; - namespace OpenTelemetry.Metrics; internal static class PeriodicExportingMetricReaderHelper { - internal const string OTelMetricExportIntervalEnvVarKey = "OTEL_METRIC_EXPORT_INTERVAL"; internal const int DefaultExportIntervalMilliseconds = 60000; - internal const string OTelMetricExportTimeoutEnvVarKey = "OTEL_METRIC_EXPORT_TIMEOUT"; internal const int DefaultExportTimeoutMilliseconds = 30000; internal static PeriodicExportingMetricReader CreatePeriodicExportingMetricReader( @@ -31,15 +27,11 @@ internal static PeriodicExportingMetricReader CreatePeriodicExportingMetricReade int defaultExportIntervalMilliseconds = DefaultExportIntervalMilliseconds, int defaultExportTimeoutMilliseconds = DefaultExportTimeoutMilliseconds) { - var exportInterval = GetValue( - options.PeriodicExportingMetricReaderOptions?.ExportIntervalMilliseconds, - OTelMetricExportIntervalEnvVarKey, - defaultExportIntervalMilliseconds); + var exportInterval = + options.PeriodicExportingMetricReaderOptions?.ExportIntervalMilliseconds ?? defaultExportIntervalMilliseconds; - var exportTimeout = GetValue( - options.PeriodicExportingMetricReaderOptions?.ExportTimeoutMilliseconds, - OTelMetricExportTimeoutEnvVarKey, - defaultExportTimeoutMilliseconds); + var exportTimeout = + options.PeriodicExportingMetricReaderOptions?.ExportTimeoutMilliseconds ?? defaultExportTimeoutMilliseconds; var metricReader = new PeriodicExportingMetricReader(exporter, exportInterval, exportTimeout) { @@ -48,19 +40,4 @@ internal static PeriodicExportingMetricReader CreatePeriodicExportingMetricReade return metricReader; } - - private static int GetValue(int? optionsValue, string envVarKey, int defaultValue) - { - if (optionsValue.HasValue) - { - return optionsValue.Value; - } - - if (EnvironmentVariableHelper.LoadNumeric(envVarKey, out var envVarValue)) - { - return envVarValue; - } - - return defaultValue; - } } diff --git a/src/OpenTelemetry/Internal/SelfDiagnosticsConfigParser.cs b/src/OpenTelemetry/Internal/SelfDiagnosticsConfigParser.cs index 91dd32fee1b..d517f8667f0 100644 --- a/src/OpenTelemetry/Internal/SelfDiagnosticsConfigParser.cs +++ b/src/OpenTelemetry/Internal/SelfDiagnosticsConfigParser.cs @@ -22,7 +22,7 @@ namespace OpenTelemetry.Internal { - internal class SelfDiagnosticsConfigParser + internal sealed class SelfDiagnosticsConfigParser { public const string ConfigFileName = "OTEL_DIAGNOSTICS.json"; private const int FileSizeLowerLimit = 1024; // Lower limit for log file size in KB: 1MB diff --git a/src/OpenTelemetry/Logs/BatchExportLogRecordProcessorOptions.cs b/src/OpenTelemetry/Logs/BatchExportLogRecordProcessorOptions.cs index ea23f314e7c..b9fe5aac85b 100644 --- a/src/OpenTelemetry/Logs/BatchExportLogRecordProcessorOptions.cs +++ b/src/OpenTelemetry/Logs/BatchExportLogRecordProcessorOptions.cs @@ -15,6 +15,7 @@ // using System; +using Microsoft.Extensions.Configuration; using OpenTelemetry.Internal; namespace OpenTelemetry.Logs @@ -47,26 +48,32 @@ public class BatchExportLogRecordProcessorOptions : BatchExportProcessorOptions< internal const string ScheduledDelayEnvVarKey = "OTEL_BLRP_SCHEDULE_DELAY"; + /// + /// Initializes a new instance of the class. + /// public BatchExportLogRecordProcessorOptions() + : this(new ConfigurationBuilder().AddEnvironmentVariables().Build()) { - int value; + } - if (EnvironmentVariableHelper.LoadNumeric(ExporterTimeoutEnvVarKey, out value)) + internal BatchExportLogRecordProcessorOptions(IConfiguration configuration) + { + if (configuration.TryGetIntValue(ExporterTimeoutEnvVarKey, out var value)) { this.ExporterTimeoutMilliseconds = value; } - if (EnvironmentVariableHelper.LoadNumeric(MaxExportBatchSizeEnvVarKey, out value)) + if (configuration.TryGetIntValue(MaxExportBatchSizeEnvVarKey, out value)) { this.MaxExportBatchSize = value; } - if (EnvironmentVariableHelper.LoadNumeric(MaxQueueSizeEnvVarKey, out value)) + if (configuration.TryGetIntValue(MaxQueueSizeEnvVarKey, out value)) { this.MaxQueueSize = value; } - if (EnvironmentVariableHelper.LoadNumeric(ScheduledDelayEnvVarKey, out value)) + if (configuration.TryGetIntValue(ScheduledDelayEnvVarKey, out value)) { this.ScheduledDelayMilliseconds = value; } diff --git a/src/OpenTelemetry/Logs/Builder/LoggerProviderBuilderSdk.cs b/src/OpenTelemetry/Logs/Builder/LoggerProviderBuilderSdk.cs index 03879a8066c..5e94c915302 100644 --- a/src/OpenTelemetry/Logs/Builder/LoggerProviderBuilderSdk.cs +++ b/src/OpenTelemetry/Logs/Builder/LoggerProviderBuilderSdk.cs @@ -54,7 +54,7 @@ public LoggerProviderBuilderSdk(IServiceCollection services) Debug.Assert(services != null, "services was null"); services.AddOptions(); - services.TryAddSingleton(sp => new LoggerProviderSdk(sp, ownsServiceProvider: false)); + services!.TryAddSingleton(sp => new LoggerProviderSdk(sp, ownsServiceProvider: false)); this.services = services; this.ownsServices = false; diff --git a/src/OpenTelemetry/Logs/Builder/LoggerProviderBuilderState.cs b/src/OpenTelemetry/Logs/Builder/LoggerProviderBuilderState.cs index fb175d6d338..03c018b82c5 100644 --- a/src/OpenTelemetry/Logs/Builder/LoggerProviderBuilderState.cs +++ b/src/OpenTelemetry/Logs/Builder/LoggerProviderBuilderState.cs @@ -29,10 +29,8 @@ internal sealed class LoggerProviderBuilderState : ProviderBuilderState + /// Initializes a new instance of the class. + /// + public ExportLogRecordProcessorOptions() + : this(new ConfigurationBuilder().AddEnvironmentVariables().Build()) + { + } + + internal ExportLogRecordProcessorOptions(IConfiguration configuration) + { + this.batchExportProcessorOptions = new BatchExportLogRecordProcessorOptions(configuration); + } + /// /// Gets or sets the export processor type to be used. The default value is . /// diff --git a/src/OpenTelemetry/Logs/LoggerProviderSdk.cs b/src/OpenTelemetry/Logs/LoggerProviderSdk.cs index 175e118b676..c02a9731ca6 100644 --- a/src/OpenTelemetry/Logs/LoggerProviderSdk.cs +++ b/src/OpenTelemetry/Logs/LoggerProviderSdk.cs @@ -56,7 +56,8 @@ public LoggerProviderSdk( Debug.Assert(this.ownedServiceProvider != null, "ownedServiceProvider was null"); } - var state = new LoggerProviderBuilderState(serviceProvider, this); + var state = new LoggerProviderBuilderState(serviceProvider); + state.RegisterProvider(nameof(LoggerProvider), this); CallbackHelper.InvokeRegisteredConfigureStateCallbacks( serviceProvider, diff --git a/src/OpenTelemetry/Metrics/AggregationType.cs b/src/OpenTelemetry/Metrics/AggregationType.cs index bd87c9e5b4f..eff60b2d91d 100644 --- a/src/OpenTelemetry/Metrics/AggregationType.cs +++ b/src/OpenTelemetry/Metrics/AggregationType.cs @@ -54,13 +54,23 @@ internal enum AggregationType DoubleGauge = 5, /// - /// Histogram. + /// Histogram with sum, count, buckets. /// Histogram = 6, /// - /// Histogram with sum, count only. + /// Histogram with sum, count, min, max, buckets. /// - HistogramSumCount = 7, + HistogramMinMax = 7, + + /// + /// Histogram with sum, count. + /// + HistogramSumCount = 8, + + /// + /// Histogram with sum, count, min, max. + /// + HistogramSumCountMinMax = 9, } } diff --git a/src/OpenTelemetry/Metrics/Builder/MeterProviderBuilderBase.cs b/src/OpenTelemetry/Metrics/Builder/MeterProviderBuilderBase.cs index d1dcf6aa765..eced32ea01c 100644 --- a/src/OpenTelemetry/Metrics/Builder/MeterProviderBuilderBase.cs +++ b/src/OpenTelemetry/Metrics/Builder/MeterProviderBuilderBase.cs @@ -51,14 +51,15 @@ internal MeterProviderBuilderBase(MeterProviderBuilderState state) this.State = state; } - // This ctor is for AddOpenTelemetryTracing scenario where the builder - // is bound to an external service collection. + // This ctor is for ConfigureOpenTelemetryMetrics + + // AddOpenTelemetryMetrics scenarios where the builder is bound to an + // external service collection. internal MeterProviderBuilderBase(IServiceCollection services) { Debug.Assert(services != null, "services was null"); - services.AddOptions(); - services.TryAddSingleton(sp => new MeterProviderSdk(sp, ownsServiceProvider: false)); + services!.AddOpenTelemetryMeterProviderBuilderServices(); + services!.TryAddSingleton(sp => new MeterProviderSdk(sp, ownsServiceProvider: false)); this.services = services; this.ownsServices = false; @@ -70,7 +71,9 @@ protected MeterProviderBuilderBase() { var services = new ServiceCollection(); - services.AddOptions(); + services.AddOpenTelemetryMeterProviderBuilderServices(); + services.AddSingleton( + sp => throw new NotSupportedException("External MeterProvider created through Sdk.CreateMeterProviderBuilder cannot be accessed using service provider.")); this.services = services; this.ownsServices = true; diff --git a/src/OpenTelemetry/Metrics/Builder/MeterProviderBuilderState.cs b/src/OpenTelemetry/Metrics/Builder/MeterProviderBuilderState.cs index b036335c43d..ebd9b81e53b 100644 --- a/src/OpenTelemetry/Metrics/Builder/MeterProviderBuilderState.cs +++ b/src/OpenTelemetry/Metrics/Builder/MeterProviderBuilderState.cs @@ -34,10 +34,8 @@ internal sealed class MeterProviderBuilderState : ProviderBuilderState /// Stores configuration for a histogram metric stream with explicit bucket boundaries. /// - public class ExplicitBucketHistogramConfiguration : MetricStreamConfiguration + public class ExplicitBucketHistogramConfiguration : HistogramConfiguration { /// /// Gets or sets the optional boundaries of the histogram metric stream. diff --git a/src/OpenTelemetry/Metrics/ExponentialBucketHistogram.cs b/src/OpenTelemetry/Metrics/ExponentialBucketHistogram.cs index 8fe69979b33..0f83121bea1 100644 --- a/src/OpenTelemetry/Metrics/ExponentialBucketHistogram.cs +++ b/src/OpenTelemetry/Metrics/ExponentialBucketHistogram.cs @@ -26,7 +26,7 @@ namespace OpenTelemetry.Metrics; /// identified by Bucket[index] = ( base ^ index, base ^ (index + 1) ], /// where index is an integer. /// -internal class ExponentialBucketHistogram +internal sealed class ExponentialBucketHistogram { private int scale; private double scalingFactor; // 2 ^ scale / log(2) diff --git a/src/OpenTelemetry/Metrics/ExponentialBucketHistogramConfiguration.cs b/src/OpenTelemetry/Metrics/ExponentialBucketHistogramConfiguration.cs index 389b2e0e4b0..53e8510d9ff 100644 --- a/src/OpenTelemetry/Metrics/ExponentialBucketHistogramConfiguration.cs +++ b/src/OpenTelemetry/Metrics/ExponentialBucketHistogramConfiguration.cs @@ -19,7 +19,7 @@ namespace OpenTelemetry.Metrics; /// /// Stores configuration for a histogram metric stream with exponential bucket boundaries. /// -internal class ExponentialBucketHistogramConfiguration : MetricStreamConfiguration +internal sealed class ExponentialBucketHistogramConfiguration : MetricStreamConfiguration { /// /// Gets or sets the maximum number of buckets in each of the positive and negative ranges, not counting the special zero bucket. diff --git a/src/OpenTelemetry/Metrics/HistogramBuckets.cs b/src/OpenTelemetry/Metrics/HistogramBuckets.cs index 2a2149b31b0..c0160e534ee 100644 --- a/src/OpenTelemetry/Metrics/HistogramBuckets.cs +++ b/src/OpenTelemetry/Metrics/HistogramBuckets.cs @@ -31,13 +31,17 @@ public class HistogramBuckets internal readonly double[] ExplicitBounds; internal readonly long[] RunningBucketCounts; - internal readonly long[] SnapshotBucketCounts; internal double RunningSum; - internal double SnapshotSum; + internal double RunningMin = double.PositiveInfinity; + internal double SnapshotMin; + + internal double RunningMax = double.NegativeInfinity; + internal double SnapshotMax; + internal int IsCriticalSectionOccupied = 0; private readonly BucketLookupNode bucketLookupTreeRoot; diff --git a/src/OpenTelemetry/Metrics/HistogramConfiguration.cs b/src/OpenTelemetry/Metrics/HistogramConfiguration.cs new file mode 100644 index 00000000000..37980098937 --- /dev/null +++ b/src/OpenTelemetry/Metrics/HistogramConfiguration.cs @@ -0,0 +1,26 @@ +// +// Copyright The OpenTelemetry Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +namespace OpenTelemetry.Metrics; + +public class HistogramConfiguration : MetricStreamConfiguration +{ + /// + /// Gets or sets a value indicating whether Min, Max + /// should be collected. + /// + public bool RecordMinMax { get; set; } = true; +} diff --git a/src/OpenTelemetry/Metrics/MeterProviderSdk.cs b/src/OpenTelemetry/Metrics/MeterProviderSdk.cs index 4cd76444f75..8a8ab77f9c8 100644 --- a/src/OpenTelemetry/Metrics/MeterProviderSdk.cs +++ b/src/OpenTelemetry/Metrics/MeterProviderSdk.cs @@ -22,6 +22,7 @@ using System.Diagnostics.Metrics; using System.Linq; using System.Text; +using Microsoft.Extensions.DependencyInjection; using OpenTelemetry.Internal; using OpenTelemetry.Resources; @@ -34,6 +35,7 @@ namespace OpenTelemetry.Metrics { internal sealed class MeterProviderSdk : MeterProvider { + internal readonly IServiceProvider ServiceProvider; internal readonly IDisposable? OwnedServiceProvider; internal int ShutdownCount; internal bool Disposed; @@ -49,6 +51,13 @@ internal MeterProviderSdk( IServiceProvider serviceProvider, bool ownsServiceProvider) { + Debug.Assert(serviceProvider != null, "serviceProvider was null"); + + var state = serviceProvider!.GetRequiredService(); + state.RegisterProvider(nameof(MeterProvider), this); + + this.ServiceProvider = serviceProvider!; + if (ownsServiceProvider) { this.OwnedServiceProvider = serviceProvider as IDisposable; @@ -57,16 +66,17 @@ internal MeterProviderSdk( OpenTelemetrySdkEventSource.Log.MeterProviderSdkEvent("Building MeterProvider."); - var state = new MeterProviderBuilderState(serviceProvider, this); - CallbackHelper.InvokeRegisteredConfigureStateCallbacks( - serviceProvider, + serviceProvider!, state); StringBuilder exportersAdded = new StringBuilder(); StringBuilder instrumentationFactoriesAdded = new StringBuilder(); - this.Resource = (state.ResourceBuilder ?? ResourceBuilder.CreateDefault()).Build(); + var resourceBuilder = state.ResourceBuilder ?? ResourceBuilder.CreateDefault(); + resourceBuilder.ServiceProvider = serviceProvider; + this.Resource = resourceBuilder.Build(); + this.viewConfigs = state.ViewConfigs; foreach (var reader in state.Readers) diff --git a/src/OpenTelemetry/Metrics/Metric.cs b/src/OpenTelemetry/Metrics/Metric.cs index 51e8df9b7ac..6f5771121b7 100644 --- a/src/OpenTelemetry/Metrics/Metric.cs +++ b/src/OpenTelemetry/Metrics/Metric.cs @@ -25,7 +25,7 @@ namespace OpenTelemetry.Metrics /// public sealed class Metric { - internal static readonly double[] DefaultHistogramBounds = new double[] { 0, 5, 10, 25, 50, 75, 100, 250, 500, 1000 }; + internal static readonly double[] DefaultHistogramBounds = new double[] { 0, 5, 10, 25, 50, 75, 100, 250, 500, 750, 1000, 2500, 5000, 7500, 10000 }; private readonly AggregatorStore aggStore; @@ -34,7 +34,8 @@ internal Metric( AggregationTemporality temporality, int maxMetricPointsPerMetricStream, double[] histogramBounds = null, - string[] tagKeysInteresting = null) + string[] tagKeysInteresting = null, + bool histogramRecordMinMax = true) { this.InstrumentIdentity = instrumentIdentity; @@ -118,15 +119,9 @@ internal Metric( { this.MetricType = MetricType.Histogram; - if (histogramBounds != null - && histogramBounds.Length == 0) - { - aggType = AggregationType.HistogramSumCount; - } - else - { - aggType = AggregationType.Histogram; - } + aggType = histogramBounds != null && histogramBounds.Length == 0 + ? (histogramRecordMinMax ? AggregationType.HistogramSumCountMinMax : AggregationType.HistogramSumCount) + : (histogramRecordMinMax ? AggregationType.HistogramMinMax : AggregationType.Histogram); } else { diff --git a/src/OpenTelemetry/Metrics/MetricPoint.cs b/src/OpenTelemetry/Metrics/MetricPoint.cs index 55abb65b9c5..50dc46d1135 100644 --- a/src/OpenTelemetry/Metrics/MetricPoint.cs +++ b/src/OpenTelemetry/Metrics/MetricPoint.cs @@ -58,11 +58,13 @@ internal MetricPoint( this.deltaLastValue = default; this.MetricPointStatus = MetricPointStatus.NoCollectPending; - if (this.aggType == AggregationType.Histogram) + if (this.aggType == AggregationType.Histogram || + this.aggType == AggregationType.HistogramMinMax) { this.histogramBuckets = new HistogramBuckets(histogramExplicitBounds); } - else if (this.aggType == AggregationType.HistogramSumCount) + else if (this.aggType == AggregationType.HistogramSumCount || + this.aggType == AggregationType.HistogramSumCountMinMax) { this.histogramBuckets = new HistogramBuckets(null); } @@ -187,7 +189,10 @@ public readonly double GetGaugeLastValueDouble() [MethodImpl(MethodImplOptions.AggressiveInlining)] public readonly long GetHistogramCount() { - if (this.aggType != AggregationType.Histogram && this.aggType != AggregationType.HistogramSumCount) + if (this.aggType != AggregationType.Histogram && + this.aggType != AggregationType.HistogramSumCount && + this.aggType != AggregationType.HistogramMinMax && + this.aggType != AggregationType.HistogramSumCountMinMax) { this.ThrowNotSupportedMetricTypeException(nameof(this.GetHistogramCount)); } @@ -205,7 +210,10 @@ public readonly long GetHistogramCount() [MethodImpl(MethodImplOptions.AggressiveInlining)] public readonly double GetHistogramSum() { - if (this.aggType != AggregationType.Histogram && this.aggType != AggregationType.HistogramSumCount) + if (this.aggType != AggregationType.Histogram && + this.aggType != AggregationType.HistogramSumCount && + this.aggType != AggregationType.HistogramMinMax && + this.aggType != AggregationType.HistogramSumCountMinMax) { this.ThrowNotSupportedMetricTypeException(nameof(this.GetHistogramSum)); } @@ -223,7 +231,10 @@ public readonly double GetHistogramSum() [MethodImpl(MethodImplOptions.AggressiveInlining)] public readonly HistogramBuckets GetHistogramBuckets() { - if (this.aggType != AggregationType.Histogram && this.aggType != AggregationType.HistogramSumCount) + if (this.aggType != AggregationType.Histogram && + this.aggType != AggregationType.HistogramSumCount && + this.aggType != AggregationType.HistogramMinMax && + this.aggType != AggregationType.HistogramSumCountMinMax) { this.ThrowNotSupportedMetricTypeException(nameof(this.GetHistogramBuckets)); } @@ -231,6 +242,47 @@ public readonly HistogramBuckets GetHistogramBuckets() return this.histogramBuckets; } + /// + /// Gets the minimum value of the histogram associated with the metric + /// point if present. Check by using . + /// + /// + /// Applies to metric type. + /// + /// A histogram's maximum value. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public double GetHistogramMin() + { + return this.histogramBuckets.SnapshotMin; + } + + /// + /// Gets the maximum value of the histogram associated with the metric + /// point if present. Check by using . + /// + /// + /// Applies to metric type. + /// + /// A histogram's maximum value. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public double GetHistogramMax() + { + return this.histogramBuckets.SnapshotMax; + } + + /// + /// Gets whether the histogram has a valid Min and Max value. + /// Should be used before + /// and to + /// ensure a valid value is returned. + /// + /// A minimum and maximum value exist. + public bool HasMinMax() + { + return this.aggType == AggregationType.HistogramMinMax || + this.aggType == AggregationType.HistogramSumCountMinMax; + } + internal readonly MetricPoint Copy() { MetricPoint copy = this; @@ -261,7 +313,9 @@ internal void Update(long number) } case AggregationType.Histogram: + case AggregationType.HistogramMinMax: case AggregationType.HistogramSumCount: + case AggregationType.HistogramSumCountMinMax: { this.Update((double)number); @@ -374,6 +428,63 @@ internal void Update(double number) sw.SpinOnce(); } + break; + } + + case AggregationType.HistogramMinMax: + { + int i = this.histogramBuckets.FindBucketIndex(number); + + var sw = default(SpinWait); + while (true) + { + if (Interlocked.Exchange(ref this.histogramBuckets.IsCriticalSectionOccupied, 1) == 0) + { + // Lock acquired + unchecked + { + this.runningValue.AsLong++; + this.histogramBuckets.RunningSum += number; + this.histogramBuckets.RunningBucketCounts[i]++; + this.histogramBuckets.RunningMin = Math.Min(this.histogramBuckets.RunningMin, number); + this.histogramBuckets.RunningMax = Math.Max(this.histogramBuckets.RunningMax, number); + } + + // Release lock + Interlocked.Exchange(ref this.histogramBuckets.IsCriticalSectionOccupied, 0); + break; + } + + sw.SpinOnce(); + } + + break; + } + + case AggregationType.HistogramSumCountMinMax: + { + var sw = default(SpinWait); + while (true) + { + if (Interlocked.Exchange(ref this.histogramBuckets.IsCriticalSectionOccupied, 1) == 0) + { + // Lock acquired + unchecked + { + this.runningValue.AsLong++; + this.histogramBuckets.RunningSum += number; + this.histogramBuckets.RunningMin = Math.Min(this.histogramBuckets.RunningMin, number); + this.histogramBuckets.RunningMax = Math.Max(this.histogramBuckets.RunningMax, number); + } + + // Release lock + Interlocked.Exchange(ref this.histogramBuckets.IsCriticalSectionOccupied, 0); + break; + } + + sw.SpinOnce(); + } + break; } } @@ -501,6 +612,7 @@ internal void TakeSnapshot(bool outputDelta) // Lock acquired this.snapshotValue.AsLong = this.runningValue.AsLong; this.histogramBuckets.SnapshotSum = this.histogramBuckets.RunningSum; + if (outputDelta) { this.runningValue.AsLong = 0; @@ -539,10 +651,88 @@ internal void TakeSnapshot(bool outputDelta) // Lock acquired this.snapshotValue.AsLong = this.runningValue.AsLong; this.histogramBuckets.SnapshotSum = this.histogramBuckets.RunningSum; + + if (outputDelta) + { + this.runningValue.AsLong = 0; + this.histogramBuckets.RunningSum = 0; + } + + this.MetricPointStatus = MetricPointStatus.NoCollectPending; + + // Release lock + Interlocked.Exchange(ref this.histogramBuckets.IsCriticalSectionOccupied, 0); + break; + } + + sw.SpinOnce(); + } + + break; + } + + case AggregationType.HistogramMinMax: + { + var sw = default(SpinWait); + while (true) + { + if (Interlocked.Exchange(ref this.histogramBuckets.IsCriticalSectionOccupied, 1) == 0) + { + // Lock acquired + this.snapshotValue.AsLong = this.runningValue.AsLong; + this.histogramBuckets.SnapshotSum = this.histogramBuckets.RunningSum; + this.histogramBuckets.SnapshotMin = this.histogramBuckets.RunningMin; + this.histogramBuckets.SnapshotMax = this.histogramBuckets.RunningMax; + + if (outputDelta) + { + this.runningValue.AsLong = 0; + this.histogramBuckets.RunningSum = 0; + this.histogramBuckets.RunningMin = double.PositiveInfinity; + this.histogramBuckets.RunningMax = double.NegativeInfinity; + } + + for (int i = 0; i < this.histogramBuckets.RunningBucketCounts.Length; i++) + { + this.histogramBuckets.SnapshotBucketCounts[i] = this.histogramBuckets.RunningBucketCounts[i]; + if (outputDelta) + { + this.histogramBuckets.RunningBucketCounts[i] = 0; + } + } + + this.MetricPointStatus = MetricPointStatus.NoCollectPending; + + // Release lock + Interlocked.Exchange(ref this.histogramBuckets.IsCriticalSectionOccupied, 0); + break; + } + + sw.SpinOnce(); + } + + break; + } + + case AggregationType.HistogramSumCountMinMax: + { + var sw = default(SpinWait); + while (true) + { + if (Interlocked.Exchange(ref this.histogramBuckets.IsCriticalSectionOccupied, 1) == 0) + { + // Lock acquired + this.snapshotValue.AsLong = this.runningValue.AsLong; + this.histogramBuckets.SnapshotSum = this.histogramBuckets.RunningSum; + this.histogramBuckets.SnapshotMin = this.histogramBuckets.RunningMin; + this.histogramBuckets.SnapshotMax = this.histogramBuckets.RunningMax; + if (outputDelta) { this.runningValue.AsLong = 0; this.histogramBuckets.RunningSum = 0; + this.histogramBuckets.RunningMin = double.PositiveInfinity; + this.histogramBuckets.RunningMax = double.NegativeInfinity; } this.MetricPointStatus = MetricPointStatus.NoCollectPending; diff --git a/src/OpenTelemetry/Metrics/MetricReaderExt.cs b/src/OpenTelemetry/Metrics/MetricReaderExt.cs index c8cb0db0a0e..4aa6769f346 100644 --- a/src/OpenTelemetry/Metrics/MetricReaderExt.cs +++ b/src/OpenTelemetry/Metrics/MetricReaderExt.cs @@ -139,7 +139,7 @@ internal List AddMetricsListWithViews(Instrument instrument, List AddMetricsListWithViews(Instrument instrument, List public class MetricReaderOptions { - private PeriodicExportingMetricReaderOptions? periodicExportingMetricReaderOptions; + private PeriodicExportingMetricReaderOptions periodicExportingMetricReaderOptions; + + /// + /// Initializes a new instance of the class. + /// + public MetricReaderOptions() + : this(new ConfigurationBuilder().AddEnvironmentVariables().Build()) + { + } + + internal MetricReaderOptions(IConfiguration configuration) + { + this.periodicExportingMetricReaderOptions = new PeriodicExportingMetricReaderOptions(configuration); + } /// /// Gets or sets the . @@ -33,11 +47,11 @@ public class MetricReaderOptions public MetricReaderTemporalityPreference TemporalityPreference { get; set; } = MetricReaderTemporalityPreference.Cumulative; /// - /// Gets or sets the . + /// Gets or sets the . /// public PeriodicExportingMetricReaderOptions PeriodicExportingMetricReaderOptions { - get => this.periodicExportingMetricReaderOptions ??= new(); + get => this.periodicExportingMetricReaderOptions; set { Guard.ThrowIfNull(value); diff --git a/src/OpenTelemetry/Metrics/MetricReaderTemporalityPreference.cs b/src/OpenTelemetry/Metrics/MetricReaderTemporalityPreference.cs index bbfc6d384c5..4443c4bb4a1 100644 --- a/src/OpenTelemetry/Metrics/MetricReaderTemporalityPreference.cs +++ b/src/OpenTelemetry/Metrics/MetricReaderTemporalityPreference.cs @@ -23,7 +23,7 @@ namespace OpenTelemetry.Metrics; public enum MetricReaderTemporalityPreference { /// - /// All aggregations are performed using cumulative temporatlity. + /// All aggregations are performed using cumulative temporality. /// Cumulative = 1, diff --git a/src/OpenTelemetry/Metrics/MetricStreamIdentity.cs b/src/OpenTelemetry/Metrics/MetricStreamIdentity.cs index 1bb9f544491..9039aa7612c 100644 --- a/src/OpenTelemetry/Metrics/MetricStreamIdentity.cs +++ b/src/OpenTelemetry/Metrics/MetricStreamIdentity.cs @@ -36,6 +36,7 @@ public MetricStreamIdentity(Instrument instrument, MetricStreamConfiguration met this.MetricStreamName = $"{this.MeterName}.{this.MeterVersion}.{this.InstrumentName}"; this.TagKeys = metricStreamConfiguration?.CopiedTagKeys; this.HistogramBucketBounds = (metricStreamConfiguration as ExplicitBucketHistogramConfiguration)?.CopiedBoundaries; + this.HistogramRecordMinMax = (metricStreamConfiguration as HistogramConfiguration)?.RecordMinMax ?? true; unchecked { @@ -44,6 +45,7 @@ public MetricStreamIdentity(Instrument instrument, MetricStreamConfiguration met hash = (hash * 31) + this.MeterName.GetHashCode(); hash = (hash * 31) + this.MeterVersion.GetHashCode(); hash = (hash * 31) + this.InstrumentName.GetHashCode(); + hash = (hash * 31) + this.HistogramRecordMinMax.GetHashCode(); hash = this.Unit == null ? hash : (hash * 31) + this.Unit.GetHashCode(); hash = this.Description == null ? hash : (hash * 31) + this.Description.GetHashCode(); hash = !this.ViewId.HasValue ? hash : (hash * 31) + this.ViewId.Value; @@ -81,6 +83,8 @@ public MetricStreamIdentity(Instrument instrument, MetricStreamConfiguration met public double[] HistogramBucketBounds { get; } + public bool HistogramRecordMinMax { get; } + public static bool operator ==(MetricStreamIdentity metricIdentity1, MetricStreamIdentity metricIdentity2) => metricIdentity1.Equals(metricIdentity2); public static bool operator !=(MetricStreamIdentity metricIdentity1, MetricStreamIdentity metricIdentity2) => !metricIdentity1.Equals(metricIdentity2); @@ -99,6 +103,7 @@ public bool Equals(MetricStreamIdentity other) && this.Unit == other.Unit && this.Description == other.Description && this.ViewId == other.ViewId + && this.HistogramRecordMinMax == other.HistogramRecordMinMax && StringArrayComparer.Equals(this.TagKeys, other.TagKeys) && HistogramBoundsEqual(this.HistogramBucketBounds, other.HistogramBucketBounds); } diff --git a/src/OpenTelemetry/Metrics/PeriodicExportingMetricReaderOptions.cs b/src/OpenTelemetry/Metrics/PeriodicExportingMetricReaderOptions.cs index a8072a0e400..b3d62913220 100644 --- a/src/OpenTelemetry/Metrics/PeriodicExportingMetricReaderOptions.cs +++ b/src/OpenTelemetry/Metrics/PeriodicExportingMetricReaderOptions.cs @@ -14,10 +14,37 @@ // limitations under the License. // +using Microsoft.Extensions.Configuration; +using OpenTelemetry.Internal; + namespace OpenTelemetry.Metrics { public class PeriodicExportingMetricReaderOptions { + internal const string OTelMetricExportIntervalEnvVarKey = "OTEL_METRIC_EXPORT_INTERVAL"; + internal const string OTelMetricExportTimeoutEnvVarKey = "OTEL_METRIC_EXPORT_TIMEOUT"; + + /// + /// Initializes a new instance of the class. + /// + public PeriodicExportingMetricReaderOptions() + : this(new ConfigurationBuilder().AddEnvironmentVariables().Build()) + { + } + + internal PeriodicExportingMetricReaderOptions(IConfiguration configuration) + { + if (configuration.TryGetIntValue(OTelMetricExportIntervalEnvVarKey, out var interval)) + { + this.ExportIntervalMilliseconds = interval; + } + + if (configuration.TryGetIntValue(OTelMetricExportTimeoutEnvVarKey, out var timeout)) + { + this.ExportTimeoutMilliseconds = timeout; + } + } + /// /// Gets or sets the metric export interval in milliseconds. /// If not set, the default value depends on the type of metric exporter diff --git a/src/OpenTelemetry/Metrics/StringArrayEqualityComparer.cs b/src/OpenTelemetry/Metrics/StringArrayEqualityComparer.cs index 6a91f201eae..579325cef2a 100644 --- a/src/OpenTelemetry/Metrics/StringArrayEqualityComparer.cs +++ b/src/OpenTelemetry/Metrics/StringArrayEqualityComparer.cs @@ -19,7 +19,7 @@ namespace OpenTelemetry.Metrics { - internal class StringArrayEqualityComparer : IEqualityComparer + internal sealed class StringArrayEqualityComparer : IEqualityComparer { public bool Equals(string[] strings1, string[] strings2) { diff --git a/src/OpenTelemetry/Metrics/ThreadStaticStorage.cs b/src/OpenTelemetry/Metrics/ThreadStaticStorage.cs index e473cfdb8af..cee643afa99 100644 --- a/src/OpenTelemetry/Metrics/ThreadStaticStorage.cs +++ b/src/OpenTelemetry/Metrics/ThreadStaticStorage.cs @@ -21,7 +21,7 @@ namespace OpenTelemetry.Metrics { - internal class ThreadStaticStorage + internal sealed class ThreadStaticStorage { private const int MaxTagCacheSize = 8; @@ -150,7 +150,7 @@ internal void CloneKeysAndValues(string[] inputTagKeys, object[] inputTagValues, } } - internal class TagStorage + internal sealed class TagStorage { // Used to split into Key sequence, Value sequence. internal readonly string[] TagKeys; diff --git a/src/OpenTelemetry/OpenTelemetry.csproj b/src/OpenTelemetry/OpenTelemetry.csproj index 542fcc9e407..c05c686b45b 100644 --- a/src/OpenTelemetry/OpenTelemetry.csproj +++ b/src/OpenTelemetry/OpenTelemetry.csproj @@ -17,8 +17,10 @@ + + diff --git a/src/OpenTelemetry/ProviderExtensions.cs b/src/OpenTelemetry/ProviderExtensions.cs index bfefeb09b55..c967965ff37 100644 --- a/src/OpenTelemetry/ProviderExtensions.cs +++ b/src/OpenTelemetry/ProviderExtensions.cs @@ -63,7 +63,23 @@ public static Resource GetResource(this BaseProvider baseProvider) /// if found otherwise . public static Resource GetDefaultResource(this BaseProvider baseProvider) { - return ResourceBuilder.CreateDefault().Build(); + var builder = ResourceBuilder.CreateDefault(); + builder.ServiceProvider = GetServiceProvider(baseProvider); + return builder.Build(); + } + + internal static IServiceProvider? GetServiceProvider(this BaseProvider baseProvider) + { + if (baseProvider is TracerProviderSdk tracerProviderSdk) + { + return tracerProviderSdk.ServiceProvider; + } + else if (baseProvider is MeterProviderSdk meterProviderSdk) + { + return meterProviderSdk.ServiceProvider; + } + + return null; } internal static Action? GetObservableInstrumentCollectCallback(this BaseProvider baseProvider) diff --git a/src/OpenTelemetry/ReadOnlyTagCollection.cs b/src/OpenTelemetry/ReadOnlyTagCollection.cs index fdbfeeaa7de..27cdaabbaaf 100644 --- a/src/OpenTelemetry/ReadOnlyTagCollection.cs +++ b/src/OpenTelemetry/ReadOnlyTagCollection.cs @@ -14,7 +14,11 @@ // limitations under the License. // +#nullable enable + +using System; using System.Collections.Generic; +using System.Diagnostics; namespace OpenTelemetry { @@ -28,16 +32,18 @@ public readonly struct ReadOnlyTagCollection private readonly string[] keys; private readonly object[] values; - internal ReadOnlyTagCollection(string[] keys, object[] values) + internal ReadOnlyTagCollection(string[]? keys, object[]? values) { - this.keys = keys; - this.values = values; + this.keys = keys ?? Array.Empty(); + this.values = values ?? Array.Empty(); + + Debug.Assert(this.keys.Length == this.values.Length, "Array length mismatch"); } /// /// Gets the number of tags in the collection. /// - public int Count => this.keys?.Length ?? 0; + public int Count => this.keys.Length; /// /// Returns an enumerator that iterates through the tags. diff --git a/src/OpenTelemetry/Resources/IResourceDetector.cs b/src/OpenTelemetry/Resources/IResourceDetector.cs index a55459807db..df3fdf427d5 100644 --- a/src/OpenTelemetry/Resources/IResourceDetector.cs +++ b/src/OpenTelemetry/Resources/IResourceDetector.cs @@ -14,6 +14,8 @@ // limitations under the License. // +#nullable enable + namespace OpenTelemetry.Resources { /// diff --git a/src/OpenTelemetry/Resources/OtelEnvResourceDetector.cs b/src/OpenTelemetry/Resources/OtelEnvResourceDetector.cs index fd78b3eba4f..b0e893618dc 100644 --- a/src/OpenTelemetry/Resources/OtelEnvResourceDetector.cs +++ b/src/OpenTelemetry/Resources/OtelEnvResourceDetector.cs @@ -14,24 +14,34 @@ // limitations under the License. // +#nullable enable + using System.Collections.Generic; +using Microsoft.Extensions.Configuration; using OpenTelemetry.Internal; namespace OpenTelemetry.Resources { - internal class OtelEnvResourceDetector : IResourceDetector + internal sealed class OtelEnvResourceDetector : IResourceDetector { public const string EnvVarKey = "OTEL_RESOURCE_ATTRIBUTES"; private const char AttributeListSplitter = ','; private const char AttributeKeyValueSplitter = '='; + private readonly IConfiguration configuration; + + public OtelEnvResourceDetector(IConfiguration configuration) + { + this.configuration = configuration; + } + public Resource Detect() { var resource = Resource.Empty; - if (EnvironmentVariableHelper.LoadString(EnvVarKey, out string envResourceAttributeValue)) + if (this.configuration.TryGetStringValue(EnvVarKey, out string? envResourceAttributeValue)) { - var attributes = ParseResourceAttributes(envResourceAttributeValue); + var attributes = ParseResourceAttributes(envResourceAttributeValue!); resource = new Resource(attributes); } diff --git a/src/OpenTelemetry/Resources/OtelServiceNameEnvVarDetector.cs b/src/OpenTelemetry/Resources/OtelServiceNameEnvVarDetector.cs index 5233f2004a4..9b48f113956 100644 --- a/src/OpenTelemetry/Resources/OtelServiceNameEnvVarDetector.cs +++ b/src/OpenTelemetry/Resources/OtelServiceNameEnvVarDetector.cs @@ -14,24 +14,34 @@ // limitations under the License. // +#nullable enable + using System.Collections.Generic; +using Microsoft.Extensions.Configuration; using OpenTelemetry.Internal; namespace OpenTelemetry.Resources { - internal class OtelServiceNameEnvVarDetector : IResourceDetector + internal sealed class OtelServiceNameEnvVarDetector : IResourceDetector { public const string EnvVarKey = "OTEL_SERVICE_NAME"; + private readonly IConfiguration configuration; + + public OtelServiceNameEnvVarDetector(IConfiguration configuration) + { + this.configuration = configuration; + } + public Resource Detect() { var resource = Resource.Empty; - if (EnvironmentVariableHelper.LoadString(EnvVarKey, out string envResourceAttributeValue)) + if (this.configuration.TryGetStringValue(EnvVarKey, out string? envResourceAttributeValue)) { resource = new Resource(new Dictionary { - [ResourceSemanticConventions.AttributeServiceName] = envResourceAttributeValue, + [ResourceSemanticConventions.AttributeServiceName] = envResourceAttributeValue!, }); } diff --git a/src/OpenTelemetry/Resources/Resource.cs b/src/OpenTelemetry/Resources/Resource.cs index ef2f0459879..f6e82e2ffa4 100644 --- a/src/OpenTelemetry/Resources/Resource.cs +++ b/src/OpenTelemetry/Resources/Resource.cs @@ -14,6 +14,8 @@ // limitations under the License. // +#nullable enable + using System; using System.Collections.Generic; using System.Globalization; diff --git a/src/OpenTelemetry/Resources/ResourceBuilder.cs b/src/OpenTelemetry/Resources/ResourceBuilder.cs index fec087699c1..7c1ef54fdaa 100644 --- a/src/OpenTelemetry/Resources/ResourceBuilder.cs +++ b/src/OpenTelemetry/Resources/ResourceBuilder.cs @@ -14,6 +14,9 @@ // limitations under the License. // +#nullable enable + +using System; using System.Collections.Generic; using System.Diagnostics; using OpenTelemetry.Internal; @@ -25,7 +28,8 @@ namespace OpenTelemetry.Resources /// public class ResourceBuilder { - internal readonly List Resources = new(); + internal readonly List ResourceDetectors = new(); + private static readonly Resource DefaultResource; static ResourceBuilder() { @@ -54,7 +58,7 @@ private ResourceBuilder() { } - private static Resource DefaultResource { get; } + internal IServiceProvider? ServiceProvider { get; set; } /// /// Creates a instance with Default @@ -83,7 +87,7 @@ public static ResourceBuilder CreateEmpty() /// for chaining. public ResourceBuilder Clear() { - this.Resources.Clear(); + this.ResourceDetectors.Clear(); return this; } @@ -96,24 +100,55 @@ public Resource Build() { Resource finalResource = Resource.Empty; - foreach (Resource resource in this.Resources) + foreach (IResourceDetector resourceDetector in this.ResourceDetectors) { - finalResource = finalResource.Merge(resource); + if (resourceDetector is ResolvingResourceDetector resolvingResourceDetector) + { + resolvingResourceDetector.Resolve(this.ServiceProvider); + } + + var resource = resourceDetector.Detect(); + if (resource != null) + { + finalResource = finalResource.Merge(resource); + } } return finalResource; } + /// + /// Add a to the builder. + /// + /// . + /// Supplied for call chaining. public ResourceBuilder AddDetector(IResourceDetector resourceDetector) { Guard.ThrowIfNull(resourceDetector); - Resource resource = resourceDetector.Detect(); + this.ResourceDetectors.Add(resourceDetector); - if (resource != null) - { - this.Resources.Add(resource); - } + return this; + } + + /// + /// Add a to the builder which will be resolved using the application . + /// + /// + /// Note: The supplied may be + /// called with a + /// for detached instances. Factories + /// should either throw if a cannot be handled, + /// or return a default when is not available. + /// + /// Resource detector factory. + /// Supplied for call chaining. + public ResourceBuilder AddDetector(Func resourceDetectorFactory) + { + Guard.ThrowIfNull(resourceDetectorFactory); + + this.ResourceDetectors.Add(new ResolvingResourceDetector(resourceDetectorFactory)); return this; } @@ -122,9 +157,47 @@ internal ResourceBuilder AddResource(Resource resource) { Guard.ThrowIfNull(resource); - this.Resources.Add(resource); + this.ResourceDetectors.Add(new WrapperResourceDetector(resource)); return this; } + + internal sealed class WrapperResourceDetector : IResourceDetector + { + private readonly Resource resource; + + public WrapperResourceDetector(Resource resource) + { + this.resource = resource; + } + + public Resource Detect() => this.resource; + } + + private sealed class ResolvingResourceDetector : IResourceDetector + { + private readonly Func resourceDetectorFactory; + private IResourceDetector? resourceDetector; + + public ResolvingResourceDetector(Func resourceDetectorFactory) + { + this.resourceDetectorFactory = resourceDetectorFactory; + } + + public void Resolve(IServiceProvider? serviceProvider) + { + this.resourceDetector = this.resourceDetectorFactory(serviceProvider) + ?? throw new InvalidOperationException("ResourceDetector factory did not return a ResourceDetector instance."); + } + + public Resource Detect() + { + var detector = this.resourceDetector; + + Debug.Assert(detector != null, "detector was null"); + + return detector?.Detect() ?? Resource.Empty; + } + } } } diff --git a/src/OpenTelemetry/Resources/ResourceBuilderExtensions.cs b/src/OpenTelemetry/Resources/ResourceBuilderExtensions.cs index 338ef61341b..c68ee7ece59 100644 --- a/src/OpenTelemetry/Resources/ResourceBuilderExtensions.cs +++ b/src/OpenTelemetry/Resources/ResourceBuilderExtensions.cs @@ -14,9 +14,13 @@ // limitations under the License. // +#nullable enable + using System; using System.Collections.Generic; using System.Reflection; +using Microsoft.Extensions.Configuration; +using Microsoft.Extensions.DependencyInjection; using OpenTelemetry.Internal; namespace OpenTelemetry.Resources @@ -49,10 +53,10 @@ public static class ResourceBuilderExtensions public static ResourceBuilder AddService( this ResourceBuilder resourceBuilder, string serviceName, - string serviceNamespace = null, - string serviceVersion = null, + string? serviceNamespace = null, + string? serviceVersion = null, bool autoGenerateServiceInstanceId = true, - string serviceInstanceId = null) + string? serviceInstanceId = null) { Dictionary resourceAttributes = new Dictionary(); @@ -62,12 +66,12 @@ public static ResourceBuilder AddService( if (!string.IsNullOrEmpty(serviceNamespace)) { - resourceAttributes.Add(ResourceSemanticConventions.AttributeServiceNamespace, serviceNamespace); + resourceAttributes.Add(ResourceSemanticConventions.AttributeServiceNamespace, serviceNamespace!); } if (!string.IsNullOrEmpty(serviceVersion)) { - resourceAttributes.Add(ResourceSemanticConventions.AttributeServiceVersion, serviceVersion); + resourceAttributes.Add(ResourceSemanticConventions.AttributeServiceVersion, serviceVersion!); } if (serviceInstanceId == null && autoGenerateServiceInstanceId) @@ -117,7 +121,11 @@ public static ResourceBuilder AddAttributes(this ResourceBuilder resourceBuilder /// Returns for chaining. public static ResourceBuilder AddEnvironmentVariableDetector(this ResourceBuilder resourceBuilder) { - return resourceBuilder.AddDetector(new OtelEnvResourceDetector()).AddDetector(new OtelServiceNameEnvVarDetector()); + Lazy configuration = new Lazy(() => new ConfigurationBuilder().AddEnvironmentVariables().Build()); + + return resourceBuilder + .AddDetector(sp => new OtelEnvResourceDetector(sp?.GetService() ?? configuration.Value)) + .AddDetector(sp => new OtelServiceNameEnvVarDetector(sp?.GetService() ?? configuration.Value)); } private static string GetFileVersion() diff --git a/src/OpenTelemetry/SuppressInstrumentationScope.cs b/src/OpenTelemetry/SuppressInstrumentationScope.cs index 6c155df5c3c..014c0743bdc 100644 --- a/src/OpenTelemetry/SuppressInstrumentationScope.cs +++ b/src/OpenTelemetry/SuppressInstrumentationScope.cs @@ -14,6 +14,8 @@ // limitations under the License. // +#nullable enable + using System; using System.Runtime.CompilerServices; using OpenTelemetry.Context; diff --git a/src/OpenTelemetry/Trace/AlwaysOffSampler.cs b/src/OpenTelemetry/Trace/AlwaysOffSampler.cs index 9615a7de283..30fd0768d00 100644 --- a/src/OpenTelemetry/Trace/AlwaysOffSampler.cs +++ b/src/OpenTelemetry/Trace/AlwaysOffSampler.cs @@ -14,6 +14,8 @@ // limitations under the License. // +#nullable enable + namespace OpenTelemetry.Trace { /// diff --git a/src/OpenTelemetry/Trace/AlwaysOnSampler.cs b/src/OpenTelemetry/Trace/AlwaysOnSampler.cs index aa1edda0037..bee15b682bd 100644 --- a/src/OpenTelemetry/Trace/AlwaysOnSampler.cs +++ b/src/OpenTelemetry/Trace/AlwaysOnSampler.cs @@ -14,6 +14,8 @@ // limitations under the License. // +#nullable enable + namespace OpenTelemetry.Trace { /// diff --git a/src/OpenTelemetry/Trace/BatchActivityExportProcessor.cs b/src/OpenTelemetry/Trace/BatchActivityExportProcessor.cs index be62c8d015c..089b848815f 100644 --- a/src/OpenTelemetry/Trace/BatchActivityExportProcessor.cs +++ b/src/OpenTelemetry/Trace/BatchActivityExportProcessor.cs @@ -14,6 +14,8 @@ // limitations under the License. // +#nullable enable + using System.Diagnostics; namespace OpenTelemetry diff --git a/src/OpenTelemetry/Trace/BatchExportActivityProcessorOptions.cs b/src/OpenTelemetry/Trace/BatchExportActivityProcessorOptions.cs index 5b78df251cb..8ea8890e8ba 100644 --- a/src/OpenTelemetry/Trace/BatchExportActivityProcessorOptions.cs +++ b/src/OpenTelemetry/Trace/BatchExportActivityProcessorOptions.cs @@ -14,8 +14,11 @@ // limitations under the License. // +#nullable enable + using System; using System.Diagnostics; +using Microsoft.Extensions.Configuration; using OpenTelemetry.Internal; namespace OpenTelemetry.Trace @@ -39,26 +42,36 @@ public class BatchExportActivityProcessorOptions : BatchExportProcessorOptions + /// Initializes a new instance of the class. + /// public BatchExportActivityProcessorOptions() + : this(new ConfigurationBuilder().AddEnvironmentVariables().Build()) { - int value; + } - if (EnvironmentVariableHelper.LoadNumeric(ExporterTimeoutEnvVarKey, out value)) + /// + /// Initializes a new instance of the class. + /// + /// . + public BatchExportActivityProcessorOptions(IConfiguration configuration) + { + if (configuration.TryGetIntValue(ExporterTimeoutEnvVarKey, out int value)) { this.ExporterTimeoutMilliseconds = value; } - if (EnvironmentVariableHelper.LoadNumeric(MaxExportBatchSizeEnvVarKey, out value)) + if (configuration.TryGetIntValue(MaxExportBatchSizeEnvVarKey, out value)) { this.MaxExportBatchSize = value; } - if (EnvironmentVariableHelper.LoadNumeric(MaxQueueSizeEnvVarKey, out value)) + if (configuration.TryGetIntValue(MaxQueueSizeEnvVarKey, out value)) { this.MaxQueueSize = value; } - if (EnvironmentVariableHelper.LoadNumeric(ScheduledDelayEnvVarKey, out value)) + if (configuration.TryGetIntValue(ScheduledDelayEnvVarKey, out value)) { this.ScheduledDelayMilliseconds = value; } diff --git a/src/OpenTelemetry/Trace/Builder/TracerProviderBuilderBase.cs b/src/OpenTelemetry/Trace/Builder/TracerProviderBuilderBase.cs index cfb0c28fb8a..8ca84ba3f1c 100644 --- a/src/OpenTelemetry/Trace/Builder/TracerProviderBuilderBase.cs +++ b/src/OpenTelemetry/Trace/Builder/TracerProviderBuilderBase.cs @@ -50,14 +50,15 @@ internal TracerProviderBuilderBase(TracerProviderBuilderState state) this.State = state; } - // This ctor is for AddOpenTelemetryTracing scenario where the builder - // is bound to an external service collection. + // This ctor is for ConfigureOpenTelemetryTracing + + // AddOpenTelemetryTracing scenarios where the builder is bound to an + // external service collection. internal TracerProviderBuilderBase(IServiceCollection services) { Debug.Assert(services != null, "services was null"); - services.AddOptions(); - services.TryAddSingleton(sp => new TracerProviderSdk(sp, ownsServiceProvider: false)); + services!.AddOpenTelemetryTracerProviderBuilderServices(); + services!.TryAddSingleton(sp => new TracerProviderSdk(sp, ownsServiceProvider: false)); this.services = services; this.ownsServices = false; @@ -69,7 +70,9 @@ protected TracerProviderBuilderBase() { var services = new ServiceCollection(); - services.AddOptions(); + services.AddOpenTelemetryTracerProviderBuilderServices(); + services.AddSingleton( + sp => throw new NotSupportedException("External TracerProvider created through Sdk.CreateTracerProviderBuilder cannot be accessed using service provider.")); this.services = services; this.ownsServices = true; diff --git a/src/OpenTelemetry/Trace/Builder/TracerProviderBuilderState.cs b/src/OpenTelemetry/Trace/Builder/TracerProviderBuilderState.cs index bb0629c1839..f446834249b 100644 --- a/src/OpenTelemetry/Trace/Builder/TracerProviderBuilderState.cs +++ b/src/OpenTelemetry/Trace/Builder/TracerProviderBuilderState.cs @@ -30,10 +30,8 @@ internal sealed class TracerProviderBuilderState : ProviderBuilderState +#nullable enable + using System; using System.Diagnostics; using System.Linq.Expressions; @@ -33,7 +35,8 @@ public ExceptionProcessor() try { var flags = BindingFlags.Static | BindingFlags.Public; - var method = typeof(Marshal).GetMethod("GetExceptionPointers", flags, null, new Type[] { }, null); + var method = typeof(Marshal).GetMethod("GetExceptionPointers", flags, null, Type.EmptyTypes, null) + ?? throw new InvalidOperationException("Marshal.GetExceptionPointers method could not be resolved reflectively."); var lambda = Expression.Lambda>(Expression.Call(method)); this.fnGetExceptionPointers = lambda.Compile(); } diff --git a/src/OpenTelemetry/Trace/ExportActivityProcessorOptions.cs b/src/OpenTelemetry/Trace/ExportActivityProcessorOptions.cs index 450e893e83d..173dc960a26 100644 --- a/src/OpenTelemetry/Trace/ExportActivityProcessorOptions.cs +++ b/src/OpenTelemetry/Trace/ExportActivityProcessorOptions.cs @@ -16,13 +16,30 @@ #nullable enable +using Microsoft.Extensions.Configuration; using OpenTelemetry.Internal; namespace OpenTelemetry.Trace; +/// +/// Options for configuring either a or . +/// public class ExportActivityProcessorOptions { - private BatchExportActivityProcessorOptions? batchExportProcessorOptions; + private BatchExportActivityProcessorOptions batchExportProcessorOptions; + + /// + /// Initializes a new instance of the class. + /// + public ExportActivityProcessorOptions() + : this(new ConfigurationBuilder().AddEnvironmentVariables().Build()) + { + } + + internal ExportActivityProcessorOptions(IConfiguration configuration) + { + this.batchExportProcessorOptions = new BatchExportActivityProcessorOptions(configuration); + } /// /// Gets or sets the export processor type to be used. The default value is . @@ -34,7 +51,7 @@ public class ExportActivityProcessorOptions /// public BatchExportActivityProcessorOptions BatchExportProcessorOptions { - get => this.batchExportProcessorOptions ??= new(); + get => this.batchExportProcessorOptions; set { Guard.ThrowIfNull(value); diff --git a/src/OpenTelemetry/Trace/ParentBasedSampler.cs b/src/OpenTelemetry/Trace/ParentBasedSampler.cs index deb9d0eb3ec..26c5c564173 100644 --- a/src/OpenTelemetry/Trace/ParentBasedSampler.cs +++ b/src/OpenTelemetry/Trace/ParentBasedSampler.cs @@ -14,6 +14,8 @@ // limitations under the License. // +#nullable enable + using System.Diagnostics; using OpenTelemetry.Internal; @@ -81,10 +83,10 @@ public ParentBasedSampler(Sampler rootSampler) /// public ParentBasedSampler( Sampler rootSampler, - Sampler remoteParentSampled = null, - Sampler remoteParentNotSampled = null, - Sampler localParentSampled = null, - Sampler localParentNotSampled = null) + Sampler? remoteParentSampled = null, + Sampler? remoteParentNotSampled = null, + Sampler? localParentSampled = null, + Sampler? localParentNotSampled = null) : this(rootSampler) { this.remoteParentSampled = remoteParentSampled ?? new AlwaysOnSampler(); diff --git a/src/OpenTelemetry/Trace/Sampler.cs b/src/OpenTelemetry/Trace/Sampler.cs index ba66c7e7226..331a090fc6c 100644 --- a/src/OpenTelemetry/Trace/Sampler.cs +++ b/src/OpenTelemetry/Trace/Sampler.cs @@ -13,6 +13,9 @@ // See the License for the specific language governing permissions and // limitations under the License. // + +#nullable enable + using System.Diagnostics; namespace OpenTelemetry.Trace diff --git a/src/OpenTelemetry/Trace/SamplingDecision.cs b/src/OpenTelemetry/Trace/SamplingDecision.cs index a8f072845d6..514afc909e7 100644 --- a/src/OpenTelemetry/Trace/SamplingDecision.cs +++ b/src/OpenTelemetry/Trace/SamplingDecision.cs @@ -14,6 +14,8 @@ // limitations under the License. // +#nullable enable + namespace OpenTelemetry.Trace { /// diff --git a/src/OpenTelemetry/Trace/SamplingParameters.cs b/src/OpenTelemetry/Trace/SamplingParameters.cs index defa5319b6c..089c1ee63a1 100644 --- a/src/OpenTelemetry/Trace/SamplingParameters.cs +++ b/src/OpenTelemetry/Trace/SamplingParameters.cs @@ -14,6 +14,8 @@ // limitations under the License. // +#nullable enable + using System.Collections.Generic; using System.Diagnostics; @@ -42,15 +44,19 @@ public SamplingParameters( ActivityTraceId traceId, string name, ActivityKind kind, - IEnumerable> tags = null, - IEnumerable links = null) + IEnumerable>? tags = null, + IEnumerable? links = null) { this.ParentContext = parentContext; this.TraceId = traceId; - this.Name = name; this.Kind = kind; this.Tags = tags; this.Links = links; + + // Note: myActivitySource.StartActivity(name: null) is currently + // allowed even though OTel spec says span name is required. See: + // https://github.com/open-telemetry/opentelemetry-dotnet/issues/3802 + this.Name = name ?? string.Empty; } /// @@ -81,11 +87,11 @@ public SamplingParameters( /// Gets the tags to be associated to the span/activity to be created. /// These are the tags provided at the time of Activity creation. /// - public IEnumerable> Tags { get; } + public IEnumerable>? Tags { get; } /// /// Gets the links to be added to the activity to be created. /// - public IEnumerable Links { get; } + public IEnumerable? Links { get; } } } diff --git a/src/OpenTelemetry/Trace/SamplingResult.cs b/src/OpenTelemetry/Trace/SamplingResult.cs index ccdaa5c9d94..fe8ca36184a 100644 --- a/src/OpenTelemetry/Trace/SamplingResult.cs +++ b/src/OpenTelemetry/Trace/SamplingResult.cs @@ -14,6 +14,9 @@ // limitations under the License. // +#nullable enable + +using System; using System.Collections.Generic; using System.Linq; @@ -22,17 +25,15 @@ namespace OpenTelemetry.Trace /// /// Sampling result. /// - public readonly struct SamplingResult : System.IEquatable + public readonly struct SamplingResult : IEquatable { /// /// Initializes a new instance of the struct. /// /// indicates whether an activity object is recorded and sampled. public SamplingResult(SamplingDecision decision) + : this(decision, attributes: null, traceStateString: null) { - this.Decision = decision; - this.Attributes = Enumerable.Empty>(); - this.TraceStateString = null; } /// @@ -40,10 +41,8 @@ public SamplingResult(SamplingDecision decision) /// /// True if sampled, false otherwise. public SamplingResult(bool isSampled) + : this(decision: isSampled ? SamplingDecision.RecordAndSample : SamplingDecision.Drop, attributes: null, traceStateString: null) { - this.Decision = isSampled ? SamplingDecision.RecordAndSample : SamplingDecision.Drop; - this.Attributes = Enumerable.Empty>(); - this.TraceStateString = null; } /// @@ -53,14 +52,8 @@ public SamplingResult(bool isSampled) /// Attributes associated with the sampling decision. Attributes list passed to /// this method must be immutable. Mutations of the collection and/or attribute values may lead to unexpected behavior. public SamplingResult(SamplingDecision decision, IEnumerable> attributes) + : this(decision, attributes, traceStateString: null) { - this.Decision = decision; - - // Note: Decision object takes ownership of the collection. - // Current implementation has no means to ensure the collection will not be modified by the caller. - // If this behavior will be abused we must switch to cloning of the collection. - this.Attributes = attributes; - this.TraceStateString = null; } /// @@ -69,10 +62,8 @@ public SamplingResult(SamplingDecision decision, IEnumerableindicates whether an activity object is recorded and sampled. /// traceStateString associated with the created Activity. public SamplingResult(SamplingDecision decision, string traceStateString) + : this(decision, attributes: null, traceStateString) { - this.Decision = decision; - this.Attributes = Enumerable.Empty>(); - this.TraceStateString = traceStateString; } /// @@ -82,14 +73,14 @@ public SamplingResult(SamplingDecision decision, string traceStateString) /// attributes associated with the sampling decision. Attributes list passed to /// this method must be immutable. Mutations of the collection and/or attribute values may lead to unexpected behavior. /// traceStateString associated with the created Activity. - public SamplingResult(SamplingDecision decision, IEnumerable> attributes, string traceStateString) + public SamplingResult(SamplingDecision decision, IEnumerable>? attributes, string? traceStateString) { this.Decision = decision; // Note: Decision object takes ownership of the collection. // Current implementation has no means to ensure the collection will not be modified by the caller. // If this behavior will be abused we must switch to cloning of the collection. - this.Attributes = attributes; + this.Attributes = attributes ?? Enumerable.Empty>(); this.TraceStateString = traceStateString; } @@ -107,7 +98,7 @@ public SamplingResult(SamplingDecision decision, IEnumerable /// Gets the tracestate. /// - public string TraceStateString { get; } + public string? TraceStateString { get; } /// /// Compare two for equality. @@ -124,16 +115,8 @@ public SamplingResult(SamplingDecision decision, IEnumerable !decision1.Equals(decision2); /// - public override bool Equals(object obj) - { - if (obj is not SamplingResult) - { - return false; - } - - var that = (SamplingResult)obj; - return this.Decision == that.Decision && this.Attributes == that.Attributes && this.TraceStateString == that.TraceStateString; - } + public override bool Equals(object? obj) + => obj is SamplingResult other && this.Equals(other); /// public override int GetHashCode() @@ -148,7 +131,9 @@ public override int GetHashCode() /// public bool Equals(SamplingResult other) { - return this.Decision == other.Decision && this.Attributes.SequenceEqual(other.Attributes) && this.TraceStateString == other.TraceStateString; + return this.Decision == other.Decision + && this.Attributes.SequenceEqual(other.Attributes) + && this.TraceStateString == other.TraceStateString; } } } diff --git a/src/OpenTelemetry/Trace/SimpleActivityExportProcessor.cs b/src/OpenTelemetry/Trace/SimpleActivityExportProcessor.cs index ac9a4a20c7f..7a9215f2156 100644 --- a/src/OpenTelemetry/Trace/SimpleActivityExportProcessor.cs +++ b/src/OpenTelemetry/Trace/SimpleActivityExportProcessor.cs @@ -14,6 +14,8 @@ // limitations under the License. // +#nullable enable + using System.Diagnostics; namespace OpenTelemetry diff --git a/src/OpenTelemetry/Trace/TraceIdRatioBasedSampler.cs b/src/OpenTelemetry/Trace/TraceIdRatioBasedSampler.cs index d1c9d364a85..20e00b5b66d 100644 --- a/src/OpenTelemetry/Trace/TraceIdRatioBasedSampler.cs +++ b/src/OpenTelemetry/Trace/TraceIdRatioBasedSampler.cs @@ -14,6 +14,8 @@ // limitations under the License. // +#nullable enable + using System; using System.Globalization; using OpenTelemetry.Internal; diff --git a/src/OpenTelemetry/Trace/TracerProviderSdk.cs b/src/OpenTelemetry/Trace/TracerProviderSdk.cs index 280680e1372..476ece22229 100644 --- a/src/OpenTelemetry/Trace/TracerProviderSdk.cs +++ b/src/OpenTelemetry/Trace/TracerProviderSdk.cs @@ -21,6 +21,8 @@ using System.Diagnostics; using System.Linq; using System.Runtime.CompilerServices; +using System.Text; +using Microsoft.Extensions.DependencyInjection; using OpenTelemetry.Internal; using OpenTelemetry.Resources; @@ -33,6 +35,7 @@ namespace OpenTelemetry.Trace { internal sealed class TracerProviderSdk : TracerProvider { + internal readonly IServiceProvider ServiceProvider; internal readonly IDisposable? OwnedServiceProvider; internal int ShutdownCount; internal bool Disposed; @@ -48,24 +51,37 @@ internal TracerProviderSdk( IServiceProvider serviceProvider, bool ownsServiceProvider) { + Debug.Assert(serviceProvider != null, "serviceProvider was null"); + + var state = serviceProvider!.GetRequiredService(); + state.RegisterProvider(nameof(TracerProvider), this); + + this.ServiceProvider = serviceProvider!; + if (ownsServiceProvider) { this.OwnedServiceProvider = serviceProvider as IDisposable; Debug.Assert(this.OwnedServiceProvider != null, "serviceProvider was not IDisposable"); } - var state = new TracerProviderBuilderState(serviceProvider, this); + OpenTelemetrySdkEventSource.Log.TracerProviderSdkEvent("Building TracerProvider."); CallbackHelper.InvokeRegisteredConfigureStateCallbacks( - serviceProvider, + serviceProvider!, state); + StringBuilder processorsAdded = new StringBuilder(); + StringBuilder instrumentationFactoriesAdded = new StringBuilder(); + if (state.SetErrorStatusOnException) { state.EnableErrorStatusOnException(); } - this.Resource = (state.ResourceBuilder ?? ResourceBuilder.CreateDefault()).Build(); + var resourceBuilder = state.ResourceBuilder ?? ResourceBuilder.CreateDefault(); + resourceBuilder.ServiceProvider = serviceProvider; + this.Resource = resourceBuilder.Build(); + this.sampler = state.Sampler ?? new ParentBasedSampler(new AlwaysOnSampler()); this.supportLegacyActivity = state.LegacyActivityOperationNames.Count > 0; @@ -84,11 +100,27 @@ internal TracerProviderSdk( foreach (var processor in state.Processors) { this.AddProcessor(processor); + processorsAdded.Append(processor.GetType()); + processorsAdded.Append(';'); } foreach (var instrumentation in state.Instrumentation) { this.instrumentations.Add(instrumentation.Instance); + instrumentationFactoriesAdded.Append(instrumentation.Name); + instrumentationFactoriesAdded.Append(';'); + } + + if (processorsAdded.Length != 0) + { + processorsAdded.Remove(processorsAdded.Length - 1, 1); + OpenTelemetrySdkEventSource.Log.TracerProviderSdkEvent($"Processors added = \"{processorsAdded}\"."); + } + + if (instrumentationFactoriesAdded.Length != 0) + { + instrumentationFactoriesAdded.Remove(instrumentationFactoriesAdded.Length - 1, 1); + OpenTelemetrySdkEventSource.Log.TracerProviderSdkEvent($"Instrumentations added = \"{instrumentationFactoriesAdded}\"."); } var listener = new ActivityListener(); @@ -269,6 +301,7 @@ internal TracerProviderSdk( ActivitySource.AddActivityListener(listener); this.listener = listener; + OpenTelemetrySdkEventSource.Log.TracerProviderSdkEvent("TracerProvider built successfully."); } internal Resource Resource { get; } diff --git a/test/Benchmarks/Exporter/JaegerExporterBenchmarks.cs b/test/Benchmarks/Exporter/JaegerExporterBenchmarks.cs index c13dc8654bc..b4a9d6d7855 100644 --- a/test/Benchmarks/Exporter/JaegerExporterBenchmarks.cs +++ b/test/Benchmarks/Exporter/JaegerExporterBenchmarks.cs @@ -51,10 +51,7 @@ public void JaegerExporter_Batching() using JaegerExporter exporter = new JaegerExporter( new JaegerExporterOptions(), new TCompactProtocol.Factory(), - new NoopJaegerClient()) - { - Process = new Jaeger::OpenTelemetry.Exporter.Jaeger.Implementation.Process("TestService"), - }; + new NoopJaegerClient()); for (int i = 0; i < this.NumberOfBatches; i++) { diff --git a/test/Benchmarks/Exporter/OtlpGrpcExporterBenchmarks.cs b/test/Benchmarks/Exporter/OtlpGrpcExporterBenchmarks.cs index 3f348a29f04..fc445fc041f 100644 --- a/test/Benchmarks/Exporter/OtlpGrpcExporterBenchmarks.cs +++ b/test/Benchmarks/Exporter/OtlpGrpcExporterBenchmarks.cs @@ -26,6 +26,7 @@ using OpenTelemetry; using OpenTelemetry.Internal; using OpenTelemetryProtocol::OpenTelemetry.Exporter; +using OpenTelemetryProtocol::OpenTelemetry.Exporter.OpenTelemetryProtocol.Implementation; using OpenTelemetryProtocol::OpenTelemetry.Exporter.OpenTelemetryProtocol.Implementation.ExportClient; using OtlpCollector = OpenTelemetryProtocol::OpenTelemetry.Proto.Collector.Trace.V1; @@ -58,6 +59,7 @@ public void GlobalSetup() var options = new OtlpExporterOptions(); this.exporter = new OtlpTraceExporter( options, + new SdkLimitOptions(), new OtlpGrpcTraceExportClient(options, mockClient.Object)); this.activity = ActivityHelper.CreateTestActivity(); diff --git a/test/Benchmarks/Exporter/OtlpHttpExporterBenchmarks.cs b/test/Benchmarks/Exporter/OtlpHttpExporterBenchmarks.cs index d10fe92064d..8f5004a3b9b 100644 --- a/test/Benchmarks/Exporter/OtlpHttpExporterBenchmarks.cs +++ b/test/Benchmarks/Exporter/OtlpHttpExporterBenchmarks.cs @@ -25,6 +25,7 @@ using OpenTelemetry.Internal; using OpenTelemetry.Tests; using OpenTelemetryProtocol::OpenTelemetry.Exporter; +using OpenTelemetryProtocol::OpenTelemetry.Exporter.OpenTelemetryProtocol.Implementation; using OpenTelemetryProtocol::OpenTelemetry.Exporter.OpenTelemetryProtocol.Implementation.ExportClient; namespace Benchmarks.Exporter @@ -74,6 +75,7 @@ public void GlobalSetup() }; this.exporter = new OtlpTraceExporter( options, + new SdkLimitOptions(), new OtlpHttpTraceExportClient(options, options.HttpClientFactory())); this.activity = ActivityHelper.CreateTestActivity(); diff --git a/test/OpenTelemetry.Exporter.Jaeger.Tests/JaegerExporterOptionsTests.cs b/test/OpenTelemetry.Exporter.Jaeger.Tests/JaegerExporterOptionsTests.cs index 33143faf16f..42b0548be66 100644 --- a/test/OpenTelemetry.Exporter.Jaeger.Tests/JaegerExporterOptionsTests.cs +++ b/test/OpenTelemetry.Exporter.Jaeger.Tests/JaegerExporterOptionsTests.cs @@ -15,6 +15,8 @@ // using System; +using System.Collections.Generic; +using Microsoft.Extensions.Configuration; using Xunit; namespace OpenTelemetry.Exporter.Jaeger.Tests @@ -93,6 +95,29 @@ public void JaegerExporterOptions_EnvironmentVariableNames() Assert.Equal("OTEL_EXPORTER_JAEGER_ENDPOINT", JaegerExporterOptions.OTelEndpointEnvVarKey); } + [Fact] + public void JaegerExporterOptions_FromConfigurationTest() + { + var values = new Dictionary() + { + [JaegerExporterOptions.OTelProtocolEnvVarKey] = "http/thrift.binary", + [JaegerExporterOptions.OTelAgentHostEnvVarKey] = "jaeger-host", + [JaegerExporterOptions.OTelAgentPortEnvVarKey] = "123", + [JaegerExporterOptions.OTelEndpointEnvVarKey] = "http://custom-endpoint:12345", + }; + + var configuration = new ConfigurationBuilder() + .AddInMemoryCollection(values) + .Build(); + + var options = new JaegerExporterOptions(configuration); + + Assert.Equal("jaeger-host", options.AgentHost); + Assert.Equal(123, options.AgentPort); + Assert.Equal(JaegerExportProtocol.HttpBinaryThrift, options.Protocol); + Assert.Equal(new Uri("http://custom-endpoint:12345"), options.Endpoint); + } + private static void ClearEnvVars() { Environment.SetEnvironmentVariable(JaegerExporterOptions.OTelProtocolEnvVarKey, null); diff --git a/test/OpenTelemetry.Exporter.Jaeger.Tests/JaegerExporterTests.cs b/test/OpenTelemetry.Exporter.Jaeger.Tests/JaegerExporterTests.cs index 28baef09e66..2998ce78fc0 100644 --- a/test/OpenTelemetry.Exporter.Jaeger.Tests/JaegerExporterTests.cs +++ b/test/OpenTelemetry.Exporter.Jaeger.Tests/JaegerExporterTests.cs @@ -20,6 +20,7 @@ using System.Diagnostics; using System.IO; using System.Linq; +using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; using OpenTelemetry.Exporter.Jaeger.Implementation; using OpenTelemetry.Exporter.Jaeger.Implementation.Tests; @@ -185,11 +186,9 @@ public void JaegerTraceExporter_SetResource_UpdatesServiceName() using var jaegerTraceExporter = new JaegerExporter(new JaegerExporterOptions()); var process = jaegerTraceExporter.Process; - process.ServiceName = "TestService"; - jaegerTraceExporter.SetResourceAndInitializeBatch(Resource.Empty); - Assert.Equal("TestService", process.ServiceName); + Assert.StartsWith("unknown_service:", process.ServiceName); jaegerTraceExporter.SetResourceAndInitializeBatch(ResourceBuilder.CreateEmpty().AddService("MyService").Build()); @@ -251,6 +250,34 @@ public void JaegerTraceExporter_SetResource_IgnoreServiceResources() Assert.Null(process.Tags); } + [Fact] + public void JaegerTraceExporter_SetResource_UpdatesServiceNameFromIConfiguration() + { + var tracerProviderBuilder = Sdk.CreateTracerProviderBuilder() + .ConfigureServices(services => + { + Dictionary configuration = new() + { + ["OTEL_SERVICE_NAME"] = "myservicename", + }; + + services.AddSingleton( + new ConfigurationBuilder().AddInMemoryCollection(configuration).Build()); + }); + + var jaegerTraceExporter = new JaegerExporter(new JaegerExporterOptions()); + + tracerProviderBuilder.AddExporter(ExportProcessorType.Batch, jaegerTraceExporter); + + using var provider = tracerProviderBuilder.Build(); + + var process = jaegerTraceExporter.Process; + + jaegerTraceExporter.SetResourceAndInitializeBatch(Resource.Empty); + + Assert.Equal("myservicename", process.ServiceName); + } + [Fact] public void JaegerTraceExporter_BuildBatchesToTransmit_FlushedBatch() { diff --git a/test/OpenTelemetry.Exporter.OpenTelemetryProtocol.Tests/Implementation/ExportClient/OtlpHttpTraceExportClientTests.cs b/test/OpenTelemetry.Exporter.OpenTelemetryProtocol.Tests/Implementation/ExportClient/OtlpHttpTraceExportClientTests.cs index a6dc816fd85..14acf30dc68 100644 --- a/test/OpenTelemetry.Exporter.OpenTelemetryProtocol.Tests/Implementation/ExportClient/OtlpHttpTraceExportClientTests.cs +++ b/test/OpenTelemetry.Exporter.OpenTelemetryProtocol.Tests/Implementation/ExportClient/OtlpHttpTraceExportClientTests.cs @@ -36,6 +36,8 @@ namespace OpenTelemetry.Exporter.OpenTelemetryProtocol.Tests { public class OtlpHttpTraceExportClientTests { + private static readonly SdkLimitOptions DefaultSdkLimitOptions = new(); + static OtlpHttpTraceExportClientTests() { Activity.DefaultIdFormat = ActivityIdFormat.W3C; @@ -171,7 +173,7 @@ void RunTest(Batch batch) { var request = new OtlpCollector.ExportTraceServiceRequest(); - request.AddBatch(resourceBuilder.Build().ToOtlpResource(), batch); + request.AddBatch(DefaultSdkLimitOptions, resourceBuilder.Build().ToOtlpResource(), batch); // Act var result = exportClient.SendExportRequest(request); diff --git a/test/OpenTelemetry.Exporter.OpenTelemetryProtocol.Tests/IntegrationTests.cs b/test/OpenTelemetry.Exporter.OpenTelemetryProtocol.Tests/IntegrationTests.cs index 85bae563da6..48ed182f561 100644 --- a/test/OpenTelemetry.Exporter.OpenTelemetryProtocol.Tests/IntegrationTests.cs +++ b/test/OpenTelemetry.Exporter.OpenTelemetryProtocol.Tests/IntegrationTests.cs @@ -21,6 +21,7 @@ using System.Diagnostics.Tracing; using System.Linq; using System.Threading; +using OpenTelemetry.Exporter.OpenTelemetryProtocol.Implementation; using OpenTelemetry.Metrics; using OpenTelemetry.Tests; using OpenTelemetry.Trace; @@ -33,6 +34,7 @@ public sealed class IntegrationTests : IDisposable { private const string CollectorHostnameEnvVarName = "OTEL_COLLECTOR_HOSTNAME"; private const int ExportIntervalMilliseconds = 10000; + private static readonly SdkLimitOptions DefaultSdkLimitOptions = new(); private static readonly string CollectorHostname = SkipUnlessEnvVarFoundTheoryAttribute.GetEnvironmentVariable(CollectorHostnameEnvVarName); private readonly OpenTelemetryEventListener openTelemetryEventListener; @@ -82,6 +84,7 @@ public void TraceExportResultIsSuccess(OtlpExportProtocol protocol, string endpo OtlpTraceExporterHelperExtensions.AddOtlpExporter( builder, exporterOptions, + DefaultSdkLimitOptions, serviceProvider: null, configureExporterInstance: otlpExporter => { diff --git a/test/OpenTelemetry.Exporter.OpenTelemetryProtocol.Tests/OtlpExporterOptionsTests.cs b/test/OpenTelemetry.Exporter.OpenTelemetryProtocol.Tests/OtlpExporterOptionsTests.cs index d3e39fb3ec9..f1b03638283 100644 --- a/test/OpenTelemetry.Exporter.OpenTelemetryProtocol.Tests/OtlpExporterOptionsTests.cs +++ b/test/OpenTelemetry.Exporter.OpenTelemetryProtocol.Tests/OtlpExporterOptionsTests.cs @@ -15,6 +15,8 @@ // using System; +using System.Collections.Generic; +using Microsoft.Extensions.Configuration; using Xunit; namespace OpenTelemetry.Exporter.OpenTelemetryProtocol.Tests @@ -72,6 +74,29 @@ public void OtlpExporterOptions_EnvironmentVariableOverride() Assert.Equal(OtlpExportProtocol.HttpProtobuf, options.Protocol); } + [Fact] + public void OtlpExporterOptions_UsingIConfiguration() + { + var values = new Dictionary() + { + [OtlpExporterOptions.EndpointEnvVarName] = "http://test:8888", + [OtlpExporterOptions.HeadersEnvVarName] = "A=2,B=3", + [OtlpExporterOptions.TimeoutEnvVarName] = "2000", + [OtlpExporterOptions.ProtocolEnvVarName] = "http/protobuf", + }; + + var configuration = new ConfigurationBuilder() + .AddInMemoryCollection(values) + .Build(); + + var options = new OtlpExporterOptions(configuration); + + Assert.Equal(new Uri("http://test:8888"), options.Endpoint); + Assert.Equal("A=2,B=3", options.Headers); + Assert.Equal(2000, options.TimeoutMilliseconds); + Assert.Equal(OtlpExportProtocol.HttpProtobuf, options.Protocol); + } + [Fact] public void OtlpExporterOptions_InvalidEndpointVariableOverride() { diff --git a/test/OpenTelemetry.Exporter.OpenTelemetryProtocol.Tests/OtlpLogExporterTests.cs b/test/OpenTelemetry.Exporter.OpenTelemetryProtocol.Tests/OtlpLogExporterTests.cs index 152f785e808..94954e25f00 100644 --- a/test/OpenTelemetry.Exporter.OpenTelemetryProtocol.Tests/OtlpLogExporterTests.cs +++ b/test/OpenTelemetry.Exporter.OpenTelemetryProtocol.Tests/OtlpLogExporterTests.cs @@ -17,6 +17,7 @@ using System; using System.Collections.Generic; using System.Diagnostics; +using System.Linq; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Hosting; using Microsoft.Extensions.Logging; @@ -27,12 +28,15 @@ using OpenTelemetry.Tests; using OpenTelemetry.Trace; using Xunit; +using OtlpCommon = OpenTelemetry.Proto.Common.V1; using OtlpLogs = OpenTelemetry.Proto.Logs.V1; namespace OpenTelemetry.Exporter.OpenTelemetryProtocol.Tests { public class OtlpLogExporterTests : Http2UnencryptedSupportTests { + private static readonly SdkLimitOptions DefaultSdkLimitOptions = new(); + [Fact] public void AddOtlpLogExporterReceivesAttributesWithParseStateValueSetToFalse() { @@ -187,7 +191,7 @@ public void OtlpLogRecordTestWhenStateValuesArePopulated() Assert.Single(logRecords); var logRecord = logRecords[0]; - var otlpLogRecord = logRecord.ToOtlpLog(); + var otlpLogRecord = logRecord.ToOtlpLog(DefaultSdkLimitOptions); Assert.NotNull(otlpLogRecord); Assert.Equal("Hello from tomato 2.99.", otlpLogRecord.Body.StringValue); @@ -224,7 +228,7 @@ public void CheckToOtlpLogRecordLoggerCategory() Assert.Single(logRecords); var logRecord = logRecords[0]; - var otlpLogRecord = logRecord.ToOtlpLog(); + var otlpLogRecord = logRecord.ToOtlpLog(DefaultSdkLimitOptions); Assert.NotNull(otlpLogRecord); Assert.Single(otlpLogRecord.Attributes); @@ -238,7 +242,7 @@ public void CheckToOtlpLogRecordLoggerCategory() Assert.Single(logRecords); logRecord = logRecords[0]; - otlpLogRecord = logRecord.ToOtlpLog(); + otlpLogRecord = logRecord.ToOtlpLog(DefaultSdkLimitOptions); Assert.NotNull(otlpLogRecord); Assert.Empty(otlpLogRecord.Attributes); } @@ -263,7 +267,7 @@ public void CheckToOtlpLogRecordEventId() Assert.Single(logRecords); var logRecord = logRecords[0]; - var otlpLogRecord = logRecord.ToOtlpLog(); + var otlpLogRecord = logRecord.ToOtlpLog(DefaultSdkLimitOptions); Assert.NotNull(otlpLogRecord); Assert.Equal("Hello from tomato 2.99.", otlpLogRecord.Body.StringValue); @@ -280,7 +284,7 @@ public void CheckToOtlpLogRecordEventId() Assert.Single(logRecords); logRecord = logRecords[0]; - otlpLogRecord = logRecord.ToOtlpLog(); + otlpLogRecord = logRecord.ToOtlpLog(DefaultSdkLimitOptions); Assert.NotNull(otlpLogRecord); Assert.Equal("Hello from tomato 2.99.", otlpLogRecord.Body.StringValue); @@ -305,7 +309,7 @@ public void CheckToOtlpLogRecordTraceIdSpanIdFlagWithNoActivity() var logger = loggerFactory.CreateLogger("OtlpLogExporterTests"); logger.LogInformation("Log when there is no activity."); var logRecord = logRecords[0]; - var otlpLogRecord = logRecord.ToOtlpLog(); + var otlpLogRecord = logRecord.ToOtlpLog(DefaultSdkLimitOptions); Assert.Null(Activity.Current); Assert.True(otlpLogRecord.TraceId.IsEmpty); @@ -335,7 +339,7 @@ public void CheckToOtlpLogRecordSpanIdTraceIdAndFlag() } var logRecord = logRecords[0]; - var otlpLogRecord = logRecord.ToOtlpLog(); + var otlpLogRecord = logRecord.ToOtlpLog(DefaultSdkLimitOptions); Assert.Equal(expectedTraceId.ToString(), ActivityTraceId.CreateFromBytes(otlpLogRecord.TraceId.ToByteArray()).ToString()); Assert.Equal(expectedSpanId.ToString(), ActivitySpanId.CreateFromBytes(otlpLogRecord.SpanId.ToByteArray()).ToString()); @@ -364,7 +368,7 @@ public void CheckToOtlpLogRecordSeverityLevelAndText(LogLevel logLevel) Assert.Single(logRecords); var logRecord = logRecords[0]; - var otlpLogRecord = logRecord.ToOtlpLog(); + var otlpLogRecord = logRecord.ToOtlpLog(DefaultSdkLimitOptions); Assert.NotNull(otlpLogRecord); Assert.Equal(logLevel.ToString(), otlpLogRecord.SeverityText); @@ -415,7 +419,7 @@ public void CheckToOtlpLogRecordBodyIsPopulated(bool includeFormattedMessage) Assert.Single(logRecords); var logRecord = logRecords[0]; - var otlpLogRecord = logRecord.ToOtlpLog(); + var otlpLogRecord = logRecord.ToOtlpLog(DefaultSdkLimitOptions); Assert.NotNull(otlpLogRecord); if (includeFormattedMessage) @@ -434,7 +438,7 @@ public void CheckToOtlpLogRecordBodyIsPopulated(bool includeFormattedMessage) Assert.Single(logRecords); logRecord = logRecords[0]; - otlpLogRecord = logRecord.ToOtlpLog(); + otlpLogRecord = logRecord.ToOtlpLog(DefaultSdkLimitOptions); Assert.NotNull(otlpLogRecord); @@ -450,7 +454,7 @@ public void CheckToOtlpLogRecordBodyIsPopulated(bool includeFormattedMessage) Assert.Single(logRecords); logRecord = logRecords[0]; - otlpLogRecord = logRecord.ToOtlpLog(); + otlpLogRecord = logRecord.ToOtlpLog(DefaultSdkLimitOptions); Assert.NotNull(otlpLogRecord); @@ -473,7 +477,7 @@ public void CheckToOtlpLogRecordExceptionAttributes() var logRecord = logRecords[0]; var loggedException = logRecord.Exception; - var otlpLogRecord = logRecord.ToOtlpLog(); + var otlpLogRecord = logRecord.ToOtlpLog(DefaultSdkLimitOptions); Assert.NotNull(otlpLogRecord); var otlpLogRecordAttributes = otlpLogRecord.Attributes.ToString(); @@ -520,7 +524,7 @@ public void CheckAddBatchInstrumentationScopeProcessed() ExportLogsServiceRequest request = new(); - request.AddBatch(new(), in batch); + request.AddBatch(DefaultSdkLimitOptions, new(), in batch); Assert.Equal(2, request.ResourceLogs[0].ScopeLogs.Count); @@ -534,5 +538,49 @@ public void CheckAddBatchInstrumentationScopeProcessed() Assert.Equal(SemanticConventions.AttributeLogEventDomain, request.ResourceLogs[0].ScopeLogs[1].Scope.Attributes[1].Key); Assert.Equal("testLogger2EventDomain", request.ResourceLogs[0].ScopeLogs[1].Scope.Attributes[1].Value.StringValue); } + + [Fact] + public void CheckToOtlpLogRecordRespectsAttributeLimits() + { + var sdkLimitOptions = new SdkLimitOptions + { + AttributeCountLimit = 3, // 3 => LogCategory, exception.type and exception.message + AttributeValueLengthLimit = 8, + }; + + var logRecords = new List(); + using var loggerFactory = LoggerFactory.Create(builder => + { + builder.AddOpenTelemetry().AddInMemoryExporter(logRecords); + }); + + var logger = loggerFactory.CreateLogger("OtlpLogExporterTests"); + logger.LogInformation(new NotSupportedException("I'm the exception message."), "Exception Occurred"); + + var logRecord = logRecords[0]; + var otlpLogRecord = logRecord.ToOtlpLog(sdkLimitOptions); + + Assert.NotNull(otlpLogRecord); + Assert.Equal(1u, otlpLogRecord.DroppedAttributesCount); + + var exceptionTypeAtt = TryGetAttribute(otlpLogRecord, SemanticConventions.AttributeExceptionType); + Assert.NotNull(exceptionTypeAtt); + + // "NotSuppo" == first 8 chars from the exception typename "NotSupportedException" + Assert.Equal("NotSuppo", exceptionTypeAtt.Value.StringValue); + var exceptionMessageAtt = TryGetAttribute(otlpLogRecord, SemanticConventions.AttributeExceptionMessage); + Assert.NotNull(exceptionMessageAtt); + + // "I'm the " == first 8 chars from the exception message + Assert.Equal("I'm the ", exceptionMessageAtt.Value.StringValue); + + var exceptionStackTraceAtt = TryGetAttribute(otlpLogRecord, SemanticConventions.AttributeExceptionStacktrace); + Assert.Null(exceptionStackTraceAtt); + } + + private static OtlpCommon.KeyValue TryGetAttribute(OtlpLogs.LogRecord record, string key) + { + return record.Attributes.FirstOrDefault(att => att.Key == key); + } } } diff --git a/test/OpenTelemetry.Exporter.OpenTelemetryProtocol.Tests/OtlpTraceExporterTests.cs b/test/OpenTelemetry.Exporter.OpenTelemetryProtocol.Tests/OtlpTraceExporterTests.cs index 835d464dc44..e302f5654f0 100644 --- a/test/OpenTelemetry.Exporter.OpenTelemetryProtocol.Tests/OtlpTraceExporterTests.cs +++ b/test/OpenTelemetry.Exporter.OpenTelemetryProtocol.Tests/OtlpTraceExporterTests.cs @@ -21,7 +21,6 @@ using Google.Protobuf.Collections; using Microsoft.Extensions.DependencyInjection; using Moq; -using OpenTelemetry.Configuration; using OpenTelemetry.Exporter.OpenTelemetryProtocol.Implementation; using OpenTelemetry.Exporter.OpenTelemetryProtocol.Implementation.ExportClient; using OpenTelemetry.Resources; @@ -38,6 +37,8 @@ namespace OpenTelemetry.Exporter.OpenTelemetryProtocol.Tests [Collection("xUnitCollectionPreventingTestsThatDependOnSdkConfigurationFromRunningInParallel")] public class OtlpTraceExporterTests : Http2UnencryptedSupportTests { + private static readonly SdkLimitOptions DefaultSdkLimitOptions = new(); + static OtlpTraceExporterTests() { Activity.DefaultIdFormat = ActivityIdFormat.W3C; @@ -187,13 +188,13 @@ public void ToOtlpResourceSpansTest(bool includeServiceNameInResource) Assert.Equal(10, exportedItems.Count); var batch = new Batch(exportedItems.ToArray(), exportedItems.Count); - RunTest(batch); + RunTest(DefaultSdkLimitOptions, batch); - void RunTest(Batch batch) + void RunTest(SdkLimitOptions sdkOptions, Batch batch) { var request = new OtlpCollector.ExportTraceServiceRequest(); - request.AddBatch(resourceBuilder.Build().ToOtlpResource(), batch); + request.AddBatch(sdkOptions, resourceBuilder.Build().ToOtlpResource(), batch); Assert.Single(request.ResourceSpans); var otlpResource = request.ResourceSpans.First().Resource; @@ -243,10 +244,13 @@ void RunTest(Batch batch) [Fact] public void SpanLimitsTest() { - SdkConfiguration.Instance.AttributeValueLengthLimit = 4; - SdkConfiguration.Instance.AttributeCountLimit = 3; - SdkConfiguration.Instance.SpanEventCountLimit = 1; - SdkConfiguration.Instance.SpanLinkCountLimit = 1; + var sdkOptions = new SdkLimitOptions() + { + AttributeValueLengthLimit = 4, + AttributeCountLimit = 3, + SpanEventCountLimit = 1, + SpanLinkCountLimit = 1, + }; var tags = new ActivityTagsCollection() { @@ -271,7 +275,7 @@ public void SpanLimitsTest() activity.AddEvent(event1); activity.AddEvent(event2); - var otlpSpan = activity.ToOtlpSpan(); + var otlpSpan = activity.ToOtlpSpan(sdkOptions); Assert.NotNull(otlpSpan); Assert.Equal(3, otlpSpan.Attributes.Count); @@ -314,8 +318,6 @@ void ArrayValueAsserts(RepeatedField values) } } } - - SdkConfiguration.Reset(); } [Fact] @@ -359,7 +361,7 @@ public void ToOtlpSpanTest() rootActivity.TraceId.CopyTo(traceIdSpan); var traceId = traceIdSpan.ToArray(); - var otlpSpan = rootActivity.ToOtlpSpan(); + var otlpSpan = rootActivity.ToOtlpSpan(DefaultSdkLimitOptions); Assert.NotNull(otlpSpan); Assert.Equal("root", otlpSpan.Name); @@ -393,7 +395,7 @@ public void ToOtlpSpanTest() rootActivity.Context.SpanId.CopyTo(parentIdSpan); var parentId = parentIdSpan.ToArray(); - otlpSpan = childActivity.ToOtlpSpan(); + otlpSpan = childActivity.ToOtlpSpan(DefaultSdkLimitOptions); Assert.NotNull(otlpSpan); Assert.Equal("child", otlpSpan.Name); @@ -432,7 +434,7 @@ public void ToOtlpSpanActivitiesWithNullArrayTest() var stringArr = new string[] { "test", string.Empty, null }; rootActivity.SetTag("stringArray", stringArr); - var otlpSpan = rootActivity.ToOtlpSpan(); + var otlpSpan = rootActivity.ToOtlpSpan(DefaultSdkLimitOptions); Assert.NotNull(otlpSpan); @@ -454,7 +456,7 @@ public void ToOtlpSpanNativeActivityStatusTest(ActivityStatusCode expectedStatus using var activity = activitySource.StartActivity("Name"); activity.SetStatus(expectedStatusCode, statusDescription); - var otlpSpan = activity.ToOtlpSpan(); + var otlpSpan = activity.ToOtlpSpan(DefaultSdkLimitOptions); if (expectedStatusCode == ActivityStatusCode.Unset) { @@ -487,7 +489,7 @@ public void ToOtlpSpanStatusTagTest(StatusCode expectedStatusCode, string status activity.SetTag(SpanAttributeConstants.StatusCodeKey, statusCodeTagValue); activity.SetTag(SpanAttributeConstants.StatusDescriptionKey, statusDescription); - var otlpSpan = activity.ToOtlpSpan(); + var otlpSpan = activity.ToOtlpSpan(DefaultSdkLimitOptions); Assert.NotNull(otlpSpan.Status); Assert.Equal((int)expectedStatusCode, (int)otlpSpan.Status.Code); @@ -512,7 +514,7 @@ public void ToOtlpSpanStatusTagIsCaseInsensitiveTest(StatusCode expectedStatusCo using var activity = activitySource.StartActivity("Name"); activity.SetTag(SpanAttributeConstants.StatusCodeKey, statusCodeTagValue); - var otlpSpan = activity.ToOtlpSpan(); + var otlpSpan = activity.ToOtlpSpan(DefaultSdkLimitOptions); Assert.NotNull(otlpSpan.Status); Assert.Equal((int)expectedStatusCode, (int)otlpSpan.Status.Code); @@ -528,7 +530,7 @@ public void ToOtlpSpanActivityStatusTakesPrecedenceOverStatusTagsWhenActivitySta activity.SetTag(SpanAttributeConstants.StatusCodeKey, "ERROR"); activity.SetTag(SpanAttributeConstants.StatusDescriptionKey, TagDescriptionOnError); - var otlpSpan = activity.ToOtlpSpan(); + var otlpSpan = activity.ToOtlpSpan(DefaultSdkLimitOptions); Assert.NotNull(otlpSpan.Status); Assert.Equal((int)ActivityStatusCode.Ok, (int)otlpSpan.Status.Code); @@ -544,7 +546,7 @@ public void ToOtlpSpanActivityStatusTakesPrecedenceOverStatusTagsWhenActivitySta activity.SetStatus(ActivityStatusCode.Error, StatusDescriptionOnError); activity.SetTag(SpanAttributeConstants.StatusCodeKey, "OK"); - var otlpSpan = activity.ToOtlpSpan(); + var otlpSpan = activity.ToOtlpSpan(DefaultSdkLimitOptions); Assert.NotNull(otlpSpan.Status); Assert.Equal((int)ActivityStatusCode.Error, (int)otlpSpan.Status.Code); @@ -560,7 +562,7 @@ public void ToOtlpSpanPeerServiceTest() rootActivity.SetTag(SemanticConventions.AttributeHttpHost, "opentelemetry.io"); - var otlpSpan = rootActivity.ToOtlpSpan(); + var otlpSpan = rootActivity.ToOtlpSpan(DefaultSdkLimitOptions); Assert.NotNull(otlpSpan); @@ -618,7 +620,7 @@ public void Shutdown_ClientShutdownIsCalled() { var exportClientMock = new Mock>(); - var exporter = new OtlpTraceExporter(new OtlpExporterOptions(), exportClientMock.Object); + var exporter = new OtlpTraceExporter(new OtlpExporterOptions(), DefaultSdkLimitOptions, exportClientMock.Object); var result = exporter.Shutdown(); diff --git a/test/OpenTelemetry.Exporter.OpenTelemetryProtocol.Tests/Configuration/SdkConfigurationTests.cs b/test/OpenTelemetry.Exporter.OpenTelemetryProtocol.Tests/SdkLimitOptionsTests.cs similarity index 58% rename from test/OpenTelemetry.Exporter.OpenTelemetryProtocol.Tests/Configuration/SdkConfigurationTests.cs rename to test/OpenTelemetry.Exporter.OpenTelemetryProtocol.Tests/SdkLimitOptionsTests.cs index dbbc9e43688..0e1fcfb0e2b 100644 --- a/test/OpenTelemetry.Exporter.OpenTelemetryProtocol.Tests/Configuration/SdkConfigurationTests.cs +++ b/test/OpenTelemetry.Exporter.OpenTelemetryProtocol.Tests/SdkLimitOptionsTests.cs @@ -1,4 +1,4 @@ -// +// // Copyright The OpenTelemetry Authors // // Licensed under the Apache License, Version 2.0 (the "License"); @@ -15,29 +15,29 @@ // using System; +using System.Collections.Generic; +using Microsoft.Extensions.Configuration; +using OpenTelemetry.Exporter.OpenTelemetryProtocol.Implementation; using Xunit; -namespace OpenTelemetry.Configuration.Tests +namespace OpenTelemetry.Exporter.OpenTelemetryProtocol.Tests { - [Collection("xUnitCollectionPreventingTestsThatDependOnSdkConfigurationFromRunningInParallel")] - public class SdkConfigurationTests : IDisposable + public sealed class SdkLimitOptionsTests : IDisposable { - public SdkConfigurationTests() + public SdkLimitOptionsTests() { ClearEnvVars(); - SdkConfiguration.Reset(); } public void Dispose() { ClearEnvVars(); - SdkConfiguration.Reset(); } [Fact] - public void SdkConfigurationDefaults() + public void SdkLimitOptionsDefaults() { - var config = SdkConfiguration.Instance; + var config = new SdkLimitOptions(); Assert.Null(config.AttributeValueLengthLimit); Assert.Null(config.AttributeCountLimit); @@ -45,12 +45,12 @@ public void SdkConfigurationDefaults() Assert.Null(config.SpanAttributeCountLimit); Assert.Null(config.SpanEventCountLimit); Assert.Null(config.SpanLinkCountLimit); - Assert.Null(config.EventAttributeCountLimit); - Assert.Null(config.LinkAttributeCountLimit); + Assert.Null(config.SpanEventAttributeCountLimit); + Assert.Null(config.SpanLinkAttributeCountLimit); } [Fact] - public void SdkConfigurationIsInitializedFromEnvironment() + public void SdkLimitOptionsIsInitializedFromEnvironment() { Environment.SetEnvironmentVariable("OTEL_ATTRIBUTE_VALUE_LENGTH_LIMIT", "10"); Environment.SetEnvironmentVariable("OTEL_ATTRIBUTE_COUNT_LIMIT", "10"); @@ -61,8 +61,7 @@ public void SdkConfigurationIsInitializedFromEnvironment() Environment.SetEnvironmentVariable("OTEL_EVENT_ATTRIBUTE_COUNT_LIMIT", "30"); Environment.SetEnvironmentVariable("OTEL_LINK_ATTRIBUTE_COUNT_LIMIT", "30"); - SdkConfiguration.Reset(); - var config = SdkConfiguration.Instance; + var config = new SdkLimitOptions(); Assert.Equal(10, config.AttributeValueLengthLimit); Assert.Equal(10, config.AttributeCountLimit); @@ -70,14 +69,14 @@ public void SdkConfigurationIsInitializedFromEnvironment() Assert.Equal(20, config.SpanAttributeCountLimit); Assert.Equal(10, config.SpanEventCountLimit); Assert.Equal(10, config.SpanLinkCountLimit); - Assert.Equal(30, config.EventAttributeCountLimit); - Assert.Equal(30, config.LinkAttributeCountLimit); + Assert.Equal(30, config.SpanEventAttributeCountLimit); + Assert.Equal(30, config.SpanLinkAttributeCountLimit); } [Fact] public void SpanAttributeValueLengthLimitFallback() { - var config = SdkConfiguration.Instance; + var config = new SdkLimitOptions(); config.AttributeValueLengthLimit = 10; Assert.Equal(10, config.AttributeValueLengthLimit); @@ -91,31 +90,62 @@ public void SpanAttributeValueLengthLimitFallback() [Fact] public void SpanAttributeCountLimitFallback() { - var config = SdkConfiguration.Instance; + var config = new SdkLimitOptions(); config.AttributeCountLimit = 10; Assert.Equal(10, config.AttributeCountLimit); Assert.Equal(10, config.SpanAttributeCountLimit); - Assert.Equal(10, config.EventAttributeCountLimit); - Assert.Equal(10, config.LinkAttributeCountLimit); + Assert.Equal(10, config.SpanEventAttributeCountLimit); + Assert.Equal(10, config.SpanLinkAttributeCountLimit); config.SpanAttributeCountLimit = 20; Assert.Equal(10, config.AttributeCountLimit); Assert.Equal(20, config.SpanAttributeCountLimit); - Assert.Equal(20, config.EventAttributeCountLimit); - Assert.Equal(20, config.LinkAttributeCountLimit); + Assert.Equal(20, config.SpanEventAttributeCountLimit); + Assert.Equal(20, config.SpanLinkAttributeCountLimit); - config.EventAttributeCountLimit = 30; + config.SpanEventAttributeCountLimit = 30; Assert.Equal(10, config.AttributeCountLimit); Assert.Equal(20, config.SpanAttributeCountLimit); - Assert.Equal(30, config.EventAttributeCountLimit); - Assert.Equal(20, config.LinkAttributeCountLimit); + Assert.Equal(30, config.SpanEventAttributeCountLimit); + Assert.Equal(20, config.SpanLinkAttributeCountLimit); - config.LinkAttributeCountLimit = 40; + config.SpanLinkAttributeCountLimit = 40; Assert.Equal(10, config.AttributeCountLimit); Assert.Equal(20, config.SpanAttributeCountLimit); - Assert.Equal(30, config.EventAttributeCountLimit); - Assert.Equal(40, config.LinkAttributeCountLimit); + Assert.Equal(30, config.SpanEventAttributeCountLimit); + Assert.Equal(40, config.SpanLinkAttributeCountLimit); + } + + [Fact] + public void SdkLimitOptionsUsingIConfiguration() + { + var values = new Dictionary() + { + ["OTEL_ATTRIBUTE_VALUE_LENGTH_LIMIT"] = "23", + ["OTEL_ATTRIBUTE_COUNT_LIMIT"] = "24", + ["OTEL_SPAN_ATTRIBUTE_VALUE_LENGTH_LIMIT"] = "25", + ["OTEL_SPAN_ATTRIBUTE_COUNT_LIMIT"] = "26", + ["OTEL_SPAN_EVENT_COUNT_LIMIT"] = "27", + ["OTEL_SPAN_LINK_COUNT_LIMIT"] = "28", + ["OTEL_EVENT_ATTRIBUTE_COUNT_LIMIT"] = "29", + ["OTEL_LINK_ATTRIBUTE_COUNT_LIMIT"] = "30", + }; + + var configuration = new ConfigurationBuilder() + .AddInMemoryCollection(values) + .Build(); + + var options = new SdkLimitOptions(configuration); + + Assert.Equal(23, options.AttributeValueLengthLimit); + Assert.Equal(24, options.AttributeCountLimit); + Assert.Equal(25, options.SpanAttributeValueLengthLimit); + Assert.Equal(26, options.SpanAttributeCountLimit); + Assert.Equal(27, options.SpanEventCountLimit); + Assert.Equal(28, options.SpanLinkCountLimit); + Assert.Equal(29, options.SpanEventAttributeCountLimit); + Assert.Equal(30, options.SpanLinkAttributeCountLimit); } private static void ClearEnvVars() diff --git a/test/OpenTelemetry.Exporter.Prometheus.AspNetCore.Tests/PrometheusExporterMiddlewareTests.cs b/test/OpenTelemetry.Exporter.Prometheus.AspNetCore.Tests/PrometheusExporterMiddlewareTests.cs index 88d18e3209f..8a6fb6eca9f 100644 --- a/test/OpenTelemetry.Exporter.Prometheus.AspNetCore.Tests/PrometheusExporterMiddlewareTests.cs +++ b/test/OpenTelemetry.Exporter.Prometheus.AspNetCore.Tests/PrometheusExporterMiddlewareTests.cs @@ -81,6 +81,23 @@ public Task PrometheusExporterMiddlewareIntegration_PathOverride() app => app.UseOpenTelemetryPrometheusScrapingEndpoint("/metrics_override")); } + [Fact] + public Task PrometheusExporterMiddlewareIntegration_WithPathNamedOptionsOverride() + { + return RunPrometheusExporterMiddlewareIntegrationTest( + "/metrics_override", + app => app.UseOpenTelemetryPrometheusScrapingEndpoint( + meterProvider: null, + predicate: null, + path: null, + configureBranchedPipeline: null, + optionsName: "myOptions"), + services => + { + services.Configure("myOptions", o => o.ScrapeEndpointPath = "/metrics_override"); + }); + } + [Fact] public Task PrometheusExporterMiddlewareIntegration_Predicate() { @@ -102,7 +119,8 @@ public Task PrometheusExporterMiddlewareIntegration_MixedPredicateAndPath() { context.Response.Headers.Add("X-MiddlewareExecuted", "true"); return next(); - })), + }), + optionsName: null), services => services.Configure(o => o.ScrapeEndpointPath = "/metrics_options"), validateResponse: rsp => { @@ -128,7 +146,8 @@ public Task PrometheusExporterMiddlewareIntegration_MixedPath() { context.Response.Headers.Add("X-MiddlewareExecuted", "true"); return next(); - })), + }), + optionsName: null), services => services.Configure(o => o.ScrapeEndpointPath = "/metrics_options"), validateResponse: rsp => { @@ -155,7 +174,8 @@ await RunPrometheusExporterMiddlewareIntegrationTest( meterProvider: meterProvider, predicate: null, path: null, - configureBranchedPipeline: null), + configureBranchedPipeline: null, + optionsName: null), registerMeterProvider: false).ConfigureAwait(false); } @@ -186,6 +206,23 @@ public Task PrometheusExporterMiddlewareIntegration_MapEndpoint_WithPathOverride services => services.AddRouting()); } + [Fact] + public Task PrometheusExporterMiddlewareIntegration_MapEndpoint_WithPathNamedOptionsOverride() + { + return RunPrometheusExporterMiddlewareIntegrationTest( + "/metrics_path", + app => app.UseRouting().UseEndpoints(builder => builder.MapPrometheusScrapingEndpoint( + path: null, + meterProvider: null, + configureBranchedPipeline: null, + optionsName: "myOptions")), + services => + { + services.AddRouting(); + services.Configure("myOptions", o => o.ScrapeEndpointPath = "/metrics_path"); + }); + } + [Fact] public async Task PrometheusExporterMiddlewareIntegration_MapEndpoint_WithMeterProvider() { @@ -199,7 +236,8 @@ await RunPrometheusExporterMiddlewareIntegrationTest( app => app.UseRouting().UseEndpoints(builder => builder.MapPrometheusScrapingEndpoint( path: null, meterProvider: meterProvider, - configureBranchedPipeline: null)), + configureBranchedPipeline: null, + optionsName: null)), services => services.AddRouting(), registerMeterProvider: false).ConfigureAwait(false); } diff --git a/test/OpenTelemetry.Exporter.Prometheus.HttpListener.Tests/PrometheusSerializerTests.cs b/test/OpenTelemetry.Exporter.Prometheus.HttpListener.Tests/PrometheusSerializerTests.cs index b9c8b3f0d3b..f6e91cbab50 100644 --- a/test/OpenTelemetry.Exporter.Prometheus.HttpListener.Tests/PrometheusSerializerTests.cs +++ b/test/OpenTelemetry.Exporter.Prometheus.HttpListener.Tests/PrometheusSerializerTests.cs @@ -273,7 +273,12 @@ public void HistogramZeroDimension() + "test_histogram_bucket{le='100'} 2 \\d+\n" + "test_histogram_bucket{le='250'} 2 \\d+\n" + "test_histogram_bucket{le='500'} 2 \\d+\n" + + "test_histogram_bucket{le='750'} 2 \\d+\n" + "test_histogram_bucket{le='1000'} 2 \\d+\n" + + "test_histogram_bucket{le='2500'} 2 \\d+\n" + + "test_histogram_bucket{le='5000'} 2 \\d+\n" + + "test_histogram_bucket{le='7500'} 2 \\d+\n" + + "test_histogram_bucket{le='10000'} 2 \\d+\n" + "test_histogram_bucket{le='\\+Inf'} 2 \\d+\n" + "test_histogram_sum 118 \\d+\n" + "test_histogram_count 2 \\d+\n" @@ -312,7 +317,12 @@ public void HistogramOneDimension() + "test_histogram_bucket{x='1',le='100'} 2 \\d+\n" + "test_histogram_bucket{x='1',le='250'} 2 \\d+\n" + "test_histogram_bucket{x='1',le='500'} 2 \\d+\n" + + "test_histogram_bucket{x='1',le='750'} 2 \\d+\n" + "test_histogram_bucket{x='1',le='1000'} 2 \\d+\n" + + "test_histogram_bucket{x='1',le='2500'} 2 \\d+\n" + + "test_histogram_bucket{x='1',le='5000'} 2 \\d+\n" + + "test_histogram_bucket{x='1',le='7500'} 2 \\d+\n" + + "test_histogram_bucket{x='1',le='10000'} 2 \\d+\n" + "test_histogram_bucket{x='1',le='\\+Inf'} 2 \\d+\n" + "test_histogram_sum{x='1'} 118 \\d+\n" + "test_histogram_count{x='1'} 2 \\d+\n" @@ -351,7 +361,12 @@ public void HistogramTwoDimensions() + "test_histogram_bucket{x='1',y='2',le='100'} 2 \\d+\n" + "test_histogram_bucket{x='1',y='2',le='250'} 2 \\d+\n" + "test_histogram_bucket{x='1',y='2',le='500'} 2 \\d+\n" + + "test_histogram_bucket{x='1',y='2',le='750'} 2 \\d+\n" + "test_histogram_bucket{x='1',y='2',le='1000'} 2 \\d+\n" + + "test_histogram_bucket{x='1',y='2',le='2500'} 2 \\d+\n" + + "test_histogram_bucket{x='1',y='2',le='5000'} 2 \\d+\n" + + "test_histogram_bucket{x='1',y='2',le='7500'} 2 \\d+\n" + + "test_histogram_bucket{x='1',y='2',le='10000'} 2 \\d+\n" + "test_histogram_bucket{x='1',y='2',le='\\+Inf'} 2 \\d+\n" + "test_histogram_sum{x='1',y='2'} 118 \\d+\n" + "test_histogram_count{x='1',y='2'} 2 \\d+\n" @@ -391,7 +406,12 @@ public void HistogramInfinities() + "test_histogram_bucket{le='100'} 1 \\d+\n" + "test_histogram_bucket{le='250'} 1 \\d+\n" + "test_histogram_bucket{le='500'} 1 \\d+\n" + + "test_histogram_bucket{le='750'} 1 \\d+\n" + "test_histogram_bucket{le='1000'} 1 \\d+\n" + + "test_histogram_bucket{le='2500'} 1 \\d+\n" + + "test_histogram_bucket{le='5000'} 1 \\d+\n" + + "test_histogram_bucket{le='7500'} 1 \\d+\n" + + "test_histogram_bucket{le='10000'} 1 \\d+\n" + "test_histogram_bucket{le='\\+Inf'} 3 \\d+\n" + "test_histogram_sum \\+Inf \\d+\n" + "test_histogram_count 3 \\d+\n" @@ -431,7 +451,12 @@ public void HistogramNaN() + "test_histogram_bucket{le='100'} 1 \\d+\n" + "test_histogram_bucket{le='250'} 1 \\d+\n" + "test_histogram_bucket{le='500'} 1 \\d+\n" + + "test_histogram_bucket{le='750'} 1 \\d+\n" + "test_histogram_bucket{le='1000'} 1 \\d+\n" + + "test_histogram_bucket{le='2500'} 1 \\d+\n" + + "test_histogram_bucket{le='5000'} 1 \\d+\n" + + "test_histogram_bucket{le='7500'} 1 \\d+\n" + + "test_histogram_bucket{le='10000'} 1 \\d+\n" + "test_histogram_bucket{le='\\+Inf'} 3 \\d+\n" + "test_histogram_sum Nan \\d+\n" + "test_histogram_count 3 \\d+\n" diff --git a/test/OpenTelemetry.Exporter.Zipkin.Tests/ZipkinExporterTests.cs b/test/OpenTelemetry.Exporter.Zipkin.Tests/ZipkinExporterTests.cs index 4cd2d97d2e5..2eb3ca9e213 100644 --- a/test/OpenTelemetry.Exporter.Zipkin.Tests/ZipkinExporterTests.cs +++ b/test/OpenTelemetry.Exporter.Zipkin.Tests/ZipkinExporterTests.cs @@ -23,6 +23,7 @@ using System.Net; using System.Net.Http; using System.Text; +using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; using OpenTelemetry.Exporter.Zipkin.Implementation; using OpenTelemetry.Resources; @@ -207,6 +208,23 @@ public void ErrorGettingUriFromEnvVarSetsDefaultEndpointValue() } } + [Fact] + public void EndpointConfigurationUsingIConfiguration() + { + var values = new Dictionary() + { + [ZipkinExporterOptions.ZipkinEndpointEnvVar] = "http://custom-endpoint:12345", + }; + + var configuration = new ConfigurationBuilder() + .AddInMemoryCollection(values) + .Build(); + + var options = new ZipkinExporterOptions(configuration); + + Assert.Equal(new Uri("http://custom-endpoint:12345"), options.Endpoint); + } + [Fact] public void UserHttpFactoryCalled() { @@ -274,6 +292,42 @@ public void ServiceProviderHttpClientFactoryInvoked() Assert.Equal(1, invocations); } + [Fact] + public void UpdatesServiceNameFromDefaultResource() + { + var zipkinExporter = new ZipkinExporter(new ZipkinExporterOptions()); + + zipkinExporter.SetLocalEndpointFromResource(Resource.Empty); + + Assert.StartsWith("unknown_service:", zipkinExporter.LocalEndpoint.ServiceName); + } + + [Fact] + public void UpdatesServiceNameFromIConfiguration() + { + var tracerProviderBuilder = Sdk.CreateTracerProviderBuilder() + .ConfigureServices(services => + { + Dictionary configuration = new() + { + ["OTEL_SERVICE_NAME"] = "myservicename", + }; + + services.AddSingleton( + new ConfigurationBuilder().AddInMemoryCollection(configuration).Build()); + }); + + var zipkinExporter = new ZipkinExporter(new ZipkinExporterOptions()); + + tracerProviderBuilder.AddExporter(ExportProcessorType.Batch, zipkinExporter); + + using var provider = tracerProviderBuilder.Build(); + + zipkinExporter.SetLocalEndpointFromResource(Resource.Empty); + + Assert.Equal("myservicename", zipkinExporter.LocalEndpoint.ServiceName); + } + [Theory] [InlineData(true, false, false)] [InlineData(false, false, false)] diff --git a/test/OpenTelemetry.Extensions.Hosting.Tests/HostingMeterExtensionTests.cs b/test/OpenTelemetry.Extensions.Hosting.Tests/HostingMeterExtensionTests.cs index f4acf44b4e2..4553ae33926 100644 --- a/test/OpenTelemetry.Extensions.Hosting.Tests/HostingMeterExtensionTests.cs +++ b/test/OpenTelemetry.Extensions.Hosting.Tests/HostingMeterExtensionTests.cs @@ -15,13 +15,14 @@ // using System; +using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; +using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Hosting; using OpenTelemetry.Metrics; using Xunit; -using static OpenTelemetry.Extensions.Hosting.Tests.HostingTracerExtensionTests; namespace OpenTelemetry.Extensions.Hosting.Tests { @@ -195,6 +196,49 @@ public void AddOpenTelemetryMetrics_MultipleCallsConfigureSingleProvider() Assert.Single(providers); } + [Fact] + public async Task AddOpenTelemetryMetrics_HostConfigurationHonoredTest() + { + bool configureBuilderCalled = false; + + var builder = new HostBuilder() + .ConfigureAppConfiguration(builder => + { + builder.AddInMemoryCollection(new Dictionary + { + ["TEST_KEY"] = "TEST_KEY_VALUE", + }); + }) + .ConfigureServices(services => + { + services.AddOpenTelemetryMetrics(builder => + { + builder.ConfigureBuilder((sp, builder) => + { + configureBuilderCalled = true; + + var configuration = sp.GetRequiredService(); + + var testKeyValue = configuration.GetValue("TEST_KEY", null); + + Assert.Equal("TEST_KEY_VALUE", testKeyValue); + }); + }); + }); + + var host = builder.Build(); + + Assert.False(configureBuilderCalled); + + await host.StartAsync(); + + Assert.True(configureBuilderCalled); + + await host.StopAsync(); + + host.Dispose(); + } + private static MeterProviderBuilder AddMyFeature(MeterProviderBuilder meterProviderBuilder) { meterProviderBuilder.ConfigureServices(services => services.AddSingleton()); diff --git a/test/OpenTelemetry.Extensions.Hosting.Tests/HostingTracerExtensionTests.cs b/test/OpenTelemetry.Extensions.Hosting.Tests/HostingTracerExtensionTests.cs index 131e9038139..22432e3f4a7 100644 --- a/test/OpenTelemetry.Extensions.Hosting.Tests/HostingTracerExtensionTests.cs +++ b/test/OpenTelemetry.Extensions.Hosting.Tests/HostingTracerExtensionTests.cs @@ -15,9 +15,11 @@ // using System; +using System.Collections.Generic; using System.Diagnostics; using System.Linq; using System.Threading.Tasks; +using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Hosting; using OpenTelemetry.Trace; @@ -198,6 +200,49 @@ public void AddOpenTelemetryTracing_MultipleCallsConfigureSingleProvider() Assert.Single(providers); } + [Fact] + public async Task AddOpenTelemetryTracing_HostConfigurationHonoredTest() + { + bool configureBuilderCalled = false; + + var builder = new HostBuilder() + .ConfigureAppConfiguration(builder => + { + builder.AddInMemoryCollection(new Dictionary + { + ["TEST_KEY"] = "TEST_KEY_VALUE", + }); + }) + .ConfigureServices(services => + { + services.AddOpenTelemetryTracing(builder => + { + builder.ConfigureBuilder((sp, builder) => + { + configureBuilderCalled = true; + + var configuration = sp.GetRequiredService(); + + var testKeyValue = configuration.GetValue("TEST_KEY", null); + + Assert.Equal("TEST_KEY_VALUE", testKeyValue); + }); + }); + }); + + var host = builder.Build(); + + Assert.False(configureBuilderCalled); + + await host.StartAsync(); + + Assert.True(configureBuilderCalled); + + await host.StopAsync(); + + host.Dispose(); + } + private static TracerProviderBuilder AddMyFeature(TracerProviderBuilder tracerProviderBuilder) { tracerProviderBuilder.ConfigureServices(services => services.AddSingleton()); diff --git a/test/OpenTelemetry.Instrumentation.AspNetCore.Tests/BasicTests.cs b/test/OpenTelemetry.Instrumentation.AspNetCore.Tests/BasicTests.cs index 2ce0e7989c7..fe623375a6a 100644 --- a/test/OpenTelemetry.Instrumentation.AspNetCore.Tests/BasicTests.cs +++ b/test/OpenTelemetry.Instrumentation.AspNetCore.Tests/BasicTests.cs @@ -105,7 +105,8 @@ void ConfigureTestServices(IServiceCollection services) { if (shouldEnrich) { - options.Enrich = ActivityEnrichment; + options.EnrichWithHttpRequest = (activity, request) => { activity.SetTag("enrichedOnStart", "yes"); }; + options.EnrichWithHttpResponse = (activity, response) => { activity.SetTag("enrichedOnStop", "yes"); }; } }) .AddInMemoryExporter(exportedItems) @@ -132,7 +133,8 @@ void ConfigureTestServices(IServiceCollection services) if (shouldEnrich) { - Assert.NotEmpty(activity.Tags.Where(tag => tag.Key == "enriched" && tag.Value == "yes")); + Assert.NotEmpty(activity.Tags.Where(tag => tag.Key == "enrichedOnStart" && tag.Value == "yes")); + Assert.NotEmpty(activity.Tags.Where(tag => tag.Key == "enrichedOnStop" && tag.Value == "yes")); } ValidateAspNetCoreActivity(activity, "/api/values"); @@ -519,7 +521,8 @@ void ConfigureTestServices(IServiceCollection services) public async Task FilterAndEnrichAreOnlyCalledWhenSampled(SamplingDecision samplingDecision, bool shouldFilterBeCalled, bool shouldEnrichBeCalled) { bool filterCalled = false; - bool enrichCalled = false; + bool enrichWithHttpRequestCalled = false; + bool enrichWithHttpResponseCalled = false; void ConfigureTestServices(IServiceCollection services) { this.tracerProvider = Sdk.CreateTracerProviderBuilder() @@ -531,9 +534,13 @@ void ConfigureTestServices(IServiceCollection services) filterCalled = true; return true; }; - options.Enrich = (activity, methodName, request) => + options.EnrichWithHttpRequest = (activity, request) => { - enrichCalled = true; + enrichWithHttpRequestCalled = true; + }; + options.EnrichWithHttpResponse = (activity, request) => + { + enrichWithHttpResponseCalled = true; }; }) .Build(); @@ -550,7 +557,8 @@ void ConfigureTestServices(IServiceCollection services) // Assert Assert.Equal(shouldFilterBeCalled, filterCalled); - Assert.Equal(shouldEnrichBeCalled, enrichCalled); + Assert.Equal(shouldEnrichBeCalled, enrichWithHttpRequestCalled); + Assert.Equal(shouldEnrichBeCalled, enrichWithHttpResponseCalled); } [Fact] diff --git a/test/OpenTelemetry.Instrumentation.Grpc.Tests/GrpcTests.client.cs b/test/OpenTelemetry.Instrumentation.Grpc.Tests/GrpcTests.client.cs index e011eead53c..89525480fbb 100644 --- a/test/OpenTelemetry.Instrumentation.Grpc.Tests/GrpcTests.client.cs +++ b/test/OpenTelemetry.Instrumentation.Grpc.Tests/GrpcTests.client.cs @@ -24,9 +24,6 @@ using Grpc.Core; using Grpc.Net.Client; using Microsoft.Extensions.DependencyInjection; -#if NET6_0_OR_GREATER -using Microsoft.AspNetCore.Http; -#endif using Moq; using OpenTelemetry.Context.Propagation; using OpenTelemetry.Instrumentation.Grpc.Tests.GrpcTestHelpers; @@ -49,6 +46,9 @@ public partial class GrpcTests [InlineData("http://[::1]", false)] public void GrpcClientCallsAreCollectedSuccessfully(string baseAddress, bool shouldEnrich = true) { + bool enrichWithHttpRequestMessageCalled = false; + bool enrichWithHttpResponseMessageCalled = false; + var uri = new Uri($"{baseAddress}:1234"); var uriHostNameType = Uri.CheckHostName(uri.Host); @@ -72,7 +72,8 @@ public void GrpcClientCallsAreCollectedSuccessfully(string baseAddress, bool sho { if (shouldEnrich) { - options.Enrich = ActivityEnrichment; + options.EnrichWithHttpRequestMessage = (activity, httpRequestMessage) => { enrichWithHttpRequestMessageCalled = true; }; + options.EnrichWithHttpResponseMessage = (activity, httpResponseMessage) => { enrichWithHttpResponseMessageCalled = true; }; } }) .AddProcessor(processor.Object) @@ -118,6 +119,12 @@ public void GrpcClientCallsAreCollectedSuccessfully(string baseAddress, bool sho Assert.Null(activity.GetTagValue(GrpcTagHelper.GrpcMethodTagName)); Assert.Null(activity.GetTagValue(GrpcTagHelper.GrpcStatusCodeTagName)); Assert.Equal(0, activity.GetTagValue(SemanticConventions.AttributeRpcGrpcStatusCode)); + + if (shouldEnrich) + { + Assert.True(enrichWithHttpRequestMessageCalled); + Assert.True(enrichWithHttpResponseMessageCalled); + } } #if NET6_0_OR_GREATER @@ -128,7 +135,12 @@ public void GrpcAndHttpClientInstrumentationIsInvoked(bool shouldEnrich) { var uri = new Uri($"http://localhost:{this.server.Port}"); var processor = new Mock>(); - processor.Setup(x => x.OnStart(It.IsAny())).Callback(c => c.SetTag("enriched", "no")); + processor.Setup(x => x.OnStart(It.IsAny())).Callback(c => + { + c.SetTag("enrichedWithHttpRequestMessage", "no"); + c.SetTag("enrichedWithHttpResponseMessage", "no"); + }); + var parent = new Activity("parent") .Start(); @@ -138,7 +150,15 @@ public void GrpcAndHttpClientInstrumentationIsInvoked(bool shouldEnrich) { if (shouldEnrich) { - options.Enrich = ActivityEnrichment; + options.EnrichWithHttpRequestMessage = (activity, httpRequestMessage) => + { + activity.SetTag("enrichedWithHttpRequestMessage", "yes"); + }; + + options.EnrichWithHttpResponseMessage = (activity, httpResponseMessage) => + { + activity.SetTag("enrichedWithHttpResponseMessage", "yes"); + }; } }) .AddHttpClientInstrumentation() @@ -166,14 +186,14 @@ public void GrpcAndHttpClientInstrumentationIsInvoked(bool shouldEnrich) Assert.Equal($"HTTP POST", httpSpan.DisplayName); Assert.Equal(grpcSpan.SpanId, httpSpan.ParentSpanId); - Assert.NotEmpty(grpcSpan.Tags.Where(tag => tag.Key == "enriched")); - Assert.Equal(shouldEnrich ? "yes" : "no", grpcSpan.Tags.Where(tag => tag.Key == "enriched").FirstOrDefault().Value); + Assert.NotEmpty(grpcSpan.Tags.Where(tag => tag.Key == "enrichedWithHttpRequestMessage")); + Assert.NotEmpty(grpcSpan.Tags.Where(tag => tag.Key == "enrichedWithHttpResponseMessage")); + Assert.Equal(shouldEnrich ? "yes" : "no", grpcSpan.Tags.Where(tag => tag.Key == "enrichedWithHttpRequestMessage").FirstOrDefault().Value); + Assert.Equal(shouldEnrich ? "yes" : "no", grpcSpan.Tags.Where(tag => tag.Key == "enrichedWithHttpResponseMessage").FirstOrDefault().Value); } - [Theory] - [InlineData(true)] - [InlineData(false)] - public void GrpcAndHttpClientInstrumentationWithSuppressInstrumentation(bool shouldEnrich) + [Fact] + public void GrpcAndHttpClientInstrumentationWithSuppressInstrumentation() { var uri = new Uri($"http://localhost:{this.server.Port}"); var processor = new Mock>(); @@ -183,14 +203,7 @@ public void GrpcAndHttpClientInstrumentationWithSuppressInstrumentation(bool sho using (Sdk.CreateTracerProviderBuilder() .SetSampler(new AlwaysOnSampler()) - .AddGrpcClientInstrumentation(o => - { - o.SuppressDownstreamInstrumentation = true; - if (shouldEnrich) - { - o.Enrich = ActivityEnrichment; - } - }) + .AddGrpcClientInstrumentation(o => o.SuppressDownstreamInstrumentation = true) .AddHttpClientInstrumentation() .AddProcessor(processor.Object) .Build()) @@ -264,17 +277,9 @@ public void GrpcPropagatesContextWithSuppressInstrumentationOptionSetToTrue() .AddHttpClientInstrumentation() .AddAspNetCoreInstrumentation(options => { - options.Enrich = (activity, eventName, obj) => + options.EnrichWithHttpRequest = (activity, request) => { - switch (eventName) - { - case "OnStartActivity": - var request = (HttpRequest)obj; - activity.SetCustomProperty("customField", request.Headers["customField"].ToString()); - break; - default: - break; - } + activity.SetCustomProperty("customField", request.Headers["customField"].ToString()); }; }) // Instrumenting the server side as well .AddProcessor(processor.Object) @@ -478,26 +483,6 @@ private static void ValidateGrpcActivity(Activity activityToValidate) Assert.Equal(ActivityKind.Client, activityToValidate.Kind); } - private static void ActivityEnrichment(Activity activity, string method, object obj) - { - Assert.True(activity.IsAllDataRequested); - switch (method) - { - case "OnStartActivity": - Assert.True(obj is HttpRequestMessage); - break; - - case "OnStopActivity": - Assert.True(obj is HttpResponseMessage); - break; - - default: - break; - } - - activity.SetTag("enriched", "yes"); - } - private static Predicate GeneratePredicateForMoqProcessorActivity(string methodName, string activityOperationName) { return invo => invo.Method.Name == methodName && (invo.Arguments[0] as Activity)?.OperationName == activityOperationName; diff --git a/test/OpenTelemetry.Instrumentation.Http.Tests/HttpClientTests.Basic.cs b/test/OpenTelemetry.Instrumentation.Http.Tests/HttpClientTests.Basic.cs index df742c63634..2716ff7da49 100644 --- a/test/OpenTelemetry.Instrumentation.Http.Tests/HttpClientTests.Basic.cs +++ b/test/OpenTelemetry.Instrumentation.Http.Tests/HttpClientTests.Basic.cs @@ -21,6 +21,7 @@ using System.Net.Http; using System.Threading.Tasks; using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Options; using Moq; using OpenTelemetry.Context.Propagation; using OpenTelemetry.Instrumentation.Http.Implementation; @@ -40,7 +41,11 @@ public HttpClientTests() this.serverLifeTime = TestHttpServer.RunServer( (ctx) => { - if (ctx.Request.Url.PathAndQuery.Contains("redirect")) + if (ctx.Request.Url.PathAndQuery.Contains("500")) + { + ctx.Response.StatusCode = 500; + } + else if (ctx.Request.Url.PathAndQuery.Contains("redirect")) { ctx.Response.RedirectLocation = "/"; ctx.Response.StatusCode = 302; @@ -92,7 +97,12 @@ public void AddHttpClientInstrumentation_BadArgs() public async Task HttpClientInstrumentationInjectsHeadersAsync(bool shouldEnrich) { var processor = new Mock>(); - processor.Setup(x => x.OnStart(It.IsAny())).Callback(c => c.SetTag("enriched", "no")); + processor.Setup(x => x.OnStart(It.IsAny())).Callback(c => + { + c.SetTag("enrichedWithHttpRequestMessage", "no"); + c.SetTag("enrichedWithHttpResponseMessage", "no"); + }); + var request = new HttpRequestMessage { RequestUri = new Uri(this.url), @@ -127,7 +137,15 @@ public async Task HttpClientInstrumentationInjectsHeadersAsync(bool shouldEnrich { if (shouldEnrich) { - o.Enrich = ActivityEnrichmentSetTag; + o.EnrichWithHttpRequestMessage = (activity, httpRequestMessage) => + { + activity.SetTag("enrichedWithHttpRequestMessage", "yes"); + }; + + o.EnrichWithHttpResponseMessage = (activity, httpResponseMessage) => + { + activity.SetTag("enrichedWithHttpResponseMessage", "yes"); + }; } }) .AddProcessor(processor.Object) @@ -154,8 +172,10 @@ public async Task HttpClientInstrumentationInjectsHeadersAsync(bool shouldEnrich Assert.Equal($"00-{activity.Context.TraceId}-{activity.Context.SpanId}-01", traceparents.Single()); Assert.Equal("k1=v1,k2=v2", tracestates.Single()); - Assert.NotEmpty(activity.Tags.Where(tag => tag.Key == "enriched")); - Assert.Equal(shouldEnrich ? "yes" : "no", activity.Tags.Where(tag => tag.Key == "enriched").FirstOrDefault().Value); + Assert.NotEmpty(activity.Tags.Where(tag => tag.Key == "enrichedWithHttpRequestMessage")); + Assert.NotEmpty(activity.Tags.Where(tag => tag.Key == "enrichedWithHttpResponseMessage")); + Assert.Equal(shouldEnrich ? "yes" : "no", activity.Tags.Where(tag => tag.Key == "enrichedWithHttpRequestMessage").FirstOrDefault().Value); + Assert.Equal(shouldEnrich ? "yes" : "no", activity.Tags.Where(tag => tag.Key == "enrichedWithHttpResponseMessage").FirstOrDefault().Value); } [Theory] @@ -163,6 +183,9 @@ public async Task HttpClientInstrumentationInjectsHeadersAsync(bool shouldEnrich [InlineData(false)] public async Task HttpClientInstrumentationInjectsHeadersAsync_CustomFormat(bool shouldEnrich) { + bool enrichWithHttpRequestMessageCalled = false; + bool enrichWithHttpResponseMessageCalled = false; + var propagator = new Mock(); propagator.Setup(m => m.Inject(It.IsAny(), It.IsAny(), It.IsAny>())) .Callback>((context, message, action) => @@ -192,7 +215,8 @@ public async Task HttpClientInstrumentationInjectsHeadersAsync_CustomFormat(bool { if (shouldEnrich) { - opt.Enrich = ActivityEnrichment; + opt.EnrichWithHttpRequestMessage = (activity, httpRequestMessage) => { enrichWithHttpRequestMessageCalled = true; }; + opt.EnrichWithHttpResponseMessage = (activity, httpResponseMessage) => { enrichWithHttpResponseMessageCalled = true; }; } }) .AddProcessor(processor.Object) @@ -223,6 +247,12 @@ public async Task HttpClientInstrumentationInjectsHeadersAsync_CustomFormat(bool new TraceContextPropagator(), new BaggagePropagator(), })); + + if (shouldEnrich) + { + Assert.True(enrichWithHttpRequestMessageCalled); + Assert.True(enrichWithHttpResponseMessageCalled); + } } [Fact] @@ -301,7 +331,7 @@ public async Task HttpClientInstrumentation_AddViaFactory_HttpInstrumentation_Co Assert.IsType(processor.Invocations[1].Arguments[0]); } - [Fact(Skip = "https://github.com/open-telemetry/opentelemetry-dotnet/issues/3729")] + [Fact] public async Task HttpClientInstrumentationExportsSpansCreatedForRetries() { var exportedItems = new List(); @@ -321,7 +351,7 @@ public async Task HttpClientInstrumentationExportsSpansCreatedForRetries() await c.SendAsync(request); // number of exported spans should be 3(maxRetries) - Assert.Equal(3, exportedItems.Count()); + Assert.Equal(maxRetries, exportedItems.Count()); var spanid1 = exportedItems[0].SpanId; var spanid2 = exportedItems[1].SpanId; @@ -396,6 +426,9 @@ public async Task HttpClientInstrumentationCorrelationAndBaggage() { var activityProcessor = new Mock>(); + bool enrichWithHttpRequestMessageCalled = false; + bool enrichWithHttpResponseMessageCalled = false; + using var parent = new Activity("w3c activity"); parent.SetIdFormat(ActivityIdFormat.W3C); parent.AddBaggage("k1", "v1"); @@ -405,7 +438,11 @@ public async Task HttpClientInstrumentationCorrelationAndBaggage() Baggage.SetBaggage("k2", "v2"); using (Sdk.CreateTracerProviderBuilder() - .AddHttpClientInstrumentation(options => options.Enrich = ActivityEnrichment) + .AddHttpClientInstrumentation(options => + { + options.EnrichWithHttpRequestMessage = (activity, httpRequestMessage) => { enrichWithHttpRequestMessageCalled = true; }; + options.EnrichWithHttpResponseMessage = (activity, httpResponseMessage) => { enrichWithHttpResponseMessageCalled = true; }; + }) .AddProcessor(activityProcessor.Object) .Build()) { @@ -414,6 +451,8 @@ public async Task HttpClientInstrumentationCorrelationAndBaggage() } Assert.Equal(5, activityProcessor.Invocations.Count); + Assert.True(enrichWithHttpRequestMessageCalled); + Assert.True(enrichWithHttpResponseMessageCalled); } [Fact] @@ -462,38 +501,94 @@ public async Task HttpClientInstrumentationContextPropagation() Assert.Equal("b1=v1", baggages.Single()); } - public void Dispose() + [Fact] + public async Task HttpClientInstrumentationReportsExceptionEventForNetworkFailuresWithGetAsync() { - this.serverLifeTime?.Dispose(); - Activity.Current = null; - GC.SuppressFinalize(this); + var exportedItems = new List(); + bool exceptionThrown = false; + + using var traceprovider = Sdk.CreateTracerProviderBuilder() + .AddHttpClientInstrumentation(o => o.RecordException = true) + .AddInMemoryExporter(exportedItems) + .Build(); + + using var c = new HttpClient(); + try + { + await c.GetAsync("https://sdlfaldfjalkdfjlkajdflkajlsdjf.sdlkjafsdjfalfadslkf.com/"); + } + catch + { + exceptionThrown = true; + } + + // Exception is thrown and collected as event + Assert.True(exceptionThrown); + Assert.Single(exportedItems[0].Events.Where(evt => evt.Name.Equals("exception"))); } - private static void ActivityEnrichmentSetTag(Activity activity, string method, object obj) + [Fact] + public async Task HttpClientInstrumentationDoesNotReportExceptionEventOnErrorResponseWithGetAsync() { - ActivityEnrichment(activity, method, obj); - activity.SetTag("enriched", "yes"); + var exportedItems = new List(); + bool exceptionThrown = false; + + using var traceprovider = Sdk.CreateTracerProviderBuilder() + .AddHttpClientInstrumentation(o => o.RecordException = true) + .AddInMemoryExporter(exportedItems) + .Build(); + + using var c = new HttpClient(); + try + { + await c.GetAsync($"{this.url}500"); + } + catch + { + exceptionThrown = true; + } + + // Exception is not thrown and not collected as event + Assert.False(exceptionThrown); + Assert.Empty(exportedItems[0].Events); } - private static void ActivityEnrichment(Activity activity, string method, object obj) + [Fact] + public async Task HttpClientInstrumentationDoesNotReportExceptionEventOnErrorResponseWithGetStringAsync() { - switch (method) + var exportedItems = new List(); + bool exceptionThrown = false; + var request = new HttpRequestMessage { - case "OnStartActivity": - Assert.True(obj is HttpRequestMessage); - break; - - case "OnStopActivity": - Assert.True(obj is HttpResponseMessage); - break; + RequestUri = new Uri($"{this.url}500"), + Method = new HttpMethod("GET"), + }; - case "OnException": - Assert.True(obj is Exception); - break; + using var traceprovider = Sdk.CreateTracerProviderBuilder() + .AddHttpClientInstrumentation(o => o.RecordException = true) + .AddInMemoryExporter(exportedItems) + .Build(); - default: - break; + using var c = new HttpClient(); + try + { + await c.GetStringAsync($"{this.url}500"); + } + catch + { + exceptionThrown = true; } + + // Exception is thrown and not collected as event + Assert.True(exceptionThrown); + Assert.Empty(exportedItems[0].Events); + } + + public void Dispose() + { + this.serverLifeTime?.Dispose(); + Activity.Current = null; + GC.SuppressFinalize(this); } } } diff --git a/test/OpenTelemetry.Instrumentation.Http.Tests/HttpClientTests.cs b/test/OpenTelemetry.Instrumentation.Http.Tests/HttpClientTests.cs index 7407e134527..047deb4d496 100644 --- a/test/OpenTelemetry.Instrumentation.Http.Tests/HttpClientTests.cs +++ b/test/OpenTelemetry.Instrumentation.Http.Tests/HttpClientTests.cs @@ -33,14 +33,16 @@ namespace OpenTelemetry.Instrumentation.Http.Tests { public partial class HttpClientTests { - private static int counter; - public static IEnumerable TestData => HttpTestData.ReadTestCases(); [Theory] [MemberData(nameof(TestData))] public async Task HttpOutCallsAreCollectedSuccessfullyAsync(HttpTestData.HttpOutTestCase tc) { + bool enrichWithHttpRequestMessageCalled = false; + bool enrichWithHttpResponseMessageCalled = false; + bool enrichWithExceptionCalled = false; + var serverLifeTime = TestHttpServer.RunServer( (ctx) => { @@ -65,7 +67,9 @@ public async Task HttpOutCallsAreCollectedSuccessfullyAsync(HttpTestData.HttpOut using (Sdk.CreateTracerProviderBuilder() .AddHttpClientInstrumentation((opt) => { - opt.Enrich = ActivityEnrichment; + opt.EnrichWithHttpRequestMessage = (activity, httpRequestMessage) => { enrichWithHttpRequestMessageCalled = true; }; + opt.EnrichWithHttpResponseMessage = (activity, httpResponseMessage) => { enrichWithHttpResponseMessageCalled = true; }; + opt.EnrichWithException = (activity, exception) => { enrichWithExceptionCalled = true; }; opt.RecordException = tc.RecordException ?? false; }) .AddProcessor(processor.Object) @@ -109,6 +113,12 @@ public async Task HttpOutCallsAreCollectedSuccessfullyAsync(HttpTestData.HttpOut Assert.Equal(ActivityKind.Client, activity.Kind); Assert.Equal(tc.SpanName, activity.DisplayName); + Assert.True(enrichWithHttpRequestMessageCalled); + if (tc.ResponseExpected) + { + Assert.True(enrichWithHttpResponseMessageCalled); + } + // Assert.Equal(tc.SpanStatus, d[span.Status.CanonicalCode]); Assert.Equal(tc.SpanStatus, activity.Status.ToString()); @@ -131,6 +141,7 @@ public async Task HttpOutCallsAreCollectedSuccessfullyAsync(HttpTestData.HttpOut if (tc.RecordException.HasValue && tc.RecordException.Value) { Assert.Single(activity.Events.Where(evt => evt.Name.Equals("exception"))); + Assert.True(enrichWithExceptionCalled); } if (tc.ResponseExpected) @@ -214,17 +225,23 @@ public async Task DebugIndividualTestAsync() [Fact] public async Task CheckEnrichmentWhenSampling() { - await CheckEnrichment(new AlwaysOffSampler(), 0, this.url).ConfigureAwait(false); - await CheckEnrichment(new AlwaysOnSampler(), 2, this.url).ConfigureAwait(false); + await CheckEnrichment(new AlwaysOffSampler(), false, this.url).ConfigureAwait(false); + await CheckEnrichment(new AlwaysOnSampler(), true, this.url).ConfigureAwait(false); } - private static async Task CheckEnrichment(Sampler sampler, int expect, string url) + private static async Task CheckEnrichment(Sampler sampler, bool enrichExpected, string url) { - counter = 0; + bool enrichWithHttpRequestMessageCalled = false; + bool enrichWithHttpResponseMessageCalled = false; + var processor = new Mock>(); using (Sdk.CreateTracerProviderBuilder() .SetSampler(sampler) - .AddHttpClientInstrumentation(options => options.Enrich = ActivityEnrichmentCounter) + .AddHttpClientInstrumentation(options => + { + options.EnrichWithHttpRequestMessage = (activity, httpRequestMessage) => { enrichWithHttpRequestMessageCalled = true; }; + options.EnrichWithHttpResponseMessage = (activity, httpResponseMessage) => { enrichWithHttpResponseMessageCalled = true; }; + }) .AddProcessor(processor.Object) .Build()) { @@ -232,12 +249,16 @@ private static async Task CheckEnrichment(Sampler sampler, int expect, string ur using var r = await c.GetAsync(url).ConfigureAwait(false); } - Assert.Equal(expect, counter); - } - - private static void ActivityEnrichmentCounter(Activity activity, string method, object obj) - { - counter++; + if (enrichExpected) + { + Assert.True(enrichWithHttpRequestMessageCalled); + Assert.True(enrichWithHttpResponseMessageCalled); + } + else + { + Assert.False(enrichWithHttpRequestMessageCalled); + Assert.False(enrichWithHttpResponseMessageCalled); + } } } } diff --git a/test/OpenTelemetry.Instrumentation.Http.Tests/HttpWebRequestActivitySourceTests.netfx.cs b/test/OpenTelemetry.Instrumentation.Http.Tests/HttpWebRequestActivitySourceTests.netfx.cs index 1d10b03d65d..a4073069167 100644 --- a/test/OpenTelemetry.Instrumentation.Http.Tests/HttpWebRequestActivitySourceTests.netfx.cs +++ b/test/OpenTelemetry.Instrumentation.Http.Tests/HttpWebRequestActivitySourceTests.netfx.cs @@ -43,7 +43,15 @@ static HttpWebRequestActivitySourceTests() { HttpWebRequestInstrumentationOptions options = new HttpWebRequestInstrumentationOptions { - Enrich = ActivityEnrichment, + EnrichWithHttpWebRequest = (activity, httpWebRequest) => + { + VerifyHeaders(httpWebRequest); + + if (validateBaggage) + { + ValidateBaggage(httpWebRequest); + } + }, }; HttpWebRequestActivitySource.Options = options; diff --git a/test/OpenTelemetry.Instrumentation.Http.Tests/HttpWebRequestTests.Basic.netfx.cs b/test/OpenTelemetry.Instrumentation.Http.Tests/HttpWebRequestTests.Basic.netfx.cs index 382a1016343..36b838087ff 100644 --- a/test/OpenTelemetry.Instrumentation.Http.Tests/HttpWebRequestTests.Basic.netfx.cs +++ b/test/OpenTelemetry.Instrumentation.Http.Tests/HttpWebRequestTests.Basic.netfx.cs @@ -15,6 +15,7 @@ // #if NETFRAMEWORK using System; +using System.Collections.Generic; using System.Diagnostics; using System.Linq; using System.Net; @@ -45,7 +46,15 @@ public HttpWebRequestTests() this.serverLifeTime = TestHttpServer.RunServer( (ctx) => { - ctx.Response.StatusCode = 200; + if (ctx.Request.Url.PathAndQuery.Contains("500")) + { + ctx.Response.StatusCode = 500; + } + else + { + ctx.Response.StatusCode = 200; + } + ctx.Response.OutputStream.Close(); }, out var host, @@ -296,6 +305,147 @@ public async Task HttpWebRequestInstrumentationOnExistingInstance() Assert.Equal(3, activityProcessor.Invocations.Count); // SetParentProvider/Begin/End called } + + [Fact] + public async Task HttpClientInstrumentationReportsExceptionEventForNetworkFailuresWithGetAsync() + { + var exportedItems = new List(); + bool exceptionThrown = false; + + using var traceprovider = Sdk.CreateTracerProviderBuilder() + .AddHttpClientInstrumentation(o => o.RecordException = true) + .AddInMemoryExporter(exportedItems) + .Build(); + + using var c = new HttpClient(); + try + { + await c.GetAsync("https://sdlfaldfjalkdfjlkajdflkajlsdjf.sdlkjafsdjfalfadslkf.com/"); + } + catch + { + exceptionThrown = true; + } + + // Exception is thrown and collected as event + Assert.True(exceptionThrown); + Assert.Single(exportedItems[0].Events.Where(evt => evt.Name.Equals("exception"))); + } + + [Fact] + public async Task HttpClientInstrumentationDoesNotReportExceptionEventOnErrorResponseWithGetAsync() + { + var exportedItems = new List(); + bool exceptionThrown = false; + + using var traceprovider = Sdk.CreateTracerProviderBuilder() + .AddHttpClientInstrumentation(o => o.RecordException = true) + .AddInMemoryExporter(exportedItems) + .Build(); + + using var c = new HttpClient(); + try + { + await c.GetAsync($"{this.url}500"); + } + catch + { + exceptionThrown = true; + } + + // Exception is not thrown and not collected as event + Assert.False(exceptionThrown); + Assert.Empty(exportedItems[0].Events); + } + + [Fact] + public async Task HttpClientInstrumentationDoesNotReportExceptionEventOnErrorResponseWithGetStringAsync() + { + var exportedItems = new List(); + bool exceptionThrown = false; + var request = new HttpRequestMessage + { + RequestUri = new Uri($"{this.url}500"), + Method = new HttpMethod("GET"), + }; + + using var traceprovider = Sdk.CreateTracerProviderBuilder() + .AddHttpClientInstrumentation(o => o.RecordException = true) + .AddInMemoryExporter(exportedItems) + .Build(); + + using var c = new HttpClient(); + try + { + await c.GetStringAsync($"{this.url}500"); + } + catch + { + exceptionThrown = true; + } + + // Exception is thrown and not collected as event + Assert.True(exceptionThrown); + Assert.Empty(exportedItems[0].Events); + } + + [Fact] + public async Task HttpWebRequestInstrumentationReportsExceptionEventForNetworkFailures() + { + var exportedItems = new List(); + bool exceptionThrown = false; + + using var traceprovider = Sdk.CreateTracerProviderBuilder() + .AddHttpClientInstrumentation(o => o.RecordException = true) + .AddInMemoryExporter(exportedItems) + .Build(); + + try + { + var request = (HttpWebRequest)WebRequest.Create("https://sdlfaldfjalkdfjlkajdflkajlsdjf.sdlkjafsdjfalfadslkf.com/"); + + request.Method = "GET"; + + using var response = await request.GetResponseAsync(); + } + catch + { + exceptionThrown = true; + } + + // Exception is thrown and collected as event + Assert.True(exceptionThrown); + Assert.Single(exportedItems[0].Events.Where(evt => evt.Name.Equals("exception"))); + } + + [Fact] + public async Task HttpWebRequestInstrumentationReportsExceptionEventOnErrorResponse() + { + var exportedItems = new List(); + bool exceptionThrown = false; + + using var traceprovider = Sdk.CreateTracerProviderBuilder() + .AddHttpClientInstrumentation(o => o.RecordException = true) + .AddInMemoryExporter(exportedItems) + .Build(); + + try + { + var request = (HttpWebRequest)WebRequest.Create($"{this.url}500"); + + request.Method = "GET"; + + using var response = await request.GetResponseAsync(); + } + catch + { + exceptionThrown = true; + } + + // Exception is thrown and collected as event + Assert.True(exceptionThrown); + Assert.Single(exportedItems[0].Events.Where(evt => evt.Name.Equals("exception"))); + } } } #endif diff --git a/test/OpenTelemetry.Instrumentation.Http.Tests/HttpWebRequestTests.netfx.cs b/test/OpenTelemetry.Instrumentation.Http.Tests/HttpWebRequestTests.netfx.cs index a31ddbaaf43..9768999ab3b 100644 --- a/test/OpenTelemetry.Instrumentation.Http.Tests/HttpWebRequestTests.netfx.cs +++ b/test/OpenTelemetry.Instrumentation.Http.Tests/HttpWebRequestTests.netfx.cs @@ -45,12 +45,18 @@ public void HttpOutCallsAreCollectedSuccessfully(HttpTestData.HttpOutTestCase tc out var host, out var port); + bool enrichWithHttpWebRequestCalled = false; + bool enrichWithHttpWebResponseCalled = false; + bool enrichWithExceptionCalled = false; + var activityProcessor = new Mock>(); using var tracerProvider = Sdk.CreateTracerProviderBuilder() .AddProcessor(activityProcessor.Object) .AddHttpClientInstrumentation(options => { - options.Enrich = ActivityEnrichment; + options.EnrichWithHttpWebRequest = (activity, httpWebRequest) => { enrichWithHttpWebRequestCalled = true; }; + options.EnrichWithHttpWebResponse = (activity, httpWebResponse) => { enrichWithHttpWebResponseCalled = true; }; + options.EnrichWithException = (activity, exception) => { enrichWithExceptionCalled = true; }; options.RecordException = tc.RecordException.HasValue ? tc.RecordException.Value : false; }) .Build(); @@ -128,9 +134,16 @@ public void HttpOutCallsAreCollectedSuccessfully(HttpTestData.HttpOutTestCase tc Assert.Equal(value, tagValue); } + Assert.True(enrichWithHttpWebRequestCalled); + if (tc.ResponseExpected) + { + Assert.True(enrichWithHttpWebResponseCalled); + } + if (tc.RecordException.HasValue && tc.RecordException.Value) { Assert.Single(activity.Events.Where(evt => evt.Name.Equals("exception"))); + Assert.True(enrichWithExceptionCalled); } } @@ -165,27 +178,6 @@ private static void ValidateHttpWebRequestActivity(Activity activityToValidate) { Assert.Equal(ActivityKind.Client, activityToValidate.Kind); } - - private static void ActivityEnrichment(Activity activity, string method, object obj) - { - switch (method) - { - case "OnStartActivity": - Assert.True(obj is HttpWebRequest); - break; - - case "OnStopActivity": - Assert.True(obj is HttpWebResponse); - break; - - case "OnException": - Assert.True(obj is Exception); - break; - - default: - break; - } - } } } #endif diff --git a/test/OpenTelemetry.Instrumentation.SqlClient.Tests/SqlClientTests.cs b/test/OpenTelemetry.Instrumentation.SqlClient.Tests/SqlClientTests.cs index 6c1979d0d58..7164ba8d18e 100644 --- a/test/OpenTelemetry.Instrumentation.SqlClient.Tests/SqlClientTests.cs +++ b/test/OpenTelemetry.Instrumentation.SqlClient.Tests/SqlClientTests.cs @@ -15,6 +15,7 @@ // using System; +using System.Collections; using System.Collections.Generic; using System.Data; using System.Diagnostics; @@ -308,6 +309,63 @@ public void SqlClientCreatesActivityWithDbSystem( VerifySamplingParameters(sampler.LatestSamplingParameters); } + + [Fact] + public void ShouldCollectTelemetryWhenFilterEvaluatesToTrue() + { + var activities = this.RunCommandWithFilter( + cmd => + { + cmd.CommandText = "select 2"; + }, + cmd => + { + if (cmd is SqlCommand command) + { + return command.CommandText == "select 2"; + } + + return true; + }); + + Assert.Single(activities); + Assert.True(activities[0].IsAllDataRequested); + Assert.True(activities[0].ActivityTraceFlags.HasFlag(ActivityTraceFlags.Recorded)); + } + + [Fact] + public void ShouldNotCollectTelemetryWhenFilterEvaluatesToFalse() + { + var activities = this.RunCommandWithFilter( + cmd => + { + cmd.CommandText = "select 1"; + }, + cmd => + { + if (cmd is SqlCommand command) + { + return command.CommandText == "select 2"; + } + + return true; + }); + + Assert.Empty(activities); + } + + [Fact] + public void ShouldNotCollectTelemetryAndShouldNotPropagateExceptionWhenFilterThrowsException() + { + var activities = this.RunCommandWithFilter( + cmd => + { + cmd.CommandText = "select 1"; + }, + cmd => throw new InvalidOperationException("foobar")); + + Assert.Empty(activities); + } #endif private static void VerifyActivityData( @@ -326,13 +384,13 @@ private static void VerifyActivityData( if (!isFailure) { - Assert.Equal(Status.Unset, activity.GetStatus()); + Assert.Equal(ActivityStatusCode.Unset, activity.Status); } else { var status = activity.GetStatus(); - Assert.Equal(Status.Error.StatusCode, status.StatusCode); - Assert.NotNull(status.Description); + Assert.Equal(ActivityStatusCode.Error, activity.Status); + Assert.NotNull(activity.StatusDescription); if (recordException) { @@ -414,6 +472,52 @@ private static void ActivityEnrichment(Activity activity, string method, object } } +#if !NETFRAMEWORK + private Activity[] RunCommandWithFilter(Action sqlCommandSetup, Func filter) + { + using var sqlConnection = new SqlConnection(TestConnectionString); + using var sqlCommand = sqlConnection.CreateCommand(); + + var activities = new List(); + using (Sdk.CreateTracerProviderBuilder() + .AddSqlClientInstrumentation( + options => + { + options.Filter = filter; + }) + .AddInMemoryExporter(activities) + .Build()) + { + var operationId = Guid.NewGuid(); + sqlCommandSetup(sqlCommand); + + var beforeExecuteEventData = new + { + OperationId = operationId, + Command = sqlCommand, + Timestamp = (long?)1000000L, + }; + + this.fakeSqlClientDiagnosticSource.Write( + SqlClientDiagnosticListener.SqlMicrosoftBeforeExecuteCommand, + beforeExecuteEventData); + + var afterExecuteEventData = new + { + OperationId = operationId, + Command = sqlCommand, + Timestamp = 2000000L, + }; + + this.fakeSqlClientDiagnosticSource.Write( + SqlClientDiagnosticListener.SqlMicrosoftAfterExecuteCommand, + afterExecuteEventData); + } + + return activities.ToArray(); + } +#endif + private class FakeSqlClientDiagnosticSource : IDisposable { private readonly DiagnosticListener listener; diff --git a/test/OpenTelemetry.Instrumentation.SqlClient.Tests/SqlEventSourceTests.netfx.cs b/test/OpenTelemetry.Instrumentation.SqlClient.Tests/SqlEventSourceTests.netfx.cs index 66c3264cf6c..0db32cfdd4e 100644 --- a/test/OpenTelemetry.Instrumentation.SqlClient.Tests/SqlEventSourceTests.netfx.cs +++ b/test/OpenTelemetry.Instrumentation.SqlClient.Tests/SqlEventSourceTests.netfx.cs @@ -276,13 +276,12 @@ private static void VerifyActivityData( if (!isFailure) { - Assert.Equal(Status.Unset, activity.GetStatus()); + Assert.Equal(ActivityStatusCode.Unset, activity.Status); } else { - var status = activity.GetStatus(); - Assert.Equal(Status.Error.StatusCode, status.StatusCode); - Assert.NotNull(status.Description); + Assert.Equal(ActivityStatusCode.Error, activity.Status); + Assert.NotNull(activity.StatusDescription); } } diff --git a/test/OpenTelemetry.Tests/Internal/EnvironmentVariableHelperTests.cs b/test/OpenTelemetry.Tests/Internal/EnvironmentVariableHelperTests.cs deleted file mode 100644 index 738fa27b9b3..00000000000 --- a/test/OpenTelemetry.Tests/Internal/EnvironmentVariableHelperTests.cs +++ /dev/null @@ -1,165 +0,0 @@ -// -// Copyright The OpenTelemetry Authors -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -// - -using System; -using Xunit; - -namespace OpenTelemetry.Internal.Tests -{ - public class EnvironmentVariableHelperTests : IDisposable - { - private const string EnvVar = "OTEL_EXAMPLE_VARIABLE"; - - public EnvironmentVariableHelperTests() - { - Environment.SetEnvironmentVariable(EnvVar, null); - } - - public void Dispose() - { - Environment.SetEnvironmentVariable(EnvVar, null); - GC.SuppressFinalize(this); - } - - [Fact] - public void LoadString() - { - const string value = "something"; - Environment.SetEnvironmentVariable(EnvVar, value); - - bool actualBool = EnvironmentVariableHelper.LoadString(EnvVar, out string actualValue); - - Assert.True(actualBool); - Assert.Equal(value, actualValue); - } - - [Fact] - public void LoadString_NoValue() - { - bool actualBool = EnvironmentVariableHelper.LoadString(EnvVar, out string actualValue); - - Assert.False(actualBool); - Assert.Null(actualValue); - } - - [Theory] - [InlineData("true", true)] - [InlineData("TRUE", true)] - [InlineData("false", false)] - [InlineData("FALSE", false)] - [InlineData(" true ", true)] - [InlineData(" false ", false)] - public void LoadBoolean(string value, bool expectedValue) - { - Environment.SetEnvironmentVariable(EnvVar, value); - - bool actualBool = EnvironmentVariableHelper.LoadBoolean(EnvVar, out bool actualValue); - - Assert.True(actualBool); - Assert.Equal(expectedValue, actualValue); - } - - [Fact] - public void LoadBoolean_NoValue() - { - bool actualBool = EnvironmentVariableHelper.LoadBoolean(EnvVar, out bool actualValue); - - Assert.False(actualBool); - Assert.False(actualValue); - } - - [Theory] - [InlineData("something")] // non true/false - [InlineData(" ")] // whitespaces - [InlineData("0")] // 0 - [InlineData("1")] // 1 - public void LoadBoolean_Invalid(string value) - { - Environment.SetEnvironmentVariable(EnvVar, value); - - Assert.Throws(() => EnvironmentVariableHelper.LoadBoolean(EnvVar, out bool _)); - } - - [Theory] - [InlineData("123", 123)] - [InlineData("0", 0)] - public void LoadNumeric(string value, int expectedValue) - { - Environment.SetEnvironmentVariable(EnvVar, value); - - bool actualBool = EnvironmentVariableHelper.LoadNumeric(EnvVar, out int actualValue); - - Assert.True(actualBool); - Assert.Equal(expectedValue, actualValue); - } - - [Fact] - public void LoadNumeric_NoValue() - { - bool actualBool = EnvironmentVariableHelper.LoadNumeric(EnvVar, out int actualValue); - - Assert.False(actualBool); - Assert.Equal(0, actualValue); - } - - [Theory] - [InlineData("something")] // NaN - [InlineData("-12")] // negative number not allowed - [InlineData("-0")] // sign not allowed - [InlineData("-1")] // -1 is not allowed - [InlineData(" 123 ")] // whitespaces not allowed - [InlineData("0xFF")] // only decimal number allowed - public void LoadNumeric_Invalid(string value) - { - Environment.SetEnvironmentVariable(EnvVar, value); - - Assert.Throws(() => EnvironmentVariableHelper.LoadNumeric(EnvVar, out int _)); - } - - [Theory] - [InlineData("http://www.example.com", "http://www.example.com/")] - [InlineData("http://www.example.com/space%20here.html", "http://www.example.com/space here.html")] // characters are converted - [InlineData("http://www.example.com/space here.html", "http://www.example.com/space here.html")] // characters are escaped - public void LoadUri(string value, string expectedValue) - { - Environment.SetEnvironmentVariable(EnvVar, value); - - bool actualBool = EnvironmentVariableHelper.LoadUri(EnvVar, out Uri actualValue); - - Assert.True(actualBool); - Assert.Equal(expectedValue, actualValue.ToString()); - } - - [Fact] - public void LoadUri_NoValue() - { - bool actualBool = EnvironmentVariableHelper.LoadUri(EnvVar, out Uri actualValue); - - Assert.False(actualBool); - Assert.Null(actualValue); - } - - [Theory] - [InlineData("invalid")] // invalid format - [InlineData(" ")] // whitespace - public void LoadUri_Invalid(string value) - { - Environment.SetEnvironmentVariable(EnvVar, value); - - Assert.Throws(() => EnvironmentVariableHelper.LoadUri(EnvVar, out Uri _)); - } - } -} diff --git a/test/OpenTelemetry.Tests/Internal/PeriodicExportingMetricReaderHelperTests.cs b/test/OpenTelemetry.Tests/Internal/PeriodicExportingMetricReaderHelperTests.cs index 78fe549436a..a5d1c4fd3cf 100644 --- a/test/OpenTelemetry.Tests/Internal/PeriodicExportingMetricReaderHelperTests.cs +++ b/test/OpenTelemetry.Tests/Internal/PeriodicExportingMetricReaderHelperTests.cs @@ -15,6 +15,8 @@ // using System; +using System.Collections.Generic; +using Microsoft.Extensions.Configuration; using OpenTelemetry.Exporter; using OpenTelemetry.Metrics; using Xunit; @@ -58,7 +60,7 @@ public void CreatePeriodicExportingMetricReader_TemporalityPreference_FromOption [Fact] public void CreatePeriodicExportingMetricReader_ExportIntervalMilliseconds_FromOptions() { - Environment.SetEnvironmentVariable(PeriodicExportingMetricReaderHelper.OTelMetricExportIntervalEnvVarKey, "88888"); // should be ignored, as value set via options has higher priority + Environment.SetEnvironmentVariable(PeriodicExportingMetricReaderOptions.OTelMetricExportIntervalEnvVarKey, "88888"); // should be ignored, as value set via options has higher priority var value = 123; var reader = CreatePeriodicExportingMetricReader(new() { @@ -74,7 +76,7 @@ public void CreatePeriodicExportingMetricReader_ExportIntervalMilliseconds_FromO [Fact] public void CreatePeriodicExportingMetricReader_ExportTimeoutMilliseconds_FromOptions() { - Environment.SetEnvironmentVariable(PeriodicExportingMetricReaderHelper.OTelMetricExportTimeoutEnvVarKey, "99999"); // should be ignored, as value set via options has higher priority + Environment.SetEnvironmentVariable(PeriodicExportingMetricReaderOptions.OTelMetricExportTimeoutEnvVarKey, "99999"); // should be ignored, as value set via options has higher priority var value = 456; var reader = CreatePeriodicExportingMetricReader(new() { @@ -91,7 +93,7 @@ public void CreatePeriodicExportingMetricReader_ExportTimeoutMilliseconds_FromOp public void CreatePeriodicExportingMetricReader_ExportIntervalMilliseconds_FromEnvVar() { var value = 789; - Environment.SetEnvironmentVariable(PeriodicExportingMetricReaderHelper.OTelMetricExportIntervalEnvVarKey, value.ToString()); + Environment.SetEnvironmentVariable(PeriodicExportingMetricReaderOptions.OTelMetricExportIntervalEnvVarKey, value.ToString()); var reader = CreatePeriodicExportingMetricReader(); Assert.Equal(value, reader.ExportIntervalMilliseconds); @@ -101,23 +103,42 @@ public void CreatePeriodicExportingMetricReader_ExportIntervalMilliseconds_FromE public void CreatePeriodicExportingMetricReader_ExportTimeoutMilliseconds_FromEnvVar() { var value = 246; - Environment.SetEnvironmentVariable(PeriodicExportingMetricReaderHelper.OTelMetricExportTimeoutEnvVarKey, value.ToString()); + Environment.SetEnvironmentVariable(PeriodicExportingMetricReaderOptions.OTelMetricExportTimeoutEnvVarKey, value.ToString()); var reader = CreatePeriodicExportingMetricReader(); Assert.Equal(value, reader.ExportTimeoutMilliseconds); } + [Fact] + public void CreatePeriodicExportingMetricReader_FromIConfiguration() + { + var values = new Dictionary() + { + [PeriodicExportingMetricReaderOptions.OTelMetricExportIntervalEnvVarKey] = "18", + [PeriodicExportingMetricReaderOptions.OTelMetricExportTimeoutEnvVarKey] = "19", + }; + + var configuration = new ConfigurationBuilder() + .AddInMemoryCollection(values) + .Build(); + + var options = new MetricReaderOptions(configuration); + + Assert.Equal(18, options.PeriodicExportingMetricReaderOptions.ExportIntervalMilliseconds); + Assert.Equal(19, options.PeriodicExportingMetricReaderOptions.ExportTimeoutMilliseconds); + } + [Fact] public void EnvironmentVariableNames() { - Assert.Equal("OTEL_METRIC_EXPORT_INTERVAL", PeriodicExportingMetricReaderHelper.OTelMetricExportIntervalEnvVarKey); - Assert.Equal("OTEL_METRIC_EXPORT_TIMEOUT", PeriodicExportingMetricReaderHelper.OTelMetricExportTimeoutEnvVarKey); + Assert.Equal("OTEL_METRIC_EXPORT_INTERVAL", PeriodicExportingMetricReaderOptions.OTelMetricExportIntervalEnvVarKey); + Assert.Equal("OTEL_METRIC_EXPORT_TIMEOUT", PeriodicExportingMetricReaderOptions.OTelMetricExportTimeoutEnvVarKey); } private static void ClearEnvVars() { - Environment.SetEnvironmentVariable(PeriodicExportingMetricReaderHelper.OTelMetricExportIntervalEnvVarKey, null); - Environment.SetEnvironmentVariable(PeriodicExportingMetricReaderHelper.OTelMetricExportTimeoutEnvVarKey, null); + Environment.SetEnvironmentVariable(PeriodicExportingMetricReaderOptions.OTelMetricExportIntervalEnvVarKey, null); + Environment.SetEnvironmentVariable(PeriodicExportingMetricReaderOptions.OTelMetricExportTimeoutEnvVarKey, null); } private static PeriodicExportingMetricReader CreatePeriodicExportingMetricReader( diff --git a/test/OpenTelemetry.Tests/Metrics/AggregatorTest.cs b/test/OpenTelemetry.Tests/Metrics/AggregatorTest.cs index 0b598d4fa34..4876c9262b2 100644 --- a/test/OpenTelemetry.Tests/Metrics/AggregatorTest.cs +++ b/test/OpenTelemetry.Tests/Metrics/AggregatorTest.cs @@ -45,15 +45,25 @@ public void HistogramDistributeToAllBucketsDefault() histogramPoint.Update(250); histogramPoint.Update(499); histogramPoint.Update(500); - histogramPoint.Update(999); + histogramPoint.Update(501); + histogramPoint.Update(750); + histogramPoint.Update(751); histogramPoint.Update(1000); histogramPoint.Update(1001); + histogramPoint.Update(2500); + histogramPoint.Update(2501); + histogramPoint.Update(5000); + histogramPoint.Update(5001); + histogramPoint.Update(7500); + histogramPoint.Update(7501); + histogramPoint.Update(10000); + histogramPoint.Update(10001); histogramPoint.Update(10000000); histogramPoint.TakeSnapshot(true); var count = histogramPoint.GetHistogramCount(); - Assert.Equal(22, count); + Assert.Equal(32, count); int actualCount = 0; foreach (var histogramMeasurement in histogramPoint.GetHistogramBuckets()) diff --git a/test/OpenTelemetry.Tests/Metrics/MeterProviderBuilderExtensionsTests.cs b/test/OpenTelemetry.Tests/Metrics/MeterProviderBuilderExtensionsTests.cs index b4c96f2cc7c..5fac30cdd53 100644 --- a/test/OpenTelemetry.Tests/Metrics/MeterProviderBuilderExtensionsTests.cs +++ b/test/OpenTelemetry.Tests/Metrics/MeterProviderBuilderExtensionsTests.cs @@ -17,6 +17,7 @@ using System; using System.Collections.Generic; using System.Linq; +using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection.Extensions; using OpenTelemetry.Resources; @@ -167,38 +168,149 @@ public void SetAndConfigureResourceTest() var builder = Sdk.CreateMeterProviderBuilder(); int configureInvocations = 0; + bool serviceProviderTestExecuted = false; builder.SetResourceBuilder(ResourceBuilder.CreateEmpty().AddService("Test")); builder.ConfigureResource(builder => { configureInvocations++; - Assert.Single(builder.Resources); + Assert.Single(builder.ResourceDetectors); builder.AddAttributes(new Dictionary() { ["key1"] = "value1" }); - Assert.Equal(2, builder.Resources.Count); + Assert.Equal(2, builder.ResourceDetectors.Count); }); builder.SetResourceBuilder(ResourceBuilder.CreateEmpty()); builder.ConfigureResource(builder => { configureInvocations++; - Assert.Empty(builder.Resources); + Assert.Empty(builder.ResourceDetectors); - builder.AddAttributes(new Dictionary() { ["key2"] = "value2" }); + builder.AddDetector(sp => + { + serviceProviderTestExecuted = true; + Assert.NotNull(sp); + return new ResourceBuilder.WrapperResourceDetector(new Resource(new Dictionary() { ["key2"] = "value2" })); + }); - Assert.Single(builder.Resources); + Assert.Single(builder.ResourceDetectors); }); using var provider = builder.Build() as MeterProviderSdk; + Assert.True(serviceProviderTestExecuted); Assert.Equal(2, configureInvocations); Assert.Single(provider.Resource.Attributes); Assert.Contains(provider.Resource.Attributes, kvp => kvp.Key == "key2" && (string)kvp.Value == "value2"); } + [Fact] + public void ConfigureBuilderIConfigurationAvailableTest() + { + Environment.SetEnvironmentVariable("TEST_KEY", "TEST_KEY_VALUE"); + + bool configureBuilderCalled = false; + + using var provider = Sdk.CreateMeterProviderBuilder() + .ConfigureBuilder((sp, builder) => + { + var configuration = sp.GetRequiredService(); + + configureBuilderCalled = true; + + var testKeyValue = configuration.GetValue("TEST_KEY", null); + + Assert.Equal("TEST_KEY_VALUE", testKeyValue); + }) + .Build(); + + Assert.True(configureBuilderCalled); + + Environment.SetEnvironmentVariable("TEST_KEY", null); + } + + [Fact] + public void ConfigureBuilderIConfigurationModifiableTest() + { + bool configureBuilderCalled = false; + + using var provider = Sdk.CreateMeterProviderBuilder() + .ConfigureServices(services => + { + var configuration = new ConfigurationBuilder() + .AddInMemoryCollection(new Dictionary { ["TEST_KEY_2"] = "TEST_KEY_2_VALUE" }) + .Build(); + + services.AddSingleton(configuration); + }) + .ConfigureBuilder((sp, builder) => + { + var configuration = sp.GetRequiredService(); + + configureBuilderCalled = true; + + var testKey2Value = configuration.GetValue("TEST_KEY_2", null); + + Assert.Equal("TEST_KEY_2_VALUE", testKey2Value); + }) + .Build(); + + Assert.True(configureBuilderCalled); + } + + [Theory] + [InlineData(true)] + [InlineData(false)] + public void MeterProviderNestedResolutionUsingBuilderTest(bool callNestedConfigure) + { + bool innerTestExecuted = false; + + using var provider = Sdk.CreateMeterProviderBuilder() + .ConfigureServices(services => + { + if (callNestedConfigure) + { + services.ConfigureOpenTelemetryMetrics(); + } + }) + .ConfigureBuilder((sp, builder) => + { + innerTestExecuted = true; + Assert.Throws(() => sp.GetService()); + }) + .Build(); + + Assert.True(innerTestExecuted); + + Assert.Throws(() => provider.GetServiceProvider()?.GetService()); + } + + [Fact] + public void MeterProviderNestedResolutionUsingConfigureTest() + { + bool innerTestExecuted = false; + + var serviceCollection = new ServiceCollection(); + + serviceCollection.ConfigureOpenTelemetryMetrics(builder => + { + builder.ConfigureBuilder((sp, builder) => + { + innerTestExecuted = true; + Assert.Throws(() => sp.GetService()); + }); + }); + + using var serviceProvider = serviceCollection.BuildServiceProvider(); + + var resolvedProvider = serviceProvider.GetRequiredService(); + + Assert.True(innerTestExecuted); + } + private static void RunBuilderServiceLifecycleTest( MeterProviderBuilder builder, Func buildFunc, diff --git a/test/OpenTelemetry.Tests/Metrics/MetricAPITest.cs b/test/OpenTelemetry.Tests/Metrics/MetricAPITest.cs index 83d64bd7932..342fffe7107 100644 --- a/test/OpenTelemetry.Tests/Metrics/MetricAPITest.cs +++ b/test/OpenTelemetry.Tests/Metrics/MetricAPITest.cs @@ -1404,14 +1404,14 @@ public void MultithreadedDoubleCounterTest() [Fact] public void MultithreadedLongHistogramTest() { - var expected = new long[11]; + var expected = new long[16]; for (var i = 0; i < expected.Length; i++) { expected[i] = NumberOfThreads * NumberOfMetricUpdateByEachThread; } - // Metric.DefaultHistogramBounds: 0, 5, 10, 25, 50, 75, 100, 250, 500, 1000 - var values = new long[] { -1, 1, 6, 20, 40, 60, 80, 200, 300, 600, 1001 }; + // Metric.DefaultHistogramBounds: 0, 5, 10, 25, 50, 75, 100, 250, 500, 750, 1000, 2500, 5000, 7500, 10000 + var values = new long[] { -1, 1, 6, 20, 40, 60, 80, 200, 300, 600, 800, 1001, 3000, 6000, 8000, 10001 }; this.MultithreadedHistogramTest(expected, values); } @@ -1419,14 +1419,14 @@ public void MultithreadedLongHistogramTest() [Fact] public void MultithreadedDoubleHistogramTest() { - var expected = new long[11]; + var expected = new long[16]; for (var i = 0; i < expected.Length; i++) { expected[i] = NumberOfThreads * NumberOfMetricUpdateByEachThread; } - // Metric.DefaultHistogramBounds: 0, 5, 10, 25, 50, 75, 100, 250, 500, 1000 - var values = new double[] { -1.0, 1.0, 6.0, 20.0, 40.0, 60.0, 80.0, 200.0, 300.0, 600.0, 1001.0 }; + // Metric.DefaultHistogramBounds: 0, 5, 10, 25, 50, 75, 100, 250, 500, 750, 1000, 2500, 5000, 7500, 10000 + var values = new double[] { -1.0, 1.0, 6.0, 20.0, 40.0, 60.0, 80.0, 200.0, 300.0, 600.0, 800.0, 1001.0, 3000.0, 6000.0, 8000.0, 10001.0 }; this.MultithreadedHistogramTest(expected, values); } diff --git a/test/OpenTelemetry.Tests/Metrics/MetricTestData.cs b/test/OpenTelemetry.Tests/Metrics/MetricTestData.cs index 0664dc18c00..c4b8fdf944a 100644 --- a/test/OpenTelemetry.Tests/Metrics/MetricTestData.cs +++ b/test/OpenTelemetry.Tests/Metrics/MetricTestData.cs @@ -49,5 +49,22 @@ public static IEnumerable InvalidHistogramBoundaries new object[] { new double[] { 0, 1, 1, 2 } }, new object[] { new double[] { 0, 1, 2, -1 } }, }; + + public static IEnumerable ValidHistogramMinMax + => new List + { + new object[] { new double[] { -10, 0, 1, 9, 10, 11, 19 }, new HistogramConfiguration(), -10, 19 }, + new object[] { new double[] { double.NegativeInfinity }, new HistogramConfiguration(), double.NegativeInfinity, double.NegativeInfinity }, + new object[] { new double[] { double.NegativeInfinity, 0, double.PositiveInfinity }, new HistogramConfiguration(), double.NegativeInfinity, double.PositiveInfinity }, + new object[] { new double[] { 1 }, new HistogramConfiguration(), 1, 1 }, + new object[] { new double[] { 5, 100, 4, 101, -2, 97 }, new ExplicitBucketHistogramConfiguration() { Boundaries = new double[] { 10, 20 } }, -2, 101 }, + }; + + public static IEnumerable InvalidHistogramMinMax + => new List + { + new object[] { new double[] { 1 }, new HistogramConfiguration() { RecordMinMax = false } }, + new object[] { new double[] { 1 }, new ExplicitBucketHistogramConfiguration() { Boundaries = new double[] { 10, 20 }, RecordMinMax = false } }, + }; } } diff --git a/test/OpenTelemetry.Tests/Metrics/MetricViewTests.cs b/test/OpenTelemetry.Tests/Metrics/MetricViewTests.cs index 3a12cd4ac05..1dda7eb6fa5 100644 --- a/test/OpenTelemetry.Tests/Metrics/MetricViewTests.cs +++ b/test/OpenTelemetry.Tests/Metrics/MetricViewTests.cs @@ -534,7 +534,7 @@ public void ViewToProduceCustomHistogramBound() int index = 0; int actualCount = 0; - var expectedBucketCounts = new long[] { 2, 1, 2, 2, 0, 0, 0, 0, 0, 0, 0 }; + var expectedBucketCounts = new long[] { 2, 1, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; foreach (var histogramMeasurement in histogramPoint.GetHistogramBuckets()) { Assert.Equal(expectedBucketCounts[index], histogramMeasurement.BucketCount); @@ -572,6 +572,74 @@ public void ViewToProduceCustomHistogramBound() Assert.Equal(boundaries.Length + 1, actualCount); } + [Theory] + [MemberData(nameof(MetricTestData.ValidHistogramMinMax), MemberType = typeof(MetricTestData))] + public void HistogramMinMax(double[] values, HistogramConfiguration histogramConfiguration, double expectedMin, double expectedMax) + { + using var meter = new Meter(Utils.GetCurrentMethodName()); + var histogram = meter.CreateHistogram("MyHistogram"); + var exportedItems = new List(); + using var meterProvider = Sdk.CreateMeterProviderBuilder() + .AddMeter(meter.Name) + .AddView(histogram.Name, histogramConfiguration) + .AddInMemoryExporter(exportedItems) + .Build(); + + for (var i = 0; i < values.Length; i++) + { + histogram.Record(values[i]); + } + + meterProvider.ForceFlush(MaxTimeToAllowForFlush); + + var metricPoints = new List(); + foreach (ref readonly var mp in exportedItems[0].GetMetricPoints()) + { + metricPoints.Add(mp); + } + + var histogramPoint = metricPoints[0]; + var hasMinMax = histogramPoint.HasMinMax(); + Assert.True(hasMinMax); + + var min = histogramPoint.GetHistogramMin(); + var max = histogramPoint.GetHistogramMax(); + + Assert.Equal(expectedMin, min); + Assert.Equal(expectedMax, max); + } + + [Theory] + [MemberData(nameof(MetricTestData.InvalidHistogramMinMax), MemberType = typeof(MetricTestData))] + public void HistogramMinMaxNotPresent(double[] values, HistogramConfiguration histogramConfiguration) + { + using var meter = new Meter(Utils.GetCurrentMethodName()); + var histogram = meter.CreateHistogram("MyHistogram"); + var exportedItems = new List(); + using var meterProvider = Sdk.CreateMeterProviderBuilder() + .AddMeter(meter.Name) + .AddView(histogram.Name, histogramConfiguration) + .AddInMemoryExporter(exportedItems) + .Build(); + + for (var i = 0; i < values.Length; i++) + { + histogram.Record(values[i]); + } + + meterProvider.ForceFlush(MaxTimeToAllowForFlush); + + var metricPoints = new List(); + foreach (ref readonly var mp in exportedItems[0].GetMetricPoints()) + { + metricPoints.Add(mp); + } + + var histogramPoint = metricPoints[0]; + + Assert.False(histogramPoint.HasMinMax()); + } + [Fact] public void ViewToSelectTagKeys() { diff --git a/test/OpenTelemetry.Tests/Resources/OtelEnvResourceDetectorTest.cs b/test/OpenTelemetry.Tests/Resources/OtelEnvResourceDetectorTest.cs index b0d445c16cc..3485874a17b 100644 --- a/test/OpenTelemetry.Tests/Resources/OtelEnvResourceDetectorTest.cs +++ b/test/OpenTelemetry.Tests/Resources/OtelEnvResourceDetectorTest.cs @@ -16,6 +16,7 @@ using System; using System.Collections.Generic; +using Microsoft.Extensions.Configuration; using Xunit; namespace OpenTelemetry.Resources.Tests @@ -43,7 +44,9 @@ public void OtelEnvResource_EnvVarKey() public void OtelEnvResource_NullEnvVar() { // Arrange - var resource = new OtelEnvResourceDetector().Detect(); + var resource = new OtelEnvResourceDetector( + new ConfigurationBuilder().AddEnvironmentVariables().Build()) + .Detect(); // Assert Assert.Equal(Resource.Empty, resource); @@ -55,7 +58,9 @@ public void OtelEnvResource_WithEnvVar_1() // Arrange var envVarValue = "Key1=Val1,Key2=Val2"; Environment.SetEnvironmentVariable(OtelEnvResourceDetector.EnvVarKey, envVarValue); - var resource = new OtelEnvResourceDetector().Detect(); + var resource = new OtelEnvResourceDetector( + new ConfigurationBuilder().AddEnvironmentVariables().Build()) + .Detect(); // Assert Assert.NotEqual(Resource.Empty, resource); @@ -68,12 +73,33 @@ public void OtelEnvResource_WithEnvVar_2() // Arrange var envVarValue = "Key1,Key2=Val2"; Environment.SetEnvironmentVariable(OtelEnvResourceDetector.EnvVarKey, envVarValue); - var resource = new OtelEnvResourceDetector().Detect(); + var resource = new OtelEnvResourceDetector( + new ConfigurationBuilder().AddEnvironmentVariables().Build()) + .Detect(); // Assert Assert.NotEqual(Resource.Empty, resource); Assert.Single(resource.Attributes); Assert.Contains(new KeyValuePair("Key2", "Val2"), resource.Attributes); } + + [Fact] + public void OtelEnvResource_UsingIConfiguration() + { + var values = new Dictionary() + { + [OtelEnvResourceDetector.EnvVarKey] = "Key1=Val1,Key2=Val2", + }; + + var configuration = new ConfigurationBuilder() + .AddInMemoryCollection(values) + .Build(); + + var resource = new OtelEnvResourceDetector(configuration).Detect(); + + Assert.NotEqual(Resource.Empty, resource); + Assert.Contains(new KeyValuePair("Key1", "Val1"), resource.Attributes); + Assert.Contains(new KeyValuePair("Key2", "Val2"), resource.Attributes); + } } } diff --git a/test/OpenTelemetry.Tests/Resources/OtelServiceNameEnvVarDetectorTests.cs b/test/OpenTelemetry.Tests/Resources/OtelServiceNameEnvVarDetectorTests.cs index 8d5e5f1aeed..c60de6b9ece 100644 --- a/test/OpenTelemetry.Tests/Resources/OtelServiceNameEnvVarDetectorTests.cs +++ b/test/OpenTelemetry.Tests/Resources/OtelServiceNameEnvVarDetectorTests.cs @@ -16,6 +16,7 @@ using System; using System.Collections.Generic; +using Microsoft.Extensions.Configuration; using Xunit; namespace OpenTelemetry.Resources.Tests @@ -43,7 +44,9 @@ public void OtelServiceNameEnvVar_EnvVarKey() public void OtelServiceNameEnvVar_Null() { // Act - var resource = new OtelServiceNameEnvVarDetector().Detect(); + var resource = new OtelServiceNameEnvVarDetector( + new ConfigurationBuilder().AddEnvironmentVariables().Build()) + .Detect(); // Assert Assert.Equal(Resource.Empty, resource); @@ -57,11 +60,31 @@ public void OtelServiceNameEnvVar_WithValue() Environment.SetEnvironmentVariable(OtelServiceNameEnvVarDetector.EnvVarKey, envVarValue); // Act - var resource = new OtelServiceNameEnvVarDetector().Detect(); + var resource = new OtelServiceNameEnvVarDetector( + new ConfigurationBuilder().AddEnvironmentVariables().Build()) + .Detect(); // Assert Assert.NotEqual(Resource.Empty, resource); Assert.Contains(new KeyValuePair(ResourceSemanticConventions.AttributeServiceName, envVarValue), resource.Attributes); } + + [Fact] + public void OtelServiceNameEnvVar_UsingIConfiguration() + { + var values = new Dictionary() + { + [OtelServiceNameEnvVarDetector.EnvVarKey] = "my-service", + }; + + var configuration = new ConfigurationBuilder() + .AddInMemoryCollection(values) + .Build(); + + var resource = new OtelServiceNameEnvVarDetector(configuration).Detect(); + + Assert.NotEqual(Resource.Empty, resource); + Assert.Contains(new KeyValuePair(ResourceSemanticConventions.AttributeServiceName, "my-service"), resource.Attributes); + } } } diff --git a/test/OpenTelemetry.Tests/Resources/ResourceTest.cs b/test/OpenTelemetry.Tests/Resources/ResourceTest.cs index bd8ab12516d..0777ba092d9 100644 --- a/test/OpenTelemetry.Tests/Resources/ResourceTest.cs +++ b/test/OpenTelemetry.Tests/Resources/ResourceTest.cs @@ -17,6 +17,7 @@ using System; using System.Collections.Generic; using System.Linq; +using Microsoft.Extensions.DependencyInjection; using Xunit; namespace OpenTelemetry.Resources.Tests @@ -499,6 +500,45 @@ public void GetResource_WithServiceNameSetWithTwoEnvVarsAndCode() Assert.Contains(new KeyValuePair("service.name", "from-code"), attributes); } + [Fact] + public void ResourceBuilder_ServiceProvider_Available() + { + var builder = ResourceBuilder.CreateDefault(); + + bool nullTestRun = false; + + builder.AddDetector(sp => + { + nullTestRun = true; + Assert.Null(sp); + return new NoopResourceDetector(); + }); + + builder.Build(); + + Assert.True(nullTestRun); + + builder = ResourceBuilder.CreateDefault(); + + bool validTestRun = false; + + var serviceCollection = new ServiceCollection(); + using var serviceProvider = serviceCollection.BuildServiceProvider(); + + builder.ServiceProvider = serviceProvider; + + builder.AddDetector(sp => + { + validTestRun = true; + Assert.NotNull(sp); + return new NoopResourceDetector(); + }); + + builder.Build(); + + Assert.True(validTestRun); + } + private static void ClearEnvVars() { Environment.SetEnvironmentVariable(OtelEnvResourceDetector.EnvVarKey, null); @@ -552,5 +592,10 @@ private static Dictionary CreateAttributes(int attributeCount, i AddAttributes(attributes, attributeCount, startIndex); return attributes; } + + private sealed class NoopResourceDetector : IResourceDetector + { + public Resource Detect() => Resource.Empty; + } } } diff --git a/test/OpenTelemetry.Tests/Trace/BatchExportActivityProcessorOptionsTest.cs b/test/OpenTelemetry.Tests/Trace/BatchExportActivityProcessorOptionsTest.cs index 712f854aa88..15ecbd6babd 100644 --- a/test/OpenTelemetry.Tests/Trace/BatchExportActivityProcessorOptionsTest.cs +++ b/test/OpenTelemetry.Tests/Trace/BatchExportActivityProcessorOptionsTest.cs @@ -15,6 +15,8 @@ // using System; +using System.Collections.Generic; +using Microsoft.Extensions.Configuration; using Xunit; namespace OpenTelemetry.Trace.Tests @@ -59,6 +61,36 @@ public void BatchExportProcessorOptions_EnvironmentVariableOverride() Assert.Equal(4, options.ScheduledDelayMilliseconds); } + [Fact] + public void ExportActivityProcessorOptions_UsingIConfiguration() + { + var values = new Dictionary() + { + [BatchExportActivityProcessorOptions.MaxQueueSizeEnvVarKey] = "1", + [BatchExportActivityProcessorOptions.MaxExportBatchSizeEnvVarKey] = "2", + [BatchExportActivityProcessorOptions.ExporterTimeoutEnvVarKey] = "3", + [BatchExportActivityProcessorOptions.ScheduledDelayEnvVarKey] = "4", + }; + + var configuration = new ConfigurationBuilder() + .AddInMemoryCollection(values) + .Build(); + + var parentOptions = new ExportActivityProcessorOptions(configuration); + + Assert.Equal(1, parentOptions.BatchExportProcessorOptions.MaxQueueSize); + Assert.Equal(2, parentOptions.BatchExportProcessorOptions.MaxExportBatchSize); + Assert.Equal(3, parentOptions.BatchExportProcessorOptions.ExporterTimeoutMilliseconds); + Assert.Equal(4, parentOptions.BatchExportProcessorOptions.ScheduledDelayMilliseconds); + + var options = new BatchExportActivityProcessorOptions(configuration); + + Assert.Equal(1, options.MaxQueueSize); + Assert.Equal(2, options.MaxExportBatchSize); + Assert.Equal(3, options.ExporterTimeoutMilliseconds); + Assert.Equal(4, options.ScheduledDelayMilliseconds); + } + [Fact] public void BatchExportProcessorOptions_InvalidPortEnvironmentVariableOverride() { diff --git a/test/OpenTelemetry.Tests/Trace/TracerProviderBuilderExtensionsTest.cs b/test/OpenTelemetry.Tests/Trace/TracerProviderBuilderExtensionsTest.cs index 383e691d358..6c94a0da77c 100644 --- a/test/OpenTelemetry.Tests/Trace/TracerProviderBuilderExtensionsTest.cs +++ b/test/OpenTelemetry.Tests/Trace/TracerProviderBuilderExtensionsTest.cs @@ -18,6 +18,7 @@ using System.Collections.Generic; using System.Diagnostics; using System.Linq; +using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection.Extensions; using OpenTelemetry.Resources; @@ -253,32 +254,39 @@ public void SetAndConfigureResourceTest() var builder = Sdk.CreateTracerProviderBuilder(); int configureInvocations = 0; + bool serviceProviderTestExecuted = false; builder.SetResourceBuilder(ResourceBuilder.CreateEmpty().AddService("Test")); builder.ConfigureResource(builder => { configureInvocations++; - Assert.Single(builder.Resources); + Assert.Single(builder.ResourceDetectors); builder.AddAttributes(new Dictionary() { ["key1"] = "value1" }); - Assert.Equal(2, builder.Resources.Count); + Assert.Equal(2, builder.ResourceDetectors.Count); }); builder.SetResourceBuilder(ResourceBuilder.CreateEmpty()); builder.ConfigureResource(builder => { configureInvocations++; - Assert.Empty(builder.Resources); + Assert.Empty(builder.ResourceDetectors); - builder.AddAttributes(new Dictionary() { ["key2"] = "value2" }); + builder.AddDetector(sp => + { + serviceProviderTestExecuted = true; + Assert.NotNull(sp); + return new ResourceBuilder.WrapperResourceDetector(new Resource(new Dictionary() { ["key2"] = "value2" })); + }); - Assert.Single(builder.Resources); + Assert.Single(builder.ResourceDetectors); }); using var provider = builder.Build() as TracerProviderSdk; + Assert.True(serviceProviderTestExecuted); Assert.Equal(2, configureInvocations); Assert.Single(provider.Resource.Attributes); @@ -393,6 +401,110 @@ public void AddExporterNamedOptionsTest() Assert.Equal(1, namedOptionsConfigureInvocations); } + [Fact] + public void ConfigureBuilderIConfigurationAvailableTest() + { + Environment.SetEnvironmentVariable("TEST_KEY", "TEST_KEY_VALUE"); + + bool configureBuilderCalled = false; + + using var provider = Sdk.CreateTracerProviderBuilder() + .ConfigureBuilder((sp, builder) => + { + var configuration = sp.GetRequiredService(); + + configureBuilderCalled = true; + + var testKeyValue = configuration.GetValue("TEST_KEY", null); + + Assert.Equal("TEST_KEY_VALUE", testKeyValue); + }) + .Build(); + + Assert.True(configureBuilderCalled); + + Environment.SetEnvironmentVariable("TEST_KEY", null); + } + + [Fact] + public void ConfigureBuilderIConfigurationModifiableTest() + { + bool configureBuilderCalled = false; + + using var provider = Sdk.CreateTracerProviderBuilder() + .ConfigureServices(services => + { + var configuration = new ConfigurationBuilder() + .AddInMemoryCollection(new Dictionary { ["TEST_KEY_2"] = "TEST_KEY_2_VALUE" }) + .Build(); + + services.AddSingleton(configuration); + }) + .ConfigureBuilder((sp, builder) => + { + var configuration = sp.GetRequiredService(); + + configureBuilderCalled = true; + + var testKey2Value = configuration.GetValue("TEST_KEY_2", null); + + Assert.Equal("TEST_KEY_2_VALUE", testKey2Value); + }) + .Build(); + + Assert.True(configureBuilderCalled); + } + + [Theory] + [InlineData(true)] + [InlineData(false)] + public void TracerProviderNestedResolutionUsingBuilderTest(bool callNestedConfigure) + { + bool innerTestExecuted = false; + + using var provider = Sdk.CreateTracerProviderBuilder() + .ConfigureServices(services => + { + if (callNestedConfigure) + { + services.ConfigureOpenTelemetryTracing(); + } + }) + .ConfigureBuilder((sp, builder) => + { + innerTestExecuted = true; + Assert.Throws(() => sp.GetService()); + }) + .Build(); + + Assert.True(innerTestExecuted); + + Assert.Throws(() => provider.GetServiceProvider()?.GetService()); + } + + [Fact] + public void TracerProviderNestedResolutionUsingConfigureTest() + { + bool innerTestExecuted = false; + + var serviceCollection = new ServiceCollection(); + + serviceCollection.ConfigureOpenTelemetryTracing(builder => + { + builder.ConfigureBuilder((sp, builder) => + { + innerTestExecuted = true; + Assert.Throws(() => sp.GetService()); + }); + }); + + using var serviceProvider = serviceCollection.BuildServiceProvider(); + + var resolvedProvider = serviceProvider.GetRequiredService(); + + Assert.True(innerTestExecuted); + } + private static void RunBuilderServiceLifecycleTest( TracerProviderBuilder builder, Func buildFunc,