Skip to content

Commit

Permalink
Refactor to use AddOtlpExporter and LoggerProviderBuilder (#180)
Browse files Browse the repository at this point in the history
We initially used UseOtlpExporter as a convenient way to enable OTLP
export by default globally for all signals. However, this plays poorly
with the AddOtlpExporter methods, which throw if called by consumer
code. This change avoids that risk. It also introduces a
LoggingProviderBuilder extension to register our defaults, which our
main builder calls.

We still support disabling our default registration of the OTLP exporter
via an environment variable, which the auto instrumentation plugin then
passes when configuring the providers.

This PR also fixes a small typo in the docs.

Closes #177
  • Loading branch information
stevejgordon authored Nov 22, 2024
1 parent 4a96eda commit 107db01
Show file tree
Hide file tree
Showing 7 changed files with 73 additions and 29 deletions.
2 changes: 1 addition & 1 deletion docs/configure.md
Original file line number Diff line number Diff line change
Expand Up @@ -172,7 +172,7 @@ Valid options: `Critical`, `Error`, `Warning`, `Information`, `Debug`, `Trace` a
* _Type_: Bool
* _Default_: `false`

Allows EDOT .NET to used with its defaults, but without enabling the export of telemetry data to
Allows EDOT .NET to be used with its defaults, but without enabling the export of telemetry data to
an OTLP endpoint. This can be useful when you want to test applications without sending telemetry data.

| Configuration method | Key |
Expand Down
4 changes: 2 additions & 2 deletions global.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"sdk": {
"version": "8.0.100",
"rollForward": "latestMajor",
"version": "8.0.404",
"rollForward": "latestFeature",
"allowPrerelease": false
}
}
13 changes: 9 additions & 4 deletions src/Elastic.OpenTelemetry/AutoInstrumentationPlugin.cs
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@ public class AutoInstrumentationPlugin
private readonly ILogger _logger;
private readonly EventListener _eventListener;

private readonly bool _skipOtlp;

/// <inheritdoc cref="AutoInstrumentationPlugin"/>
public AutoInstrumentationPlugin()
{
Expand All @@ -31,6 +33,11 @@ public AutoInstrumentationPlugin()

_logger = logger;
_eventListener = eventListener;

var skipOtlpString = Environment.GetEnvironmentVariable("ELASTIC_OTEL_SKIP_OTLP_EXPORTER");

if (skipOtlpString is not null && bool.TryParse(skipOtlpString, out var skipOtlp))
_skipOtlp = skipOtlp;
}

/// To access TracerProvider right after TracerProviderBuilder.Build() is executed.
Expand All @@ -45,22 +52,20 @@ public void MeterProviderInitialized(MeterProvider meterProvider)

/// To configure tracing SDK before Auto Instrumentation configured SDK
public TracerProviderBuilder BeforeConfigureTracerProvider(TracerProviderBuilder builder) =>
builder.UseElasticDefaults(_logger);

builder.UseElasticDefaults(_skipOtlp, _logger);

/// To configure tracing SDK after Auto Instrumentation configured SDK
public TracerProviderBuilder AfterConfigureTracerProvider(TracerProviderBuilder builder) =>
builder;

/// To configure metrics SDK before Auto Instrumentation configured SDK
public MeterProviderBuilder BeforeConfigureMeterProvider(MeterProviderBuilder builder) =>
builder.UseElasticDefaults(_logger);
builder.UseElasticDefaults(_skipOtlp, _logger);

/// To configure metrics SDK after Auto Instrumentation configured SDK
public MeterProviderBuilder AfterConfigureMeterProvider(MeterProviderBuilder builder) =>
builder;


/// To configure logs SDK (the method name is the same as for other logs options)
public void ConfigureLogsOptions(OpenTelemetryLoggerOptions options) =>
options.UseElasticDefaults(_logger);
Expand Down
28 changes: 12 additions & 16 deletions src/Elastic.OpenTelemetry/ElasticOpenTelemetryBuilder.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@

