Skip to main content
The .NET SDK now uses OpenTelemetry to collect and send metrics, logs, and traces.
Request logging, tracing, and application log capture are now enabled by default. If you previously used the SDK for metrics only, set SampleRate = 0 to keep that behavior.

Installation and setup

The updated setup guide provides the installation steps and initialization code. Follow it to replace your existing SDK integration. The SDK now requires .NET 8 or later. If your application references OpenTelemetry packages directly, upgrade them to version 1.19.0 or later.

Write tokens replace client IDs

The SDK now authenticates with a write token instead of a client ID. Your existing app’s token (apt_...) is available under Setup instructions in the Apitally dashboard. Use this token as the WriteToken option in place of ClientId, or set the APITALLY_WRITE_TOKEN environment variable. A missing or invalid token no longer fails application startup. Instead, the SDK logs an error and disables itself.

UseApitally() has been removed

AddApitally() now registers everything the SDK needs, including its middleware. Remove the app.UseApitally() call. The SDK adds its middleware at the start of the request pipeline automatically.
If you use a Startup class, keep calling services.AddApitally() in ConfigureServices and remove app.UseApitally() from Configure.

Configuration changes

The RequestLoggingOptions class and RequestLogging property have been removed. Their settings are now properties directly on ApitallyOptions, with the option changes listed below. The same applies to the Apitally section in appsettings.json:

Changed options

The following options have been changed:
OptionChange
ClientIdReplaced by WriteToken, which requires a new credential.
EnvDefaults to the lowercased ASP.NET Core environment name instead of default, with Production shortened to prod and Development to dev. Remove the option if the derived name fits your setup.
RequestLogging.CaptureLogsMoved to CaptureLogs. Default changed from false to true.
RequestLogging.IncludeRequestHeadersRenamed to CaptureRequestHeaders.
RequestLogging.IncludeRequestBodyRenamed to CaptureRequestBody.
RequestLogging.IncludeResponseHeadersRenamed to CaptureResponseHeaders.
RequestLogging.IncludeResponseBodyRenamed to CaptureResponseBody.
RequestLogging.QueryParamMaskPatternsRenamed to MaskQueryParams.
RequestLogging.HeaderMaskPatternsRenamed to MaskHeaders.
RequestLogging.BodyFieldMaskPatternsRenamed to MaskBodyFields.
RequestLogging.MaskRequestBodyMoved to MaskRequestBody with new arguments.
RequestLogging.MaskResponseBodyMoved to MaskResponseBody with new arguments.
RequestLogging.ShouldExcludeReplaced by SampleOnRequest or SampleOnResponse with new arguments and return values.
RequestLogging.PathExcludePatternsRenamed to ExcludePaths. Matches actual request paths instead of matched route patterns.

Removed options

These options have been removed:
Removed optionMigration
RequestLoggingSet its properties directly on ApitallyOptions, applying the changes above. Remove the Enabled flag.
RequestLogging.Enabled and
RequestLogging.CaptureTraces
Previously defaulted to false. Request logging and tracing are now enabled by default. Use SampleRate = 0 to disable request logs and traces.
RequestLogging.IncludeQueryParamsQuery parameters are now always captured. To mask all values, use MaskQueryParams = [”.*”].
RequestLogging.IncludeExceptionUnhandled exceptions are now always captured in request traces.
The configuration reference lists all available options.

Consumer identification

The SDK now provides the IApitally service with a SetConsumer() method. Setting the ApitallyConsumer item in HttpContext.Items no longer has any effect, and the ApitallyConsumer class has been removed. Call SetConsumer() where the consumer is known, such as in your authentication code. Inject IApitally into your controllers, Minimal API handlers, or middleware, or resolve it from HttpContext.RequestServices:
The identifier is now always a string. Convert numeric identifiers with ToString().

Body masking callbacks

MaskRequestBody and MaskResponseBody now both receive (span, body), rather than the Request and Response objects. The body is passed as a byte[] after decompression. Callbacks may run later on another thread against an ended span snapshot. Request metadata is available through span.Attributes. For example, a callback that masks bodies for admin routes becomes:

Request exclusion

Use sampling callbacks to exclude requests: SampleOnRequest for early decisions based on the request, or SampleOnResponse for decisions based on the response status or consumer. Both receive the span as their only argument. The callbacks should return 1.0 to capture the request, and 0.0 to exclude it. Callbacks can also return any probability between 0 and 1. Returning null preserves a previously made sampling decision. For example, to capture only error responses:
Replace the ShouldExclude option with the appropriate sampling callback. Note that captured headers and bodies are not available in sampling callbacks. Sampling affects request logs and traces, but not metrics. See sampling for details.

Path exclusions

ExcludePaths now matches request paths rather than matched route patterns. If a pattern contains route parameters, update it to match concrete values. For example, replace "^/users/\\{id\\}$" with "^/users/[^/]+$" to match /users/123.

Existing OpenTelemetry setups

If your application registers a tracer provider via AddOpenTelemetry().WithTracing(...), the SDK automatically adds its span processor. No manual registration is required. If you build a tracer provider separately, for example with Sdk.CreateTracerProviderBuilder(), add the ASP.NET Core instrumentation and the apitally.otel source to it, and register it with dependency injection so the SDK can find it:
Review these settings when upgrading:
  • Sampling: Previously, your provider’s sampler affected traces but not Apitally’s request logs. It now affects both, so review its sampling rate when upgrading. Metrics remain unsampled.
  • Sources: Previously, the SDK captured activities from any ActivitySource during requests. It now captures only the activities your provider is configured for. Register your own sources with AddSource(), and add AddHttpClientInstrumentation() to keep tracing outgoing HTTP calls.

Other changes

  • Integration tests: The SDK is automatically disabled in tests using the in-memory TestServer, including the default WebApplicationFactory. For tests running against a real Kestrel server, set Disabled = true or the APITALLY_DISABLED environment variable.
  • Network access: The SDK now sends data to otlp.apitally.io instead of hub.apitally.io. Update firewall allowlists if necessary.
  • Removed types: The Apitally.Models namespace, ApitallyConsumer, RequestLoggingOptions, ValidationErrorFilter, and ValidationError have been removed from the public API.