Documentation

Last updated in git: 2026-06-11

Site access log

Each site can record an HTTP access log. It's off by default; when you turn it on, every request to the site is captured as a JSONL entry and committed to a dedicated git store. The design keeps commits in the low single digits per day for typical sites, so the log repo doesn't balloon.

Turning it on

/site log enable my-wiki

This:

  • creates a new store named my-wiki-logs (always derived from the site's content store name — there is no separate store= setting for the log)
  • starts the writer hot, without a backend restart
  • begins capturing requests immediately

Turning it back off keeps the existing log store intact for the record:

/site log disable my-wiki

Tuning

/site log set my-wiki flush_interval=2m
/site log set my-wiki flush_max_bytes=524288
/site log set my-wiki flush_max_entries=2000

Defaults: flush every 5 minutes, or when the buffer reaches 256 KiB / 1000 entries (whichever fires first), or on shutdown. There's also a buffer_hard_cap safety ceiling (1 MiB by default) — if it's reached, the writer logs a backpressure warning and forces an emergency flush.

Inspecting

/site log status my-wiki

Shows:

  • whether logging is enabled
  • the derived log store name
  • how many bytes / entries are buffered right now
  • the dropped-entry counter (incremented when the channel is full)
  • the timestamp of the last successful flush
  • the last error, if any
/site log tail my-wiki 100

Prints the last 100 lines from the most recent day file(s). Each line is validated; lines with an unknown schema version are reported with their file path and line number, but the rest of the file is still readable.

What gets captured

One JSON object per line. Field order is fixed:

{"v":1,"ts":"2026-06-04T14:32:11.482Z","site":"my-wiki","host":"wiki.localhost","method":"GET","path":"/posts/hello","status":200,"bytes":4821,"ip":"203.0.113.7","ref":"https://duckduckgo.com/","ua":"Mozilla/5.0 ...","dur_ms":12}
  • ts is UTC with millisecond precision.
  • path includes the query string. Sensitive query params (password, token, code, state, secret) have their values redacted as ***.
  • bytes is the response body size in bytes (excluding headers), 0 for HEAD/204/304.
  • ip is the first entry of X-Forwarded-For if present (trusted unconditionally — Everlock assumes a controlled frontend), otherwise the socket peer address. Omitted when neither is available.
  • dur_ms is wall-clock time from the body wrapper attaching to response completion.
  • WebSocket upgrades (status 101) are not logged.

File layout

The log store is a normal git repo:

my-wiki-logs/
  2026/
    2026-06-04.jsonl
    2026-06-03.jsonl
  2025/
    2025-12-31.jsonl
  README.md

One file per UTC day, grouped by year. Each daily file contains only entries whose ts falls within that day — the first flush after midnight emits two commits: a final append to yesterday's file for the 23:59 stragglers, then a normal append to today's file.

Reading the log

The files are plain UTF-8 JSONL, so:

jq 'select(.status==404)' 2026-06-04.jsonl
grep '"status":404' 2026-06-04.jsonl
jq -r '[.ts, .ip, .method, .path, .status] | @tsv' 2026-06-04.jsonl

git log on the log store shows the flush history, which is useful for verifying that retention or pruning policies are working.

Why a separate store

Logs live in <site-store>-logs, never in the content store itself. Reasons:

  • the content repo's git log keeps telling the story of edits, not traffic
  • log retention can differ from content retention (e.g. prune after 90 days)
  • the site can be public while the log store stays private
  • one fewer name to invent — the log store name is always derived

Failure handling

The request path is never blocked by logging:

  • if the in-memory channel is full, entries are dropped (rate-limited warning, dropped count visible in /site log status)
  • if store.write to the log store fails (disk full, git lock stuck, etc.), the writer drops the pending buffer with a rate-limited warning and keeps going — no auto-disable, no retry queue, and the site itself keeps serving requests normally

See also

sites access-log ops