.NET Core and .NET 5+
edit.NET Core and .NET 5+
editQuick start
editIn .NET (Core) applications using Microsoft.Extensions.Hosting
, the agent can be registered on the IServiceCollection
. This applies to ASP.NET Core and to other .NET applications that depend on the hosting APIs, such as those created using the worker services template.
The simplest way to enable the agent and its instrumentations requires a reference to the Elastic.Apm.NetCoreAll
package.
The following code sample assumes the instrumentation of a .NET 8 worker service, using top-level statements.
Program.cs
using WorkerServiceSample; var builder = Host.CreateApplicationBuilder(args); builder.Services.AddHttpClient(); builder.Services.AddAllElasticApm(); builder.Services.AddHostedService<Worker>(); var host = builder.Build(); host.Run();
Register Elastic APM before registering other IHostedServices to ensure its dependencies are initialized first. |
When registering services with AddAllElasticApm()
, an APM agent with all instrumentations is enabled. On ASP.NET Core, it’ll automatically capture incoming requests, database calls through supported technologies, outgoing HTTP requests, etc.
For other application templates, such as worker services, you must manually instrument your BackgroundService
to identify one or more units of work that should be captured.
Manual instrumentation using ITracer
editAddAllElasticApm
adds an ITracer
to the Dependency Injection system, which can be used in your code to manually instrument your application, using the Public API
Worker.cs
using Elastic.Apm.Api; namespace WorkerServiceSample { public class Worker : BackgroundService { private readonly IHttpClientFactory _httpClientFactory; private readonly ITracer _tracer; public Worker(IHttpClientFactory httpClientFactory, ITracer tracer) { _httpClientFactory = httpClientFactory; _tracer = tracer; } protected override async Task ExecuteAsync(CancellationToken stoppingToken) { while (!stoppingToken.IsCancellationRequested) { await _tracer.CaptureTransaction("UnitOfWork", ApiConstants.TypeApp, async () => { var client = _httpClientFactory.CreateClient(); await client.GetAsync("https://www.elastic.co", stoppingToken); await Task.Delay(5000, stoppingToken); }); } } } }
The |
When this application runs, a new transaction will be captured and sent for each while loop iteration. A span named HTTP GET within the transaction will be created for the HTTP request to https://www.elastic.co
. The HTTP span is captured because the NetCoreAll package enables this instrumentation automatically.
Manual instrumentation using OpenTelemetry
editAs an alternative to using the Elastic APM API by injecting an ITracer
, you can use the OpenTelemetry API to manually instrument your application. The Elastic APM agent automatically bridges instrumentations created using the OpenTelemetry API, so you can use it to create spans and transactions. In .NET, the Activity
API can be used to instrument applications.
In the case of this sample worker service, we can update the code to prefer the OpenTelemetry API.
Worker.cs
using System.Diagnostics; namespace WorkerServiceSample { public class Worker : BackgroundService { private readonly IHttpClientFactory _httpClientFactory; private static readonly ActivitySource ActivitySource = new("MyActivitySource"); public Worker(IHttpClientFactory httpClientFactory) { _httpClientFactory = httpClientFactory; } protected override async Task ExecuteAsync(CancellationToken stoppingToken) { while (!stoppingToken.IsCancellationRequested) { using var activity = ActivitySource.StartActivity("UnitOfWork"); var client = _httpClientFactory.CreateClient(); await client.GetAsync("https://www.elastic.co", stoppingToken); await Task.Delay(5000, stoppingToken); } } } }
Defines an |
|
Starts an |
Instrumentation modules
editThe Elastic.Apm.NetCoreAll
package references every agent component that can be automatically configured. This is usually not a problem, but if you want to keep dependencies minimal, you can instead reference the Elastic.Apm.Extensions.Hosting
package and register services with AddElasticApm
method, instead of AddAllElasticApm
. With this setup you can explicitly control what the agent will listen for.
The following example only turns on outgoing HTTP monitoring (so, for instance, database and Elasticsearch calls won’t be automatically captured):
using Elastic.Apm.DiagnosticSource; using WorkerServiceSample; var builder = Host.CreateApplicationBuilder(args); builder.Services.AddHttpClient(); builder.Services.AddElasticApm(new HttpDiagnosticsSubscriber()); builder.Services.AddHostedService<Worker>(); var host = builder.Build(); host.Run();
The |
Zero code change setup on .NET Core and .NET 5+ ( [1.7] Added in 1.7. )
editIf you can’t or don’t want to reference NuGet packages in your application, you can use the startup hook feature to inject the agent during startup, if your application runs on .NET Core 3.0, .NET Core 3.1 or .NET 5 or newer.
To configure startup hooks
-
Download the
ElasticApmAgent_<version>.zip
file from the Releases page of the .NET APM Agent GitHub repository. You can find the file under Assets. - Unzip the zip file into a folder.
-
Set the
DOTNET_STARTUP_HOOKS
environment variable to point to theElasticApmAgentStartupHook.dll
file in the unzipped folder -
Start your .NET Core application in a context where the
DOTNET_STARTUP_HOOKS
environment variable is visible.
With this setup, the agent will be injected into the application during startup, enabling every instrumentation feature. Incoming requests will be automatically captured on ASP.NET Core (including gRPC).
Agent configuration can be controlled through environment variables when using the startup hook feature.