Set the endpoint and the token on the exporter. Logs, traces and metrics over OTLP, by HTTP or gRPC. No agent on the host and no collector in between; add Vector, Fluent Bit or Alloy for a disk buffer or enrichment. Hosted is this path, our infra.
OTEL_EXPORTER_OTLP_ENDPOINT=http://127.0.0.1:8080 OTEL_EXPORTER_OTLP_PROTOCOL=http/protobuf OTEL_EXPORTER_OTLP_HEADERS=Authorization=Bearer%20${TOPOSCOPE_INGEST_TOKEN} OTEL_SERVICE_NAME=billing OTEL_RESOURCE_ATTRIBUTES=service.version=1.4.2 OTEL_LOGS_EXPORTER=otlp OTEL_METRICS_EXPORTER=otlp
OTEL_EXPORTER_OTLP_ENDPOINT=http://127.0.0.1:4319 OTEL_EXPORTER_OTLP_HEADERS=Authorization=Bearer%20${TOPOSCOPE_INGEST_TOKEN}
sources: apps: type: opentelemetry http: address: 127.0.0.1:4318 grpc: address: 127.0.0.1:4317 use_otlp_decoding: true sinks: toposcope: type: opentelemetry inputs: [apps.logs] protocol: type: http uri: http://127.0.0.1:8080/v1/logs encoding: codec: otlp batch: max_events: 1 request: headers: Authorization: "Bearer ${TOPOSCOPE_INGEST_TOKEN}" buffer: type: disk max_size: 268435488 when_full: block
[OUTPUT] Name opentelemetry Match * Host 127.0.0.1 Port 8080 Logs_uri /v1/logs Traces_uri /v1/traces Header Authorization Bearer ${TOPOSCOPE_INGEST_TOKEN}
otelcol.auth.headers "toposcope" { header { key = "Authorization" value = "Bearer ${TOPOSCOPE_INGEST_TOKEN}" } } otelcol.exporter.otlphttp "toposcope" { client { endpoint = "http://127.0.0.1:8080" auth = otelcol.auth.headers.toposcope.handler } }
curl -X POST http://127.0.0.1:8080/api/ingest \ -H 'authorization: Bearer ${TOPOSCOPE_INGEST_TOKEN}' \ -d '{"service":"api","level":"error","message":"timeout"}'
- name: Mark deploy in Toposcope env: TOPOSCOPE_URL: ${{ secrets.TOPOSCOPE_URL }} TOPOSCOPE_INGEST_TOKEN: ${{ secrets.TOPOSCOPE_INGEST_TOKEN }} TOPOSCOPE_SERVICE: billing run: | curl -fsS -X POST "${TOPOSCOPE_URL}/v1/marks" \ -H "authorization: Bearer ${TOPOSCOPE_INGEST_TOKEN}" \ -H "content-type: application/json" \ -d "{\"kind\":\"deploy\",\"title\":\"${GITHUB_REF_NAME}\",\"id\":\"deploy-${TOPOSCOPE_SERVICE:+${TOPOSCOPE_SERVICE}-}${GITHUB_REF_NAME}\",\"service\":\"${TOPOSCOPE_SERVICE}\",\"attrs\":{\"version\":\"${GITHUB_REF_NAME}\",\"sha\":\"${GITHUB_SHA}\",\"source\":\"github\"}}"
mark_deploy: stage: deploy rules: - if: $CI_COMMIT_TAG script: - | curl -fsS -X POST "${TOPOSCOPE_URL}/v1/marks" \ -H "authorization: Bearer ${TOPOSCOPE_INGEST_TOKEN}" \ -H "content-type: application/json" \ -d "{\"kind\":\"deploy\",\"title\":\"${CI_COMMIT_TAG}\",\"id\":\"deploy-${TOPOSCOPE_SERVICE:+${TOPOSCOPE_SERVICE}-}${CI_COMMIT_TAG}\",\"service\":\"${TOPOSCOPE_SERVICE}\",\"attrs\":{\"version\":\"${CI_COMMIT_TAG}\",\"sha\":\"${CI_COMMIT_SHA}\",\"source\":\"gitlab\"}}"
echo '<27>Aug 14 01:02:03 api-1 nginx: timeout' \ | nc -u -w1 127.0.0.1 5514
The React UI, Hono API, ingest, query and alerts ship in one process. ClickHouse holds signal data; SQLite holds control state.
TOPOSCOPE · ONE BUN APP
CLICKHOUSE · SIGNAL DATA
Level, service and host searches across the week return in under 0.1 s, cold or warm. One attribute takes 1.3 s warm and about 3 s cold. A message term is refused across the week; across a day it takes 0.14 s.
Refused: a message term across the full week is past the read budget of 20 million rows, 256 MiB or 8 seconds. The newest 100 events still return; the count and histogram do not.
Each load profile is in the repo. Run it, then search.
Hosted early access is planned for Q4 2026. The same product as the free self-hosted edition, operated by us.