Skip to content

Commit

Permalink
Move LoggerProvider and friends (OTEL1000) to a stable API (#5648)
Browse files Browse the repository at this point in the history
  • Loading branch information
CodeBlanch authored Jun 5, 2024
1 parent 248043a commit 2710c42
Show file tree
Hide file tree
Showing 52 changed files with 508 additions and 1,011 deletions.
20 changes: 20 additions & 0 deletions build/Common.nonprod.props
Original file line number Diff line number Diff line change
Expand Up @@ -44,4 +44,24 @@

<Message Importance="high" Text="Skipping test execution for '$(TargetPath)' because it does not contain the '$(TargetFramework)' target." Condition="'$(_SkipTests)' == 'true'" />
</Target>

<Target Name="ResolveExposedExperimentalFeatures" BeforeTargets="CoreCompile">
<!-- Note: What this does is look for $(ProjectReferenceName).BuildFlags.txt
files for all the dependencies of the project being compiled. If
ExposeExperimentalFeatures=true is found in those files we set compiler
constants for each project where experimental features were exposed.
Example:
OPENTELEMETRY_EXPORTER_INMEMORY_EXPERIMENTAL_FEATURES_EXPOSED;OPENTELEMETRY_EXPERIMENTAL_FEATURES_EXPOSED;OPENTELEMETRY_API_EXPERIMENTAL_FEATURES_EXPOSED;OPENTELEMETRY_API_PROVIDERBUILDEREXTENSIONS_EXPERIMENTAL_FEATURES_EXPOSED
-->
<ItemGroup>
<DependenciesWithExposedExperimentalFeatures
Include="@(_ResolvedProjectReferencePaths->'%(Filename)')"
Condition="$([System.IO.File]::Exists('%(RootDir)%(Directory)%(Filename).BuildFlags.txt')) AND $([System.IO.File]::ReadAllText('%(RootDir)%(Directory)%(Filename).BuildFlags.txt').Contains('ExposeExperimentalFeatures=true'))" />
<CompilerConstantsForDependenciesWithExposedExperimentalFeatures Include="@(DependenciesWithExposedExperimentalFeatures->'$([System.String]::Copy('%(DependenciesWithExposedExperimentalFeatures.Identity)').ToUpper().Replace('.', '_'))_EXPERIMENTAL_FEATURES_EXPOSED')" />
</ItemGroup>

<PropertyGroup Condition="'@(CompilerConstantsForDependenciesWithExposedExperimentalFeatures)' != ''">
<DefineConstants>$(DefineConstants);@(CompilerConstantsForDependenciesWithExposedExperimentalFeatures)</DefineConstants>
</PropertyGroup>
</Target>
</Project>
13 changes: 13 additions & 0 deletions build/Common.prod.props
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,10 @@
<ItemGroup>
<None Include="$(MSBuildThisFileDirectory)opentelemetry-icon-color.png" Pack="true" PackagePath="\" />
<SourceRoot Condition="'$(Deterministic)'=='true'" Include="$(MSBuildThisFileDirectory)/" />
<None Include="$(IntermediateOutputPath)$(ProjectName).BuildFlags.txt"
Link="$(ProjectName).BuildFlags.txt"
CopyToOutputDirectory="PreserveNewest"
Visible="false" />
<!-- Note: This includes all the PublicApiAnalyzers files in projects to make editing easier in the IDE -->
<None Include=".publicApi\**\PublicAPI.*.txt" />
</ItemGroup>
Expand Down Expand Up @@ -82,6 +86,15 @@
<DefineConstants>$(DefineConstants);EXPOSE_EXPERIMENTAL_FEATURES</DefineConstants>
</PropertyGroup>

<!-- Note: We write a file into the output dir which captures the state of
ExposeExperimentalFeatures for the current compilation. This is used by
consuming projects (tests, benchmarks, examples, etc) to add compiler
constants which can be used to detect experimental APIs -->
<WriteLinesToFile
File="$(IntermediateOutputPath)$(ProjectName).BuildFlags.txt"
Lines="ExposeExperimentalFeatures=$(ExposeExperimentalFeatures)"
Overwrite="true"/>

<!-- Note: This selects the correct PublicApiAnalyzers files based on $(ExposeExperimentalFeatures) -->
<ItemGroup>
<AdditionalFiles Include=".publicApi\Stable\PublicAPI.*.txt" />
Expand Down
10 changes: 8 additions & 2 deletions docs/diagnostics/experimental-apis/OTEL1000.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,17 @@

This is an Experimental API diagnostic covering the following APIs:

* `ILoggingBuilder.UseOpenTelemetry`

Experimental APIs may be changed or removed in the future.

The following portions of `OTEL1000` were released stable in `1.9.0` and are no
longer considered experimental:

* `LoggerProviderBuilder`
* `LoggerProvider`
* `IDeferredLoggerProviderBuilder`

Experimental APIs may be changed or removed in the future.
* `OpenTelemetryBuilder.WithLogging`

## Details

Expand Down
1 change: 1 addition & 0 deletions docs/diagnostics/experimental-apis/OTEL1001.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ This is an Experimental API diagnostic covering the following APIs:
* `LogRecordAttributeList`
* `LogRecordData`
* `LogRecordSeverity`
* `Sdk.CreateLoggerProviderBuilder`

Experimental APIs may be changed or removed in the future.

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,20 +11,25 @@ public static class DedicatedLoggingServiceCollectionExtensions
public static IServiceCollection AddDedicatedLogging(
this IServiceCollection services,
IConfiguration configuration,
Action<OpenTelemetryLoggerOptions> configureOpenTelemetry)
Action<LoggerProviderBuilder> configureOpenTelemetry)
{
ArgumentNullException.ThrowIfNull(configureOpenTelemetry);

services.TryAddSingleton(sp =>
services.TryAddSingleton(_ =>
{
var loggerFactory = LoggerFactory.Create(builder =>
var services = new ServiceCollection();
services.AddLogging(builder =>
{
builder.AddConfiguration(configuration);

builder.AddOpenTelemetry(configureOpenTelemetry);
builder.AddOpenTelemetry();
});

return new DedicatedLoggerFactory(loggerFactory);
services.ConfigureOpenTelemetryLoggerProvider(configureOpenTelemetry);

var sp = services.BuildServiceProvider();

return new DedicatedLoggerFactory(sp);
});

services.TryAdd(ServiceDescriptor.Singleton(typeof(IDedicatedLogger<>), typeof(DedicatedLogger<>)));
Expand Down Expand Up @@ -54,11 +59,13 @@ public void Log<TState>(LogLevel logLevel, EventId eventId, TState state, Except

private sealed class DedicatedLoggerFactory : ILoggerFactory
{
private readonly ServiceProvider serviceProvider;
private readonly ILoggerFactory innerLoggerFactory;

public DedicatedLoggerFactory(ILoggerFactory loggerFactory)
public DedicatedLoggerFactory(ServiceProvider serviceProvider)
{
this.innerLoggerFactory = loggerFactory;
this.serviceProvider = serviceProvider;
this.innerLoggerFactory = serviceProvider.GetRequiredService<ILoggerFactory>();
}

public void AddProvider(ILoggerProvider provider)
Expand All @@ -68,6 +75,6 @@ public ILogger CreateLogger(string categoryName)
=> this.innerLoggerFactory.CreateLogger(categoryName);

public void Dispose()
=> this.innerLoggerFactory.Dispose();
=> this.serviceProvider.Dispose();
}
}
15 changes: 8 additions & 7 deletions docs/logs/dedicated-pipeline/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,18 +8,19 @@

builder.Logging.ClearProviders();

builder.Logging.AddOpenTelemetry(options =>
{
// Set up primary pipeline for common app logs
options.AddConsoleExporter();
});
builder.Services.AddOpenTelemetry()
.WithLogging(logging =>
{
// Set up primary pipeline for common app logs
logging.AddConsoleExporter();
});

builder.Services.AddDedicatedLogging(
builder.Configuration.GetSection("DedicatedLogging"), // Bind configuration for dedicated logging pipeline
options =>
logging =>
{
// Set up secondary pipeline for dedicated logs
options.AddConsoleExporter();
logging.AddConsoleExporter();
});

var app = builder.Build();
Expand Down
28 changes: 12 additions & 16 deletions docs/logs/getting-started-aspnetcore/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,25 +6,21 @@

var builder = WebApplication.CreateBuilder(args);

// Remove default providers and add OpenTelemetry logging provider.
// For instructional purposes only, disable the default .NET console logging provider to
// use the verbose OpenTelemetry console exporter instead. For most development
// and production scenarios the default console provider works well and there is no need to
// For instructional purposes only, disable the default .NET logging providers.
// We remove the console logging provider in this demo to use the verbose
// OpenTelemetry console exporter instead. For most development and production
// scenarios the default console provider works well and there is no need to
// clear these providers.
builder.Logging.ClearProviders();

builder.Logging.AddOpenTelemetry(logging =>
{
var resourceBuilder = ResourceBuilder
.CreateDefault()
.AddService(builder.Environment.ApplicationName);

logging.SetResourceBuilder(resourceBuilder)

// ConsoleExporter is used for demo purpose only.
// In production environment, ConsoleExporter should be replaced with other exporters (e.g. OTLP Exporter).
.AddConsoleExporter();
});
// Add OpenTelemetry logging provider by calling the WithLogging extension.
builder.Services.AddOpenTelemetry()
.ConfigureResource(r => r.AddService(builder.Environment.ApplicationName))
.WithLogging(logging => logging
/* Note: ConsoleExporter is used for demo purpose only. In production
environment, ConsoleExporter should be replaced with other exporters
(e.g. OTLP Exporter). */
.AddConsoleExporter());

var app = builder.Build();

Expand Down
62 changes: 27 additions & 35 deletions examples/AspNetCore/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -24,20 +24,21 @@
// Note: Switch between Explicit/Exponential by setting HistogramAggregation in appsettings.json
var histogramAggregation = appBuilder.Configuration.GetValue("HistogramAggregation", defaultValue: "explicit")!.ToLowerInvariant();

// Build a resource configuration action to set service information.
Action<ResourceBuilder> configureResource = r => r.AddService(
serviceName: appBuilder.Configuration.GetValue("ServiceName", defaultValue: "otel-test")!,
serviceVersion: typeof(Program).Assembly.GetName().Version?.ToString() ?? "unknown",
serviceInstanceId: Environment.MachineName);

// Create a service to expose ActivitySource, and Metric Instruments
// for manual instrumentation
appBuilder.Services.AddSingleton<Instrumentation>();

// Configure OpenTelemetry tracing & metrics with auto-start using the
// Clear default logging providers used by WebApplication host.
appBuilder.Logging.ClearProviders();

// Configure OpenTelemetry logging, metrics, & tracing with auto-start using the
// AddOpenTelemetry extension from OpenTelemetry.Extensions.Hosting.
appBuilder.Services.AddOpenTelemetry()
.ConfigureResource(configureResource)
.ConfigureResource(r => r
.AddService(
serviceName: appBuilder.Configuration.GetValue("ServiceName", defaultValue: "otel-test")!,
serviceVersion: typeof(Program).Assembly.GetName().Version?.ToString() ?? "unknown",
serviceInstanceId: Environment.MachineName))
.WithTracing(builder =>
{
// Tracing
Expand Down Expand Up @@ -121,34 +122,25 @@
builder.AddConsoleExporter();
break;
}
});

// Clear default logging providers used by WebApplication host.
appBuilder.Logging.ClearProviders();

// Configure OpenTelemetry Logging.
appBuilder.Logging.AddOpenTelemetry(options =>
{
// Note: See appsettings.json Logging:OpenTelemetry section for configuration.

var resourceBuilder = ResourceBuilder.CreateDefault();
configureResource(resourceBuilder);
options.SetResourceBuilder(resourceBuilder);

switch (logExporter)
})
.WithLogging(builder =>
{
case "otlp":
options.AddOtlpExporter(otlpOptions =>
{
// Use IConfiguration directly for Otlp exporter endpoint option.
otlpOptions.Endpoint = new Uri(appBuilder.Configuration.GetValue("Otlp:Endpoint", defaultValue: "http://localhost:4317")!);
});
break;
default:
options.AddConsoleExporter();
break;
}
});
// Note: See appsettings.json Logging:OpenTelemetry section for configuration.

switch (logExporter)
{
case "otlp":
builder.AddOtlpExporter(otlpOptions =>
{
// Use IConfiguration directly for Otlp exporter endpoint option.
otlpOptions.Endpoint = new Uri(appBuilder.Configuration.GetValue("Otlp:Endpoint", defaultValue: "http://localhost:4317")!);
});
break;
default:
builder.AddConsoleExporter();
break;
}
});

