@graphty/remote-logger 0.0.1 → 1.1.1
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 +636 -28
- package/bin/remote-log-server.js +3 -0
- package/dist/client/RemoteLogClient.d.ts +114 -0
- package/dist/client/RemoteLogClient.d.ts.map +1 -0
- package/dist/client/RemoteLogClient.js +238 -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 +47 -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/server/index.d.ts +8 -0
- package/dist/server/index.d.ts.map +1 -0
- package/dist/server/index.js +8 -0
- package/dist/server/index.js.map +1 -0
- package/dist/server/log-server.d.ts +75 -0
- package/dist/server/log-server.d.ts.map +1 -0
- package/dist/server/log-server.js +453 -0
- package/dist/server/log-server.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/package.json +80 -7
- package/src/client/RemoteLogClient.ts +280 -0
- package/src/client/index.ts +7 -0
- package/src/client/types.ts +49 -0
- package/src/index.ts +28 -0
- package/src/server/index.ts +17 -0
- package/src/server/log-server.ts +571 -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/README.md
CHANGED
|
@@ -1,45 +1,653 @@
|
|
|
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
|
+
## Features
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
- **Browser Client**: Lightweight client for sending logs from browser to server
|
|
8
|
+
- **Log Server**: HTTPS/HTTP server with colored terminal output and REST API
|
|
9
|
+
- **Console Capture UI**: Floating widget to copy/download/view browser console logs
|
|
10
|
+
- **Batching & Retry**: Efficient log delivery with automatic retry on failure
|
|
11
|
+
- **Session Tracking**: Unique session IDs for correlating logs across page loads
|
|
12
|
+
- **Throttling**: Configurable rate limiting for high-frequency log messages
|
|
13
|
+
- **File Logging**: Optional JSONL file output for persistent log storage
|
|
8
14
|
|
|
9
|
-
##
|
|
15
|
+
## Installation
|
|
10
16
|
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
17
|
+
```bash
|
|
18
|
+
npm install @graphty/remote-logger
|
|
19
|
+
# or
|
|
20
|
+
pnpm add @graphty/remote-logger
|
|
21
|
+
```
|
|
15
22
|
|
|
16
|
-
##
|
|
23
|
+
## Quick Start
|
|
17
24
|
|
|
18
|
-
|
|
25
|
+
### 1. Start the Log Server
|
|
19
26
|
|
|
20
|
-
|
|
27
|
+
```bash
|
|
28
|
+
# Using npx
|
|
29
|
+
npx remote-log-server --http --port 9080
|
|
21
30
|
|
|
22
|
-
|
|
31
|
+
# Or via CLI after installation
|
|
32
|
+
remote-log-server --http --port 9080
|
|
33
|
+
```
|
|
23
34
|
|
|
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
|
|
35
|
+
### 2. Add Client to Your Application
|
|
28
36
|
|
|
29
|
-
|
|
37
|
+
```typescript
|
|
38
|
+
import { RemoteLogClient } from "@graphty/remote-logger";
|
|
30
39
|
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
40
|
+
// Create client pointing to your log server
|
|
41
|
+
const logger = new RemoteLogClient({
|
|
42
|
+
serverUrl: "http://localhost:9080",
|
|
43
|
+
sessionPrefix: "myapp",
|
|
44
|
+
});
|
|
36
45
|
|
|
37
|
-
|
|
46
|
+
// Log messages (batched and sent automatically)
|
|
47
|
+
logger.log("INFO", "Application started");
|
|
48
|
+
logger.log("DEBUG", "Loading user data", { userId: 123 });
|
|
49
|
+
logger.log("ERROR", "Failed to fetch", { error: "Network error" });
|
|
38
50
|
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
- [GitHub Actions OIDC Documentation](https://docs.github.com/en/actions/deployment/security-hardening-your-deployments/about-security-hardening-with-openid-connect)
|
|
51
|
+
// Flush immediately when needed (e.g., before page unload)
|
|
52
|
+
await logger.flush();
|
|
42
53
|
|
|
43
|
-
|
|
54
|
+
// Clean up when done
|
|
55
|
+
await logger.close();
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
### 3. View Logs in Terminal
|
|
59
|
+
|
|
60
|
+
Logs appear in the server terminal with colors and session info:
|
|
61
|
+
|
|
62
|
+
```
|
|
63
|
+
10:30:15 [myapp-abc123] INFO Application started
|
|
64
|
+
10:30:15 [myapp-abc123] DEBUG Loading user data
|
|
65
|
+
10:30:16 [myapp-abc123] ERROR Failed to fetch
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
Log levels are displayed with the following colors:
|
|
69
|
+
| Level | Color |
|
|
70
|
+
|-------|-------|
|
|
71
|
+
| ERROR | White text on red background |
|
|
72
|
+
| WARN/WARNING | Bold text on yellow background |
|
|
73
|
+
| INFO | Blue |
|
|
74
|
+
| DEBUG | Cyan |
|
|
75
|
+
| TRACE | Dim/gray |
|
|
76
|
+
| LOG (default) | Green |
|
|
77
|
+
|
|
78
|
+
## CLI Reference
|
|
79
|
+
|
|
80
|
+
```
|
|
81
|
+
Usage:
|
|
82
|
+
npx remote-log-server [options]
|
|
83
|
+
|
|
84
|
+
Options:
|
|
85
|
+
--port, -p <port> Port to listen on (default: 9080)
|
|
86
|
+
--host, -h <host> Hostname to bind to (default: localhost)
|
|
87
|
+
--cert, -c <path> Path to SSL certificate file
|
|
88
|
+
--key, -k <path> Path to SSL private key file
|
|
89
|
+
--log-file, -l <path> Write logs to file (JSONL format)
|
|
90
|
+
--http Use HTTP instead of HTTPS
|
|
91
|
+
--quiet, -q Suppress startup banner
|
|
92
|
+
--help Show help message
|
|
93
|
+
|
|
94
|
+
Examples:
|
|
95
|
+
npx remote-log-server # HTTPS with auto-generated cert
|
|
96
|
+
npx remote-log-server --http --port 9080 # HTTP on port 9080
|
|
97
|
+
npx remote-log-server --cert cert.pem --key key.pem # Custom SSL certs
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
## API Reference
|
|
101
|
+
|
|
102
|
+
### RemoteLogClient
|
|
103
|
+
|
|
104
|
+
The browser-side client for sending logs.
|
|
105
|
+
|
|
106
|
+
```typescript
|
|
107
|
+
import { RemoteLogClient, createRemoteLogClient } from "@graphty/remote-logger";
|
|
108
|
+
|
|
109
|
+
// Using constructor
|
|
110
|
+
const client = new RemoteLogClient(options);
|
|
111
|
+
|
|
112
|
+
// Using factory function
|
|
113
|
+
const client = createRemoteLogClient(options);
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
#### Options
|
|
117
|
+
|
|
118
|
+
| Option | Type | Default | Description |
|
|
119
|
+
|--------|------|---------|-------------|
|
|
120
|
+
| `serverUrl` | `string` | required | URL of the log server |
|
|
121
|
+
| `sessionPrefix` | `string` | `"session"` | Prefix for session ID |
|
|
122
|
+
| `batchIntervalMs` | `number` | `1000` | Interval between batch sends |
|
|
123
|
+
| `maxRetries` | `number` | `3` | Max retry attempts on failure |
|
|
124
|
+
| `retryDelayMs` | `number` | `1000` | Base delay between retries (uses exponential backoff) |
|
|
125
|
+
| `throttlePatterns` | `ThrottlePattern[]` | `[]` | Patterns to throttle (see below) |
|
|
126
|
+
|
|
127
|
+
#### Throttling High-Frequency Logs
|
|
128
|
+
|
|
129
|
+
Use throttle patterns to prevent log flooding from high-frequency events:
|
|
130
|
+
|
|
131
|
+
```typescript
|
|
132
|
+
const logger = new RemoteLogClient({
|
|
133
|
+
serverUrl: "http://localhost:9080",
|
|
134
|
+
throttlePatterns: [
|
|
135
|
+
// Only send "Rendering frame" once per second
|
|
136
|
+
{ pattern: /Rendering frame/, intervalMs: 1000 },
|
|
137
|
+
// Only send mouse position updates every 500ms
|
|
138
|
+
{ pattern: /Mouse position:/, intervalMs: 500 },
|
|
139
|
+
],
|
|
140
|
+
});
|
|
141
|
+
```
|
|
142
|
+
|
|
143
|
+
#### Methods
|
|
144
|
+
|
|
145
|
+
| Method | Description |
|
|
146
|
+
|--------|-------------|
|
|
147
|
+
| `log(level, message, data?)` | Log a message with optional data object |
|
|
148
|
+
| `flush(): Promise<void>` | Immediately send pending logs to server |
|
|
149
|
+
| `close(): Promise<void>` | Flush remaining logs and stop accepting new ones |
|
|
150
|
+
|
|
151
|
+
#### Properties
|
|
152
|
+
|
|
153
|
+
| Property | Type | Description |
|
|
154
|
+
|----------|------|-------------|
|
|
155
|
+
| `sessionId` | `string` (readonly) | Unique session identifier in format `{prefix}-{timestamp}-{random}` |
|
|
156
|
+
|
|
157
|
+
### startLogServer
|
|
158
|
+
|
|
159
|
+
Start the log server programmatically.
|
|
160
|
+
|
|
161
|
+
```typescript
|
|
162
|
+
import { startLogServer } from "@graphty/remote-logger/server";
|
|
163
|
+
|
|
164
|
+
const server = startLogServer({
|
|
165
|
+
port: 9080,
|
|
166
|
+
host: "localhost",
|
|
167
|
+
useHttp: true,
|
|
168
|
+
quiet: false,
|
|
169
|
+
});
|
|
170
|
+
```
|
|
171
|
+
|
|
172
|
+
#### Options
|
|
173
|
+
|
|
174
|
+
| Option | Type | Default | Description |
|
|
175
|
+
|--------|------|---------|-------------|
|
|
176
|
+
| `port` | `number` | `9080` | Port to listen on |
|
|
177
|
+
| `host` | `string` | `"localhost"` | Hostname to bind to |
|
|
178
|
+
| `certPath` | `string` | - | Path to SSL certificate |
|
|
179
|
+
| `keyPath` | `string` | - | Path to SSL private key |
|
|
180
|
+
| `logFile` | `string` | - | Path for file logging |
|
|
181
|
+
| `useHttp` | `boolean` | `false` | Use HTTP instead of HTTPS |
|
|
182
|
+
| `quiet` | `boolean` | `false` | Suppress output |
|
|
183
|
+
|
|
184
|
+
### REST API Endpoints
|
|
185
|
+
|
|
186
|
+
| Endpoint | Method | Description |
|
|
187
|
+
|----------|--------|-------------|
|
|
188
|
+
| `/log` | POST | Receive logs from client |
|
|
189
|
+
| `/logs` | GET | Get all logs by session |
|
|
190
|
+
| `/logs/recent` | GET | Get recent logs (`?n=50&errors=true`) |
|
|
191
|
+
| `/logs/errors` | GET | Get error-level logs only |
|
|
192
|
+
| `/logs/clear` | POST | Clear all stored logs |
|
|
193
|
+
| `/health` | GET | Health check |
|
|
194
|
+
|
|
195
|
+
#### POST /log
|
|
196
|
+
|
|
197
|
+
Receive log entries from clients. This is the endpoint used by `RemoteLogClient`.
|
|
198
|
+
|
|
199
|
+
**Request body:**
|
|
200
|
+
```json
|
|
201
|
+
{
|
|
202
|
+
"sessionId": "myapp-abc123-xyz789",
|
|
203
|
+
"logs": [
|
|
204
|
+
{
|
|
205
|
+
"time": "2024-01-15T10:30:00.000Z",
|
|
206
|
+
"level": "INFO",
|
|
207
|
+
"message": "User logged in",
|
|
208
|
+
"data": { "userId": 123 }
|
|
209
|
+
}
|
|
210
|
+
]
|
|
211
|
+
}
|
|
212
|
+
```
|
|
213
|
+
|
|
214
|
+
**Response:**
|
|
215
|
+
```json
|
|
216
|
+
{ "success": true }
|
|
217
|
+
```
|
|
218
|
+
|
|
219
|
+
#### GET /logs
|
|
220
|
+
|
|
221
|
+
Returns all logs grouped by session.
|
|
222
|
+
|
|
223
|
+
**Response:**
|
|
224
|
+
```json
|
|
225
|
+
{
|
|
226
|
+
"myapp-abc123": [
|
|
227
|
+
{ "time": "2024-01-15T10:30:00Z", "level": "INFO", "message": "Hello" }
|
|
228
|
+
],
|
|
229
|
+
"myapp-def456": [
|
|
230
|
+
{ "time": "2024-01-15T10:31:00Z", "level": "DEBUG", "message": "Debug msg" }
|
|
231
|
+
]
|
|
232
|
+
}
|
|
233
|
+
```
|
|
234
|
+
|
|
235
|
+
#### GET /logs/recent
|
|
236
|
+
|
|
237
|
+
Returns recent logs across all sessions, sorted by time.
|
|
238
|
+
|
|
239
|
+
**Query parameters:**
|
|
240
|
+
- `n` (optional): Number of logs to return (default: 50)
|
|
241
|
+
- `errors` (optional): Set to `true` to return only error-level logs
|
|
242
|
+
|
|
243
|
+
**Response:**
|
|
244
|
+
```json
|
|
245
|
+
{
|
|
246
|
+
"total": 150,
|
|
247
|
+
"showing": 50,
|
|
248
|
+
"logs": [
|
|
249
|
+
{ "sessionId": "myapp-abc123", "time": "...", "level": "INFO", "message": "..." }
|
|
250
|
+
]
|
|
251
|
+
}
|
|
252
|
+
```
|
|
253
|
+
|
|
254
|
+
#### GET /logs/errors
|
|
255
|
+
|
|
256
|
+
Returns only error-level logs across all sessions.
|
|
257
|
+
|
|
258
|
+
**Response:**
|
|
259
|
+
```json
|
|
260
|
+
{
|
|
261
|
+
"total": 5,
|
|
262
|
+
"logs": [
|
|
263
|
+
{ "sessionId": "myapp-abc123", "time": "...", "level": "ERROR", "message": "..." }
|
|
264
|
+
]
|
|
265
|
+
}
|
|
266
|
+
```
|
|
267
|
+
|
|
268
|
+
#### POST /logs/clear
|
|
269
|
+
|
|
270
|
+
Clears all stored logs from memory.
|
|
271
|
+
|
|
272
|
+
**Response:**
|
|
273
|
+
```json
|
|
274
|
+
{ "success": true }
|
|
275
|
+
```
|
|
276
|
+
|
|
277
|
+
#### GET /health
|
|
278
|
+
|
|
279
|
+
Health check endpoint for monitoring.
|
|
280
|
+
|
|
281
|
+
**Response:**
|
|
282
|
+
```json
|
|
283
|
+
{ "status": "ok", "sessions": 3 }
|
|
284
|
+
```
|
|
285
|
+
|
|
286
|
+
### ConsoleCaptureUI
|
|
287
|
+
|
|
288
|
+
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.
|
|
289
|
+
|
|
290
|
+
```typescript
|
|
291
|
+
import { initConsoleCaptureUI, ConsoleCaptureUI } from "@graphty/remote-logger/ui";
|
|
292
|
+
|
|
293
|
+
// Initialize the UI (adds floating button to page)
|
|
294
|
+
const ui = initConsoleCaptureUI();
|
|
295
|
+
|
|
296
|
+
// Or use the class directly
|
|
297
|
+
const ui = new ConsoleCaptureUI();
|
|
298
|
+
|
|
299
|
+
// All console methods are now captured
|
|
300
|
+
console.log("This is captured");
|
|
301
|
+
console.error("This too");
|
|
302
|
+
|
|
303
|
+
// Access captured logs programmatically
|
|
304
|
+
const logsText = ui.getLogs();
|
|
305
|
+
|
|
306
|
+
// Later, clean up (restores original console methods)
|
|
307
|
+
ui.destroy();
|
|
308
|
+
```
|
|
309
|
+
|
|
310
|
+
#### Widget Features
|
|
311
|
+
|
|
312
|
+
The floating button (📋) appears in the top-right corner of the page. Clicking it reveals a menu with:
|
|
313
|
+
|
|
314
|
+
| Button | Action |
|
|
315
|
+
|--------|--------|
|
|
316
|
+
| 📋 Copy Logs | Copy all captured logs to clipboard |
|
|
317
|
+
| 💾 Download | Download logs as a timestamped text file |
|
|
318
|
+
| 🗑️ Clear | Clear all captured logs |
|
|
319
|
+
| 👁️ Show Logs | Open a modal to view and select logs |
|
|
320
|
+
|
|
321
|
+
#### Instance Methods
|
|
322
|
+
|
|
323
|
+
| Method | Description |
|
|
324
|
+
|--------|-------------|
|
|
325
|
+
| `getLogs(): string` | Get all captured logs as formatted text |
|
|
326
|
+
| `clearLogs(): void` | Clear captured logs |
|
|
327
|
+
| `copyLogs(): Promise<void>` | Copy logs to clipboard |
|
|
328
|
+
| `downloadLogs(): void` | Download logs as text file |
|
|
329
|
+
| `destroy(): void` | Restore console methods and remove UI |
|
|
330
|
+
|
|
331
|
+
#### Global Methods
|
|
332
|
+
|
|
333
|
+
When initialized, `window.__console__` is exposed for programmatic access:
|
|
334
|
+
|
|
335
|
+
```typescript
|
|
336
|
+
// Available globally after initConsoleCaptureUI()
|
|
337
|
+
window.__console__.copy(); // Copy to clipboard
|
|
338
|
+
window.__console__.download(); // Download as file
|
|
339
|
+
window.__console__.clear(); // Clear logs
|
|
340
|
+
window.__console__.get(); // Get logs as string
|
|
341
|
+
window.__console__.logs; // Raw log array
|
|
342
|
+
```
|
|
343
|
+
|
|
344
|
+
#### Log Format
|
|
345
|
+
|
|
346
|
+
Captured logs are formatted as:
|
|
347
|
+
```
|
|
348
|
+
[2024-01-15T10:30:00.000Z] [INFO] User logged in
|
|
349
|
+
[2024-01-15T10:30:01.000Z] [ERROR] Failed to connect
|
|
350
|
+
```
|
|
351
|
+
|
|
352
|
+
## Integration Examples
|
|
353
|
+
|
|
354
|
+
### Basic Browser Integration
|
|
355
|
+
|
|
356
|
+
```typescript
|
|
357
|
+
import { RemoteLogClient } from "@graphty/remote-logger";
|
|
358
|
+
|
|
359
|
+
// Create a logger instance
|
|
360
|
+
const logger = new RemoteLogClient({
|
|
361
|
+
serverUrl: "http://localhost:9080",
|
|
362
|
+
sessionPrefix: "myapp",
|
|
363
|
+
});
|
|
364
|
+
|
|
365
|
+
// Wrap console methods to also send to remote server
|
|
366
|
+
const originalLog = console.log;
|
|
367
|
+
console.log = (...args) => {
|
|
368
|
+
originalLog.apply(console, args);
|
|
369
|
+
logger.log("LOG", args.map(String).join(" "));
|
|
370
|
+
};
|
|
371
|
+
|
|
372
|
+
// Flush before page unload
|
|
373
|
+
window.addEventListener("beforeunload", () => {
|
|
374
|
+
logger.flush();
|
|
375
|
+
});
|
|
376
|
+
```
|
|
377
|
+
|
|
378
|
+
### React/Vue/Angular Error Boundary
|
|
379
|
+
|
|
380
|
+
```typescript
|
|
381
|
+
import { RemoteLogClient } from "@graphty/remote-logger";
|
|
382
|
+
|
|
383
|
+
const logger = new RemoteLogClient({
|
|
384
|
+
serverUrl: "http://localhost:9080",
|
|
385
|
+
sessionPrefix: "react-app",
|
|
386
|
+
});
|
|
387
|
+
|
|
388
|
+
// Global error handler
|
|
389
|
+
window.onerror = (message, source, lineno, colno, error) => {
|
|
390
|
+
logger.log("ERROR", String(message), {
|
|
391
|
+
source,
|
|
392
|
+
lineno,
|
|
393
|
+
colno,
|
|
394
|
+
stack: error?.stack,
|
|
395
|
+
});
|
|
396
|
+
};
|
|
397
|
+
|
|
398
|
+
// Unhandled promise rejections
|
|
399
|
+
window.onunhandledrejection = (event) => {
|
|
400
|
+
logger.log("ERROR", "Unhandled rejection", {
|
|
401
|
+
reason: String(event.reason),
|
|
402
|
+
});
|
|
403
|
+
};
|
|
404
|
+
```
|
|
405
|
+
|
|
406
|
+
### Usage with graphty-element
|
|
407
|
+
|
|
408
|
+
Add URL parameter to enable remote logging in Storybook:
|
|
409
|
+
|
|
410
|
+
```
|
|
411
|
+
?graphty-element-remote-log=http://localhost:9080
|
|
412
|
+
```
|
|
413
|
+
|
|
414
|
+
### Node.js Custom Server Integration
|
|
415
|
+
|
|
416
|
+
```typescript
|
|
417
|
+
import { startLogServer, clearLogs } from "@graphty/remote-logger/server";
|
|
418
|
+
import type { Server } from "http";
|
|
419
|
+
|
|
420
|
+
// Start server and store reference
|
|
421
|
+
const server: Server = startLogServer({
|
|
422
|
+
port: 9080,
|
|
423
|
+
useHttp: true,
|
|
424
|
+
quiet: true, // Suppress banner for programmatic use
|
|
425
|
+
logFile: "./logs/debug.jsonl",
|
|
426
|
+
});
|
|
427
|
+
|
|
428
|
+
// Clear logs periodically
|
|
429
|
+
setInterval(() => {
|
|
430
|
+
clearLogs();
|
|
431
|
+
}, 3600000); // Every hour
|
|
432
|
+
|
|
433
|
+
// Graceful shutdown
|
|
434
|
+
process.on("SIGTERM", () => {
|
|
435
|
+
server.close(() => {
|
|
436
|
+
process.exit(0);
|
|
437
|
+
});
|
|
438
|
+
});
|
|
439
|
+
```
|
|
440
|
+
|
|
441
|
+
### Combining RemoteLogClient with ConsoleCaptureUI
|
|
442
|
+
|
|
443
|
+
```typescript
|
|
444
|
+
import { RemoteLogClient } from "@graphty/remote-logger";
|
|
445
|
+
import { initConsoleCaptureUI } from "@graphty/remote-logger/ui";
|
|
446
|
+
|
|
447
|
+
// Initialize console capture for local viewing
|
|
448
|
+
const ui = initConsoleCaptureUI();
|
|
449
|
+
|
|
450
|
+
// Also send to remote server
|
|
451
|
+
const remoteLogger = new RemoteLogClient({
|
|
452
|
+
serverUrl: "http://localhost:9080",
|
|
453
|
+
sessionPrefix: "dual-logging",
|
|
454
|
+
});
|
|
455
|
+
|
|
456
|
+
// Hook into captured logs
|
|
457
|
+
const originalLog = console.log;
|
|
458
|
+
console.log = (...args) => {
|
|
459
|
+
// ConsoleCaptureUI already captures this
|
|
460
|
+
originalLog.apply(console, args);
|
|
461
|
+
// Also send to remote
|
|
462
|
+
remoteLogger.log("LOG", args.map(String).join(" "));
|
|
463
|
+
};
|
|
464
|
+
```
|
|
465
|
+
|
|
466
|
+
## HTTPS Certificates
|
|
467
|
+
|
|
468
|
+
### Auto-generated Self-Signed Cert
|
|
469
|
+
|
|
470
|
+
By default, the server generates a self-signed certificate. You'll need to accept the certificate warning in your browser.
|
|
471
|
+
|
|
472
|
+
### Using Let's Encrypt or Custom Certs
|
|
473
|
+
|
|
474
|
+
```bash
|
|
475
|
+
npx remote-log-server \
|
|
476
|
+
--cert /path/to/fullchain.pem \
|
|
477
|
+
--key /path/to/privkey.pem \
|
|
478
|
+
--host yourdomain.com
|
|
479
|
+
```
|
|
480
|
+
|
|
481
|
+
## File Logging
|
|
482
|
+
|
|
483
|
+
Write logs to a JSONL file for later analysis:
|
|
484
|
+
|
|
485
|
+
```bash
|
|
486
|
+
npx remote-log-server --log-file ./logs/debug.jsonl
|
|
487
|
+
```
|
|
488
|
+
|
|
489
|
+
Each line contains a JSON object:
|
|
490
|
+
```json
|
|
491
|
+
{"time":"2024-01-15T10:30:00Z","sessionId":"myapp-abc123","level":"INFO","message":"Hello"}
|
|
492
|
+
```
|
|
493
|
+
|
|
494
|
+
## TypeScript
|
|
495
|
+
|
|
496
|
+
Full TypeScript support with type definitions included.
|
|
497
|
+
|
|
498
|
+
```typescript
|
|
499
|
+
// Client types
|
|
500
|
+
import type {
|
|
501
|
+
LogEntry,
|
|
502
|
+
RemoteLogClientOptions,
|
|
503
|
+
ThrottlePattern
|
|
504
|
+
} from "@graphty/remote-logger";
|
|
505
|
+
|
|
506
|
+
// Server types (from server entry point)
|
|
507
|
+
import type {
|
|
508
|
+
LogServerOptions,
|
|
509
|
+
ParseArgsResult,
|
|
510
|
+
GeneratedCert
|
|
511
|
+
} from "@graphty/remote-logger/server";
|
|
512
|
+
```
|
|
513
|
+
|
|
514
|
+
### Type Definitions
|
|
515
|
+
|
|
516
|
+
```typescript
|
|
517
|
+
interface LogEntry {
|
|
518
|
+
time: string; // ISO 8601 timestamp
|
|
519
|
+
level: string; // Log level (INFO, DEBUG, WARN, ERROR, etc.)
|
|
520
|
+
message: string; // Log message
|
|
521
|
+
data?: Record<string, unknown>; // Optional additional data
|
|
522
|
+
}
|
|
523
|
+
|
|
524
|
+
interface ThrottlePattern {
|
|
525
|
+
pattern: RegExp; // Pattern to match log messages
|
|
526
|
+
intervalMs: number; // Minimum interval between matching messages
|
|
527
|
+
}
|
|
528
|
+
|
|
529
|
+
interface RemoteLogClientOptions {
|
|
530
|
+
serverUrl: string;
|
|
531
|
+
sessionPrefix?: string;
|
|
532
|
+
batchIntervalMs?: number;
|
|
533
|
+
maxRetries?: number;
|
|
534
|
+
retryDelayMs?: number;
|
|
535
|
+
throttlePatterns?: ThrottlePattern[];
|
|
536
|
+
}
|
|
537
|
+
|
|
538
|
+
interface LogServerOptions {
|
|
539
|
+
port?: number;
|
|
540
|
+
host?: string;
|
|
541
|
+
certPath?: string;
|
|
542
|
+
keyPath?: string;
|
|
543
|
+
logFile?: string;
|
|
544
|
+
useHttp?: boolean;
|
|
545
|
+
quiet?: boolean;
|
|
546
|
+
}
|
|
547
|
+
```
|
|
548
|
+
|
|
549
|
+
## Troubleshooting
|
|
550
|
+
|
|
551
|
+
### CORS Errors
|
|
552
|
+
|
|
553
|
+
The server includes CORS headers by default (`Access-Control-Allow-Origin: *`). If you still encounter CORS issues:
|
|
554
|
+
|
|
555
|
+
1. Ensure you're using the correct protocol (http vs https)
|
|
556
|
+
2. Check that the port is correct
|
|
557
|
+
3. For HTTPS, you may need to accept the self-signed certificate first by visiting the server URL directly
|
|
558
|
+
|
|
559
|
+
### Certificate Warnings
|
|
560
|
+
|
|
561
|
+
When using auto-generated self-signed certificates:
|
|
562
|
+
|
|
563
|
+
1. Navigate to `https://localhost:9080/health` in your browser
|
|
564
|
+
2. Accept the security warning
|
|
565
|
+
3. Your application should now be able to connect
|
|
566
|
+
|
|
567
|
+
### Logs Not Appearing
|
|
568
|
+
|
|
569
|
+
1. Check the browser console for network errors
|
|
570
|
+
2. Verify the server is running: `curl http://localhost:9080/health`
|
|
571
|
+
3. Check that `flush()` is being called before page unload
|
|
572
|
+
4. Increase `batchIntervalMs` if logs are being sent too frequently
|
|
573
|
+
|
|
574
|
+
### High Memory Usage on Server
|
|
575
|
+
|
|
576
|
+
The server stores all logs in memory. For long-running sessions:
|
|
577
|
+
|
|
578
|
+
1. Use `POST /logs/clear` periodically to clear logs
|
|
579
|
+
2. Or use `clearLogs()` programmatically
|
|
580
|
+
3. Consider using `--log-file` to persist logs to disk and reduce memory pressure
|
|
581
|
+
|
|
582
|
+
## Package Exports
|
|
583
|
+
|
|
584
|
+
The package provides three entry points for different use cases:
|
|
585
|
+
|
|
586
|
+
### Main Entry (`@graphty/remote-logger`)
|
|
587
|
+
|
|
588
|
+
Browser-safe exports for the logging client:
|
|
589
|
+
|
|
590
|
+
```typescript
|
|
591
|
+
import {
|
|
592
|
+
RemoteLogClient,
|
|
593
|
+
createRemoteLogClient
|
|
594
|
+
} from "@graphty/remote-logger";
|
|
595
|
+
|
|
596
|
+
// Types
|
|
597
|
+
import type {
|
|
598
|
+
LogEntry,
|
|
599
|
+
RemoteLogClientOptions,
|
|
600
|
+
ThrottlePattern
|
|
601
|
+
} from "@graphty/remote-logger";
|
|
602
|
+
```
|
|
603
|
+
|
|
604
|
+
### Server Entry (`@graphty/remote-logger/server`)
|
|
605
|
+
|
|
606
|
+
Node.js-only exports for the log server:
|
|
607
|
+
|
|
608
|
+
```typescript
|
|
609
|
+
import {
|
|
610
|
+
startLogServer, // Start server programmatically
|
|
611
|
+
main, // CLI entry point
|
|
612
|
+
parseArgs, // Parse CLI arguments
|
|
613
|
+
clearLogs, // Clear stored logs
|
|
614
|
+
HELP_TEXT, // CLI help text
|
|
615
|
+
|
|
616
|
+
// Certificate utilities
|
|
617
|
+
generateSelfSignedCert,
|
|
618
|
+
certFilesExist,
|
|
619
|
+
readCertFiles,
|
|
620
|
+
} from "@graphty/remote-logger/server";
|
|
621
|
+
|
|
622
|
+
// Types
|
|
623
|
+
import type {
|
|
624
|
+
LogServerOptions,
|
|
625
|
+
LogEntry,
|
|
626
|
+
ParseArgsResult,
|
|
627
|
+
GeneratedCert,
|
|
628
|
+
} from "@graphty/remote-logger/server";
|
|
629
|
+
```
|
|
630
|
+
|
|
631
|
+
### UI Entry (`@graphty/remote-logger/ui`)
|
|
632
|
+
|
|
633
|
+
Browser exports for the console capture widget:
|
|
634
|
+
|
|
635
|
+
```typescript
|
|
636
|
+
import {
|
|
637
|
+
ConsoleCaptureUI,
|
|
638
|
+
initConsoleCaptureUI
|
|
639
|
+
} from "@graphty/remote-logger/ui";
|
|
640
|
+
```
|
|
641
|
+
|
|
642
|
+
### Client Entry (`@graphty/remote-logger/client`)
|
|
643
|
+
|
|
644
|
+
Direct client-only imports (same as main entry):
|
|
645
|
+
|
|
646
|
+
```typescript
|
|
647
|
+
import { RemoteLogClient } from "@graphty/remote-logger/client";
|
|
648
|
+
```
|
|
649
|
+
|
|
650
|
+
## License
|
|
651
|
+
|
|
652
|
+
MIT
|
|
44
653
|
|
|
45
|
-
**Maintained for OIDC setup purposes only**
|