Instrumenting Your App
Tael ingests standard OTLP, so instrumenting an app is just standard OpenTelemetry pointed at Tael's endpoint. There is no Tael SDK to adopt and no vendor lock-in — if you ever switch backends, you change one environment variable.
Point your exporter at Tael
Set the standard OTel environment variables before your app starts:
export OTEL_EXPORTER_OTLP_ENDPOINT=http://127.0.0.1:4317
export OTEL_EXPORTER_OTLP_PROTOCOL=grpc
export OTEL_SERVICE_NAME=my-agentMost SDKs default OTEL_EXPORTER_OTLP_PROTOCOL to grpc and the endpoint to http://localhost:4317, so in practice OTEL_SERVICE_NAME is often the only one you must set. The service name is what shows up in tael services.
Emit wide-event spans
The payoff in Tael comes from wide events: one span per unit of work, with every useful fact attached as an attribute.
from opentelemetry import trace
tracer = trace.get_tracer(__name__)
def handle_request(user_id, flags):
with tracer.start_as_current_span("http.request") as span:
span.set_attribute("user.id", user_id)
span.set_attribute("flag.dark_mode", flags.get("dark_mode"))
try:
count = retrieve_items(user_id)
span.set_attribute("result.count", count)
except Exception as e:
span.set_attribute("error.type", "timeout")
span.record_exception(e)
span.set_status(trace.Status(trace.StatusCode.ERROR))
raiseOther languages (Go, Rust, Java, Ruby) work the same way — set the env vars and use that language's OTel SDK. See opentelemetry.io for SDK setup.
Instrumenting LLM calls
For model calls, set the span kind to LLM and attach the OpenTelemetry gen_ai.* attributes. Tael flattens these into typed columns (model, tokens, cost, TTFT) — see LLM spans.
The conventions Tael reads include:
gen_ai.request.model→modelgen_ai.usage.input_tokens→input_tokensgen_ai.usage.output_tokens→output_tokensgen_ai.response.finish_reason→finish_reason
Prompt and completion text attached to the span are stored as content-addressed blobs and become full-text searchable via tael query traces --text.
Verify it's flowing
Start the server (tael serve), run your app, then in another terminal:
tael services --format table
tael query traces --service my-agent --last 5m --format tableIf your service doesn't appear, check the usual suspects:
- Wrong endpoint — the exporter isn't pointed at
http://127.0.0.1:4317. - Wrong protocol — sending HTTP/protobuf when the SDK is set to gRPC, or vice versa.
- Missing
OTEL_SERVICE_NAME— the app reports under a default name. - Not flushing on exit — a short-lived process exits before the batch exporter flushes. Make sure your SDK's shutdown/flush runs before the process ends.
Metrics via Prometheus
If you already emit Prometheus metrics, Tael accepts remote-write at POST /api/v1/write. Note that remote-write v1 loses metric type information, so those points are stored with type unknown.
Related
- Wide Events — the discipline that makes instrumentation pay off.
- Quickstart — the end-to-end loop.
- Debugging with an Agent — querying what you've instrumented.
