What's new#
The .NET SDK 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:
_10<PackageReference Include="Supabase" Version="8.0.0" />_10<PackageReference Include="OpenTelemetry.Extensions.Hosting" Version="1.19.1" />_10<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:
_20using OpenTelemetry.Metrics;_20using OpenTelemetry.Trace;_20using Supabase;_20using Supabase.Postgrest;_20using Supabase.Gotrue;_20using Supabase.Storage;_20using Supabase.Functions;_20_20builder.Services.AddOpenTelemetry()_20 // All sources at once._20 .WithTracing(tracing => tracing_20 .AddSource(SupabaseDiagnostics.SourceNames.ToArray())_20 .AddOtlpExporter())_20 // Or one client at a time._20 .WithMetrics(metrics => metrics_20 .AddMeter(PostgrestDiagnostics.SourceName)_20 .AddMeter(GotrueDiagnostics.SourceName)_20 .AddMeter(StorageDiagnostics.SourceName)_20 .AddMeter(FunctionsDiagnostics.SourceName)_20 .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.