Quickstart
Run sigiro with one docker command. Point OpenTelemetry at it. Then ask it what changed and why. This takes five minutes. You need no collector and no configuration file.
In this tutorial you start a sigiro server, send it telemetry from your own service, and ask it two questions. At the end you read a diagnosis and run the SQL behind it. This takes five minutes.
sigiro is one process. You deploy no collector and you write no configuration file.
1. Run it
curl -fsSL https://sigiro.com/install | sh
sigiro serveThe script reads your operating system and processor. Then it checks the SHA-256
of the download against the published checksum. It writes the binary to
~/.local/bin. Set SIGIRO_INSTALL_DIR for a different directory.
Builds exist for Linux and macOS on arm64, and for Linux on x86-64. On another platform, use the container.
docker run -p 4317:4317 -p 4318:4318 -p 9999:9999 ghcr.io/sigiroai/sigiroAdd -v sigiro-data:/var/lib/sigiro to keep the data across container restarts.
Each of the three ports has one function:
| Port | Protocol |
|---|---|
4317 |
OTLP over gRPC |
4318 |
OTLP over HTTP |
9999 |
the query and diagnose API |
At the first start, sigiro downloads its query extensions. This can take 30–90
seconds, so expect a pause before the server accepts a request. Each later start
is immediate. sigiro writes the data to SIGIRO_DATA_DIR. That directory is
~/.local/share/sigiro for the binary, and /var/lib/sigiro in the image.
Notice that the server asks you for no key. A self-hosted server authenticates no request, so keep it on a private network. To read why the network is the boundary, see About the one-process design.
2. Send it telemetry
Any OpenTelemetry SDK or collector in your stack works without a change. Point the standard environment variables at sigiro:
OTEL_EXPORTER_OTLP_ENDPOINT=http://localhost:4318 \
OTEL_SERVICE_NAME=checkout \
<your-app-start-command>
If your code has no instrumentation yet, do not add it by hand. Follow Instrument your code with an agent first, then come back here.
Now send some real traffic through your service, and confirm that the telemetry arrived:
curl http://localhost:9999/v1/services
The response is a JSON object with a services array. Your service appears in
that array within a few seconds of the first request. If the array is empty,
check that the port is 4318 for OTLP over HTTP and 4317 for OTLP over gRPC.
3. Ask what changed
anomalies is the entry point of the loop. It returns the shifts that deviate
from the recent baseline of each service, biggest shift first.
sigiro anomalies
sigiro anomalies --service checkout
You configure nothing here. There are no thresholds to choose, and a service that is always slow but stable is not an anomaly. To read how sigiro decides that, see About evidence instead of a dashboard.
Notice that the list can be empty on a young server. sigiro needs a few 5-minute buckets of history before it can compare anything, so run your service for a while and then ask again.
4. Ask why
diagnose returns one structured evidence block for a service and a time
window. The block starts with a ranked list of what deserves attention. Under
that, it holds error counts, error breakdowns for each operation, LLM statistics
for each model, sampled spans, and deduplicated log patterns. Every row also
carries a ready-to-run SQL query.
sigiro diagnose checkout
sigiro diagnose checkout --from $(date -v-1H +%s) --grep POST
The command prints indented JSON. Read the findings array first: it is sorted
critical first, and each item carries a summary you can read and a
drill_down_sql you can run.
An agent asks the same question over HTTP. The HTTP request needs an explicit window, and both timestamps are microseconds since the Unix epoch:
curl -X POST http://localhost:9999/v1/diagnose \
-H 'content-type: application/json' \
-d "{\"service\":\"checkout\",
\"from_ts\":$(( $(date +%s) - 900 ))000000,
\"to_ts\":$(date +%s)000000}"
The --from/--to flags on the CLI take epoch seconds, and the CLI
defaults the window to the last 15 minutes. The HTTP body takes microseconds and
defaults nothing. sigiro rejects a seconds value on the HTTP path with a message
that names the unit, so a wrong unit fails loudly rather than returns an empty
window.
5. Run the query behind a row
When the evidence block does not answer your question, run the SQL that a row gave you. Your telemetry is a set of tables, and the body of a query request is the raw SQL rather than JSON:
curl -X POST http://localhost:9999/v1/query \
--data "SELECT service_name, count(*) AS errors
FROM sigiro_spans
WHERE status_code = 2 AND timestamp > now() - INTERVAL '1 hour'
GROUP BY 1 ORDER BY errors DESC"
The response is a JSON array of row objects. status_code is the OTLP enum, so
2 is an error.
Notice that the query bounds timestamp. Bound timestamp in every query:
sigiro keeps no secondary index, so a bounded query reads a small number of
files and an unbounded query reads every file. About the one-process
design explains
why.
sigiro_spans is one of nine tables. The
hosted guide lists
all nine with the rules that apply to them, and About the
tables explains what each family measures.
What you did
You started a server, sent it OpenTelemetry, asked it what changed, asked it why, and ran the query that proves one of its answers. That is the whole loop that an agent runs on its own.
Next
- Instrument your code with an agent — if your service still has no OpenTelemetry
- Send telemetry to hosted sigiro — if you do not want to run the server yourself
- CLI reference — the other four subcommands, and every flag and environment variable
GET /openapi.json— the full API, machine-readable, and no key is necessary