Skip to content

Commit

Permalink
[Logs] Support dependency injection in logging build-up (#3504)
Browse files Browse the repository at this point in the history
* Support dependency injection in logging. Add AddOpenTelemetryEventSourceLogEmitter extension.

* CHANGELOG update.

* Bug fixes and a test.

* More fixes and more tests.

* Tweak comments for clarity.

* Added OpenTelemetryLoggerOptions.Services xml detail remarks.

* More tests.

* More tests.

* Test fix.

* More tests.

* Tests and fixes.

* Warning cleanup.

* Added resource test.

* Smooth out multiple resource configurations.

* Resource chaining fix.

* Remove throw for additional SetResourceBuilder calls.

* Warning fixes.

* Moved OpenTelemetryEventSourceLogEmitter extension to OpenTelemetryLoggerOptions.

* Tweaks.

* Switched from static to builder pattern.

* Tweaks.

* More tests.

* Fix CHANGELOG for release.

* Tweaks.

* Test updates.

* Added a detached configuration option.

* Prevent double registration to be consistent with tracer builder pattern.

* API review.

* Warning cleanup.

* Build fixes.

* Test fix.
  • Loading branch information
CodeBlanch authored Aug 6, 2022
1 parent 72f4e07 commit 952c3b1
Show file tree
Hide file tree
Showing 31 changed files with 1,450 additions and 361 deletions.
15 changes: 6 additions & 9 deletions examples/LoggingExtensions/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -16,19 +16,16 @@

using System.Diagnostics.Tracing;
using Examples.LoggingExtensions;
using OpenTelemetry;
using OpenTelemetry.Logs;
using OpenTelemetry.Resources;
using Serilog;

var resourceBuilder = ResourceBuilder.CreateDefault().AddService("Examples.LoggingExtensions");

var openTelemetryLoggerProvider = new OpenTelemetryLoggerProvider(options =>
{
options.IncludeFormattedMessage = true;
options
.SetResourceBuilder(resourceBuilder)
.AddConsoleExporter();
});
var openTelemetryLoggerProvider = Sdk.CreateLoggerProviderBuilder()
.SetIncludeFormattedMessage(true)
.ConfigureResource(builder => builder.AddService("Examples.LoggingExtensions"))
.AddConsoleExporter()
.Build();

// Creates an OpenTelemetryEventSourceLogEmitter for routing ExampleEventSource
// events into logs
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
#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!
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
#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!
1 change: 1 addition & 0 deletions src/OpenTelemetry.Extensions.EventSource/AssemblyInfo.cs
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
using System.Runtime.CompilerServices;

[assembly: CLSCompliant(false)]
[assembly: InternalsVisibleTo("OpenTelemetry.Extensions.EventSource.Tests" + AssemblyInfo.PublicKey)]
[assembly: InternalsVisibleTo("DynamicProxyGenAssembly2" + AssemblyInfo.MoqPublicKey)]

#if SIGNED
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
// <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();
}
}
}
}
37 changes: 30 additions & 7 deletions src/OpenTelemetry.Extensions.EventSource/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,19 +17,42 @@ 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 = new OpenTelemetryLoggerProvider(options =>
{
options
.SetResourceBuilder(ResourceBuilder.CreateDefault().AddService("MyService"))
.AddConsoleExporter();
});
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.StartsWith("OpenTelemetry") ? EventLevel.LogAlways : null,
(name) => name == MyEventSource.Name ? EventLevel.Informational : null,
disposeProvider: true);
```

Expand Down
10 changes: 4 additions & 6 deletions src/OpenTelemetry.Extensions.Serilog/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,12 +17,10 @@ dotnet add package OpenTelemetry.Extensions.Serilog --prerelease

```csharp
// Step 1: Configure OpenTelemetryLoggerProvider...
var openTelemetryLoggerProvider = new OpenTelemetryLoggerProvider(options =>
{
options
.SetResourceBuilder(ResourceBuilder.CreateDefault().AddService("MyService"))
.AddConsoleExporter();
});
var openTelemetryLoggerProvider = Sdk.CreateLoggerProviderBuilder()
.ConfigureResource(builder => builder.AddService("MyService"))
.AddConsoleExporter()
.Build();

