Skip to content

feat: add pod and serverless worker log readers - #599

Open
muhibwqr wants to merge 1 commit into
runpod:mainfrom
muhibwqr:feat/pod-logs
Open

muhibwqr wants to merge 1 commit into
runpod:mainfrom
muhibwqr:feat/pod-logs

Conversation

@muhibwqr

Copy link
Copy Markdown

Closes #400.

The REST v2 API already serves pod and worker logs as SSE streams (GET /v2/pods/{id}/logs, GET /v2/serverless/{id}/workers/{workerId}/logs), and runpodctl pod logs wraps them. This adds the Python SDK side. It follows the bounded-snapshot shape agreed in the issue thread, plus a follow mode.

API

# snapshot: backfill + up to max_wait seconds of live output
logs = runpod.get_pod_logs(pod_id, tail=200, source="container", max_wait=5)
# [{"id": "...", "ts": "2026-06-01T12:02:03Z", "source": "container", "line": "Model loaded."}, ...]

# follow: yields as lines arrive; resumes via Last-Event-ID
for entry in runpod.iter_pod_logs(pod_id, tail=0):
    print(entry["line"])

# serverless workers
workers = runpod.get_endpoint_workers(endpoint_id)
logs = runpod.get_endpoint_worker_logs(endpoint_id, workers[0]["id"])
Addition Notes
get_pod_logs, get_endpoint_worker_logs Return a list, oldest first. Stop after max_wait seconds, or once the stream has been idle that long. Past max_bytes (default 4 MiB) the oldest lines are dropped, so the newest output (usually the crash) is kept.
iter_pod_logs, iter_endpoint_worker_logs Generators. When the stream closes or goes idle they reconnect with Last-Event-ID, so lines are neither repeated nor skipped. On reconnect they retry network errors and 429s (honoring Retry-After). Errors on the first connection, and non-429 HTTP errors, raise. Optional max_wait caps total time.
get_endpoint_workers GET /v2/serverless/{id}/workers. Worker log readers need worker IDs, and the SDK had no way to list them.
QueryError.retry_after Seconds from Retry-After on any REST error, or None.
rest.read_event_stream Streaming SSE transport. run_rest_request is unchanged.

Arguments are validated before any request is made (tail 0–5000, source in container/system/None, since as an RFC3339 string or a timezone-aware datetime). This applies to the generators too.

Tests

  • Unit tests for the SSE parser (frames split across chunks, CRLF, comments, multi-line data, UTF-8 split mid-character, an incomplete trailing event dropped), the transport, and reconnect/retry logic.
  • tests/test_api/test_logs_server.py runs the readers against a local fake of the log endpoints over real sockets, so the requests/urllib3 chunked-read and read-timeout behavior is exercised, not mocked. It covers the idle and busy-stream deadlines, a cut frame, the byte cap, 404, Last-Event-ID resume without gaps, a 429 on reconnect, max_wait, and the worker listing plus worker logs. It takes about 4s.
  • Full suite: 839 passed, coverage 94.32%. ruff and pylint report nothing on the changed modules.

Not yet run against the live API. The wire format follows the published API reference and the runpod-mcp stream-pod-logs reader.

Docs: README Logs section, and retry_after in docs/api/handling_errors.md.

🤖 Generated with Claude Code

Read the REST v2 SSE log streams (GET /v2/pods/{id}/logs and
GET /v2/serverless/{id}/workers/{workerId}/logs):

- get_pod_logs / get_endpoint_worker_logs return a bounded snapshot
  (tail backfill plus up to max_wait seconds of live output, capped at
  max_bytes with the oldest lines dropped).
- iter_pod_logs / iter_endpoint_worker_logs follow the stream, resuming
  from Last-Event-ID on close or idle, and waiting out 429s on reconnect.
- get_endpoint_workers lists worker IDs for the worker log readers.
- QueryError.retry_after exposes the Retry-After header.

Refs runpod#400

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
@muhibwqr

muhibwqr commented Sep 25, 2026 •

Copy link
Copy Markdown
Author

hi my name is muhib, i am a second year waterloo math student, i thought it would be pretty cool to push a pr here as I wanted to a) find an internship for the winter b) actually try and understand how runpod works

This branch has not been deployed

No deployments
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.

Feature Request: Add API Support for Retrieving Pod Logs

1 participant