appBuilder.Services.AddControllers();

Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +0,0 @@
OpenTelemetry.Logs.OpenTelemetryDependencyInjectionLoggerProviderBuilderExtensions
OpenTelemetry.Logs.OpenTelemetryDependencyInjectionLoggingServiceCollectionExtensions
static OpenTelemetry.Logs.OpenTelemetryDependencyInjectionLoggerProviderBuilderExtensions.AddInstrumentation<T>(this OpenTelemetry.Logs.LoggerProviderBuilder! loggerProviderBuilder) -> OpenTelemetry.Logs.LoggerProviderBuilder!
static OpenTelemetry.Logs.OpenTelemetryDependencyInjectionLoggerProviderBuilderExtensions.AddInstrumentation<T>(this OpenTelemetry.Logs.LoggerProviderBuilder! loggerProviderBuilder, System.Func<System.IServiceProvider!, OpenTelemetry.Logs.LoggerProvider!, T!>! instrumentationFactory) -> OpenTelemetry.Logs.LoggerProviderBuilder!
static OpenTelemetry.Logs.OpenTelemetryDependencyInjectionLoggerProviderBuilderExtensions.AddInstrumentation<T>(this OpenTelemetry.Logs.LoggerProviderBuilder! loggerProviderBuilder, System.Func<System.IServiceProvider!, T!>! instrumentationFactory) -> OpenTelemetry.Logs.LoggerProviderBuilder!
static OpenTelemetry.Logs.OpenTelemetryDependencyInjectionLoggerProviderBuilderExtensions.AddInstrumentation<T>(this OpenTelemetry.Logs.LoggerProviderBuilder! loggerProviderBuilder, T! instrumentation) -> OpenTelemetry.Logs.LoggerProviderBuilder!
static OpenTelemetry.Logs.OpenTelemetryDependencyInjectionLoggerProviderBuilderExtensions.ConfigureServices(this OpenTelemetry.Logs.LoggerProviderBuilder! loggerProviderBuilder, System.Action<Microsoft.Extensions.DependencyInjection.IServiceCollection!>! configure) -> OpenTelemetry.Logs.LoggerProviderBuilder!
static OpenTelemetry.Logs.OpenTelemetryDependencyInjectionLoggingServiceCollectionExtensions.ConfigureOpenTelemetryLoggerProvider(this Microsoft.Extensions.DependencyInjection.IServiceCollection! services, System.Action<OpenTelemetry.Logs.LoggerProviderBuilder!>! configure) -> Microsoft.Extensions.DependencyInjection.IServiceCollection!
static OpenTelemetry.Logs.OpenTelemetryDependencyInjectionLoggingServiceCollectionExtensions.ConfigureOpenTelemetryLoggerProvider(this Microsoft.Extensions.DependencyInjection.IServiceCollection! services, System.Action<System.IServiceProvider!, OpenTelemetry.Logs.LoggerProviderBuilder!>! configure) -> Microsoft.Extensions.DependencyInjection.IServiceCollection!
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
OpenTelemetry.Logs.OpenTelemetryDependencyInjectionLoggerProviderBuilderExtensions
OpenTelemetry.Logs.OpenTelemetryDependencyInjectionLoggingServiceCollectionExtensions
static OpenTelemetry.Logs.OpenTelemetryDependencyInjectionLoggerProviderBuilderExtensions.AddInstrumentation<T>(this OpenTelemetry.Logs.LoggerProviderBuilder! loggerProviderBuilder) -> OpenTelemetry.Logs.LoggerProviderBuilder!
static OpenTelemetry.Logs.OpenTelemetryDependencyInjectionLoggerProviderBuilderExtensions.AddInstrumentation<T>(this OpenTelemetry.Logs.LoggerProviderBuilder! loggerProviderBuilder, System.Func<System.IServiceProvider!, OpenTelemetry.Logs.LoggerProvider!, T!>! instrumentationFactory) -> OpenTelemetry.Logs.LoggerProviderBuilder!
static OpenTelemetry.Logs.OpenTelemetryDependencyInjectionLoggerProviderBuilderExtensions.AddInstrumentation<T>(this OpenTelemetry.Logs.LoggerProviderBuilder! loggerProviderBuilder, System.Func<System.IServiceProvider!, T!>! instrumentationFactory) -> OpenTelemetry.Logs.LoggerProviderBuilder!
static OpenTelemetry.Logs.OpenTelemetryDependencyInjectionLoggerProviderBuilderExtensions.AddInstrumentation<T>(this OpenTelemetry.Logs.LoggerProviderBuilder! loggerProviderBuilder, T! instrumentation) -> OpenTelemetry.Logs.LoggerProviderBuilder!
static OpenTelemetry.Logs.OpenTelemetryDependencyInjectionLoggerProviderBuilderExtensions.ConfigureServices(this OpenTelemetry.Logs.LoggerProviderBuilder! loggerProviderBuilder, System.Action<Microsoft.Extensions.DependencyInjection.IServiceCollection!>! configure) -> OpenTelemetry.Logs.LoggerProviderBuilder!
static OpenTelemetry.Logs.OpenTelemetryDependencyInjectionLoggingServiceCollectionExtensions.ConfigureOpenTelemetryLoggerProvider(this Microsoft.Extensions.DependencyInjection.IServiceCollection! services, System.Action<OpenTelemetry.Logs.LoggerProviderBuilder!>! configure) -> Microsoft.Extensions.DependencyInjection.IServiceCollection!
static OpenTelemetry.Logs.OpenTelemetryDependencyInjectionLoggingServiceCollectionExtensions.ConfigureOpenTelemetryLoggerProvider(this Microsoft.Extensions.DependencyInjection.IServiceCollection! services, System.Action<System.IServiceProvider!, OpenTelemetry.Logs.LoggerProviderBuilder!>! configure) -> Microsoft.Extensions.DependencyInjection.IServiceCollection!
6 changes: 6 additions & 0 deletions src/OpenTelemetry.Api.ProviderBuilderExtensions/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,12 @@

## Unreleased

* The experimental APIs previously covered by `OTEL1000`
(`LoggerProviderBuilder` `AddInstrumentation` & `ConfigureServices` extensions
and `IServiceCollection.ConfigureOpenTelemetryLoggerProvider` extension) will
now be part of the public API and supported in stable builds.
([#5648](https://github.com/open-telemetry/opentelemetry-dotnet/pull/5648))

## 1.9.0-alpha.1

Released 2024-May-20
Expand Down
Loading

0 comments on commit 2710c42

Please sign in to comment.