RepoDb.Telemetry.Default

August 18, 2026 · View on GitHub

Drop-in telemetry for RepoDB. Wires up a default ITrace that captures every operation (Insert, Query, Update, Delete, etc.) and publishes it to an insights collector — no custom ITrace implementation required.

Built on top of RepoDb.Telemetry.Core. See more at Telemetry feature for more details.

Setting up Docker

Download the docker-compose.yml and .env files into any directory and run the command below:

cd c:/folder-location
docker compose up -d

Once the stack is up, the collector Collector API runs at http://localhost:5000 by default and the Grafana dashboard is at http://localhost:3000.

Everything runs with local defaults (RepoDB2026 as the shared password/API key) meant for trying things out, not production. Override them with environment variables in a .env file before deploying to production.

Getting Started

Install the package:

dotnet add package RepoDb.Telemetry.Default

Enable it once at application startup:

GlobalConfiguration
    .Setup(new GlobalConfigurationOptions { UseRegisteredGlobalTraces = true })
    .UseDefaultTelemetry(
        host: "https://your-collector-host",
        apiKey: "YOUR_API_KEY",
        applicationName: "MyApp",
        groupName: "Default");

That's it — every operation across all connections in the app is now traced automatically.

UseRegisteredGlobalTraces = true is required. It tells RepoDB to run every globally registered tracer (this one included) for every operation, without having to pass a trace argument to each call.

How It Works

  • Each operation's start/end is captured as a TelemetryItem (application, group, operation name, statement, elapsed time, client machine, source assembly, etc.).
  • Items are buffered in memory and flushed on an interval (Frequency, default 5 seconds).
  • On flush, the batch is JSON-serialized, gzip-compressed, and POSTed to {host}/v1/telemetry/publish, with an X-API-Key header when an API key is supplied.
  • Publish failures never throw — they're routed to the optional errorCallback and logger.

The DefaultTelemetryItem Model

Every captured operation is represented as a DefaultTelemetryItem — a concrete, RepoDB-specific subclass of RepoDb.Telemetry.Core's TelemetryItem (it adds no fields of its own; it exists so the default pipeline has its own type to construct, serialize, and evolve independently of the core package). Each instance carries:

PropertyDescription
ApplicationName of the application that produced the telemetry (from your DefaultTelemetryOption).
GroupThe logical group the application is categorized under.
SessionIdUnique identifier correlating an operation's before/after execution logs.
OperationThe operation name (e.g. Insert, Query, Update, Delete).
StartTimeUTC timestamp of when the operation started executing.
StatementThe SQL statement (or equivalent) that was executed.
ElapsedTotal elapsed time of the operation, in milliseconds.
IsCancelledWhether the operation was cancelled from within a trace callback.
ClientThe machine name the operation ran on.
SourceThe name of the assembly that hosts/consumes RepoDB (your application).
VersionThe version of that assembly.

These items are what gets buffered, batched, and serialized to JSON before being published to your collector.

Not an OpenTelemetry Collector — By Design

This package intentionally does not ship an OpenTelemetry (OTel) exporter or rely on the OTel SDK. DefaultTelemetryTrace hooks directly into RepoDB's ITrace before/after execution events and serializes its own lightweight DefaultTelemetryItem payload straight to HTTP — there's no OTel Span/Activity machinery, no resource/attribute mapping layer, and no dependency on the OTel collector protocol in the hot path.

That's a deliberate tradeoff, not an oversight:

  • Performance. Operations are captured with a handful of property assignments and buffered in memory; nothing allocates spans, contexts, or goes through an exporter pipeline per call. For a library whose whole value proposition is being a thin, fast layer over ADO.NET, that overhead matters.
  • Tight coupling to the library. The capture shape (DefaultTelemetryItem) mirrors RepoDB's own operation model (session id, statement, elapsed time, cancellation) instead of being generalized to fit an industry-wide schema, keeping the implementation simple and directly meaningful for RepoDB users.

An OTel-based collector is planned as a separate, opt-in package for enterprise-grade telemetry scenarios (distributed tracing across services, vendor-neutral export to existing observability stacks, etc.). Until then, RepoDb.Telemetry.Default is the fast, zero-fuss path to seeing what your RepoDB operations are doing.

Configuration

For more control, pass a DefaultTelemetryOption instead of individual arguments:

GlobalConfiguration
    .Setup(new GlobalConfigurationOptions { UseRegisteredGlobalTraces = true })
    .UseDefaultTelemetry(
        new DefaultTelemetryOption("MyApp")
        {
            Host = "https://your-collector-host",
            ApiKey = "YOUR_API_KEY",
            Group = "Default",
            Frequency = TimeSpan.FromSeconds(10)
        },
        errorCallback: ex => logger.LogError(ex, "Telemetry publish failed"),
        logger: serilogLogger);
PropertyDescriptionDefault
ApplicationName of the application producing telemetry.(required)
GroupLogical grouping for the dashboard."Default"
HostCollector endpoint to publish to.http://localhost:5000
ApiKeyAPI key sent via X-API-Key. Leave empty if the collector doesn't require one.null
FrequencyHow often buffered telemetry is flushed.5 seconds

UseDefaultTelemetry is idempotent — calling it again reuses the same underlying tracer instance rather than starting a new one.

What's with Docker Compose

The docker-compose.yml at the root of this project spins up a complete, self-hosted telemetry stack: a Postgres database, the HTTP collector your app publishes to, a query API, two background workers (a file data sinker and a purger), and a Grafana-based visualization dashboard.

Most settings are supplied as environment variables using the ${VAR:-default} pattern, so they can be overridden without touching the compose file — either by exporting them in your shell or by placing a .env file next to docker-compose.yml. A few values (like the Postgres password on the pgsql service itself) are hardcoded and would need a direct edit to the compose file to change.

pgsql

The Postgres database backing the entire stack — the collector writes to it, and the query, filedatasinker, purger, and visualization services all read from it.

Environment VariableDescriptionDefault
POSTGRES_PASSWORDPassword for the Postgres superuser, used to initialize the database. Hardcoded in the compose file rather than sourced from a ${...} variable, so changing it means editing docker-compose.yml directly — and keeping it in sync with REPODB_PG_PASSWORD used elsewhere.RepoDB2026

collector

The HTTP endpoint your application publishes telemetry to (this is the host you pass to UseDefaultTelemetry). It validates the API key and writes incoming batches to Postgres.

Environment VariableDescriptionDefault
API_KEYAPI key required via the X-API-Key header on publish requests. Should match the apiKey your app passes to UseDefaultTelemetry. Sourced from REPODB_API_KEY.RepoDB2026
CONNECTION_STRINGPostgreSQL connection string used to persist published telemetry into the repodb_insights database. The password segment is sourced from REPODB_PG_PASSWORD.postgresql://postgres:RepoDB2026@pgsql:5432/repodb_insights

query

The read API that serves telemetry data to the visualization dashboard.

Environment VariableDescriptionDefault
API_KEYAPI key required to authenticate query requests. Sourced from REPODB_API_KEY.RepoDB2026
CONNECTION_STRINGPostgreSQL connection string used to read telemetry data. The password segment is sourced from REPODB_PG_PASSWORD.postgresql://postgres:RepoDB2026@pgsql:5432/repodb_insights
DIRECTORY_PATHPath inside the container where telemetry files (staged by filedatasinker) are read from. Backed by the shared telemetry_data volume./tmp/repodb/telemetry
ALLOWED_ORIGINSCORS-allowed origin permitted to call the query API — normally the URL the visualization dashboard is served from. Sourced from REPODB_VISUALIZATION_ORIGIN.http://localhost:3000

filedatasinker

A background worker that periodically exports telemetry data from Postgres into flat files for downstream consumption by the query service.

Environment VariableDescriptionDefault
CONNECTION_STRINGPostgreSQL connection string the sinker reads telemetry from. The password segment is sourced from REPODB_PG_PASSWORD.postgresql://postgres:RepoDB2026@pgsql:5432/repodb_insights
DIRECTORY_PATHPath inside the container where exported telemetry files are written. Backed by the shared telemetry_data volume./tmp/repodb/telemetry
FREQUENCY_IN_MINUTESHow often, in minutes, the sinker runs its export pass. Sourced from REPODB_FILEDATASINKER_FREQUENCY_IN_MINUTES.60

purger

A background worker that deletes telemetry records older than a configured retention window, keeping the Postgres database from growing unbounded.

Environment VariableDescriptionDefault
CONNECTION_STRINGPostgreSQL connection string the purger deletes records through. The password segment is sourced from REPODB_PG_PASSWORD.postgresql://postgres:RepoDB2026@pgsql:5432/repodb_insights
RETENTION_PERIOD_IN_MINUTESHow long, in minutes, telemetry records are kept before being eligible for deletion. Sourced from REPODB_PURGER_RETENTION_PERIOD_IN_MINUTES.10080 (7 days)
FREQUENCY_IN_MINUTESHow often, in minutes, the purger runs its cleanup pass. Sourced from REPODB_PURGER_FREQUENCY_IN_MINUTES.5

visualization

The Grafana-based dashboard used to browse and chart the telemetry your app has published.

Environment VariableDescriptionDefault
GF_SECURITY_ADMIN_PASSWORDAdmin password for signing into the Grafana dashboard.RepoDB2026
REPODB_PG_HOSTPostgres host the dashboard's data source connects to.pgsql
REPODB_PG_PORTPostgres port the dashboard's data source connects to.5432
REPODB_PG_PASSWORDPostgres password used by the dashboard's data source connection.RepoDB2026
REPODB_COMPANY_NAMECompany name shown in the dashboard's branding.Your Company Name
REPODB_COMPANY_LOGOURL of the logo shown in the dashboard's branding.RepoDB's logo on GitHub
REPODB_API_KEYAPI key the dashboard uses when calling the collector/query API.RepoDB2026

Volumes and networks

Two named volumes persist state across restarts: pgdata (the Postgres data directory) and telemetry_data (the shared directory filedatasinker writes to and query reads from). All services share a single bridge network, repodb, so they can reach each other by service name (e.g. pgsql, collector).

License

Apache-2.0 — Copyright © 2018 Michael Camara Pendon