Reading API /api/v1/logs with a stable cursor, and API tokens #26

Merged
claude Bot merged 1 commits from feat/logs-api into main 2026-11-01 15:52:42 +01:00

Requested by Cédric

What

  • GET /api/v1/logs?query=<LogsQL filter>&since=<cursor|RFC 3339|15m/6h/7d>&limit=<1..10000, default 1000>&lag=<default 30s> returns {rows, next_cursor, has_more, until, waiting?}, rows sorted by _time (reception time).
  • Stable cursor: position on _time plus the number of rows already returned among those with that exact _time, ordered by a hash of their content. A page never cuts a group in an unstable way, so following the cursors gives every row once (identical rows included).
  • Rows only count once older than lag (queue, reverse DNS), and nothing is returned (waiting: true, same cursor) while the disk spool still holds logs, so late-stored logs are not skipped.
  • API tokens (Settings > API, admins only): create (shown once), last use and IP, revoke. Stored as SHA-256 in /data/api_tokens.json (0600). Authorization: Bearer lst_…, read-only, /api/v1/ only, valid in local, OIDC and no-auth modes.
  • README EN/FR: route, parameters, errors, n8n workflow (Schedule Trigger, Code + $getWorkflowStaticData, HTTP Request, Code).

Tests

go vet, go build, go test -race -count=3 ./... OK. Cursor tests against a fake VictoriaLogs that shuffles rows sharing a timestamp: no loss or duplicate for limits 1 to 1000 with groups larger than a page, and new logs arriving between polls. Token tests: storage, hash only, revocation, Bearer scope, local auth bypass. UI checked in a static preview.

Not tested against a real VictoriaLogs: the _time:[T, T] exact-time query should be checked in the lab.

🤖 Generated with Claude Code

<!-- claude-projects-attribution: {"github_login":"vblogio"} --> _Requested by **Cédric**_ ## What - `GET /api/v1/logs?query=<LogsQL filter>&since=<cursor|RFC 3339|15m/6h/7d>&limit=<1..10000, default 1000>&lag=<default 30s>` returns `{rows, next_cursor, has_more, until, waiting?}`, rows sorted by `_time` (reception time). - Stable cursor: position on `_time` plus the number of rows already returned among those with that exact `_time`, ordered by a hash of their content. A page never cuts a group in an unstable way, so following the cursors gives every row once (identical rows included). - Rows only count once older than `lag` (queue, reverse DNS), and nothing is returned (`waiting: true`, same cursor) while the disk spool still holds logs, so late-stored logs are not skipped. - API tokens (Settings > API, admins only): create (shown once), last use and IP, revoke. Stored as SHA-256 in `/data/api_tokens.json` (0600). `Authorization: Bearer lst_…`, read-only, `/api/v1/` only, valid in local, OIDC and no-auth modes. - README EN/FR: route, parameters, errors, n8n workflow (Schedule Trigger, Code + `$getWorkflowStaticData`, HTTP Request, Code). ## Tests `go vet`, `go build`, `go test -race -count=3 ./...` OK. Cursor tests against a fake VictoriaLogs that shuffles rows sharing a timestamp: no loss or duplicate for limits 1 to 1000 with groups larger than a page, and new logs arriving between polls. Token tests: storage, hash only, revocation, Bearer scope, local auth bypass. UI checked in a static preview. Not tested against a real VictoriaLogs: the `_time:[T, T]` exact-time query should be checked in the lab. 🤖 Generated with [Claude Code](https://claude.com/claude-code)
claude Bot added 1 commit 2026-11-01 15:48:11 +01:00
GET /api/v1/logs?query=<LogsQL>&since=<cursor|time|duration>&limit=<n>
returns the logs after a cursor, oldest first, with next_cursor and
has_more. The cursor is a position on _time (the reception time) plus
the number of rows already returned among those sharing that exact
time, ordered by a hash of their content, so following the cursors
gives every row once even within groups cut by a page. Rows count once
older than the lag (30 s), and nothing is returned while the disk
spool still holds logs.

API tokens (Settings > API) give read-only access to /api/v1/ as
"Authorization: Bearer lst_...", in every auth mode; only their SHA-256
is kept in /data/api_tokens.json. README (EN/FR) documents the route and
an n8n workflow keeping the cursor in $getWorkflowStaticData.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
claude Bot marked the pull request as ready for review 2026-11-01 15:52:39 +01:00
claude Bot merged commit e77fcb326d into main 2026-11-01 15:52:42 +01:00
Sign in to join this conversation.
No Reviewers
No labels
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: vLab-BZH/logstream#26