Token导航 LogoToken导航

Agent Skill · 开发

opentelemetry-net-instrumentation(OpenTelemetry NET instrumentation 命令行)

opentelemetry-net-instrumentation 用于处理 GitHub 仓库、Issue、Pull Request 和代码协作信息,适合在 Codex、Claude、Cursor、Gemini CLI 中需要围绕仓库状态、代码变更或协作事项进行整理时使用。可结合来源仓库、安装命令和原始 README 继续核验具体用法。安装前建议确认权限范围、维护状态,以及是否会触发联网、命令执行或文件读写。

opentelemetry-net-instrumentation 是开发类 Agent Skill,可用宿主为 Codex、Claude、Cursor、Gemini CLI,通过GitHub 仓库获取,权限为需要联网;许可证信息还不明确,第三方扫描已通过,按安装量在开发类的 21,746 个 Skill 里排第 11,257。

总安装 1,866周安装 77GitHub Stars 889下载 610核验 2026-05-01

安装说明

本站只整理中文说明,不托管安装包,也不代用户安装。
GitHub
许可证
unknown

安装方式

通过对话安装

复制提示词发给支持本地命令或 Skills 的 AI 助手,先确认命令和权限,再让它执行。

请帮我安装这个 Agent Skill:opentelemetry-net-instrumentation(OpenTelemetry NET instrumentation 命令行)
来源仓库:https://github.com/aaronontheweb/dotnet-skills
仓库路径:skills/opentelemetry-net-instrumentation
安装命令:
npx skills add https://github.com/aaronontheweb/dotnet-skills --skill OpenTelemetry-NET-Instrumentation
安装前请先检查当前环境是否支持对应 CLI,并向我确认将要执行的命令、安装目录、联网范围和文件读写权限;确认后再执行。

命令行安装

复制命令到本机终端执行。该命令会通过 npx skills 从第三方来源获取 Skill;本站只展示命令,不托管安装包,也不自动执行。

skills.shnpx skills
npx skills add https://github.com/aaronontheweb/dotnet-skills --skill OpenTelemetry-NET-Instrumentation

这个 Skill 是做什么的

开发类 Skill 面向写代码、改代码和排查问题,一般会读写仓库文件,部分还会执行构建或测试命令。

用于处理 GitHub 仓库、Issue、Pull Request 和代码协作信息,适合跟踪 .NET 项目变更。支持围绕仓库活动、代码审查与 Issue 管理进行信息组织。通过 npx skills add 命令从 dotnet-skills 仓库安装使用。需确认是否具备写权限及是否会执行系统级操作。

opentelemetry-net-instrumentation 属于开发类 Skill,可作为该场景下的辅助能力补充。

来源仓库内路径:skills/opentelemetry-net-instrumentation

上手步骤

4 步
  1. 1

    确认自己的宿主工具

    公开资料标注支持 Codex、Claude、Cursor、Gemini CLI;先确认自己用的是其中之一,再按对应工具的 Skills 目录放置。

  2. 2

    拿到安装命令

    可以直接复制的命令是 npx skills add https://github.com/aaronontheweb/dotnet-skills --skill OpenTeleme…;命令里的占位符换成自己的路径或密钥再执行。

  3. 3

    安装后重启宿主

    命令执行完要完全退出宿主工具再打开,让新装的 Skill 被重新扫描到,否则列表里可能看不到。

  4. 4

    按最小权限试用

    它需要需要联网,先在测试目录或测试账号里跑,确认没问题再放到正式项目。

常见问题

6 条

opentelemetry-net-instrumentation 怎么安装?

在终端执行 npx skills add https://github.com/aaronontheweb/dotnet-skills --skill OpenTelemetry-NET-In…。装完完全退出宿主工具再打开,让它重新扫描本地 Skill。

opentelemetry-net-instrumentation 支持哪些 AI 工具?

公开资料标注支持 Codex、Claude、Cursor、Gemini CLI。其他工具只要能读取本地 Skill 目录,一般也能手动放进去,但要自己确认触发方式是否一致。

opentelemetry-net-instrumentation 需要什么权限?

