[Logs] Revert logging API additions (#3702)

* Revert logging API additions.

* Cleanup.

* Cleanup.

* CHANGELOG update.

* Bug fix.
This commit is contained in:
Mikel Blanchard 2022-09-28 17:18:38 -07:00 committed by GitHub
parent 4938c35e16
commit 7fd3783371
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
62 changed files with 115 additions and 3610 deletions

View File

@ -222,16 +222,6 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "correlation", "docs\logs\co
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "OpenTelemetry.Tests.Stress.Logs", "test\OpenTelemetry.Tests.Stress.Logs\OpenTelemetry.Tests.Stress.Logs.csproj", "{4298057B-24E0-47B3-BB76-C17E81AF6B39}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Examples.LoggingExtensions", "examples\LoggingExtensions\Examples.LoggingExtensions.csproj", "{F5EFF065-7AF5-4D7D-8038-CC419ABD8777}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "OpenTelemetry.Extensions.Serilog", "src\OpenTelemetry.Extensions.Serilog\OpenTelemetry.Extensions.Serilog.csproj", "{0D85558E-15B9-4251-BDBD-9CB7933B57E2}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "OpenTelemetry.Extensions.Serilog.Tests", "test\OpenTelemetry.Extensions.Serilog.Tests\OpenTelemetry.Extensions.Serilog.Tests.csproj", "{6A2C122A-C1CD-4B6B-AE09-2ABB7D3C50CE}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "OpenTelemetry.Extensions.EventSource", "src\OpenTelemetry.Extensions.EventSource\OpenTelemetry.Extensions.EventSource.csproj", "{7AFB4975-9680-4668-9F5E-C3F0CA41E982}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "OpenTelemetry.Extensions.EventSource.Tests", "test\OpenTelemetry.Extensions.EventSource.Tests\OpenTelemetry.Extensions.EventSource.Tests.csproj", "{304FCFFF-97DE-484B-8D8C-612C644426E5}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "OpenTelemetry.Exporter.Prometheus.AspNetCore", "src\OpenTelemetry.Exporter.Prometheus.AspNetCore\OpenTelemetry.Exporter.Prometheus.AspNetCore.csproj", "{921CF401-4C2F-4C6D-A750-0B5DC457C1F1}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "OpenTelemetry.Exporter.Prometheus.HttpListener", "src\OpenTelemetry.Exporter.Prometheus.HttpListener\OpenTelemetry.Exporter.Prometheus.HttpListener.csproj", "{6B0232B7-5F29-4FB5-B383-1AA02DFE1089}"
@ -462,26 +452,6 @@ Global
{4298057B-24E0-47B3-BB76-C17E81AF6B39}.Debug|Any CPU.Build.0 = Debug|Any CPU
{4298057B-24E0-47B3-BB76-C17E81AF6B39}.Release|Any CPU.ActiveCfg = Release|Any CPU
{4298057B-24E0-47B3-BB76-C17E81AF6B39}.Release|Any CPU.Build.0 = Release|Any CPU
{F5EFF065-7AF5-4D7D-8038-CC419ABD8777}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{F5EFF065-7AF5-4D7D-8038-CC419ABD8777}.Debug|Any CPU.Build.0 = Debug|Any CPU
{F5EFF065-7AF5-4D7D-8038-CC419ABD8777}.Release|Any CPU.ActiveCfg = Release|Any CPU
{F5EFF065-7AF5-4D7D-8038-CC419ABD8777}.Release|Any CPU.Build.0 = Release|Any CPU
{0D85558E-15B9-4251-BDBD-9CB7933B57E2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{0D85558E-15B9-4251-BDBD-9CB7933B57E2}.Debug|Any CPU.Build.0 = Debug|Any CPU
{0D85558E-15B9-4251-BDBD-9CB7933B57E2}.Release|Any CPU.ActiveCfg = Release|Any CPU
{0D85558E-15B9-4251-BDBD-9CB7933B57E2}.Release|Any CPU.Build.0 = Release|Any CPU
{6A2C122A-C1CD-4B6B-AE09-2ABB7D3C50CE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{6A2C122A-C1CD-4B6B-AE09-2ABB7D3C50CE}.Debug|Any CPU.Build.0 = Debug|Any CPU
{6A2C122A-C1CD-4B6B-AE09-2ABB7D3C50CE}.Release|Any CPU.ActiveCfg = Release|Any CPU
{6A2C122A-C1CD-4B6B-AE09-2ABB7D3C50CE}.Release|Any CPU.Build.0 = Release|Any CPU
{7AFB4975-9680-4668-9F5E-C3F0CA41E982}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{7AFB4975-9680-4668-9F5E-C3F0CA41E982}.Debug|Any CPU.Build.0 = Debug|Any CPU
{7AFB4975-9680-4668-9F5E-C3F0CA41E982}.Release|Any CPU.ActiveCfg = Release|Any CPU
{7AFB4975-9680-4668-9F5E-C3F0CA41E982}.Release|Any CPU.Build.0 = Release|Any CPU
{304FCFFF-97DE-484B-8D8C-612C644426E5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{304FCFFF-97DE-484B-8D8C-612C644426E5}.Debug|Any CPU.Build.0 = Debug|Any CPU
{304FCFFF-97DE-484B-8D8C-612C644426E5}.Release|Any CPU.ActiveCfg = Release|Any CPU
{304FCFFF-97DE-484B-8D8C-612C644426E5}.Release|Any CPU.Build.0 = Release|Any CPU
{921CF401-4C2F-4C6D-A750-0B5DC457C1F1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{921CF401-4C2F-4C6D-A750-0B5DC457C1F1}.Debug|Any CPU.Build.0 = Debug|Any CPU
{921CF401-4C2F-4C6D-A750-0B5DC457C1F1}.Release|Any CPU.ActiveCfg = Release|Any CPU
@ -541,7 +511,6 @@ Global
{41B784AA-3301-4126-AF9F-1D59BD04B0BF} = {3277B1C0-BDFE-4460-9B0D-D9A661FB48DB}
{6C7A1595-36D6-4229-BBB5-5A6B5791791D} = {3862190B-E2C5-418E-AFDC-DB281FB5C705}
{9A07D215-90AC-4BAF-BCDB-73D74FD3A5C5} = {3862190B-E2C5-418E-AFDC-DB281FB5C705}
{F5EFF065-7AF5-4D7D-8038-CC419ABD8777} = {E359BB2B-9AEC-497D-B321-7DF2450C3B8E}
{5FDAF679-DE5A-4C73-A49B-8ABCF2399229} = {77C7929A-2EED-4AA6-8705-B5C443C8AA0F}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution

View File

@ -1,33 +0,0 @@
// <copyright file="ExampleEventSource.cs" company="OpenTelemetry Authors">
// 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.
// </copyright>
using System.Diagnostics.Tracing;
namespace Examples.LoggingExtensions;
[EventSource(Name = EventSourceName)]
internal sealed class ExampleEventSource : EventSource
{
public const string EventSourceName = "OpenTelemetry-ExampleEventSource";
public static ExampleEventSource Log { get; } = new();
[Event(1, Message = "Example event written with '{0}' reason", Level = EventLevel.Informational)]
public void ExampleEvent(string reason)
{
this.WriteEvent(1, reason);
}
}

View File

@ -1,16 +0,0 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net6.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="$(RepoRoot)\src\OpenTelemetry.Exporter.Console\OpenTelemetry.Exporter.Console.csproj" />
<ProjectReference Include="$(RepoRoot)\src\OpenTelemetry.Extensions.Serilog\OpenTelemetry.Extensions.Serilog.csproj" />
<ProjectReference Include="$(RepoRoot)\src\OpenTelemetry.Extensions.EventSource\OpenTelemetry.Extensions.EventSource.csproj" />
</ItemGroup>
</Project>

View File

@ -1,55 +0,0 @@
// <copyright file="Program.cs" company="OpenTelemetry Authors">
// 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.
// </copyright>
using System.Diagnostics.Tracing;
using Examples.LoggingExtensions;
using OpenTelemetry;
using OpenTelemetry.Logs;
using OpenTelemetry.Resources;
using Serilog;
var openTelemetryLoggerProvider = Sdk.CreateLoggerProviderBuilder()
.SetIncludeFormattedMessage(true)
.ConfigureResource(builder => builder.AddService("Examples.LoggingExtensions"))
.AddConsoleExporter()
.Build();
// Creates an OpenTelemetryEventSourceLogEmitter for routing ExampleEventSource
// events into logs
using var openTelemetryEventSourceLogEmitter = new OpenTelemetryEventSourceLogEmitter(
openTelemetryLoggerProvider, // <- Events will be written to openTelemetryLoggerProvider
(name) => name == ExampleEventSource.EventSourceName ? EventLevel.Informational : null,
disposeProvider: false); // <- Do not dispose the provider with OpenTelemetryEventSourceLogEmitter since in this case it is shared with Serilog
// Configure Serilog global logger
Log.Logger = new LoggerConfiguration()
.WriteTo.OpenTelemetry(
openTelemetryLoggerProvider, // <- Register OpenTelemetry Serilog sink writing to openTelemetryLoggerProvider
disposeProvider: false) // <- Do not dispose the provider with Serilog since in this case it is shared with OpenTelemetryEventSourceLogEmitter
.CreateLogger();
ExampleEventSource.Log.ExampleEvent("Startup complete");
// Note: Serilog ForContext API is used to set "CategoryName" on log messages
ILogger programLogger = Log.Logger.ForContext<Program>();
programLogger.Information("Application started {Greeting} {Location}", "Hello", "World");
// Note: For Serilog this call flushes all logs
Log.CloseAndFlush();
// Manually dispose OpenTelemetryLoggerProvider since it is being shared
openTelemetryLoggerProvider.Dispose();

View File

@ -1,10 +0,0 @@
# OpenTelemetry Logging Extensions Example
This project contains examples of the `LogEmitter` API being used to extend
existing logging platforms to write into OpenTelemetry logs.
* Serilog: Using OpenTelemetry.Extensions.Serilog
## References
* [OpenTelemetry Project](https://opentelemetry.io/)

View File

@ -1,7 +1,6 @@
override OpenTelemetry.Exporter.ConsoleLogRecordExporter.Dispose(bool disposing) -> void
*REMOVED*static OpenTelemetry.Logs.ConsoleExporterLoggingExtensions.AddConsoleExporter(this OpenTelemetry.Logs.OpenTelemetryLoggerOptions loggerOptions, System.Action<OpenTelemetry.Exporter.ConsoleExporterOptions> configure = null) -> OpenTelemetry.Logs.OpenTelemetryLoggerOptions
static OpenTelemetry.Logs.ConsoleExporterLoggingExtensions.AddConsoleExporter(this OpenTelemetry.Logs.OpenTelemetryLoggerOptions loggerOptions) -> OpenTelemetry.Logs.OpenTelemetryLoggerOptions
static OpenTelemetry.Logs.ConsoleExporterLoggingExtensions.AddConsoleExporter(this OpenTelemetry.Logs.OpenTelemetryLoggerOptions loggerOptions, string name, System.Action<OpenTelemetry.Exporter.ConsoleExporterOptions> configure) -> OpenTelemetry.Logs.OpenTelemetryLoggerOptions
static OpenTelemetry.Logs.ConsoleExporterLoggingExtensions.AddConsoleExporter(this OpenTelemetry.Logs.OpenTelemetryLoggerOptions loggerOptions, System.Action<OpenTelemetry.Exporter.ConsoleExporterOptions> configure) -> OpenTelemetry.Logs.OpenTelemetryLoggerOptions
static OpenTelemetry.Metrics.ConsoleExporterMetricsExtensions.AddConsoleExporter(this OpenTelemetry.Metrics.MeterProviderBuilder builder, string name, System.Action<OpenTelemetry.Exporter.ConsoleExporterOptions, OpenTelemetry.Metrics.MetricReaderOptions> configureExporterAndMetricReader) -> OpenTelemetry.Metrics.MeterProviderBuilder
static OpenTelemetry.Metrics.ConsoleExporterMetricsExtensions.AddConsoleExporter(this OpenTelemetry.Metrics.MeterProviderBuilder builder, string name, System.Action<OpenTelemetry.Exporter.ConsoleExporterOptions> configureExporter) -> OpenTelemetry.Metrics.MeterProviderBuilder

View File

@ -1,7 +1,6 @@
override OpenTelemetry.Exporter.ConsoleLogRecordExporter.Dispose(bool disposing) -> void
*REMOVED*static OpenTelemetry.Logs.ConsoleExporterLoggingExtensions.AddConsoleExporter(this OpenTelemetry.Logs.OpenTelemetryLoggerOptions loggerOptions, System.Action<OpenTelemetry.Exporter.ConsoleExporterOptions> configure = null) -> OpenTelemetry.Logs.OpenTelemetryLoggerOptions
static OpenTelemetry.Logs.ConsoleExporterLoggingExtensions.AddConsoleExporter(this OpenTelemetry.Logs.OpenTelemetryLoggerOptions loggerOptions) -> OpenTelemetry.Logs.OpenTelemetryLoggerOptions
static OpenTelemetry.Logs.ConsoleExporterLoggingExtensions.AddConsoleExporter(this OpenTelemetry.Logs.OpenTelemetryLoggerOptions loggerOptions, string name, System.Action<OpenTelemetry.Exporter.ConsoleExporterOptions> configure) -> OpenTelemetry.Logs.OpenTelemetryLoggerOptions
static OpenTelemetry.Logs.ConsoleExporterLoggingExtensions.AddConsoleExporter(this OpenTelemetry.Logs.OpenTelemetryLoggerOptions loggerOptions, System.Action<OpenTelemetry.Exporter.ConsoleExporterOptions> configure) -> OpenTelemetry.Logs.OpenTelemetryLoggerOptions
static OpenTelemetry.Metrics.ConsoleExporterMetricsExtensions.AddConsoleExporter(this OpenTelemetry.Metrics.MeterProviderBuilder builder, string name, System.Action<OpenTelemetry.Exporter.ConsoleExporterOptions, OpenTelemetry.Metrics.MetricReaderOptions> configureExporterAndMetricReader) -> OpenTelemetry.Metrics.MeterProviderBuilder
static OpenTelemetry.Metrics.ConsoleExporterMetricsExtensions.AddConsoleExporter(this OpenTelemetry.Metrics.MeterProviderBuilder builder, string name, System.Action<OpenTelemetry.Exporter.ConsoleExporterOptions> configureExporter) -> OpenTelemetry.Metrics.MeterProviderBuilder

View File

@ -11,11 +11,6 @@
management
([#3648](https://github.com/open-telemetry/opentelemetry-dotnet/pull/3648))
* Added overloads which accept a name to the `OpenTelemetryLoggerOptions`
`AddConsoleExporter` extension to allow for more fine-grained options
management
([#3657](https://github.com/open-telemetry/opentelemetry-dotnet/pull/3657))
* Added overloads which accept a name to the `TracerProviderBuilder`
`AddConsoleExporter` extension to allow for more fine-grained options
management

View File

@ -15,8 +15,6 @@
// </copyright>
using System;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Options;
using OpenTelemetry.Exporter;
using OpenTelemetry.Internal;
@ -30,7 +28,7 @@ namespace OpenTelemetry.Logs
/// <param name="loggerOptions"><see cref="OpenTelemetryLoggerOptions"/> options to use.</param>
/// <returns>The instance of <see cref="OpenTelemetryLoggerOptions"/> to chain the calls.</returns>
public static OpenTelemetryLoggerOptions AddConsoleExporter(this OpenTelemetryLoggerOptions loggerOptions)
=> AddConsoleExporter(loggerOptions, name: null, configure: null);
=> AddConsoleExporter(loggerOptions, configure: null);
/// <summary>
/// Adds Console exporter with OpenTelemetryLoggerOptions.
@ -39,35 +37,12 @@ namespace OpenTelemetry.Logs
/// <param name="configure">Callback action for configuring <see cref="ConsoleExporterOptions"/>.</param>
/// <returns>The instance of <see cref="OpenTelemetryLoggerOptions"/> to chain the calls.</returns>
public static OpenTelemetryLoggerOptions AddConsoleExporter(this OpenTelemetryLoggerOptions loggerOptions, Action<ConsoleExporterOptions> configure)
=> AddConsoleExporter(loggerOptions, name: null, configure);
/// <summary>
/// Adds Console exporter with OpenTelemetryLoggerOptions.
/// </summary>
/// <param name="loggerOptions"><see cref="OpenTelemetryLoggerOptions"/> options to use.</param>
/// <param name="name">Name which is used when retrieving options.</param>
/// <param name="configure">Callback action for configuring <see cref="ConsoleExporterOptions"/>.</param>
/// <returns>The instance of <see cref="OpenTelemetryLoggerOptions"/> to chain the calls.</returns>
public static OpenTelemetryLoggerOptions AddConsoleExporter(
this OpenTelemetryLoggerOptions loggerOptions,
string name,
Action<ConsoleExporterOptions> configure)
{
Guard.ThrowIfNull(loggerOptions);
name ??= Options.DefaultName;
if (configure != null)
{
loggerOptions.ConfigureServices(services => services.Configure(name, configure));
}
return loggerOptions.ConfigureProvider((sp, provider) =>
{
var options = sp.GetRequiredService<IOptionsMonitor<ConsoleExporterOptions>>().Get(name);
provider.AddProcessor(new SimpleLogRecordExportProcessor(new ConsoleLogRecordExporter(options)));
});
var options = new ConsoleExporterOptions();
configure?.Invoke(options);
return loggerOptions.AddProcessor(new SimpleLogRecordExportProcessor(new ConsoleLogRecordExporter(options)));
}
}
}

View File

@ -1,4 +1,3 @@
OpenTelemetry.Logs.OtlpLogExporterHelperExtensions
static OpenTelemetry.Logs.OtlpLogExporterHelperExtensions.AddOtlpExporter(this OpenTelemetry.Logs.OpenTelemetryLoggerOptions loggerOptions) -> OpenTelemetry.Logs.OpenTelemetryLoggerOptions
static OpenTelemetry.Logs.OtlpLogExporterHelperExtensions.AddOtlpExporter(this OpenTelemetry.Logs.OpenTelemetryLoggerOptions loggerOptions, string name, System.Action<OpenTelemetry.Exporter.OtlpExporterOptions> configure) -> OpenTelemetry.Logs.OpenTelemetryLoggerOptions
static OpenTelemetry.Logs.OtlpLogExporterHelperExtensions.AddOtlpExporter(this OpenTelemetry.Logs.OpenTelemetryLoggerOptions loggerOptions, System.Action<OpenTelemetry.Exporter.OtlpExporterOptions> configure) -> OpenTelemetry.Logs.OpenTelemetryLoggerOptions

View File

@ -1,4 +1,3 @@
OpenTelemetry.Logs.OtlpLogExporterHelperExtensions
static OpenTelemetry.Logs.OtlpLogExporterHelperExtensions.AddOtlpExporter(this OpenTelemetry.Logs.OpenTelemetryLoggerOptions loggerOptions) -> OpenTelemetry.Logs.OpenTelemetryLoggerOptions
static OpenTelemetry.Logs.OtlpLogExporterHelperExtensions.AddOtlpExporter(this OpenTelemetry.Logs.OpenTelemetryLoggerOptions loggerOptions, string name, System.Action<OpenTelemetry.Exporter.OtlpExporterOptions> configure) -> OpenTelemetry.Logs.OpenTelemetryLoggerOptions
static OpenTelemetry.Logs.OtlpLogExporterHelperExtensions.AddOtlpExporter(this OpenTelemetry.Logs.OpenTelemetryLoggerOptions loggerOptions, System.Action<OpenTelemetry.Exporter.OtlpExporterOptions> configure) -> OpenTelemetry.Logs.OpenTelemetryLoggerOptions

View File

@ -1,4 +1,3 @@
OpenTelemetry.Logs.OtlpLogExporterHelperExtensions
static OpenTelemetry.Logs.OtlpLogExporterHelperExtensions.AddOtlpExporter(this OpenTelemetry.Logs.OpenTelemetryLoggerOptions loggerOptions) -> OpenTelemetry.Logs.OpenTelemetryLoggerOptions
static OpenTelemetry.Logs.OtlpLogExporterHelperExtensions.AddOtlpExporter(this OpenTelemetry.Logs.OpenTelemetryLoggerOptions loggerOptions, string name, System.Action<OpenTelemetry.Exporter.OtlpExporterOptions> configure) -> OpenTelemetry.Logs.OpenTelemetryLoggerOptions
static OpenTelemetry.Logs.OtlpLogExporterHelperExtensions.AddOtlpExporter(this OpenTelemetry.Logs.OpenTelemetryLoggerOptions loggerOptions, System.Action<OpenTelemetry.Exporter.OtlpExporterOptions> configure) -> OpenTelemetry.Logs.OpenTelemetryLoggerOptions

View File

@ -7,10 +7,6 @@
`HttpProtobuf` is configured
([#3640](https://github.com/open-telemetry/opentelemetry-dotnet/pull/3640))
* Added overloads which accept a name to the `OpenTelemetryLoggerOptions`
`AddOtlpExporter` extension to allow for more fine-grained options management
([#3652](https://github.com/open-telemetry/opentelemetry-dotnet/pull/3652))
## 1.4.0-alpha.2
Released 2022-Aug-18

View File

@ -15,10 +15,7 @@
// </copyright>
using System;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Options;
using OpenTelemetry.Exporter;
using OpenTelemetry.Internal;
namespace OpenTelemetry.Logs
{
@ -30,23 +27,11 @@ namespace OpenTelemetry.Logs
/// <summary>
/// Adds OTLP Exporter as a configuration to the OpenTelemetry ILoggingBuilder.
/// </summary>
/// <remarks><inheritdoc cref="AddOtlpExporter(OpenTelemetryLoggerOptions, string, Action{OtlpExporterOptions})" path="/remarks"/></remarks>
/// <remarks><inheritdoc cref="AddOtlpExporter(OpenTelemetryLoggerOptions, Action{OtlpExporterOptions})" path="/remarks"/></remarks>
/// <param name="loggerOptions"><see cref="OpenTelemetryLoggerOptions"/> options to use.</param>
/// <returns>The instance of <see cref="OpenTelemetryLoggerOptions"/> to chain the calls.</returns>
public static OpenTelemetryLoggerOptions AddOtlpExporter(this OpenTelemetryLoggerOptions loggerOptions)
=> AddOtlpExporter(loggerOptions, name: null, configure: null);
/// <summary>
/// Adds OTLP Exporter as a configuration to the OpenTelemetry ILoggingBuilder.
/// </summary>
/// <remarks><inheritdoc cref="AddOtlpExporter(OpenTelemetryLoggerOptions, string, Action{OtlpExporterOptions})" path="/remarks"/></remarks>
/// <param name="loggerOptions"><see cref="OpenTelemetryLoggerOptions"/> options to use.</param>
/// <param name="configure">Callback action for configuring <see cref="OtlpExporterOptions"/>.</param>
/// <returns>The instance of <see cref="OpenTelemetryLoggerOptions"/> to chain the calls.</returns>
public static OpenTelemetryLoggerOptions AddOtlpExporter(
this OpenTelemetryLoggerOptions loggerOptions,
Action<OtlpExporterOptions> configure)
=> AddOtlpExporter(loggerOptions, name: null, configure);
=> AddOtlpExporter(loggerOptions, configure: null);
/// <summary>
/// Adds OTLP Exporter as a configuration to the OpenTelemetry ILoggingBuilder.
@ -57,59 +42,37 @@ namespace OpenTelemetry.Logs
/// langword="true"/>.
/// </remarks>
/// <param name="loggerOptions"><see cref="OpenTelemetryLoggerOptions"/> options to use.</param>
/// <param name="name">Name which is used when retrieving options.</param>
/// <param name="configure">Callback action for configuring <see cref="OtlpExporterOptions"/>.</param>
/// <returns>The instance of <see cref="OpenTelemetryLoggerOptions"/> to chain the calls.</returns>
public static OpenTelemetryLoggerOptions AddOtlpExporter(
this OpenTelemetryLoggerOptions loggerOptions,
string name,
Action<OtlpExporterOptions> configure)
=> AddOtlpExporter(loggerOptions, new(), configure);
private static OpenTelemetryLoggerOptions AddOtlpExporter(
OpenTelemetryLoggerOptions loggerOptions,
OtlpExporterOptions exporterOptions,
Action<OtlpExporterOptions> configure)
{
Guard.ThrowIfNull(loggerOptions);
loggerOptions.ParseStateValues = true;
name ??= Options.DefaultName;
if (configure != null)
{
loggerOptions.ConfigureServices(services => services.Configure(name, configure));
}
return loggerOptions.ConfigureProvider((sp, provider) =>
{
var options = sp.GetRequiredService<IOptionsMonitor<OtlpExporterOptions>>().Get(name);
AddOtlpExporter(provider, options, sp);
});
}
private static void AddOtlpExporter(
OpenTelemetryLoggerProvider provider,
OtlpExporterOptions exporterOptions,
IServiceProvider serviceProvider)
{
exporterOptions.TryEnableIHttpClientFactoryIntegration(serviceProvider, "OtlpLogExporter");
configure?.Invoke(exporterOptions);
var otlpExporter = new OtlpLogExporter(exporterOptions);
loggerOptions.ParseStateValues = true;
if (exporterOptions.ExportProcessorType == ExportProcessorType.Simple)
{
provider.AddProcessor(new SimpleLogRecordExportProcessor(otlpExporter));
loggerOptions.AddProcessor(new SimpleLogRecordExportProcessor(otlpExporter));
}
else
{
// TODO: exporterOptions.BatchExportProcessorOptions is
// BatchExportActivityProcessorOptions which is using tracing
// environment variables. There should probably be a dedicated
// setting for logs using BatchExportLogRecordProcessorOptions
provider.AddProcessor(new BatchLogRecordExportProcessor(
loggerOptions.AddProcessor(new BatchLogRecordExportProcessor(
otlpExporter,
exporterOptions.BatchExportProcessorOptions.MaxQueueSize,
exporterOptions.BatchExportProcessorOptions.ScheduledDelayMilliseconds,
exporterOptions.BatchExportProcessorOptions.ExporterTimeoutMilliseconds,
exporterOptions.BatchExportProcessorOptions.MaxExportBatchSize));
}
return loggerOptions;
}
}
}

View File

@ -123,9 +123,8 @@ services.AddOpenTelemetryTracing((builder) => builder
For users using
[IHttpClientFactory](https://docs.microsoft.com/dotnet/architecture/microservices/implement-resilient-applications/use-httpclientfactory-to-implement-resilient-http-requests)
you may also customize the named "OtlpTraceExporter", "OtlpMetricExporter",
and/or "OtlpLogExporter" `HttpClient` using the built-in `AddHttpClient`
extension:
you may also customize the named "OtlpTraceExporter" and/or "OtlpMetricExporter"
`HttpClient` using the built-in `AddHttpClient` extension:
```csharp
services.AddHttpClient(

View File

@ -1,6 +0,0 @@
#nullable enable
OpenTelemetry.Logs.OpenTelemetryEventSourceLogEmitter
OpenTelemetry.Logs.OpenTelemetryEventSourceLogEmitter.OpenTelemetryEventSourceLogEmitter(OpenTelemetry.Logs.OpenTelemetryLoggerProvider! openTelemetryLoggerProvider, System.Func<string!, System.Diagnostics.Tracing.EventLevel?>! shouldListenToFunc, bool disposeProvider = true) -> void
OpenTelemetry.Logs.OpenTelemetryEventSourceLoggerOptionsExtensions
override OpenTelemetry.Logs.OpenTelemetryEventSourceLogEmitter.Dispose() -> void
static OpenTelemetry.Logs.OpenTelemetryEventSourceLoggerOptionsExtensions.AddEventSourceLogEmitter(this OpenTelemetry.Logs.OpenTelemetryLoggerOptions! options, System.Func<string!, System.Diagnostics.Tracing.EventLevel?>! shouldListenToFunc) -> OpenTelemetry.Logs.OpenTelemetryLoggerOptions!

View File

@ -1,6 +0,0 @@
#nullable enable
OpenTelemetry.Logs.OpenTelemetryEventSourceLogEmitter
OpenTelemetry.Logs.OpenTelemetryEventSourceLogEmitter.OpenTelemetryEventSourceLogEmitter(OpenTelemetry.Logs.OpenTelemetryLoggerProvider! openTelemetryLoggerProvider, System.Func<string!, System.Diagnostics.Tracing.EventLevel?>! shouldListenToFunc, bool disposeProvider = true) -> void
OpenTelemetry.Logs.OpenTelemetryEventSourceLoggerOptionsExtensions
override OpenTelemetry.Logs.OpenTelemetryEventSourceLogEmitter.Dispose() -> void
static OpenTelemetry.Logs.OpenTelemetryEventSourceLoggerOptionsExtensions.AddEventSourceLogEmitter(this OpenTelemetry.Logs.OpenTelemetryLoggerOptions! options, System.Func<string!, System.Diagnostics.Tracing.EventLevel?>! shouldListenToFunc) -> OpenTelemetry.Logs.OpenTelemetryLoggerOptions!

View File

@ -1,36 +0,0 @@
// <copyright file="AssemblyInfo.cs" company="OpenTelemetry Authors">
// 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.
// </copyright>
using System;
using System.Runtime.CompilerServices;
[assembly: CLSCompliant(false)]
[assembly: InternalsVisibleTo("OpenTelemetry.Extensions.EventSource.Tests" + AssemblyInfo.PublicKey)]
[assembly: InternalsVisibleTo("DynamicProxyGenAssembly2" + AssemblyInfo.MoqPublicKey)]
#if SIGNED
internal static class AssemblyInfo
{
public const string PublicKey = ", PublicKey=002400000480000094000000060200000024000052534131000400000100010051C1562A090FB0C9F391012A32198B5E5D9A60E9B80FA2D7B434C9E5CCB7259BD606E66F9660676AFC6692B8CDC6793D190904551D2103B7B22FA636DCBB8208839785BA402EA08FC00C8F1500CCEF28BBF599AA64FFB1E1D5DC1BF3420A3777BADFE697856E9D52070A50C3EA5821C80BEF17CA3ACFFA28F89DD413F096F898";
public const string MoqPublicKey = ", PublicKey=0024000004800000940000000602000000240000525341310004000001000100c547cac37abd99c8db225ef2f6c8a3602f3b3606cc9891605d02baa56104f4cfc0734aa39b93bf7852f7d9266654753cc297e7d2edfe0bac1cdcf9f717241550e0a7b191195b7667bb4f64bcb8e2121380fd1d9d46ad2d92d2d15605093924cceaf74c4861eff62abf69b9291ed0a340e113be11e6a7d3113e92484cf7045cc7";
}
#else
internal static class AssemblyInfo
{
public const string PublicKey = "";
public const string MoqPublicKey = "";
}
#endif

View File

@ -1,5 +0,0 @@
# Changelog
## Unreleased
Initial release.

View File

@ -1,19 +0,0 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<!-- OmniSharp/VS Code requires TargetFrameworks to be in descending order for IntelliSense and analysis. -->
<TargetFrameworks>netstandard2.1;netstandard2.0</TargetFrameworks>
<Description>Extensions for using OpenTelemetry with System.Diagnostics.Tracing.EventSource</Description>
<Nullable>enable</Nullable>
<AnalysisMode>AllEnabledByDefault</AnalysisMode>
<AnalysisLevel>latest</AnalysisLevel>
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="$(RepoRoot)\src\OpenTelemetry\OpenTelemetry.csproj" />
</ItemGroup>
<ItemGroup>
<Compile Include="$(RepoRoot)\src\OpenTelemetry.Api\Internal\Guard.cs" Link="Includes\Guard.cs" />
</ItemGroup>
</Project>

View File

@ -1,224 +0,0 @@
// <copyright file="OpenTelemetryEventSourceLogEmitter.cs" company="OpenTelemetry Authors">
// 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.
// </copyright>
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Diagnostics.Tracing;
using System.Globalization;
using System.Linq;
using Microsoft.Extensions.Logging;
using OpenTelemetry.Internal;
namespace OpenTelemetry.Logs
{
/// <summary>
/// Implements an <see cref="EventListener"/> which will convert <see
/// cref="EventSource"/> events into OpenTelemetry logs.
/// </summary>
public sealed class OpenTelemetryEventSourceLogEmitter : EventListener
{
private readonly bool includeFormattedMessage;
private readonly OpenTelemetryLoggerProvider openTelemetryLoggerProvider;
private readonly LogEmitter logEmitter;
private readonly object lockObj = new();
private readonly Func<string, EventLevel?> shouldListenToFunc;
private readonly List<EventSource> eventSources = new();
private readonly List<EventSource>? eventSourcesBeforeConstructor = new();
private readonly bool disposeProvider;
/// <summary>
/// Initializes a new instance of the <see
/// cref="OpenTelemetryEventSourceLogEmitter"/> class.
/// </summary>
/// <param name="openTelemetryLoggerProvider"><see
/// cref="OpenTelemetryLoggerProvider"/>.</param>
/// <param name="shouldListenToFunc">Callback function used to decide if
/// events should be captured for a given <see
/// cref="EventSource.Name"/>. Return <see langword="null"/> if no
/// events should be captured.</param>
/// <param name="disposeProvider">Controls whether or not the supplied
/// <paramref name="openTelemetryLoggerProvider"/> will be disposed when
/// the <see cref="EventListener"/> is disposed. Default value: <see
/// langword="true"/>.</param>
public OpenTelemetryEventSourceLogEmitter(
OpenTelemetryLoggerProvider openTelemetryLoggerProvider,
Func<string, EventLevel?> shouldListenToFunc,
bool disposeProvider = true)
{
Guard.ThrowIfNull(openTelemetryLoggerProvider);
Guard.ThrowIfNull(shouldListenToFunc);
this.includeFormattedMessage = openTelemetryLoggerProvider.IncludeFormattedMessage;
this.openTelemetryLoggerProvider = openTelemetryLoggerProvider!;
this.disposeProvider = disposeProvider;
this.shouldListenToFunc = shouldListenToFunc;
var logEmitter = this.openTelemetryLoggerProvider.CreateEmitter();
Debug.Assert(logEmitter != null, "logEmitter was null");
this.logEmitter = logEmitter!;
lock (this.lockObj)
{
foreach (EventSource eventSource in this.eventSourcesBeforeConstructor)
{
this.ProcessSource(eventSource);
}
this.eventSourcesBeforeConstructor = null;
}
}
/// <inheritdoc/>
public override void Dispose()
{
foreach (EventSource eventSource in this.eventSources)
{
this.DisableEvents(eventSource);
}
this.eventSources.Clear();
if (this.disposeProvider)
{
this.openTelemetryLoggerProvider.Dispose();
}
base.Dispose();
}
#pragma warning disable CA1062 // Validate arguments of public methods
/// <inheritdoc/>
protected override void OnEventSourceCreated(EventSource eventSource)
{
Debug.Assert(eventSource != null, "EventSource was null.");
try
{
if (this.eventSourcesBeforeConstructor != null)
{
lock (this.lockObj)
{
if (this.eventSourcesBeforeConstructor != null)
{
this.eventSourcesBeforeConstructor.Add(eventSource!);
return;
}
}
}
this.ProcessSource(eventSource!);
}
finally
{
base.OnEventSourceCreated(eventSource);
}
}
#pragma warning restore CA1062 // Validate arguments of public methods
#pragma warning disable CA1062 // Validate arguments of public methods
/// <inheritdoc/>
protected override void OnEventWritten(EventWrittenEventArgs eventData)
{
Debug.Assert(eventData != null, "EventData was null.");
string? rawMessage = eventData!.Message;
LogRecordData data = new(Activity.Current)
{
#if NETSTANDARD2_1_OR_GREATER
Timestamp = eventData.TimeStamp,
#endif
EventId = new EventId(eventData.EventId, eventData.EventName),
LogLevel = ConvertEventLevelToLogLevel(eventData.Level),
};
LogRecordAttributeList attributes = default;
attributes.Add("event_source.name", eventData.EventSource.Name);
if (eventData.ActivityId != Guid.Empty)
{
attributes.Add("event_source.activity_id", eventData.ActivityId);
}
if (eventData.RelatedActivityId != Guid.Empty)
{
attributes.Add("event_source.related_activity_id", eventData.RelatedActivityId);
}
int payloadCount = eventData.Payload?.Count ?? 0;
if (payloadCount > 0 && payloadCount == eventData.PayloadNames?.Count)
{
for (int i = 0; i < payloadCount; i++)
{
string name = eventData.PayloadNames[i];
if (!string.IsNullOrEmpty(rawMessage) && !this.includeFormattedMessage)
{
// TODO: This code converts the event message from
// string.Format syntax (eg: "Some message {0} {1}")
// into structured log format (eg: "Some message
// {propertyName1} {propertyName2}") but it is
// expensive. Probably needs a cache.
#if NETSTANDARD2_0
rawMessage = rawMessage.Replace($"{{{i}}}", $"{{{name}}}");
#else
rawMessage = rawMessage.Replace($"{{{i}}}", $"{{{name}}}", StringComparison.Ordinal);
#endif
}
attributes.Add(name, eventData.Payload![i]);
}
}
if (!string.IsNullOrEmpty(rawMessage) && this.includeFormattedMessage && payloadCount > 0)
{
rawMessage = string.Format(CultureInfo.InvariantCulture, rawMessage, eventData.Payload!.ToArray());
}
data.Message = rawMessage;
this.logEmitter.Emit(in data, in attributes);
}
#pragma warning restore CA1062 // Validate arguments of public methods
private static LogLevel ConvertEventLevelToLogLevel(EventLevel eventLevel)
{
return eventLevel switch
{
EventLevel.Informational => LogLevel.Information,
EventLevel.Warning => LogLevel.Warning,
EventLevel.Error => LogLevel.Error,
EventLevel.Critical => LogLevel.Critical,
_ => LogLevel.Trace,
};
}
private void ProcessSource(EventSource eventSource)
{
EventLevel? eventLevel = this.shouldListenToFunc(eventSource.Name);
if (eventLevel.HasValue)
{
this.eventSources.Add(eventSource);
this.EnableEvents(eventSource, eventLevel.Value, EventKeywords.All);
}
}
}
}

View File

@ -1,78 +0,0 @@
// <copyright file="OpenTelemetryEventSourceLoggerOptionsExtensions.cs" company="OpenTelemetry Authors">
// 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.
// </copyright>
using System;
using System.Collections.Generic;
using System.Diagnostics.Tracing;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.DependencyInjection.Extensions;
using OpenTelemetry.Internal;
namespace OpenTelemetry.Logs
{
/// <summary>
/// Contains extension methods for registering OpenTelemetry EventSource utilities into logging services.
/// </summary>
public static class OpenTelemetryEventSourceLoggerOptionsExtensions
{
/// <summary>
/// Registers an <see cref="EventListener"/> which will convert <see
/// cref="EventSource"/> events into OpenTelemetry logs.
/// </summary>
/// <param name="options"><see
/// cref="OpenTelemetryLoggerOptions"/>.</param>
/// <param name="shouldListenToFunc">Callback function used to decide if
/// events should be captured for a given <see
/// cref="EventSource.Name"/>. Return <see langword="null"/> if no
/// events should be captured.</param>
/// <returns>Supplied <see cref="OpenTelemetryLoggerOptions"/> for
/// chaining calls.</returns>
public static OpenTelemetryLoggerOptions AddEventSourceLogEmitter(
this OpenTelemetryLoggerOptions options,
Func<string, EventLevel?> shouldListenToFunc)
{
Guard.ThrowIfNull(options);
Guard.ThrowIfNull(shouldListenToFunc);
options.ConfigureServices(services => services.TryAddSingleton<EventSourceManager>());
options.ConfigureProvider((sp, provider) =>
{
var manager = sp.GetRequiredService<EventSourceManager>();
manager.Emitters.Add(
new OpenTelemetryEventSourceLogEmitter(provider, shouldListenToFunc, disposeProvider: false));
});
return options;
}
internal sealed class EventSourceManager : IDisposable
{
public List<OpenTelemetryEventSourceLogEmitter> Emitters { get; } = new();
public void Dispose()
{
foreach (var emitter in this.Emitters)
{
emitter.Dispose();
}
this.Emitters.Clear();
}
}
}
}

View File

@ -1,61 +0,0 @@
# OpenTelemetry.Extensions.EventSource
[![NuGet](https://img.shields.io/nuget/v/OpenTelemetry.Extensions.EventSource.svg)](https://www.nuget.org/packages/OpenTelemetry.Extensions.EventSource)
[![NuGet](https://img.shields.io/nuget/dt/OpenTelemetry.Extensions.EventSource.svg)](https://www.nuget.org/packages/OpenTelemetry.Extensions.EventSource)
This project contains an
[EventListener](https://docs.microsoft.com/dotnet/api/system.diagnostics.tracing.eventlistener)
which can be used to translate events written to an
[EventSource](https://docs.microsoft.com/dotnet/api/system.diagnostics.tracing.eventsource)
into OpenTelemetry logs.
## Installation
```shell
dotnet add package OpenTelemetry.Extensions.EventSource --prerelease
```
## Usage Example
### Configured using dependency injection
```csharp
IHost host = Host.CreateDefaultBuilder(args)
.ConfigureLogging(builder =>
{
builder.ClearProviders();
// Step 1: Configure OpenTelemetry logging...
builder.AddOpenTelemetry(options =>
{
options
.ConfigureResource(builder => builder.AddService("MyService"))
.AddConsoleExporter()
// Step 2: Register OpenTelemetryEventSourceLogEmitter to listen to events...
.AddEventSourceLogEmitter((name) => name == MyEventSource.Name ? EventLevel.Informational : null);
});
})
.Build();
host.Run();
```
### Configured manually
```csharp
// Step 1: Configure OpenTelemetryLoggerProvider...
var openTelemetryLoggerProvider = Sdk.CreateLoggerProviderBuilder()
.ConfigureResource(builder => builder.AddService("MyService"))
.AddConsoleExporter()
.Build();
// Step 2: Create OpenTelemetryEventSourceLogEmitter to listen to events...
using var openTelemetryEventSourceLogEmitter = new OpenTelemetryEventSourceLogEmitter(
openTelemetryLoggerProvider,
(name) => name == MyEventSource.Name ? EventLevel.Informational : null,
disposeProvider: true);
```
## References
* [OpenTelemetry Project](https://opentelemetry.io/)

View File

@ -1,3 +0,0 @@
#nullable enable
Serilog.OpenTelemetrySerilogExtensions
static Serilog.OpenTelemetrySerilogExtensions.OpenTelemetry(this Serilog.Configuration.LoggerSinkConfiguration! loggerConfiguration, OpenTelemetry.Logs.OpenTelemetryLoggerProvider! openTelemetryLoggerProvider, bool disposeProvider = true) -> Serilog.LoggerConfiguration!

View File

@ -1,35 +0,0 @@
// <copyright file="AssemblyInfo.cs" company="OpenTelemetry Authors">
// 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.
// </copyright>
using System;
using System.Runtime.CompilerServices;
[assembly: CLSCompliant(false)]
[assembly: InternalsVisibleTo("DynamicProxyGenAssembly2" + AssemblyInfo.MoqPublicKey)]
#if SIGNED
internal static class AssemblyInfo
{
public const string PublicKey = ", PublicKey=002400000480000094000000060200000024000052534131000400000100010051C1562A090FB0C9F391012A32198B5E5D9A60E9B80FA2D7B434C9E5CCB7259BD606E66F9660676AFC6692B8CDC6793D190904551D2103B7B22FA636DCBB8208839785BA402EA08FC00C8F1500CCEF28BBF599AA64FFB1E1D5DC1BF3420A3777BADFE697856E9D52070A50C3EA5821C80BEF17CA3ACFFA28F89DD413F096F898";
public const string MoqPublicKey = ", PublicKey=0024000004800000940000000602000000240000525341310004000001000100c547cac37abd99c8db225ef2f6c8a3602f3b3606cc9891605d02baa56104f4cfc0734aa39b93bf7852f7d9266654753cc297e7d2edfe0bac1cdcf9f717241550e0a7b191195b7667bb4f64bcb8e2121380fd1d9d46ad2d92d2d15605093924cceaf74c4861eff62abf69b9291ed0a340e113be11e6a7d3113e92484cf7045cc7";
}
#else
internal static class AssemblyInfo
{
public const string PublicKey = "";
public const string MoqPublicKey = "";
}
#endif

View File

@ -1,5 +0,0 @@
# Changelog
## Unreleased
Initial release.

View File

@ -1,24 +0,0 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<!-- OmniSharp/VS Code requires TargetFrameworks to be in descending order for IntelliSense and analysis. -->
<TargetFrameworks>netstandard2.0</TargetFrameworks>
<Description>Extensions to enable OpenTelemetry logging when using the Serilog library</Description>
<PackageTags>$(PackageTags);serilog;logging</PackageTags>
<Nullable>enable</Nullable>
<AnalysisMode>AllEnabledByDefault</AnalysisMode>
<AnalysisLevel>latest</AnalysisLevel>
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="$(RepoRoot)\src\OpenTelemetry\OpenTelemetry.csproj" />
</ItemGroup>
<ItemGroup>
<Compile Include="$(RepoRoot)\src\OpenTelemetry.Api\Internal\Guard.cs" Link="Includes\Guard.cs" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="Serilog" Version="$(SerilogPkgVer)" />
</ItemGroup>
</Project>

View File

@ -1,54 +0,0 @@
// <copyright file="OpenTelemetrySerilogExtensions.cs" company="OpenTelemetry Authors">
// 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.
// </copyright>
using OpenTelemetry.Internal;
using OpenTelemetry.Logs;
using Serilog.Configuration;
namespace Serilog
{
/// <summary>
/// Contains Serilog extension methods.
/// </summary>
public static class OpenTelemetrySerilogExtensions
{
/// <summary>
/// Adds a sink to Serilog <see cref="LoggerConfiguration"/> which will
/// write to OpenTelemetry.
/// </summary>
/// <param name="loggerConfiguration"><see
/// cref="LoggerSinkConfiguration"/>.</param>
/// <param name="openTelemetryLoggerProvider"><see
/// cref="OpenTelemetryLoggerProvider"/>.</param>
/// <param name="disposeProvider">Controls whether or not the supplied
/// <paramref name="openTelemetryLoggerProvider"/> will be disposed when
/// the logger is disposed. Default value: <see
/// langword="true"/>.</param>
/// <returns>Supplied <see cref="LoggerConfiguration"/> for chaining calls.</returns>
public static LoggerConfiguration OpenTelemetry(
this LoggerSinkConfiguration loggerConfiguration,
OpenTelemetryLoggerProvider openTelemetryLoggerProvider,
bool disposeProvider = true)
{
Guard.ThrowIfNull(loggerConfiguration);
Guard.ThrowIfNull(openTelemetryLoggerProvider);
#pragma warning disable CA2000 // Dispose objects before losing scope
return loggerConfiguration.Sink(new OpenTelemetrySerilogSink(openTelemetryLoggerProvider, disposeProvider));
#pragma warning restore CA2000 // Dispose objects before losing scope
}
}
}

View File

@ -1,135 +0,0 @@
// <copyright file="OpenTelemetrySerilogSink.cs" company="OpenTelemetry Authors">
// 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.
// </copyright>
using System;
using System.Collections.Generic;
using System.Diagnostics;
using Microsoft.Extensions.Logging;
using Serilog.Core;
using Serilog.Events;
namespace OpenTelemetry.Logs
{
internal sealed class OpenTelemetrySerilogSink : ILogEventSink, IDisposable
{
private readonly OpenTelemetryLoggerProvider openTelemetryLoggerProvider;
private readonly bool includeFormattedMessage;
private readonly LogEmitter logEmitter;
private readonly bool disposeProvider;
public OpenTelemetrySerilogSink(OpenTelemetryLoggerProvider openTelemetryLoggerProvider, bool disposeProvider)
{
Debug.Assert(openTelemetryLoggerProvider != null, "openTelemetryLoggerProvider was null");
this.openTelemetryLoggerProvider = openTelemetryLoggerProvider!;
this.disposeProvider = disposeProvider;
var logEmitter = this.openTelemetryLoggerProvider.CreateEmitter();
Debug.Assert(logEmitter != null, "logEmitter was null");
this.logEmitter = logEmitter!;
// TODO: This project can only access IncludeFormattedMessage
// because it can see SDK internals. At some point this is likely
// not to be the case. Need to figure out where to put
// IncludeFormattedMessage so that extensions can see it. Ideas:
// Make it public on OpenTelemetryLoggerProvider or expose it on
// LogEmitter instance.
this.includeFormattedMessage = this.openTelemetryLoggerProvider.IncludeFormattedMessage;
}
public void Emit(LogEvent logEvent)
{
Debug.Assert(logEvent != null, "LogEvent was null.");
LogRecordData data = new(Activity.Current)
{
Timestamp = logEvent!.Timestamp.UtcDateTime,
LogLevel = (LogLevel)(int)logEvent.Level,
Message = this.includeFormattedMessage ? logEvent.RenderMessage() : logEvent.MessageTemplate.Text,
Exception = logEvent.Exception,
};
LogRecordAttributeList attributes = default;
foreach (KeyValuePair<string, LogEventPropertyValue> property in logEvent.Properties)
{
// TODO: Serilog supports complex type logging. This is not yet
// supported in OpenTelemetry.
if (property.Key == Constants.SourceContextPropertyName
&& property.Value is ScalarValue sourceContextValue)
{
data.CategoryName = sourceContextValue.Value as string;
}
else if (property.Value is ScalarValue scalarValue)
{
attributes.Add(property.Key, scalarValue.Value);
}
else if (property.Value is SequenceValue sequenceValue)
{
IReadOnlyList<LogEventPropertyValue> elements = sequenceValue.Elements;
if (elements.Count > 0)
{
// Note: The goal here is to build a typed array (eg
// int[]) if all the element types match otherwise
// fallback to object[]
Type? elementType = null;
Array? values = null;
for (int i = 0; i < elements.Count; i++)
{
if (elements[i] is ScalarValue value)
{
Type currentElementType = value.Value?.GetType() ?? typeof(object);
if (values == null)
{
elementType = currentElementType;
values = Array.CreateInstance(elementType, elements.Count);
}
else if (!elementType!.IsAssignableFrom(currentElementType))
{
// Array with mixed types detected
object[] newValues = new object[elements.Count];
values.CopyTo(newValues, 0);
values = newValues;
elementType = typeof(object);
}
values.SetValue(value.Value, i);
}
}
if (values != null)
{
attributes.Add(property.Key, values);
}
}
}
}
this.logEmitter.Emit(in data, in attributes);
}
public void Dispose()
{
if (this.disposeProvider)
{
this.openTelemetryLoggerProvider.Dispose();
}
}
}
}

View File

@ -1,36 +0,0 @@
# OpenTelemetry.Extensions.Serilog
[![NuGet](https://img.shields.io/nuget/v/OpenTelemetry.Extensions.Serilog.svg)](https://www.nuget.org/packages/OpenTelemetry.Extensions.Serilog)
[![NuGet](https://img.shields.io/nuget/dt/OpenTelemetry.Extensions.Serilog.svg)](https://www.nuget.org/packages/OpenTelemetry.Extensions.Serilog)
This project contains a [Serilog](https://github.com/serilog/)
[sink](https://github.com/serilog/serilog/wiki/Configuration-Basics#sinks) for
writing log messages to OpenTelemetry.
## Installation
```shell
dotnet add package OpenTelemetry.Extensions.Serilog --prerelease
```
## Usage Example
```csharp
// Step 1: Configure OpenTelemetryLoggerProvider...
var openTelemetryLoggerProvider = Sdk.CreateLoggerProviderBuilder()
.ConfigureResource(builder => builder.AddService("MyService"))
.AddConsoleExporter()
.Build();
// Step 2: Register OpenTelemetry sink with Serilog...
Log.Logger = new LoggerConfiguration()
.WriteTo.OpenTelemetry(openTelemetryLoggerProvider, disposeProvider: true)
.CreateLogger();
// Step 3: When application is shutdown flush all log messages and dispose provider...
Log.CloseAndFlush();
```
## References
* [OpenTelemetry Project](https://opentelemetry.io/)

View File

@ -1,13 +1,5 @@
Microsoft.Extensions.DependencyInjection.MeterProviderBuilderServiceCollectionExtensions
Microsoft.Extensions.DependencyInjection.TracerProviderBuilderServiceCollectionExtensions
OpenTelemetry.Logs.BatchExportLogRecordProcessorOptions
OpenTelemetry.Logs.BatchExportLogRecordProcessorOptions.BatchExportLogRecordProcessorOptions() -> void
OpenTelemetry.Logs.ExportLogRecordProcessorOptions
OpenTelemetry.Logs.ExportLogRecordProcessorOptions.BatchExportProcessorOptions.get -> OpenTelemetry.Logs.BatchExportLogRecordProcessorOptions!
OpenTelemetry.Logs.ExportLogRecordProcessorOptions.BatchExportProcessorOptions.set -> void
OpenTelemetry.Logs.ExportLogRecordProcessorOptions.ExportLogRecordProcessorOptions() -> void
OpenTelemetry.Logs.ExportLogRecordProcessorOptions.ExportProcessorType.get -> OpenTelemetry.ExportProcessorType
OpenTelemetry.Logs.ExportLogRecordProcessorOptions.ExportProcessorType.set -> void
OpenTelemetry.Logs.LogRecord.CategoryName.set -> void
OpenTelemetry.Logs.LogRecord.EventId.set -> void
OpenTelemetry.Logs.LogRecord.Exception.set -> void
@ -17,23 +9,7 @@ OpenTelemetry.Logs.LogRecord.Timestamp.set -> void
OpenTelemetry.Logs.LogRecord.TraceFlags.set -> void
OpenTelemetry.Logs.LogRecord.TraceId.set -> void
OpenTelemetry.Logs.LogRecord.TraceState.set -> void
OpenTelemetry.Logs.OpenTelemetryLoggerOptions.AddExporter(OpenTelemetry.ExportProcessorType exportProcessorType, OpenTelemetry.BaseExporter<OpenTelemetry.Logs.LogRecord!>! exporter) -> OpenTelemetry.Logs.OpenTelemetryLoggerOptions!
OpenTelemetry.Logs.OpenTelemetryLoggerOptions.AddExporter(OpenTelemetry.ExportProcessorType exportProcessorType, OpenTelemetry.BaseExporter<OpenTelemetry.Logs.LogRecord!>! exporter, string? name, System.Action<OpenTelemetry.Logs.ExportLogRecordProcessorOptions!>? configure) -> OpenTelemetry.Logs.OpenTelemetryLoggerOptions!
OpenTelemetry.Logs.OpenTelemetryLoggerOptions.AddExporter(OpenTelemetry.ExportProcessorType exportProcessorType, OpenTelemetry.BaseExporter<OpenTelemetry.Logs.LogRecord!>! exporter, System.Action<OpenTelemetry.Logs.ExportLogRecordProcessorOptions!>! configure) -> OpenTelemetry.Logs.OpenTelemetryLoggerOptions!
OpenTelemetry.Logs.OpenTelemetryLoggerOptions.AddExporter<T>(OpenTelemetry.ExportProcessorType exportProcessorType) -> OpenTelemetry.Logs.OpenTelemetryLoggerOptions!
OpenTelemetry.Logs.OpenTelemetryLoggerOptions.AddExporter<T>(OpenTelemetry.ExportProcessorType exportProcessorType, string? name, System.Action<OpenTelemetry.Logs.ExportLogRecordProcessorOptions!>? configure) -> OpenTelemetry.Logs.OpenTelemetryLoggerOptions!
OpenTelemetry.Logs.OpenTelemetryLoggerOptions.AddExporter<T>(OpenTelemetry.ExportProcessorType exportProcessorType, System.Action<OpenTelemetry.Logs.ExportLogRecordProcessorOptions!>! configure) -> OpenTelemetry.Logs.OpenTelemetryLoggerOptions!
OpenTelemetry.Logs.OpenTelemetryLoggerOptions.AddProcessor<T>() -> OpenTelemetry.Logs.OpenTelemetryLoggerOptions!
OpenTelemetry.Logs.OpenTelemetryLoggerOptions.ConfigureProvider(System.Action<System.IServiceProvider!, OpenTelemetry.Logs.OpenTelemetryLoggerProvider!>! configure) -> OpenTelemetry.Logs.OpenTelemetryLoggerOptions!
OpenTelemetry.Logs.OpenTelemetryLoggerOptions.ConfigureResource(System.Action<OpenTelemetry.Resources.ResourceBuilder!>! configure) -> OpenTelemetry.Logs.OpenTelemetryLoggerOptions!
OpenTelemetry.Logs.OpenTelemetryLoggerOptions.ConfigureServices(System.Action<Microsoft.Extensions.DependencyInjection.IServiceCollection!>! configure) -> OpenTelemetry.Logs.OpenTelemetryLoggerOptions!
OpenTelemetry.Logs.OpenTelemetryLoggerOptions.SetIncludeFormattedMessage(bool enabled) -> OpenTelemetry.Logs.OpenTelemetryLoggerOptions!
OpenTelemetry.Logs.OpenTelemetryLoggerOptions.SetIncludeScopes(bool enabled) -> OpenTelemetry.Logs.OpenTelemetryLoggerOptions!
OpenTelemetry.Logs.OpenTelemetryLoggerOptions.SetParseStateValues(bool enabled) -> OpenTelemetry.Logs.OpenTelemetryLoggerOptions!
OpenTelemetry.Logs.OpenTelemetryLoggerOptionsExtensions
OpenTelemetry.Logs.OpenTelemetryLoggerProvider.AddProcessor(OpenTelemetry.BaseProcessor<OpenTelemetry.Logs.LogRecord!>! processor) -> OpenTelemetry.Logs.OpenTelemetryLoggerProvider!
OpenTelemetry.Logs.OpenTelemetryLoggerProvider.ForceFlush(int timeoutMilliseconds = -1) -> bool
OpenTelemetry.Logs.OpenTelemetryLoggerProvider.OpenTelemetryLoggerProvider() -> void
static Microsoft.Extensions.DependencyInjection.MeterProviderBuilderServiceCollectionExtensions.ConfigureOpenTelemetryMetrics(this Microsoft.Extensions.DependencyInjection.IServiceCollection! services) -> Microsoft.Extensions.DependencyInjection.IServiceCollection!
static Microsoft.Extensions.DependencyInjection.MeterProviderBuilderServiceCollectionExtensions.ConfigureOpenTelemetryMetrics(this Microsoft.Extensions.DependencyInjection.IServiceCollection! services, System.Action<OpenTelemetry.Metrics.MeterProviderBuilder!>! configure) -> Microsoft.Extensions.DependencyInjection.IServiceCollection!
static OpenTelemetry.Metrics.MeterProviderBuilderExtensions.AddInstrumentation<T>(this OpenTelemetry.Metrics.MeterProviderBuilder! meterProviderBuilder) -> OpenTelemetry.Metrics.MeterProviderBuilder!
@ -53,8 +29,6 @@ OpenTelemetry.Trace.ExportActivityProcessorOptions.ExportActivityProcessorOption
OpenTelemetry.Trace.ExportActivityProcessorOptions.ExportProcessorType.get -> OpenTelemetry.ExportProcessorType
OpenTelemetry.Trace.ExportActivityProcessorOptions.ExportProcessorType.set -> void
static Microsoft.Extensions.Logging.OpenTelemetryLoggingExtensions.AddOpenTelemetry(this Microsoft.Extensions.Logging.ILoggingBuilder! builder) -> Microsoft.Extensions.Logging.ILoggingBuilder!
static Microsoft.Extensions.Logging.OpenTelemetryLoggingExtensions.AddOpenTelemetry(this Microsoft.Extensions.Logging.ILoggingBuilder! builder, OpenTelemetry.Logs.OpenTelemetryLoggerProvider! openTelemetryLoggerProvider) -> Microsoft.Extensions.Logging.ILoggingBuilder!
static Microsoft.Extensions.Logging.OpenTelemetryLoggingExtensions.AddOpenTelemetry(this Microsoft.Extensions.Logging.ILoggingBuilder! builder, OpenTelemetry.Logs.OpenTelemetryLoggerProvider! openTelemetryLoggerProvider, bool disposeProvider) -> Microsoft.Extensions.Logging.ILoggingBuilder!
static Microsoft.Extensions.Logging.OpenTelemetryLoggingExtensions.AddOpenTelemetry(this Microsoft.Extensions.Logging.ILoggingBuilder! builder, System.Action<OpenTelemetry.Logs.OpenTelemetryLoggerOptions!>? configure) -> Microsoft.Extensions.Logging.ILoggingBuilder!
static OpenTelemetry.Trace.TracerProviderBuilderExtensions.AddExporter(this OpenTelemetry.Trace.TracerProviderBuilder! tracerProviderBuilder, OpenTelemetry.ExportProcessorType exportProcessorType, OpenTelemetry.BaseExporter<System.Diagnostics.Activity!>! exporter) -> OpenTelemetry.Trace.TracerProviderBuilder!
static OpenTelemetry.Trace.TracerProviderBuilderExtensions.AddExporter(this OpenTelemetry.Trace.TracerProviderBuilder! tracerProviderBuilder, OpenTelemetry.ExportProcessorType exportProcessorType, OpenTelemetry.BaseExporter<System.Diagnostics.Activity!>! exporter, System.Action<OpenTelemetry.Trace.ExportActivityProcessorOptions!>! configure) -> OpenTelemetry.Trace.TracerProviderBuilder!
@ -65,8 +39,6 @@ static OpenTelemetry.Trace.TracerProviderBuilderExtensions.AddProcessor<T>(this
static OpenTelemetry.Trace.TracerProviderBuilderExtensions.ConfigureBuilder(this OpenTelemetry.Trace.TracerProviderBuilder! tracerProviderBuilder, System.Action<System.IServiceProvider!, OpenTelemetry.Trace.TracerProviderBuilder!>! configure) -> OpenTelemetry.Trace.TracerProviderBuilder!
static OpenTelemetry.Trace.TracerProviderBuilderExtensions.ConfigureServices(this OpenTelemetry.Trace.TracerProviderBuilder! tracerProviderBuilder, System.Action<Microsoft.Extensions.DependencyInjection.IServiceCollection!>! configure) -> OpenTelemetry.Trace.TracerProviderBuilder!
static OpenTelemetry.Trace.TracerProviderBuilderExtensions.SetSampler<T>(this OpenTelemetry.Trace.TracerProviderBuilder! tracerProviderBuilder) -> OpenTelemetry.Trace.TracerProviderBuilder!
static OpenTelemetry.Logs.OpenTelemetryLoggerOptionsExtensions.Build(this OpenTelemetry.Logs.OpenTelemetryLoggerOptions! options) -> OpenTelemetry.Logs.OpenTelemetryLoggerProvider!
static OpenTelemetry.Sdk.CreateLoggerProviderBuilder() -> OpenTelemetry.Logs.OpenTelemetryLoggerOptions!
static Microsoft.Extensions.DependencyInjection.TracerProviderBuilderServiceCollectionExtensions.ConfigureOpenTelemetryTracing(this Microsoft.Extensions.DependencyInjection.IServiceCollection! services) -> Microsoft.Extensions.DependencyInjection.IServiceCollection!
static Microsoft.Extensions.DependencyInjection.TracerProviderBuilderServiceCollectionExtensions.ConfigureOpenTelemetryTracing(this Microsoft.Extensions.DependencyInjection.IServiceCollection! services, System.Action<OpenTelemetry.Trace.TracerProviderBuilder!>! configure) -> Microsoft.Extensions.DependencyInjection.IServiceCollection!
static OpenTelemetry.Metrics.MeterProviderBuilderExtensions.ConfigureResource(this OpenTelemetry.Metrics.MeterProviderBuilder! meterProviderBuilder, System.Action<OpenTelemetry.Resources.ResourceBuilder!>! configure) -> OpenTelemetry.Metrics.MeterProviderBuilder!

View File

@ -1,13 +1,5 @@
Microsoft.Extensions.DependencyInjection.MeterProviderBuilderServiceCollectionExtensions
Microsoft.Extensions.DependencyInjection.TracerProviderBuilderServiceCollectionExtensions
OpenTelemetry.Logs.BatchExportLogRecordProcessorOptions
OpenTelemetry.Logs.BatchExportLogRecordProcessorOptions.BatchExportLogRecordProcessorOptions() -> void
OpenTelemetry.Logs.ExportLogRecordProcessorOptions
OpenTelemetry.Logs.ExportLogRecordProcessorOptions.BatchExportProcessorOptions.get -> OpenTelemetry.Logs.BatchExportLogRecordProcessorOptions!
OpenTelemetry.Logs.ExportLogRecordProcessorOptions.BatchExportProcessorOptions.set -> void
OpenTelemetry.Logs.ExportLogRecordProcessorOptions.ExportLogRecordProcessorOptions() -> void
OpenTelemetry.Logs.ExportLogRecordProcessorOptions.ExportProcessorType.get -> OpenTelemetry.ExportProcessorType
OpenTelemetry.Logs.ExportLogRecordProcessorOptions.ExportProcessorType.set -> void
OpenTelemetry.Logs.LogRecord.CategoryName.set -> void
OpenTelemetry.Logs.LogRecord.EventId.set -> void
OpenTelemetry.Logs.LogRecord.Exception.set -> void
@ -17,23 +9,7 @@ OpenTelemetry.Logs.LogRecord.Timestamp.set -> void
OpenTelemetry.Logs.LogRecord.TraceFlags.set -> void
OpenTelemetry.Logs.LogRecord.TraceId.set -> void
OpenTelemetry.Logs.LogRecord.TraceState.set -> void
OpenTelemetry.Logs.OpenTelemetryLoggerOptions.AddExporter(OpenTelemetry.ExportProcessorType exportProcessorType, OpenTelemetry.BaseExporter<OpenTelemetry.Logs.LogRecord!>! exporter) -> OpenTelemetry.Logs.OpenTelemetryLoggerOptions!
OpenTelemetry.Logs.OpenTelemetryLoggerOptions.AddExporter(OpenTelemetry.ExportProcessorType exportProcessorType, OpenTelemetry.BaseExporter<OpenTelemetry.Logs.LogRecord!>! exporter, string? name, System.Action<OpenTelemetry.Logs.ExportLogRecordProcessorOptions!>? configure) -> OpenTelemetry.Logs.OpenTelemetryLoggerOptions!
OpenTelemetry.Logs.OpenTelemetryLoggerOptions.AddExporter(OpenTelemetry.ExportProcessorType exportProcessorType, OpenTelemetry.BaseExporter<OpenTelemetry.Logs.LogRecord!>! exporter, System.Action<OpenTelemetry.Logs.ExportLogRecordProcessorOptions!>! configure) -> OpenTelemetry.Logs.OpenTelemetryLoggerOptions!
OpenTelemetry.Logs.OpenTelemetryLoggerOptions.AddExporter<T>(OpenTelemetry.ExportProcessorType exportProcessorType) -> OpenTelemetry.Logs.OpenTelemetryLoggerOptions!
OpenTelemetry.Logs.OpenTelemetryLoggerOptions.AddExporter<T>(OpenTelemetry.ExportProcessorType exportProcessorType, string? name, System.Action<OpenTelemetry.Logs.ExportLogRecordProcessorOptions!>? configure) -> OpenTelemetry.Logs.OpenTelemetryLoggerOptions!
OpenTelemetry.Logs.OpenTelemetryLoggerOptions.AddExporter<T>(OpenTelemetry.ExportProcessorType exportProcessorType, System.Action<OpenTelemetry.Logs.ExportLogRecordProcessorOptions!>! configure) -> OpenTelemetry.Logs.OpenTelemetryLoggerOptions!
OpenTelemetry.Logs.OpenTelemetryLoggerOptions.AddProcessor<T>() -> OpenTelemetry.Logs.OpenTelemetryLoggerOptions!
OpenTelemetry.Logs.OpenTelemetryLoggerOptions.ConfigureProvider(System.Action<System.IServiceProvider!, OpenTelemetry.Logs.OpenTelemetryLoggerProvider!>! configure) -> OpenTelemetry.Logs.OpenTelemetryLoggerOptions!
OpenTelemetry.Logs.OpenTelemetryLoggerOptions.ConfigureResource(System.Action<OpenTelemetry.Resources.ResourceBuilder!>! configure) -> OpenTelemetry.Logs.OpenTelemetryLoggerOptions!
OpenTelemetry.Logs.OpenTelemetryLoggerOptions.ConfigureServices(System.Action<Microsoft.Extensions.DependencyInjection.IServiceCollection!>! configure) -> OpenTelemetry.Logs.OpenTelemetryLoggerOptions!
OpenTelemetry.Logs.OpenTelemetryLoggerOptions.SetIncludeFormattedMessage(bool enabled) -> OpenTelemetry.Logs.OpenTelemetryLoggerOptions!
OpenTelemetry.Logs.OpenTelemetryLoggerOptions.SetIncludeScopes(bool enabled) -> OpenTelemetry.Logs.OpenTelemetryLoggerOptions!
OpenTelemetry.Logs.OpenTelemetryLoggerOptions.SetParseStateValues(bool enabled) -> OpenTelemetry.Logs.OpenTelemetryLoggerOptions!
OpenTelemetry.Logs.OpenTelemetryLoggerOptionsExtensions
OpenTelemetry.Logs.OpenTelemetryLoggerProvider.AddProcessor(OpenTelemetry.BaseProcessor<OpenTelemetry.Logs.LogRecord!>! processor) -> OpenTelemetry.Logs.OpenTelemetryLoggerProvider!
OpenTelemetry.Logs.OpenTelemetryLoggerProvider.ForceFlush(int timeoutMilliseconds = -1) -> bool
OpenTelemetry.Logs.OpenTelemetryLoggerProvider.OpenTelemetryLoggerProvider() -> void
static Microsoft.Extensions.DependencyInjection.MeterProviderBuilderServiceCollectionExtensions.ConfigureOpenTelemetryMetrics(this Microsoft.Extensions.DependencyInjection.IServiceCollection! services) -> Microsoft.Extensions.DependencyInjection.IServiceCollection!
static Microsoft.Extensions.DependencyInjection.MeterProviderBuilderServiceCollectionExtensions.ConfigureOpenTelemetryMetrics(this Microsoft.Extensions.DependencyInjection.IServiceCollection! services, System.Action<OpenTelemetry.Metrics.MeterProviderBuilder!>! configure) -> Microsoft.Extensions.DependencyInjection.IServiceCollection!
static OpenTelemetry.Metrics.MeterProviderBuilderExtensions.AddInstrumentation<T>(this OpenTelemetry.Metrics.MeterProviderBuilder! meterProviderBuilder) -> OpenTelemetry.Metrics.MeterProviderBuilder!
@ -53,8 +29,6 @@ OpenTelemetry.Trace.ExportActivityProcessorOptions.ExportActivityProcessorOption
OpenTelemetry.Trace.ExportActivityProcessorOptions.ExportProcessorType.get -> OpenTelemetry.ExportProcessorType
OpenTelemetry.Trace.ExportActivityProcessorOptions.ExportProcessorType.set -> void
static Microsoft.Extensions.Logging.OpenTelemetryLoggingExtensions.AddOpenTelemetry(this Microsoft.Extensions.Logging.ILoggingBuilder! builder) -> Microsoft.Extensions.Logging.ILoggingBuilder!
static Microsoft.Extensions.Logging.OpenTelemetryLoggingExtensions.AddOpenTelemetry(this Microsoft.Extensions.Logging.ILoggingBuilder! builder, OpenTelemetry.Logs.OpenTelemetryLoggerProvider! openTelemetryLoggerProvider) -> Microsoft.Extensions.Logging.ILoggingBuilder!
static Microsoft.Extensions.Logging.OpenTelemetryLoggingExtensions.AddOpenTelemetry(this Microsoft.Extensions.Logging.ILoggingBuilder! builder, OpenTelemetry.Logs.OpenTelemetryLoggerProvider! openTelemetryLoggerProvider, bool disposeProvider) -> Microsoft.Extensions.Logging.ILoggingBuilder!
static Microsoft.Extensions.Logging.OpenTelemetryLoggingExtensions.AddOpenTelemetry(this Microsoft.Extensions.Logging.ILoggingBuilder! builder, System.Action<OpenTelemetry.Logs.OpenTelemetryLoggerOptions!>? configure) -> Microsoft.Extensions.Logging.ILoggingBuilder!
static OpenTelemetry.Trace.TracerProviderBuilderExtensions.AddExporter(this OpenTelemetry.Trace.TracerProviderBuilder! tracerProviderBuilder, OpenTelemetry.ExportProcessorType exportProcessorType, OpenTelemetry.BaseExporter<System.Diagnostics.Activity!>! exporter) -> OpenTelemetry.Trace.TracerProviderBuilder!
static OpenTelemetry.Trace.TracerProviderBuilderExtensions.AddExporter(this OpenTelemetry.Trace.TracerProviderBuilder! tracerProviderBuilder, OpenTelemetry.ExportProcessorType exportProcessorType, OpenTelemetry.BaseExporter<System.Diagnostics.Activity!>! exporter, System.Action<OpenTelemetry.Trace.ExportActivityProcessorOptions!>! configure) -> OpenTelemetry.Trace.TracerProviderBuilder!
@ -65,8 +39,6 @@ static OpenTelemetry.Trace.TracerProviderBuilderExtensions.AddProcessor<T>(this
static OpenTelemetry.Trace.TracerProviderBuilderExtensions.ConfigureBuilder(this OpenTelemetry.Trace.TracerProviderBuilder! tracerProviderBuilder, System.Action<System.IServiceProvider!, OpenTelemetry.Trace.TracerProviderBuilder!>! configure) -> OpenTelemetry.Trace.TracerProviderBuilder!
static OpenTelemetry.Trace.TracerProviderBuilderExtensions.ConfigureServices(this OpenTelemetry.Trace.TracerProviderBuilder! tracerProviderBuilder, System.Action<Microsoft.Extensions.DependencyInjection.IServiceCollection!>! configure) -> OpenTelemetry.Trace.TracerProviderBuilder!
static OpenTelemetry.Trace.TracerProviderBuilderExtensions.SetSampler<T>(this OpenTelemetry.Trace.TracerProviderBuilder! tracerProviderBuilder) -> OpenTelemetry.Trace.TracerProviderBuilder!
static OpenTelemetry.Logs.OpenTelemetryLoggerOptionsExtensions.Build(this OpenTelemetry.Logs.OpenTelemetryLoggerOptions! options) -> OpenTelemetry.Logs.OpenTelemetryLoggerProvider!
static OpenTelemetry.Sdk.CreateLoggerProviderBuilder() -> OpenTelemetry.Logs.OpenTelemetryLoggerOptions!
static Microsoft.Extensions.DependencyInjection.TracerProviderBuilderServiceCollectionExtensions.ConfigureOpenTelemetryTracing(this Microsoft.Extensions.DependencyInjection.IServiceCollection! services) -> Microsoft.Extensions.DependencyInjection.IServiceCollection!
static Microsoft.Extensions.DependencyInjection.TracerProviderBuilderServiceCollectionExtensions.ConfigureOpenTelemetryTracing(this Microsoft.Extensions.DependencyInjection.IServiceCollection! services, System.Action<OpenTelemetry.Trace.TracerProviderBuilder!>! configure) -> Microsoft.Extensions.DependencyInjection.IServiceCollection!
static OpenTelemetry.Metrics.MeterProviderBuilderExtensions.ConfigureResource(this OpenTelemetry.Metrics.MeterProviderBuilder! meterProviderBuilder, System.Action<OpenTelemetry.Resources.ResourceBuilder!>! configure) -> OpenTelemetry.Metrics.MeterProviderBuilder!

View File

@ -1,13 +1,5 @@
Microsoft.Extensions.DependencyInjection.MeterProviderBuilderServiceCollectionExtensions
Microsoft.Extensions.DependencyInjection.TracerProviderBuilderServiceCollectionExtensions
OpenTelemetry.Logs.BatchExportLogRecordProcessorOptions
OpenTelemetry.Logs.BatchExportLogRecordProcessorOptions.BatchExportLogRecordProcessorOptions() -> void
OpenTelemetry.Logs.ExportLogRecordProcessorOptions
OpenTelemetry.Logs.ExportLogRecordProcessorOptions.BatchExportProcessorOptions.get -> OpenTelemetry.Logs.BatchExportLogRecordProcessorOptions!
OpenTelemetry.Logs.ExportLogRecordProcessorOptions.BatchExportProcessorOptions.set -> void
OpenTelemetry.Logs.ExportLogRecordProcessorOptions.ExportLogRecordProcessorOptions() -> void
OpenTelemetry.Logs.ExportLogRecordProcessorOptions.ExportProcessorType.get -> OpenTelemetry.ExportProcessorType
OpenTelemetry.Logs.ExportLogRecordProcessorOptions.ExportProcessorType.set -> void
OpenTelemetry.Logs.LogRecord.CategoryName.set -> void
OpenTelemetry.Logs.LogRecord.EventId.set -> void
OpenTelemetry.Logs.LogRecord.Exception.set -> void
@ -17,22 +9,6 @@ OpenTelemetry.Logs.LogRecord.Timestamp.set -> void
OpenTelemetry.Logs.LogRecord.TraceFlags.set -> void
OpenTelemetry.Logs.LogRecord.TraceId.set -> void
OpenTelemetry.Logs.LogRecord.TraceState.set -> void
OpenTelemetry.Logs.OpenTelemetryLoggerOptions.AddExporter(OpenTelemetry.ExportProcessorType exportProcessorType, OpenTelemetry.BaseExporter<OpenTelemetry.Logs.LogRecord!>! exporter) -> OpenTelemetry.Logs.OpenTelemetryLoggerOptions!
OpenTelemetry.Logs.OpenTelemetryLoggerOptions.AddExporter(OpenTelemetry.ExportProcessorType exportProcessorType, OpenTelemetry.BaseExporter<OpenTelemetry.Logs.LogRecord!>! exporter, string? name, System.Action<OpenTelemetry.Logs.ExportLogRecordProcessorOptions!>? configure) -> OpenTelemetry.Logs.OpenTelemetryLoggerOptions!
OpenTelemetry.Logs.OpenTelemetryLoggerOptions.AddExporter(OpenTelemetry.ExportProcessorType exportProcessorType, OpenTelemetry.BaseExporter<OpenTelemetry.Logs.LogRecord!>! exporter, System.Action<OpenTelemetry.Logs.ExportLogRecordProcessorOptions!>! configure) -> OpenTelemetry.Logs.OpenTelemetryLoggerOptions!
OpenTelemetry.Logs.OpenTelemetryLoggerOptions.AddExporter<T>(OpenTelemetry.ExportProcessorType exportProcessorType) -> OpenTelemetry.Logs.OpenTelemetryLoggerOptions!
OpenTelemetry.Logs.OpenTelemetryLoggerOptions.AddExporter<T>(OpenTelemetry.ExportProcessorType exportProcessorType, string? name, System.Action<OpenTelemetry.Logs.ExportLogRecordProcessorOptions!>? configure) -> OpenTelemetry.Logs.OpenTelemetryLoggerOptions!
OpenTelemetry.Logs.OpenTelemetryLoggerOptions.AddExporter<T>(OpenTelemetry.ExportProcessorType exportProcessorType, System.Action<OpenTelemetry.Logs.ExportLogRecordProcessorOptions!>! configure) -> OpenTelemetry.Logs.OpenTelemetryLoggerOptions!
OpenTelemetry.Logs.OpenTelemetryLoggerOptions.AddProcessor<T>() -> OpenTelemetry.Logs.OpenTelemetryLoggerOptions!
OpenTelemetry.Logs.OpenTelemetryLoggerOptions.ConfigureProvider(System.Action<System.IServiceProvider!, OpenTelemetry.Logs.OpenTelemetryLoggerProvider!>! configure) -> OpenTelemetry.Logs.OpenTelemetryLoggerOptions!
OpenTelemetry.Logs.OpenTelemetryLoggerOptions.ConfigureServices(System.Action<Microsoft.Extensions.DependencyInjection.IServiceCollection!>! configure) -> OpenTelemetry.Logs.OpenTelemetryLoggerOptions!
OpenTelemetry.Logs.OpenTelemetryLoggerOptions.SetIncludeFormattedMessage(bool enabled) -> OpenTelemetry.Logs.OpenTelemetryLoggerOptions!
OpenTelemetry.Logs.OpenTelemetryLoggerOptions.SetIncludeScopes(bool enabled) -> OpenTelemetry.Logs.OpenTelemetryLoggerOptions!
OpenTelemetry.Logs.OpenTelemetryLoggerOptions.SetParseStateValues(bool enabled) -> OpenTelemetry.Logs.OpenTelemetryLoggerOptions!
OpenTelemetry.Logs.OpenTelemetryLoggerOptionsExtensions
OpenTelemetry.Logs.OpenTelemetryLoggerProvider.AddProcessor(OpenTelemetry.BaseProcessor<OpenTelemetry.Logs.LogRecord!>! processor) -> OpenTelemetry.Logs.OpenTelemetryLoggerProvider!
OpenTelemetry.Logs.OpenTelemetryLoggerProvider.ForceFlush(int timeoutMilliseconds = -1) -> bool
OpenTelemetry.Logs.OpenTelemetryLoggerProvider.OpenTelemetryLoggerProvider() -> void
OpenTelemetry.Logs.OpenTelemetryLoggerOptions.ConfigureResource(System.Action<OpenTelemetry.Resources.ResourceBuilder!>! configure) -> OpenTelemetry.Logs.OpenTelemetryLoggerOptions!
static Microsoft.Extensions.DependencyInjection.MeterProviderBuilderServiceCollectionExtensions.ConfigureOpenTelemetryMetrics(this Microsoft.Extensions.DependencyInjection.IServiceCollection! services) -> Microsoft.Extensions.DependencyInjection.IServiceCollection!
static Microsoft.Extensions.DependencyInjection.MeterProviderBuilderServiceCollectionExtensions.ConfigureOpenTelemetryMetrics(this Microsoft.Extensions.DependencyInjection.IServiceCollection! services, System.Action<OpenTelemetry.Metrics.MeterProviderBuilder!>! configure) -> Microsoft.Extensions.DependencyInjection.IServiceCollection!
@ -53,8 +29,6 @@ OpenTelemetry.Trace.ExportActivityProcessorOptions.ExportActivityProcessorOption
OpenTelemetry.Trace.ExportActivityProcessorOptions.ExportProcessorType.get -> OpenTelemetry.ExportProcessorType
OpenTelemetry.Trace.ExportActivityProcessorOptions.ExportProcessorType.set -> void
static Microsoft.Extensions.Logging.OpenTelemetryLoggingExtensions.AddOpenTelemetry(this Microsoft.Extensions.Logging.ILoggingBuilder! builder) -> Microsoft.Extensions.Logging.ILoggingBuilder!
static Microsoft.Extensions.Logging.OpenTelemetryLoggingExtensions.AddOpenTelemetry(this Microsoft.Extensions.Logging.ILoggingBuilder! builder, OpenTelemetry.Logs.OpenTelemetryLoggerProvider! openTelemetryLoggerProvider) -> Microsoft.Extensions.Logging.ILoggingBuilder!
static Microsoft.Extensions.Logging.OpenTelemetryLoggingExtensions.AddOpenTelemetry(this Microsoft.Extensions.Logging.ILoggingBuilder! builder, OpenTelemetry.Logs.OpenTelemetryLoggerProvider! openTelemetryLoggerProvider, bool disposeProvider) -> Microsoft.Extensions.Logging.ILoggingBuilder!
static Microsoft.Extensions.Logging.OpenTelemetryLoggingExtensions.AddOpenTelemetry(this Microsoft.Extensions.Logging.ILoggingBuilder! builder, System.Action<OpenTelemetry.Logs.OpenTelemetryLoggerOptions!>? configure) -> Microsoft.Extensions.Logging.ILoggingBuilder!
static OpenTelemetry.Trace.TracerProviderBuilderExtensions.AddExporter(this OpenTelemetry.Trace.TracerProviderBuilder! tracerProviderBuilder, OpenTelemetry.ExportProcessorType exportProcessorType, OpenTelemetry.BaseExporter<System.Diagnostics.Activity!>! exporter) -> OpenTelemetry.Trace.TracerProviderBuilder!
static OpenTelemetry.Trace.TracerProviderBuilderExtensions.AddExporter(this OpenTelemetry.Trace.TracerProviderBuilder! tracerProviderBuilder, OpenTelemetry.ExportProcessorType exportProcessorType, OpenTelemetry.BaseExporter<System.Diagnostics.Activity!>! exporter, System.Action<OpenTelemetry.Trace.ExportActivityProcessorOptions!>! configure) -> OpenTelemetry.Trace.TracerProviderBuilder!
@ -65,8 +39,6 @@ static OpenTelemetry.Trace.TracerProviderBuilderExtensions.AddProcessor<T>(this
static OpenTelemetry.Trace.TracerProviderBuilderExtensions.ConfigureBuilder(this OpenTelemetry.Trace.TracerProviderBuilder! tracerProviderBuilder, System.Action<System.IServiceProvider!, OpenTelemetry.Trace.TracerProviderBuilder!>! configure) -> OpenTelemetry.Trace.TracerProviderBuilder!
static OpenTelemetry.Trace.TracerProviderBuilderExtensions.ConfigureServices(this OpenTelemetry.Trace.TracerProviderBuilder! tracerProviderBuilder, System.Action<Microsoft.Extensions.DependencyInjection.IServiceCollection!>! configure) -> OpenTelemetry.Trace.TracerProviderBuilder!
static OpenTelemetry.Trace.TracerProviderBuilderExtensions.SetSampler<T>(this OpenTelemetry.Trace.TracerProviderBuilder! tracerProviderBuilder) -> OpenTelemetry.Trace.TracerProviderBuilder!
static OpenTelemetry.Logs.OpenTelemetryLoggerOptionsExtensions.Build(this OpenTelemetry.Logs.OpenTelemetryLoggerOptions! options) -> OpenTelemetry.Logs.OpenTelemetryLoggerProvider!
static OpenTelemetry.Sdk.CreateLoggerProviderBuilder() -> OpenTelemetry.Logs.OpenTelemetryLoggerOptions!
static Microsoft.Extensions.DependencyInjection.TracerProviderBuilderServiceCollectionExtensions.ConfigureOpenTelemetryTracing(this Microsoft.Extensions.DependencyInjection.IServiceCollection! services) -> Microsoft.Extensions.DependencyInjection.IServiceCollection!
static Microsoft.Extensions.DependencyInjection.TracerProviderBuilderServiceCollectionExtensions.ConfigureOpenTelemetryTracing(this Microsoft.Extensions.DependencyInjection.IServiceCollection! services, System.Action<OpenTelemetry.Trace.TracerProviderBuilder!>! configure) -> Microsoft.Extensions.DependencyInjection.IServiceCollection!
static OpenTelemetry.Metrics.MeterProviderBuilderExtensions.ConfigureResource(this OpenTelemetry.Metrics.MeterProviderBuilder! meterProviderBuilder, System.Action<OpenTelemetry.Resources.ResourceBuilder!>! configure) -> OpenTelemetry.Metrics.MeterProviderBuilder!

View File

@ -1,13 +1,5 @@
Microsoft.Extensions.DependencyInjection.MeterProviderBuilderServiceCollectionExtensions
Microsoft.Extensions.DependencyInjection.TracerProviderBuilderServiceCollectionExtensions
OpenTelemetry.Logs.BatchExportLogRecordProcessorOptions
OpenTelemetry.Logs.BatchExportLogRecordProcessorOptions.BatchExportLogRecordProcessorOptions() -> void
OpenTelemetry.Logs.ExportLogRecordProcessorOptions
OpenTelemetry.Logs.ExportLogRecordProcessorOptions.BatchExportProcessorOptions.get -> OpenTelemetry.Logs.BatchExportLogRecordProcessorOptions!
OpenTelemetry.Logs.ExportLogRecordProcessorOptions.BatchExportProcessorOptions.set -> void
OpenTelemetry.Logs.ExportLogRecordProcessorOptions.ExportLogRecordProcessorOptions() -> void
OpenTelemetry.Logs.ExportLogRecordProcessorOptions.ExportProcessorType.get -> OpenTelemetry.ExportProcessorType
OpenTelemetry.Logs.ExportLogRecordProcessorOptions.ExportProcessorType.set -> void
OpenTelemetry.Logs.LogRecord.CategoryName.set -> void
OpenTelemetry.Logs.LogRecord.EventId.set -> void
OpenTelemetry.Logs.LogRecord.Exception.set -> void
@ -17,23 +9,7 @@ OpenTelemetry.Logs.LogRecord.Timestamp.set -> void
OpenTelemetry.Logs.LogRecord.TraceFlags.set -> void
OpenTelemetry.Logs.LogRecord.TraceId.set -> void
OpenTelemetry.Logs.LogRecord.TraceState.set -> void
OpenTelemetry.Logs.OpenTelemetryLoggerOptions.AddExporter(OpenTelemetry.ExportProcessorType exportProcessorType, OpenTelemetry.BaseExporter<OpenTelemetry.Logs.LogRecord!>! exporter) -> OpenTelemetry.Logs.OpenTelemetryLoggerOptions!
OpenTelemetry.Logs.OpenTelemetryLoggerOptions.AddExporter(OpenTelemetry.ExportProcessorType exportProcessorType, OpenTelemetry.BaseExporter<OpenTelemetry.Logs.LogRecord!>! exporter, string? name, System.Action<OpenTelemetry.Logs.ExportLogRecordProcessorOptions!>? configure) -> OpenTelemetry.Logs.OpenTelemetryLoggerOptions!
OpenTelemetry.Logs.OpenTelemetryLoggerOptions.AddExporter(OpenTelemetry.ExportProcessorType exportProcessorType, OpenTelemetry.BaseExporter<OpenTelemetry.Logs.LogRecord!>! exporter, System.Action<OpenTelemetry.Logs.ExportLogRecordProcessorOptions!>! configure) -> OpenTelemetry.Logs.OpenTelemetryLoggerOptions!
OpenTelemetry.Logs.OpenTelemetryLoggerOptions.AddExporter<T>(OpenTelemetry.ExportProcessorType exportProcessorType) -> OpenTelemetry.Logs.OpenTelemetryLoggerOptions!
OpenTelemetry.Logs.OpenTelemetryLoggerOptions.AddExporter<T>(OpenTelemetry.ExportProcessorType exportProcessorType, string? name, System.Action<OpenTelemetry.Logs.ExportLogRecordProcessorOptions!>? configure) -> OpenTelemetry.Logs.OpenTelemetryLoggerOptions!
OpenTelemetry.Logs.OpenTelemetryLoggerOptions.AddExporter<T>(OpenTelemetry.ExportProcessorType exportProcessorType, System.Action<OpenTelemetry.Logs.ExportLogRecordProcessorOptions!>! configure) -> OpenTelemetry.Logs.OpenTelemetryLoggerOptions!
OpenTelemetry.Logs.OpenTelemetryLoggerOptions.AddProcessor<T>() -> OpenTelemetry.Logs.OpenTelemetryLoggerOptions!
OpenTelemetry.Logs.OpenTelemetryLoggerOptions.ConfigureProvider(System.Action<System.IServiceProvider!, OpenTelemetry.Logs.OpenTelemetryLoggerProvider!>! configure) -> OpenTelemetry.Logs.OpenTelemetryLoggerOptions!
OpenTelemetry.Logs.OpenTelemetryLoggerOptions.ConfigureResource(System.Action<OpenTelemetry.Resources.ResourceBuilder!>! configure) -> OpenTelemetry.Logs.OpenTelemetryLoggerOptions!
OpenTelemetry.Logs.OpenTelemetryLoggerOptions.ConfigureServices(System.Action<Microsoft.Extensions.DependencyInjection.IServiceCollection!>! configure) -> OpenTelemetry.Logs.OpenTelemetryLoggerOptions!
OpenTelemetry.Logs.OpenTelemetryLoggerOptions.SetIncludeFormattedMessage(bool enabled) -> OpenTelemetry.Logs.OpenTelemetryLoggerOptions!
OpenTelemetry.Logs.OpenTelemetryLoggerOptions.SetIncludeScopes(bool enabled) -> OpenTelemetry.Logs.OpenTelemetryLoggerOptions!
OpenTelemetry.Logs.OpenTelemetryLoggerOptions.SetParseStateValues(bool enabled) -> OpenTelemetry.Logs.OpenTelemetryLoggerOptions!
OpenTelemetry.Logs.OpenTelemetryLoggerOptionsExtensions
OpenTelemetry.Logs.OpenTelemetryLoggerProvider.AddProcessor(OpenTelemetry.BaseProcessor<OpenTelemetry.Logs.LogRecord!>! processor) -> OpenTelemetry.Logs.OpenTelemetryLoggerProvider!
OpenTelemetry.Logs.OpenTelemetryLoggerProvider.ForceFlush(int timeoutMilliseconds = -1) -> bool
OpenTelemetry.Logs.OpenTelemetryLoggerProvider.OpenTelemetryLoggerProvider() -> void
static Microsoft.Extensions.DependencyInjection.MeterProviderBuilderServiceCollectionExtensions.ConfigureOpenTelemetryMetrics(this Microsoft.Extensions.DependencyInjection.IServiceCollection! services) -> Microsoft.Extensions.DependencyInjection.IServiceCollection!
static Microsoft.Extensions.DependencyInjection.MeterProviderBuilderServiceCollectionExtensions.ConfigureOpenTelemetryMetrics(this Microsoft.Extensions.DependencyInjection.IServiceCollection! services, System.Action<OpenTelemetry.Metrics.MeterProviderBuilder!>! configure) -> Microsoft.Extensions.DependencyInjection.IServiceCollection!
static OpenTelemetry.Metrics.MeterProviderBuilderExtensions.AddInstrumentation<T>(this OpenTelemetry.Metrics.MeterProviderBuilder! meterProviderBuilder) -> OpenTelemetry.Metrics.MeterProviderBuilder!
@ -53,8 +29,6 @@ OpenTelemetry.Trace.ExportActivityProcessorOptions.ExportActivityProcessorOption
OpenTelemetry.Trace.ExportActivityProcessorOptions.ExportProcessorType.get -> OpenTelemetry.ExportProcessorType
OpenTelemetry.Trace.ExportActivityProcessorOptions.ExportProcessorType.set -> void
static Microsoft.Extensions.Logging.OpenTelemetryLoggingExtensions.AddOpenTelemetry(this Microsoft.Extensions.Logging.ILoggingBuilder! builder) -> Microsoft.Extensions.Logging.ILoggingBuilder!
static Microsoft.Extensions.Logging.OpenTelemetryLoggingExtensions.AddOpenTelemetry(this Microsoft.Extensions.Logging.ILoggingBuilder! builder, OpenTelemetry.Logs.OpenTelemetryLoggerProvider! openTelemetryLoggerProvider) -> Microsoft.Extensions.Logging.ILoggingBuilder!
static Microsoft.Extensions.Logging.OpenTelemetryLoggingExtensions.AddOpenTelemetry(this Microsoft.Extensions.Logging.ILoggingBuilder! builder, OpenTelemetry.Logs.OpenTelemetryLoggerProvider! openTelemetryLoggerProvider, bool disposeProvider) -> Microsoft.Extensions.Logging.ILoggingBuilder!
static Microsoft.Extensions.Logging.OpenTelemetryLoggingExtensions.AddOpenTelemetry(this Microsoft.Extensions.Logging.ILoggingBuilder! builder, System.Action<OpenTelemetry.Logs.OpenTelemetryLoggerOptions!>? configure) -> Microsoft.Extensions.Logging.ILoggingBuilder!
static OpenTelemetry.Trace.TracerProviderBuilderExtensions.AddExporter(this OpenTelemetry.Trace.TracerProviderBuilder! tracerProviderBuilder, OpenTelemetry.ExportProcessorType exportProcessorType, OpenTelemetry.BaseExporter<System.Diagnostics.Activity!>! exporter) -> OpenTelemetry.Trace.TracerProviderBuilder!
static OpenTelemetry.Trace.TracerProviderBuilderExtensions.AddExporter(this OpenTelemetry.Trace.TracerProviderBuilder! tracerProviderBuilder, OpenTelemetry.ExportProcessorType exportProcessorType, OpenTelemetry.BaseExporter<System.Diagnostics.Activity!>! exporter, System.Action<OpenTelemetry.Trace.ExportActivityProcessorOptions!>! configure) -> OpenTelemetry.Trace.TracerProviderBuilder!
@ -65,8 +39,6 @@ static OpenTelemetry.Trace.TracerProviderBuilderExtensions.AddProcessor<T>(this
static OpenTelemetry.Trace.TracerProviderBuilderExtensions.ConfigureBuilder(this OpenTelemetry.Trace.TracerProviderBuilder! tracerProviderBuilder, System.Action<System.IServiceProvider!, OpenTelemetry.Trace.TracerProviderBuilder!>! configure) -> OpenTelemetry.Trace.TracerProviderBuilder!
static OpenTelemetry.Trace.TracerProviderBuilderExtensions.ConfigureServices(this OpenTelemetry.Trace.TracerProviderBuilder! tracerProviderBuilder, System.Action<Microsoft.Extensions.DependencyInjection.IServiceCollection!>! configure) -> OpenTelemetry.Trace.TracerProviderBuilder!
static OpenTelemetry.Trace.TracerProviderBuilderExtensions.SetSampler<T>(this OpenTelemetry.Trace.TracerProviderBuilder! tracerProviderBuilder) -> OpenTelemetry.Trace.TracerProviderBuilder!
static OpenTelemetry.Logs.OpenTelemetryLoggerOptionsExtensions.Build(this OpenTelemetry.Logs.OpenTelemetryLoggerOptions! options) -> OpenTelemetry.Logs.OpenTelemetryLoggerProvider!
static OpenTelemetry.Sdk.CreateLoggerProviderBuilder() -> OpenTelemetry.Logs.OpenTelemetryLoggerOptions!
static Microsoft.Extensions.DependencyInjection.TracerProviderBuilderServiceCollectionExtensions.ConfigureOpenTelemetryTracing(this Microsoft.Extensions.DependencyInjection.IServiceCollection! services) -> Microsoft.Extensions.DependencyInjection.IServiceCollection!
static Microsoft.Extensions.DependencyInjection.TracerProviderBuilderServiceCollectionExtensions.ConfigureOpenTelemetryTracing(this Microsoft.Extensions.DependencyInjection.IServiceCollection! services, System.Action<OpenTelemetry.Trace.TracerProviderBuilder!>! configure) -> Microsoft.Extensions.DependencyInjection.IServiceCollection!
static OpenTelemetry.Metrics.MeterProviderBuilderExtensions.ConfigureResource(this OpenTelemetry.Metrics.MeterProviderBuilder! meterProviderBuilder, System.Action<OpenTelemetry.Resources.ResourceBuilder!>! configure) -> OpenTelemetry.Metrics.MeterProviderBuilder!

View File

@ -18,13 +18,11 @@ using System.Runtime.CompilerServices;
[assembly: InternalsVisibleTo("OpenTelemetry.Tests" + AssemblyInfo.PublicKey)]
[assembly: InternalsVisibleTo("OpenTelemetry.Exporter.InMemory" + AssemblyInfo.PublicKey)]
[assembly: InternalsVisibleTo("OpenTelemetry.Extensions.EventSource" + AssemblyInfo.PublicKey)]
[assembly: InternalsVisibleTo("OpenTelemetry.Exporter.Prometheus.Shared" + AssemblyInfo.PublicKey)]
[assembly: InternalsVisibleTo("OpenTelemetry.Exporter.Prometheus.AspNetCore" + AssemblyInfo.PublicKey)]
[assembly: InternalsVisibleTo("OpenTelemetry.Exporter.Prometheus.AspNetCore.Tests" + AssemblyInfo.PublicKey)]
[assembly: InternalsVisibleTo("OpenTelemetry.Exporter.Prometheus.HttpListener" + AssemblyInfo.PublicKey)]
[assembly: InternalsVisibleTo("OpenTelemetry.Exporter.Prometheus.HttpListener.Tests" + AssemblyInfo.PublicKey)]
[assembly: InternalsVisibleTo("OpenTelemetry.Extensions.Hosting.Tests" + AssemblyInfo.PublicKey)]
[assembly: InternalsVisibleTo("OpenTelemetry.Extensions.Serilog" + AssemblyInfo.PublicKey)]
[assembly: InternalsVisibleTo("DynamicProxyGenAssembly2" + AssemblyInfo.MoqPublicKey)]
[assembly: InternalsVisibleTo("Benchmarks" + AssemblyInfo.PublicKey)]

View File

@ -11,14 +11,13 @@
* Added support for `UpDownCounter` and `ObservableUpDownCounter` instruments.
([#3606](https://github.com/open-telemetry/opentelemetry-dotnet/pull/3606))
* Added `AddExporter` `OpenTelemetryLoggerOptions` methods and further refined
the `OpenTelemetryLoggerProvider` dependency injection scenarios
([#3596](https://github.com/open-telemetry/opentelemetry-dotnet/pull/3596))
* Added support for dependency injection scenarios when configuring
`MeterProvider`
([#3646](https://github.com/open-telemetry/opentelemetry-dotnet/pull/3646))
* Revert new logging APIs pending OTel specification changes
([#3702](https://github.com/open-telemetry/opentelemetry-dotnet/pull/3702))
## 1.4.0-alpha.2
Released 2022-Aug-18

View File

@ -1,75 +0,0 @@
// <copyright file="BatchExportLogRecordProcessorOptions.cs" company="OpenTelemetry Authors">
// 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.
// </copyright>
using System;
using OpenTelemetry.Internal;
namespace OpenTelemetry.Logs
{
/// <summary>
/// Batch log processor options. OTEL_DOTNET_BLP_MAX_QUEUE_SIZE,
/// OTEL_DOTNET_BLP_MAX_EXPORT_BATCH_SIZE, OTEL_DOTNET_BLP_EXPORT_TIMEOUT,
/// OTEL_DOTNET_BLP_SCHEDULE_DELAY environment variables are parsed during
/// object construction.
/// </summary>
/// <remarks>
/// Notes:
/// <list type="bullet">
/// <item>The constructor throws <see cref="FormatException"/> if it fails
/// to parse any of the supported environment variables.</item>
/// <item>The environment variable keys are currently experimental and
/// subject to change. See: <see
/// href="https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/sdk-environment-variables.md#opentelemetry-environment-variable-specification">OpenTelemetry
/// Environment Variable Specification</see>.
/// </item>
/// </list>
/// </remarks>
public class BatchExportLogRecordProcessorOptions : BatchExportProcessorOptions<LogRecord>
{
internal const string MaxQueueSizeEnvVarKey = "OTEL_DOTNET_BLP_MAX_QUEUE_SIZE";
internal const string MaxExportBatchSizeEnvVarKey = "OTEL_DOTNET_BLP_MAX_EXPORT_BATCH_SIZE";
internal const string ExporterTimeoutEnvVarKey = "OTEL_DOTNET_BLP_EXPORT_TIMEOUT";
internal const string ScheduledDelayEnvVarKey = "OTEL_DOTNET_BLP_SCHEDULE_DELAY";
public BatchExportLogRecordProcessorOptions()
{
int value;
if (EnvironmentVariableHelper.LoadNumeric(ExporterTimeoutEnvVarKey, out value))
{
this.ExporterTimeoutMilliseconds = value;
}
if (EnvironmentVariableHelper.LoadNumeric(MaxExportBatchSizeEnvVarKey, out value))
{
this.MaxExportBatchSize = value;
}
if (EnvironmentVariableHelper.LoadNumeric(MaxQueueSizeEnvVarKey, out value))
{
this.MaxQueueSize = value;
}
if (EnvironmentVariableHelper.LoadNumeric(ScheduledDelayEnvVarKey, out value))
{
this.ScheduledDelayMilliseconds = value;
}
}
}
}

View File

@ -1,45 +0,0 @@
// <copyright file="ExportLogRecordProcessorOptions.cs" company="OpenTelemetry Authors">
// 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.
// </copyright>
#nullable enable
using OpenTelemetry.Internal;
namespace OpenTelemetry.Logs;
public class ExportLogRecordProcessorOptions
{
private BatchExportLogRecordProcessorOptions? batchExportProcessorOptions;
/// <summary>
/// Gets or sets the export processor type to be used. The default value is <see cref="ExportProcessorType.Batch"/>.
/// </summary>
public ExportProcessorType ExportProcessorType { get; set; }
/// <summary>
/// Gets or sets the batch export options. Ignored unless <see cref="ExportProcessorType"/> is <see cref="ExportProcessorType.Batch"/>.
/// </summary>
public BatchExportLogRecordProcessorOptions BatchExportProcessorOptions
{
get => this.batchExportProcessorOptions ??= new();
set
{
Guard.ThrowIfNull(value);
this.batchExportProcessorOptions = value;
}
}
}

View File

@ -1,67 +0,0 @@
// <copyright file="LogEmitter.cs" company="OpenTelemetry Authors">
// 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.
// </copyright>
#nullable enable
using OpenTelemetry.Internal;
namespace OpenTelemetry.Logs
{
/// <summary>
/// LogEmitter implementation.
/// </summary>
/// <remarks>
/// Spec reference: <a href="https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/logs/logging-library-sdk.md#logemitter">LogEmitter</a>.
/// </remarks>
internal sealed class LogEmitter
{
private readonly OpenTelemetryLoggerProvider loggerProvider;
internal LogEmitter(OpenTelemetryLoggerProvider loggerProvider)
{
Guard.ThrowIfNull(loggerProvider);
this.loggerProvider = loggerProvider;
}
/// <summary>
/// Emit a <see cref="LogRecord"/>.
/// </summary>
/// <param name="data"><see cref="LogRecordData"/>.</param>
/// <param name="attributes"><see cref="LogRecordAttributeList"/>.</param>
public void Emit(in LogRecordData data, in LogRecordAttributeList attributes = default)
{
var provider = this.loggerProvider;
var processor = provider.Processor;
if (processor != null)
{
var pool = provider.LogRecordPool;
var logRecord = pool.Rent();
logRecord.Data = data;
attributes.ApplyToLogRecord(logRecord);
processor.OnEnd(logRecord);
// Attempt to return the LogRecord to the pool. This will no-op
// if a batch exporter has added a reference.
pool.Return(logRecord);
}
}
}
}

View File

@ -18,10 +18,8 @@
using System;
using System.Collections;
using System.Diagnostics;
using System.Text;
using System.Threading;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
using OpenTelemetry.Internal;
@ -39,9 +37,7 @@ namespace OpenTelemetry.Logs
internal readonly bool IncludeFormattedMessage;
internal readonly bool ParseStateValues;
internal BaseProcessor<LogRecord>? Processor;
internal ResourceBuilder? ResourceBuilder;
internal Resource Resource;
private readonly ServiceProvider? ownedServiceProvider;
private readonly Hashtable loggers = new();
private ILogRecordPool? threadStaticPool = LogRecordThreadStaticPool.Instance;
private bool disposed;
@ -57,21 +53,22 @@ namespace OpenTelemetry.Logs
/// Initializes a new instance of the <see cref="OpenTelemetryLoggerProvider"/> class.
/// </summary>
/// <param name="options"><see cref="OpenTelemetryLoggerOptions"/>.</param>
[Obsolete("Use the Sdk.CreateLoggerProviderBuilder method instead")]
public OpenTelemetryLoggerProvider(IOptionsMonitor<OpenTelemetryLoggerOptions> options)
: this(options?.CurrentValue ?? throw new ArgumentNullException(nameof(options)), serviceProvider: null, ownsServiceProvider: false)
: this(options?.CurrentValue ?? throw new ArgumentNullException(nameof(options)))
{
}
/// <summary>
/// Initializes a new instance of the <see cref="OpenTelemetryLoggerProvider"/> class.
/// </summary>
public OpenTelemetryLoggerProvider()
: this(new(), serviceProvider: null, ownsServiceProvider: false)
internal OpenTelemetryLoggerProvider()
: this(new OpenTelemetryLoggerOptions())
{
}
internal OpenTelemetryLoggerProvider(OpenTelemetryLoggerOptions options, IServiceProvider? serviceProvider, bool ownsServiceProvider)
internal OpenTelemetryLoggerProvider(Action<OpenTelemetryLoggerOptions> configure)
: this(BuildOptions(configure))
{
}
internal OpenTelemetryLoggerProvider(OpenTelemetryLoggerOptions options)
{
OpenTelemetrySdkEventSource.Log.OpenTelemetryLoggerProviderEvent("Building OpenTelemetryLoggerProvider.");
@ -81,37 +78,13 @@ namespace OpenTelemetry.Logs
this.IncludeFormattedMessage = options.IncludeFormattedMessage;
this.ParseStateValues = options.ParseStateValues;
if (ownsServiceProvider)
this.Resource = options.ResourceBuilder.Build();
foreach (var processor in options.Processors)
{
this.ownedServiceProvider = serviceProvider as ServiceProvider;
Debug.Assert(this.ownedServiceProvider != null, "ownedServiceProvider was null");
this.AddProcessor(processor);
}
this.ResourceBuilder ??= ResourceBuilder.CreateDefault();
var configurationActions = options.ConfigurationActions;
if (configurationActions?.Count > 0)
{
if (serviceProvider == null)
{
throw new InvalidOperationException("Configuration actions were registered on options but no service provider was supplied.");
}
// Note: Not using a foreach loop because additional actions can be
// added during each call.
for (int i = 0; i < configurationActions.Count; i++)
{
configurationActions[i](serviceProvider, this);
}
OpenTelemetrySdkEventSource.Log.OpenTelemetryLoggerProviderEvent($"Number of actions configured = {configurationActions.Count}.");
options.ConfigurationActions = null;
}
this.Resource = this.ResourceBuilder.Build();
this.ResourceBuilder = null;
OpenTelemetrySdkEventSource.Log.OpenTelemetryLoggerProviderEvent("OpenTelemetryLoggerProvider built successfully.");
}
@ -177,7 +150,7 @@ namespace OpenTelemetry.Logs
/// <remarks>
/// This function guarantees thread-safety.
/// </remarks>
public bool ForceFlush(int timeoutMilliseconds = Timeout.Infinite)
internal bool ForceFlush(int timeoutMilliseconds = Timeout.Infinite)
{
OpenTelemetrySdkEventSource.Log.OpenTelemetryLoggerProviderForceFlushInvoked(timeoutMilliseconds);
return this.Processor?.ForceFlush(timeoutMilliseconds) ?? true;
@ -193,7 +166,7 @@ namespace OpenTelemetry.Logs
/// </remarks>
/// <param name="processor">Log processor to add.</param>
/// <returns>The supplied <see cref="OpenTelemetryLoggerOptions"/> for chaining.</returns>
public OpenTelemetryLoggerProvider AddProcessor(BaseProcessor<LogRecord> processor)
internal OpenTelemetryLoggerProvider AddProcessor(BaseProcessor<LogRecord> processor)
{
OpenTelemetrySdkEventSource.Log.OpenTelemetryLoggerProviderEvent("Started adding processor.");
@ -246,12 +219,6 @@ namespace OpenTelemetry.Logs
return this;
}
/// <summary>
/// Create a <see cref="LogEmitter"/>.
/// </summary>
/// <returns><see cref="LogEmitter"/>.</returns>
internal LogEmitter CreateEmitter() => new(this);
internal bool ContainsBatchProcessor(BaseProcessor<LogRecord> processor)
{
if (processor is BatchExportProcessor<LogRecord>)
@ -285,8 +252,6 @@ namespace OpenTelemetry.Logs
// Wait for up to 5 seconds grace period
this.Processor?.Shutdown(5000);
this.Processor?.Dispose();
this.ownedServiceProvider?.Dispose();
}
this.disposed = true;
@ -295,5 +260,12 @@ namespace OpenTelemetry.Logs
base.Dispose(disposing);
}
private static OpenTelemetryLoggerOptions BuildOptions(Action<OpenTelemetryLoggerOptions> configure)
{
var options = new OpenTelemetryLoggerOptions();
configure?.Invoke(options);
return options;
}
}
}

View File

@ -21,7 +21,6 @@ using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.DependencyInjection.Extensions;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Logging.Configuration;
using Microsoft.Extensions.Options;
using OpenTelemetry.Internal;
using OpenTelemetry.Logs;
@ -58,107 +57,14 @@ namespace Microsoft.Extensions.Logging
builder.AddConfiguration();
builder.Services.TryAddEnumerable(ServiceDescriptor.Singleton<ILoggerProvider, OpenTelemetryLoggerProvider>(sp =>
{
var finalOptions = sp.GetRequiredService<IOptionsMonitor<OpenTelemetryLoggerOptions>>().CurrentValue;
return new OpenTelemetryLoggerProvider(finalOptions, sp, ownsServiceProvider: false);
}));
builder.Services.TryAddEnumerable(ServiceDescriptor.Singleton<ILoggerProvider, OpenTelemetryLoggerProvider>());
// Note: This will bind logger options element (eg "Logging:OpenTelemetry") to OpenTelemetryLoggerOptions
LoggerProviderOptions.RegisterProviderOptions<OpenTelemetryLoggerOptions, OpenTelemetryLoggerProvider>(builder.Services);
if (configure != null)
{
/*
* We do a two-phase configuration here.
*
* Step 1: Configure callback is first invoked immediately. This
* is to make "Services" available for extension authors to
* register additional dependencies into the collection if
* needed.
*/
var options = new OpenTelemetryLoggerOptions(builder.Services);
configure(options);
/*
* Step 2: When ServiceProvider is built from "Services" and the
* LoggerFactory is created then the options pipeline runs and
* builds a new OpenTelemetryLoggerOptions from configuration
* and callbacks are executed. "Services" can no longer be
* modified in this phase because the ServiceProvider is already
* complete. We apply the inline options to the final instance
* to bridge this gap.
*/
builder.Services.Configure<OpenTelemetryLoggerOptions>(finalOptions =>
{
options.ApplyTo(finalOptions);
});
}
return builder;
}
/// <summary>
/// Adds an OpenTelemetry logger named 'OpenTelemetry' to the <see cref="ILoggerFactory"/>.
/// </summary>
/// <remarks>
/// Notes:
/// <list type="bullet">
/// <item>
/// The supplied <see cref="OpenTelemetryLoggerProvider"/> will
/// automatically be disposed when the <see cref="ILoggerFactory"/>
/// built from <paramref name="builder"/> is disposed.
/// </item>
/// <item>
/// Only a single<see cref="OpenTelemetryLoggerProvider"/> can be
/// registered for a given <see cref="IServiceCollection"/>. Additional
/// calls to this method will be ignored.
/// </item>
/// </list>
/// </remarks>
/// <param name="builder">The <see cref="ILoggingBuilder"/> to use.</param>
/// <param name="openTelemetryLoggerProvider"><see cref="OpenTelemetryLoggerProvider"/>.</param>
/// <returns>The supplied <see cref="ILoggingBuilder"/> for call chaining.</returns>
public static ILoggingBuilder AddOpenTelemetry(this ILoggingBuilder builder, OpenTelemetryLoggerProvider openTelemetryLoggerProvider)
=> AddOpenTelemetry(builder, openTelemetryLoggerProvider, disposeProvider: true);
/// <summary>
/// Adds an OpenTelemetry logger named 'OpenTelemetry' to the <see cref="ILoggerFactory"/>.
/// </summary>
/// <remarks>
/// Note: Only a single <see cref="OpenTelemetryLoggerProvider"/> can be
/// registered for a given <see cref="IServiceCollection"/>. Additional
/// calls to this method will be ignored.
/// </remarks>
/// <param name="builder">The <see cref="ILoggingBuilder"/> to use.</param>
/// <param name="openTelemetryLoggerProvider"><see cref="OpenTelemetryLoggerProvider"/>.</param>
/// <param name="disposeProvider">Controls whether or not the supplied
/// <paramref name="openTelemetryLoggerProvider"/> will be disposed when
/// the <see cref="ILoggerFactory"/> is disposed.</param>
/// <returns>The supplied <see cref="ILoggingBuilder"/> for call chaining.</returns>
public static ILoggingBuilder AddOpenTelemetry(
this ILoggingBuilder builder,
OpenTelemetryLoggerProvider openTelemetryLoggerProvider,
bool disposeProvider)
{
Guard.ThrowIfNull(builder);
Guard.ThrowIfNull(openTelemetryLoggerProvider);
// Note: Currently if multiple OpenTelemetryLoggerProvider instances
// are added to the same ILoggingBuilder everything after the first
// is silently ignored.
if (disposeProvider)
{
builder.Services.TryAddEnumerable(ServiceDescriptor.Singleton<ILoggerProvider, OpenTelemetryLoggerProvider>(sp => openTelemetryLoggerProvider));
}
else
{
builder.Services.TryAddEnumerable(ServiceDescriptor.Singleton<ILoggerProvider>(openTelemetryLoggerProvider));
builder.Services.Configure(configure);
}
return builder;

View File

@ -18,10 +18,6 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.DependencyInjection.Extensions;
using Microsoft.Extensions.Options;
using OpenTelemetry.Internal;
using OpenTelemetry.Resources;
@ -32,51 +28,22 @@ namespace OpenTelemetry.Logs
/// </summary>
public class OpenTelemetryLoggerOptions
{
internal List<Action<IServiceProvider, OpenTelemetryLoggerProvider>>? ConfigurationActions = new();
private const bool DefaultIncludeScopes = false;
private const bool DefaultIncludeFormattedMessage = false;
private const bool DefaultParseStateValues = false;
private IServiceCollection? services;
private bool? includeScopes;
private bool? includeFormattedMessage;
private bool? parseStateValues;
/// <summary>
/// Initializes a new instance of the <see cref="OpenTelemetryLoggerOptions"/> class.
/// </summary>
public OpenTelemetryLoggerOptions()
: this(services: null)
{
}
internal OpenTelemetryLoggerOptions(IServiceCollection? services)
{
this.services = services;
}
internal readonly List<BaseProcessor<LogRecord>> Processors = new();
internal ResourceBuilder ResourceBuilder = ResourceBuilder.CreateDefault();
/// <summary>
/// Gets or sets a value indicating whether or not log scopes should be
/// included on generated <see cref="LogRecord"/>s. Default value:
/// False.
/// </summary>
public bool IncludeScopes
{
get => this.includeScopes ?? DefaultIncludeScopes;
set => this.includeScopes = value;
}
public bool IncludeScopes { get; set; }
/// <summary>
/// Gets or sets a value indicating whether or not formatted log message
/// should be included on generated <see cref="LogRecord"/>s. Default
/// value: False.
/// </summary>
public bool IncludeFormattedMessage
{
get => this.includeFormattedMessage ?? DefaultIncludeFormattedMessage;
set => this.includeFormattedMessage = value;
}
public bool IncludeFormattedMessage { get; set; }
/// <summary>
/// Gets or sets a value indicating whether or not log state should be
@ -88,142 +55,18 @@ namespace OpenTelemetry.Logs
/// langword="true"/> <see cref="LogRecord.State"/> will always be <see
/// langword="null"/>.
/// </remarks>
public bool ParseStateValues
{
get => this.parseStateValues ?? DefaultParseStateValues;
set => this.parseStateValues = value;
}
internal IServiceCollection? Services => this.services;
public bool ParseStateValues { get; set; }
/// <summary>
/// Adds processor to the options.
/// </summary>
/// <remarks>
/// Note: The supplied <paramref name="processor"/> will be
/// automatically disposed when then the final <see
/// cref="OpenTelemetryLoggerProvider"/> built from the options is
/// disposed.
/// </remarks>
/// <param name="processor">Log processor to add.</param>
/// <returns>Returns <see cref="OpenTelemetryLoggerOptions"/> for chaining.</returns>
public OpenTelemetryLoggerOptions AddProcessor(BaseProcessor<LogRecord> processor)
{
Guard.ThrowIfNull(processor);
this.ConfigureProvider((sp, provider) => provider.AddProcessor(processor));
return this;
}
/// <summary>
/// Adds a processor to the options which will be retrieved using dependency injection.
/// </summary>
/// <remarks>
/// Note: The type specified by <typeparamref name="T"/> will be
/// registered as a singleton service into application services.
/// </remarks>
/// <typeparam name="T">Processor type.</typeparam>
/// <returns>Returns <see cref="OpenTelemetryLoggerOptions"/> for chaining.</returns>
public OpenTelemetryLoggerOptions AddProcessor<T>()
where T : BaseProcessor<LogRecord>
{
this.TryAddSingleton<T>();
this.ConfigureProvider((sp, provider) => provider.AddProcessor(sp.GetRequiredService<T>()));
return this;
}
/// <summary>
/// Adds an exporter to the provider.
/// </summary>
/// <param name="exportProcessorType"><see cref="ExportProcessorType"/>.</param>
/// <param name="exporter">LogRecord exporter to add.</param>
/// <returns>Returns <see cref="OpenTelemetryLoggerOptions"/> for chaining.</returns>
public OpenTelemetryLoggerOptions AddExporter(ExportProcessorType exportProcessorType, BaseExporter<LogRecord> exporter)
=> this.AddExporter(exportProcessorType, exporter, name: null, configure: null);
/// <summary>
/// Adds an exporter to the provider.
/// </summary>
/// <param name="exportProcessorType"><see cref="ExportProcessorType"/>.</param>
/// <param name="exporter">LogRecord exporter to add.</param>
/// <param name="configure"><inheritdoc cref="AddExporter{T}(ExportProcessorType, string?, Action{ExportLogRecordProcessorOptions}?)" path="/param[@name='configure']"/></param>
/// <returns>Returns <see cref="OpenTelemetryLoggerOptions"/> for chaining.</returns>
public OpenTelemetryLoggerOptions AddExporter(ExportProcessorType exportProcessorType, BaseExporter<LogRecord> exporter, Action<ExportLogRecordProcessorOptions> configure)
=> this.AddExporter(exportProcessorType, exporter, name: null, configure);
/// <summary>
/// Adds an exporter to the provider.
/// </summary>
/// <param name="exportProcessorType"><see cref="ExportProcessorType"/>.</param>
/// <param name="exporter">LogRecord exporter to add.</param>
/// <param name="name">Name which is used when retrieving options.</param>
/// <param name="configure"><inheritdoc cref="AddExporter{T}(ExportProcessorType, string?, Action{ExportLogRecordProcessorOptions}?)" path="/param[@name='configure']"/></param>
/// <returns>Returns <see cref="OpenTelemetryLoggerOptions"/> for chaining.</returns>
public OpenTelemetryLoggerOptions AddExporter(
ExportProcessorType exportProcessorType,
BaseExporter<LogRecord> exporter,
string? name,
Action<ExportLogRecordProcessorOptions>? configure)
{
Guard.ThrowIfNull(exporter);
this.ConfigureProvider((sp, provider)
=> provider.AddProcessor(
BuildExportProcessor(sp, exportProcessorType, exporter, name, configure)));
return this;
}
/// <summary>
/// Adds an exporter to the provider which will be retrieved using dependency injection.
/// </summary>
/// <remarks><inheritdoc cref="AddExporter{T}(ExportProcessorType, string?, Action{ExportLogRecordProcessorOptions}?)" path="/remarks"/></remarks>
/// <typeparam name="T">Exporter type.</typeparam>
/// <param name="exportProcessorType"><see cref="ExportProcessorType"/>.</param>
/// <returns>Returns <see cref="OpenTelemetryLoggerOptions"/> for chaining.</returns>
public OpenTelemetryLoggerOptions AddExporter<T>(ExportProcessorType exportProcessorType)
where T : BaseExporter<LogRecord>
=> this.AddExporter<T>(exportProcessorType, name: null, configure: null);
/// <summary>
/// Adds an exporter to the provider which will be retrieved using dependency injection.
/// </summary>
/// <remarks><inheritdoc cref="AddExporter{T}(ExportProcessorType, string?, Action{ExportLogRecordProcessorOptions}?)" path="/remarks"/></remarks>
/// <typeparam name="T">Exporter type.</typeparam>
/// <param name="exportProcessorType"><see cref="ExportProcessorType"/>.</param>
/// <param name="configure"><inheritdoc cref="AddExporter{T}(ExportProcessorType, string?, Action{ExportLogRecordProcessorOptions}?)" path="/param[@name='configure']"/></param>
/// <returns>Returns <see cref="OpenTelemetryLoggerOptions"/> for chaining.</returns>
public OpenTelemetryLoggerOptions AddExporter<T>(ExportProcessorType exportProcessorType, Action<ExportLogRecordProcessorOptions> configure)
where T : BaseExporter<LogRecord>
=> this.AddExporter<T>(exportProcessorType, name: null, configure);
/// <summary>
/// Adds an exporter to the provider which will be retrieved using dependency injection.
/// </summary>
/// <remarks>
/// Note: The type specified by <typeparamref name="T"/> will be
/// registered as a singleton service into application services.
/// </remarks>
/// <typeparam name="T">Exporter type.</typeparam>
/// <param name="exportProcessorType"><see cref="ExportProcessorType"/>.</param>
/// <param name="name">Name which is used when retrieving options.</param>
/// <param name="configure">Callback action to configure <see
/// cref="ExportLogRecordProcessorOptions"/>. Only invoked when <paramref
/// name="exportProcessorType"/> is <see
/// cref="ExportProcessorType.Batch"/>.</param>
/// <returns>Returns <see cref="OpenTelemetryLoggerOptions"/> for chaining.</returns>
public OpenTelemetryLoggerOptions AddExporter<T>(
ExportProcessorType exportProcessorType,
string? name,
Action<ExportLogRecordProcessorOptions>? configure)
where T : BaseExporter<LogRecord>
{
this.TryAddSingleton<T>();
this.ConfigureProvider((sp, provider)
=> provider.AddProcessor(
BuildExportProcessor(sp, exportProcessorType, sp.GetRequiredService<T>(), name, configure)));
this.Processors.Add(processor);
return this;
}
@ -231,8 +74,6 @@ namespace OpenTelemetry.Logs
/// <summary>
/// Sets the <see cref="ResourceBuilder"/> from which the Resource associated with
/// this provider is built from. Overwrites currently set ResourceBuilder.
/// You should usually use <see cref="ConfigureResource(Action{ResourceBuilder})"/> instead
/// (call <see cref="ResourceBuilder.Clear"/> if desired).
/// </summary>
/// <param name="resourceBuilder"><see cref="ResourceBuilder"/> from which Resource will be built.</param>
/// <returns>Returns <see cref="OpenTelemetryLoggerOptions"/> for chaining.</returns>
@ -240,7 +81,8 @@ namespace OpenTelemetry.Logs
{
Guard.ThrowIfNull(resourceBuilder);
return this.ConfigureProvider((sp, provider) => provider.ResourceBuilder = resourceBuilder);
this.ResourceBuilder = resourceBuilder;
return this;
}
/// <summary>
@ -249,212 +91,11 @@ namespace OpenTelemetry.Logs
/// </summary>
/// <param name="configure">An action which modifies the provided <see cref="ResourceBuilder"/> in-place.</param>
/// <returns>Returns <see cref="OpenTelemetryLoggerOptions"/> for chaining.</returns>
public OpenTelemetryLoggerOptions ConfigureResource(
Action<ResourceBuilder> configure)
public OpenTelemetryLoggerOptions ConfigureResource(Action<ResourceBuilder> configure)
{
Guard.ThrowIfNull(configure);
this.ConfigureProvider((sp, provider) =>
{
Debug.Assert(provider.ResourceBuilder != null, "provider.ResourceBuilder was null");
configure(provider.ResourceBuilder!);
});
Guard.ThrowIfNull(configure, nameof(configure));
configure(this.ResourceBuilder);
return this;
}
/// <summary>
/// Register a callback action to configure the <see
/// cref="IServiceCollection"/> where logging services are configured.
/// </summary>
/// <remarks>
/// Note: Logging services are only available during the application
/// configuration phase. When using "Options" pattern via <see
/// cref="OptionsServiceCollectionExtensions"/> or interfaces such as
/// <see cref="IConfigureOptions{T}"/> logging services will be
/// unavailable because "Options" are built after application services
/// have been configured.
/// </remarks>
/// <param name="configure">Configuration callback.</param>
/// <returns>The supplied <see cref="OpenTelemetryLoggerOptions"/> for chaining.</returns>
public OpenTelemetryLoggerOptions ConfigureServices(
Action<IServiceCollection> configure)
{
Guard.ThrowIfNull(configure);
var services = this.services;
if (services == null)
{
throw new NotSupportedException("Services cannot be configured outside of application configuration phase.");
}
configure(services);
return this;
}
/// <summary>
/// Register a callback action to configure the <see
/// cref="OpenTelemetryLoggerProvider"/> once the application <see
/// cref="IServiceProvider"/> is available.
/// </summary>
/// <param name="configure">Configuration callback.</param>
/// <returns>The supplied <see cref="OpenTelemetryLoggerOptions"/> for chaining.</returns>
public OpenTelemetryLoggerOptions ConfigureProvider(
Action<IServiceProvider, OpenTelemetryLoggerProvider> configure)
{
Guard.ThrowIfNull(configure);
var configurationActions = this.ConfigurationActions;
if (configurationActions == null)
{
throw new NotSupportedException("Configuration actions cannot be registered on options after OpenTelemetryLoggerProvider has been created.");
}
configurationActions.Add(configure);
return this;
}
/// <summary>
/// Sets the value of the <see cref="IncludeFormattedMessage"/> options.
/// </summary>
/// <param name="enabled"><see langword="true"/> to enable the option or
/// <see langword="false"/> to disable it.</param>
/// <returns>The supplied <see cref="OpenTelemetryLoggerOptions"/> for
/// chaining.</returns>
public OpenTelemetryLoggerOptions SetIncludeFormattedMessage(bool enabled)
{
this.includeFormattedMessage = enabled;
return this;
}
/// <summary>
/// Sets the value of the <see cref="IncludeScopes"/> options.
/// </summary>
/// <param name="enabled"><see langword="true"/> to enable the option or
/// <see langword="false"/> to disable it.</param>
/// <returns>The supplied <see cref="OpenTelemetryLoggerOptions"/> for
/// chaining.</returns>
public OpenTelemetryLoggerOptions SetIncludeScopes(bool enabled)
{
this.includeScopes = enabled;
return this;
}
/// <summary>
/// Sets the value of the <see cref="ParseStateValues"/> options.
/// </summary>
/// <param name="enabled"><see langword="true"/> to enable the option or
/// <see langword="false"/> to disable it.</param>
/// <returns>The supplied <see cref="OpenTelemetryLoggerOptions"/> for
/// chaining.</returns>
public OpenTelemetryLoggerOptions SetParseStateValues(bool enabled)
{
this.parseStateValues = enabled;
return this;
}
internal OpenTelemetryLoggerProvider Build()
{
var services = this.services;
if (services == null)
{
throw new NotSupportedException("OpenTelemetryLoggerOptions build method cannot be called multiple times.");
}
this.services = null;
#if DEBUG
bool validateScopes = true;
#else
bool validateScopes = false;
#endif
var serviceProvider = services.BuildServiceProvider(validateScopes);
var finalOptions = serviceProvider.GetRequiredService<IOptionsMonitor<OpenTelemetryLoggerOptions>>().CurrentValue;
this.ApplyTo(finalOptions);
var provider = new OpenTelemetryLoggerProvider(
finalOptions,
serviceProvider,
ownsServiceProvider: true);
this.ConfigurationActions = null;
return provider;
}
internal void ApplyTo(OpenTelemetryLoggerOptions other)
{
Debug.Assert(other != null, "other instance was null");
if (this.includeFormattedMessage.HasValue)
{
other!.includeFormattedMessage = this.includeFormattedMessage;
}
if (this.includeScopes.HasValue)
{
other!.includeScopes = this.includeScopes;
}
if (this.parseStateValues.HasValue)
{
other!.parseStateValues = this.parseStateValues;
}
Debug.Assert(this.ConfigurationActions != null && other!.ConfigurationActions != null, "ConfigurationActions was null");
foreach (var configurationAction in this.ConfigurationActions!)
{
other!.ConfigurationActions!.Add(configurationAction);
}
}
private static BaseProcessor<LogRecord> BuildExportProcessor(
IServiceProvider serviceProvider,
ExportProcessorType exportProcessorType,
BaseExporter<LogRecord> exporter,
string? name,
Action<ExportLogRecordProcessorOptions>? configure)
{
name ??= Options.DefaultName;
switch (exportProcessorType)
{
case ExportProcessorType.Simple:
return new SimpleLogRecordExportProcessor(exporter);
case ExportProcessorType.Batch:
var options = serviceProvider.GetRequiredService<IOptionsMonitor<ExportLogRecordProcessorOptions>>().Get(name);
options.ExportProcessorType = ExportProcessorType.Batch;
configure?.Invoke(options);
var batchOptions = options.BatchExportProcessorOptions;
return new BatchLogRecordExportProcessor(
exporter,
batchOptions.MaxQueueSize,
batchOptions.ScheduledDelayMilliseconds,
batchOptions.ExporterTimeoutMilliseconds,
batchOptions.MaxExportBatchSize);
default:
throw new NotSupportedException($"ExportProcessorType '{exportProcessorType}' is not supported.");
}
}
private void TryAddSingleton<T>()
where T : class
{
var services = this.services;
services?.TryAddSingleton<T>();
}
}
}

View File

@ -1,45 +0,0 @@
// <copyright file="OpenTelemetryLoggerOptionsExtensions.cs" company="OpenTelemetry Authors">
// 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.
// </copyright>
#nullable enable
using System;
using OpenTelemetry.Internal;
namespace OpenTelemetry.Logs;
/// <summary>
/// Contains extension methods for the <see cref="OpenTelemetryLoggerOptions"/> class.
/// </summary>
public static class OpenTelemetryLoggerOptionsExtensions
{
/// <summary>
/// Run the given actions to initialize the <see cref="OpenTelemetryLoggerProvider"/>.
/// </summary>
/// <param name="options"><see cref="OpenTelemetryLoggerOptions"/>.</param>
/// <returns><see cref="OpenTelemetryLoggerProvider"/>.</returns>
public static OpenTelemetryLoggerProvider Build(this OpenTelemetryLoggerOptions options)
{
Guard.ThrowIfNull(options);
if (options is not OpenTelemetryLoggerOptionsSdk openTelemetryLoggerOptionsSdk)
{
throw new NotSupportedException("Build is only supported on options instances created using the Sdk.CreateLoggerProviderBuilder method.");
}
return openTelemetryLoggerOptionsSdk.Build();
}
}

View File

@ -1,30 +0,0 @@
// <copyright file="OpenTelemetryLoggerOptionsSdk.cs" company="OpenTelemetry Authors">
// 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.
// </copyright>
#nullable enable
using Microsoft.Extensions.DependencyInjection;
namespace OpenTelemetry.Logs;
internal sealed class OpenTelemetryLoggerOptionsSdk : OpenTelemetryLoggerOptions
{
public OpenTelemetryLoggerOptionsSdk()
: base(new ServiceCollection())
{
this.ConfigureServices(services => services.AddOptions());
}
}

View File

@ -19,7 +19,6 @@
using System.Diagnostics;
using OpenTelemetry.Context.Propagation;
using OpenTelemetry.Internal;
using OpenTelemetry.Logs;
using OpenTelemetry.Metrics;
using OpenTelemetry.Trace;
@ -59,19 +58,6 @@ namespace OpenTelemetry
Propagators.DefaultTextMapPropagator = textMapPropagator;
}
/// <summary>
/// Creates a <see cref="OpenTelemetryLoggerOptions"/> which is used to build
/// an <see cref="OpenTelemetryLoggerProvider"/>. In a typical application, a single
/// <see cref="OpenTelemetryLoggerProvider"/> is created at application startup and disposed
/// at application shutdown. It is important to ensure that the provider is not
/// disposed too early.
/// </summary>
/// <returns><see cref="OpenTelemetryLoggerOptions"/> instance, which is used to build a <see cref="OpenTelemetryLoggerProvider"/>.</returns>
public static OpenTelemetryLoggerOptions CreateLoggerProviderBuilder()
{
return new OpenTelemetryLoggerOptionsSdk();
}
/// <summary>
/// Creates a <see cref="MeterProviderBuilder"/> which is used to build
/// a <see cref="MeterProvider"/>. In a typical application, a single

View File

@ -113,32 +113,6 @@ namespace OpenTelemetry.Exporter.OpenTelemetryProtocol.Tests
Assert.Null(logRecord.StateValues);
}
[Fact]
public void AddOtlpLogExporterNamedOptionsSupported()
{
int defaultExporterOptionsConfigureOptionsInvocations = 0;
int namedExporterOptionsConfigureOptionsInvocations = 0;
using var loggerFactory = LoggerFactory.Create(builder =>
{
builder.AddOpenTelemetry(options =>
{
options
.ConfigureServices(services =>
{
services.Configure<OtlpExporterOptions>(o => defaultExporterOptionsConfigureOptionsInvocations++);
services.Configure<OtlpExporterOptions>("Exporter2", o => namedExporterOptionsConfigureOptionsInvocations++);
})
.AddOtlpExporter()
.AddOtlpExporter("Exporter2", o => { });
});
});
Assert.Equal(1, defaultExporterOptionsConfigureOptionsInvocations);
Assert.Equal(1, namedExporterOptionsConfigureOptionsInvocations);
}
[Fact]
public void OtlpLogRecordTestWhenStateValuesArePopulated()
{

View File

@ -1,19 +0,0 @@
// <copyright file="AssemblyInfo.cs" company="OpenTelemetry Authors">
// 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.
// </copyright>
using System;
[assembly: CLSCompliant(false)]

View File

@ -1,27 +0,0 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<Description>Unit test project for OpenTelemetry EventSource extensions</Description>
<!-- OmniSharp/VS Code requires TargetFrameworks to be in descending order for IntelliSense and analysis. -->
<TargetFrameworks>net6.0</TargetFrameworks>
<TargetFrameworks Condition="$(OS) == 'Windows_NT'">$(TargetFrameworks);net462</TargetFrameworks>
<Nullable>enable</Nullable>
<AnalysisMode>AllEnabledByDefault</AnalysisMode>
<AnalysisLevel>latest</AnalysisLevel>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="$(MicrosoftNETTestSdkPkgVer)" />
<PackageReference Include="xunit" Version="$(XUnitPkgVer)" />
<PackageReference Include="xunit.runner.visualstudio" Version="$(XUnitRunnerVisualStudioPkgVer)">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers</IncludeAssets>
</PackageReference>
<DotNetCliToolReference Include="dotnet-xunit" Version="$(DotNetXUnitCliVer)" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="$(RepoRoot)\src\OpenTelemetry.Extensions.EventSource\OpenTelemetry.Extensions.EventSource.csproj" />
<ProjectReference Include="$(RepoRoot)\src\OpenTelemetry.Exporter.InMemory\OpenTelemetry.Exporter.InMemory.csproj" />
</ItemGroup>
</Project>

View File

@ -1,328 +0,0 @@
// <copyright file="OpenTelemetryEventSourceLogEmitterTests.cs" company="OpenTelemetry Authors">
// 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.
// </copyright>
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Diagnostics.Tracing;
using System.Globalization;
using Microsoft.Extensions.Logging;
using OpenTelemetry.Logs;
using Xunit;
namespace OpenTelemetry.Extensions.EventSource.Tests
{
public class OpenTelemetryEventSourceLogEmitterTests
{
[Theory]
[InlineData(true)]
[InlineData(false)]
public void OpenTelemetryEventSourceLogEmitterDisposesProviderTests(bool dispose)
{
#pragma warning disable CA2000 // Dispose objects before losing scope
var disposeTrackingProcessor = new DisposeTrackingProcessor();
#pragma warning restore CA2000 // Dispose objects before losing scope
using (var openTelemetryLoggerProvider = Sdk.CreateLoggerProviderBuilder()
.AddProcessor(disposeTrackingProcessor)
.Build())
{
using (var openTelemetryEventSourceLogEmitter = new OpenTelemetryEventSourceLogEmitter(
openTelemetryLoggerProvider,
(name) => null,
disposeProvider: dispose))
{
}
Assert.Equal(dispose, disposeTrackingProcessor.Disposed);
openTelemetryLoggerProvider.Dispose();
}
Assert.True(disposeTrackingProcessor.Disposed);
}
[Theory]
[InlineData(TestEventSource.EventSourceName, EventLevel.LogAlways, 2)]
[InlineData(TestEventSource.EventSourceName, EventLevel.Warning, 1)]
[InlineData("_invalid_", EventLevel.LogAlways, 0)]
public void OpenTelemetryEventSourceLogEmitterFilterTests(string sourceName, EventLevel? eventLevel, int expectedNumberOfLogRecords)
{
List<LogRecord> exportedItems = new();
#pragma warning disable CA2000 // Dispose objects before losing scope
var openTelemetryLoggerProvider = Sdk.CreateLoggerProviderBuilder()
.AddInMemoryExporter(exportedItems)
.Build();
#pragma warning restore CA2000 // Dispose objects before losing scope
using (var openTelemetryEventSourceLogEmitter = new OpenTelemetryEventSourceLogEmitter(
openTelemetryLoggerProvider,
(name) => name == sourceName ? eventLevel : null))
{
TestEventSource.Log.SimpleEvent();
TestEventSource.Log.ComplexEvent("Test_Message", 18);
}
Assert.Equal(expectedNumberOfLogRecords, exportedItems.Count);
}
[Fact]
public void OpenTelemetryEventSourceLogEmitterCapturesExistingSourceTest()
{
List<LogRecord> exportedItems = new();
#pragma warning disable CA2000 // Dispose objects before losing scope
var openTelemetryLoggerProvider = Sdk.CreateLoggerProviderBuilder()
.AddInMemoryExporter(exportedItems)
.Build();
#pragma warning restore CA2000 // Dispose objects before losing scope
TestEventSource.Log.SimpleEvent();
using (var openTelemetryEventSourceLogEmitter = new OpenTelemetryEventSourceLogEmitter(
openTelemetryLoggerProvider,
(name) => name == TestEventSource.EventSourceName ? EventLevel.LogAlways : null))
{
TestEventSource.Log.SimpleEvent();
}
Assert.Single(exportedItems);
}
[Fact]
public void OpenTelemetryEventSourceLogEmitterSimpleEventTest()
{
List<LogRecord> exportedItems = new();
#pragma warning disable CA2000 // Dispose objects before losing scope
var openTelemetryLoggerProvider = Sdk.CreateLoggerProviderBuilder()
.AddInMemoryExporter(exportedItems)
.Build();
#pragma warning restore CA2000 // Dispose objects before losing scope
using (var openTelemetryEventSourceLogEmitter = new OpenTelemetryEventSourceLogEmitter(
openTelemetryLoggerProvider,
(name) => name == TestEventSource.EventSourceName ? EventLevel.LogAlways : null))
{
TestEventSource.Log.SimpleEvent();
}
Assert.Single(exportedItems);
var logRecord = exportedItems[0];
Assert.NotEqual(DateTime.MinValue, logRecord.Timestamp);
Assert.Equal(TestEventSource.SimpleEventMessage, logRecord.FormattedMessage);
Assert.Equal(TestEventSource.SimpleEventId, logRecord.EventId.Id);
Assert.Equal(nameof(TestEventSource.SimpleEvent), logRecord.EventId.Name);
Assert.Equal(LogLevel.Warning, logRecord.LogLevel);
Assert.Null(logRecord.CategoryName);
Assert.Null(logRecord.Exception);
Assert.Equal(default, logRecord.TraceId);
Assert.Equal(default, logRecord.SpanId);
Assert.Null(logRecord.TraceState);
Assert.Equal(ActivityTraceFlags.None, logRecord.TraceFlags);
Assert.NotNull(logRecord.StateValues);
Assert.Contains(logRecord.StateValues, kvp => kvp.Key == "event_source.name" && (string?)kvp.Value == TestEventSource.EventSourceName);
}
[Fact]
public void OpenTelemetryEventSourceLogEmitterSimpleEventWithActivityTest()
{
using var activity = new Activity("Test");
activity.Start();
List<LogRecord> exportedItems = new();
#pragma warning disable CA2000 // Dispose objects before losing scope
var openTelemetryLoggerProvider = Sdk.CreateLoggerProviderBuilder()
.AddInMemoryExporter(exportedItems)
.Build();
#pragma warning restore CA2000 // Dispose objects before losing scope
using (var openTelemetryEventSourceLogEmitter = new OpenTelemetryEventSourceLogEmitter(
openTelemetryLoggerProvider,
(name) => name == TestEventSource.EventSourceName ? EventLevel.LogAlways : null))
{
TestEventSource.Log.SimpleEvent();
}
Assert.Single(exportedItems);
var logRecord = exportedItems[0];
Assert.NotEqual(default, logRecord.TraceId);
Assert.Equal(activity.TraceId, logRecord.TraceId);
Assert.Equal(activity.SpanId, logRecord.SpanId);
Assert.Equal(activity.TraceStateString, logRecord.TraceState);
Assert.Equal(activity.ActivityTraceFlags, logRecord.TraceFlags);
}
[Theory]
[InlineData(true)]
[InlineData(false)]
public void OpenTelemetryEventSourceLogEmitterComplexEventTest(bool formatMessage)
{
List<LogRecord> exportedItems = new();
#pragma warning disable CA2000 // Dispose objects before losing scope
var openTelemetryLoggerProvider = Sdk.CreateLoggerProviderBuilder()
.SetIncludeFormattedMessage(formatMessage)
.AddInMemoryExporter(exportedItems)
.Build();
#pragma warning restore CA2000 // Dispose objects before losing scope
using (var openTelemetryEventSourceLogEmitter = new OpenTelemetryEventSourceLogEmitter(
openTelemetryLoggerProvider,
(name) => name == TestEventSource.EventSourceName ? EventLevel.LogAlways : null))
{
TestEventSource.Log.ComplexEvent("Test_Message", 18);
}
Assert.Single(exportedItems);
var logRecord = exportedItems[0];
Assert.NotEqual(DateTime.MinValue, logRecord.Timestamp);
if (!formatMessage)
{
Assert.Equal(TestEventSource.ComplexEventMessageStructured, logRecord.FormattedMessage);
}
else
{
string expectedMessage = string.Format(CultureInfo.InvariantCulture, TestEventSource.ComplexEventMessage, "Test_Message", 18);
Assert.Equal(expectedMessage, logRecord.FormattedMessage);
}
Assert.Equal(TestEventSource.ComplexEventId, logRecord.EventId.Id);
Assert.Equal(nameof(TestEventSource.ComplexEvent), logRecord.EventId.Name);
Assert.Equal(LogLevel.Information, logRecord.LogLevel);
Assert.Null(logRecord.CategoryName);
Assert.Null(logRecord.Exception);
Assert.Equal(default, logRecord.TraceId);
Assert.Equal(default, logRecord.SpanId);
Assert.Null(logRecord.TraceState);
Assert.Equal(ActivityTraceFlags.None, logRecord.TraceFlags);
Assert.NotNull(logRecord.StateValues);
Assert.Contains(logRecord.StateValues, kvp => kvp.Key == "event_source.name" && (string?)kvp.Value == TestEventSource.EventSourceName);
Assert.Contains(logRecord.StateValues, kvp => kvp.Key == "arg1" && (string?)kvp.Value == "Test_Message");
Assert.Contains(logRecord.StateValues, kvp => kvp.Key == "arg2" && (int?)kvp.Value == 18);
}
[Theory(Skip = "Not runnable in CI, see note.")]
[InlineData(true)]
[InlineData(false)]
public void OpenTelemetryEventSourceLogEmitterActivityIdTest(bool enableTplListener)
{
/*
* Note:
*
* To enable Activity ID the 'System.Threading.Tasks.TplEventSource'
* source must be enabled see:
* https://docs.microsoft.com/en-us/dotnet/core/diagnostics/eventsource-activity-ids#tracking-work-using-an-activity-id
*
* Once enabled, it cannot be turned off:
* https://github.com/dotnet/runtime/blob/0fbdb1ed6e076829e4693a61ae5d11c4cb23e7ee/src/libraries/System.Private.CoreLib/src/System/Diagnostics/Tracing/ActivityTracker.cs#L208
*
* That behavior makes testing it difficult.
*/
using var tplListener = enableTplListener ? new TplEventSourceListener() : null;
List<LogRecord> exportedItems = new();
#pragma warning disable CA2000 // Dispose objects before losing scope
var openTelemetryLoggerProvider = Sdk.CreateLoggerProviderBuilder()
.AddInMemoryExporter(exportedItems)
.Build();
#pragma warning restore CA2000 // Dispose objects before losing scope
using (var openTelemetryEventSourceLogEmitter = new OpenTelemetryEventSourceLogEmitter(
openTelemetryLoggerProvider,
(name) => name == TestEventSource.EventSourceName ? EventLevel.LogAlways : null))
{
TestEventSource.Log.WorkStart();
TestEventSource.Log.SubworkStart();
TestEventSource.Log.SubworkStop();
TestEventSource.Log.WorkStop();
}
Assert.Equal(4, exportedItems.Count);
var logRecord = exportedItems[1];
Assert.NotNull(logRecord.StateValues);
if (enableTplListener)
{
Assert.Contains(logRecord.StateValues, kvp => kvp.Key == "event_source.activity_id");
Assert.Contains(logRecord.StateValues, kvp => kvp.Key == "event_source.related_activity_id");
}
else
{
Assert.DoesNotContain(logRecord.StateValues, kvp => kvp.Key == "event_source.activity_id");
Assert.DoesNotContain(logRecord.StateValues, kvp => kvp.Key == "event_source.related_activity_id");
}
}
private sealed class DisposeTrackingProcessor : BaseProcessor<LogRecord>
{
public bool Disposed { get; private set; }
protected override void Dispose(bool disposing)
{
this.Disposed = true;
base.Dispose(disposing);
}
}
private sealed class TplEventSourceListener : EventListener
{
private readonly List<System.Diagnostics.Tracing.EventSource> eventSources = new();
/// <inheritdoc/>
public override void Dispose()
{
foreach (System.Diagnostics.Tracing.EventSource eventSource in this.eventSources)
{
this.DisableEvents(eventSource);
}
this.eventSources.Clear();
base.Dispose();
}
protected override void OnEventSourceCreated(System.Diagnostics.Tracing.EventSource eventSource)
{
if (eventSource.Name == "System.Threading.Tasks.TplEventSource")
{
// Activity IDs aren't enabled by default.
// Enabling Keyword 0x80 on the TplEventSource turns them on
this.EnableEvents(eventSource, EventLevel.LogAlways, (EventKeywords)0x80);
this.eventSources.Add(eventSource);
}
}
}
}
}

View File

@ -1,65 +0,0 @@
// <copyright file="OpenTelemetryEventSourceLoggerOptionsExtensionsTests.cs" company="OpenTelemetry Authors">
// 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.
// </copyright>
#nullable enable
using System.Collections.Generic;
using System.Diagnostics.Tracing;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using OpenTelemetry.Logs;
using Xunit;
namespace OpenTelemetry.Extensions.EventSource.Tests
{
public class OpenTelemetryEventSourceLoggerOptionsExtensionsTests
{
[Fact]
public void AddOpenTelemetryEventSourceLogEmitterTest()
{
var exportedItems = new List<LogRecord>();
var services = new ServiceCollection();
services.AddLogging(configure =>
{
configure.AddOpenTelemetry(options =>
{
options
.AddInMemoryExporter(exportedItems)
.AddEventSourceLogEmitter((name) => name == TestEventSource.EventSourceName ? EventLevel.LogAlways : null);
});
});
OpenTelemetryEventSourceLoggerOptionsExtensions.EventSourceManager? eventSourceManager = null;
using (var serviceProvider = services.BuildServiceProvider())
{
var loggerFactory = serviceProvider.GetRequiredService<ILoggerFactory>();
eventSourceManager = serviceProvider.GetRequiredService<OpenTelemetryEventSourceLoggerOptionsExtensions.EventSourceManager>();
Assert.Single(eventSourceManager.Emitters);
TestEventSource.Log.SimpleEvent();
}
Assert.Single(exportedItems);
Assert.Empty(eventSourceManager.Emitters);
}
}
}

View File

@ -1,71 +0,0 @@
// <copyright file="TestEventSource.cs" company="OpenTelemetry Authors">
// 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.
// </copyright>
using System.Diagnostics.Tracing;
namespace OpenTelemetry.Extensions.EventSource.Tests
{
[EventSource(Name = TestEventSource.EventSourceName)]
public sealed class TestEventSource : System.Diagnostics.Tracing.EventSource
{
public const string EventSourceName = "OpenTelemetry.Extensions.EventSource.Tests";
public const int SimpleEventId = 1;
public const string SimpleEventMessage = "Warning event with no arguments.";
public const int ComplexEventId = 2;
public const string ComplexEventMessage = "Information event with two arguments: '{0}' & '{1}'.";
public const string ComplexEventMessageStructured = "Information event with two arguments: '{arg1}' & '{arg2}'.";
public static TestEventSource Log { get; } = new();
[Event(SimpleEventId, Message = SimpleEventMessage, Level = EventLevel.Warning)]
public void SimpleEvent()
{
this.WriteEvent(SimpleEventId);
}
[Event(ComplexEventId, Message = ComplexEventMessage, Level = EventLevel.Informational)]
public void ComplexEvent(string arg1, int arg2)
{
this.WriteEvent(ComplexEventId, arg1, arg2);
}
[Event(3, Level = EventLevel.Verbose)]
public void WorkStart()
{
this.WriteEvent(3);
}
[Event(4, Level = EventLevel.Verbose)]
public void WorkStop()
{
this.WriteEvent(4);
}
[Event(5, Level = EventLevel.Verbose)]
public void SubworkStart()
{
this.WriteEvent(5);
}
[Event(6, Level = EventLevel.Verbose)]
public void SubworkStop()
{
this.WriteEvent(6);
}
}
}

View File

@ -1,19 +0,0 @@
// <copyright file="AssemblyInfo.cs" company="OpenTelemetry Authors">
// 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.
// </copyright>
using System;
[assembly: CLSCompliant(false)]

View File

@ -1,27 +0,0 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<Description>Unit test project for OpenTelemetry Serilog extensions</Description>
<!-- OmniSharp/VS Code requires TargetFrameworks to be in descending order for IntelliSense and analysis. -->
<TargetFrameworks>net6.0</TargetFrameworks>
<TargetFrameworks Condition="$(OS) == 'Windows_NT'">$(TargetFrameworks);net462</TargetFrameworks>
<Nullable>enable</Nullable>
<AnalysisMode>AllEnabledByDefault</AnalysisMode>
<AnalysisLevel>latest</AnalysisLevel>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="$(MicrosoftNETTestSdkPkgVer)" />
<PackageReference Include="xunit" Version="$(XUnitPkgVer)" />
<PackageReference Include="xunit.runner.visualstudio" Version="$(XUnitRunnerVisualStudioPkgVer)">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers</IncludeAssets>
</PackageReference>
<DotNetCliToolReference Include="dotnet-xunit" Version="$(DotNetXUnitCliVer)" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="$(RepoRoot)\src\OpenTelemetry.Extensions.Serilog\OpenTelemetry.Extensions.Serilog.csproj" />
<ProjectReference Include="$(RepoRoot)\src\OpenTelemetry.Exporter.InMemory\OpenTelemetry.Exporter.InMemory.csproj" />
</ItemGroup>
</Project>

View File

@ -1,285 +0,0 @@
// <copyright file="OpenTelemetrySerilogSinkTests.cs" company="OpenTelemetry Authors">
// 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.
// </copyright>
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using Microsoft.Extensions.Logging;
using OpenTelemetry.Logs;
using Serilog;
using Xunit;
using ILogger = Serilog.ILogger;
namespace OpenTelemetry.Extensions.Serilog.Tests
{
public class OpenTelemetrySerilogSinkTests
{
[Theory]
[InlineData(true)]
[InlineData(false)]
public void SerilogDisposesProviderTests(bool dispose)
{
#pragma warning disable CA2000 // Dispose objects before losing scope
var disposeTrackingProcessor = new DisposeTrackingProcessor();
#pragma warning restore CA2000 // Dispose objects before losing scope
using (var openTelemetryLoggerProvider = Sdk.CreateLoggerProviderBuilder()
.AddProcessor(disposeTrackingProcessor)
.Build())
{
Log.Logger = new LoggerConfiguration()
.WriteTo.OpenTelemetry(openTelemetryLoggerProvider, disposeProvider: dispose)
.CreateLogger();
Log.CloseAndFlush();
Assert.Equal(dispose, disposeTrackingProcessor.Disposed);
}
Assert.True(disposeTrackingProcessor.Disposed);
}
[Theory]
[InlineData(true)]
[InlineData(false)]
public void SerilogBasicLogTests(bool includeFormattedMessage)
{
List<LogRecord> exportedItems = new();
#pragma warning disable CA2000 // Dispose objects before losing scope
var openTelemetryLoggerProvider = Sdk.CreateLoggerProviderBuilder()
.SetIncludeFormattedMessage(includeFormattedMessage)
.AddInMemoryExporter(exportedItems)
.Build();
#pragma warning restore CA2000 // Dispose objects before losing scope
Log.Logger = new LoggerConfiguration()
.WriteTo.OpenTelemetry(openTelemetryLoggerProvider, disposeProvider: true)
.CreateLogger();
Log.Logger.Information("Hello {greeting}", "World");
Log.CloseAndFlush();
Assert.Single(exportedItems);
LogRecord logRecord = exportedItems[0];
if (!includeFormattedMessage)
{
Assert.Equal("Hello {greeting}", logRecord.FormattedMessage);
}
else
{
Assert.Equal("Hello \"World\"", logRecord.FormattedMessage);
}
Assert.NotEqual(DateTime.MinValue, logRecord.Timestamp);
Assert.Equal(DateTimeKind.Utc, logRecord.Timestamp.Kind);
Assert.Equal(LogLevel.Information, logRecord.LogLevel);
Assert.Null(logRecord.CategoryName);
Assert.NotNull(logRecord.StateValues);
Assert.Single(logRecord.StateValues);
Assert.Contains(logRecord.StateValues, kvp => kvp.Key == "greeting" && (string?)kvp.Value == "World");
Assert.Equal(default, logRecord.TraceId);
Assert.Equal(default, logRecord.SpanId);
Assert.Null(logRecord.TraceState);
Assert.Equal(ActivityTraceFlags.None, logRecord.TraceFlags);
}
[Fact]
public void SerilogBasicLogWithActivityTest()
{
using var activity = new Activity("Test");
activity.Start();
List<LogRecord> exportedItems = new();
#pragma warning disable CA2000 // Dispose objects before losing scope
var openTelemetryLoggerProvider = Sdk.CreateLoggerProviderBuilder()
.AddInMemoryExporter(exportedItems)
.Build();
#pragma warning restore CA2000 // Dispose objects before losing scope
Log.Logger = new LoggerConfiguration()
.WriteTo.OpenTelemetry(openTelemetryLoggerProvider, disposeProvider: true)
.CreateLogger();
Log.Logger.Information("Hello {greeting}", "World");
Log.CloseAndFlush();
Assert.Single(exportedItems);
var logRecord = exportedItems[0];
Assert.NotEqual(default, logRecord.TraceId);
Assert.Equal(activity.TraceId, logRecord.TraceId);
Assert.Equal(activity.SpanId, logRecord.SpanId);
Assert.Equal(activity.TraceStateString, logRecord.TraceState);
Assert.Equal(activity.ActivityTraceFlags, logRecord.TraceFlags);
}
[Fact]
public void SerilogCategoryNameTest()
{
List<LogRecord> exportedItems = new();
#pragma warning disable CA2000 // Dispose objects before losing scope
var openTelemetryLoggerProvider = Sdk.CreateLoggerProviderBuilder()
.AddInMemoryExporter(exportedItems)
.Build();
#pragma warning restore CA2000 // Dispose objects before losing scope
Log.Logger = new LoggerConfiguration()
.WriteTo.OpenTelemetry(openTelemetryLoggerProvider, disposeProvider: true)
.CreateLogger();
// Note: Serilog ForContext API is used to set "CategoryName" on log messages
ILogger logger = Log.Logger.ForContext<OpenTelemetrySerilogSinkTests>();
logger.Information("Hello {greeting}", "World");
Log.CloseAndFlush();
Assert.Single(exportedItems);
LogRecord logRecord = exportedItems[0];
Assert.Equal("OpenTelemetry.Extensions.Serilog.Tests.OpenTelemetrySerilogSinkTests", logRecord.CategoryName);
}
[Fact]
public void SerilogComplexMessageTemplateTest()
{
List<LogRecord> exportedItems = new();
#pragma warning disable CA2000 // Dispose objects before losing scope
var openTelemetryLoggerProvider = Sdk.CreateLoggerProviderBuilder()
.AddInMemoryExporter(exportedItems)
.Build();
#pragma warning restore CA2000 // Dispose objects before losing scope
Log.Logger = new LoggerConfiguration()
.WriteTo.OpenTelemetry(openTelemetryLoggerProvider, disposeProvider: true)
.CreateLogger();
ComplexType complexType = new();
Log.Logger.Information("Hello {greeting} {id} {@complexObj} {$complexStr}", "World", 18, complexType, complexType);
Log.CloseAndFlush();
Assert.Single(exportedItems);
LogRecord logRecord = exportedItems[0];
Assert.NotNull(logRecord.StateValues);
Assert.Equal(3, logRecord.StateValues!.Count); // Note: complexObj is currently not supported/ignored.
Assert.Contains(logRecord.StateValues, kvp => kvp.Key == "greeting" && (string?)kvp.Value == "World");
Assert.Contains(logRecord.StateValues, kvp => kvp.Key == "id" && (int?)kvp.Value == 18);
Assert.Contains(logRecord.StateValues, kvp => kvp.Key == "complexStr" && (string?)kvp.Value == "ComplexTypeToString");
}
[Fact]
public void SerilogArrayMessageTemplateTest()
{
List<LogRecord> exportedItems = new();
#pragma warning disable CA2000 // Dispose objects before losing scope
var openTelemetryLoggerProvider = Sdk.CreateLoggerProviderBuilder()
.AddInMemoryExporter(exportedItems)
.Build();
#pragma warning restore CA2000 // Dispose objects before losing scope
Log.Logger = new LoggerConfiguration()
.WriteTo.OpenTelemetry(openTelemetryLoggerProvider, disposeProvider: true)
.CreateLogger();
ComplexType complexType = new();
var intArray = new int[] { 0, 1, 2, 3, 4 };
var mixedArray = new object?[] { 0, null, "3", 18.0D };
Log.Logger.Information("Int array {data}", intArray);
Log.Logger.Information("Mixed array {data}", new object[] { mixedArray });
Log.CloseAndFlush();
Assert.Equal(2, exportedItems.Count);
LogRecord logRecord = exportedItems[0];
Assert.NotNull(logRecord.StateValues);
Assert.Contains(logRecord.StateValues, kvp => kvp.Key == "data" && kvp.Value is int[] typedArray && intArray.SequenceEqual(typedArray));
logRecord = exportedItems[1];
Assert.NotNull(logRecord.StateValues);
Assert.Contains(logRecord.StateValues, kvp => kvp.Key == "data" && kvp.Value is object?[] typedArray && mixedArray.SequenceEqual(typedArray));
}
[Fact]
public void SerilogExceptionTest()
{
List<LogRecord> exportedItems = new();
InvalidOperationException ex = new();
#pragma warning disable CA2000 // Dispose objects before losing scope
var openTelemetryLoggerProvider = Sdk.CreateLoggerProviderBuilder()
.AddInMemoryExporter(exportedItems)
.Build();
#pragma warning restore CA2000 // Dispose objects before losing scope
Log.Logger = new LoggerConfiguration()
.WriteTo.OpenTelemetry(openTelemetryLoggerProvider, disposeProvider: true)
.CreateLogger();
ComplexType complexType = new();
Log.Logger.Information(ex, "Exception");
Log.CloseAndFlush();
Assert.Single(exportedItems);
LogRecord logRecord = exportedItems[0];
Assert.Equal(ex, logRecord.Exception);
}
private sealed class DisposeTrackingProcessor : BaseProcessor<LogRecord>
{
public bool Disposed { get; private set; }
protected override void Dispose(bool disposing)
{
this.Disposed = true;
base.Dispose(disposing);
}
}
private sealed class ComplexType
{
public override string ToString() => "ComplexTypeToString";
}
}
}

View File

@ -1,173 +0,0 @@
// <copyright file="LogEmitterTests.cs" company="OpenTelemetry Authors">
// 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.
// </copyright>
using System;
using System.Collections.Generic;
using System.Diagnostics;
using Microsoft.Extensions.Logging;
using Xunit;
namespace OpenTelemetry.Logs.Tests
{
public sealed class LogEmitterTests
{
[Fact]
public void LogEmitterBasicTest()
{
var exportedItems = new List<LogRecord>();
using var provider = Sdk.CreateLoggerProviderBuilder()
.AddInMemoryExporter(exportedItems)
.Build();
var logEmitter = provider.CreateEmitter();
Exception ex = new InvalidOperationException();
logEmitter.Emit(
new()
{
CategoryName = "LogEmitter",
Message = "Hello world",
LogLevel = LogLevel.Warning,
EventId = new EventId(18, "CustomEvent"),
Exception = ex,
},
new()
{
["key1"] = "value1",
["key2"] = "value2",
});
Assert.Single(exportedItems);
var logRecord = exportedItems[0];
Assert.NotNull(logRecord);
Assert.Equal("LogEmitter", logRecord.CategoryName);
Assert.Equal("Hello world", logRecord.FormattedMessage);
Assert.Equal(LogLevel.Warning, logRecord.LogLevel);
Assert.Equal(18, logRecord.EventId.Id);
Assert.Equal("CustomEvent", logRecord.EventId.Name);
Assert.Equal(ex, logRecord.Exception);
Assert.NotEqual(DateTime.MinValue, logRecord.Timestamp);
Assert.Equal(default, logRecord.TraceId);
Assert.Equal(default, logRecord.SpanId);
Assert.Equal(ActivityTraceFlags.None, logRecord.TraceFlags);
Assert.Null(logRecord.TraceState);
Assert.NotNull(logRecord.StateValues);
Assert.Equal(2, logRecord.StateValues.Count);
Assert.Contains(logRecord.StateValues, item => item.Key == "key1" && (string)item.Value == "value1");
Assert.Contains(logRecord.StateValues, item => item.Key == "key2" && (string)item.Value == "value2");
}
[Fact]
public void LogEmitterFromActivityTest()
{
var exportedItems = new List<LogRecord>();
using var provider = Sdk.CreateLoggerProviderBuilder()
.AddInMemoryExporter(exportedItems)
.Build();
var logEmitter = provider.CreateEmitter();
using var activity = new Activity("Test");
activity.Start();
activity.ActivityTraceFlags = ActivityTraceFlags.Recorded;
activity.TraceStateString = "key1=value1";
logEmitter.Emit(new(activity));
Assert.Single(exportedItems);
var logRecord = exportedItems[0];
Assert.NotNull(logRecord);
Assert.Equal(activity.TraceId, logRecord.TraceId);
Assert.Equal(activity.SpanId, logRecord.SpanId);
Assert.Equal(activity.ActivityTraceFlags, logRecord.TraceFlags);
Assert.Equal(activity.TraceStateString, logRecord.TraceState);
Assert.Null(logRecord.StateValues);
}
[Fact]
public void LogEmitterLocalToUtcTimestampTest()
{
var exportedItems = new List<LogRecord>();
using var provider = Sdk.CreateLoggerProviderBuilder()
.AddInMemoryExporter(exportedItems)
.Build();
var logEmitter = provider.CreateEmitter();
DateTime timestamp = DateTime.SpecifyKind(
new DateTime(2022, 6, 30, 16, 0, 0),
DateTimeKind.Local);
logEmitter.Emit(new()
{
Timestamp = timestamp,
});
Assert.Single(exportedItems);
var logRecord = exportedItems[0];
Assert.NotNull(logRecord);
Assert.Equal(timestamp.ToUniversalTime(), logRecord.Timestamp);
Assert.Equal(DateTimeKind.Utc, logRecord.Timestamp.Kind);
}
[Fact]
public void LogEmitterUnspecifiedTimestampTest()
{
var exportedItems = new List<LogRecord>();
using var provider = Sdk.CreateLoggerProviderBuilder()
.AddInMemoryExporter(exportedItems)
.Build();
var logEmitter = provider.CreateEmitter();
DateTime timestamp = DateTime.SpecifyKind(
new DateTime(2022, 6, 30, 16, 0, 0),
DateTimeKind.Unspecified);
logEmitter.Emit(new()
{
Timestamp = timestamp,
});
Assert.Single(exportedItems);
var logRecord = exportedItems[0];
Assert.NotNull(logRecord);
Assert.Equal(timestamp, logRecord.Timestamp);
Assert.Equal(DateTimeKind.Unspecified, logRecord.Timestamp.Kind);
}
}
}

View File

@ -14,7 +14,6 @@
// limitations under the License.
// </copyright>
using Microsoft.Extensions.DependencyInjection;
using Xunit;
namespace OpenTelemetry.Logs.Tests
@ -26,18 +25,13 @@ namespace OpenTelemetry.Logs.Tests
[InlineData(false)]
public void VerifyOptionsCannotBeChangedAfterInit(bool initialValue)
{
OpenTelemetryLoggerOptions options = null;
using var provider = Sdk.CreateLoggerProviderBuilder()
.ConfigureServices(services => services.Configure<OpenTelemetryLoggerOptions>(o =>
{
options = o;
o.IncludeFormattedMessage = initialValue;
o.IncludeScopes = initialValue;
o.ParseStateValues = initialValue;
}))
.Build();
var options = new OpenTelemetryLoggerOptions
{
IncludeFormattedMessage = initialValue,
IncludeScopes = initialValue,
ParseStateValues = initialValue,
};
var provider = new OpenTelemetryLoggerProvider(options);
// Verify initial set
Assert.Equal(initialValue, provider.IncludeFormattedMessage);

View File

@ -1,119 +0,0 @@
// <copyright file="OpenTelemetryLoggerOptionsSdkTests.cs" company="OpenTelemetry Authors">
// 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.
// </copyright>
#nullable enable
using System;
using System.Collections.Generic;
using Microsoft.Extensions.DependencyInjection;
using OpenTelemetry.Resources;
using Xunit;
namespace OpenTelemetry.Logs.Tests;
public class OpenTelemetryLoggerOptionsSdkTests
{
[Fact]
public void CreateLoggerProviderBuilderBuildValidProviderTest()
{
List<LogRecord> exportedItems = new();
using var provider = Sdk.CreateLoggerProviderBuilder()
.AddInMemoryExporter(exportedItems)
.Build();
Assert.NotNull(provider);
provider.CreateEmitter().Emit(new()
{
Message = "Hello world",
});
Assert.Single(exportedItems);
}
[Fact]
public void CreateLoggerProviderBuilderExtensionPointsTest()
{
int optionsConfigureInvocations = 0;
OpenTelemetryLoggerProvider? providerFromConfigureCallback = null;
var returnedOptions = Sdk.CreateLoggerProviderBuilder()
.AddProcessor(new CustomProcessor())
.AddProcessor<CustomProcessor>()
.ConfigureServices(services =>
{
services.AddSingleton<TestClass1>();
services.Configure<OpenTelemetryLoggerOptions>(o =>
{
optionsConfigureInvocations++;
Assert.Null(o.Services);
Assert.Throws<NotSupportedException>(() => o.ConfigureServices(s => { }));
o.ConfigureResource(r => r.AddAttributes(new Dictionary<string, object> { ["key1"] = "value1" }));
o.ConfigureProvider((sp, p) => optionsConfigureInvocations++);
});
})
.ConfigureProvider((sp, p) =>
{
Assert.NotNull(sp);
providerFromConfigureCallback = p;
Assert.NotNull(sp.GetService<TestClass1>());
});
using var provider = returnedOptions.Build();
Assert.NotNull(provider);
Assert.Throws<NotSupportedException>(() => returnedOptions.ConfigureServices(s => { }));
Assert.Throws<NotSupportedException>(() => returnedOptions.ConfigureResource(r => { }));
Assert.Throws<NotSupportedException>(() => returnedOptions.ConfigureProvider((sp, p) => { }));
Assert.Throws<NotSupportedException>(() => returnedOptions.Build());
Assert.Equal(2, optionsConfigureInvocations);
Assert.NotNull(providerFromConfigureCallback);
Assert.Equal(provider, providerFromConfigureCallback);
Assert.NotNull(provider.Resource?.Attributes);
Assert.Contains(provider.Resource!.Attributes, kvp => kvp.Key == "key1" && (string)kvp.Value == "value1");
var processor = provider.Processor as CompositeProcessor<LogRecord>;
Assert.NotNull(processor);
int count = 0;
var current = processor?.Head;
while (current != null)
{
count++;
current = current.Next;
}
Assert.Equal(2, count);
}
private sealed class TestClass1
{
}
private sealed class CustomProcessor : BaseProcessor<LogRecord>
{
}
}

View File

@ -16,7 +16,6 @@
using System.Collections.Generic;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
using OpenTelemetry.Exporter;
using OpenTelemetry.Resources;
using Xunit;
@ -44,15 +43,18 @@ namespace OpenTelemetry.Logs.Tests
{
OpenTelemetryLoggerOptions defaults = new();
using OpenTelemetryLoggerProvider provider = Sdk.CreateLoggerProviderBuilder()
.SetIncludeScopes(!defaults.IncludeScopes)
.SetIncludeFormattedMessage(!defaults.IncludeFormattedMessage)
.SetParseStateValues(!defaults.ParseStateValues)
.SetResourceBuilder(ResourceBuilder
using OpenTelemetryLoggerProvider provider = new(options =>
{
options.IncludeScopes = !defaults.IncludeScopes;
options.IncludeFormattedMessage = !defaults.IncludeFormattedMessage;
options.ParseStateValues = !defaults.ParseStateValues;
options.SetResourceBuilder(ResourceBuilder
.CreateEmpty()
.AddAttributes(new[] { new KeyValuePair<string, object>("key1", "value1") }))
.AddInMemoryExporter(new List<LogRecord>())
.Build();
.AddAttributes(new[] { new KeyValuePair<string, object>("key1", "value1") }));
options.AddInMemoryExporter(new List<LogRecord>());
});
Assert.Equal(!defaults.IncludeScopes, provider.IncludeScopes);
Assert.Equal(!defaults.IncludeFormattedMessage, provider.IncludeFormattedMessage);
@ -87,20 +89,20 @@ namespace OpenTelemetry.Logs.Tests
[Fact]
public void ThreadStaticPoolUsedByProviderTests()
{
using var provider1 = new OpenTelemetryLoggerProvider();
using var provider1 = new OpenTelemetryLoggerProvider(new OpenTelemetryLoggerOptions());
Assert.Equal(LogRecordThreadStaticPool.Instance, provider1.LogRecordPool);
using var provider2 = Sdk.CreateLoggerProviderBuilder()
.AddProcessor(new SimpleLogRecordExportProcessor(new NoopExporter()))
.Build();
var options = new OpenTelemetryLoggerOptions();
options.AddProcessor(new SimpleLogRecordExportProcessor(new NoopExporter()));
using var provider2 = new OpenTelemetryLoggerProvider(options);
Assert.Equal(LogRecordThreadStaticPool.Instance, provider2.LogRecordPool);
using var provider3 = Sdk.CreateLoggerProviderBuilder()
.AddProcessor(new SimpleLogRecordExportProcessor(new NoopExporter()))
.AddProcessor(new SimpleLogRecordExportProcessor(new NoopExporter()))
.Build();
options.AddProcessor(new SimpleLogRecordExportProcessor(new NoopExporter()));
using var provider3 = new OpenTelemetryLoggerProvider(options);
Assert.Equal(LogRecordThreadStaticPool.Instance, provider3.LogRecordPool);
}
@ -108,27 +110,30 @@ namespace OpenTelemetry.Logs.Tests
[Fact]
public void SharedPoolUsedByProviderTests()
{
using var provider1 = Sdk.CreateLoggerProviderBuilder()
.AddProcessor(new BatchLogRecordExportProcessor(new NoopExporter()))
.Build();
var options = new OpenTelemetryLoggerOptions();
options.AddProcessor(new BatchLogRecordExportProcessor(new NoopExporter()));
using var provider1 = new OpenTelemetryLoggerProvider(options);
Assert.Equal(LogRecordSharedPool.Current, provider1.LogRecordPool);
using var provider2 = Sdk.CreateLoggerProviderBuilder()
.AddProcessor(new SimpleLogRecordExportProcessor(new NoopExporter()))
.AddProcessor(new BatchLogRecordExportProcessor(new NoopExporter()))
.Build();
options = new OpenTelemetryLoggerOptions();
options.AddProcessor(new SimpleLogRecordExportProcessor(new NoopExporter()));
options.AddProcessor(new BatchLogRecordExportProcessor(new NoopExporter()));
using var provider2 = new OpenTelemetryLoggerProvider(options);
Assert.Equal(LogRecordSharedPool.Current, provider2.LogRecordPool);
using var provider3 = Sdk.CreateLoggerProviderBuilder()
.AddProcessor(new SimpleLogRecordExportProcessor(new NoopExporter()))
.AddProcessor(new CompositeProcessor<LogRecord>(new BaseProcessor<LogRecord>[]
{
new SimpleLogRecordExportProcessor(new NoopExporter()),
new BatchLogRecordExportProcessor(new NoopExporter()),
}))
.Build();
options = new OpenTelemetryLoggerOptions();
options.AddProcessor(new SimpleLogRecordExportProcessor(new NoopExporter()));
options.AddProcessor(new CompositeProcessor<LogRecord>(new BaseProcessor<LogRecord>[]
{
new SimpleLogRecordExportProcessor(new NoopExporter()),
new BatchLogRecordExportProcessor(new NoopExporter()),
}));
using var provider3 = new OpenTelemetryLoggerProvider(options);
Assert.Equal(LogRecordSharedPool.Current, provider3.LogRecordPool);
}

View File

@ -16,11 +16,8 @@
#nullable enable
using System.Collections.Generic;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
using OpenTelemetry.Resources;
using Xunit;
namespace OpenTelemetry.Logs.Tests;
@ -28,7 +25,7 @@ namespace OpenTelemetry.Logs.Tests;
public sealed class OpenTelemetryLoggingExtensionsTests
{
[Fact]
public void LoggingBuilderAddOpenTelemetryNoParametersTest()
public void ServiceCollectionAddOpenTelemetryNoParametersTest()
{
bool optionsCallbackInvoked = false;
@ -54,9 +51,10 @@ public sealed class OpenTelemetryLoggingExtensionsTests
}
[Theory]
[InlineData(1)]
[InlineData(5)]
public void LoggingBuilderAddOpenTelemetryConfigureActionTests(int numberOfOptionsRegistrations)
[InlineData(1, 0)]
[InlineData(1, 1)]
[InlineData(5, 5)]
public void ServiceCollectionAddOpenTelemetryConfigureActionTests(int numberOfBuilderRegistrations, int numberOfOptionsRegistrations)
{
int configureCallbackInvocations = 0;
int optionsCallbackInvocations = 0;
@ -66,8 +64,10 @@ public sealed class OpenTelemetryLoggingExtensionsTests
serviceCollection.AddLogging(configure =>
{
configure.AddOpenTelemetry(); // <- Just to verify this doesn't cause a throw.
configure.AddOpenTelemetry(ConfigureCallback);
for (int i = 0; i < numberOfBuilderRegistrations; i++)
{
configure.AddOpenTelemetry(ConfigureCallback);
}
});
for (int i = 0; i < numberOfOptionsRegistrations; i++)
@ -75,17 +75,15 @@ public sealed class OpenTelemetryLoggingExtensionsTests
serviceCollection.Configure<OpenTelemetryLoggerOptions>(OptionsCallback);
}
Assert.NotNull(optionsInstance);
using ServiceProvider serviceProvider = serviceCollection.BuildServiceProvider();
optionsInstance = null;
ILoggerFactory? loggerFactory = serviceProvider.GetService<ILoggerFactory>();
Assert.NotNull(loggerFactory);
Assert.Equal(1, configureCallbackInvocations);
Assert.NotNull(optionsInstance);
Assert.Equal(numberOfBuilderRegistrations, configureCallbackInvocations);
Assert.Equal(numberOfOptionsRegistrations, optionsCallbackInvocations);
void ConfigureCallback(OpenTelemetryLoggerOptions options)
@ -96,8 +94,7 @@ public sealed class OpenTelemetryLoggingExtensionsTests
}
else
{
// Note: In the callback phase each options instance is unique
Assert.NotEqual(optionsInstance, options);
Assert.Equal(optionsInstance, options);
}
configureCallbackInvocations++;
@ -111,518 +108,10 @@ public sealed class OpenTelemetryLoggingExtensionsTests
}
else
{
// Note: In the options phase each instance is the same
Assert.Equal(optionsInstance, options);
}
optionsCallbackInvocations++;
}
}
[Fact]
public void LoggingBuilderAddOpenTelemetryMultipleBuildersTest()
{
var serviceCollection = new ServiceCollection();
OpenTelemetryLoggerProvider? provider = null;
serviceCollection.AddLogging(configure =>
{
configure.AddOpenTelemetry(options
=> options.ConfigureResource(
r => r.AddAttributes(new Dictionary<string, object>() { ["key1"] = "value1" })));
configure.AddOpenTelemetry(options
=> options.ConfigureResource(
r => r.AddAttributes(new Dictionary<string, object>() { ["key2"] = "value2" })));
configure.AddOpenTelemetry(options
=> options.ConfigureProvider((sp, p) => provider = p));
});
using ServiceProvider serviceProvider = serviceCollection.BuildServiceProvider();
var loggerFactory = serviceProvider.GetService<ILoggerFactory>();
Assert.NotNull(loggerFactory);
Assert.NotNull(provider);
Assert.Contains(provider!.Resource.Attributes, kvp => kvp.Key == "key1" && (string)kvp.Value == "value1");
Assert.Contains(provider!.Resource.Attributes, kvp => kvp.Key == "key2" && (string)kvp.Value == "value2");
}
[Fact]
public void LoggingBuilderAddOpenTelemetryWithProviderTest()
{
var provider = new WrappedOpenTelemetryLoggerProvider();
var serviceCollection = new ServiceCollection();
serviceCollection.AddLogging(configure =>
{
configure.AddOpenTelemetry(provider);
});
using (ServiceProvider serviceProvider = serviceCollection.BuildServiceProvider())
{
ILoggerFactory? loggerFactory = serviceProvider.GetService<ILoggerFactory>();
Assert.NotNull(loggerFactory);
loggerFactory!.Dispose();
// Note: Provider disposal does not actually happen until serviceProvider is disposed
Assert.False(provider.Disposed);
}
Assert.True(provider.Disposed);
}
[Theory]
[InlineData(true)]
[InlineData(false)]
public void LoggingBuilderAddOpenTelemetryWithProviderAndDisposeSpecifiedTests(bool dispose)
{
var provider = new WrappedOpenTelemetryLoggerProvider();
var serviceCollection = new ServiceCollection();
serviceCollection.AddLogging(configure =>
{
configure.AddOpenTelemetry(provider, disposeProvider: dispose);
});
using (ServiceProvider serviceProvider = serviceCollection.BuildServiceProvider())
{
ILoggerFactory? loggerFactory = serviceProvider.GetService<ILoggerFactory>();
Assert.NotNull(loggerFactory);
loggerFactory!.Dispose();
// Note: Provider disposal does not actually happen until serviceProvider is disposed
Assert.False(provider.Disposed);
}
Assert.Equal(dispose, provider.Disposed);
provider.Dispose();
Assert.True(provider.Disposed);
}
[Theory]
[InlineData(true)]
[InlineData(false)]
public void LoggerFactoryCreateAddOpenTelemetryWithProviderAndDisposeSpecifiedTests(bool dispose)
{
var provider = new WrappedOpenTelemetryLoggerProvider();
using (var factory = LoggerFactory.Create(configure =>
{
configure.AddOpenTelemetry(provider, disposeProvider: dispose);
}))
{
Assert.False(provider.Disposed);
}
Assert.Equal(dispose, provider.Disposed);
provider.Dispose();
Assert.True(provider.Disposed);
}
[Fact]
public void LoggingBuilderAddOpenTelemetryServicesAvailableTest()
{
int invocationCount = 0;
var services = new ServiceCollection();
services.AddLogging(configure =>
{
configure.AddOpenTelemetry(options =>
{
invocationCount++;
Assert.NotNull(options.Services);
});
});
services.Configure<OpenTelemetryLoggerOptions>(options =>
{
invocationCount++;
// Note: Services are no longer available once OpenTelemetryLoggerOptions has been created
Assert.Null(options.Services);
});
using var serviceProvider = services.BuildServiceProvider();
var loggerFactory = serviceProvider.GetRequiredService<ILoggerFactory>();
Assert.Equal(2, invocationCount);
}
[Fact]
public void LoggingBuilderAddOpenTelemetryProcessorThroughDependencyTest()
{
CustomProcessor.InstanceCount = 0;
var services = new ServiceCollection();
services.AddLogging(configure =>
{
configure.AddOpenTelemetry(options =>
{
options.AddProcessor<CustomProcessor>();
});
});
CustomProcessor? customProcessor = null;
using (var serviceProvider = services.BuildServiceProvider())
{
var loggerFactory = serviceProvider.GetRequiredService<ILoggerFactory>();
customProcessor = serviceProvider.GetRequiredService<CustomProcessor>();
Assert.NotNull(customProcessor);
loggerFactory.Dispose();
Assert.False(customProcessor!.Disposed);
}
Assert.True(customProcessor.Disposed);
Assert.Equal(1, CustomProcessor.InstanceCount);
}
[Fact]
public void LoggingBuilderAddOpenTelemetryConfigureCallbackTest()
{
var services = new ServiceCollection();
services.AddSingleton<TestClass>();
CustomProcessor? customProcessor = null;
services.AddLogging(configure =>
{
configure.AddOpenTelemetry(options =>
{
options.ConfigureProvider((sp, provider) =>
{
var testClass = sp.GetRequiredService<TestClass>();
customProcessor = new CustomProcessor
{
TestClass = testClass,
};
provider.AddProcessor(customProcessor);
});
});
});
using var serviceProvider = services.BuildServiceProvider();
var loggerFactory = serviceProvider.GetRequiredService<ILoggerFactory>();
Assert.NotNull(customProcessor?.TestClass);
}
[Fact]
public void LoggingBuilderAddOpenTelemetryOptionsOrderingTest()
{
int configureInvocationCount = 0;
var services = new ServiceCollection();
OpenTelemetryLoggerProvider? provider = null;
services.Configure<OpenTelemetryLoggerOptions>(options =>
{
// Note: This will be applied first to the final options
options.IncludeFormattedMessage = true;
options.IncludeScopes = true;
options.ParseStateValues = true;
options.AddProcessor(new CustomProcessor(0));
options.ConfigureProvider((sp, p) =>
{
Assert.Null(provider);
provider = p;
configureInvocationCount++;
});
});
services.AddLogging(configure =>
{
configure.AddOpenTelemetry(options =>
{
// Note: This will run first, but be applied second to the final options
options.IncludeFormattedMessage = false;
options.ParseStateValues = false;
options.AddProcessor(new CustomProcessor(1));
options.ConfigureProvider((sp, p) =>
{
configureInvocationCount++;
Assert.NotNull(provider);
Assert.Equal(provider, p);
});
});
});
services.Configure<OpenTelemetryLoggerOptions>(options =>
{
// Note: This will be applied last to the final options
options.ParseStateValues = true;
options.AddProcessor(new CustomProcessor(2));
options.ConfigureProvider((sp, p) =>
{
configureInvocationCount++;
Assert.NotNull(provider);
Assert.Equal(provider, p);
});
});
using var serviceProvider = services.BuildServiceProvider();
var loggerFactory = serviceProvider.GetRequiredService<ILoggerFactory>();
Assert.NotNull(provider);
Assert.Equal(3, configureInvocationCount);
var finalOptions = serviceProvider.GetRequiredService<IOptionsMonitor<OpenTelemetryLoggerOptions>>().CurrentValue;
Assert.False(finalOptions.IncludeFormattedMessage);
Assert.True(finalOptions.IncludeScopes);
Assert.True(finalOptions.ParseStateValues);
var processor = provider!.Processor as CompositeProcessor<LogRecord>;
Assert.NotNull(processor);
int count = 0;
var current = processor!.Head;
while (current != null)
{
var instance = current.Value as CustomProcessor;
Assert.Equal(count, instance?.Id);
count++;
current = current.Next;
}
Assert.Equal(3, count);
}
[Fact]
public void LoggingBuilderAddOpenTelemetryResourceTest()
{
var services = new ServiceCollection();
OpenTelemetryLoggerProvider? provider = null;
services.AddLogging(configure =>
{
configure.AddOpenTelemetry(options =>
{
options.SetResourceBuilder(ResourceBuilder.CreateDefault().AddService("Examples.LoggingExtensions"));
options.ConfigureProvider((sp, p) => provider = p);
});
});
services.Configure<OpenTelemetryLoggerOptions>(options =>
{
options.ConfigureResource(builder => builder.AddAttributes(new Dictionary<string, object> { ["key1"] = "value1" }));
});
services.Configure<OpenTelemetryLoggerOptions>(options =>
{
options.ConfigureResource(builder => builder.AddAttributes(new Dictionary<string, object> { ["key2"] = "value2" }));
});
using var serviceProvider = services.BuildServiceProvider();
var loggerFactory = serviceProvider.GetRequiredService<ILoggerFactory>();
Assert.NotNull(provider);
var resource = provider!.Resource;
Assert.NotNull(resource);
Assert.Contains(resource.Attributes, kvp => kvp.Key == "service.name");
Assert.Contains(resource.Attributes, kvp => kvp.Key == "service.instance.id");
Assert.Contains(resource.Attributes, kvp => kvp.Key == "key1");
Assert.Contains(resource.Attributes, kvp => kvp.Key == "key2");
}
[Fact]
public void LoggingBuilderAddOpenTelemetryAddExporterTest()
{
var builder = Sdk.CreateLoggerProviderBuilder();
builder.AddExporter(ExportProcessorType.Simple, new CustomExporter());
builder.AddExporter<CustomExporter>(ExportProcessorType.Batch);
using var provider = builder.Build();
Assert.NotNull(provider);
var processor = provider.Processor as CompositeProcessor<LogRecord>;
Assert.NotNull(processor);
var firstProcessor = processor!.Head.Value;
var secondProcessor = processor.Head.Next?.Value;
Assert.True(firstProcessor is SimpleLogRecordExportProcessor simpleProcessor && simpleProcessor.Exporter is CustomExporter);
Assert.True(secondProcessor is BatchLogRecordExportProcessor batchProcessor && batchProcessor.Exporter is CustomExporter);
}
[Fact]
public void LoggingBuilderAddOpenTelemetryAddExporterWithOptionsTest()
{
int optionsInvocations = 0;
var builder = Sdk.CreateLoggerProviderBuilder();
builder.ConfigureServices(services =>
{
services.Configure<ExportLogRecordProcessorOptions>(options =>
{
// Note: This is testing options integration
optionsInvocations++;
options.BatchExportProcessorOptions.MaxExportBatchSize = 18;
});
});
builder.AddExporter(
ExportProcessorType.Simple,
new CustomExporter(),
options =>
{
// Note: Options delegate isn't invoked for simple processor type
Assert.True(false);
});
builder.AddExporter<CustomExporter>(
ExportProcessorType.Batch,
options =>
{
optionsInvocations++;
Assert.Equal(18, options.BatchExportProcessorOptions.MaxExportBatchSize);
options.BatchExportProcessorOptions.MaxExportBatchSize = 100;
});
using var provider = builder.Build();
Assert.NotNull(provider);
Assert.Equal(2, optionsInvocations);
var processor = provider.Processor as CompositeProcessor<LogRecord>;
Assert.NotNull(processor);
var firstProcessor = processor!.Head.Value;
var secondProcessor = processor.Head.Next?.Value;
Assert.True(firstProcessor is SimpleLogRecordExportProcessor simpleProcessor && simpleProcessor.Exporter is CustomExporter);
Assert.True(secondProcessor is BatchLogRecordExportProcessor batchProcessor
&& batchProcessor.Exporter is CustomExporter
&& batchProcessor.MaxExportBatchSize == 100);
}
[Fact]
public void LoggingBuilderAddOpenTelemetryAddExporterNamedOptionsTest()
{
var builder = Sdk.CreateLoggerProviderBuilder();
int defaultOptionsConfigureInvocations = 0;
int namedOptionsConfigureInvocations = 0;
builder.ConfigureServices(services =>
{
services.Configure<ExportLogRecordProcessorOptions>(o => defaultOptionsConfigureInvocations++);
services.Configure<ExportLogRecordProcessorOptions>("Exporter2", o => namedOptionsConfigureInvocations++);
});
builder.AddExporter(ExportProcessorType.Batch, new CustomExporter());
builder.AddExporter(ExportProcessorType.Batch, new CustomExporter(), name: "Exporter2", configure: null);
builder.AddExporter<CustomExporter>(ExportProcessorType.Batch);
builder.AddExporter<CustomExporter>(ExportProcessorType.Batch, name: "Exporter2", configure: null);
using var provider = builder.Build();
Assert.NotNull(provider);
Assert.Equal(1, defaultOptionsConfigureInvocations);
Assert.Equal(1, namedOptionsConfigureInvocations);
}
private sealed class WrappedOpenTelemetryLoggerProvider : OpenTelemetryLoggerProvider
{
public bool Disposed { get; private set; }
protected override void Dispose(bool disposing)
{
this.Disposed = true;
base.Dispose(disposing);
}
}
private sealed class CustomProcessor : BaseProcessor<LogRecord>
{
public CustomProcessor(int? id = null)
{
this.Id = id;
InstanceCount++;
}
public static int InstanceCount { get; set; }
public int? Id { get; }
public bool Disposed { get; private set; }
public TestClass? TestClass { get; set; }
protected override void Dispose(bool disposing)
{
this.Disposed = true;
base.Dispose(disposing);
}
}
private sealed class CustomExporter : BaseExporter<LogRecord>
{
public override ExportResult Export(in Batch<LogRecord> batch)
{
return ExportResult.Success;
}
}
private sealed class TestClass
{
}
}