Skip to content

feat(logs): add --once for bounded non-interactive capture#120

Open
tcerqueira wants to merge 1 commit into
mainfrom
tc/logs-once
Open

feat(logs): add --once for bounded non-interactive capture#120
tcerqueira wants to merge 1 commit into
mainfrom
tc/logs-once

Conversation

@tcerqueira

Copy link
Copy Markdown
Member

What

Adds --once to deno deploy logs: a bounded, non-interactive "capture
currently-available logs then exit" mode for CI and agents. Addresses the rough
edge from #112 — previously logs could only tail live forever or stream a
fixed --start/--end window, with no way to grab the current backlog and exit
without already knowing an --end.

Semantics

  • --once streams the backfilled logs in the window, then exits 0 the moment
    the backend emits its "streaming" phase marker (verified empirically: the
    marker is sent after the backfill batches, signalling the switch from
    historical backfill to live tailing). It does not enter live tail.
  • The SSE subscription is closed (sub.unsubscribe()) and the process exits
    cleanly with ExitCode.OK. A server-completed stream (onStopped, e.g. a
    bounded --start/--end window) is also treated as a clean end-of-capture.
  • Window defaults to the last hour when no --start is given (a bare
    new Date() start would request an empty window); an explicit --start
    widens/narrows it.
  • --json NDJSON discipline is preserved: only log records on stdout, one JSON
    object per line. An empty window exits 0 with no output.

Rejected / deferred alternatives

  • Inactivity --timeout <duration> (exit after N seconds of silence): useful
    for bounded live capture, but heuristic and non-deterministic. --once uses
    a real backend signal (backfill-complete), so it's exact. Can be added later as
    a complementary flag.
  • --max <n> lines: orthogonal cap; not needed for the "drain current
    backlog" use case and easily composed downstream (| head -n).

Supporting fix

logs is read-only, so it now calls config.noCreate() like the other
inspection commands (apps, orgs, deployments, whoami). That exposed a
long-standing bug: the actionHandler save guard tested !config (the
always-truthy Config wrapper) instead of !config.config (no existing config
file), so noCreate() never actually prevented file creation. Fixed. Net
effect: no command creates a stray deno.jsonc as a side effect — which in
--json mode would otherwise print a non-JSON Created configuration file line
on stdout. Existing config files are still updated.

Verification (live, against a throwaway app)

  • logs --once --json --non-interactive: exits on its own (~0s), emits clean
    NDJSON (all lines parse), no deno.jsonc created.
  • Empty window (--once --start <now>): exits 0 with no output.
  • Human mode (--once): exits 0, formatted output.
  • Regression: a pre-existing deno.json is still updated with the deploy
    object.

Overlap

Touches the logs command region of deploy/mod.ts; the tc/app-production-url
sibling PR touches the publish/deploy flow in the same file and will rebase.

`deno deploy logs` could only tail live forever or stream a fixed
--start/--end window; CI and agents had no way to capture the
currently-available logs and exit without already knowing an --end
(rough edge from #112).

--once drains the backfill window and exits 0 at the live boundary (the
server's "streaming" phase marker), so the capture is bounded and
deterministic. With no --start it defaults to the last hour so there is
something to drain; an explicit --start still wins. NDJSON on stdout is
preserved and the SSE subscription is closed cleanly before exit. An
empty window exits 0 with no output.

Also make `logs` read-only like the other inspection commands via
config.noCreate(), and fix the long-broken noCreate guard in
actionHandler (it tested the always-truthy config wrapper instead of
config.config). No command now creates a stray deno.jsonc as a side
effect, which in --json mode would otherwise print a non-JSON "Created
configuration file" line on stdout. Existing config files are still
updated.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant