Skip to content

feat(app): stream live server logs to the management UI via SSE#45

Merged
CoderCoco merged 5 commits into
mainfrom
claude/issue-43-lgcMo
May 1, 2026
Merged

feat(app): stream live server logs to the management UI via SSE#45
CoderCoco merged 5 commits into
mainfrom
claude/issue-43-lgcMo

Conversation

@CoderCoco
Copy link
Copy Markdown
Owner

@CoderCoco CoderCoco commented Apr 30, 2026

Closes #43

Adds a real-time log tail to the Logs panel:

  • LogsService.streamLogs(game, signal) – AsyncGenerator that polls
    FilterLogEvents every 2 s, de-duplicates by eventId, advances
    startTime on each tick, and exits cleanly when the AbortSignal fires.
    Queries the whole log group so task stop+start (new stream) is handled
    automatically.

  • GET /api/logs/:game/stream – @sse() endpoint wrapping the generator
    in an RxJS Observable. Teardown aborts the generator when the client
    disconnects.

  • ApiTokenGuard – falls back to ?token= query param when the
    Authorization header is absent, which is necessary because the
    browser's native EventSource cannot set custom headers.

  • LogsPanel.tsx – fetches a snapshot on game change then opens an
    EventSource stream that appends new lines (capped at 1 000). Pause
    buffers incoming lines; Resume flushes the buffer. Replaces the old
    manual Refresh button.

  • LogsService.test.ts – seven new streamLogs cases covering clean
    termination, multi-poll delivery, de-duplication, log-group naming,
    error recovery, and missing message fields.

  • docs/components/management-app.md – updated endpoint table, Live Logs
    description, auth notes, and LogsService blurb.

IAM: logs:* already covers FilterLogEvents (docs/setup.md unchanged).

https://claude.ai/code/session_01THkoGDYjJhojhtnUEYi4w9

Adds a real-time log tail to the Logs panel:

- LogsService.streamLogs(game, signal) – AsyncGenerator that polls
  FilterLogEvents every 2 s, de-duplicates by eventId, advances
  startTime on each tick, and exits cleanly when the AbortSignal fires.
  Queries the whole log group so task stop+start (new stream) is handled
  automatically.

- GET /api/logs/:game/stream – @sse() endpoint wrapping the generator
  in an RxJS Observable. Teardown aborts the generator when the client
  disconnects.

- ApiTokenGuard – falls back to ?token= query param when the
  Authorization header is absent, which is necessary because the
  browser's native EventSource cannot set custom headers.

- LogsPanel.tsx – fetches a snapshot on game change then opens an
  EventSource stream that appends new lines (capped at 1 000). Pause
  buffers incoming lines; Resume flushes the buffer. Replaces the old
  manual Refresh button.

- LogsService.test.ts – seven new streamLogs cases covering clean
  termination, multi-poll delivery, de-duplication, log-group naming,
  error recovery, and missing message fields.

- docs/components/management-app.md – updated endpoint table, Live Logs
  description, auth notes, and LogsService blurb.

IAM: logs:* already covers FilterLogEvents (docs/setup.md unchanged).

https://claude.ai/code/session_01THkoGDYjJhojhtnUEYi4w9
Copilot AI review requested due to automatic review settings April 30, 2026 17:18
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Adds live log tailing to the management UI using Server-Sent Events (SSE), backed by a new LogsService.streamLogs poller and an SSE controller endpoint, plus an auth guard update to support EventSource limitations.

Changes:

  • Add LogsService.streamLogs() async generator polling CloudWatch FilterLogEvents, plus an SSE endpoint GET /api/logs/:game/stream.
  • Update ApiTokenGuard to accept ?token= when Authorization is not present (for SSE/EventSource).
  • Update the web LogsPanel to load a snapshot then stream new lines via EventSource, and update docs/tests accordingly.

Reviewed changes

Copilot reviewed 7 out of 7 changed files in this pull request and generated 3 comments.

Show a summary per file
File Description
docs/docs/components/management-app.md Documents the new SSE logs endpoint, streaming behavior, and auth fallback.
app/packages/web/src/components/LogsPanel.tsx Replaces manual refresh with snapshot + SSE streaming, plus Pause/Resume buffering.
app/packages/server/src/services/LogsService.ts Adds streamLogs() async generator and interruptible sleep for polling.
app/packages/server/src/services/LogsService.test.ts Adds test coverage for streamLogs() polling, dedupe, termination, and error recovery.
app/packages/server/src/guards/api-token.guard.ts Allows ?token= fallback when Authorization header is absent.
app/packages/server/src/controllers/logs.controller.ts Adds @Sse(':game/stream') endpoint wrapping streamLogs() in an Observable.

Comment thread app/packages/web/src/components/LogsPanel.tsx Outdated
Comment thread app/packages/server/src/services/LogsService.ts Outdated
Comment thread app/packages/server/src/services/LogsService.ts
claude added 2 commits May 1, 2026 00:10
- sleepInterruptible: remove the abort listener on both the resolve and
  reject paths so it doesn't accumulate on long-lived streams.
- streamLogs: pass { abortSignal: signal } to client.send() so an
  in-flight FilterLogEvents call is cancelled promptly on disconnect.
- LogsPanel: await the snapshot before starting the SSE stream to
  prevent a race where setLines(snapshot) overwrites already-streamed
  lines. Start the stream even if the snapshot fetch fails.

https://claude.ai/code/session_01THkoGDYjJhojhtnUEYi4w9
Copilot AI review requested due to automatic review settings May 1, 2026 01:35
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 7 out of 7 changed files in this pull request and generated 2 comments.

Comment thread app/packages/server/src/guards/api-token.guard.ts
Comment thread app/packages/server/src/services/LogsService.ts
RequestLoggerMiddleware logs req.query on every response; deleting the
token from req.query in ApiTokenGuard (which runs before the finish
handler) prevents it appearing in structured logs.

https://claude.ai/code/session_01THkoGDYjJhojhtnUEYi4w9
@CoderCoco CoderCoco merged commit 8fb9ab6 into main May 1, 2026
7 checks passed
@CoderCoco CoderCoco deleted the claude/issue-43-lgcMo branch May 1, 2026 01:47
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.

feat(app): stream live server logs to the management UI

3 participants