telemetry
Skill1 starsChanged 6 days agoMITView on GitHub
How OpenTelemetry traces, metrics and logs work - the standard OTEL_* settings that switch exporting on, the span LoggingBehaviour gives every use case, EF Core's built-in metrics, what each presentation layer instruments, the Aspire dashboard in Docker Compose, and the signals we're waiting on. Use when adding a span, metric or tag, changing what's exported or where, reading telemetry locally, or adding a dependency that should be traced.
11 other projects use a version of this.
Adopted by
Most recently taken up by
- MMACABRE/SKILLStheir own version, first seen Nov 8, 2026
- egregore-labs/egregoretheir own version, first seen Nov 6, 2026
- SethGammon/Citadeltheir own version, first seen Nov 4, 2026
- LazyIsEfficient/agentic-ostheir own version, first seen Oct 22, 2026
- microsoft/power-platform-skillstheir own version, first seen Oct 13, 2026
- openai/pluginstheir own version, first seen Oct 13, 2026
Used with
Projects with it also use dashboard, create-skill and 1 more.
Other files people use alongside this one.
Files found in the same public projects as a version of this one, more often than they turn up anywhere else. Each project counts once, large collections count for less, and this file's own repository is left out.
GoogleSkilldashboard
Configures and launches the GKE Capacity & Triage Dashboard scoped to a GCP project ID, GKE cluster name, or target ML workload ID. Uses the configure-and-launch-dashboard action and launch-workload-dashboard workflow to verify local dashboard health, discover cluster capacity, trigger live scans, and generate deep-linked URLs. Use when the user types "/dashboard", says "launch dashboard", "open dashboard", "show capacity", or "view triage dashboard" with a project, cluster, or workload. Don't use for general workload log querying or automated failure attribution (use the troubleshoot skill).
Also in 3 projects that use this
ElasticSkillcreate-skill
Interactively create a new Claude Code skill and add it to the elastic-docs-skills catalog. Use when the user wants to generate a new skill, scaffold a slash command, or build automation for docs tasks.
Also in 3 projects that use this
VercelSkillsetup
Set up Vercel CLI and project configuration. Use when the user says "set up Vercel", "configure Vercel", "link to Vercel", or "vercel init".
Also in 3 projects that use this
Other versions11 projects use a version of this.
Word for word · 0
None found.
Edited · 0
None found.
Wrote their own version · 11
- carla-simulator/carla★ 15ksame name
- openai/plugins★ 7.8ksame name
- microsoft/power-platform-skills★ 1.1ksame name
- SethGammon/Citadel★ 927same name
- egregore-labs/egregore★ 293same name
- magnus919/agent-skills★ 172same name
- LazyIsEfficient/agentic-os★ 17same name
- mayankjain1815-commits/CITADEL★ 4same name
- MMACABRE/SKILLS★ 1same name
- academysim/claude-code-skills★ 0same name
1 more not listed
How matches are found. Word for word: the exact same text. Edited: shares passages with this file (“99% same” means 99% of its five-word phrases also appear here; 10% or more counts). Their own version: similar meaning, or, weakest, the same name. We can’t tell which project had it first. Projects are counted among the 200 most-starred candidates, and mentions are links to the repository we found, up to 50 per site, so both counts are a floor.
In this repository40 other files it gives its agents.
- AGENTS.mdAGENTS.md
- CLAUDE.mdCLAUDE.md
- add-a-use-caseSkill
- api-conventionsSkill
- branches-and-pull-requestsSkill
- cancellationSkill
- ci-for-your-solutionSkill
- ci-pipelineSkill
- clean-architecture-layersSkill
- configuration-and-environmentsSkill
- coverageSkill
- csharp-house-styleSkill
- data-access-ef-coreSkill
- database-migrationsSkill
- docker-and-composeSkill
- docs-and-voiceSkill
- errors-and-exceptionsSkill
- expose-a-use-caseSkill
- family-syncSkill
- health-checksSkill
- integration-testsSkill
- json-serializationSkill
- mapping-with-mapperlySkill
- mcp-inspectorSkill
- mediatorSkill
- optional-token-authSkill
- packages-and-dependenciesSkill
- pagingSkill
- presentation-integration-testsSkill
- releasesSkill
- sample-dataSkill
- security-findingsSkill
- serilogSkill
- template-authoringSkill
- test-designSkill
- time-providerSkill
- unit-testsSkill
- validationSkill
- writing-a-skillSkill
- xml-docs-and-openapiSkill
The file
We split this skill into the rules it gives an agent
7 rules. 0 are common, 5 are distinctive, and 2 are very specific to this project.
0
Common
Most of the 9 edited versions we read keep these.
5
Distinctive
This author's own choices. Worth a look.
2
Very specific
Tied to their project's names, files or tools. Probably skip.
- Common
- Distinctive
- Very specific
- Distinctive: line 48
Before writing any telemetry code, check what the instrumentation already records.
- Distinctive: line 51
Use stable packages only. When the only instrumentation is a prerelease package, go without that signal and add it to the watch list below.
- Very specific: line 52
Test spans with an ActivityListener that keeps only the test's own trace (unit-tests).
- Distinctive: line 102
Add a prerelease package, or hand-write instrumentation, to get a signal a package will give us later.
- Distinctive: line 103
Add a custom metric that repeats one the instrumentation already records.
- Distinctive: line 104
Put ids, tokens or personal data in span names, tags or metric tags.
- Very specific: line 107
Start a span with new Activity(...).
“Common” is measured: kept by at least 6 in 10 of the 9 edited versions of this file we could read. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.
Files
Telemetry
The rule
Telemetry is OpenTelemetry, and it leaves the app over OTLP and nothing else. No vendor SDK, no Aspire package, nothing that ties the code to one backend. Signals come from stable Microsoft and OpenTelemetry instrumentation; we write our own only where nothing covers it, and that's one span per use case. Traces and metrics are always collected; they're exported, with the logs, only when OTEL_EXPORTER_OTLP_ENDPOINT is set. Every standard OTEL_* setting works as the OpenTelemetry SDK documents it.
| Signal | What we send | Where it comes from |
| Traces | A span for each incoming request and each use case, plus outgoing HTTP calls | Presentation instrumentation, LoggingBehaviour |
| Metrics | EF Core's own meter, ASP.NET Core, HttpClient and runtime metrics, with exemplars linking a measurement to a trace | Microsoft.EntityFrameworkCore, Presentation instrumentation |
| Logs | Every Serilog event, carrying the trace and span IDs of whatever was running when it was written. Validation failures and missing entities are logged inside the use case span, so they sit on its trace | Serilog's OpenTelemetry sink (serilog) |
| Baggage | Propagated with the trace context by the ASP.NET Core and HttpClient instrumentation | W3C baggage header |
| Events | An exception event on the use case span for unexpected errors | LoggingBehaviour |
Each layer publishes under its own name, and only the presentation layer's startup knows about the OpenTelemetry SDK:
| Layer | Publishes | How |
| Application | ApplicationTelemetry.Name activity source: a span per use case, named after the request, tagged with application.request.name and application.request.outcome | LoggingBehaviour, with System.Diagnostics only, so Application stays free of telemetry packages |
| Infrastructure | Microsoft.EntityFrameworkCore meter: queries, saves, active contexts, compiled query cache | Built into EF Core; startup subscribes to it by name |
| Presentation | service.name, service.version and deployment.environment.name on everything, plus its own instrumentation | TelemetrySettings and the startup's Telemetry region |
What each presentation layer adds:
| Template | Instrumentation |
| Minimal API, Web API | ASP.NET Core and HttpClient traces and metrics, runtime metrics and, with authentication, its meters. Health endpoints aren't traced |
| GraphQL | The same, plus Hot Chocolate's resolver and operation spans from HotChocolate.Diagnostics |
| MCP | The same, plus the MCP SDK's own Experimental.ModelContextProtocol spans and mcp.*.operation.duration metrics |
| Lambda | A span per invocation from OpenTelemetry.Instrumentation.AWSLambda, and runtime metrics. Traces and metrics are flushed before the function returns, because Lambda can freeze the environment as soon as it does |
The Lambda template builds its tracer and meter providers once in Startup with Sdk.CreateTracerProviderBuilder() and Sdk.CreateMeterProviderBuilder() rather than AddOpenTelemetry(), because the classes Lambda Annotations generates build two service providers from the same services, and each would otherwise export everything again. X-Ray context extraction is off, so a "not sampled" header from Lambda can't switch tracing off; the collector can still send to X-Ray. Lambda container images can't use layers, so in AWS the collector is either built into the image (the ADOT collector extension) or runs as a gateway.
The app sends to an OpenTelemetry Collector, never straight to a backend, because that's how it should run in production: the collector owns batching, retries, sampling, scrubbing and the choice of backend, so none of that lives in the app. otel-collector.yaml holds its configuration: an OTLP receiver on 4317 (gRPC) and 4318 (HTTP), the memory_limiter and batch processors, and one exporter per backend.
Locally, Docker Compose runs the collector (otel/opentelemetry-collector) and the Aspire dashboard (mcr.microsoft.com/dotnet/aspire-dashboard), and the collector forwards everything to the dashboard. The dashboard is only a container that receives OTLP and shows logs, traces and metrics on the template's dashboard port (docker-and-compose); it keeps everything in memory, so it's empty after a restart. In production, run a collector beside the app or as a gateway and swap the dashboard exporter for your backend's.
Steps
- A new use case needs nothing:
LoggingBehaviourgives it a span named after the request class, with its outcome as a tag. - Before writing any telemetry code, check what the instrumentation already records. Request durations per route, GraphQL operations, MCP tool calls and Lambda invocations are all covered, so we don't count or time them again.
- To trace work inside Application, start a child span with
using var activity = ApplicationTelemetry.ActivitySource.StartActivity("Name");, and use the semantic convention tag names where one exists. - A new dependency in Infrastructure (a queue, an HTTP API) gets its spans and metrics from its own instrumentation package, if a stable one exists. Subscribe to its source or meter name in the presentation layer's startup.
- Use stable packages only. When the only instrumentation is a prerelease package, go without that signal and add it to the watch list below.
- Test spans with an
ActivityListenerthat keeps only the test's own trace (unit-tests). The integration tests send atraceparentheader and check the request and use case spans join up. - To send telemetry somewhere new, add an exporter to
otel-collector.yamland list it in the pipelines. The app's settings don't change. - To see it locally, run
docker compose up -d --buildand open the dashboard on the portdocs/RUN.mdlists. For adotnet run, start the collector withdocker compose up -d otel-collectorand setOTEL_EXPORTER_OTLP_ENDPOINTto its gRPC port,http://$(docker compose port otel-collector 4317).
Example
// src/Application/Common/Behaviours/LoggingBehaviour.cs
using var activity = ApplicationTelemetry.ActivitySource.StartActivity(RequestName);
_ = activity?.SetTag(ApplicationTelemetry.RequestNameTag, RequestName);
...
catch (Exception exception)
{
_ = activity?.SetTag(ApplicationTelemetry.RequestOutcomeTag, "error")
.SetStatus(ActivityStatusCode.Error, exception.Message)
.AddException(exception);
throw;
}# docker-compose.yml
environment:
OTEL_EXPORTER_OTLP_ENDPOINT: http://otel-collector:4317
OTEL_EXPORTER_OTLP_PROTOCOL: grpc# otel-collector.yaml
exporters:
otlp_grpc/aspire:
endpoint: aspire-dashboard:18889
tls:
insecure: trueWatch list
These signals and packages aren't stable for .NET yet. Check them when dependencies are updated, and adopt each one once it has a stable release:
OpenTelemetry.Instrumentation.EntityFrameworkCore: adds a span per SQL command. Until it's stable there are no database spans, only EF Core's metrics.- Profiles: there's no stable .NET SDK for the profiling signal.
- The OpenTelemetry Events API: until then, events are
[LoggerMessage]logs.
Don't
- Reference an OpenTelemetry, Aspire or vendor package from Application or Infrastructure. They publish with
System.Diagnostics, and Presentation subscribes. - Export anywhere but OTLP, or hard-code an endpoint. Settings come from the
OTEL_*variables. - Point the app straight at a backend, the dashboard included. It sends to a collector, and the collector decides where things go.
- Add a prerelease package, or hand-write instrumentation, to get a signal a package will give us later.
- Add a custom metric that repeats one the instrumentation already records.
- Put ids, tokens or personal data in span names, tags or metric tags.
- Mark a span as an error for a validation failure or a missing entity. The caller got an answer; the outcome tag and the log say what happened.
- Trace the health endpoints. Probes would bury everything else.
- Start a span with
new Activity(...). Use the layer'sActivitySource, so nothing is recorded when nobody is listening.
Check
dotnet test --filter "FullyQualifiedName~Telemetry|FullyQualifiedName~LoggingBehaviour" # use case span and end-to-end trace tests
docker compose up -d --build # then open the dashboard on the port docs/RUN.md lists and make a requestDoes it work?
Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.
No reviews yet
People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.
- It worked
- Partly
- It didn't
Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.
Your trail
Files you open will collect here, so you can find them again.
Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.
Now do this for your own.
Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.

