Skip to content

feat: add session record disk logging (RecordLogger)#953

Open
guapisolo wants to merge 5 commits intomainfrom
feat/session-record-logger
Open

feat: add session record disk logging (RecordLogger)#953
guapisolo wants to merge 5 commits intomainfrom
feat/session-record-logger

Conversation

@guapisolo
Copy link
Copy Markdown
Collaborator

Summary

  • Add RecordLogger class that writes SessionRecord objects as one-JSON-per-line to per-session files under --session-record-log-dir
  • Records are flushed immediately so partial sessions survive crashes
  • Integrate into SessionRegistry: records are written on each chat completion and file handles are closed when sessions are deleted
  • Add --session-record-log-dir CLI argument (disabled when not set)

Test plan

  • Verify session records are written to disk when --session-record-log-dir is set
  • Verify no logging occurs when the flag is not set
  • Verify file handles are properly closed on session deletion

Made with Cursor

Copy link
Copy Markdown
Contributor

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request introduces a disk-based JSONL logger for session records, enabling per-session logging to a configurable directory. Key changes include the implementation of the RecordLogger class, integration into the session registry, and a new CLI argument to enable the feature. Feedback focuses on performance and efficiency: the logging call within the asynchronous chat_completions function performs blocking I/O and should be offloaded to a thread pool to prevent event loop degradation. Additionally, using Pydantic's model_dump_json() is recommended for more efficient serialization of session records.

response=response,
)
session.append_record(record)
registry.log_record(session_id, record)
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

The registry.log_record call performs blocking synchronous I/O (writing to disk and flushing) within an async function. This will block the event loop and degrade performance for all concurrent requests. Consider offloading this to a thread pool.

Suggested change
registry.log_record(session_id, record)
import asyncio
await asyncio.to_thread(registry.log_record, session_id, record)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Here I think we dont need asyncio, the record logging should be very light-weighted? Not sure

def log_record(self, session_id: str, record: SessionRecord) -> None:
try:
handle = self._get_handle(session_id)
handle.write(json.dumps(record.model_dump(), default=str) + "\n")
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

Since SessionRecord is a Pydantic model, using model_dump_json() is more efficient than manually dumping to a dict and then to JSON. It also handles common types like datetime or UUID more gracefully.

Suggested change
handle.write(json.dumps(record.model_dump(), default=str) + "\n")
handle.write(record.model_dump_json() + "\n")

"""Enqueue a session-close event (flushes and closes the file handle)."""
self._queue.put(("close", session_id, None))

def close_all(self) -> None:
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

close_all here is not called other than test?

Do you want to add an atexit with close all?

e.g.

import atexit

def __init__(self, log_dir: str):
    ...
    self._thread.start()
    atexit.register(self.close_all)

response=response,
)
session.append_record(record)
registry.log_record(session_id, record)
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Here I think we dont need asyncio, the record logging should be very light-weighted? Not sure

callers (typically async request handlers) never block on file operations.
Records are flushed immediately so that partial sessions are preserved
if the process crashes.
"""
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you refactor this file? I think the logic is good but a little hard to follow.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Okay. Let me check in more detail

guapisolo and others added 5 commits April 10, 2026 00:23
Add a JSONL-based RecordLogger that writes each SessionRecord to a
per-session file under `--session-record-log-dir`. Records are flushed
immediately so partial sessions survive crashes.

Integrate RecordLogger into SessionRegistry: records are written on
each chat completion and file handles are closed when sessions are
deleted.

Made-with: Cursor
Move serialization and disk I/O off the event loop into a dedicated
daemon thread backed by a SimpleQueue, so log_record() and
close_session() return immediately without blocking async handlers.

Co-Authored-By: Claude Opus 4.6 (1M context) <[email protected]>
Remove the standalone --session-record-log-dir argument and instead
automatically set it to {dump_details}/session_records when
--dump-details is provided, consistent with rollout_data and train_data.

Co-Authored-By: Claude Opus 4.6 (1M context) <[email protected]>
@guapisolo guapisolo force-pushed the feat/session-record-logger branch from 02449ea to 69eee6a Compare April 10, 2026 00:24
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.

2 participants