---
slug: dotnet-opentelemetry-support
published: 2026-10-14
change_type: new-feature
affected_products:
  - supabase-dotnet
page: https://supabase.com/changelog/dotnet-opentelemetry-support
---

# OpenTelemetry traces and metrics in the Supabase .NET SDK

## What's new

The [.NET SDK](https://github.com/supabase/supabase-csharp#) emit traces and metrics through `System.Diagnostics`. Each client exposes its own `ActivitySource` and `Meter`, so you subscribe to them the same way you subscribe to any other .NET instrumentation. The SDK takes no dependency on the OpenTelemetry packages, and the clients stay silent until something subscribes, so there is no overhead when you are not collecting.

This covers the Auth, Postgrest, Storage, and Functions clients. Realtime is not yet instrumented. URLs are recorded with the query string stripped, and no token, credential, or payload is placed in a tag.

## What you get

| Client    | Spans                                                                                                                                                                              | Metrics                                                                                                          |
|-----------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|------------------------------------------------------------------------------------------------------------------|
| Postgrest | One per request (`{METHOD} {path}`), with a `db.operation` tag (`select`, `insert`, `update`, `upsert`, `delete`, `count`, `rpc`) to tell apart operations that share an HTTP verb | `supabase.postgrest.http.request.duration`                                                                       |
| Auth      | One per operation (`gotrue.sign_in`, `gotrue.refresh_token`, …), with a child span for the HTTP call                                                                               | `supabase.gotrue.http.request.duration`                                                                          |
| Storage   | One per request, with a `storage.transfer.direction` tag on uploads and downloads; a resumable (TUS) upload is a single span for the whole transfer                                | `supabase.storage.http.request.duration`, `supabase.storage.transfer.duration`, `supabase.storage.transfer.size` |
| Functions | One per invocation, with a `faas.invoked_name` tag; a relay error is a failed span even when the HTTP status succeeds                                                              | `supabase.functions.invoke.duration`                                                                             |

## How to use it

Add the OpenTelemetry hosting package and an exporter alongside the SDK:

```xml
<PackageReference Include="Supabase" Version="8.0.0" />
<PackageReference Include="OpenTelemetry.Extensions.Hosting" Version="1.19.1" />
<PackageReference Include="OpenTelemetry.Exporter.OpenTelemetryProtocol" Version="1.19.1" />
```

Then register the Supabase sources. Each client shares one name between its `ActivitySource` and its `Meter`, so you can register them all at once with `SupabaseDiagnostics.SourceNames`, or one client at a time by its own `SourceName`:

```csharp
using OpenTelemetry.Metrics;
using OpenTelemetry.Trace;
using Supabase;
using Supabase.Postgrest;
using Supabase.Gotrue;
using Supabase.Storage;
using Supabase.Functions;

builder.Services.AddOpenTelemetry()
    // All sources at once.
    .WithTracing(tracing => tracing
        .AddSource(SupabaseDiagnostics.SourceNames.ToArray())
        .AddOtlpExporter())
    // Or one client at a time.
    .WithMetrics(metrics => metrics
        .AddMeter(PostgrestDiagnostics.SourceName)
        .AddMeter(GotrueDiagnostics.SourceName)
        .AddMeter(StorageDiagnostics.SourceName)
        .AddMeter(FunctionsDiagnostics.SourceName)
        .AddOtlpExporter());
```

Swap `AddOtlpExporter` for `AddConsoleExporter` to print locally, or use any other exporter. Without the OpenTelemetry SDK, a raw `ActivityListener` or `MeterListener` works too. We have one README per-package which shows how to do it.

## Why it matters

You get the SDK's calls in the same traces as the rest of your app: which ran, how long they took, whether they failed. You write no instrumentation for it, and the SDK pulls in no OpenTelemetry dependency of its own.
