Skip to content

feat(workers logs): FUNC-853 - add supabase workers logs command - #6408

Merged
johnstonmatt merged 0 commit into
FUNC-848/workers-deploy-wait-flagfrom
FUNC-853/workers-logs-command
Aug 31, 2026
Merged

feat(workers logs): FUNC-853 - add supabase workers logs command#6408
johnstonmatt merged 0 commit into
FUNC-848/workers-deploy-wait-flagfrom
FUNC-853/workers-logs-command

Conversation

@johnstonmatt

Copy link
Copy Markdown
Contributor

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 makes workers push return without waiting on the build by default.

  • Add supabase workers logs <name>, reading the project's unified logs endpoint (there is no worker-scoped log route) filtered on log_attributes rather than the empty top-level source column, with --source, --tail, and a --follow mode that polls at the rate limit's floor, dedupes overlapping windows, and streams via stream-json
  • Print log timestamps in local time in text output, matching the --debug HTTP logger, while machine payloads keep UTC and epoch forms
  • Make supabase 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
  • Add --wait to supabase 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 through
  • Unify the workers command family's "what to run next" hints onto emitSuccessTrailer, standardize list's advisories on the WARNING: shape, and drop the URL column from list's table since it made every row 130+ columns wide for a derivable field
  • Add a repo-wide test guarding that every legacy CLI boolean flag carries a default, after --wait initially shipped without one and broke plain workers push parsing

@johnstonmatt
johnstonmatt requested a review from a team as a code owner August 31, 2026 19:08
@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Aug 31, 2026

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review Completed 2026-08-31T19:27:19.998950Z c9cb51c PR opened
ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

@johnstonmatt
johnstonmatt force-pushed the FUNC-853/workers-logs-command branch from c9cb51c to 49ad40f Compare August 31, 2026 19:14
@johnstonmatt
johnstonmatt merged commit 49ad40f into develop Aug 31, 2026
1 check passed
@johnstonmatt
johnstonmatt deleted the FUNC-853/workers-logs-command branch August 31, 2026 19:14
@johnstonmatt
johnstonmatt restored the FUNC-853/workers-logs-command branch August 31, 2026 19:19
@github-actions

Copy link
Copy Markdown
Contributor

Supabase CLI preview

npx --yes https://pkg.pr.new/supabase/cli/supabase@49ad40f7e83b342996d7621a4d1b83bcbe21b24c

Preview package for commit 49ad40f.

@chatgpt-codex-connector

Copy link
Copy Markdown

💡 Codex Review

const pollTail = Math.max(flags.tail, 1);

P1 Badge Decouple follow polling from the history limit

When --follow is combined with a small --tail value—especially the documented --tail 0 --follow case—each poll requests only one or a few rows. If more than that many entries arrive between polls, the descending SQL limit returns only the newest entries; the cursor then advances to the newest timestamp, and subsequent limited queries keep omitting the older unseen entries. This silently drops live logs, so follow polls need a batch limit independent of the requested history size.


const projectRef = yield* resolver.resolve(flags.projectRef);

P2 Badge Install telemetry finalization before resolving the project

When project resolution fails—for example, an unlinked non-interactive checkout—the failure occurs before the Effect.ensuring(telemetryState.flush) finalizer is installed, so this invocation never persists its telemetry state. Move the telemetry finalizer outside project resolution while keeping the project-dependent cache finalizer inside; every legacy invocation is required to flush on both success and failure.

AGENTS.md reference: apps/cli/AGENTS.md:L290-L290


const C0_CONTROLS = /[\u0000-\u0008\u000b\u000c\u000e-\u001f\u007f]/gu;

P2 Badge Strip carriage returns from guest log output

A guest message containing \r passes through this regex unchanged, and output.raw sends it directly to the terminal. Carriage return moves the cursor to column zero, allowing tenant-controlled output to overwrite the timestamp and stream prefix and visually forge the rendered metadata despite this sanitizer's stated purpose. Preserve tabs/newlines if needed, but strip or normalize carriage returns.


const deployed = yield* getWorker(api, projectRef, name);

P2 Badge Keep progress active during the worker lookup

When the logs query returns no rows, the initial task has already been cleared before this second API request begins. A slow or stalled getWorker call therefore leaves text-mode users with no spinner and an apparently hung command. Wrap this lookup in output.task as well, as required for asynchronous API calls.

AGENTS.md reference: apps/cli/AGENTS.md:L425-L427


? [WORKER_LOG_STREAMS[flags.source.value as WorkerLogSourceChoice]]

P2 Badge Preserve the source flag's type without an assertion

This assertion papers over the CLI flag's inferred type, so future drift between the accepted --source choices and WORKER_LOG_STREAMS can produce an undefined stream and malformed SQL instead of a compile-time failure. Restructure the flag/map typing so the choice remains a WorkerLogSourceChoice without an as assertion.

AGENTS.md reference: apps/cli/AGENTS.md:L94-L94


if (!flags.follow && output.format !== "text") {

P2 Badge Honor explicit pretty output before output-format

When users combine -o pretty with --output-format json or stream-json, legacyEmitWorkersMachineOutput returns false for pretty, after which this branch selects the structured output layer instead of the explicitly requested text rendering. The legacy --output flag is required to take priority whenever it is set, so the handler must distinguish an explicit human format from no legacy format.

AGENTS.md reference: apps/cli/AGENTS.md:L300-L300


if (entries.length === 0 && flags.tail > 0) {

P2 Badge Validate deployment for history-free follows

With --tail 0 --follow, this condition skips the worker lookup entirely. If the name is valid but not deployed, the unified logs endpoint simply keeps returning an empty result, so the command prints its waiting message and polls indefinitely rather than reporting WorkerNotDeployedError as it does for every positive tail. History-free follow should still check deployment before entering the loop.



P2 Badge Preserve request and build details in streamed entries

In --follow --output-format stream-json, using only entry.message irreversibly drops fields that the text renderer relies on: request rows lose status and duration, while build failures can lose their reason. For example, a 500 request becomes merely GET /, even though it is routed to stderr; construct the event line from the same attributes as the text output or extend the structured event so machine consumers receive the actual diagnostic details.


const poll = pollOnce.pipe(Effect.retry({ schedule: readRetrySchedule }));

P2 Badge Retry only transient follow failures

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.


return { ...actionability.apiStatus, fingerprint_suffix: "query" };

P2 Badge Classify rejected built-in queries as CLI failures

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 apiStatus records the incident as an external-service problem instead of a CLI defect, corrupting the actionability KPI and hiding regressions in this query; use the repository's CLI-bug classification while retaining the query-specific fingerprint.

AGENTS.md reference: apps/cli/AGENTS.md:L372-L372


entries.length === 0 ? Date.now() : entries[entries.length - 1]!.timestampMs,

P2 Badge Advance the follow watermark after successful polls

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 GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

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".

@johnstonmatt

Copy link
Copy Markdown
Contributor Author

Closed by a botched stack reorder on my side, not merged — none of these commits ever reached develop.

GitHub marked this merged because its head branch's commits became reachable from its base branch (FUNC-848) during a force-push, before the PR bases were repointed. A merged PR can't be reopened, so the work continues in #6410 with the same commits, rebased onto the experimental move (#6409).

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