权限级别是需要联网。该 Skill 可能需要联网访问来源站点、仓库或外部 API;具体网络访问范围需要结合源码和 README 复核。

opentelemetry-net-instrumentation 是免费的吗?

公开资料没有标注明确许可证,收费和商用限制都无法确认。正式使用前请到来源仓库核对授权说明。

opentelemetry-net-instrumentation 用的人多吗?

公开数据是累计安装 1,866 次,近一周安装 77 次,下载 610 次,GitHub 889 星。这些数字来自第三方目录统计,只能当作热度参考,不代表质量或安全性。

opentelemetry-net-instrumentation 安全吗?

第三方扫描结果为通过,但这只覆盖已知的静态检查项,不能替代自己读一遍源码和安装命令。

值得选的地方和要先想清楚的地方

值得选的地方

  • 同时适配 4 种工具,换客户端不用重新找替代品。
  • 第三方扫描已通过,常见的高风险行为没有命中。

先想清楚的地方

  • 许可证没有明确标注,能不能商用、能不能再分发都不确定。
  • 第三方目录整理,版本更新和行为细节以来源仓库为准。

适不适合你

更适合

  • 已经在用 Codex,想直接扩展它能力的人。
  • 需要处理开发类任务、又不想每次都手写提示词的人。

不太适合

  • 需要明确授权才能用到公司项目里的场景。
  • 需要厂商级技术支持和 SLA 的生产系统。

开发类 Skill 对比

6 个同类
Skill总安装GitHub 星权限许可证扫描
skill-vetter

技能审查员 · OpenClaw

8,779,018986操作浏览器MIT-0通过
ontology

本体论 · OpenClaw

6,636,960576只读MIT-0通过
entra-app-registration

内部应用程序注册 · Codex、Claude

6,631,872764接触敏感数据未明确通过
entra-app-registration

内部应用程序注册 · Codex、Claude

3,757,680201接触敏感数据未明确通过
nano-banana-pro

纳米香蕉专业版 · OpenClaw

3,526,898364接触敏感数据MIT-0有提醒
opentelemetry-net-instrumentation

OpenTelemetry NET instrumentation 命令行 · 本页

1,866889需要联网未明确通过

按安装量取同分类前几名;数字来自第三方目录统计,只作热度参考,不代表质量结论。

SKILL.md 原文

OpenTelemetry.NET Instrumentation Skill

Description

Provides guidance for implementing OpenTelemetry instrumentation in.NET codebases, covering tracing (Activities/Spans), metrics, naming conventions, error handling, performance, and API design best practices.

When to Use

  • Adding OpenTelemetry instrumentation to.NET code
  • Creating or modifying ActivitySources and metrics
  • Reviewing telemetry implementations for compliance
  • Optimizing instrumentation performance
  • Designing telemetry APIs that become part of the public surface

Prerequisites

  • .NET application with OpenTelemetry SDK
  • Understanding of System.Diagnostics.Metrics and ActivitySource APIs
  • Access to observability backend (e.g., Jaeger, Prometheus, Grafana)

Core Principles

Resiliency First

CRITICAL: Exceptions in diagnostic/tracing/metrics logic MUST NEVER impact application processing.

  • Always protect against null Activity references except in Activity extension methods (use activity?.ExtensionMethod())
  • Assume Activity instances can be null (only created when listeners subscribe)
  • 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

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 the ActivitySource using SemVer
  • Create separate ActivitySources for specialized/opt-in scenarios

Creating Activities

// ✅ CORRECT: Check HasListeners before creating
if (ActivitySource.HasListeners())
{
    using var activity = ActivitySource.StartActivity("ProcessItem", ActivityKind.Internal);

    if (activity != null)
    {
        activity.DisplayName = "Processing order #12345";

        // Only compute expensive tags if requested
        if (activity.IsAllDataRequested)
        {
            activity.SetTag("app.item_id", itemId);
            activity.SetTag("app.item_type", itemType);
        }
    }
}

// ❌ WRONG: Don't start activities in async helper methods (breaks AsyncLocal)
async Task HelperAsync()
{
    using var activity = ActivitySource.StartActivity("Helper"); // ❌ BAD
    await DoWorkAsync();
}

