5.1 KiB
5.1 KiB
Design Document: Shell & Logs Feature Specification
Overview
Shell and Logs are real-time terminal and streaming views for Kubernetes resources. These features enable users to interact with running pods and monitor application behavior.
Shell Terminal (kubectl exec)
Requirements
- Implementation: xterm.js on client
- Backend: WebSocket → kubectl exec
- Protocol: Bidirectional terminal protocol
Terminal Configuration
{
rows: 24,
cols: 80,
fontFamily: 'IBM Plex Mono',
fontSize: 12,
lineHeight: 1.5,
cursorBlink: true,
theme: {
background: '#1a1e26',
foreground: '#b9c6d8',
}
}
Connection Flow
- User opens shell view
- Extract pod name and namespace
- Connect WebSocket to
/ws/shell?pod=X&ns=Y - Backend:
- Extract query params
- Connect to k8s exec API
- Create execstream
- Proxy bidirectionally
- Frontend:
- Initialize xterm
- Attach to WebSocket
- Handle resize events
- Route keypresses
Key Routing
- Shell focused + type: Route to terminal
- Canvas shortcuts disabled when shell has focus
- Space key: Goes to terminal (not spotlight)
- Ctrl/⌘+scroll: Zoom canvas (not terminal zoom)
Resize Handling
- Client: term.resize(cols, rows)
- Server: Send resize message via WebSocket
- Backend: Update k8s exec term size
- Debounce: 100ms for resize events
State Management
interface ShellState {
connected: boolean;
connectedAt: number;
lastActive: number;
buffer: string[];
cols: number;
rows: number;
}
Error States
- Connection failed: Show error message
- Disconnected: Show "Disconnected" + reconnect button
- Permission denied: Show clear error
- Pod not found: Show error message
Logs Viewer (kubectl logs)
Requirements
- Implementation: WebSocket streaming
- Auto-scroll: To bottom by default
- Color coding: ERROR/WARN/INFO
Connection Flow
- User opens logs view
- Connect to
/ws/logs?pod=X&ns=Y - Backend:
- Start kubectl logs stream
- Forward to WebSocket
- Frontend:
- Append lines to buffer
- Auto-scroll if at bottom
- Colorize based on level
Log Parsing
Each log line should include:
- Timestamp
- Log level (ERROR/WARN/INFO/DEBUG)
- Message
Format:
interface LogLine {
timestamp: string; // ISO 8601
level: 'ERROR' | 'WARN' | 'INFO' | 'DEBUG';
message: string;
}
Color Coding
- ERROR:
#ef6f6f - WARN:
#e8b54a - INFO:
#b9c6d8 - DEBUG:
#6b7280
Auto-Scroll Logic
- Track scroll position: Store
scrollTop - At bottom: Auto-scroll on new log
- Scrolled up: Don't auto-scroll
- Threshold: Within 20px of bottom = "at bottom"
User Controls
- Click auto-scroll toggle: Switch between auto and manual scroll
- Clear logs: Button to clear buffer
- Copy log line: Right-click menu
- Filter: Simple filtering (show/hide levels)
State Management
interface LogsState {
connected: boolean;
autoScroll: boolean;
logLines: LogLine[];
scrollPosition: number;
filterLevels: Set<LogLevel>;
}
Streaming Considerations
- Backpressure: Buffer if client slow
- Rate limiting: Server can throttle logs
- Keep-alive: Ping every 30s
- Reconnect: Exponential backoff on disconnect
Performance Optimization
- Virtualization: Only render visible lines
- Batching: Flush logs in batches if high volume
- Throttling: 16ms throttle for updates
- Cleanup: Remove old logs (keep last 1000 lines)
Shared Features
View State
- Both views persist state in krate.window.state
- reconnect: Auto reconnect on disconnect
- timestamps: Show/hide timestamps
- wrap: Word wrap toggle
Tab Switching
- Shell tab: Enabled for pods only
- Logs tab: Enabled for pods/workloads
- Empty state: Show helpful message for unsupported resources
Close Behavior
- Shell: Keep buffer, show "Disconnnected"
- Logs: Stop streaming, keep buffer
- Cleanup: Close WebSocket, cancel watchers
WebSocket Protocol
Shell
// Client → Server
{
type: 'shell:input',
data: string // Key press data
}
{
type: 'shell:resize',
cols: number,
rows: number
}
// Server → Client
{
type: 'shell:output',
data: string // stdout/stderr
}
{
type: 'shell:status',
connected: boolean,
message?: string
}
Logs
// Client → Server
{
type: 'logs:subscribe',
pod: string,
namespace: string,
follow: boolean,
timestamps: boolean
}
{
type: 'logs:filter',
levels: string[]
}
// Server → Client
{
type: 'log',
log: LogLine
}
{
type: 'status',
connected: boolean,
message?: string
}
Gotchas
- Space key: Must distinguish between canvas pan and shell input
- Focus routing: Route keys based on hovered window
- Scroll management: Track scroll position for logs
- Terminal resize: Debounce resize events
- Reconnection: Handle WebSocket disconnects gracefully
- Memory: Clean up old logs/shell buffers
- Authentication: Validate user on WebSocket upgrade
- Permissions: Enforce namespace RBAC on backend