Bilis
Features Pricing Docs Blog
Documentation

Getting started

View raw

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/traces and POST /api/v1/metrics, each accepting the JSON and the protobuf encoding, gzip or deflate compressed or not — plus a simple JSON fallback at POST /api/v1/ingest for 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_traces and the five otel_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

  1. Your app or collector POSTs a batch to /api/v1/logs or /api/v1/ingest with an API key.
  2. The key resolves to a project. Bad records inside the batch are skipped and counted; the healthy ones still go through.
  3. Rows are written to otel_logs with async_insert=1 and wait_for_async_insert=0 — the response means queued, not durable. See Limits and behavior.
  4. The viewer reads them back, filtered by project and time range.

How a span travels

  1. Your SDK or collector POSTs an OTLP export to /api/v1/traces with the same API key. Spans that cannot be parsed are skipped and reported in the OTLP partialSuccess response; the rest go through.
  2. One row per span is written to otel_traces, on the same asynchronous insert path as the logs.
  3. 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.
  4. The waterfall reads the spans back by trace id inside a time window; a log line whose TraceId matches 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.