Install
$ agentstack add skill-xobotyi-cc-foundry-otel-tracing ✓ scanned · ✓ verified, works with Claude Code, Cursor, and more.
Security review
✓ PassedNo issues found. Passed automated security review. · v0.1.0 How review works →
- ✓ Prompt-injection patterns
- ✓ Secret / credential exfiltration
- ✓ Dangerous shell & filesystem operations
- ✓ Untrusted network calls
- ✓ Known-malicious package signatures
What it can access
- ● Network access Used
- ✓ Filesystem access No
- ✓ Shell / process execution No
- ✓ Environment & secrets No
- ✓ Dynamic code execution No
From automated source analysis of v0.1.0. “Used” means the capability is present in the source — more access means more to trust, not that it’s unsafe.
Verified badge
Passed review? Show it. Paste this badge into your README, it links to the public security report.
Reliability & compatibility
Declared compatibility
Compatibility is declared by the source manifest. End-to-end runtime verification is coming, see below.
We're building live execution health for every listing: tool-call success rate, median latency, uptime, and last-checked timestamps, measured, not self-reported. It isn't live yet, so we don't show numbers we can't stand behind.
How agent discovery & health will work →About
OTel Tracing
Create spans for logical operations, propagate context across every boundary, use semantic conventions for attribute names. Every tracing decision — span granularity, attribute selection, sampling strategy — trades off cost against visibility.
References
- Spans — [
${CLAUDE_SKILL_DIR}/references/spans.md]: Span anatomy, root spans, lifetime code patterns - Span data — [
${CLAUDE_SKILL_DIR}/references/span-data.md]: Events format, links format, SDK limits table - Context propagation — [
${CLAUDE_SKILL_DIR}/references/context-propagation.md]: W3C header format, propagator
selection, baggage details, security
- Instrumentation — [
${CLAUDE_SKILL_DIR}/references/instrumentation.md]: Server/client/async code patterns,
library rules, testing guidance
- Sampling — [
${CLAUDE_SKILL_DIR}/references/sampling.md]: Head/tail/combined strategies, decision guide, sampler
types
- Semantic conventions — [
${CLAUDE_SKILL_DIR}/references/semantic-conventions.md]: HTTP/DB/messaging attribute
lists, status mapping, general conventions
- SDK components — [
${CLAUDE_SKILL_DIR}/references/sdk-components.md]: Resource config, env vars, Collector
deployment, exporter types
Spans
A span represents one unit of work in a trace — an HTTP request handler, a database query, a message publish. Not every function call.
Span Naming
Name spans for the class of operation, not the instance. Low-cardinality names enable aggregation; high-cardinality names destroy it.
- Use the most general string that identifies a statistically interesting class
- Never embed high-cardinality values (IDs, emails, paths with IDs)
- HTTP:
{METHOD} {route}— server:GET /users/:id; client:GET - DB:
{operation} {table}—SELECT users,INSERT orders
| Name | Verdict | | ---------------------------- | ------------------------- | | get | Too general | | get_account/42 | Too specific — ID in name | | get_account | Good | | GET /users/{userId} | Good — route template | | POST /api/v2/orders/abc123 | Bad — order ID in name |
SpanKind
SpanKind tells backends how to assemble the trace tree. Set it correctly.
SERVER(Incoming) — HTTP handler, gRPC server methodCLIENT(Outgoing) — HTTP client call, DB query, gRPC callPRODUCER(Outgoing) — Enqueue message, schedule jobCONSUMER(Incoming) — Dequeue message, process jobINTERNAL(Neither) — In-process business logic, computation
- A single span MUST NOT serve more than one purpose
- Create a new span before injecting context for outgoing calls
CLIENT->SERVERfor synchronous calls;PRODUCER->CONSUMERfor async- Using
INTERNALfor HTTP handlers or DB calls is wrong — useSERVERorCLIENT
Span Status
Unset— No error. Default — do not change on success.Error— Operation failed. When an error occurs; include description.Ok— Explicitly successful. Only to override a previousError; rarely needed.
- Leave status
Unseton success — it already means "no error" Okis a "final call" — once set, subsequentErrorattempts are ignored- Instrumentation libraries SHOULD NOT set
Ok— leave to application code
Span Lifetime
- Every created span MUST be ended — leaked spans cause memory issues and incomplete traces
- After
end(), the span becomes non-recording; further mutations are ignored - Use language-idiomatic patterns:
defer(Go), try/finally (Java/JS), context manager (Python)
Span Data: Attributes, Events, Links
Attributes
Key-value pairs annotating a span. Value types: string, boolean, integer, float, or arrays of these.
- Use semantic conventions for attribute names —
http.request.method,db.system, not custom names. Consistent
naming enables cross-service analysis.
- Add sampling-relevant attributes at span creation — samplers can only see attributes present at creation time.
- Keep cardinality low — attribute values should be from a bounded set.
- Check
IsRecordingbefore expensive attribute computation — sampled-out spans discard all data. - Never store PII in attributes — trace data flows to shared backends. Use opaque identifiers.
- Respect attribute limits — SDK enforces
AttributeCountLimit(default 128). Excess attributes are silently
dropped.
Events
Timestamped annotations — structured log entries attached to a span.
- Use events when the timestamp matters; use attributes for metadata with no meaningful timestamp
- Add events for key domain occurrences ("page became interactive", "retry attempted")
- Use events for verbose data instead of additional spans
Recording Exceptions
- Always pair
RecordExceptionwithsetStatus(ERROR)— RecordException alone does not change span status - Never swallow application exceptions in instrumentation — catch instrumentation errors, log them, but always rethrow
application exceptions
Links
Associate a span with spans from other traces without parent-child hierarchy.
- Batch processing: link consumer span to each producer span
- Async follow-up: job span links back to triggering span
- Add links at span creation when possible — samplers can consider them
See ${CLAUDE_SKILL_DIR}/references/span-data.md for events format, links format, and SDK limits table.
Context Propagation
Context propagation correlates spans across service boundaries. Without it, each service produces isolated spans — no trace.
Inject / Extract Pattern
- Sender creates a span, makes it current, injects context into outgoing carrier (HTTP headers, message
metadata)
- Receiver extracts context from incoming carrier and uses it as parent for new spans
- Call inject AFTER creating the outgoing CLIENT or PRODUCER span
- Call extract BEFORE creating the server/consumer span
- Use W3C TraceContext as the default propagation format
In-Process Propagation
- Make spans active/current — enables automatic log correlation, nested auto-instrumentation picking up correct
parent, context propagation to child ops
- Pass context explicitly in async code — automatic propagation may break across thread boundaries, goroutines, or
async callbacks
- Never propagate request context to background work — background tasks should start new traces and link back to the
triggering span
Baggage
Propagates arbitrary key-value pairs across service boundaries alongside trace context.
- Use for: tenant ID, request priority, feature flags, sampling hints
- NEVER put PII, credentials, or API keys in baggage — visible to all downstream services
See ${CLAUDE_SKILL_DIR}/references/context-propagation.md for W3C header format, propagator selection table, baggage details, and security considerations.
Instrumentation
Approaches
| Approach | When | Trade-off | | -------------------- | ----------------------------------------- | ------------------------------------------ | | Automatic | Supported libraries (HTTP, DB, messaging) | Zero code, no business attrs | | Manual | Business logic, unsupported libraries | Full control, more code | | Hybrid (recommended) | Production | Auto for infra + manual for business logic |
Getting a Tracer
- Name the tracer after your library, package, or module — not the application
- Include a version string matching your library version
- Libraries: accept
TracerProvidervia dependency injection or use the global one - Applications: configure the SDK and set the global
TracerProvider
What to Instrument
Good candidates: public API methods with I/O or significant computation, request/message handlers, outbound calls (HTTP, DB, RPC), background jobs.
Poor candidates: every function call (noise), thin wrapper libraries (already instrumented underneath), pure computation with no I/O and sub-ms duration.
Decision: Is it a network call or significant I/O? -> Create span (CLIENT/SERVER). Is it a meaningful business operation? -> Create span (INTERNAL). Would a span event on parent suffice? -> Add event. Otherwise -> don't instrument.
Library Instrumentation Rules
- Depend on OpenTelemetry API only — never SDK. The API is a no-op without SDK — zero overhead for users who don't
use OTel.
- Follow semantic conventions for your domain
- Set the
schema_urlto record which semantic convention version you use - Prefer events over spans for verbose internal details
- Support optional
TracerProviderinjection for testability
See ${CLAUDE_SKILL_DIR}/references/instrumentation.md for server-side, client-side, and async producer/consumer patterns, plus testing guidance.
Sampling
Sampling controls which traces are recorded and exported — the primary cost management mechanism.
Head Sampling
Decision at trace creation time, before any spans complete.
AlwaysOn— Record and sample everythingAlwaysOff— Drop everythingTraceIdRatioBased(ratio)— Sample based on trace ID hashParentBased(root)— Delegate based on parent sampling decision
ParentBased is the most common production configuration — respects parent decisions, applies custom root sampling. Default SDK sampler: ParentBased(root=AlwaysOn).
Tail Sampling
Decision after all spans in a trace complete. Requires collector infrastructure.
- All services export at 100%
- OTel Collector with tail sampling processor buffers spans by trace ID
- All spans with the same trace ID MUST reach the same collector — use trace-ID-aware load balancing
Sampling Principles
- Start with no sampling — add only when cost or volume requires it
- Always sample errors — configure tail sampling to keep error traces
- Use
ParentBased— children follow parent decisions for complete traces - Provide attributes at span creation — samplers cannot see late-added attributes
- Filter health checks — high volume, low value; sample aggressively or filter entirely
See ${CLAUDE_SKILL_DIR}/references/sampling.md for combined head+tail strategies, decision guide, and per-scenario recommendations.
Semantic Conventions
Use semantic conventions for span names and attributes. Consistent naming enables cross-service analysis without learning custom attribute names.
- HTTP server spans: kind
SERVER, name{METHOD} {http.route}, never full URI path - HTTP client spans: kind
CLIENT, name{METHOD} - Database spans: kind
CLIENT, name{operation} {target}, always sanitize queries - Messaging producer: kind
PRODUCER, name{destination} publish - Messaging consumer: kind
CONSUMER, name{destination} process
See ${CLAUDE_SKILL_DIR}/references/semantic-conventions.md for required/recommended attributes per domain, status mapping rules, and general conventions.
SDK Components
TracerProvider
- Initialize once, early in application startup
- Always call
shutdown()on exit — flushes remaining spans - Configure
Resourcewithservice.name— identifies your service in backends - Use
BatchSpanProcessorin production —SimpleSpanProcessoris for dev/testing only
See ${CLAUDE_SKILL_DIR}/references/sdk-components.md for Resource attributes, BatchSpanProcessor tuning, exporter types, environment variable configuration, and Collector deployment patterns.
Application
When writing tracing code:
- Apply all conventions silently — don't narrate each rule.
- Use semantic conventions for attribute names. Check the reference for your domain (HTTP, DB, messaging) before
inventing names.
- If an existing codebase contradicts a convention, follow the codebase and flag the divergence once.
When reviewing tracing code:
- Cite the specific violation and show the fix inline.
- Focus on: span naming cardinality, missing context propagation, missing error recording, wrong SpanKind, missing
span.end().
Integration
The coding skill governs workflow; this skill governs tracing implementation choices. Language-specific skills handle SDK API differences.
Source & license
This open-source skill is cataloged on AgentStack and links to its original source — we do not rehost the code.
- Author: xobotyi
- Source: xobotyi/cc-foundry
- License: MIT
Install and usage instructions live in the source repository linked above.
Reviews
No reviews yet, be the first.
Write a review
Versions
- v0.1.0 Imported from the upstream source.