@graphty/remote-logger 0.0.1 → 1.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +944 -28
- package/bin/remote-log-server.js +3 -0
- package/dist/client/RemoteLogClient.d.ts +116 -0
- package/dist/client/RemoteLogClient.d.ts.map +1 -0
- package/dist/client/RemoteLogClient.js +269 -0
- package/dist/client/RemoteLogClient.js.map +1 -0
- package/dist/client/index.d.ts +7 -0
- package/dist/client/index.d.ts.map +1 -0
- package/dist/client/index.js +6 -0
- package/dist/client/index.js.map +1 -0
- package/dist/client/types.d.ts +60 -0
- package/dist/client/types.d.ts.map +1 -0
- package/dist/client/types.js +6 -0
- package/dist/client/types.js.map +1 -0
- package/dist/index.d.ts +22 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +23 -0
- package/dist/index.js.map +1 -0
- package/dist/mcp/index.d.ts +9 -0
- package/dist/mcp/index.d.ts.map +1 -0
- package/dist/mcp/index.js +9 -0
- package/dist/mcp/index.js.map +1 -0
- package/dist/mcp/mcp-server.d.ts +32 -0
- package/dist/mcp/mcp-server.d.ts.map +1 -0
- package/dist/mcp/mcp-server.js +270 -0
- package/dist/mcp/mcp-server.js.map +1 -0
- package/dist/mcp/tools/index.d.ts +14 -0
- package/dist/mcp/tools/index.d.ts.map +1 -0
- package/dist/mcp/tools/index.js +14 -0
- package/dist/mcp/tools/index.js.map +1 -0
- package/dist/mcp/tools/logs-clear.d.ts +76 -0
- package/dist/mcp/tools/logs-clear.d.ts.map +1 -0
- package/dist/mcp/tools/logs-clear.js +58 -0
- package/dist/mcp/tools/logs-clear.js.map +1 -0
- package/dist/mcp/tools/logs-get-all.d.ts +60 -0
- package/dist/mcp/tools/logs-get-all.d.ts.map +1 -0
- package/dist/mcp/tools/logs-get-all.js +50 -0
- package/dist/mcp/tools/logs-get-all.js.map +1 -0
- package/dist/mcp/tools/logs-get-errors.d.ts +65 -0
- package/dist/mcp/tools/logs-get-errors.d.ts.map +1 -0
- package/dist/mcp/tools/logs-get-errors.js +46 -0
- package/dist/mcp/tools/logs-get-errors.js.map +1 -0
- package/dist/mcp/tools/logs-get-file-path.d.ts +75 -0
- package/dist/mcp/tools/logs-get-file-path.d.ts.map +1 -0
- package/dist/mcp/tools/logs-get-file-path.js +90 -0
- package/dist/mcp/tools/logs-get-file-path.js.map +1 -0
- package/dist/mcp/tools/logs-get-recent.d.ts +89 -0
- package/dist/mcp/tools/logs-get-recent.d.ts.map +1 -0
- package/dist/mcp/tools/logs-get-recent.js +74 -0
- package/dist/mcp/tools/logs-get-recent.js.map +1 -0
- package/dist/mcp/tools/logs-list-sessions.d.ts +64 -0
- package/dist/mcp/tools/logs-list-sessions.d.ts.map +1 -0
- package/dist/mcp/tools/logs-list-sessions.js +48 -0
- package/dist/mcp/tools/logs-list-sessions.js.map +1 -0
- package/dist/mcp/tools/logs-receive.d.ts +150 -0
- package/dist/mcp/tools/logs-receive.d.ts.map +1 -0
- package/dist/mcp/tools/logs-receive.js +68 -0
- package/dist/mcp/tools/logs-receive.js.map +1 -0
- package/dist/mcp/tools/logs-search.d.ts +91 -0
- package/dist/mcp/tools/logs-search.d.ts.map +1 -0
- package/dist/mcp/tools/logs-search.js +68 -0
- package/dist/mcp/tools/logs-search.js.map +1 -0
- package/dist/mcp/tools/logs-status.d.ts +45 -0
- package/dist/mcp/tools/logs-status.d.ts.map +1 -0
- package/dist/mcp/tools/logs-status.js +45 -0
- package/dist/mcp/tools/logs-status.js.map +1 -0
- package/dist/server/dual-server.d.ts +76 -0
- package/dist/server/dual-server.d.ts.map +1 -0
- package/dist/server/dual-server.js +214 -0
- package/dist/server/dual-server.js.map +1 -0
- package/dist/server/index.d.ts +12 -0
- package/dist/server/index.d.ts.map +1 -0
- package/dist/server/index.js +12 -0
- package/dist/server/index.js.map +1 -0
- package/dist/server/jsonl-writer.d.ts +93 -0
- package/dist/server/jsonl-writer.d.ts.map +1 -0
- package/dist/server/jsonl-writer.js +205 -0
- package/dist/server/jsonl-writer.js.map +1 -0
- package/dist/server/log-server.d.ts +126 -0
- package/dist/server/log-server.d.ts.map +1 -0
- package/dist/server/log-server.js +589 -0
- package/dist/server/log-server.js.map +1 -0
- package/dist/server/log-storage.d.ts +301 -0
- package/dist/server/log-storage.d.ts.map +1 -0
- package/dist/server/log-storage.js +408 -0
- package/dist/server/log-storage.js.map +1 -0
- package/dist/server/marker-utils.d.ts +69 -0
- package/dist/server/marker-utils.d.ts.map +1 -0
- package/dist/server/marker-utils.js +118 -0
- package/dist/server/marker-utils.js.map +1 -0
- package/dist/server/self-signed-cert.d.ts +30 -0
- package/dist/server/self-signed-cert.d.ts.map +1 -0
- package/dist/server/self-signed-cert.js +83 -0
- package/dist/server/self-signed-cert.js.map +1 -0
- package/dist/ui/ConsoleCaptureUI.d.ts +118 -0
- package/dist/ui/ConsoleCaptureUI.d.ts.map +1 -0
- package/dist/ui/ConsoleCaptureUI.js +571 -0
- package/dist/ui/ConsoleCaptureUI.js.map +1 -0
- package/dist/ui/index.d.ts +15 -0
- package/dist/ui/index.d.ts.map +1 -0
- package/dist/ui/index.js +15 -0
- package/dist/ui/index.js.map +1 -0
- package/dist/vite/index.d.ts +8 -0
- package/dist/vite/index.d.ts.map +1 -0
- package/dist/vite/index.js +8 -0
- package/dist/vite/index.js.map +1 -0
- package/dist/vite/plugin.d.ts +42 -0
- package/dist/vite/plugin.d.ts.map +1 -0
- package/dist/vite/plugin.js +46 -0
- package/dist/vite/plugin.js.map +1 -0
- package/package.json +90 -7
- package/src/client/RemoteLogClient.ts +328 -0
- package/src/client/index.ts +7 -0
- package/src/client/types.ts +62 -0
- package/src/index.ts +28 -0
- package/src/mcp/index.ts +25 -0
- package/src/mcp/mcp-server.ts +364 -0
- package/src/mcp/tools/index.ts +69 -0
- package/src/mcp/tools/logs-clear.ts +86 -0
- package/src/mcp/tools/logs-get-all.ts +78 -0
- package/src/mcp/tools/logs-get-errors.ts +71 -0
- package/src/mcp/tools/logs-get-file-path.ts +121 -0
- package/src/mcp/tools/logs-get-recent.ts +104 -0
- package/src/mcp/tools/logs-list-sessions.ts +71 -0
- package/src/mcp/tools/logs-receive.ts +96 -0
- package/src/mcp/tools/logs-search.ts +95 -0
- package/src/mcp/tools/logs-status.ts +69 -0
- package/src/server/dual-server.ts +308 -0
- package/src/server/index.ts +54 -0
- package/src/server/jsonl-writer.ts +277 -0
- package/src/server/log-server.ts +763 -0
- package/src/server/log-storage.ts +651 -0
- package/src/server/marker-utils.ts +144 -0
- package/src/server/self-signed-cert.ts +93 -0
- package/src/ui/ConsoleCaptureUI.ts +649 -0
- package/src/ui/index.ts +15 -0
- package/src/vite/index.ts +8 -0
- package/src/vite/plugin.ts +59 -0
package/README.md
CHANGED
|
@@ -1,45 +1,961 @@
|
|
|
1
1
|
# @graphty/remote-logger
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
Remote logging client and server for browser debugging. Send console logs from browsers to a terminal-based log server for easy debugging of web applications.
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
## Why Remote Logging?
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
Browser applications run in a sandbox - their `console.log()` output appears in browser DevTools but is not accessible to CLI tools, terminal sessions, or AI assistants. Remote logging bridges this gap by sending browser logs to a server where they can be viewed, searched, and analyzed.
|
|
8
8
|
|
|
9
|
-
|
|
9
|
+
**Use cases where remote logging shines:**
|
|
10
10
|
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
11
|
+
- **Storybook & Component Development** - See console output without switching to browser DevTools
|
|
12
|
+
- **Mobile Web Apps** - Phones and tablets require USB debugging to access DevTools
|
|
13
|
+
- **VR/AR Applications** - You can't see a browser console while wearing a headset
|
|
14
|
+
- **Embedded Devices** - Kiosks, smart displays, and IoT devices without keyboard access
|
|
15
|
+
- **CI/CD & Automated Testing** - Capture browser logs during headless test runs
|
|
16
|
+
- **LLM-Assisted Debugging** - AI assistants can read, interpret, and act on logs without requiring user interaction with browser DevTools
|
|
15
17
|
|
|
16
|
-
##
|
|
18
|
+
## Features
|
|
17
19
|
|
|
18
|
-
|
|
20
|
+
- **Browser Client**: Lightweight client for sending logs from browser to server
|
|
21
|
+
- **Log Server**: HTTPS/HTTP server with colored terminal output and REST API
|
|
22
|
+
- **MCP Server**: Model Context Protocol server for Claude Code integration
|
|
23
|
+
- **Console Capture UI**: Floating widget to copy/download/view browser console logs
|
|
24
|
+
- **Batching & Retry**: Efficient log delivery with automatic retry on failure
|
|
25
|
+
- **Session Tracking**: Unique session IDs for correlating logs across page loads
|
|
26
|
+
- **Project Markers**: Filter logs by git worktree or project name
|
|
27
|
+
- **Throttling**: Configurable rate limiting for high-frequency log messages
|
|
28
|
+
- **File Logging**: JSONL file streaming organized by project marker
|
|
29
|
+
- **Log Retention**: Automatic cleanup of old logs (configurable, default 7 days)
|
|
19
30
|
|
|
20
|
-
##
|
|
31
|
+
## Installation
|
|
21
32
|
|
|
22
|
-
|
|
33
|
+
```bash
|
|
34
|
+
npm install @graphty/remote-logger
|
|
35
|
+
# or
|
|
36
|
+
pnpm add @graphty/remote-logger
|
|
37
|
+
```
|
|
23
38
|
|
|
24
|
-
|
|
25
|
-
2. Configure the trusted publisher (e.g., GitHub Actions)
|
|
26
|
-
3. Specify the repository and workflow that should be allowed to publish
|
|
27
|
-
4. Use the configured workflow to publish your actual package
|
|
39
|
+
## Quick Start
|
|
28
40
|
|
|
29
|
-
|
|
41
|
+
### 1. Start the Log Server
|
|
30
42
|
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
-
|
|
34
|
-
- Should not be installed as a dependency
|
|
35
|
-
- Exists only for administrative purposes
|
|
43
|
+
```bash
|
|
44
|
+
# Using npx
|
|
45
|
+
npx remote-log-server --port 9080
|
|
36
46
|
|
|
37
|
-
|
|
47
|
+
# Or via CLI after installation
|
|
48
|
+
remote-log-server --port 9080
|
|
49
|
+
```
|
|
38
50
|
|
|
39
|
-
|
|
40
|
-
- [npm Trusted Publishing Documentation](https://docs.npmjs.com/generating-provenance-statements)
|
|
41
|
-
- [GitHub Actions OIDC Documentation](https://docs.github.com/en/actions/deployment/security-hardening-your-deployments/about-security-hardening-with-openid-connect)
|
|
51
|
+
### 2. Add Client to Your Application
|
|
42
52
|
|
|
43
|
-
|
|
53
|
+
```typescript
|
|
54
|
+
import { RemoteLogClient } from "@graphty/remote-logger";
|
|
55
|
+
|
|
56
|
+
// Create client pointing to your log server
|
|
57
|
+
const logger = new RemoteLogClient({
|
|
58
|
+
serverUrl: "http://localhost:9080",
|
|
59
|
+
sessionPrefix: "myapp",
|
|
60
|
+
});
|
|
61
|
+
|
|
62
|
+
// Log messages (batched and sent automatically)
|
|
63
|
+
logger.log("INFO", "Application started");
|
|
64
|
+
logger.log("DEBUG", "Loading user data", { userId: 123 });
|
|
65
|
+
logger.log("ERROR", "Failed to fetch", { error: "Network error" });
|
|
66
|
+
|
|
67
|
+
// Flush immediately when needed (e.g., before page unload)
|
|
68
|
+
await logger.flush();
|
|
69
|
+
|
|
70
|
+
// Clean up when done
|
|
71
|
+
await logger.close();
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
### 3. View Logs in Terminal
|
|
75
|
+
|
|
76
|
+
Logs appear in the server terminal with colors and session info:
|
|
77
|
+
|
|
78
|
+
```
|
|
79
|
+
10:30:15 [myapp-abc123] INFO Application started
|
|
80
|
+
10:30:15 [myapp-abc123] DEBUG Loading user data
|
|
81
|
+
10:30:16 [myapp-abc123] ERROR Failed to fetch
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
Log levels are displayed with the following colors:
|
|
85
|
+
| Level | Color |
|
|
86
|
+
|-------|-------|
|
|
87
|
+
| ERROR | White text on red background |
|
|
88
|
+
| WARN/WARNING | Bold text on yellow background |
|
|
89
|
+
| INFO | Blue |
|
|
90
|
+
| DEBUG | Cyan |
|
|
91
|
+
| TRACE | Dim/gray |
|
|
92
|
+
| LOG (default) | Green |
|
|
93
|
+
|
|
94
|
+
## CLI Reference
|
|
95
|
+
|
|
96
|
+
```
|
|
97
|
+
Usage:
|
|
98
|
+
npx remote-log-server [options]
|
|
99
|
+
|
|
100
|
+
Options:
|
|
101
|
+
--port, -p <port> Port to listen on (default: 9080)
|
|
102
|
+
--host, -h <host> Hostname to bind to (default: localhost)
|
|
103
|
+
--cert, -c <path> Path to SSL certificate file (enables HTTPS)
|
|
104
|
+
--key, -k <path> Path to SSL private key file (enables HTTPS)
|
|
105
|
+
--log-file, -l <path> Write logs to file (JSONL format)
|
|
106
|
+
--quiet, -q Suppress startup banner
|
|
107
|
+
--mcp-only Start only MCP server (no HTTP)
|
|
108
|
+
--http-only Start only HTTP server (no MCP)
|
|
109
|
+
--help Show help message
|
|
110
|
+
|
|
111
|
+
Protocol:
|
|
112
|
+
HTTP is used by default. To use HTTPS, provide both --cert and --key.
|
|
113
|
+
|
|
114
|
+
Examples:
|
|
115
|
+
npx remote-log-server # Dual mode: HTTP + MCP (default)
|
|
116
|
+
npx remote-log-server --port 9080 # HTTP on port 9080 + MCP
|
|
117
|
+
npx remote-log-server --mcp-only # MCP only (for Claude Code)
|
|
118
|
+
npx remote-log-server --http-only # HTTP only (legacy mode)
|
|
119
|
+
npx remote-log-server --cert cert.pem --key key.pem # Use HTTPS with custom certs
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
### Environment Variables
|
|
123
|
+
|
|
124
|
+
| Variable | Default | Description |
|
|
125
|
+
|----------|---------|-------------|
|
|
126
|
+
| `REMOTE_LOG_RETENTION_DAYS` | `7` | Number of days to retain logs before cleanup |
|
|
127
|
+
|
|
128
|
+
## API Reference
|
|
129
|
+
|
|
130
|
+
### RemoteLogClient
|
|
131
|
+
|
|
132
|
+
The browser-side client for sending logs.
|
|
133
|
+
|
|
134
|
+
```typescript
|
|
135
|
+
import { RemoteLogClient, createRemoteLogClient } from "@graphty/remote-logger";
|
|
136
|
+
|
|
137
|
+
// Using constructor
|
|
138
|
+
const client = new RemoteLogClient(options);
|
|
139
|
+
|
|
140
|
+
// Using factory function
|
|
141
|
+
const client = createRemoteLogClient(options);
|
|
142
|
+
```
|
|
143
|
+
|
|
144
|
+
#### Options
|
|
145
|
+
|
|
146
|
+
| Option | Type | Default | Description |
|
|
147
|
+
|--------|------|---------|-------------|
|
|
148
|
+
| `serverUrl` | `string` | required | URL of the log server |
|
|
149
|
+
| `sessionPrefix` | `string` | `"session"` | Prefix for session ID |
|
|
150
|
+
| `batchIntervalMs` | `number` | `1000` | Interval between batch sends |
|
|
151
|
+
| `maxRetries` | `number` | `3` | Max retry attempts on failure |
|
|
152
|
+
| `retryDelayMs` | `number` | `1000` | Base delay between retries (uses exponential backoff) |
|
|
153
|
+
| `throttlePatterns` | `ThrottlePattern[]` | `[]` | Patterns to throttle (see below) |
|
|
154
|
+
| `projectMarker` | `string` | auto | Project identifier for filtering (auto-detected from Vite globals) |
|
|
155
|
+
| `worktreePath` | `string` | auto | Full worktree path for debugging (auto-detected from Vite globals) |
|
|
156
|
+
|
|
157
|
+
#### Throttling High-Frequency Logs
|
|
158
|
+
|
|
159
|
+
Use throttle patterns to prevent log flooding from high-frequency events:
|
|
160
|
+
|
|
161
|
+
```typescript
|
|
162
|
+
const logger = new RemoteLogClient({
|
|
163
|
+
serverUrl: "http://localhost:9080",
|
|
164
|
+
throttlePatterns: [
|
|
165
|
+
// Only send "Rendering frame" once per second
|
|
166
|
+
{ pattern: /Rendering frame/, intervalMs: 1000 },
|
|
167
|
+
// Only send mouse position updates every 500ms
|
|
168
|
+
{ pattern: /Mouse position:/, intervalMs: 500 },
|
|
169
|
+
],
|
|
170
|
+
});
|
|
171
|
+
```
|
|
172
|
+
|
|
173
|
+
#### Methods
|
|
174
|
+
|
|
175
|
+
| Method | Description |
|
|
176
|
+
|--------|-------------|
|
|
177
|
+
| `log(level, message, data?)` | Log a message with optional data object |
|
|
178
|
+
| `flush(): Promise<void>` | Immediately send pending logs to server |
|
|
179
|
+
| `close(): Promise<void>` | Flush remaining logs and stop accepting new ones |
|
|
180
|
+
|
|
181
|
+
#### Properties
|
|
182
|
+
|
|
183
|
+
| Property | Type | Description |
|
|
184
|
+
|----------|------|-------------|
|
|
185
|
+
| `sessionId` | `string` (readonly) | Unique session identifier in format `{prefix}-{timestamp}-{random}` |
|
|
186
|
+
|
|
187
|
+
### startLogServer
|
|
188
|
+
|
|
189
|
+
Start the log server programmatically.
|
|
190
|
+
|
|
191
|
+
```typescript
|
|
192
|
+
import { startLogServer } from "@graphty/remote-logger/server";
|
|
193
|
+
|
|
194
|
+
const server = startLogServer({
|
|
195
|
+
port: 9080,
|
|
196
|
+
host: "localhost",
|
|
197
|
+
useHttp: true,
|
|
198
|
+
quiet: false,
|
|
199
|
+
});
|
|
200
|
+
```
|
|
201
|
+
|
|
202
|
+
#### Options
|
|
203
|
+
|
|
204
|
+
| Option | Type | Default | Description |
|
|
205
|
+
|--------|------|---------|-------------|
|
|
206
|
+
| `port` | `number` | `9080` | Port to listen on |
|
|
207
|
+
| `host` | `string` | `"localhost"` | Hostname to bind to |
|
|
208
|
+
| `certPath` | `string` | - | Path to SSL certificate |
|
|
209
|
+
| `keyPath` | `string` | - | Path to SSL private key |
|
|
210
|
+
| `logFile` | `string` | - | Path for file logging |
|
|
211
|
+
| `useHttp` | `boolean` | `false` | Use HTTP instead of HTTPS |
|
|
212
|
+
| `quiet` | `boolean` | `false` | Suppress output |
|
|
213
|
+
|
|
214
|
+
### REST API Endpoints
|
|
215
|
+
|
|
216
|
+
| Endpoint | Method | Description |
|
|
217
|
+
|----------|--------|-------------|
|
|
218
|
+
| `/log` | POST | Receive logs from client |
|
|
219
|
+
| `/logs` | GET | Get all logs by session |
|
|
220
|
+
| `/logs/recent` | GET | Get recent logs (`?n=50&errors=true`) |
|
|
221
|
+
| `/logs/errors` | GET | Get error-level logs only |
|
|
222
|
+
| `/logs/clear` | POST | Clear all stored logs |
|
|
223
|
+
| `/health` | GET | Health check |
|
|
224
|
+
|
|
225
|
+
#### POST /log
|
|
226
|
+
|
|
227
|
+
Receive log entries from clients. This is the endpoint used by `RemoteLogClient`.
|
|
228
|
+
|
|
229
|
+
**Request body:**
|
|
230
|
+
```json
|
|
231
|
+
{
|
|
232
|
+
"sessionId": "myapp-abc123-xyz789",
|
|
233
|
+
"logs": [
|
|
234
|
+
{
|
|
235
|
+
"time": "2024-01-15T10:30:00.000Z",
|
|
236
|
+
"level": "INFO",
|
|
237
|
+
"message": "User logged in",
|
|
238
|
+
"data": { "userId": 123 }
|
|
239
|
+
}
|
|
240
|
+
]
|
|
241
|
+
}
|
|
242
|
+
```
|
|
243
|
+
|
|
244
|
+
**Response:**
|
|
245
|
+
```json
|
|
246
|
+
{ "success": true }
|
|
247
|
+
```
|
|
248
|
+
|
|
249
|
+
#### GET /logs
|
|
250
|
+
|
|
251
|
+
Returns all logs grouped by session.
|
|
252
|
+
|
|
253
|
+
**Response:**
|
|
254
|
+
```json
|
|
255
|
+
{
|
|
256
|
+
"myapp-abc123": [
|
|
257
|
+
{ "time": "2024-01-15T10:30:00Z", "level": "INFO", "message": "Hello" }
|
|
258
|
+
],
|
|
259
|
+
"myapp-def456": [
|
|
260
|
+
{ "time": "2024-01-15T10:31:00Z", "level": "DEBUG", "message": "Debug msg" }
|
|
261
|
+
]
|
|
262
|
+
}
|
|
263
|
+
```
|
|
264
|
+
|
|
265
|
+
#### GET /logs/recent
|
|
266
|
+
|
|
267
|
+
Returns recent logs across all sessions, sorted by time.
|
|
268
|
+
|
|
269
|
+
**Query parameters:**
|
|
270
|
+
- `n` (optional): Number of logs to return (default: 50)
|
|
271
|
+
- `errors` (optional): Set to `true` to return only error-level logs
|
|
272
|
+
|
|
273
|
+
**Response:**
|
|
274
|
+
```json
|
|
275
|
+
{
|
|
276
|
+
"total": 150,
|
|
277
|
+
"showing": 50,
|
|
278
|
+
"logs": [
|
|
279
|
+
{ "sessionId": "myapp-abc123", "time": "...", "level": "INFO", "message": "..." }
|
|
280
|
+
]
|
|
281
|
+
}
|
|
282
|
+
```
|
|
283
|
+
|
|
284
|
+
#### GET /logs/errors
|
|
285
|
+
|
|
286
|
+
Returns only error-level logs across all sessions.
|
|
287
|
+
|
|
288
|
+
**Response:**
|
|
289
|
+
```json
|
|
290
|
+
{
|
|
291
|
+
"total": 5,
|
|
292
|
+
"logs": [
|
|
293
|
+
{ "sessionId": "myapp-abc123", "time": "...", "level": "ERROR", "message": "..." }
|
|
294
|
+
]
|
|
295
|
+
}
|
|
296
|
+
```
|
|
297
|
+
|
|
298
|
+
#### POST /logs/clear
|
|
299
|
+
|
|
300
|
+
Clears all stored logs from memory.
|
|
301
|
+
|
|
302
|
+
**Response:**
|
|
303
|
+
```json
|
|
304
|
+
{ "success": true }
|
|
305
|
+
```
|
|
306
|
+
|
|
307
|
+
#### GET /health
|
|
308
|
+
|
|
309
|
+
Health check endpoint for monitoring.
|
|
310
|
+
|
|
311
|
+
**Response:**
|
|
312
|
+
```json
|
|
313
|
+
{ "status": "ok", "sessions": 3 }
|
|
314
|
+
```
|
|
315
|
+
|
|
316
|
+
## MCP Server (Claude Code Integration)
|
|
317
|
+
|
|
318
|
+
The remote-logger includes a Model Context Protocol (MCP) server that allows Claude Code to directly query and manage logs. This enables AI-assisted debugging by letting Claude Code see browser console output in real-time.
|
|
319
|
+
|
|
320
|
+
### Setup with Claude Code
|
|
321
|
+
|
|
322
|
+
Add the following to your Claude Code MCP configuration (`~/.config/claude-code/mcp.json` or project settings):
|
|
323
|
+
|
|
324
|
+
```json
|
|
325
|
+
{
|
|
326
|
+
"mcpServers": {
|
|
327
|
+
"remote-logger": {
|
|
328
|
+
"command": "npx",
|
|
329
|
+
"args": ["remote-log-server", "--mcp-only"]
|
|
330
|
+
}
|
|
331
|
+
}
|
|
332
|
+
}
|
|
333
|
+
```
|
|
334
|
+
|
|
335
|
+
Or if installed globally:
|
|
336
|
+
|
|
337
|
+
```json
|
|
338
|
+
{
|
|
339
|
+
"mcpServers": {
|
|
340
|
+
"remote-logger": {
|
|
341
|
+
"command": "remote-log-server",
|
|
342
|
+
"args": ["--mcp-only"]
|
|
343
|
+
}
|
|
344
|
+
}
|
|
345
|
+
}
|
|
346
|
+
```
|
|
347
|
+
|
|
348
|
+
### Dual Mode (HTTP + MCP)
|
|
349
|
+
|
|
350
|
+
By default, the server runs in dual mode with both HTTP and MCP interfaces sharing the same log storage. This allows browsers to send logs via HTTP while Claude Code queries them via MCP.
|
|
351
|
+
|
|
352
|
+
```bash
|
|
353
|
+
# Start dual server (HTTP + MCP)
|
|
354
|
+
npx remote-log-server --port 9080
|
|
355
|
+
```
|
|
356
|
+
|
|
357
|
+
### MCP Tools
|
|
358
|
+
|
|
359
|
+
The MCP server provides 9 tools for log management:
|
|
360
|
+
|
|
361
|
+
#### `logs_get_recent`
|
|
362
|
+
|
|
363
|
+
Get recent logs from the server, sorted by time (oldest first).
|
|
364
|
+
|
|
365
|
+
**Parameters:**
|
|
366
|
+
| Parameter | Type | Default | Description |
|
|
367
|
+
|-----------|------|---------|-------------|
|
|
368
|
+
| `count` | `number` | `50` | Number of logs to return (max 500) |
|
|
369
|
+
| `projectMarker` | `string` | - | Filter by project marker |
|
|
370
|
+
| `workingDirectory` | `string` | - | Derive marker from path (e.g., `/path/.worktrees/my-branch`) |
|
|
371
|
+
| `level` | `string` | - | Filter by log level (ERROR, WARN, INFO, DEBUG) |
|
|
372
|
+
| `since` | `string` | - | Only logs after this ISO timestamp |
|
|
373
|
+
|
|
374
|
+
**Example usage in Claude Code:**
|
|
375
|
+
> "Show me the last 20 logs from the graphty-element project"
|
|
376
|
+
|
|
377
|
+
#### `logs_status`
|
|
378
|
+
|
|
379
|
+
Get the status of the remote log server.
|
|
380
|
+
|
|
381
|
+
**Returns:**
|
|
382
|
+
- Server status, uptime, session count, log count, error count, memory usage
|
|
383
|
+
- HTTP endpoint configuration (port, host, protocol, full URL for browser clients)
|
|
384
|
+
- Retention settings (how long logs are kept before automatic cleanup)
|
|
385
|
+
|
|
386
|
+
**Example usage:**
|
|
387
|
+
> "What is the status of the remote logger?"
|
|
388
|
+
> "What URL should I use to configure the browser client?"
|
|
389
|
+
> "How long are logs retained?"
|
|
390
|
+
|
|
391
|
+
#### `logs_list_sessions`
|
|
392
|
+
|
|
393
|
+
List all logging sessions with their metadata.
|
|
394
|
+
|
|
395
|
+
**Parameters:**
|
|
396
|
+
| Parameter | Type | Description |
|
|
397
|
+
|-----------|------|-------------|
|
|
398
|
+
| `projectMarker` | `string` | Filter by project marker |
|
|
399
|
+
| `hasErrors` | `boolean` | Only show sessions with errors |
|
|
400
|
+
|
|
401
|
+
**Returns:** Array of sessions with:
|
|
402
|
+
- `sessionId`, `projectMarker`, `worktreePath`, `pageUrl`
|
|
403
|
+
- `firstLogTime`, `lastLogTime`, `logCount`, `errorCount`
|
|
404
|
+
|
|
405
|
+
**Example usage:**
|
|
406
|
+
> "List all logging sessions that have errors"
|
|
407
|
+
|
|
408
|
+
#### `logs_receive`
|
|
409
|
+
|
|
410
|
+
Store logs from a browser or application session.
|
|
411
|
+
|
|
412
|
+
**Parameters:**
|
|
413
|
+
| Parameter | Type | Required | Description |
|
|
414
|
+
|-----------|------|----------|-------------|
|
|
415
|
+
| `sessionId` | `string` | Yes | Unique session identifier |
|
|
416
|
+
| `logs` | `array` | Yes | Array of log entries |
|
|
417
|
+
| `projectMarker` | `string` | No | Project identifier |
|
|
418
|
+
| `worktreePath` | `string` | No | Full worktree path |
|
|
419
|
+
| `pageUrl` | `string` | No | Browser page URL |
|
|
420
|
+
|
|
421
|
+
#### `logs_get_all`
|
|
422
|
+
|
|
423
|
+
Get all logs grouped by session.
|
|
424
|
+
|
|
425
|
+
**Parameters:**
|
|
426
|
+
| Parameter | Type | Description |
|
|
427
|
+
|-----------|------|-------------|
|
|
428
|
+
| `projectMarker` | `string` | Filter by project marker |
|
|
429
|
+
|
|
430
|
+
**Returns:** Object mapping session IDs to log arrays
|
|
431
|
+
|
|
432
|
+
#### `logs_get_errors`
|
|
433
|
+
|
|
434
|
+
Get only ERROR level logs.
|
|
435
|
+
|
|
436
|
+
**Parameters:**
|
|
437
|
+
| Parameter | Type | Description |
|
|
438
|
+
|-----------|------|-------------|
|
|
439
|
+
| `projectMarker` | `string` | Filter by project marker |
|
|
440
|
+
| `since` | `string` | Only errors after this timestamp |
|
|
441
|
+
|
|
442
|
+
**Example usage:**
|
|
443
|
+
> "Show me all errors from the current project"
|
|
444
|
+
|
|
445
|
+
#### `logs_clear`
|
|
446
|
+
|
|
447
|
+
Clear logs from the server.
|
|
448
|
+
|
|
449
|
+
**Parameters:**
|
|
450
|
+
| Parameter | Type | Required | Description |
|
|
451
|
+
|-----------|------|----------|-------------|
|
|
452
|
+
| `confirm` | `boolean` | Yes | Must be `true` to proceed |
|
|
453
|
+
| `projectMarker` | `string` | No | Only clear this project's logs |
|
|
454
|
+
| `sessionId` | `string` | No | Only clear this session's logs |
|
|
455
|
+
|
|
456
|
+
**Example usage:**
|
|
457
|
+
> "Clear all logs for the remote-logging project, confirm"
|
|
458
|
+
|
|
459
|
+
#### `logs_search`
|
|
460
|
+
|
|
461
|
+
Search logs by text pattern.
|
|
462
|
+
|
|
463
|
+
**Parameters:**
|
|
464
|
+
| Parameter | Type | Default | Description |
|
|
465
|
+
|-----------|------|---------|-------------|
|
|
466
|
+
| `query` | `string` | required | Search text or regex pattern |
|
|
467
|
+
| `regex` | `boolean` | `false` | Treat query as regex |
|
|
468
|
+
| `projectMarker` | `string` | - | Filter by project |
|
|
469
|
+
| `level` | `string` | - | Filter by log level |
|
|
470
|
+
| `limit` | `number` | `100` | Max results (max 1000) |
|
|
471
|
+
|
|
472
|
+
**Example usage:**
|
|
473
|
+
> "Search the logs for 'connection failed'"
|
|
474
|
+
> "Search logs for any network errors using regex 'network|timeout|connection'"
|
|
475
|
+
|
|
476
|
+
#### `logs_get_file_path`
|
|
477
|
+
|
|
478
|
+
Get the file path to the JSONL log file for a project.
|
|
479
|
+
|
|
480
|
+
**Parameters:**
|
|
481
|
+
| Parameter | Type | Description |
|
|
482
|
+
|-----------|------|-------------|
|
|
483
|
+
| `projectMarker` | `string` | Project marker |
|
|
484
|
+
| `workingDirectory` | `string` | Derive marker from path |
|
|
485
|
+
|
|
486
|
+
**Returns:** File path, existence status, and size
|
|
487
|
+
|
|
488
|
+
**Example usage:**
|
|
489
|
+
> "Get the log file path for this project so I can grep it"
|
|
490
|
+
|
|
491
|
+
This tool is useful for accessing logs via file-based tools like `Grep` or `Read` when you need more advanced searching capabilities.
|
|
492
|
+
|
|
493
|
+
### Project Markers
|
|
494
|
+
|
|
495
|
+
Project markers allow you to filter logs by project, which is especially useful in monorepos or when working with multiple projects simultaneously.
|
|
496
|
+
|
|
497
|
+
Markers are determined in the following priority:
|
|
498
|
+
1. Explicit `projectMarker` parameter
|
|
499
|
+
2. Derived from `workingDirectory` path (extracts from `.worktrees/` or uses basename)
|
|
500
|
+
3. Extracted from `sessionId` prefix (e.g., `graphty-element-123-abc` → `graphty-element`)
|
|
501
|
+
4. Default: `"default"`
|
|
502
|
+
|
|
503
|
+
### JSONL File Organization
|
|
504
|
+
|
|
505
|
+
Logs are streamed to JSONL files organized by project marker:
|
|
506
|
+
|
|
507
|
+
```
|
|
508
|
+
{tmpdir}/remote-logger/
|
|
509
|
+
├── graphty-element/
|
|
510
|
+
│ └── logs.jsonl
|
|
511
|
+
├── remote-logging/
|
|
512
|
+
│ └── logs.jsonl
|
|
513
|
+
└── default/
|
|
514
|
+
└── logs.jsonl
|
|
515
|
+
```
|
|
516
|
+
|
|
517
|
+
## ConsoleCaptureUI
|
|
518
|
+
|
|
519
|
+
A floating UI widget that captures all console output (`log`, `error`, `warn`, `info`, `debug`) and provides a menu to copy, download, view, or clear the captured logs.
|
|
520
|
+
|
|
521
|
+
```typescript
|
|
522
|
+
import { initConsoleCaptureUI, ConsoleCaptureUI } from "@graphty/remote-logger/ui";
|
|
523
|
+
|
|
524
|
+
// Initialize the UI (adds floating button to page)
|
|
525
|
+
const ui = initConsoleCaptureUI();
|
|
526
|
+
|
|
527
|
+
// Or use the class directly
|
|
528
|
+
const ui = new ConsoleCaptureUI();
|
|
529
|
+
|
|
530
|
+
// All console methods are now captured
|
|
531
|
+
console.log("This is captured");
|
|
532
|
+
console.error("This too");
|
|
533
|
+
|
|
534
|
+
// Access captured logs programmatically
|
|
535
|
+
const logsText = ui.getLogs();
|
|
536
|
+
|
|
537
|
+
// Later, clean up (restores original console methods)
|
|
538
|
+
ui.destroy();
|
|
539
|
+
```
|
|
540
|
+
|
|
541
|
+
#### Widget Features
|
|
542
|
+
|
|
543
|
+
The floating button (📋) appears in the top-right corner of the page. Clicking it reveals a menu with:
|
|
544
|
+
|
|
545
|
+
| Button | Action |
|
|
546
|
+
|--------|--------|
|
|
547
|
+
| 📋 Copy Logs | Copy all captured logs to clipboard |
|
|
548
|
+
| 💾 Download | Download logs as a timestamped text file |
|
|
549
|
+
| 🗑️ Clear | Clear all captured logs |
|
|
550
|
+
| 👁️ Show Logs | Open a modal to view and select logs |
|
|
551
|
+
|
|
552
|
+
#### Instance Methods
|
|
553
|
+
|
|
554
|
+
| Method | Description |
|
|
555
|
+
|--------|-------------|
|
|
556
|
+
| `getLogs(): string` | Get all captured logs as formatted text |
|
|
557
|
+
| `clearLogs(): void` | Clear captured logs |
|
|
558
|
+
| `copyLogs(): Promise<void>` | Copy logs to clipboard |
|
|
559
|
+
| `downloadLogs(): void` | Download logs as text file |
|
|
560
|
+
| `destroy(): void` | Restore console methods and remove UI |
|
|
561
|
+
|
|
562
|
+
#### Global Methods
|
|
563
|
+
|
|
564
|
+
When initialized, `window.__console__` is exposed for programmatic access:
|
|
565
|
+
|
|
566
|
+
```typescript
|
|
567
|
+
// Available globally after initConsoleCaptureUI()
|
|
568
|
+
window.__console__.copy(); // Copy to clipboard
|
|
569
|
+
window.__console__.download(); // Download as file
|
|
570
|
+
window.__console__.clear(); // Clear logs
|
|
571
|
+
window.__console__.get(); // Get logs as string
|
|
572
|
+
window.__console__.logs; // Raw log array
|
|
573
|
+
```
|
|
574
|
+
|
|
575
|
+
#### Log Format
|
|
576
|
+
|
|
577
|
+
Captured logs are formatted as:
|
|
578
|
+
```
|
|
579
|
+
[2024-01-15T10:30:00.000Z] [INFO] User logged in
|
|
580
|
+
[2024-01-15T10:30:01.000Z] [ERROR] Failed to connect
|
|
581
|
+
```
|
|
582
|
+
|
|
583
|
+
## Integration Examples
|
|
584
|
+
|
|
585
|
+
### Basic Browser Integration
|
|
586
|
+
|
|
587
|
+
```typescript
|
|
588
|
+
import { RemoteLogClient } from "@graphty/remote-logger";
|
|
589
|
+
|
|
590
|
+
// Create a logger instance
|
|
591
|
+
const logger = new RemoteLogClient({
|
|
592
|
+
serverUrl: "http://localhost:9080",
|
|
593
|
+
sessionPrefix: "myapp",
|
|
594
|
+
});
|
|
595
|
+
|
|
596
|
+
// Wrap console methods to also send to remote server
|
|
597
|
+
const originalLog = console.log;
|
|
598
|
+
console.log = (...args) => {
|
|
599
|
+
originalLog.apply(console, args);
|
|
600
|
+
logger.log("LOG", args.map(String).join(" "));
|
|
601
|
+
};
|
|
602
|
+
|
|
603
|
+
// Flush before page unload
|
|
604
|
+
window.addEventListener("beforeunload", () => {
|
|
605
|
+
logger.flush();
|
|
606
|
+
});
|
|
607
|
+
```
|
|
608
|
+
|
|
609
|
+
### React/Vue/Angular Error Boundary
|
|
610
|
+
|
|
611
|
+
```typescript
|
|
612
|
+
import { RemoteLogClient } from "@graphty/remote-logger";
|
|
613
|
+
|
|
614
|
+
const logger = new RemoteLogClient({
|
|
615
|
+
serverUrl: "http://localhost:9080",
|
|
616
|
+
sessionPrefix: "react-app",
|
|
617
|
+
});
|
|
618
|
+
|
|
619
|
+
// Global error handler
|
|
620
|
+
window.onerror = (message, source, lineno, colno, error) => {
|
|
621
|
+
logger.log("ERROR", String(message), {
|
|
622
|
+
source,
|
|
623
|
+
lineno,
|
|
624
|
+
colno,
|
|
625
|
+
stack: error?.stack,
|
|
626
|
+
});
|
|
627
|
+
};
|
|
628
|
+
|
|
629
|
+
// Unhandled promise rejections
|
|
630
|
+
window.onunhandledrejection = (event) => {
|
|
631
|
+
logger.log("ERROR", "Unhandled rejection", {
|
|
632
|
+
reason: String(event.reason),
|
|
633
|
+
});
|
|
634
|
+
};
|
|
635
|
+
```
|
|
636
|
+
|
|
637
|
+
### Vite Integration (Automatic Project Markers)
|
|
638
|
+
|
|
639
|
+
Use the Vite plugin to automatically inject project markers into your browser builds:
|
|
640
|
+
|
|
641
|
+
```typescript
|
|
642
|
+
// vite.config.ts
|
|
643
|
+
import { defineConfig } from "vite";
|
|
644
|
+
import { remoteLoggerPlugin } from "@graphty/remote-logger/vite";
|
|
645
|
+
|
|
646
|
+
export default defineConfig({
|
|
647
|
+
plugins: [remoteLoggerPlugin()],
|
|
648
|
+
});
|
|
649
|
+
```
|
|
650
|
+
|
|
651
|
+
The plugin automatically:
|
|
652
|
+
- Detects if you're in a git worktree (e.g., `.worktrees/my-feature`) and uses the worktree name as the marker
|
|
653
|
+
- Falls back to the project directory basename for regular projects
|
|
654
|
+
- Injects `__REMOTE_LOG_PROJECT_MARKER__` and `__REMOTE_LOG_WORKTREE_PATH__` globals
|
|
655
|
+
|
|
656
|
+
The `RemoteLogClient` automatically reads these globals when available:
|
|
657
|
+
|
|
658
|
+
```typescript
|
|
659
|
+
// These are injected by the Vite plugin
|
|
660
|
+
declare const __REMOTE_LOG_PROJECT_MARKER__: string | undefined;
|
|
661
|
+
declare const __REMOTE_LOG_WORKTREE_PATH__: string | undefined;
|
|
662
|
+
|
|
663
|
+
// Client reads them automatically
|
|
664
|
+
const client = new RemoteLogClient({
|
|
665
|
+
serverUrl: "http://localhost:9080",
|
|
666
|
+
// projectMarker and worktreePath are auto-detected!
|
|
667
|
+
});
|
|
668
|
+
```
|
|
669
|
+
|
|
670
|
+
### Usage with graphty-element
|
|
671
|
+
|
|
672
|
+
Add URL parameter to enable remote logging in Storybook:
|
|
673
|
+
|
|
674
|
+
```
|
|
675
|
+
?graphty-element-remote-log=http://localhost:9080
|
|
676
|
+
```
|
|
677
|
+
|
|
678
|
+
### Node.js Custom Server Integration
|
|
679
|
+
|
|
680
|
+
```typescript
|
|
681
|
+
import { startLogServer, clearLogs } from "@graphty/remote-logger/server";
|
|
682
|
+
import type { Server } from "http";
|
|
683
|
+
|
|
684
|
+
// Start server and store reference
|
|
685
|
+
const server: Server = startLogServer({
|
|
686
|
+
port: 9080,
|
|
687
|
+
useHttp: true,
|
|
688
|
+
quiet: true, // Suppress banner for programmatic use
|
|
689
|
+
logFile: "./logs/debug.jsonl",
|
|
690
|
+
});
|
|
691
|
+
|
|
692
|
+
// Clear logs periodically
|
|
693
|
+
setInterval(() => {
|
|
694
|
+
clearLogs();
|
|
695
|
+
}, 3600000); // Every hour
|
|
696
|
+
|
|
697
|
+
// Graceful shutdown
|
|
698
|
+
process.on("SIGTERM", () => {
|
|
699
|
+
server.close(() => {
|
|
700
|
+
process.exit(0);
|
|
701
|
+
});
|
|
702
|
+
});
|
|
703
|
+
```
|
|
704
|
+
|
|
705
|
+
### Combining RemoteLogClient with ConsoleCaptureUI
|
|
706
|
+
|
|
707
|
+
```typescript
|
|
708
|
+
import { RemoteLogClient } from "@graphty/remote-logger";
|
|
709
|
+
import { initConsoleCaptureUI } from "@graphty/remote-logger/ui";
|
|
710
|
+
|
|
711
|
+
// Initialize console capture for local viewing
|
|
712
|
+
const ui = initConsoleCaptureUI();
|
|
713
|
+
|
|
714
|
+
// Also send to remote server
|
|
715
|
+
const remoteLogger = new RemoteLogClient({
|
|
716
|
+
serverUrl: "http://localhost:9080",
|
|
717
|
+
sessionPrefix: "dual-logging",
|
|
718
|
+
});
|
|
719
|
+
|
|
720
|
+
// Hook into captured logs
|
|
721
|
+
const originalLog = console.log;
|
|
722
|
+
console.log = (...args) => {
|
|
723
|
+
// ConsoleCaptureUI already captures this
|
|
724
|
+
originalLog.apply(console, args);
|
|
725
|
+
// Also send to remote
|
|
726
|
+
remoteLogger.log("LOG", args.map(String).join(" "));
|
|
727
|
+
};
|
|
728
|
+
```
|
|
729
|
+
|
|
730
|
+
## HTTPS Certificates
|
|
731
|
+
|
|
732
|
+
### Auto-generated Self-Signed Cert
|
|
733
|
+
|
|
734
|
+
By default, the server generates a self-signed certificate. You'll need to accept the certificate warning in your browser.
|
|
735
|
+
|
|
736
|
+
### Using Let's Encrypt or Custom Certs
|
|
737
|
+
|
|
738
|
+
```bash
|
|
739
|
+
npx remote-log-server \
|
|
740
|
+
--cert /path/to/fullchain.pem \
|
|
741
|
+
--key /path/to/privkey.pem \
|
|
742
|
+
--host yourdomain.com
|
|
743
|
+
```
|
|
744
|
+
|
|
745
|
+
## File Logging
|
|
746
|
+
|
|
747
|
+
Write logs to a JSONL file for later analysis:
|
|
748
|
+
|
|
749
|
+
```bash
|
|
750
|
+
npx remote-log-server --log-file ./logs/debug.jsonl
|
|
751
|
+
```
|
|
752
|
+
|
|
753
|
+
Each line contains a JSON object:
|
|
754
|
+
```json
|
|
755
|
+
{"time":"2024-01-15T10:30:00Z","sessionId":"myapp-abc123","level":"INFO","message":"Hello"}
|
|
756
|
+
```
|
|
757
|
+
|
|
758
|
+
## TypeScript
|
|
759
|
+
|
|
760
|
+
Full TypeScript support with type definitions included.
|
|
761
|
+
|
|
762
|
+
```typescript
|
|
763
|
+
// Client types
|
|
764
|
+
import type {
|
|
765
|
+
LogEntry,
|
|
766
|
+
RemoteLogClientOptions,
|
|
767
|
+
ThrottlePattern
|
|
768
|
+
} from "@graphty/remote-logger";
|
|
769
|
+
|
|
770
|
+
// Server types (from server entry point)
|
|
771
|
+
import type {
|
|
772
|
+
LogServerOptions,
|
|
773
|
+
ParseArgsResult,
|
|
774
|
+
GeneratedCert
|
|
775
|
+
} from "@graphty/remote-logger/server";
|
|
776
|
+
```
|
|
777
|
+
|
|
778
|
+
### Type Definitions
|
|
779
|
+
|
|
780
|
+
```typescript
|
|
781
|
+
interface LogEntry {
|
|
782
|
+
time: string; // ISO 8601 timestamp
|
|
783
|
+
level: string; // Log level (INFO, DEBUG, WARN, ERROR, etc.)
|
|
784
|
+
message: string; // Log message
|
|
785
|
+
data?: Record<string, unknown>; // Optional additional data
|
|
786
|
+
}
|
|
787
|
+
|
|
788
|
+
interface ThrottlePattern {
|
|
789
|
+
pattern: RegExp; // Pattern to match log messages
|
|
790
|
+
intervalMs: number; // Minimum interval between matching messages
|
|
791
|
+
}
|
|
792
|
+
|
|
793
|
+
interface RemoteLogClientOptions {
|
|
794
|
+
serverUrl: string;
|
|
795
|
+
sessionPrefix?: string;
|
|
796
|
+
batchIntervalMs?: number;
|
|
797
|
+
maxRetries?: number;
|
|
798
|
+
retryDelayMs?: number;
|
|
799
|
+
throttlePatterns?: ThrottlePattern[];
|
|
800
|
+
projectMarker?: string; // Project identifier for filtering
|
|
801
|
+
worktreePath?: string; // Full path for debugging
|
|
802
|
+
}
|
|
803
|
+
|
|
804
|
+
interface LogServerOptions {
|
|
805
|
+
port?: number;
|
|
806
|
+
host?: string;
|
|
807
|
+
certPath?: string;
|
|
808
|
+
keyPath?: string;
|
|
809
|
+
logFile?: string;
|
|
810
|
+
useHttp?: boolean;
|
|
811
|
+
quiet?: boolean;
|
|
812
|
+
}
|
|
813
|
+
```
|
|
814
|
+
|
|
815
|
+
## Troubleshooting
|
|
816
|
+
|
|
817
|
+
### CORS Errors
|
|
818
|
+
|
|
819
|
+
The server includes CORS headers by default (`Access-Control-Allow-Origin: *`). If you still encounter CORS issues:
|
|
820
|
+
|
|
821
|
+
1. Ensure you're using the correct protocol (http vs https)
|
|
822
|
+
2. Check that the port is correct
|
|
823
|
+
3. For HTTPS, you may need to accept the self-signed certificate first by visiting the server URL directly
|
|
824
|
+
|
|
825
|
+
### Certificate Warnings
|
|
826
|
+
|
|
827
|
+
When using auto-generated self-signed certificates:
|
|
828
|
+
|
|
829
|
+
1. Navigate to `https://localhost:9080/health` in your browser
|
|
830
|
+
2. Accept the security warning
|
|
831
|
+
3. Your application should now be able to connect
|
|
832
|
+
|
|
833
|
+
### Logs Not Appearing
|
|
834
|
+
|
|
835
|
+
1. Check the browser console for network errors
|
|
836
|
+
2. Verify the server is running: `curl http://localhost:9080/health`
|
|
837
|
+
3. Check that `flush()` is being called before page unload
|
|
838
|
+
4. Increase `batchIntervalMs` if logs are being sent too frequently
|
|
839
|
+
|
|
840
|
+
### High Memory Usage on Server
|
|
841
|
+
|
|
842
|
+
The server stores all logs in memory. For long-running sessions:
|
|
843
|
+
|
|
844
|
+
1. Use `POST /logs/clear` periodically to clear logs
|
|
845
|
+
2. Or use `clearLogs()` programmatically
|
|
846
|
+
3. Consider using `--log-file` to persist logs to disk and reduce memory pressure
|
|
847
|
+
|
|
848
|
+
## Package Exports
|
|
849
|
+
|
|
850
|
+
The package provides three entry points for different use cases:
|
|
851
|
+
|
|
852
|
+
### Main Entry (`@graphty/remote-logger`)
|
|
853
|
+
|
|
854
|
+
Browser-safe exports for the logging client:
|
|
855
|
+
|
|
856
|
+
```typescript
|
|
857
|
+
import {
|
|
858
|
+
RemoteLogClient,
|
|
859
|
+
createRemoteLogClient
|
|
860
|
+
} from "@graphty/remote-logger";
|
|
861
|
+
|
|
862
|
+
// Types
|
|
863
|
+
import type {
|
|
864
|
+
LogEntry,
|
|
865
|
+
RemoteLogClientOptions,
|
|
866
|
+
ThrottlePattern
|
|
867
|
+
} from "@graphty/remote-logger";
|
|
868
|
+
```
|
|
869
|
+
|
|
870
|
+
### Server Entry (`@graphty/remote-logger/server`)
|
|
871
|
+
|
|
872
|
+
Node.js-only exports for the log server:
|
|
873
|
+
|
|
874
|
+
```typescript
|
|
875
|
+
import {
|
|
876
|
+
startLogServer, // Start server programmatically
|
|
877
|
+
main, // CLI entry point
|
|
878
|
+
parseArgs, // Parse CLI arguments
|
|
879
|
+
clearLogs, // Clear stored logs
|
|
880
|
+
HELP_TEXT, // CLI help text
|
|
881
|
+
|
|
882
|
+
// Certificate utilities
|
|
883
|
+
generateSelfSignedCert,
|
|
884
|
+
certFilesExist,
|
|
885
|
+
readCertFiles,
|
|
886
|
+
} from "@graphty/remote-logger/server";
|
|
887
|
+
|
|
888
|
+
// Types
|
|
889
|
+
import type {
|
|
890
|
+
LogServerOptions,
|
|
891
|
+
LogEntry,
|
|
892
|
+
ParseArgsResult,
|
|
893
|
+
GeneratedCert,
|
|
894
|
+
} from "@graphty/remote-logger/server";
|
|
895
|
+
```
|
|
896
|
+
|
|
897
|
+
### UI Entry (`@graphty/remote-logger/ui`)
|
|
898
|
+
|
|
899
|
+
Browser exports for the console capture widget:
|
|
900
|
+
|
|
901
|
+
```typescript
|
|
902
|
+
import {
|
|
903
|
+
ConsoleCaptureUI,
|
|
904
|
+
initConsoleCaptureUI
|
|
905
|
+
} from "@graphty/remote-logger/ui";
|
|
906
|
+
```
|
|
907
|
+
|
|
908
|
+
### Client Entry (`@graphty/remote-logger/client`)
|
|
909
|
+
|
|
910
|
+
Direct client-only imports (same as main entry):
|
|
911
|
+
|
|
912
|
+
```typescript
|
|
913
|
+
import { RemoteLogClient } from "@graphty/remote-logger/client";
|
|
914
|
+
```
|
|
915
|
+
|
|
916
|
+
### Vite Entry (`@graphty/remote-logger/vite`)
|
|
917
|
+
|
|
918
|
+
Vite plugin for automatic project marker injection:
|
|
919
|
+
|
|
920
|
+
```typescript
|
|
921
|
+
import { remoteLoggerPlugin } from "@graphty/remote-logger/vite";
|
|
922
|
+
```
|
|
923
|
+
|
|
924
|
+
## Log Retention
|
|
925
|
+
|
|
926
|
+
Logs are automatically cleaned up after a configurable retention period (default: 7 days). This applies to both in-memory logs and JSONL files.
|
|
927
|
+
|
|
928
|
+
### Configuration
|
|
929
|
+
|
|
930
|
+
Set retention via environment variable:
|
|
931
|
+
|
|
932
|
+
```bash
|
|
933
|
+
export REMOTE_LOG_RETENTION_DAYS=3
|
|
934
|
+
npx remote-log-server
|
|
935
|
+
```
|
|
936
|
+
|
|
937
|
+
Or programmatically:
|
|
938
|
+
|
|
939
|
+
```typescript
|
|
940
|
+
import { LogStorage } from "@graphty/remote-logger/server";
|
|
941
|
+
|
|
942
|
+
const storage = new LogStorage({
|
|
943
|
+
retentionDays: 3, // Keep logs for 3 days
|
|
944
|
+
cleanupIntervalMs: 3600000, // Check every hour (default)
|
|
945
|
+
});
|
|
946
|
+
```
|
|
947
|
+
|
|
948
|
+
### How It Works
|
|
949
|
+
|
|
950
|
+
1. **Memory cleanup**: Individual logs older than the retention period are removed. Sessions with no remaining logs are deleted entirely.
|
|
951
|
+
|
|
952
|
+
2. **JSONL cleanup**: Project directories whose files haven't been modified within the retention period are removed.
|
|
953
|
+
|
|
954
|
+
3. **Automatic scheduling**: Cleanup runs automatically at the configured interval (default: 1 hour).
|
|
955
|
+
|
|
956
|
+
4. **Graceful shutdown**: Call `storage.stopCleanupTimer()` when shutting down to prevent memory leaks.
|
|
957
|
+
|
|
958
|
+
## License
|
|
959
|
+
|
|
960
|
+
MIT
|
|
44
961
|
|
|
45
|
-
**Maintained for OIDC setup purposes only**
|