# 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`): ```typescript 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: ```typescript 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 on `this.chatSessionId`, looks up the `CodeSession` via `SocketService.getCodeSessionByChatSessionId()`, forwards the call. ### CodeSession (`gadget-code/src/lib/code-session.ts`) - `onLog()` calls `this.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: ```typescript 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 |