Add sc logs — follow a running service's output #12
No reviewers
Labels
No labels
⏳in-progress
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set
Reference
Grey.ooo/someones.computer_agent!12
Loading…
Reference in a new issue
No description provided.
Delete branch "feature/sc-logs"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
The CLI half of log tailing. The platform serves the tail as newline-delimited JSON on the bearer-token firewall; this reads it.
Against a live platform:
Decisions worth reviewing
stdout is log lines and nothing else. Which application, which endpoint, why the stream ended — all stderr, so redirecting collects the log clean. There's a test asserting the keep-alive reaches neither stream.
The application resolves exactly as
deployresolves it —--app, then.sc.yml, then the directory name — so the two cannot mean different applications in one checkout.The streaming request does not use the shared
http.Client. Its five-minute ceiling is exactly wrong for a tail, whose job is to stay open and say nothing for long stretches; the deadline that matters is the context's. Tested, because the failure mode is a tail that dies after five minutes and nobody notices until they leave one running.mainnow installs a signal handler and runs the command with that context. Ctrl-C is how a person stops watching a log, so cancellation is reported as a quiet end rather than an error. Every other command benefits too: a request is now actually abandoned rather than left for the platform to answer into a dead socket.Unparseable frames are skipped, not fatal. A newer platform sending something this client doesn't know shouldn't cost the reader the lines either side of it.
APIErrorgainsRetryAfter, so a full stream pool is reported as "try again in 10s" rather than "try again".Depends on
The platform-side endpoint
GET /cli/applications/{slug}/services/{service}/logs— Someones.Computer#155. Against a platform without it,sc logssays "…cannot stream logs —sc logsneeds a newer platform" rather than "not found", because a 404 with noerrorkey is a missing route, not a missing application. There's a test for that too.Verification
go vet ./...,go test ./...— clean.19 new tests — 11 on the client (framing, ping, escaping, cancellation, the timeout, each error shape) and 8 on the command (stream separation, the flags, and each error turned into a sentence someone can act on).
sc logs— follow a running service's outputThe platform serves the tail as newline-delimited JSON on the bearer-token firewall; this reads it. `sc logs <service>` streams one service's stdout and stderr as it happens, with --tail N of history first (200 by default, 0 to start from now). Log lines go to stdout and everything else — which application on which endpoint, why the stream ended — to stderr, so `sc logs web > web.log` collects the log and nothing else. The application resolves exactly as `deploy` resolves it (--app, then .sc.yml, then the directory name), so the two cannot mean different applications in one checkout. Three things the framing buys, which a raw text stream could not: - a keep-alive is recognisable as one and is swallowed rather than printed; - the stream ending on purpose is told apart from the connection dropping, and only the first carries a reason; - a frame from a newer platform that this client cannot parse is skipped rather than ending the tail, so the lines either side still arrive. The streaming request deliberately does not use the shared http.Client: its five-minute ceiling is exactly wrong for a tail, whose job is to stay open and say nothing for long stretches. The deadline that matters is the context's. main now installs a signal handler and runs the command with that context. Ctrl-C is how a person stops watching a log, so cancellation is reported as a quiet end rather than an error — and every other command now gets a request that is actually abandoned instead of one the platform answers into a dead socket. APIError carries Retry-After, so a full log-stream pool can be reported as "try again in 10s" rather than "try again". Verified against a live platform: streamed a real Postgres service, and checked the 409 (no such service), 404 (no such application) and missing-token paths through the built binary. Requires the platform-side endpoint — GET /cli/applications/{slug}/services/{service}/logs.