feat(workers logs): FUNC-853 - add supabase workers logs command - #6408
Conversation
Codex Review SummaryThis comment shows the latest Codex review activity on this pull request.
ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings. |
c9cb51c to
49ad40f
Compare
Supabase CLI previewnpx --yes https://pkg.pr.new/supabase/cli/supabase@49ad40f7e83b342996d7621a4d1b83bcbe21b24cPreview package for commit |
💡 Codex ReviewWhen When project resolution fails—for example, an unlinked non-interactive checkout—the failure occurs before the AGENTS.md reference: apps/cli/AGENTS.md:L290-L290 A guest message containing When the logs query returns no rows, the initial task has already been cleared before this second API request begins. A slow or stalled AGENTS.md reference: apps/cli/AGENTS.md:L425-L427 This assertion papers over the CLI flag's inferred type, so future drift between the accepted AGENTS.md reference: apps/cli/AGENTS.md:L94-L94 When users combine AGENTS.md reference: apps/cli/AGENTS.md:L300-L300 With In Once follow mode is running, this unfiltered retry also catches permanent failures such as exhausted usage (402), an unavailable project (404), authentication/permission statuses, and a rejected built-in query. Those errors are then reissued every five seconds for up to a minute before reaching the user; for a 429 this extra traffic can itself keep the request window saturated. Restrict retries to genuinely transient network, rate-limit, and retryable server failures, with an interval appropriate to the rate limit. This class is raised when the fixed SQL generated by the CLI is rejected, and its own documentation correctly notes that the projection or filter in the CLI is therefore wrong. Classifying it as AGENTS.md reference: apps/cli/AGENTS.md:L372-L372 The cursor starts at the newest emitted event timestamp and advances only when a still-newer event appears. On a quiet worker, the interval from that timestamp to the current time therefore grows on every poll; a tail left running eventually re-queries nearly the full 24-hour window every ten seconds, repeatedly scanning and returning the same deduplicated rows until it hits query timeouts or usage limits. Track the last successful polling watermark separately and advance it even for empty or only-late batches, retaining only the intended grace overlap. ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
If Codex has suggestions, it will comment; otherwise it will react with 👍. Codex can also answer questions or update the PR. Try commenting "@codex address that feedback". |
|
Closed by a botched stack reorder on my side, not merged — none of these commits ever reached GitHub marked this merged because its head branch's commits became reachable from its base branch ( |
…e#6410) ## Summary Reads the project's unified logs stream rather than a worker route — there is no worker-scoped log endpoint — via `v1GetProjectLogs`, which the generated client already carries. `--kind app|requests|builds` narrows to one of the three streams; without it all three are returned, tagged per line. `--tail` caps the rows. `--follow` keeps printing until interrupted. ## Three non-obvious things about that endpoint Each is documented at its call site, because none is guessable from the API surface: - **The filter is `log_attributes`, not the `source` column.** Worker rows carry an empty top-level `source`, because the Workers Logflare source is not enrolled as a category in the generic logs path, so `where source = 'worker_guest_logs'` matches nothing. The `in (...)` list over the three known streams is a tenancy guard rather than a convenience — with `source` empty it is the only thing excluding a non-worker row that happens to carry a `worker` attribute. - **Both timestamp bounds are always sent, spanning under 24h.** One bound alone yields a one-minute window, silently; neither is an outright error; and a span over 24h is clamped to `start + 24h`, returning an *older* slice than the one asked for rather than a truncated one. - **A failed query can arrive as HTTP 200** with a populated `error`, so the envelope is checked before `result`. The response is decoded against a local schema rather than the generated `V1GetProjectLogsOutput`: that schema marks `result`/`error` optional but permits neither to be `null`, while the endpoint always sends one of them as an explicit `null`. Decoding a real response against it always fails — worth fixing in the spec separately. ## Rendering Per-stream, because `event_message` differs in kind: on the request stream it is only `"GET /"`, with status and duration in `log_attributes`, so the request line is composed. `severity_text` is ignored — it is `INFO` on every row of every stream — so the level is derived, and app lines report none rather than a guess. An app message is tenant-controlled bytes, so escape sequences are stripped before it reaches a terminal while a stack trace's newlines and indentation survive. ## `--follow` The poll interval is set by the rate limit, not by responsiveness: the v1 analytics endpoints allow 10 requests per 60 seconds, so the two-second poll a live tail suggests would spend the whole allowance in ten seconds. It polls every 10 seconds, measured at ~7 requests in the worst 60-second window. The cursor deliberately lags 60 seconds behind the newest line printed. Guest lines are relayed CloudWatch → subscription filter → Lambda → Logflare and arrive late and out of order, so a cursor sitting on the newest timestamp would drop every straggler permanently. Overlap is therefore guaranteed; dedupe on the Logflare-minted `id` is what makes it invisible. `-o json|yaml|toml` and `--output-format json` are refused up front — each promises one terminal payload and a tail has no last element. `--output-format stream-json` emits one `log-entry` event per line. SIGINT exits 130. ## Stack On top of the workers output polish (supabase#6389), with `push --wait` (supabase#6371) stacked above so it can be rejected independently. Below those: the `workers new` name prompt (supabase#6349). ## Note Replaces supabase#6408, which GitHub marked merged during a stack reorder. It was never merged to `develop`; the branch and its commits are intact here.
Adds a way to read a worker's runtime output, closing the gap between a successful deploy and diagnosing a misbehaving worker. Along the way it makes
workers new's name prompt-driven, moves the command family's output onto shared conventions, and makesworkers pushreturn without waiting on the build by default.supabase workers logs <name>, reading the project's unified logs endpoint (there is no worker-scoped log route) filtered onlog_attributesrather than the empty top-levelsourcecolumn, with--source,--tail, and a--followmode that polls at the rate limit's floor, dedupes overlapping windows, and streams viastream-json--debugHTTP logger, while machine payloads keep UTC and epoch formssupabase workers new's name argument optional, prompting for it (validated against the same checks the command already enforces) when omitted and there's a terminal to ask on, gated on both stdout and stdin being a TTY--waittosupabase workers push, so the command returns once the deploy is accepted rather than blocking on the server-side build; report unattempted workers on a run that fails partway throughemitSuccessTrailer, standardizelist's advisories on theWARNING:shape, and drop the URL column fromlist's table since it made every row 130+ columns wide for a derivable field--waitinitially shipped without one and broke plainworkers pushparsing