Skip to content

Configuration Telemetry

quyvu edited this page Oct 13, 2026 · 2 revisions

Telemetry & Observability

FxMap emits OpenTelemetry-compatible traces for mapping requests, server-side processing and data access, so you can see every lookup across your services.

Overview

Distributed tracing

One span per request and key on the client, on the server and on the data provider, linked into one trace across services.

Standard .NET model

FxMap publishes through an ActivitySource named FxMap. Any OpenTelemetry exporter can ship it.

No cost when unobserved

When no listener is configured, creating an activity returns null and allocates nothing. You pay only for what you subscribe to.

Traces only, for now

FxMap currently publishes traces. It does not publish metrics (counters or histograms), so there is no FxMap meter to subscribe to. If you need numbers, derive them from the spans in your tracing backend, for example request duration per distributed key.

Trace Visualization

An illustrative trace of an order list that maps users and products, then the provinces of those users. The user and product requests run in parallel; the province request starts when the users have come back. The timings are made up; the shape is what FxMap produces.

GET /orders

trace-id: 7f8a9b2c3d4e5f6a

10 Spans0.0ms / 62ms

Service & Operation

0ms13ms26ms39ms52ms

orders-service

GET /orders

orders-service

fxmap.request UserDistributedKey

users-service

fxmap.process UserDistributedKey

users-service

fxmap.db.query postgresql

orders-service

fxmap.request ProductDistributedKey

products-service

fxmap.process ProductDistributedKey

products-service

fxmap.db.query postgresql

orders-service

fxmap.request ProvinceDistributedKey

users-service

fxmap.process ProvinceDistributedKey

users-service

fxmap.db.query postgresql

Services:

orders-service

users-service

products-service

Configuration

Add the OpenTelemetry packages you need and listen to the FxMap source:

dotnet add package OpenTelemetry.Extensions.Hosting
dotnet add package OpenTelemetry.Instrumentation.AspNetCore
dotnet add package OpenTelemetry.Exporter.OpenTelemetryProtocol
builder.Services.AddOpenTelemetry()
    .ConfigureResource(r => r.AddService("orders-service"))
    .WithTracing(tracing => tracing
        .AddSource("FxMap")                 // FxMap's activities
        .AddAspNetCoreInstrumentation()     // the incoming HTTP request
        .AddOtlpExporter());                // Jaeger, Tempo, an OpenTelemetry collector, ...

Do this in both services: the one that maps and the one that owns the data. When both subscribe, and the transport carries the trace context, the two halves of a request appear in one trace.

Activities

Activity Kind Where What it covers
fxmap.request Client The service that maps Sending one request for one distributed key over a transport
fxmap.process Server The service that owns the data Handling that request
fxmap.db.query Client The service that owns the data The data provider query (Entity Framework Core or MongoDB)

Trace context across services

On the message-based transports FxMap passes the trace context in the message headers, in the W3C traceparent format. The server side starts its fxmap.process activity as a child of the caller's request, so one trace spans the mapping service and the owning service without extra code.

Failures

When a request fails, the exception is recorded on the activity with an error status, its type and its message, so failed lookups are easy to filter on in your backend.

Tags

FxMap tags

Tag Meaning
fxmap.distributed_key The distributed key being mapped, for example UserDistributedKey
fxmap.transport Transport used for the request (on fxmap.request)
fxmap.version FxMap version
fxmap.expressions The expressions requested for that key
fxmap.selector_count Number of distinct ids in the request
fxmap.selector_ids The first few ids of the request (up to five)
fxmap.item_count Number of items that came back

Messaging tags (broker transports)

Tag Meaning
messaging.system Messaging system of the transport
messaging.destination Destination queue or topic
messaging.message_id Message identifier
messaging.operation Operation type

Database tags

Tag Meaning
db.system Database system
db.name Database name
db.statement Statement, when the provider records it
db.collection Collection or table
db.operation Operation

Error tags

Tag Meaning
otel.status_description Status description, set together with an error status
exception.type Exception type of a failed request
exception.message Exception message
exception.stacktrace Exception stack trace

fxmap.selector_count next to fxmap.item_count tells you whether batching worked and whether the owner answered for every id you sent.

Exporters

Jaeger, through OTLP

Run Jaeger locally and send spans to it with the OTLP exporter:

docker run -d --name jaeger \
  -p 16686:16686 -p 4317:4317 -p 4318:4318 \
  jaegertracing/all-in-one:latest
 
# open http://localhost:16686
.WithTracing(tracing => tracing
    .AddSource("FxMap")
    .AddOtlpExporter(o => o.Endpoint = new Uri("http://localhost:4317")));

OTLP collector (Grafana Tempo, an OpenTelemetry Collector, vendors)

.WithTracing(tracing => tracing
    .AddSource("FxMap")
    .AddOtlpExporter(o =>
    {
        o.Endpoint = new Uri("https://otel-collector.internal:4317");
        o.Protocol = OpenTelemetry.Exporter.OtlpExportProtocol.Grpc;
    }));

Azure Monitor / Application Insights

dotnet add package Azure.Monitor.OpenTelemetry.Exporter
.WithTracing(tracing => tracing
    .AddSource("FxMap")
    .AddAzureMonitorTraceExporter(o => o.ConnectionString = "<your-connection-string>"));

Best Practices

  • Subscribe to FxMap in every service that maps or owns data, or the trace will have gaps.
  • Sample in busy services. Head sampling in your OpenTelemetry setup keeps the cost bounded; keep sampling higher in staging.
  • Mind what the tags carry: fxmap.selector_ids holds the first ids of a request and db.statement can hold a statement. Do not ship them to a backend that should not see them.
  • Use fxmap.selector_count to check that batching works: many fxmap.request spans for one key point to objects being mapped one at a time.

For a walkthrough of reading a trace, see Tracing FxMap with OpenTelemetry.


Source: https://fxmapper.net/docs/configuration/telemetry/ — the website is always the most up to date version.

Clone this wiki locally