/opentelementry-dotnet-instrumentation
Provides 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.
$ npx -y skills add aaronontheweb/dotnet-skills --skill opentelementry-dotnet-instrumentation --agent claude-codeHow it fires
How this skill gets triggered: by you, by Claude, or both.
- Fires itselfAuto-invocation. Claude auto-loads it when your prompt matches the work.Auto-invocation is when the right skill fires by itself at the right moment, driven by a FLOW.md router and a hook, instead of you invoking it by name. It is the difference between a skill being installed and a skill actually getting used.Read the full definition →
- You can call itInvoke it directly when you want it.
- Slash command
/opentelementry-dotnet-instrumentation
Context preview
The summary Claude sees to decide when to auto-load this skill.
Provides 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.
SKILL.md
opentelementry-dotnet-instrumentation.SKILL.mdname: opentelemetry-net-instrumentation
description: Provides 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.
version: 2.0.0
tags:
- opentelemetry
- dotnet
- observability
- tracing
- metrics
- logs
- performance
OpenTelemetry .NET Instrumentation Skill
When to Use
- Adding OpenTelemetry instrumentation to .NET code (traces, metrics, logs)
- Creating or modifying ActivitySources, Meters, or ILogger usage
- Setting up the OpenTelemetry SDK, resources, exporters, or sampling
- Reviewing telemetry implementations for spec compliance
- Optimizing instrumentation performance
- Designing telemetry APIs that become part of the public surface
- Implementing context propagation across service boundaries
Architecture: .NET Is Different
**CRITICAL**: The .NET OpenTelemetry implementation is fundamentally different from other platforms. .NET provides tracing, metrics, and logging APIs **in the framework itself**. That means **OTel does not provide a separate instrumentation API** — it uses the built-in .NET APIs and acts as the collection/export layer.
The Three Built-in .NET APIs (Primary — Zero Dependencies)
| Signal | .NET Framework API | Namespace | |--------|-------------------|-----------| | **Tracing** | `ActivitySource` / `Activity` | `System.Diagnostics` | | **Metrics** | `Meter` / `Counter<T>` / `Histogram<T>` / etc. | `System.Diagnostics.Metrics` | | **Logging** | `ILogger<T>` | `Microsoft.Extensions.Logging` |
These are **the primary and only APIs** library authors should use for instrumentation. They ship with the .NET runtime — **no NuGet packages required**.
The OTel Collection/Export Layer (Secondary — Application Root Only)
OTel NuGet packages are the **collection and export layer**, added only at the application composition root (not in libraries):
| Package | Purpose | When to add | |---------|---------|-------------| | `OpenTelemetry.Extensions.Hosting` | DI integration for ASP.NET Core / generic host | Application only | | `OpenTelemetry.Exporter.Console` | Console exporter (dev/testing) | Application only | | `OpenTelemetry.Exporter.OpenTelemetryProtocol` | OTLP exporter (production) | Application only | | `OpenTelemetry.Exporter.Prometheus*` | Prometheus metrics endpoint | Application only | | `OpenTelemetry.Instrumentation.AspNetCore` | Auto-instrument ASP.NET Core requests | Application only | | `OpenTelemetry.Instrumentation.Http` | Auto-instrument HttpClient calls | Application only | | `OpenTelemetry.Instrumentation.SqlClient` | Auto-instrument SQL calls | Application only |
Package Decision Guide
**Before adding ANY OpenTelemetry NuGet package, discuss the trade-off with the user:**
> "You're about to add an OTel NuGet package. Is this an application where you need to > export telemetry to an observability backend (Jaeger, Prometheus, OTLP collector)? > If you're writing a library, you likely need **zero** OTel packages — just use > `System.Diagnostics.ActivitySource` / `System.Diagnostics.Metrics.Meter` and let the > consuming application configure the export pipeline. Do you want to proceed?"
**Library authors**: Add **nothing**. Use only `System.Diagnostics.*` and `ILogger`. The consuming application wires up the SDK and exporters.
**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.
**Never add** `OpenTelemetry.Api` to a library — `System.Diagnostics.*` IS the API.
For SDK setup, resource configuration, exporters, sampling, and logs integration, see [sdk-resources-and-logs-reference.md](sdk-resources-and-logs-reference.md).
Core Principles
Resiliency First
**CRITICAL**: Exceptions in diagnostic/tracing/metrics logic MUST NEVER impact application processing.
- Assume Activity instances can be null. Always protect against null Activity references except in Activity extension methods (use `activity?.ExtensionMethod()`)
- Guard all instrumentation code with appropriate null checks
API Surface Awareness
- Any telemetry emitted becomes part of the public API surface
- Changes are subject to breaking changes guidelines
- Telemetry should be emitted by default (users opt-in to collection via OpenTelemetry extensions)
- Exception: High-cardinality metric dimensions may require explicit opt-in
Standards Compliance
- Follow Microsoft best practices for [distributed tracing instrumentation](https://learn.microsoft.com/en-us/dotnet/core/diagnostics/distributed-tracing-instrumentation-walkthroughs)
- Follow [OpenTelemetry semantic conventions](https://opentelemetry.io/docs/specs/semconv/)
- Attribute values support: **string, boolean, double (IEEE 754), int64, byte arrays, and homogeneous arrays** of these primitive types. Null/empty values are valid and meaningful per the [OTel AnyValue spec](https://opentelemetry.io/docs/specs/otel/common/#anyvalue) — they MUST be stored and passed to exporters.
- Attribute **keys** must be non-null, non-empty strings
Traces / Spans (Activities)
ActivitySource Setup
// ✅ CORRECT: Use ActivitySource, not DiagnosticSource
public class MyFeature
{
// Primary ActivitySource - name typically matches the component or NuGet package name
private static readonly ActivitySource ActivitySource = new("MyApp.MyComponent", "1.0.0");
// Specialized ActivitySource for opt-in scenarios
private static readonly ActivitySource DetailedActivitySource = new("MyApp.MyComponent.Detailed", "1.0.0");
}**Rules**:
- Every component defines a primary `ActivitySource` for mainstream activities
- Name typically matches the component or NuGet package (e.g., `"MyCompany.MyLibrary"`)
- Version
Read more
name: opentelemetry-net-instrumentation description: Provides 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. version: 2.0.0 tags: - opentelemetry - dotnet - observability - tracing - metrics - logs - performance
OpenTelemetry .NET Instrumentation Skill
When to Use
- Adding OpenTelemetry instrumentation to .NET code (traces, metrics, logs)
- Creating or modifying ActivitySources, Meters, or ILogger usage
- Setting up the OpenTelemetry SDK, resources, exporters, or sampling
- Reviewing telemetry implementations for spec compliance
- Optimizing instrumentation performance
- Designing telemetry APIs that become part of the public surface
- Implementing context propagation across service boundaries
Architecture: .NET Is Different
**CRITICAL**: The .NET OpenTelemetry implementation is fundamentally different from other platforms. .NET provides tracing, metrics, and logging APIs **in the framework itself**. That means **OTel does not provide a separate instrumentation API** — it uses the built-in .NET APIs and acts as the collection/export layer.
The Three Built-in .NET APIs (Primary — Zero Dependencies)
| Signal | .NET Framework API | Namespace | |--------|-------------------|-----------| | **Tracing** | `ActivitySource` / `Activity` | `System.Diagnostics` | | **Metrics** | `Meter` / `Counter<T>` / `Histogram<T>` / etc. | `System.Diagnostics.Metrics` | | **Logging** | `ILogger<T>` | `Microsoft.Extensions.Logging` |
These are **the primary and only APIs** library authors should use for instrumentation. They ship with the .NET runtime — **no NuGet packages required**.
The OTel Collection/Export Layer (Secondary — Application Root Only)
OTel NuGet packages are the **collection and export layer**, added only at the application composition root (not in libraries):
| Package | Purpose | When to add | |---------|---------|-------------| | `OpenTelemetry.Extensions.Hosting` | DI integration for ASP.NET Core / generic host | Application only | | `OpenTelemetry.Exporter.Console` | Console exporter (dev/testing) | Application only | | `OpenTelemetry.Exporter.OpenTelemetryProtocol` | OTLP exporter (production) | Application only | | `OpenTelemetry.Exporter.Prometheus*` | Prometheus metrics endpoint | Application only | | `OpenTelemetry.Instrumentation.AspNetCore` | Auto-instrument ASP.NET Core requests | Application only | | `OpenTelemetry.Instrumentation.Http` | Auto-instrument HttpClient calls | Application only | | `OpenTelemetry.Instrumentation.SqlClient` | Auto-instrument SQL calls | Application only |
Package Decision Guide
**Before adding ANY OpenTelemetry NuGet package, discuss the trade-off with the user:**
> "You're about to add an OTel NuGet package. Is this an application where you need to > export telemetry to an observability backend (Jaeger, Prometheus, OTLP collector)? > If you're writing a library, you likely need **zero** OTel packages — just use > `System.Diagnostics.ActivitySource` / `System.Diagnostics.Metrics.Meter` and let the > consuming application configure the export pipeline. Do you want to proceed?"
**Library authors**: Add **nothing**. Use only `System.Diagnostics.*` and `ILogger`. The consuming application wires up the SDK and exporters.
**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.
**Never add** `OpenTelemetry.Api` to a library — `System.Diagnostics.*` IS the API.
For SDK setup, resource configuration, exporters, sampling, and logs integration, see [sdk-resources-and-logs-reference.md](sdk-resources-and-logs-reference.md).
Core Principles
Resiliency First
**CRITICAL**: Exceptions in diagnostic/tracing/metrics logic MUST NEVER impact application processing.
- Assume Activity instances can be null. Always protect against null Activity references except in Activity extension methods (use `activity?.ExtensionMethod()`)
- Guard all instrumentation code with appropriate null checks
API Surface Awareness
- Any telemetry emitted becomes part of the public API surface
- Changes are subject to breaking changes guidelines
- Telemetry should be emitted by default (users opt-in to collection via OpenTelemetry extensions)
- Exception: High-cardinality metric dimensions may require explicit opt-in
Standards Compliance
- Follow Microsoft best practices for [distributed tracing instrumentation](https://learn.microsoft.com/en-us/dotnet/core/diagnostics/distributed-tracing-instrumentation-walkthroughs)
- Follow [OpenTelemetry semantic conventions](https://opentelemetry.io/docs/specs/semconv/)
- Attribute values support: **string, boolean, double (IEEE 754), int64, byte arrays, and homogeneous arrays** of these primitive types. Null/empty values are valid and meaningful per the [OTel AnyValue spec](https://opentelemetry.io/docs/specs/otel/common/#anyvalue) — they MUST be stored and passed to exporters.
- Attribute **keys** must be non-null, non-empty strings
Traces / Spans (Activities)
ActivitySource Setup
// ✅ CORRECT: Use ActivitySource, not DiagnosticSource
public class MyFeature
{
// Primary ActivitySource - name typically matches the component or NuGet package name
private static readonly ActivitySource ActivitySource = new("MyApp.MyComponent", "1.0.0");
// Specialized ActivitySource for opt-in scenarios
private static readonly ActivitySource DetailedActivitySource = new("MyApp.MyComponent.Detailed", "1.0.0");
}**Rules**:
- Every component defines a primary `ActivitySource` for mainstream activities
- Name typically matches the component or NuGet package (e.g., `"MyCompany.MyLibrary"`)
- Version
A comprehensive AI coding plugin with 30 skills and 5 specialized agents for professional .NET development. Battle-tested patterns from production systems covering C#, Akka.NET, Aspire, EF Core, testing, and performance optimization.
Other skills on dotnet-skills.
- /akka-aspire-configuration
Configure Akka.NET with .NET Aspire for local development and production deployments. Covers actor system setup, clustering, persistence, Akka.Management integration, and Aspire orchestration patterns.
Open skill - /akka-best-practices
Critical Akka.NET best practices including EventStream vs DistributedPubSub, supervision strategies, error handling, Props vs DependencyResolver, work distribution patterns, and cluster/local mode abstractions for testability.
Open skill - /akka-hosting-actor-patterns
Patterns for building entity actors with Akka.Hosting - GenericChildPerEntityParent, message extractors, cluster sharding abstraction, akka-reminders, and ITimeProvider. Supports both local testing and clustered production modes.
Open skill - /akka-management
Akka.Management for cluster bootstrapping, service discovery (Kubernetes, Azure, Config), health checks, and dynamic cluster formation without static seed nodes.
Open skill - /akka-testing-patterns
Write unit and integration tests for Akka.NET actors using modern Akka.Hosting.TestKit patterns. Covers dependency injection, TestProbes, persistence testing, and actor interaction verification. Includes guidance on when to use traditional TestKit.
Open skill - /aspire-configuration
Configure Aspire AppHost to emit explicit app config via environment variables; keep app code free of Aspire clients and service discovery.
Open skill

