Getting started
Overview
What Bilis is, how a log line and a span travel through it, what v1 does, and what it deliberately does not do.
Bilis is self-hosted storage and search for logs, traces and metrics. You point your applications at one host, the lines, spans and data points land in ClickHouse, and a viewer built for finding one line among millions — and the request it belonged to — sits on top. One Laravel app and one database — no Grafana stack to operate.
What v1 does
- OTLP/HTTP ingest for logs, traces and metrics —
POST /api/v1/logs,POST /api/v1/tracesandPOST /api/v1/metrics, each accepting the JSON and the protobuf encoding, gzip or deflate compressed or not — plus a simple JSON fallback atPOST /api/v1/ingestfor log lines from anything without an OTel exporter. See Endpoints, Traces and Metrics. - OTel-compatible ClickHouse tables. The column names and types of
otel_logs,otel_tracesand the fiveotel_metrics_*tables are the ones the upstream OpenTelemetry ClickHouse exporter writes, so the storage layer is not a private format you would have to migrate out of. - A log viewer: time range, project / service / severity filters, full-text search over the message body, and live tail.
- A trace viewer: a trace list with live tail, a span waterfall per trace, and latency per service.
- A metrics explorer: one metric at a time, filtered by service and attributes and grouped by one of them — counters as rates, gauges as levels, histograms as p50 / p95 / p99.
- Logs and traces linked both ways. A log line carrying a trace id opens its trace's waterfall; a span in the waterfall opens the log viewer filtered to that exact trace and span.
- A Sentry-SDK-compatible endpoint for shipping exceptions your app already catches, stored as error logs. See Sentry-compatible ingest.
- Projects and API keys. A key belongs to exactly one project, and the project a log line, span or data point lands in is decided by the key that carried it — never by anything in the payload.
What is not in v1
Said plainly, so you can plan around it:
- No alerting, no user-defined dashboards, no saved searches.
- No eBPF collection, no S3 tiering, no ClickHouse replication.
- No self-serve billing. bilis.app has a Free plan with published limits; paid plans are arranged by contact; a self-hosted install has no plan at all.
- No OTLP over gRPC — HTTP only, in either encoding. Collectors and SDKs default to gRPC on port 4317, which is the most common reason a new install looks broken. See Traces.
Note: these are scope decisions, not a roadmap countdown. If a feature above is load-bearing for you today, Bilis v1 is not the right tool yet.
How a log line travels
- Your app or collector POSTs a batch to
/api/v1/logsor/api/v1/ingestwith an API key. - The key resolves to a project. Bad records inside the batch are skipped and counted; the healthy ones still go through.
- Rows are written to
otel_logswithasync_insert=1andwait_for_async_insert=0— the response means queued, not durable. See Limits and behavior. - The viewer reads them back, filtered by project and time range.
How a span travels
- Your SDK or collector POSTs an OTLP export to
/api/v1/traceswith the same API key. Spans that cannot be parsed are skipped and reported in the OTLPpartialSuccessresponse; the rest go through. - One row per span is written to
otel_traces, on the same asynchronous insert path as the logs. - A materialized view folds each insert into
trace_summary— one row per trace carrying its root operation, start and end, span count and error count. That is what the trace list reads, and it outlives the spans themselves: spans are kept for 30 days, summaries for 90. - The waterfall reads the spans back by trace id inside a time window; a log
line whose
TraceIdmatches links to it, and a span links back to the logs that were written under it.
Next
- Quickstart — project, key, first line.
- Endpoints — the request and response contract.
- Traces — the span endpoint, per-SDK setup, and the Collector configuration for every signal.
- Metrics — the metrics endpoint, temporality, and what the explorer draws for each metric type.