Implement qrun logs with streaming #44

Open
opened 2026-01-03 23:45:51 +00:00 by KofTwentyTwo · 0 comments
KofTwentyTwo commented 2026-01-03 23:45:51 +00:00 (Migrated from github.com)

User Story

As a developer, I want to view logs from my deployed application so I can debug issues and monitor behavior in real-time.

Design

Command Interface

# Tail last 100 lines
qrun logs --app orders-service --env prod

# Follow logs in real-time
qrun logs --app orders-service --env prod --follow

# Filter by time range
qrun logs --app orders-service --env prod --since 1h

# Filter by instance
qrun logs --app orders-service --env prod --instance orders-service-abc12

# Filter by log level
qrun logs --app orders-service --env prod --level error

# Limit lines
qrun logs --app orders-service --env prod --lines 500

Output Format

2024-01-15T10:30:15.123Z [orders-service-abc12] INFO  Processing order #12345
2024-01-15T10:30:15.456Z [orders-service-abc12] DEBUG Order validated successfully
2024-01-15T10:30:15.789Z [orders-service-abc12] INFO  Order #12345 completed

Voyage API Integration

# Initial fetch
GET /v1/apps/{app}/logs?env={env}&since=1h&lines=100

# Streaming (SSE)
GET /v1/apps/{app}/logs/stream?env={env}
Accept: text/event-stream

Response (SSE):
data: {"timestamp":"2024-01-15T10:30:15.123Z","instance":"abc12","level":"INFO","message":"..."}

Files to Create/Modify

File Action Purpose
qctl-qrun/src/main/java/io/qrun/qctl/qrun/LogsCommand.java Create Main logs command
qctl-qrun/src/main/java/io/qrun/qctl/qrun/model/LogEntry.java Create Log entry model
qctl-qrun/src/main/java/io/qrun/qctl/qrun/client/VoyageClient.java Modify Add getLogs(), streamLogs()
qctl-qrun/src/main/java/io/qrun/qctl/qrun/stream/LogStreamer.java Create SSE stream handler
qctl-qrun/src/main/java/io/qrun/qctl/qrun/format/LogFormatter.java Create Log output formatting

Implementation Tasks

  • Create LogsCommand with Picocli annotations
  • Add --app, --env, --follow, --since, --instance, --level, --lines options
  • Create LogEntry model class
  • Implement VoyageClient.getLogs() for batch fetch
  • Implement VoyageClient.streamLogs() with SSE support
  • Create LogStreamer for handling SSE events
  • Create LogFormatter with color-coded log levels
  • Parse --since duration (1h, 30m, 1d formats)
  • Handle stream reconnection on disconnect
  • Add Ctrl+C handler for clean stream termination
  • Write unit tests for LogsCommand
  • Write unit tests for LogStreamer

Acceptance Criteria

  • qrun logs --app <app> --env <env> shows recent logs
  • --follow streams logs in real-time until Ctrl+C
  • --since filters logs by time range
  • --instance filters to specific instance
  • --level filters by log level (error, warn, info, debug)
  • Log levels are color-coded in terminal
  • Stream reconnects automatically on disconnect
  • Works with Voyage mock API
## User Story As a developer, I want to view logs from my deployed application so I can debug issues and monitor behavior in real-time. ## Design ### Command Interface ```bash # Tail last 100 lines qrun logs --app orders-service --env prod # Follow logs in real-time qrun logs --app orders-service --env prod --follow # Filter by time range qrun logs --app orders-service --env prod --since 1h # Filter by instance qrun logs --app orders-service --env prod --instance orders-service-abc12 # Filter by log level qrun logs --app orders-service --env prod --level error # Limit lines qrun logs --app orders-service --env prod --lines 500 ``` ### Output Format ``` 2024-01-15T10:30:15.123Z [orders-service-abc12] INFO Processing order #12345 2024-01-15T10:30:15.456Z [orders-service-abc12] DEBUG Order validated successfully 2024-01-15T10:30:15.789Z [orders-service-abc12] INFO Order #12345 completed ``` ### Voyage API Integration ``` # Initial fetch GET /v1/apps/{app}/logs?env={env}&since=1h&lines=100 # Streaming (SSE) GET /v1/apps/{app}/logs/stream?env={env} Accept: text/event-stream Response (SSE): data: {"timestamp":"2024-01-15T10:30:15.123Z","instance":"abc12","level":"INFO","message":"..."} ``` ## Files to Create/Modify | File | Action | Purpose | |------|--------|---------| | `qctl-qrun/src/main/java/io/qrun/qctl/qrun/LogsCommand.java` | Create | Main logs command | | `qctl-qrun/src/main/java/io/qrun/qctl/qrun/model/LogEntry.java` | Create | Log entry model | | `qctl-qrun/src/main/java/io/qrun/qctl/qrun/client/VoyageClient.java` | Modify | Add getLogs(), streamLogs() | | `qctl-qrun/src/main/java/io/qrun/qctl/qrun/stream/LogStreamer.java` | Create | SSE stream handler | | `qctl-qrun/src/main/java/io/qrun/qctl/qrun/format/LogFormatter.java` | Create | Log output formatting | ## Implementation Tasks - [ ] Create LogsCommand with Picocli annotations - [ ] Add --app, --env, --follow, --since, --instance, --level, --lines options - [ ] Create LogEntry model class - [ ] Implement VoyageClient.getLogs() for batch fetch - [ ] Implement VoyageClient.streamLogs() with SSE support - [ ] Create LogStreamer for handling SSE events - [ ] Create LogFormatter with color-coded log levels - [ ] Parse --since duration (1h, 30m, 1d formats) - [ ] Handle stream reconnection on disconnect - [ ] Add Ctrl+C handler for clean stream termination - [ ] Write unit tests for LogsCommand - [ ] Write unit tests for LogStreamer ## Acceptance Criteria - [ ] `qrun logs --app <app> --env <env>` shows recent logs - [ ] `--follow` streams logs in real-time until Ctrl+C - [ ] `--since` filters logs by time range - [ ] `--instance` filters to specific instance - [ ] `--level` filters by log level (error, warn, info, debug) - [ ] Log levels are color-coded in terminal - [ ] Stream reconnects automatically on disconnect - [ ] Works with Voyage mock API
Sign in to join this conversation.