$npx -y skills add Aaronontheweb/dotnet-skills --skill opentelementry-dotnet-instrumentationProvides guidance for implementing OpenTelemetry instrumentation in .NET codebases, covering tracing (Activities/Spans), metrics, logs, naming conventions, error handling, performance, SDK setup, resources, context propagation, and API design best practices.
| 1 | # OpenTelemetry .NET Instrumentation Skill |
| 2 | |
| 3 | ## When to Use |
| 4 | |
| 5 | - Adding OpenTelemetry instrumentation to .NET code (traces, metrics, logs) |
| 6 | - Creating or modifying ActivitySources, Meters, or ILogger usage |
| 7 | - Setting up the OpenTelemetry SDK, resources, exporters, or sampling |
| 8 | - Reviewing telemetry implementations for spec compliance |
| 9 | - Optimizing instrumentation performance |
| 10 | - Designing telemetry APIs that become part of the public surface |
| 11 | - Implementing context propagation across service boundaries |
| 12 | |
| 13 | ## Architecture: .NET Is Different |
| 14 | |
| 15 | **CRITICAL**: The .NET OpenTelemetry implementation is fundamentally different from other platforms. .NET provides tracing, metrics, and logging APIs **in the framework itself**. |
| 16 | That means **OTel does not provide a separate instrumentation API** — it uses the built-in .NET APIs and acts as the collection/export layer. |
| 17 | |
| 18 | ### The Three Built-in .NET APIs (Primary — Zero Dependencies) |
| 19 | |
| 20 | | Signal | .NET Framework API | Namespace | |
| 21 | |--------|-------------------|-----------| |
| 22 | | **Tracing** | `ActivitySource` / `Activity` | `System.Diagnostics` | |
| 23 | | **Metrics** | `Meter` / `Counter<T>` / `Histogram<T>` / etc. | `System.Diagnostics.Metrics` | |
| 24 | | **Logging** | `ILogger<T>` | `Microsoft.Extensions.Logging` | |
| 25 | |
| 26 | These are **the primary and only APIs** library authors should use for instrumentation. |
| 27 | They ship with the .NET runtime — **no NuGet packages required**. |
| 28 | |
| 29 | ### The OTel Collection/Export Layer (Secondary — Application Root Only) |
| 30 | |
| 31 | OTel NuGet packages are the **collection and export layer**, added only at the application |
| 32 | composition root (not in libraries): |
| 33 | |
| 34 | | Package | Purpose | When to add | |
| 35 | |---------|---------|-------------| |
| 36 | | `OpenTelemetry.Extensions.Hosting` | DI integration for ASP.NET Core / generic host | Application only | |
| 37 | | `OpenTelemetry.Exporter.Console` | Console exporter (dev/testing) | Application only | |
| 38 | | `OpenTelemetry.Exporter.OpenTelemetryProtocol` | OTLP exporter (production) | Application only | |
| 39 | | `OpenTelemetry.Exporter.Prometheus*` | Prometheus metrics endpoint | Application only | |
| 40 | | `OpenTelemetry.Instrumentation.AspNetCore` | Auto-instrument ASP.NET Core requests | Application only | |
| 41 | | `OpenTelemetry.Instrumentation.Http` | Auto-instrument HttpClient calls | Application only | |
| 42 | | `OpenTelemetry.Instrumentation.SqlClient` | Auto-instrument SQL calls | Application only | |
| 43 | |
| 44 | ### Package Decision Guide |
| 45 | |
| 46 | **Before adding ANY OpenTelemetry NuGet package, discuss the trade-off with the user:** |
| 47 | |
| 48 | > "You're about to add an OTel NuGet package. Is this an application where you need to |
| 49 | > export telemetry to an observability backend (Jaeger, Prometheus, OTLP collector)? |
| 50 | > If you're writing a library, you likely need **zero** OTel packages — just use |
| 51 | > `System.Diagnostics.ActivitySource` / `System.Diagnostics.Metrics.Meter` and let the |
| 52 | > consuming application configure the export pipeline. Do you want to proceed?" |
| 53 | |
| 54 | **Library authors**: Add **nothing**. Use only `System.Diagnostics.*` and `ILogger`. |
| 55 | The consuming application wires up the SDK and exporters. |
| 56 | |
| 57 | **Application authors**: Add `OpenTelemetry.Extensions.Hosting` + the exporters and instrumentation libraries you need. See [sdk-resources-and-logs-reference.md](sdk-resources-and-logs-reference.md) for full setup patterns. |
| 58 | |
| 59 | **Never add** `OpenTelemetry.Api` to a library — `System.Diagnostics.*` IS the API. |
| 60 | |
| 61 | For SDK setup, resource configuration, exporters, sampling, and logs integration, see [sdk-resources-and-logs-reference.md](sdk-resources-and-logs-reference.md). |
| 62 | |
| 63 | ## Core Principles |
| 64 | |
| 65 | ### Resiliency First |
| 66 | **CRITICAL**: Exceptions in diagnostic/tracing/metrics logic MUST NEVER impact application processing. |
| 67 | - Assume Activity instances can be null. Always protect against null Activity references except in Activity extension methods (use `activity?.ExtensionMethod()`) |
| 68 | - Guard all instrumentation code with appropriate null checks |
| 69 | |
| 70 | ### API Surface Awareness |
| 71 | - Any telemetry emitted becomes part of the public API surface |
| 72 | - Changes are subject to breaking changes guidelines |
| 73 | - Telemetry should be emitted by default (users opt-in to collection via OpenTelemetry extensions) |
| 74 | - Exception: High-cardinality metric dimensions may require explicit opt-in |
| 75 | |
| 76 | ### Standards Compliance |
| 77 | - Follow Microsoft best practices for [distributed tracing instrumentation](https://learn.microsoft.com/en-us/dotnet/core/diagnostics/distributed-tracing-instrumentation-walkthroughs) |
| 78 | - Follow [OpenTelemetry semantic conventions](https://opentelemetry.io/docs/specs/semconv/) |
| 79 | - Attribute values support: **string, boolean, double (IEEE 754), int |