Skip to content
sigiro[.]com

Instrument your code with an AI agent

Give a coding agent one prompt and it adds OpenTelemetry auto-instrumentation to your service, pointed at sigiro. Works with Claude Code, OpenCode, and Codex.

If your code has no OpenTelemetry in it yet, don't add it by hand. Paste the prompt below into a coding agent and it will detect your framework, install the official auto-instrumentation, and point the exporter at sigiro.

Works with Claude Code, OpenCode, Codex, or any coding agent that can edit files and run your package manager.

Before you start

You need a sigiro server to send to — sigiro serve, or the Docker command from the quickstart. A self-hosted server needs no key. Only the hosted service does, shaped sk_<tenant>_<random>.

Auto-instrumentation exists for Python, Node.js, Java, .NET and Ruby. Go has no runtime agent, so there the work is a few lines of SDK setup instead.

1. Give the agent this prompt

Replace the endpoint, and drop the key line entirely unless you are on hosted.

plaintext
Instrument this codebase for sigiro observability.

SIGIRO ENDPOINT: http://localhost:4318  (replace with your OTLP ingest address)
HOSTED API KEY: sk_<tenant>_<random>  (omit entirely for a self-hosted server)

Goal: add OpenTelemetry auto-instrumentation so this service emits traces,
metrics, and logs to sigiro. Make the minimum change that works — prefer
auto-instrumentation over hand-written spans.

Rules:
- Detect the language and framework automatically
- Use official OTel auto-instrumentation where it exists (Python opentelemetry-instrument,
  Java javaagent, Node.js auto-instrumentations-node, etc.)
- If auto-instrumentation is not available for this language/framework, add
  manual OTel SDK spans for HTTP handlers and database calls
- Set OTEL_EXPORTER_OTLP_ENDPOINT to the sigiro OTLP HTTP endpoint (:4318)
- For hosted sigiro only, set OTEL_EXPORTER_OTLP_HEADERS with the tenant bearer token
- Set OTEL_SERVICE_NAME to identify this service (use the existing service name or repo name)
- Use the existing package manager (pip, npm, Maven, Gradle, gem, go get)
- For hosted sigiro, do NOT hardcode the tenant key — read it from SIGIRO_API_KEY
- If a file already initializes the OTel SDK, update it rather than re-initializing
- Add SIGIRO_API_KEY to .env.example only for a hosted deployment

If the agent guesses the language wrong, tell it outright:

plaintext
Language: <python|nodejs|java|dotnet|ruby|go>
Framework: <fastapi|express|spring-boot|rails|...>

2. What each language gets

LanguageApproachCovers
Pythonopentelemetry-instrument CLI + distroHTTP (FastAPI, Flask, Starlette), DB (psycopg2, asyncpg), Redis
Node.js@opentelemetry/auto-instrumentations-nodeHTTP (Express, Fastify), DB (pg, mysql2, mongoose)
Javaopentelemetry-javaagent.jarHTTP (Servlets, Spring), DB (JDBC), JVM metrics
.NETOpenTelemetry.AutoInstrumentation startup hookHTTP (ASP.NET Core), DB (EF Core)
Rubyopentelemetry-instrumentation-all gemHTTP (Rails), DB (ActiveRecord), Sidekiq
GoManual SDK setupHTTP spans via middleware, DB spans via OTel hooks

Go needs the tracer wired up by hand and every handler wrapped:

go
import (
    "context"

    "go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp"
    "go.opentelemetry.io/otel"
    "go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp"
    sdktrace "go.opentelemetry.io/otel/sdk/trace"
)

func initTracer(ctx context.Context) (func(context.Context) error, error) {
    exporter, err := otlptracehttp.New(ctx,
        otlptracehttp.WithEndpoint("localhost:4318"),
        otlptracehttp.WithInsecure(),
    )
    if err != nil {
        return nil, err
    }
    tp := sdktrace.NewTracerProvider(sdktrace.WithBatcher(exporter))
    otel.SetTracerProvider(tp)
    return tp.Shutdown, nil
}

// Wrap each handler so its spans carry the route name:
http.Handle("/checkout", otelhttp.NewHandler(
    http.HandlerFunc(checkoutHandler), "checkout",
))

WithInsecure() is what makes the exporter talk plain HTTP to a local server. Drop it for hosted, which is TLS, and add the bearer token with otlptracehttp.WithHeaders(map[string]string{"Authorization": "Bearer " + key}).

3. Check it worked

bash
OTEL_EXPORTER_OTLP_ENDPOINT=http://localhost:4318 \
OTEL_SERVICE_NAME=my-service \
  <your-app-start-command>

Then ask sigiro what it has seen:

bash
curl http://localhost:9999/v1/services

Your service should appear within a few seconds of real traffic. Once it does, sigiro investigate my-service has something to work with.

If nothing shows up: confirm the port (:4318 HTTP, :4317 gRPC), run sigiro status to check the server is healthy, and read your service's own logs for OTel startup errors — a misconfigured exporter usually says so loudly at boot. On hosted, check the header is exactly Authorization: Bearer sk_<tenant>_<random>. A self-hosted server ignores auth headers entirely, so a bad key there fails silently rather than 401ing.

Tell the agent what not to do

Agents reach for more than you want here. Worth stating up front:

  • Don't install an OTel Collector. sigiro is the collector.
  • Don't add per-endpoint manual spans. Auto-instrumentation already covers them.
  • Don't touch database connection strings or business logic.
  • Don't set up dashboards or alert configs. There aren't any.

The whole job is: detect the framework, install auto-instrumentation, point it at sigiro.

Point Claude Code itself at sigiro

Claude Code emits its own OpenTelemetry. To watch your sessions, set these in the environment that launches it — a shell profile, an .envrc, or a wrapper script:

bash
export CLAUDE_CODE_ENABLE_TELEMETRY=1
export CLAUDE_CODE_ENHANCED_TELEMETRY_BETA=1
export OTEL_METRICS_EXPORTER=otlp
export OTEL_LOGS_EXPORTER=otlp
export OTEL_TRACES_EXPORTER=otlp
export OTEL_EXPORTER_OTLP_PROTOCOL=grpc
export OTEL_EXPORTER_OTLP_ENDPOINT=http://localhost:4317

For hosted, add OTEL_EXPORTER_OTLP_HEADERS="Authorization=Bearer ${SIGIRO_API_KEY}" and keep the key out of anything committed.

This instruments Claude Code, not the commands it runs. Apps it starts through its shell tool may not inherit these variables, so instrumented services still need their own exporter settings.

Point Codex itself at sigiro

Codex reads telemetry settings from its own config rather than the environment. In ~/.codex/config.toml:

toml
[otel]
environment = "dev"
log_user_prompt = false
exporter = "otlp-grpc"

[otel.exporter."otlp-grpc"]
endpoint = "http://localhost:4317"

For hosted, add headers = { authorization = "Bearer ${SIGIRO_API_KEY}" } and set SIGIRO_API_KEY in the environment that starts Codex. The same caveat applies: this covers Codex, not the services it edits.

Next