Rules:

  • Check ActivitySource.HasListeners() before creating (zero-allocation fast path)
  • Always check if activity is null after creation
  • Never start activities in asynchronous helper methods (Activity.Current uses AsyncLocal)
  • Use activity.IsAllDataRequested before expensive computations
  • Always use W3C ID format (enforce format change if parent uses hierarchical)

Activity Naming

// ✅ CORRECT: Unique operation name, friendly display name
using var activity = ActivitySource.StartActivity(
    name: "ProcessItem",              // Unique, identifies class of spans
    kind: ActivityKind.Internal
);
activity.DisplayName = "Processing order #12345"; // User-friendly, can be specific

// ❌ WRONG: Don't include runtime data in operation name
using var activity = ActivitySource.StartActivity($"Process_{itemId}"); // ❌ BAD

Rules:

  • Each span type has unique OperationName (identifies statistically interesting class of spans)
  • Operation name should NOT contain runtime data (only compile/config-time info)
  • Use human-readable DisplayName for specifics
  • Follow OpenTelemetry span naming conventions

Span Attributes (Tags)

// ✅ CORRECT: Namespace, lowercase, underscore-delimited
activity?.SetTag("myapp.order_id", orderId);
activity?.SetTag("myapp.order_type", orderType);
activity?.SetTag("myapp.db.table_name", tableName);

// Standard semantic conventions where applicable
activity?.SetTag("db.system", "postgresql");
activity?.SetTag("http.method", "GET");

// ❌ WRONG: Various naming violations
activity?.SetTag("MyApp.OrderId", orderId);         // ❌ Wrong case
activity?.SetTag("myapp.order-id", orderId);        // ❌ Wrong delimiter
activity?.SetTag("myapp.orders", count);            // ❌ Plural
activity?.SetTag("unrelated.ip_address", ip);       // ❌ Not characteristic

Naming Conventions:

  • Use a namespace prefix matching your component: myapp.*, myapp.db.*
  • All lowercase letters
  • Underscore (_) delimiters for multi-word attributes
  • Singular form
  • Only set tags directly relevant to this activity
  • Prefer standard OpenTelemetry semantic conventions over custom attributes where they exist
  • Only use standard semantic conventions if certain no downstream library will set them

Activity Status and Errors

// ✅ CORRECT: Set status and record exceptions
try
{
    await ProcessItemAsync();
    activity?.SetStatus(ActivityStatusCode.Ok);
}
catch (Exception ex)
{
    if (activity != null)
    {
        activity.SetStatus(ActivityStatusCode.Error);
        activity.SetTag("otel.status_code", "error");
        activity.SetTag("otel.status_description", ex.Message);

        // Record exception event per OTel spec
        activity.AddEvent(new ActivityEvent(
            "exception",
            tags: new ActivityTagsCollection
            {
                ["exception.type"] = ex.GetType().FullName,
                ["exception.message"] = ex.Message,
                ["exception.stacktrace"] = ex.ToString()
            }
        ));
    }
    throw;
}

Rules:

  • Set ActivityStatusCode.Ok on success
  • Set ActivityStatusCode.Error on exception
  • Always add otel.status_code and otel.status_description tags
  • Record exception events following OTel exception conventions

Activity Events

// ✅ CORRECT: Use events for additional context (sparingly)
activity?.AddEvent(new ActivityEvent("ItemRetried", tags: new ActivityTagsCollection
{
    ["retry_attempt"] = retryCount,
    ["next_retry_delay"] = delayMs
}));

// ❌ WRONG: Don't use events for verbose logging
activity?.AddEvent(new ActivityEvent($"Step {i} completed")); // ❌ Use logging instead

Rules:

  • Events stored in-memory until transmission (use sparingly)
  • Only for additional context; consider nested spans for multiple events
  • Use logging for verbose information

Accessing Activities

// ❌ WRONG: Don't rely on Activity.Current when you need a specific span
public async Task HandleAsync(Context context)
{
    var activity = Activity.Current; // ❌ Might be a user-created span, not yours
    activity?.SetTag("custom", "value");
}

