Skip to content

Commit

Permalink
Add multiple OTLP exporters from configuration (#12)
Browse files Browse the repository at this point in the history
* Add AddNamedOtlpExporters extension

Adds a new `AddNamedOtlpExporters` extension method that will register a named OTLP exporter for every child section found in the specific configuration.

This allows multiple named exporters to be configured without the names and associated configuration sections being known at compile time.

* Update README.md

* Update example to use AddNamedOtlpExporters

* Update version.json
  • Loading branch information
wazzamatazz authored Dec 20, 2024
1 parent 7f2027d commit 72ad1d5
Show file tree
Hide file tree
Showing 5 changed files with 138 additions and 6 deletions.
13 changes: 13 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -261,6 +261,19 @@ You could then configure the exporters in your `appsettings.json` file as follow
}
```

Alternatively, you can also use the `AddNamedOtlpExporters` extension method to automatically configure a named exporter for every child section found in a given configuration section:

```csharp
services.AddOpenTelemetry()
.ConfigureResource(builder => builder.AddService(typeof(MyType).Assembly))
// TODO: configure trace and metrics instrumentation.
.AddNamedOtlpExporters(
configuration,
configurationSectionName: "OpenTelemetry:Exporters:OTLP"));
```

This approach is particularly useful when the number and names of the exporters is not known at compile time, as it allows additional exporters to be added solely via a configuration change.


# Building the Solution

Expand Down
2 changes: 1 addition & 1 deletion build/version.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"Major": 2,
"Minor": 4,
"Minor": 5,
"Patch": 0,
"PreRelease": ""
}
3 changes: 1 addition & 2 deletions samples/MultipleDestinationOtlpExporterExample/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,7 @@
// export different signal types. See appsettings.json for the configuration.
builder.Services.AddOpenTelemetry()
.ConfigureResource(resource => resource.AddDefaultService())
.AddOtlpExporter("seq-traces", builder.Configuration, "OpenTelemetry:Exporters:OTLP:SeqTraces")
.AddOtlpExporter("seq-logs", builder.Configuration, "OpenTelemetry:Exporters:OTLP:SeqLogs")
.AddNamedOtlpExporters(builder.Configuration)
.WithTracing(tracing => tracing.AddSource(Worker.ActivitySourceName));

var host = builder.Build();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -125,7 +125,7 @@ public static OpenTelemetryBuilder AddOtlpExporter(this OpenTelemetryBuilder bui
/// </para>
///
/// </remarks>
public static OpenTelemetryBuilder AddOtlpExporter(this OpenTelemetryBuilder builder, IConfiguration configuration, string? configurationSectionName = OtlpExporterConfigurationUtilities.DefaultOtlpExporterConfigurationSection, Action<JaahasOtlpExporterOptions>? configure = null)
public static OpenTelemetryBuilder AddOtlpExporter(this OpenTelemetryBuilder builder, IConfiguration configuration, string? configurationSectionName = OtlpExporterConfigurationUtilities.DefaultOtlpExporterConfigurationSection, Action<JaahasOtlpExporterOptions>? configure = null)
=> builder.AddOtlpExporter(null, configuration, configurationSectionName, configure);


Expand Down Expand Up @@ -227,7 +227,7 @@ public static OpenTelemetryBuilder AddOtlpExporter(this OpenTelemetryBuilder bui
/// </para>
///
/// </remarks>
public static OpenTelemetryBuilder AddOtlpExporter(this OpenTelemetryBuilder builder, Action<JaahasOtlpExporterOptions> configure)
public static OpenTelemetryBuilder AddOtlpExporter(this OpenTelemetryBuilder builder, Action<JaahasOtlpExporterOptions> configure)
=> builder.AddOtlpExporter(null, configure);


Expand Down Expand Up @@ -309,7 +309,7 @@ public static OpenTelemetryBuilder AddOtlpExporter(this OpenTelemetryBuilder bui
/// </para>
///
/// </remarks>
public static OpenTelemetryBuilder AddOtlpExporter(this OpenTelemetryBuilder builder, JaahasOtlpExporterOptions options)
public static OpenTelemetryBuilder AddOtlpExporter(this OpenTelemetryBuilder builder, JaahasOtlpExporterOptions options)
=> builder.AddOtlpExporter(null, options);


Expand Down Expand Up @@ -376,5 +376,112 @@ public static OpenTelemetryBuilder AddOtlpExporter(this OpenTelemetryBuilder bui
return builder;
}


/// <summary>
/// Adds named OpenTelemetry Protocol (OTLP) exporters that are configured using the
/// provided <see cref="IConfiguration"/>.
/// </summary>
/// <param name="builder">
/// The <see cref="OpenTelemetryBuilder"/> to configure.
/// </param>
/// <param name="configuration">
/// The <see cref="IConfiguration"/> containing the OTLP exporter configuration.
/// </param>
/// <param name="configurationSectionName">
/// The root configuration section to bind the OTLP exporter configurations from.
/// Specify <see langword="null"/> to bind directly against the root of the
/// <paramref name="configuration"/>.
/// </param>
/// <param name="configure">
/// A delegate used to further configure the OTLP exporter options after binding the
/// configuration section.
/// </param>
/// <returns>
/// The updated <see cref="OpenTelemetryBuilder"/>.
/// </returns>
/// <exception cref="ArgumentNullException">
/// <paramref name="builder"/> is <see langword="null"/>.
/// </exception>
/// <exception cref="ArgumentNullException">
/// <paramref name="configuration"/> is <see langword="null"/>.
/// </exception>
/// <remarks>
///
/// <para>
/// Use this method in preference to <see cref="AddOtlpExporter(OpenTelemetryBuilder, string?, IConfiguration, string?, Action{JaahasOtlpExporterOptions}?)"/>
/// when your configuration contains multiple named OTLP exporter configurations that may
/// not be known at compile time.
/// </para>
///
/// <para>
/// This method will register a named OTLP exporter for each child key under the provided
/// <paramref name="configuration"/> and <paramref name="configurationSectionName"/>.
/// This allows you to configure additional destinations for telemetry signals using
/// configuration only. For example, the following configuration could be used to export
/// signals to both a remote Seq instances and a local Jaeger instance:
/// </para>
///
/// <code language="json">
/// {
/// "OpenTelemetry": {
/// "Exporters": {
/// "OTLP": {
/// "Seq": {
/// "Enabled": true,
/// "Protocol": "HttpProtobuf",
/// "Endpoint": "https://my-seq-server/ingest/otlp",
/// "Signals": "TracesAndLogs",
/// "Headers": {
/// "X-Seq-ApiKey": "my-api-key"
/// }
/// },
/// "Jaeger": {
/// "Enabled": true,
/// "Protocol": "HttpProtobuf",
/// "Signals": "Traces"
/// }
/// }
/// }
/// }
/// }
/// </code>
///
/// </remarks>
public static OpenTelemetryBuilder AddNamedOtlpExporters(
this OpenTelemetryBuilder builder,
IConfiguration configuration,
string? configurationSectionName = OtlpExporterConfigurationUtilities.DefaultOtlpExporterConfigurationSection,
Action<string, JaahasOtlpExporterOptions>? configure = null
) {
#if NET8_0_OR_GREATER
ArgumentNullException.ThrowIfNull(builder);
ArgumentNullException.ThrowIfNull(configuration);
#else
if (builder == null) {
throw new ArgumentNullException(nameof(builder));
}
if (configuration == null) {
throw new ArgumentNullException(nameof(configuration));
}
#endif

var configurationSection = string.IsNullOrWhiteSpace(configurationSectionName)
? configuration
: configuration.GetSection(configurationSectionName!);

foreach (var child in configurationSection.GetChildren()) {
var name = child.Key;
builder.AddOtlpExporter(
name,
child,
configurationSectionName: null,
configure: configure == null
? null
: options => configure?.Invoke(name, options));
}

return builder;
}

}
}
13 changes: 13 additions & 0 deletions src/Jaahas.OpenTelemetry.Extensions/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -255,3 +255,16 @@ You would then configure the exporters in your `appsettings.json` file as follow
}
}
```

Alternatively, you can also use the `AddNamedOtlpExporters` extension method to automatically configure a named exporter for every child section found in a given configuration section:

```csharp
services.AddOpenTelemetry()
.ConfigureResource(builder => builder.AddService(typeof(MyType).Assembly))
// TODO: configure trace and metrics instrumentation.
.AddNamedOtlpExporters(
configuration,
configurationSectionName: "OpenTelemetry:Exporters:OTLP"));
```

This approach is particularly useful when the number and names of the exporters is not known at compile time, as it allows additional exporters to be added solely via a configuration change.

0 comments on commit 72ad1d5

Please sign in to comment.