using System.Diagnostics;
using System.Diagnostics.Tracing;
using System.Reflection;
using Elastic.OpenTelemetry.Configuration;
using Elastic.OpenTelemetry.Diagnostics;
using Elastic.OpenTelemetry.Diagnostics.Logging;
Expand All @@ -15,10 +14,6 @@
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
using OpenTelemetry;
using OpenTelemetry.Logs;
using OpenTelemetry.Metrics;
using OpenTelemetry.Trace;
using static Elastic.OpenTelemetry.Configuration.ElasticOpenTelemetryOptions;

namespace Elastic.OpenTelemetry;

Expand Down Expand Up @@ -112,49 +107,50 @@ public ElasticOpenTelemetryBuilder(ElasticOpenTelemetryBuilderOptions options)
openTelemetry.ConfigureResource(r => r.UseElasticDefaults(Logger));
var distro = options.DistroOptions;

//https://github.com/open-telemetry/opentelemetry-dotnet/pull/5400
if (!distro.SkipOtlpExporter)
openTelemetry.UseOtlpExporter();

if (distro.Signals.HasFlag(Signals.Logs))
{
//TODO Move to WithLogging once it gets stable
Services.Configure<OpenTelemetryLoggerOptions>(logging =>
openTelemetry.WithLogging(logging =>
{
if (distro.ElasticDefaults.HasFlag(ElasticDefaults.Logs))
logging.UseElasticDefaults();
logging.UseElasticDefaults(distro.SkipOtlpExporter, Logger);
else
Logger.LogDefaultsDisabled(nameof(ElasticDefaults.Logs));
});
}
else
{
Logger.LogSignalDisabled(nameof(Signals.Logs));
}

if (distro.Signals.HasFlag(Signals.Traces))
{
openTelemetry.WithTracing(tracing =>
{
if (distro.ElasticDefaults.HasFlag(ElasticDefaults.Traces))
tracing.UseElasticDefaults(Logger);
tracing.UseElasticDefaults(distro.SkipOtlpExporter, Logger);
else
Logger.LogDefaultsDisabled(nameof(ElasticDefaults.Traces));
});
}
else
{
Logger.LogSignalDisabled(nameof(Signals.Metrics));
}

if (distro.Signals.HasFlag(Signals.Metrics))
{
openTelemetry.WithMetrics(metrics =>
{
if (distro.ElasticDefaults.HasFlag(ElasticDefaults.Metrics))
metrics.UseElasticDefaults(Logger);
metrics.UseElasticDefaults(distro.SkipOtlpExporter, Logger);
else
Logger.LogDefaultsDisabled(nameof(ElasticDefaults.Metrics));
});
}
else
{
Logger.LogSignalDisabled(nameof(Signals.Metrics));
}
}
}

Expand All @@ -169,10 +165,10 @@ internal static partial class LoggerMessages
[LoggerMessage(EventId = 2, Level = LogLevel.Information, Message = "No Elastic defaults were enabled.")]
public static partial void LogNoElasticDefaults(this ILogger logger);

[LoggerMessage(EventId = 1, Level = LogLevel.Information, Message = "ElasticOpenTelemetryBuilder {Signal} skipped, configured to be disabled")]
[LoggerMessage(EventId = 3, Level = LogLevel.Information, Message = "ElasticOpenTelemetryBuilder {Signal} skipped, configured to be disabled")]
public static partial void LogSignalDisabled(this ILogger logger, string signal);

[LoggerMessage(EventId = 1, Level = LogLevel.Information, Message = "Elastic defaults for {Signal} skipped, configured to be disabled")]
[LoggerMessage(EventId = 4, Level = LogLevel.Information, Message = "Elastic defaults for {Signal} skipped, configured to be disabled")]
public static partial void LogDefaultsDisabled(this ILogger logger, string signal);

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
// Licensed to Elasticsearch B.V under one or more agreements.
// Elasticsearch B.V licenses this file to you under the Apache 2.0 License.
// See the LICENSE file in the project root for more information