// Step 2: Register OpenTelemetry sink with Serilog...
Log.Logger = new LoggerConfiguration()
Expand Down
6 changes: 3 additions & 3 deletions src/OpenTelemetry/.publicApi/net462/PublicAPI.Shipped.txt
Original file line number Diff line number Diff line change
Expand Up @@ -94,9 +94,9 @@ readonly OpenTelemetry.BaseExportProcessor<T>.exporter -> OpenTelemetry.BaseExpo
~static OpenTelemetry.Resources.ResourceBuilderExtensions.AddEnvironmentVariableDetector(this OpenTelemetry.Resources.ResourceBuilder resourceBuilder) -> OpenTelemetry.Resources.ResourceBuilder
~static OpenTelemetry.Resources.ResourceBuilderExtensions.AddService(this OpenTelemetry.Resources.ResourceBuilder resourceBuilder, string serviceName, string serviceNamespace = null, string serviceVersion = null, bool autoGenerateServiceInstanceId = true, string serviceInstanceId = null) -> OpenTelemetry.Resources.ResourceBuilder
~static OpenTelemetry.Resources.ResourceBuilderExtensions.AddTelemetrySdk(this OpenTelemetry.Resources.ResourceBuilder resourceBuilder) -> OpenTelemetry.Resources.ResourceBuilder
~static OpenTelemetry.Sdk.CreateMeterProviderBuilder() -> OpenTelemetry.Metrics.MeterProviderBuilder
~static OpenTelemetry.Sdk.CreateTracerProviderBuilder() -> OpenTelemetry.Trace.TracerProviderBuilder
~static OpenTelemetry.Sdk.SetDefaultTextMapPropagator(OpenTelemetry.Context.Propagation.TextMapPropagator textMapPropagator) -> void
static OpenTelemetry.Sdk.CreateMeterProviderBuilder() -> OpenTelemetry.Metrics.MeterProviderBuilder!
static OpenTelemetry.Sdk.CreateTracerProviderBuilder() -> OpenTelemetry.Trace.TracerProviderBuilder!
static OpenTelemetry.Sdk.SetDefaultTextMapPropagator(OpenTelemetry.Context.Propagation.TextMapPropagator! textMapPropagator) -> void
~static OpenTelemetry.SuppressInstrumentationScope.Begin(bool value = true) -> System.IDisposable
~static OpenTelemetry.Trace.TracerProviderBuilderExtensions.AddProcessor(this OpenTelemetry.Trace.TracerProviderBuilder tracerProviderBuilder, OpenTelemetry.BaseProcessor<System.Diagnostics.Activity> processor) -> OpenTelemetry.Trace.TracerProviderBuilder
~static OpenTelemetry.Trace.TracerProviderBuilderExtensions.Build(this OpenTelemetry.Trace.TracerProviderBuilder tracerProviderBuilder) -> OpenTelemetry.Trace.TracerProvider
Expand Down
13 changes: 11 additions & 2 deletions src/OpenTelemetry/.publicApi/net462/PublicAPI.Unshipped.txt
Original file line number Diff line number Diff line change
Expand Up @@ -7,14 +7,23 @@ 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.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
OpenTelemetry.Logs.OpenTelemetryLoggerProvider.OpenTelemetryLoggerProvider(System.Action<OpenTelemetry.Logs.OpenTelemetryLoggerOptions!>! configure) -> void
OpenTelemetry.Logs.OpenTelemetryLoggerOptions.ConfigureResource(System.Action<OpenTelemetry.Resources.ResourceBuilder!>! configure) -> OpenTelemetry.Logs.OpenTelemetryLoggerOptions!
*REMOVED*static Microsoft.Extensions.Logging.OpenTelemetryLoggingExtensions.AddOpenTelemetry(this Microsoft.Extensions.Logging.ILoggingBuilder! builder, System.Action<OpenTelemetry.Logs.OpenTelemetryLoggerOptions!>? configure = null) -> Microsoft.Extensions.Logging.ILoggingBuilder!
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.Logs.OpenTelemetryLoggerOptionsExtensions.Build(this OpenTelemetry.Logs.OpenTelemetryLoggerOptions! options) -> OpenTelemetry.Logs.OpenTelemetryLoggerProvider!
static OpenTelemetry.Sdk.CreateLoggerProviderBuilder() -> OpenTelemetry.Logs.OpenTelemetryLoggerOptions!
~static OpenTelemetry.Metrics.MeterProviderBuilderExtensions.ConfigureResource(this OpenTelemetry.Metrics.MeterProviderBuilder meterProviderBuilder, System.Action<OpenTelemetry.Resources.ResourceBuilder> configure) -> OpenTelemetry.Metrics.MeterProviderBuilder
~static OpenTelemetry.Trace.TracerProviderBuilderExtensions.ConfigureResource(this OpenTelemetry.Trace.TracerProviderBuilder tracerProviderBuilder, System.Action<OpenTelemetry.Resources.ResourceBuilder> configure) -> OpenTelemetry.Trace.TracerProviderBuilder
6 changes: 3 additions & 3 deletions src/OpenTelemetry/.publicApi/net6.0/PublicAPI.Shipped.txt
Original file line number Diff line number Diff line change
Expand Up @@ -94,9 +94,9 @@ readonly OpenTelemetry.BaseExportProcessor<T>.exporter -> OpenTelemetry.BaseExpo
~static OpenTelemetry.Resources.ResourceBuilderExtensions.AddEnvironmentVariableDetector(this OpenTelemetry.Resources.ResourceBuilder resourceBuilder) -> OpenTelemetry.Resources.ResourceBuilder
~static OpenTelemetry.Resources.ResourceBuilderExtensions.AddService(this OpenTelemetry.Resources.ResourceBuilder resourceBuilder, string serviceName, string serviceNamespace = null, string serviceVersion = null, bool autoGenerateServiceInstanceId = true, string serviceInstanceId = null) -> OpenTelemetry.Resources.ResourceBuilder
~static OpenTelemetry.Resources.ResourceBuilderExtensions.AddTelemetrySdk(this OpenTelemetry.Resources.ResourceBuilder resourceBuilder) -> OpenTelemetry.Resources.ResourceBuilder
~static OpenTelemetry.Sdk.CreateMeterProviderBuilder() -> OpenTelemetry.Metrics.MeterProviderBuilder
~static OpenTelemetry.Sdk.CreateTracerProviderBuilder() -> OpenTelemetry.Trace.TracerProviderBuilder
~static OpenTelemetry.Sdk.SetDefaultTextMapPropagator(OpenTelemetry.Context.Propagation.TextMapPropagator textMapPropagator) -> void
static OpenTelemetry.Sdk.CreateMeterProviderBuilder() -> OpenTelemetry.Metrics.MeterProviderBuilder!
static OpenTelemetry.Sdk.CreateTracerProviderBuilder() -> OpenTelemetry.Trace.TracerProviderBuilder!
static OpenTelemetry.Sdk.SetDefaultTextMapPropagator(OpenTelemetry.Context.Propagation.TextMapPropagator! textMapPropagator) -> void
~static OpenTelemetry.SuppressInstrumentationScope.Begin(bool value = true) -> System.IDisposable
~static OpenTelemetry.Trace.TracerProviderBuilderExtensions.AddProcessor(this OpenTelemetry.Trace.TracerProviderBuilder tracerProviderBuilder, OpenTelemetry.BaseProcessor<System.Diagnostics.Activity> processor) -> OpenTelemetry.Trace.TracerProviderBuilder
~static OpenTelemetry.Trace.TracerProviderBuilderExtensions.Build(this OpenTelemetry.Trace.TracerProviderBuilder tracerProviderBuilder) -> OpenTelemetry.Trace.TracerProvider
Expand Down
Loading

0 comments on commit 952c3b1

Please sign in to comment.