// ✅ CORRECT: Pass Activity explicitly or store it in a dedicated context object
public async Task HandleAsync(Context context)
{
    if (context.TryGetActivity(out var activity))
    {
        activity?.SetTag("custom", "value");
    }
}

Metrics

Meter and Metrics Class Setup

// ✅ CORRECT: Group metrics by feature/component
public sealed class OrderProcessingMetrics : IDisposable
{
    private readonly Meter meter;
    private readonly Histogram<double> processingDuration;
    private readonly Counter<long> itemsProcessed;

    public OrderProcessingMetrics()
    {
        meter = new Meter("MyApp.OrderProcessing", "1.0.0");

        // Singular names, appropriate units, nested hierarchy
        processingDuration = meter.CreateHistogram<double>(
            "myapp.order.processing.duration",
            unit: "s",
            description: "Duration of order processing"
        );

        itemsProcessed = meter.CreateCounter<long>(
            "myapp.order.processing.count",
            unit: "{order}",
            description: "Number of orders processed"
        );
    }

    public void Dispose() => meter.Dispose();
}

Naming Conventions (follow OTel semantic conventions):

  • Singular names (use _count suffix instead of pluralization)
  • Nested hierarchy: myapp.order.processing.duration
  • Define units (s, ms, {item}, {connection})
  • Avoid technical suffixes (_counter, _histogram)
  • Start with pre-1.0.0 version until adoption proven

Metric Recording Method Naming

// ✅ CORRECT: Action/outcome-based naming, separate methods per outcome
public sealed class OrderProcessingMetrics
{
    // Event happened: describe what occurred
    public void OrderProcessingSucceeded(string orderType, TimeSpan duration)
    {
        processingDuration.Record(duration.TotalSeconds,
            new KeyValuePair<string, object?>("myapp.order_type", orderType),
            new KeyValuePair<string, object?>("outcome", "success")
        );
    }

    public void OrderProcessingFailed(string orderType, Exception exception, TimeSpan duration)
    {
        processingDuration.Record(duration.TotalSeconds,
            new KeyValuePair<string, object?>("myapp.order_type", orderType),
            new KeyValuePair<string, object?>("outcome", "failure"),
            new KeyValuePair<string, object?>("exception.type", exception.GetType().Name)
        );
    }

    public void ConnectionOpened() => connectionsOpen.Add(1);
    public void ConnectionClosed() => connectionsOpen.Add(-1);
}

// ❌ WRONG: Various naming anti-patterns
public void RecordOrderProcessingDuration(...) { } // ❌ Don't name after metric
public void RecordError(bool succeeded, Exception? ex) { } // ❌ Confusing signature

Rules (inspired by ASP.NET Core patterns):

  • Name after action/outcome: OrderProcessingSucceeded, RetryAttempted, ConnectionFailed
  • NOT after metric name: avoid RecordXxx, IncrementXxx
  • Separate methods for different outcomes (avoid boolean flags + optional exceptions)
  • Event-based naming for state changes: ConnectionOpened(), ItemQueued()

Metric Dimensions

// ✅ CORRECT: Low-cardinality, predefined dimensions
public void OrderProcessingSucceeded(string orderType, TimeSpan duration)
{
    processingDuration.Record(duration.TotalSeconds,
        new KeyValuePair<string, object?>("myapp.order_type", orderType),
        new KeyValuePair<string, object?>("myapp.region", region),
        new KeyValuePair<string, object?>("outcome", "success")
    );
}

// ❌ WRONG: High-cardinality dimensions (unbounded values cause cardinality explosion)
public void OrderFailed(string orderId, string exceptionMessage)
{
    failureCount.Add(1,
        new KeyValuePair<string, object?>("order_id", orderId),               // ❌ Unbounded
        new KeyValuePair<string, object?>("exception_message", exceptionMessage) // ❌ Unbounded
    );
}

Rules:

  • Dimensions MUST be predefined at instrument creation
  • Avoid dynamic/unbounded values (causes cardinality explosion: each unique value creates a new time series row)
  • High-cardinality dimensions MUST be opt-in configuration
  • Use low-cardinality identifiers: item type, queue name, outcome
  • Consistent dimension names across components: myapp.region means same thing everywhere
  • Avoid sensitive data
  • Consider metric enrichment alternatives
  • Users can enable metric exemplars for correlation (not through dimensions)

