About otel-fastapi-style
A coding skill for adding OpenTelemetry observability to FastAPI applications. It emphasizes native framework instrumentation and covers request spans, logs, helper spans, and LLM token metrics.
Key features
- 01Native FastAPI instrumentation
- 02Initialize before serving traffic
- 03Module-level tracing and metrics
- 04OTLP log configuration
- 05LLM token coverage guidance
Use cases
- 01Instrument incoming FastAPI requests
- 02Add spans to business helper functions
- 03Configure forwarding for application logs
- 04Track input and output tokens on LLM routes
Install
Copy the command and run it in a terminal.
npx skills add https:/ / github.com/ superloglabs/ skills --skill otel-fastapi-styleAfter installing, type/otel-fastapi-stylein Claude Code to confirm it loaded.
Details
From the project READMEOTel FastAPI Style
Use native FastAPI instrumentation. Do not replace request handling with manual middleware just to create spans.
from fastapi import FastAPI
from opentelemetry.instrumentation.fastapi import FastAPIInstrumentor
def init_observability(app: FastAPI) -> bool:
...
FastAPIInstrumentor.instrument_app(app)
return True
Keep FastAPIInstrumentor.instrument_app(app) with the rest of the
observability setup so the bootstrap is easy to reason about. If the generated
token is not claimed yet because signup is still in progress, it is still okay
to initialize providers; ingest may reject exports until the browser flow
finishes.
Entrypoint
Initialize before serving user traffic.
app = FastAPI(title="Mugline API")
init_observability(app)
Bounded Work
Use module-scope OTel objects and decorators for helpers that auto-instrumented HTTP spans cannot see.
tracer = trace.get_tracer("mugline.api")
meter = metrics.get_meter("mugline.api")
@tracer.start_as_current_span("mug.recommend")
async def recommend_mug(*, tenant_id: str, preference: str) -> dict[str, str]:
span = trace.get_current_span()
span.set_attribute("tenant.id", tenant_id)
...
Logs
For OTLP-forwarded stdlib logs, configure all of these:
LoggerProviderset_logger_provider(logger_provider)OTLPLogExporterLoggingHandlerLoggingInstrumentor().instrument(...)
LLM Calls
LLM routes need token coverage:
llm.tokens.inputllm.tokens.output
Tag explicit token counters with tenant, provider, model, use case, call site, and outcome only when provider instrumentation cannot capture token usage. Do not add app-side LLM cost metrics or pricing tables; Superlog estimates cost centrally from provider/model/token data.