Telemetry Reference

Stario has built-in, trace-based observability. Every request is a "trace" that can contain multiple "spans" (steps).

Quick Start

Choose your tracer based on the environment:

from stario import Stario, RichTracer, JsonTracer

# Dev: Pretty console output
tracer = RichTracer()

# Prod: Structured JSON logs
tracer = JsonTracer()

app = Stario(tracer)

Trace Steps (c.step)

Use c.step to time specific blocks of code. These appear as nested entries in your logs.

async def handler(c: Context, w: Writer):
    # 1. Add attributes to the main request span
    c["user_id"] = 42

    # 2. Create a child step
    with c.step("db.fetch", {"table": "users"}) as s:
        users = await db.get_users()
        s["count"] = len(users) # Attributes on the child span

Events

Record a single point in time without a duration:

c("cache.hit")
c("email.sent", {"to": "user@example.com"})

Tracer Types

RichTracer

Optimized for development. Groups spans by request and uses colors/tables for readability. Shows exactly what happened in a single request without interweaving other concurrent logs.

JsonTracer

Optimized for production. Outputs one JSON line per event/span. Compatible with Datadog, ELK, and CloudWatch.

Trace IDs

Every request has a unique trace_id. Access it via c.span.trace_id. Use this to correlate logs across your microservices or pass it to the frontend for debugging.