Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Move LoggerProvider and friends (OTEL1000) to a stable API #5648

Merged
merged 18 commits into from
Jun 5, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

should we add a note here to warn users that this approach only works if their exporter also supports this model?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Might get confusing. I think either a) we leave it as is or b) we show the old style. Let me know which you prefer! I'm hoping the gap is short-lived and we can get these extensions added soon after 1.9.0 is out.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

okay to keep this as-is, assuming the gap is short-lived.

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);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

❤️ seeing common Resource across all 3!

And also ❤️ fixing the awkwardness of calling methods like AddExporter on a supposedly pure "Options" class!


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!
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
Loading