Exporters
Send telemetry to the OpenTelemetry Collector to make sure it’s exported correctly. Using the Collector in production environments is a best practice. To visualize your telemetry, export it to a backend such as Jaeger, Zipkin, Prometheus, or a vendor-specific backend.
Available exporters
The registry contains a list of exporters for .NET.
Among exporters, OpenTelemetry Protocol (OTLP) exporters are designed with the OpenTelemetry data model in mind, emitting OTel data without any loss of information. Furthermore, many tools that operate on telemetry data support OTLP (such as Prometheus, Jaeger, and most vendors), providing you with a high degree of flexibility when you need it. To learn more about OTLP, see OTLP Specification.
This page covers the main OpenTelemetry .NET exporters and how to set them up.
If you use zero-code instrumentation, you can learn how to set up exporters by following the Configuration Guide.
OTLP
Collector Setup
If you have a OTLP collector or backend already set up, you can skip this section and setup the OTLP exporter dependencies for your application.
To try out and verify your OTLP exporters, you can run the collector in a docker container that writes telemetry directly to the console.
In an empty directory, create a file called collector-config.yaml with the
following content:
receivers:
otlp:
protocols:
grpc:
endpoint: 0.0.0.0:4317
http:
endpoint: 0.0.0.0:4318
exporters:
debug:
verbosity: detailed
service:
pipelines:
traces:
receivers: [otlp]
exporters: [debug]
metrics:
receivers: [otlp]
exporters: [debug]
logs:
receivers: [otlp]
exporters: [debug]
Now run the collector in a docker container:
docker run -p 4317:4317 -p 4318:4318 --rm -v $(pwd)/collector-config.yaml:/etc/otelcol/config.yaml otel/opentelemetry-collector
This collector is now able to accept telemetry via OTLP. Later you may want to configure the collector to send your telemetry to your observability backend.
Dependencies
If you want to send telemetry data to an OTLP endpoint (like the OpenTelemetry Collector, Jaeger or Prometheus), you can choose between two different protocols to transport your data:
- HTTP/protobuf
- gRPC
Start by installing the
OpenTelemetry.Exporter.OpenTelemetryProtocol
package as a dependency for your project:
dotnet add package OpenTelemetry.Exporter.OpenTelemetryProtocol
If you’re using ASP.NET Core install the
OpenTelemetry.Extensions.Hosting
package as well:
dotnet add package OpenTelemetry.Extensions.Hosting
Usage
ASP.NET Core
Configure the exporters in your ASP.NET Core services:
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddOpenTelemetry()
.WithTracing(tracing => tracing
// The rest of your setup code goes here
.AddOtlpExporter())
.WithMetrics(metrics => metrics
// The rest of your setup code goes here
.AddOtlpExporter());
builder.Logging.AddOpenTelemetry(logging => {
// The rest of your setup code goes here
logging.AddOtlpExporter();
});
This will, by default, send telemetry using gRPC to http://localhost:4317, to customize this to use HTTP and the protobuf format, you can add options like this:
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddOpenTelemetry()
.WithTracing(tracing => tracing
// The rest of your setup code goes here
.AddOtlpExporter(options =>
{
options.Endpoint = new Uri("your-endpoint-here/v1/traces");
options.Protocol = OtlpExportProtocol.HttpProtobuf;
}))
.WithMetrics(metrics => metrics
// The rest of your setup code goes here
.AddOtlpExporter(options =>
{
options.Endpoint = new Uri("your-endpoint-here/v1/metrics");
options.Protocol = OtlpExportProtocol.HttpProtobuf;
}));
builder.Logging.AddOpenTelemetry(logging => {
// The rest of your setup code goes here
logging.AddOtlpExporter(options =>
{
options.Endpoint = new Uri("your-endpoint-here/v1/logs");
options.Protocol = OtlpExportProtocol.HttpProtobuf;
});
});
Non-ASP.NET Core
Configure the exporter when creating a TracerProvider, MeterProvider or
LoggerFactory:
var tracerProvider = Sdk.CreateTracerProviderBuilder()
// Other setup code, like setting a resource goes here too
.AddOtlpExporter(options =>
{
options.Endpoint = new Uri("your-endpoint-here/v1/traces");
options.Protocol = OtlpExportProtocol.HttpProtobuf;
})
.Build();
var meterProvider = Sdk.CreateMeterProviderBuilder()
// Other setup code, like setting a resource goes here too
.AddOtlpExporter(options =>
{
options.Endpoint = new Uri("your-endpoint-here/v1/metrics");
options.Protocol = OtlpExportProtocol.HttpProtobuf;
})
.Build();
var loggerFactory = LoggerFactory.Create(builder =>
{
builder.AddOpenTelemetry(logging =>
{
logging.AddOtlpExporter(options =>
{
options.Endpoint = new Uri("your-endpoint-here/v1/logs");
options.Protocol = OtlpExportProtocol.HttpProtobuf;
})
});
});
Use environment variables to set values like headers and an endpoint URL for production.
Console
Dependencies
The console exporter is useful for development and debugging tasks, and is the
simplest to set up. Start by installing the
OpenTelemetry.Exporter.Console
package as a dependency for your project:
dotnet add package OpenTelemetry.Exporter.Console
If you’re using ASP.NET Core install the
OpenTelemetry.Extensions.Hosting
package as well:
dotnet add package OpenTelemetry.Extensions.Hosting
Usage
ASP.NET Core
Configure the exporter in your ASP.NET Core services:
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddOpenTelemetry()
.WithTracing(tracing => tracing
// The rest of your setup code goes here
.AddConsoleExporter()
)
.WithMetrics(metrics => metrics
// The rest of your setup code goes here
.AddConsoleExporter()
);
builder.Logging.AddOpenTelemetry(logging => {
// The rest of your setup code goes here
logging.AddConsoleExporter();
});
Non-ASP.NET Core
Configure the exporter when creating a TracerProvider, MeterProvider or
LoggerFactory:
var tracerProvider = Sdk.CreateTracerProviderBuilder()
// The rest of your setup code goes here
.AddConsoleExporter()
.Build();
var meterProvider = Sdk.CreateMeterProviderBuilder()
// The rest of your setup code goes here
.AddConsoleExporter()
.Build();
var loggerFactory = LoggerFactory.Create(builder =>
{
builder.AddOpenTelemetry(logging =>
{
logging.AddConsoleExporter();
});
});
Jaeger
Backend Setup
Jaeger natively supports OTLP to receive trace data. You can run Jaeger in a docker container with the UI accessible on port 16686 and OTLP enabled on ports 4317 and 4318:
docker run --rm \
-e COLLECTOR_ZIPKIN_HOST_PORT=:9411 \
-p 16686:16686 \
-p 4317:4317 \
-p 4318:4318 \
-p 9411:9411 \
jaegertracing/all-in-one:latest
Usage
Now following the instruction to setup the OTLP exporters.
Prometheus
To send your metric data to Prometheus, you can either
enable Prometheus’ OTLP Receiver
and use the OTLP exporter or you can use the Prometheus exporter, a
MetricReader that starts an HTTP server that collects metrics and serialize to
Prometheus text format on request.
Backend Setup
If you have Prometheus or a Prometheus-compatible backend already set up, you can skip this section and setup the Prometheus or OTLP exporter dependencies for your application.
You can run Prometheus in a docker container,
accessible on port 9090 by following these instructions:
Create a file called prometheus.yml with the following content:
scrape_configs:
- job_name: dice-service
scrape_interval: 5s
static_configs:
- targets: [host.docker.internal:9464]
Run Prometheus in a docker container with the UI accessible on port 9090:
docker run --rm -v ${PWD}/prometheus.yml:/prometheus/prometheus.yml -p 9090:9090 prom/prometheus --web.enable-otlp-receiver
When using Prometheus’ OTLP Receiver, make sure that you set the OTLP endpoint
for metrics in your application to http://localhost:9090/api/v1/otlp.
Not all docker environments support host.docker.internal. In some cases you
may need to replace host.docker.internal with localhost or the IP address
of your machine.
The following sections provide detailed, .NET-specific instructions for configuring the Prometheus exporter.
There are two approaches for exporting metrics to Prometheus:
Using OTLP Exporter (Push): Push metrics to Prometheus using the OTLP protocol. This requires Prometheus’ OTLP Receiver to be enabled. This is the recommended approach for production environments as it supports exemplars and is stable.
Using Prometheus Exporter (Pull/Scrape): Expose a scraping endpoint in your application that Prometheus can scrape. This is the traditional Prometheus approach.
Using OTLP Exporter (Push)
This approach uses the OTLP exporter to push metrics directly to Prometheus' OTLP receiver endpoint. This is recommended for production environments because it supports exemplars and uses the stable OTLP protocol.
Dependencies
Install the
OpenTelemetry.Exporter.OpenTelemetryProtocol
package as a dependency for your project:
dotnet add package OpenTelemetry.Exporter.OpenTelemetryProtocol
If you’re using ASP.NET Core install the
OpenTelemetry.Extensions.Hosting
package as well:
dotnet add package OpenTelemetry.Extensions.Hosting
Usage
ASP.NET Core
Configure the OTLP exporter to send metrics to Prometheus OTLP receiver:
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddOpenTelemetry()
.WithMetrics(metrics => metrics
// The rest of your setup code goes here
.AddOtlpExporter(options =>
{
options.Endpoint = new Uri("http://localhost:9090/api/v1/otlp/v1/metrics");
options.Protocol = OtlpExportProtocol.HttpProtobuf;
}));
Non-ASP.NET Core
Configure the exporter when creating a MeterProvider:
var meterProvider = Sdk.CreateMeterProviderBuilder()
// Other setup code, like setting a resource goes here too
.AddOtlpExporter(options =>
{
options.Endpoint = new Uri("http://localhost:9090/api/v1/otlp/v1/metrics");
options.Protocol = OtlpExportProtocol.HttpProtobuf;
})
.Build();
Make sure Prometheus is started with the OTLP receiver enabled:
./prometheus --web.enable-otlp-receiver
Or when using Docker:
docker run -p 9090:9090 prom/prometheus --web.enable-otlp-receiver
Using Prometheus Exporter (Pull/Scrape)
This approach exposes a metrics endpoint in your application (e.g., /metrics)
that Prometheus scrapes at regular intervals.
This exporter is still under development and doesn’t support exemplars. For production environments, consider using the OTLP exporter approach instead.
Dependencies
Install the exporter package as a dependency for your application:
dotnet add package OpenTelemetry.Exporter.Prometheus.AspNetCore --version 1.15.0-beta.1
If you’re using ASP.NET Core install the
OpenTelemetry.Extensions.Hosting
package as well:
dotnet add package OpenTelemetry.Extensions.Hosting
Usage
ASP.NET Core
Configure the exporter in your ASP.NET Core services:
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddOpenTelemetry()
.WithMetrics(metrics => metrics.AddPrometheusExporter());
You’ll then need to register the Prometheus scraping middleware so that
Prometheus can scrape your application. Use the
UseOpenTelemetryPrometheusScrapingEndpoint extension method on
IApplicationBuilder:
var builder = WebApplication.CreateBuilder(args);
// ... Setup
var app = builder.Build();
app.UseOpenTelemetryPrometheusScrapingEndpoint();
await app.RunAsync();
By default, this exposes the metrics endpoint at /metrics. You can customize
the endpoint path or use a predicate function for more advanced configuration:
app.UseOpenTelemetryPrometheusScrapingEndpoint(
context => context.Request.Path == "/internal/metrics"
&& context.Connection.LocalPort == 5067);
Non-ASP.NET Core
This component is intended for dev inner-loop, there is no plan to make it
production ready. Production environments should use
OpenTelemetry.Exporter.Prometheus.AspNetCore,
or a combination of
OpenTelemetry.Exporter.OpenTelemetryProtocol and
OpenTelemetry Collector.
For applications not using ASP.NET Core, you can use the HttpListener version
which is available in a
different package:
dotnet add package OpenTelemetry.Exporter.Prometheus.HttpListener --version 1.15.0-beta.1
Then this is setup directly on the MeterProviderBuilder:
var meterProvider = Sdk.CreateMeterProviderBuilder()
.AddMeter(MyMeter.Name)
.AddPrometheusHttpListener(
options => options.UriPrefixes = new string[] { "http://localhost:9464/" })
.Build();
Prometheus Configuration (Scrape)
When using the Prometheus exporter (pull/scrape approach), you need to configure
Prometheus to scrape your application. Add the following to your
prometheus.yml:
scrape_configs:
- job_name: 'your-app-name'
scrape_interval: 5s
static_configs:
- targets: ['localhost:5000'] # Your application's host:port
For more details on configuring the Prometheus exporter, see OpenTelemetry.Exporter.Prometheus.AspNetCore.
Zipkin
Backend Setup
If you have Zipkin or a Zipkin-compatible backend already set up, you can skip this section and setup the Zipkin exporter dependencies for your application.
You can run Zipkin on in a Docker container by executing the following command:
docker run --rm -d -p 9411:9411 --name zipkin openzipkin/zipkin
Dependencies
To send your trace data to Zipkin, install the exporter package as a dependency for your application:
dotnet add package OpenTelemetry.Exporter.Zipkin
If you’re using ASP.NET Core install the
OpenTelemetry.Extensions.Hosting
package as well:
dotnet add package OpenTelemetry.Extensions.Hosting
Usage
ASP.NET Core
Configure the exporter in your ASP.NET Core services:
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddOpenTelemetry()
.WithTracing(tracing => tracing
// The rest of your setup code goes here
.AddZipkinExporter(options =>
{
options.Endpoint = new Uri("your-zipkin-uri-here");
}));
Non-ASP.NET Core
Configure the exporter when creating a tracer provider:
var tracerProvider = Sdk.CreateTracerProviderBuilder()
// The rest of your setup code goes here
.AddZipkinExporter(options =>
{
options.Endpoint = new Uri("your-zipkin-uri-here");
})
.Build();
Feedback
Was this page helpful?
Thank you. Your feedback is appreciated!
Please let us know how we can improve this page. Your feedback is appreciated!