Repository navigation
Configuration Telemetry
FxMap emits OpenTelemetry-compatible traces for mapping requests, server-side processing and data access, so you can see every lookup across your services.
One span per request and key on the client, on the server and on the data provider, linked into one trace across services.
FxMap publishes through an ActivitySource named FxMap. Any OpenTelemetry exporter can ship it.
When no listener is configured, creating an activity returns null and allocates nothing. You pay only for what you subscribe to.
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.
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
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.OpenTelemetryProtocolbuilder.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.
| 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) |
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.
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.
| 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 |
| Tag | Meaning |
|---|---|
| messaging.system | Messaging system of the transport |
| messaging.destination | Destination queue or topic |
| messaging.message_id | Message identifier |
| messaging.operation | Operation type |
| 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 |
| 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.
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")));.WithTracing(tracing => tracing
.AddSource("FxMap")
.AddOtlpExporter(o =>
{
o.Endpoint = new Uri("https://otel-collector.internal:4317");
o.Protocol = OpenTelemetry.Exporter.OtlpExportProtocol.Grpc;
}));dotnet add package Azure.Monitor.OpenTelemetry.Exporter.WithTracing(tracing => tracing
.AddSource("FxMap")
.AddAzureMonitorTraceExporter(o => o.ConnectionString = "<your-connection-string>"));- Subscribe to
FxMapin 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_idsholds the first ids of a request anddb.statementcan hold a statement. Do not ship them to a backend that should not see them. - Use
fxmap.selector_countto check that batching works: manyfxmap.requestspans 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.
Introduction
Getting Started
Configuration
- Service Registration
- Entities & Profiles
- Handlers
- Pipelines
- Strongly Typed IDs
- Error Handling
- Retry Policy
- Supervisor
- Telemetry
- Kestrel (HTTP/2)
- Analyzers
Expressions
- Overview
- Property Access
- Filters, Sorting & Paging
- Functions
- Aggregations
- Projections
- Coalesce & Ternary
- GroupBy
Data Providers
Transports
Integrations
Quality
AI Assistants
Migration
Release Notes