Skip to content

Commit fcc9495

Browse files
authored
Add EDOT .NET troubleshooting for custom processors (#3780)
Closes elastic/elastic-otel-dotnet#312
1 parent 95a7dda commit fcc9495

File tree

1 file changed

+47
-1
lines changed
  • troubleshoot/ingest/opentelemetry/edot-sdks/dotnet

1 file changed

+47
-1
lines changed

troubleshoot/ingest/opentelemetry/edot-sdks/dotnet/index.md

Lines changed: 47 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -194,4 +194,50 @@ To avoid this scenario, make sure each placeholder uses a unique name. For examp
194194

195195
```csharp
196196
Logger.LogInformation("Eat your {fruit1} {fruit2} {fruit3}!", "apple", "banana", "mango");
197-
```
197+
```
198+
199+
### Custom processors are not applied to exported data
200+
201+
When using custom processors, be aware that they may not run before data is exported unless explicitly configured.
202+
203+
By default, EDOT .NET simplifies the getting started experience by applying [opinionated defaults](elastic-otel-dotnet://reference/edot-dotnet/setup/edot-defaults.md). These defaults include registering the OTLP exporter with the OpenTelemetry SDK so that telemetry data is exported automatically, without requiring additional code.
204+
205+
In advanced scenarios, you might want to develop custom processors that enrich telemetry data before it passes through the rest of the processing pipeline. In such circumstances, you have to add the processor to the relevant signal provider builder.
206+
207+
For example, if you use the following code to register a custom processor for trace data using
208+
the `TracerProviderBuilder`, it won't work as intended:
209+
210+
```csharp
211+
builder.AddElasticOpenTelemetry(b => b
212+
.WithTracing(t => t.AddProcessor<SpanRollupProcessor>())
213+
.WithMetrics(m => m.AddMeter("MyAppMeter")));
214+
```
215+
216+
This code will not work as desired due to EDOT .NET registering the OTLP exporter before the processor,
217+
therefore running earlier in the pipeline than `SpanRollupProcessor`. The exact behaviour may vary or appear to
218+
work because trace data is exported in batches and the custom processor may partially apply to trace data before
219+
the batch is exported.
220+
221+
To address this, you can disable the automatic OTLP exporter registration using the `SkipOtlpExporter` option. This allows you to manually register the exporter *after* registering your custom processor.
222+
223+
Taking the prior example, the correct code should be as follows:
224+
225+
```csharp
226+
builder.AddElasticOpenTelemetry(new ElasticOpenTelemetryOptions() { SkipOtlpExporter = true }, b => b
227+
.WithLogging(l => l.AddOtlpExporter())
228+
.WithTracing(t =>
229+
{
230+
t.AddProcessor<SpanRollupProcessor>();
231+
t.AddOtlpExporter();
232+
})
233+
.WithMetrics(m => m
234+
.AddMeter("MyAppMeter")
235+
.AddOtlpExporter()));
236+
```
237+
238+
In this example, `SkipOtlpExporter` is set to `true` using the `ElasticOpenTelemetryOptions` overload of `AddElasticOpenTelemetry`. If preferred, this can also be configured using the `appSettings.json` file.
239+
240+
With `SkipOtlpExporter` enabled, the exporter must be added to __each__ signal that should be exported. In
241+
this example, the OTLP exporter is manually added for logs, traces and metrics. Crucially, for traces, the
242+
exporter is registered after the custom `SpanRollupProcessor` to ensure that trace data is batched for export
243+
after the processor has completed.

0 commit comments

Comments
 (0)