Skip to main content

Run Logs (client.log)

View as Markdown

Run Logs — client.log

Every task writes one continuous JSONL event log per projectId + source (+ scope) — a continuum in which individual runs are chapter markers. The client.log namespace reads it: chapters for the activity timeline, ranged event reads, raw segment fetches, deletion, and the DVR session (open_event_stream) that powers live monitoring and replay with one API.

import asyncio
from rocketride import RocketRideClient


async def main():
client = RocketRideClient(host='localhost', port=5565)
await client.connect()

# The stream's chapters (runs): begin/end/outcome per run.
timeline = await client.log.chapters('proj-1', 'chat_1')
for chapter in timeline['chapters']:
print(chapter['beginTime'], chapter.get('outcome'))

# Ranged event read over the continuum (paged).
page = await client.log.read('proj-1', 'chat_1', from_seq=0, types=['output'])
for event in page['events']:
print(event['body'].get('output', ''), end='')

# The DVR session — live + replay through one surface.
# Own dev stream; pass team_id='team-prod' for a team's deploy continuum.
session = client.log.open_event_stream('proj-1', 'chat_1')
await session.seek('live')
status = await session.get_status() # state as of the position
console = await session.get_console(500) # exactly what the console showed
traces = await session.get_traces(50) # in-flight + last 50 closed
await session.play(None, 0, lambda item: print(item['event']['event']))

# Drill into one trace by its PERMANENT identity — the begin event's
# continuum seq (slot ids recycle; beginSeq never does). A fresh or
# all-in-flight stream may have no closed traces yet.
if traces['closed']:
detail = await session.get_trace(traces['closed'][0]['beginSeq'])

session.pause()
session.close_event_stream()
await client.disconnect()


asyncio.run(main())

Event shape

Every event carries the continuum stamps in its body — the only place they exist: body['eventTime'] (epoch seconds, stamped once at engine ingress) and body['logSeq'] (catalog-seeded — a fresh stream starts at 1 and continues from the recorded lastSeq + 1 across runs and restarts; strictly monotonic) — identical live and on replay, beside the project_id/source identity. The DAP envelope's own seq is per-connection protocol bookkeeping and says nothing about the continuum. Legacy segments that carried the stamps at the header are canonicalized into the body at decode, so consumers read one shape.

Methods

MethodPurpose
chapters(project_id, source, *, team_id='')Runs (tracks) + segment spans + stream extents
read(project_id, source, *, team_id='', ...)Ranged event read: from_seq/to_seq, from_time/to_time, types, paging via nextSeq cursor
segment(project_id, source, segment_id, *, team_id='', ...)Raw whole-line-aligned segment bytes (bulk replay path)
delete(project_id, source, *, team_id='', ...)Drop history: before_time or everything
open_event_stream(project_id, source, *, team_id='')The DVR session (below)

The scope is the kind. Pass team_id to address that team's DEPLOY continuum — deploy runs execute as the team and log into its tree, so any teammate with monitor rights can watch and replay them. Omit team_id for your own dev stream. There is no run-kind argument anywhere.

The DVR session

open_event_stream() returns a LogEventStream mirroring the TypeScript SDK session (seek, play, pause, get_status, get_traces, get_trace, get_console, ingest_live, close_event_stream). Seed-then-stream protocol: seek(pos) positions the session, the get_* calls answer as of that position, and play(pos, speed, cb) delivers events strictly after the seed watermark, paced by speed (0 = flat-out, 1 = real time, 10 = 10x). Playing from a past position auto-pins to live on catching the wall clock — replay flows into live with no seam.

get_trace(begin_seq) resolves a trace by its begin event's continuum seq. It fails when the seq has fallen below the retention horizon, or when no trace-begin event exists at that seq — a recycled slot id or a client fold's document counter is NOT a trace identity.

get_traces(n) errors when n > 50 — the session exposes all in-flight traces plus a sliding window of the 50 most recently closed; any older trace is still reachable by seeking to a position inside its lifetime.