Apitally .NET SDK v1: rebuilt on OpenTelemetry

The new SDK brings simpler setup, built-in sampling for logs and traces, and custom attributes for requests and API consumers.

Simon GurckeSimon Gurcke//4 min read

Today we’re releasing v1 of the Apitally .NET SDK. Rebuilt from scratch on OpenTelemetry, it introduces simpler setup, built-in sampling, and custom attributes for requests and API consumers.

Apitally is a simple API observability tool for small engineering teams. It helps you understand API usage, monitor errors and performance, and troubleshoot individual requests with correlated logs and traces. The new SDK gives you more control over what you capture, while keeping setup to a few lines of code.

Rebuilt on OpenTelemetry

The SDK is now an OpenTelemetry distribution. It automatically configures OpenTelemetry and sends metrics, logs, and traces to Apitally using OTLP, the industry-standard telemetry data protocol.

You don’t need to understand OpenTelemetry to use Apitally, but if you already have it configured, the SDK can integrate with your existing setup.

You can use standard instrumentation packages and APIs to trace database queries, external HTTP calls, and your own code. See the tracing guide for more details and examples.

Other noteworthy changes

Simpler setup

A single AddApitally() call now registers everything the SDK needs, including its middleware:

using Apitally;

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddApitally(options =>
{
    options.WriteToken = "your-write-token";
});

var app = builder.Build();

The SDK now authenticates using write tokens, which you can create and revoke in the Apitally dashboard. You can configure the write token in code or through standard .NET configuration, including appsettings.json and environment variables.

The SDK also picks up your ASP.NET Core environment automatically, mapping Development to dev and Production to prod. You can override it with the Env option.

You no longer need to explicitly enable request logging, tracing, or application log capture, as these are now enabled by default. You can still opt out, of course.

Sampling for request logs and traces

Sampling lets you capture detailed logs and traces for only a fraction of your traffic while keeping metrics for every request. This gives you control over data capture volume and quota usage as your API grows.

You can set a fixed SampleRate or use the SampleOnRequest / SampleOnResponse callbacks for custom sampling logic.

For example, this callback captures 100% of error responses (4xx, 5xx) and only 10% of successful responses:

builder.Services.AddApitally(options =>
{
    options.SampleOnResponse = span =>
    {
        var statusCode = span.Attributes
            .GetValueOrDefault("http.response.status_code") as long?;
        if (statusCode >= 400)
        {
            return 1.0; // keep all
        }
        return 0.1; // keep only 10%
    };
});

The sampling callbacks can use request/response details, consumer identity, or custom attributes set by your application. See the sampling guide for more details and examples.

More control over application logs

The new MaskLogRecord callback lets you redact sensitive values or drop individual application log records before export.

For example, this callback excludes logs from Entity Framework Core:

builder.Services.AddApitally(options =>
{
    options.MaskLogRecord = record =>
    {
        if (record.CategoryName.StartsWith("Microsoft.EntityFrameworkCore"))
        {
            return null; // drop record
        }
        return record;
    };
});

See the masking guide for more details.

More context for requests and consumers

Custom request attributes let you attach application-specific details to a request’s trace. Add them with SetRequestAttribute() during request handling. You can also use these attributes in sampling and body-masking rules.

API consumers can now also carry custom attributes alongside their identifier, name, and group. Call SetConsumer() to identify the consumer and pass their custom attributes as an attributes dictionary.

Both methods are provided by the new IApitally service, which is available through standard .NET dependency injection:

using Apitally;

app.MapGet("/orders/{orderId}", (string orderId, IApitally apitally) =>
{
    apitally.SetRequestAttribute("tenant", "acme");

    apitally.SetConsumer(
        identifier: "[email protected]",
        name: "John Doe",
        group: "Users",
        attributes: new Dictionary<string, string?> { ["tenant"] = "acme" }
    );

    return Results.Ok();
});

Validation errors in Minimal APIs

The SDK now captures standard validation errors from Minimal APIs in addition to MVC model validation errors. In Apitally, you can review the affected fields, error messages, and occurrence counts to understand why requests are being rejected.

Tested and benchmarked

We’ve put a lot of effort into testing the new SDK, so you can rely on it in production.

Daily end-to-end tests run against real ASP.NET Core applications across .NET versions, checking that the SDK captures the expected metrics, logs, and traces.

We also benchmark the same applications with and without the SDK to measure its impact on latency, CPU usage, and memory. Longer load tests keep those applications busy at high throughput to check how performance and resource usage hold up over time.

We’ll share more about how we test and benchmark the SDKs in a dedicated post, which will also include detailed benchmark results.

What’s next

The new SDK lays the groundwork for broader application monitoring, including background jobs, workers, or scheduled tasks. The aim is to make monitoring these parts of an application as straightforward as API monitoring is with Apitally today.

The OpenTelemetry foundation will also enable support for custom metrics. For example, if you charge for API usage in credits, you could track each consumer’s credit usage in Apitally.

Getting started

Our setup guide for ASP.NET Core walks you through installing and configuring the SDK. The SDK requires .NET 8 or later.

If you’re already using Apitally, follow the migration guide to upgrade to v1.

If you have feedback or questions about the SDK, please let us know.