Install
$ agentstack add skill-acaprino-claude-code-daodan-opentelemetry ✓ 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
OpenTelemetry Python
Index for OTel Python -- traces, metrics, log-trace correlation, distributed propagation. References hold the gotchas; canonical reference lives at https://opentelemetry-python.readthedocs.io and https://opentelemetry.io/docs/.
When to use
- New Python service that needs distributed tracing
- Adding OTel to FastAPI / Celery / async Python
- Custom transports (AMQP, ZMQ, Kafka) needing propagator wiring
- OTLP exporter / Collector / AWS ADOT configuration
- Auditing existing instrumentation for gaps or anti-patterns
- Log-trace correlation
- Sampling strategy choice for production
Quick-start production recipe
For most Python services, start with this and iterate:
- Init:
opentelemetry-bootstrap -a install+opentelemetry-instrumentwrapper - Resource: set
service.name,service.version,deployment.environment - Sampler:
ParentBased(TraceIdRatioBased(0.1))-- 10% head sampling - Exporter: OTLP gRPC to a local Collector at
localhost:4317 - Processor:
BatchSpanProcessorwith default tuning (raiseOTEL_BSP_MAX_QUEUE_SIZE=8192if bursty) - Shutdown: register
provider.shutdown()in lifespan /atexit/SIGTERM
Then escalate based on what you actually need:
- Custom business spans → manual
tracer.start_as_current_span() - Non-HTTP transport → custom propagator (skeleton in
exporters-and-backends.md) - AWS deployment → ADOT distro + X-Ray ID generator (
aws-deployment.md) - High throughput → tune BSP queue size + export timeout
- Error-only retention → tail sampling at the Collector
Auto vs manual instrumentation (the matrix)
| Layer | Approach | Examples | |-------|----------|----------| | HTTP frameworks | Auto | FastAPI, Django, Flask | | Database clients | Auto | SQLAlchemy, psycopg2, asyncpg | | HTTP clients | Auto | httpx, requests, aiohttp | | Message queues | Auto | Celery, Kafka | | Cache | Auto | redis, memcached | | Business logic | Manual | Order processing, payment flows | | Custom transport | Manual | AMQP payload, ZMQ events |
Combined pattern: opentelemetry-instrument wraps the app for auto; manual spans inside routes/handlers for business logic. See instrumentation-patterns.md for per-framework details.
Critical framework gotchas (worth memorizing)
- Celery: init OTel after fork via
@worker_process_init.connect.BatchSpanProcessorthreads don't survivefork()-- export silently fails otherwise. Recipe ininstrumentation-patterns.md. - SQLAlchemy async: pass
engine.sync_engineto the instrumentor, NOT the async engine. - FastAPI: register
provider.shutdown()inlifespancleanup, otherwise last span batch is lost on every restart. - HTTP status / Span Status: only 5xx →
StatusCode.ERROR. 4xx are client errors, leave UNSET. Business rejections (declined payment) useadd_event, not ERROR.
Custom transport propagation (skeleton)
For AMQP, ZMQ, custom sockets -- inject on producer, extract on consumer, use W3C TraceContext format.
# Producer
from opentelemetry.propagate import inject
headers = {}; inject(headers)
message.payload["_trace_context"] = headers
# Consumer
from opentelemetry.propagate import extract
from opentelemetry import context, trace
ctx = extract(carrier=message.payload.get("_trace_context", {}))
token = context.attach(ctx)
try:
with trace.get_tracer(__name__).start_as_current_span("process"):
handle(message)
finally:
context.detach(token)
Full discussion + custom SpanProcessor patterns: exporters-and-backends.md.
Sampling -- the decision tree
ParentBased(TraceIdRatioBased(rate))-- the right default. Respects upstream decision; only applies the delegate to root spans. Without ParentBased, downstream services re-roll → broken traces.- Tail sampling at the Collector -- when you need to keep 100% of errors/slow traces while sampling routine traffic. Requires trace-ID affinity (loadbalancing exporter in front).
- Hybrid at scale: head-sample 10-20% in SDK + tail-sample at Collector for error/slow retention.
Env shortcut: OTEL_TRACES_SAMPLER=parentbased_traceidratio, OTEL_TRACES_SAMPLER_ARG=0.1.
Reference index
async-context-propagation.md-- contextvars mechanics, asyncio task propagation, thread boundary trap, TracedThreadPoolExecutor, fork+BSP loss, Python 3.12+ improvements (the crown jewel of this skill -- read first when debugging missing/broken context)instrumentation-patterns.md-- auto-instrument setup, FastAPI/Celery/SQLAlchemy patterns,traced_asyncdecorator,TracedClassmixin, sensitive-arg redaction, error handlingexporters-and-backends.md-- OTLP gRPC vs HTTP, BSP tuning, propagation formats, custom SpanProcessors, multi-backend Collector YAMLaws-deployment.md-- ADOT distro, X-Ray ID generator + propagator, ECS sidecar with memory_limiter ordering, IAM list, Lambda layer, collector-less when/when-not, X-Ray SDK migrationproduction-checklist.md-- do/don't operational rules, resource detection boilerplate, signal maturity, version pinning policy
Three pillars correlation (one-liner)
# Inject trace_id / span_id / service_name into every stdlib log record
from opentelemetry.instrumentation.logging import LoggingInstrumentor
LoggingInstrumentor().instrument(set_logging_format=True)
# OR env: OTEL_PYTHON_LOG_CORRELATION=true
For metrics: MeterProvider + Counter/Histogram/UpDownCounter/ObservableGauge. Shares Resource with TracerProvider so service identity is consistent.
For OTLP log export: the Logs SDK (opentelemetry._logs, leading underscore = experimental) -- in production today, use the LoggingInstrumentor bridge and ship via your existing log pipeline.
Official docs
- Python SDK: https://opentelemetry-python.readthedocs.io/
- Specification: https://opentelemetry.io/docs/specs/otel/
- All instrumentations index: https://github.com/open-telemetry/opentelemetry-python-contrib/tree/main/instrumentation
- Collector contrib: https://github.com/open-telemetry/opentelemetry-collector-contrib
- Release notes (always check before upgrade): https://github.com/open-telemetry/opentelemetry-python/releases
Source & license
This open-source skill is cataloged on AgentStack and links to its original source — we do not rehost the code.
- Author: acaprino
- Source: acaprino/claude-code-daodan
- 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.