4.7 KiB
Gadget Code: GadgetLogTransportSocket
GadgetLog now ships four transports out of the box: Console, File, Socket, and the abstract base. The socket transport (GadgetLogTransportSocket) transmits every log entry from gadget-drone → gadget-code:backend → gadget-code:frontend over Socket.IO, rendering live in the IDE's LogPanel.
Message Flow
gadget-drone
│ GadgetLogTransportSocket.writeLog()
│ socket.emit("log", timestamp, component, level, message, metadata?)
▼
gadget-code:backend (DroneSession.onLog)
│ SocketService.getCodeSessionByChatSessionId(chatSessionId)
│ codeSession.onLog(...)
▼
gadget-code:backend (CodeSession.onLog)
│ socket.emit("log", timestamp, component, level, message, metadata?)
▼
gadget-code:frontend (SocketClient)
│ raw socket "log" → internal "log:entry" event
│ { level, component, message, metadata, timestamp }
▼
ChatSessionView.handleLogEntry
│ setLogs(...)
▼
LogPanel — terminal-styled live log viewer
Transport: GadgetLogTransportSocket
File: packages/api/src/lib/log-transport-socket.ts
Accepts a generic emit function (no Socket.IO dependency in @gadget/api):
export type LogEmitFunction = (
event: string,
timestamp: Date,
component: GadgetComponent,
level: GadgetLogLevel,
message: string,
metadata?: unknown,
) => void;
writeLog() calls this.emit("log", ...) with the same parameters GadgetLog.writeLog() receives.
Registration in gadget-drone
Registered in gadget-drone.ts connectSocket(), after the Socket.IO connection succeeds:
const socketTransport = new GadgetLogTransportSocket((event, ...args) => {
(this.socket as any)?.emit(event, ...args);
});
GadgetLog.addDefaultTransport(socketTransport);
this.log.transports.push(socketTransport);
AgentService.log.transports.push(socketTransport);
AiService.log.transports.push(socketTransport);
PlatformService.log.transports.push(socketTransport);
The transport is injected into all existing loggers (main process + 3 services) and set as a default for future GadgetLog instances.
Backend Routing
DroneSession (gadget-code/src/lib/drone-session.ts)
- Registers
this.socket.on("log", this.onLog.bind(this)) onLog()guards onthis.chatSessionId, looks up theCodeSessionviaSocketService.getCodeSessionByChatSessionId(), forwards the call.
CodeSession (gadget-code/src/lib/code-session.ts)
onLog()callsthis.socket.emit("log", timestamp, component, level, message, metadata)forwards to the IDE.
Frontend Bridging
SocketClient (gadget-code/frontend/src/lib/socket.ts)
The raw Socket.IO log event is forwarded to the internal log:entry event system:
this.socket.on("log", (timestamp, component, level, message, metadata) => {
this.emit("log:entry", {
level,
component: component.name,
message,
metadata,
timestamp: new Date(timestamp).getTime(),
});
});
ChatSessionView
handleLogEntry callback builds a LogEntry with all fields and appends to the logs state array.
LogPanel Display
File: gadget-code/frontend/src/components/LogPanel.tsx
Styled to match the Console Transport:
| Element | Console Color | Tailwind Class |
|---|---|---|
| Timestamp | darkGray |
text-gray-600 |
| Level: debug | darkGray |
text-gray-500 |
| Level: info | green |
text-green-400 |
| Level: warn | yellow |
text-yellow-400 |
| Level: alert | red |
text-red-400 |
| Level: error | bgRed + white |
bg-red-800 text-white |
| Level: crit | bgRed + yellow |
bg-red-800 text-yellow-300 |
| Level: fatal | bgRed + darkGray |
bg-red-800 text-gray-400 |
| Component | cyan |
text-cyan-400 |
| Message | darkGray |
text-text-secondary |
Metadata is displayed as expandable JSON below the log line (toggled with ⊞/⊟).
Files Changed
| File | Action |
|---|---|
packages/api/src/lib/log-transport-socket.ts |
NEW — socket transport |
packages/api/src/index.ts |
MODIFY — export new transport |
gadget-drone/src/gadget-drone.ts |
MODIFY — register transport on connect |
gadget-drone/src/lib/service.ts |
MODIFY — log public for transport injection |
gadget-code/src/lib/drone-session.ts |
MODIFY — onLog handler |
gadget-code/src/lib/code-session.ts |
MODIFY — onLog forwarding |
gadget-code/frontend/src/lib/socket.ts |
MODIFY — bridge log → log:entry |
gadget-code/frontend/src/pages/ChatSessionView.tsx |
MODIFY — enriched LogEntry |
gadget-code/frontend/src/components/LogPanel.tsx |
REWRITE — console-styled display |