Performance Requirements

Instrumentation MUST be cheap by default. Follow these rules to minimize overhead:

Zero-Allocation Fast Path

// ✅ CORRECT: Guard with cheap checks
if (ActivitySource.HasListeners())
{
    using var activity = ActivitySource.StartActivity("Operation");
    // ... expensive work
}

// ✅ CORRECT: Use TagList (struct) for metrics
var tags = new TagList
{
    { "myapp.order_type", orderType },
    { "outcome", "success" }
};
counter.Add(1, tags);

Timing

// ✅ CORRECT: Timestamp math (no allocation)
var startTime = Stopwatch.GetTimestamp();
try
{
    await ProcessAsync();
}
finally
{
    var duration = Stopwatch.GetElapsedTime(startTime);
    metrics.OrderProcessingSucceeded(orderType, duration);
}

// ❌ WRONG: Allocates Stopwatch object
var stopwatch = Stopwatch.StartNew(); // ❌ Allocates

// ❌ WRONG: IDisposable timing class (allocates per use)
using (new MetricScope(metrics, "ProcessOrder")) // ❌ BAD
{
    ProcessOrder();
}

Avoid Hidden Allocations

// ❌ WRONG: String interpolation allocates
activity?.SetTag("item", $"Processing {itemId}"); // ❌ Allocates

// ✅ CORRECT: Check IsAllDataRequested first
if (activity?.IsAllDataRequested == true)
{
    activity.SetTag("item", $"Processing {itemId}");
}

// ❌ WRONG: LINQ allocates enumerators
activity?.SetTag("handlers", handlers.Select(h => h.Name).ToArray()); // ❌ Bad

// ✅ CORRECT: Manual construction or check first
if (activity?.IsAllDataRequested == true)
{
    activity.SetTag("handlers", string.Join(",", handlers.Select(h => h.Name)));
}

Rules:

  • No Stopwatch.StartNew() (use timestamp math)
  • No timing IDisposable wrappers as classes
  • Prefer TagList (struct) over arrays/dictionaries
  • No hidden work: avoid LINQ, string interpolation, async state machines in hot paths

Testing Requirements

Span Tests

[Test]
public async Task Should_create_processing_span_with_correct_parent()
{
    // Arrange
    using var parent = new Activity("Parent").Start();

    // Act
    await handler.Handle(item);

    // Assert
    var processingSpan = recordedActivities.Single(a => a.OperationName == "ProcessItem");
    Assert.AreEqual(parent.Id, processingSpan.ParentId);
    Assert.AreEqual("myapp.item_type", processingSpan.Tags.First().Key);
}

[Test]
public void Should_not_introduce_breaking_changes_to_span_names()
{
    // Ensures string values in span names are under test
    Assert.AreEqual("ProcessItem", MyFeature.SpanName);
}

Rules:

  • Test which spans activities connect to
  • Test string values (span names, tag names) to prevent breaking changes
  • Remember: telemetry is part of public API

Versioning

  • Telemetry versioning decoupled from package version
  • Use SemVer semantics
  • Traces and Metrics use separate versions (evolve independently)
  • Start with pre-1.0.0 version until adoption/usefulness proven
private static readonly ActivitySource ActivitySource = new("MyApp.MyComponent", "0.9.0");
private readonly Meter meter = new("MyApp.MyComponent", "0.8.0");

References

平台分布

Codex

37.93%
按下载量换算231

Claude

28.49%
按下载量换算174

Cursor

18.65%
按下载量换算114

Gemini CLI

9.11%
按下载量换算56

安全审计

Gen Agent Trust Hub

通过

Socket

通过

Snyk

通过

权限和风险

需要联网

该 Skill 可能需要联网访问来源站点、仓库或外部 API;具体网络访问范围需要结合源码和 README 复核。

安装前确认

本站仅展示第三方公开信息,不托管安装包,不提供自动安装或运行环境。安装前应自行审查源码、依赖和命令行为。目前只有一个公开来源,建议同时核对源仓库。

继续浏览同类 Skills