Trace Azure Functions with OpenTelemetry .NET
The OpenTelemetry Protocol (OTLP) exporters for .NET currently support gRPC and HTTP 1.1 with binary Protocol Buffers (Protobuf) payload transports. Supported corresponding protocol values are grpc
and http/protobuf
. Configuration options can be set either via environment variables or explicitly in code.
Prerequisites
The following prerequisites and limitations apply:
- Dynatrace version 1.222+
- W3C Trace Context is enabled
- From the Dynatrace menu, go to Settings and select Server-side service monitoring > Deep monitoring > Distributed tracing.
- Turn on Send W3C Trace Context HTTP headers.
Instrument Azure Functions
Dynatrace uses OpenTelemetry Trace Ingest to provide end-to-end visibility to your Azure Functions.
To instrument your Azure Functions
Set up export
Add dependencies
Instrument code
Set up export
To ingest gRPC via the Dynatrace Trace API, you need to use an OpenTelemetry collector between Dynatrace and the exporter.
If you use environment variables for setup, you need to set the following value:
- For
OTEL_EXPORTER_OTLP_PROTOCOL
:grpc
Configure the OpenTelemetry Collector
To ingest gRPC via the Dynatrace Trace API, you need to use an OpenTelemetry collector between Dynatrace and the exporter.
The OpenTelemetry Collector is available as a Docker image. To use this collector to export trace data to Dynatrace, you need to customize the configuration using the OpenTelemetry OTLP exporter.
Here is a sample configuration file:
receivers:
otlp:
protocols:
grpc:
exporters:
otlphttp:
endpoint: "https://<YOUR-TENANT-ID>.live.dynatrace.com/api/v2/otlp"
headers: {"Authorization": "Api-Token <YOUR-DYNATRACE-API-TOKEN>"}
service:
pipelines:
traces:
receivers: [otlp]
exporters: [otlphttp]
For further details on configuration, see Send OpenTelemetry trace data to Dynatrace.
To ingest HTTP via the Dynatrace Trace API, you need to configure the exporter. The exporter will then directly send traces to the configured endpoint.
If you use environment variables for setup, you need to set the following values:
-
For
OTEL_EXPORTER_OTLP_PROTOCOL
:http/protobuf
-
For
OTEL_EXPORTER_OTLP_ENDPOINT
: the URL for export endpointNotes:
- If you set the endpoint URL via environment variables, the export endpoints for traces and metrics are automatically appended by
v1/traces
for traces andv1/metrics
for metrics. For example, if the endpoint is set tohttps://<YOUR-TENANT-ID>.live.dynatrace.com/api/v2/otlp
, traces will be exported tohttps://<YOUR-TENANT-ID>.live.dynatrace.com/api/v2/otlp/v1/traces
. - If you set the endpoint explicitly in code, it will be used as is.
For details, see Endpoint URLs for OTLP/HTTP.
- If you set the endpoint URL via environment variables, the export endpoints for traces and metrics are automatically appended by
-
For
OTEL_EXPORTER_OTLP_HEADERS
: the authorization API token value in the following format:Authorization=Api-Token <TOKEN>
.
Add dependencies
Add the following dependencies via NuGet to your project:
OpenTelemetry.Exporter.OpenTelemetryProtocol
OpenTelemetry also provides other auto-instrumentation libraries available as NuGet packages.
Instrument code with OpenTelemetry
Note: If you don't set the Protocol
property of the OtlpExporterOptions
class via environment variables or in code, it will be initialized as OtlpExportProtocol.Grpc
by default.
public class Startup : FunctionsStartup
{
public override void Configure(IFunctionsHostBuilder builder)
{
string activitySource = "[activitySource]";
string serviceName = "[serviceName]";
string collectorUrl = "[collectorUrl]" // Points to the running collector, configured before.
builder.Services.AddSingleton((builder) =>
{
return Sdk.CreateTracerProviderBuilder()
.SetSampler(new AlwaysOnSampler())
.AddSource(activitySource)
.SetResourceBuilder(ResourceBuilder.CreateDefault().AddService(serviceName))
.AddHttpClientInstrumentation(op =>
{
// Exclude frequent calls generated by Azure Application Insights
op.Filter = (req) => !req.RequestUri.AbsoluteUri.Contains("visualstudio");
})
.AddOtlpExporter(otlpOptions =>
{
otlpOptions.Endpoint = new Uri(collectorUrl);
})
.Build();
});
}
}
The code sample using HTTP exporter is similar to the gRPC exporter sample; the only difference is in the configuration of OtlpExporterOptions
:
return Sdk.CreateTracerProviderBuilder()
// ...
// ... other initialization code (see the code snippet for the gRPC case)
// ...
.AddOtlpExporter(otlpOptions =>
{
otlpOptions.Protocol = OtlpExportProtocol.HttpProtobuf;
otlpOptions.Headers = "Authorization=Api-Token <TOKEN>";
//Use an explicitly set endpoint for export
//or an endpoint configured via environment variable.
otlpOptions.Endpoint = new Uri("https://<YOUR-TENANT-ID>.live.dynatrace.com/api/v2/otlp");
})
.Build();
If the configuration is done via environment variables, the code for adding an OTLP/HTTP exporter is even simpler:
return Sdk.CreateTracerProviderBuilder()
// ...
// ... other initialization code (see the code snippet for the gRPC case)
// ...
.AddOtlpExporter()
.Build();