using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Logging.Abstractions;
using OpenTelemetry.Logs;
using OpenTelemetry.Trace;
using static Elastic.OpenTelemetry.Configuration.Signals;

namespace Elastic.OpenTelemetry.Extensions;

/// <summary>
/// Elastic extensions for <see cref="LoggerProviderBuilder"/>.
/// </summary>
public static class LoggingProviderBuilderExtensions
{
/// <summary>
/// Use Elastic Distribution of OpenTelemetry .NET defaults for <see cref="LoggerProviderBuilder"/>.
/// </summary>
public static LoggerProviderBuilder UseElasticDefaults(this LoggerProviderBuilder builder, bool skipOtlp = false, ILogger? logger = null)
{
logger ??= NullLogger.Instance;

if (!skipOtlp)
builder.AddOtlpExporter();

logger.LogConfiguredSignalProvider(nameof(Logs), nameof(LoggerProviderBuilder));
return builder;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ namespace Elastic.OpenTelemetry.Extensions;
public static class MeterProviderBuilderExtensions
{
/// <summary> Use Elastic Distribution of OpenTelemetry .NET defaults for <see cref="MeterProviderBuilder"/> </summary>
public static MeterProviderBuilder UseElasticDefaults(this MeterProviderBuilder builder, ILogger? logger = null)
public static MeterProviderBuilder UseElasticDefaults(this MeterProviderBuilder builder, bool skipOtlp = false, ILogger? logger = null)
{
logger ??= NullLogger.Instance;

Expand All @@ -24,6 +24,9 @@ public static MeterProviderBuilder UseElasticDefaults(this MeterProviderBuilder
.AddRuntimeInstrumentation()
.AddHttpClientInstrumentation();

if (!skipOtlp)
builder.AddOtlpExporter();

logger.LogConfiguredSignalProvider(nameof(Metrics), nameof(MeterProviderBuilder));

return builder;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,15 @@
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Logging.Abstractions;
using OpenTelemetry;
using OpenTelemetry.Logs;
using OpenTelemetry.Trace;
using static Elastic.OpenTelemetry.Configuration.Signals;

namespace Elastic.OpenTelemetry.Extensions;

/// <summary> Elastic extensions for <see cref="TracerProviderBuilder"/>. </summary>
/// <summary>
/// Elastic extensions for <see cref="TracerProviderBuilder"/>.
/// </summary>
public static class TracerProviderBuilderExtensions
{
/// <summary>
Expand All @@ -34,17 +37,23 @@ private static TracerProviderBuilder LogAndAddProcessor(this TracerProviderBuild
return builder.AddProcessor(processor);
}

/// <summary> Use Elastic Distribution of OpenTelemetry .NET defaults for <see cref="TracerProviderBuilder"/> </summary>
public static TracerProviderBuilder UseElasticDefaults(this TracerProviderBuilder builder, ILogger? logger = null)
/// <summary>
/// Use Elastic Distribution of OpenTelemetry .NET defaults for <see cref="TracerProviderBuilder"/>.
/// </summary>
public static TracerProviderBuilder UseElasticDefaults(this TracerProviderBuilder builder, bool skipOtlp = false, ILogger? logger = null)
{
logger ??= NullLogger.Instance;

builder
.AddHttpClientInstrumentation()
.AddGrpcClientInstrumentation()
.AddEntityFrameworkCoreInstrumentation();
.AddEntityFrameworkCoreInstrumentation()
.AddSource("Elastic.Transport")
.AddElasticProcessors(logger);

if (!skipOtlp)
builder.AddOtlpExporter();

builder.AddElasticProcessors(logger);
logger.LogConfiguredSignalProvider(nameof(Traces), nameof(TracerProviderBuilder));
return builder;
}
Expand Down

0 comments on commit 107db01

Please sign in to comment.