e-volv

Log Manager

Log Manager captures logs and traces from every project in a workspace hub, stores them in TimescaleDB with long retention, and turns bursts of errors into incidents with a failure graph. This page covers the standalone surface — the SDKs, OTLP ingest, the query language, the CLI and the public query API. Log Manager is a paid tier in early access; see pricing and the public API reference.

Quickstart

In the app, open Logs and create a project. Evolve mints a dedicated ingest key (scope logs:write), shows it exactly once, and gives you copy-paste snippets. Then install the SDK:

npm install @evolve/logs        # JS / TS, Node 18+
pip install evolve-logs         # Python 3.10+

JavaScript / TypeScript:

import { init } from '@evolve/logs';

init({
  key: 'evk_...',
  url: 'https://api.e-volv.io/api/public/v1/logs',
  service: 'api',
});

Python:

import evolve_logs

evolve_logs.init(
    key='evk_...',
    url='https://api.e-volv.io/api/public/v1/logs',
    service='api',
)

Both SDKs batch (200 events / 2 s / 512 KB), gzip, back off on 429 and 413, redact password|secret|token|authorization| cookie|set-cookie|api[-_]?key attributes, and propagate the traceparent across fetch, httpx and requests so a trace crosses every service it touches. Full references live in the JS SDK README and the Python SDK README.

OTLP endpoint

Any OpenTelemetry collector — or curl — can post OTLP/HTTP JSON to POST https://api.e-volv.io/api/public/v1/logs/otlp with the project key as a bearer token. Logs and traces are auto-detected; the resource’s service.name attribute picks the project:

curl -X POST "https://api.e-volv.io/api/public/v1/logs/otlp" \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer evk_..." \
  -d '{"resourceLogs":[{"resource":{"attributes":[{"key":"service.name","value":{"stringValue":"api"}}]},"scopeLogs":[{"logRecords":[{"timeUnixNano":"<unix-ns>","severityNumber":9,"body":{"stringValue":"hello from curl"}}]}]}]}'

Ingest answers 202 after enqueueing — it never waits on storage. Batches are limited to 1 000 events or 5 MB per request.

Query language

Search uses a deliberately small filter grammar compiled to SQL, with at most one aggregation suffix:

level>=error service:api "connection timeout" attrs.region=ap-southeast-1 -attrs.retry:true
| count by service, 5m
FormMeans
level>=error, level<=warnSeverity comparison using the OTel scale (trace 1 … fatal 21).
service:apiMatch a project. Known keys: level, service, trace, span.
attrs.region=ap-southeast-1Match a dotted path inside the event attributes (JSONB).
"connection timeout"Quoted phrase → full-text match on the message.
timeoutBare word → trigram contains match on the message.
-attrs.retry:trueA leading - negates any of the forms above.
duration>=250Span filters only; meaningful against traces, not log events.

One aggregation is allowed, at the end of the query:

FormMeans
| count by service, 5mEvent count grouped by the given columns, optionally time-bucketed.
| p95 duration by service, 15mp95 span latency grouped the same way.

Bucket suffixes: 1m, 5m, 15m, 1h, 1d.

CLI

The zero-dependency evolve-logs CLI (Node 18+) talks to the public query API with a logs:read key:

# Follow live logs (SSE; one JSON event per line)
evolve-logs tail --key evk_... --url https://api.e-volv.io [--project api]

# Search with the query language; prints NDJSON, pages automatically
evolve-logs search --key evk_... --url https://api.e-volv.io \
  --q 'level>=error service:api "connection timeout"' \
  [--from 2026-09-05T00:00:00Z] [--to 2026-09-05T01:00:00Z]

# List incidents
evolve-logs incidents --key evk_... --url https://api.e-volv.io

Without --from/--to, search covers the last 24 hours. The CLI ships in the repository at tools/logs-cli.

Public query API

The same search, dashboards and tail the app serves are keyed by API keys with the logs:read scope. The full route table is on the public API page; a search looks like:

curl "https://api.e-volv.io/api/public/v1/logs/query?q=level%3E%3Derror+service%3Aapi&limit=100" \
  -H "Authorization: Bearer evk_..."

Retention and caps

LimitIncluded
Projects per hub50
Ingest25 GB / month per workspace, pooled across projects
Over the capOldest events are dropped first — never the newest
Raw log retention30 days hot, 90 days tiered
Traces, error groups and incidents180 days

Dashboards read per-minute continuous aggregates, so volume, error rate and p95 latency stay fast at full retention. Error groups and incidents are kept for 180 days.