@rudderjs/telescope 0.0.1 → 1.0.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 +101 -27
- package/dist/api/routes.d.ts +10 -6
- package/dist/api/routes.d.ts.map +1 -1
- package/dist/api/routes.js +42 -54
- package/dist/api/routes.js.map +1 -1
- package/dist/batch-context.d.ts +19 -0
- package/dist/batch-context.d.ts.map +1 -0
- package/dist/batch-context.js +24 -0
- package/dist/batch-context.js.map +1 -0
- package/dist/collectors/ai.d.ts +13 -0
- package/dist/collectors/ai.d.ts.map +1 -0
- package/dist/collectors/ai.js +61 -0
- package/dist/collectors/ai.js.map +1 -0
- package/dist/collectors/broadcast.d.ts +10 -0
- package/dist/collectors/broadcast.d.ts.map +1 -0
- package/dist/collectors/broadcast.js +46 -0
- package/dist/collectors/broadcast.js.map +1 -0
- package/dist/collectors/cache.d.ts.map +1 -1
- package/dist/collectors/cache.js +5 -4
- package/dist/collectors/cache.js.map +1 -1
- package/dist/collectors/command.d.ts +21 -0
- package/dist/collectors/command.d.ts.map +1 -0
- package/dist/collectors/command.js +55 -0
- package/dist/collectors/command.js.map +1 -0
- package/dist/collectors/dump.d.ts +17 -0
- package/dist/collectors/dump.d.ts.map +1 -0
- package/dist/collectors/dump.js +37 -0
- package/dist/collectors/dump.js.map +1 -0
- package/dist/collectors/event.d.ts.map +1 -1
- package/dist/collectors/event.js +2 -1
- package/dist/collectors/event.js.map +1 -1
- package/dist/collectors/exception.d.ts +1 -0
- package/dist/collectors/exception.d.ts.map +1 -1
- package/dist/collectors/exception.js +23 -4
- package/dist/collectors/exception.js.map +1 -1
- package/dist/collectors/gate.d.ts +18 -0
- package/dist/collectors/gate.d.ts.map +1 -0
- package/dist/collectors/gate.js +49 -0
- package/dist/collectors/gate.js.map +1 -0
- package/dist/collectors/http.d.ts +21 -0
- package/dist/collectors/http.d.ts.map +1 -0
- package/dist/collectors/http.js +64 -0
- package/dist/collectors/http.js.map +1 -0
- package/dist/collectors/job.d.ts.map +1 -1
- package/dist/collectors/job.js +3 -2
- package/dist/collectors/job.js.map +1 -1
- package/dist/collectors/live.d.ts +13 -0
- package/dist/collectors/live.d.ts.map +1 -0
- package/dist/collectors/live.js +60 -0
- package/dist/collectors/live.js.map +1 -0
- package/dist/collectors/log.d.ts.map +1 -1
- package/dist/collectors/log.js +2 -1
- package/dist/collectors/log.js.map +1 -1
- package/dist/collectors/mail.d.ts.map +1 -1
- package/dist/collectors/mail.js +2 -1
- package/dist/collectors/mail.js.map +1 -1
- package/dist/collectors/mcp.d.ts +14 -0
- package/dist/collectors/mcp.d.ts.map +1 -0
- package/dist/collectors/mcp.js +49 -0
- package/dist/collectors/mcp.js.map +1 -0
- package/dist/collectors/model.d.ts +6 -0
- package/dist/collectors/model.d.ts.map +1 -1
- package/dist/collectors/model.js +44 -1
- package/dist/collectors/model.js.map +1 -1
- package/dist/collectors/notification.d.ts.map +1 -1
- package/dist/collectors/notification.js +2 -1
- package/dist/collectors/notification.js.map +1 -1
- package/dist/collectors/query.d.ts.map +1 -1
- package/dist/collectors/query.js +5 -3
- package/dist/collectors/query.js.map +1 -1
- package/dist/collectors/request.d.ts +2 -1
- package/dist/collectors/request.d.ts.map +1 -1
- package/dist/collectors/request.js +78 -4
- package/dist/collectors/request.js.map +1 -1
- package/dist/index.d.ts +17 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +152 -95
- package/dist/index.js.map +1 -1
- package/dist/redact.d.ts +25 -0
- package/dist/redact.d.ts.map +1 -0
- package/dist/redact.js +55 -0
- package/dist/redact.js.map +1 -0
- package/dist/routes.d.ts +22 -0
- package/dist/routes.d.ts.map +1 -0
- package/dist/routes.js +105 -0
- package/dist/routes.js.map +1 -0
- package/dist/storage.d.ts.map +1 -1
- package/dist/storage.js +13 -0
- package/dist/storage.js.map +1 -1
- package/dist/types.d.ts +32 -1
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js +13 -0
- package/dist/types.js.map +1 -1
- package/dist/views/vanilla/Dashboard.d.ts +10 -0
- package/dist/views/vanilla/Dashboard.d.ts.map +1 -0
- package/dist/views/vanilla/Dashboard.js +48 -0
- package/dist/views/vanilla/Dashboard.js.map +1 -0
- package/dist/views/vanilla/EntryList.d.ts +29 -0
- package/dist/views/vanilla/EntryList.d.ts.map +1 -0
- package/dist/views/vanilla/EntryList.js +172 -0
- package/dist/views/vanilla/EntryList.js.map +1 -0
- package/dist/views/vanilla/Layout.d.ts +25 -0
- package/dist/views/vanilla/Layout.d.ts.map +1 -0
- package/dist/views/vanilla/Layout.js +225 -0
- package/dist/views/vanilla/Layout.js.map +1 -0
- package/dist/views/vanilla/_html.d.ts +27 -0
- package/dist/views/vanilla/_html.d.ts.map +1 -0
- package/dist/views/vanilla/_html.js +55 -0
- package/dist/views/vanilla/_html.js.map +1 -0
- package/dist/views/vanilla/columns.d.ts +20 -0
- package/dist/views/vanilla/columns.d.ts.map +1 -0
- package/dist/views/vanilla/columns.js +181 -0
- package/dist/views/vanilla/columns.js.map +1 -0
- package/dist/views/vanilla/details/Batch.d.ts +14 -0
- package/dist/views/vanilla/details/Batch.d.ts.map +1 -0
- package/dist/views/vanilla/details/Batch.js +120 -0
- package/dist/views/vanilla/details/Batch.js.map +1 -0
- package/dist/views/vanilla/details/Layout.d.ts +21 -0
- package/dist/views/vanilla/details/Layout.d.ts.map +1 -0
- package/dist/views/vanilla/details/Layout.js +163 -0
- package/dist/views/vanilla/details/Layout.js.map +1 -0
- package/dist/views/vanilla/details/NotFound.d.ts +8 -0
- package/dist/views/vanilla/details/NotFound.d.ts.map +1 -0
- package/dist/views/vanilla/details/NotFound.js +20 -0
- package/dist/views/vanilla/details/NotFound.js.map +1 -0
- package/dist/views/vanilla/details/index.d.ts +5 -0
- package/dist/views/vanilla/details/index.d.ts.map +1 -0
- package/dist/views/vanilla/details/index.js +5 -0
- package/dist/views/vanilla/details/index.js.map +1 -0
- package/dist/views/vanilla/details/sections.d.ts +46 -0
- package/dist/views/vanilla/details/sections.d.ts.map +1 -0
- package/dist/views/vanilla/details/sections.js +145 -0
- package/dist/views/vanilla/details/sections.js.map +1 -0
- package/dist/views/vanilla/details/views.d.ts +15 -0
- package/dist/views/vanilla/details/views.d.ts.map +1 -0
- package/dist/views/vanilla/details/views.js +534 -0
- package/dist/views/vanilla/details/views.js.map +1 -0
- package/dist/views/vanilla/index.d.ts +5 -0
- package/dist/views/vanilla/index.d.ts.map +1 -0
- package/dist/views/vanilla/index.js +5 -0
- package/dist/views/vanilla/index.js.map +1 -0
- package/package.json +53 -13
- package/dist/ui/layout.d.ts +0 -11
- package/dist/ui/layout.d.ts.map +0 -1
- package/dist/ui/layout.js +0 -69
- package/dist/ui/layout.js.map +0 -1
- package/dist/ui/pages.d.ts +0 -21
- package/dist/ui/pages.d.ts.map +0 -1
- package/dist/ui/pages.js +0 -225
- package/dist/ui/pages.js.map +0 -1
package/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# @rudderjs/telescope
|
|
2
2
|
|
|
3
|
-
Debug assistant for RudderJS — records requests, queries, jobs, exceptions, logs, mail, notifications, events, cache operations, scheduled tasks, and
|
|
3
|
+
Debug assistant for RudderJS — records requests, queries, jobs, exceptions, logs, mail, notifications, events, cache operations, scheduled tasks, model changes, CLI commands, outgoing HTTP requests, authorization decisions, WebSocket lifecycle, Yjs CRDT events, and `dump()`/`dd()` calls.
|
|
4
4
|
|
|
5
5
|
## Installation
|
|
6
6
|
|
|
@@ -10,13 +10,32 @@ pnpm add @rudderjs/telescope
|
|
|
10
10
|
|
|
11
11
|
## Setup
|
|
12
12
|
|
|
13
|
+
Telescope is auto-discovered via `defaultProviders()`. Just install the package, run `pnpm rudder providers:discover`, and add a config file:
|
|
14
|
+
|
|
13
15
|
```ts
|
|
14
|
-
//
|
|
15
|
-
import {
|
|
16
|
-
import
|
|
17
|
-
|
|
16
|
+
// config/telescope.ts
|
|
17
|
+
import { Env } from '@rudderjs/core'
|
|
18
|
+
import type { TelescopeConfig } from '@rudderjs/telescope'
|
|
19
|
+
|
|
20
|
+
export default {
|
|
21
|
+
enabled: Env.getBool('TELESCOPE_ENABLED', true),
|
|
22
|
+
path: 'telescope',
|
|
23
|
+
storage: 'memory',
|
|
24
|
+
} satisfies TelescopeConfig
|
|
18
25
|
```
|
|
19
26
|
|
|
27
|
+
## Dashboard
|
|
28
|
+
|
|
29
|
+
Telescope serves a built-in UI at `/{path}` (default `/telescope`) with:
|
|
30
|
+
|
|
31
|
+
- **Dashboard** — count cards for all entry types
|
|
32
|
+
- **Per-type list pages** — searchable, paginated tables with tag filtering and auto-refresh (2s polling)
|
|
33
|
+
- **Detail pages** — rich, type-specific views at `/telescope/{type}/{id}` (formatted SQL, mail HTML preview, stack traces, WebSocket timelines, etc.)
|
|
34
|
+
- **Batch grouping** — entries linked by `batchId` (e.g. all queries from one request, all events from one WebSocket connection) viewable at `/telescope/batches/{batchId}`
|
|
35
|
+
- **Sensitive data redaction** — headers and body fields are redacted at collection time, before they reach storage
|
|
36
|
+
|
|
37
|
+
The UI is vanilla HTML + Alpine.js + Tailwind CDN — no client framework dependency. Works regardless of whether your app uses React, Vue, Solid, or none.
|
|
38
|
+
|
|
20
39
|
## Telescope Facade
|
|
21
40
|
|
|
22
41
|
```ts
|
|
@@ -39,8 +58,6 @@ await Telescope.prune('log') // prune by type
|
|
|
39
58
|
await Telescope.prune() // prune all
|
|
40
59
|
```
|
|
41
60
|
|
|
42
|
-
## `Telescope` Methods
|
|
43
|
-
|
|
44
61
|
| Method | Returns | Description |
|
|
45
62
|
|--------|---------|-------------|
|
|
46
63
|
| `list(options?)` | `TelescopeEntry[]` | List entries with type/tag/search/pagination filters |
|
|
@@ -51,21 +68,34 @@ await Telescope.prune() // prune all
|
|
|
51
68
|
|
|
52
69
|
## Entry Types
|
|
53
70
|
|
|
54
|
-
Telescope records
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
|
59
|
-
|
|
60
|
-
| `
|
|
61
|
-
| `
|
|
62
|
-
| `
|
|
63
|
-
| `
|
|
64
|
-
| `
|
|
65
|
-
| `
|
|
66
|
-
| `
|
|
67
|
-
| `
|
|
68
|
-
| `
|
|
71
|
+
Telescope records 17 entry types via the observer-registry pattern — each peer package exports a process-wide observer singleton, and the corresponding collector subscribes at boot. If a peer package isn't installed, its collector silently skips.
|
|
72
|
+
|
|
73
|
+
### Core watchers
|
|
74
|
+
|
|
75
|
+
| Type | Collector | Source | Description |
|
|
76
|
+
|------|-----------|--------|-------------|
|
|
77
|
+
| `request` | RequestCollector | `@rudderjs/router` | Incoming HTTP requests and responses |
|
|
78
|
+
| `query` | QueryCollector | `@rudderjs/orm` | Database queries (flags slow queries above threshold) |
|
|
79
|
+
| `job` | JobCollector | `@rudderjs/queue` | Queue job dispatch and execution |
|
|
80
|
+
| `exception` | ExceptionCollector | `@rudderjs/core` | Unhandled exceptions |
|
|
81
|
+
| `log` | LogCollector | `@rudderjs/log` | Log messages across all channels |
|
|
82
|
+
| `mail` | MailCollector | `@rudderjs/mail` | Sent emails |
|
|
83
|
+
| `notification` | NotificationCollector | `@rudderjs/notification` | Dispatched notifications |
|
|
84
|
+
| `event` | EventCollector | `@rudderjs/core` | Dispatched events with listener list |
|
|
85
|
+
| `cache` | CacheCollector | `@rudderjs/cache` | Cache hits, misses, writes, forgets |
|
|
86
|
+
| `schedule` | ScheduleCollector | `@rudderjs/schedule` | Scheduled task execution with output |
|
|
87
|
+
| `model` | ModelCollector | `@rudderjs/orm` | Model create/update/delete with dirty attributes diff |
|
|
88
|
+
| `command` | CommandCollector | `@rudderjs/rudder` | CLI command invocations with args, duration, exit code |
|
|
89
|
+
| `http` | HttpCollector | `@rudderjs/http` | Outgoing HTTP requests with timing, headers, response body |
|
|
90
|
+
| `gate` | GateCollector | `@rudderjs/auth` | Authorization decisions — ability, allowed/denied, resolution path (ability/policy/before), timing |
|
|
91
|
+
| `dump` | DumpCollector | `@rudderjs/support` | `dump()` and `dd()` calls with arguments and caller location |
|
|
92
|
+
|
|
93
|
+
### Real-time watchers (differentiators — Laravel Telescope doesn't have these)
|
|
94
|
+
|
|
95
|
+
| Type | Collector | Source | Description |
|
|
96
|
+
|------|-----------|--------|-------------|
|
|
97
|
+
| `broadcast` | BroadcastCollector | `@rudderjs/broadcast` | Full WebSocket lifecycle — connections, subscriptions, presence, broadcasts, auth failures. Grouped by `connectionId`. |
|
|
98
|
+
| `live` | LiveCollector | `@rudderjs/live` | Yjs CRDT debugging — document open/close, updates applied, awareness changes (throttled), persistence events, sync errors |
|
|
69
99
|
|
|
70
100
|
## Storage Drivers
|
|
71
101
|
|
|
@@ -74,6 +104,8 @@ Telescope records 11 entry types:
|
|
|
74
104
|
|
|
75
105
|
## Configuration
|
|
76
106
|
|
|
107
|
+
Every collector can be toggled independently:
|
|
108
|
+
|
|
77
109
|
```ts
|
|
78
110
|
// config/telescope.ts
|
|
79
111
|
export default {
|
|
@@ -83,6 +115,8 @@ export default {
|
|
|
83
115
|
sqlitePath: '.telescope.db',
|
|
84
116
|
maxEntries: 1000,
|
|
85
117
|
pruneAfterHours: 24,
|
|
118
|
+
|
|
119
|
+
// Core watchers
|
|
86
120
|
recordRequests: true,
|
|
87
121
|
recordQueries: true,
|
|
88
122
|
recordJobs: true,
|
|
@@ -94,18 +128,58 @@ export default {
|
|
|
94
128
|
recordCache: true,
|
|
95
129
|
recordSchedule: true,
|
|
96
130
|
recordModels: true,
|
|
131
|
+
recordCommands: true,
|
|
132
|
+
recordHttp: true,
|
|
133
|
+
recordGate: true,
|
|
134
|
+
recordDumps: true,
|
|
135
|
+
|
|
136
|
+
// Real-time watchers
|
|
137
|
+
recordBroadcasts: true,
|
|
138
|
+
recordLive: true,
|
|
139
|
+
liveAwarenessSampleMs: 500, // throttle Yjs awareness events
|
|
140
|
+
|
|
141
|
+
// Filtering
|
|
97
142
|
ignoreRequests: ['/telescope*', '/health'],
|
|
98
|
-
slowQueryThreshold: 100,
|
|
143
|
+
slowQueryThreshold: 100, // ms
|
|
144
|
+
|
|
145
|
+
// Sensitive data redaction (at collection time, never stored)
|
|
146
|
+
hideRequestHeaders: ['authorization', 'cookie', 'set-cookie', 'x-csrf-token', 'x-api-key'],
|
|
147
|
+
hideRequestFields: ['password', 'password_confirmation', 'token', 'secret'],
|
|
148
|
+
|
|
149
|
+
// Auth gate for the dashboard
|
|
99
150
|
auth: null,
|
|
100
151
|
} satisfies TelescopeConfig
|
|
101
152
|
```
|
|
102
153
|
|
|
103
|
-
##
|
|
154
|
+
## Custom routes registration
|
|
155
|
+
|
|
156
|
+
For packages or apps that need manual control over telescope routes:
|
|
157
|
+
|
|
158
|
+
```ts
|
|
159
|
+
import { registerTelescopeRoutes } from '@rudderjs/telescope'
|
|
160
|
+
|
|
161
|
+
await registerTelescopeRoutes(storage, {
|
|
162
|
+
path: 'telescope',
|
|
163
|
+
auth: (req) => req.user?.isAdmin ?? false,
|
|
164
|
+
middleware: [myCustomMiddleware],
|
|
165
|
+
})
|
|
166
|
+
```
|
|
167
|
+
|
|
168
|
+
## API
|
|
169
|
+
|
|
170
|
+
The dashboard UI is built on a JSON API that you can use directly to build custom UIs:
|
|
104
171
|
|
|
105
|
-
|
|
172
|
+
| Endpoint | Description |
|
|
173
|
+
|----------|-------------|
|
|
174
|
+
| `GET /telescope/api/overview` | Count per entry type |
|
|
175
|
+
| `GET /telescope/api/{type}s` | List entries (supports `?page`, `?tag`, `?search`) |
|
|
176
|
+
| `GET /telescope/api/{type}s/:id` | Single entry |
|
|
177
|
+
| `GET /telescope/api/batches/:batchId` | All entries in a batch |
|
|
178
|
+
| `DELETE /telescope/api/entries` | Prune entries (supports `?type`) |
|
|
106
179
|
|
|
107
180
|
## Notes
|
|
108
181
|
|
|
109
|
-
- Auto-prune runs on a background interval
|
|
110
|
-
-
|
|
182
|
+
- Auto-prune runs on a background interval based on `pruneAfterHours`.
|
|
183
|
+
- All peer packages are optional — install only the ones you use, and only those collectors activate.
|
|
111
184
|
- `createEntry()` helper is exported for manually constructing entries.
|
|
185
|
+
- The observer-registry pattern means collectors never break the build if a peer package is absent — they fail gracefully via try/catch on dynamic import.
|
package/dist/api/routes.d.ts
CHANGED
|
@@ -1,7 +1,11 @@
|
|
|
1
|
-
import type {
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
export declare function
|
|
1
|
+
import type { AppRequest, AppResponse, MiddlewareHandler } from '@rudderjs/contracts';
|
|
2
|
+
import type { TelescopeStorage, TelescopeConfig, EntryType } from '../types.js';
|
|
3
|
+
export declare function listEntries(storage: TelescopeStorage, type: EntryType, req: AppRequest, res: AppResponse): Promise<void>;
|
|
4
|
+
export declare function showEntry(storage: TelescopeStorage, req: AppRequest, res: AppResponse): Promise<void>;
|
|
5
|
+
export declare function listBatch(storage: TelescopeStorage, req: AppRequest, res: AppResponse): Promise<void>;
|
|
6
|
+
export declare function overview(storage: TelescopeStorage, res: AppResponse): Promise<void>;
|
|
7
|
+
export declare function prune(storage: TelescopeStorage, req: AppRequest, res: AppResponse): Promise<void>;
|
|
8
|
+
export declare function getRecording(res: AppResponse): void;
|
|
9
|
+
export declare function toggleRecording(res: AppResponse): void;
|
|
10
|
+
export declare function authMiddleware(config: Pick<TelescopeConfig, 'auth'>): MiddlewareHandler;
|
|
7
11
|
//# sourceMappingURL=routes.d.ts.map
|
package/dist/api/routes.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"routes.d.ts","sourceRoot":"","sources":["../../src/api/routes.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"routes.d.ts","sourceRoot":"","sources":["../../src/api/routes.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,WAAW,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAA;AACrF,OAAO,KAAK,EAAE,gBAAgB,EAAE,eAAe,EAAE,SAAS,EAAE,MAAM,aAAa,CAAA;AAa/E,wBAAsB,WAAW,CAC/B,OAAO,EAAE,gBAAgB,EACzB,IAAI,EAAK,SAAS,EAClB,GAAG,EAAM,UAAU,EACnB,GAAG,EAAM,WAAW,GACnB,OAAO,CAAC,IAAI,CAAC,CAmBf;AAED,wBAAsB,SAAS,CAC7B,OAAO,EAAE,gBAAgB,EACzB,GAAG,EAAM,UAAU,EACnB,GAAG,EAAM,WAAW,GACnB,OAAO,CAAC,IAAI,CAAC,CAcf;AAED,wBAAsB,SAAS,CAC7B,OAAO,EAAE,gBAAgB,EACzB,GAAG,EAAM,UAAU,EACnB,GAAG,EAAM,WAAW,GACnB,OAAO,CAAC,IAAI,CAAC,CAIf;AAED,wBAAsB,QAAQ,CAC5B,OAAO,EAAE,gBAAgB,EACzB,GAAG,EAAM,WAAW,GACnB,OAAO,CAAC,IAAI,CAAC,CAMf;AAED,wBAAsB,KAAK,CACzB,OAAO,EAAE,gBAAgB,EACzB,GAAG,EAAM,UAAU,EACnB,GAAG,EAAM,WAAW,GACnB,OAAO,CAAC,IAAI,CAAC,CAQf;AAOD,wBAAgB,YAAY,CAC1B,GAAG,EAAE,WAAW,GACf,IAAI,CAEN;AAED,wBAAgB,eAAe,CAC7B,GAAG,EAAE,WAAW,GACf,IAAI,CAIN;AAID,wBAAgB,cAAc,CAAC,MAAM,EAAE,IAAI,CAAC,eAAe,EAAE,MAAM,CAAC,GAAG,iBAAiB,CAWvF"}
|
package/dist/api/routes.js
CHANGED
|
@@ -1,58 +1,13 @@
|
|
|
1
|
-
import { dashboardPage, requestsPage, queriesPage, jobsPage, exceptionsPage, logsPage, mailPage, notificationsPage, eventsPage, cachePage, schedulePage, modelsPage, } from '../ui/pages.js';
|
|
2
1
|
const ENTRY_TYPES = [
|
|
3
2
|
'request', 'query', 'job', 'exception', 'log',
|
|
4
|
-
'mail', 'notification', 'event', 'cache', 'schedule', 'model',
|
|
3
|
+
'mail', 'notification', 'event', 'cache', 'schedule', 'model', 'command', 'broadcast', 'live',
|
|
5
4
|
];
|
|
6
|
-
/**
|
|
7
|
-
* Register all Telescope API routes on the router.
|
|
8
|
-
* Called during the service provider's boot phase.
|
|
9
|
-
*/
|
|
10
|
-
export async function registerRoutes(storage, config) {
|
|
11
|
-
const { router } = await import('@rudderjs/router');
|
|
12
|
-
const basePath = `/${config.path ?? 'telescope'}`;
|
|
13
|
-
const prefix = `${basePath}/api`;
|
|
14
|
-
const middleware = config.auth ? [authMiddleware(config)] : [];
|
|
15
|
-
// ── UI Pages ─────────────────────────────────────────────
|
|
16
|
-
const html = (_req, res, content) => res.header('Content-Type', 'text/html').send(content);
|
|
17
|
-
router.get(basePath, (r, s) => html(r, s, dashboardPage(basePath, prefix)), middleware);
|
|
18
|
-
router.get(`${basePath}/requests`, (r, s) => html(r, s, requestsPage(basePath, prefix)), middleware);
|
|
19
|
-
router.get(`${basePath}/queries`, (r, s) => html(r, s, queriesPage(basePath, prefix)), middleware);
|
|
20
|
-
router.get(`${basePath}/jobs`, (r, s) => html(r, s, jobsPage(basePath, prefix)), middleware);
|
|
21
|
-
router.get(`${basePath}/exceptions`, (r, s) => html(r, s, exceptionsPage(basePath, prefix)), middleware);
|
|
22
|
-
router.get(`${basePath}/logs`, (r, s) => html(r, s, logsPage(basePath, prefix)), middleware);
|
|
23
|
-
router.get(`${basePath}/mail`, (r, s) => html(r, s, mailPage(basePath, prefix)), middleware);
|
|
24
|
-
router.get(`${basePath}/notifications`, (r, s) => html(r, s, notificationsPage(basePath, prefix)), middleware);
|
|
25
|
-
router.get(`${basePath}/events`, (r, s) => html(r, s, eventsPage(basePath, prefix)), middleware);
|
|
26
|
-
router.get(`${basePath}/cache`, (r, s) => html(r, s, cachePage(basePath, prefix)), middleware);
|
|
27
|
-
router.get(`${basePath}/schedule`, (r, s) => html(r, s, schedulePage(basePath, prefix)), middleware);
|
|
28
|
-
router.get(`${basePath}/models`, (r, s) => html(r, s, modelsPage(basePath, prefix)), middleware);
|
|
29
|
-
// ── List routes for each entry type ──────────────────────
|
|
30
|
-
for (const type of ENTRY_TYPES) {
|
|
31
|
-
router.get(`${prefix}/${type === 'query' ? 'queries' : `${type}s`}`, (req, res) => listEntries(storage, type, req, res), middleware);
|
|
32
|
-
router.get(`${prefix}/${type === 'query' ? 'queries' : `${type}s`}/:id`, (req, res) => showEntry(storage, req, res), middleware);
|
|
33
|
-
}
|
|
34
|
-
// ── Overview ─────────────────────────────────────────────
|
|
35
|
-
router.get(`${prefix}/overview`, async (_req, res) => {
|
|
36
|
-
const counts = {};
|
|
37
|
-
for (const type of ENTRY_TYPES) {
|
|
38
|
-
counts[type] = await storage.count(type);
|
|
39
|
-
}
|
|
40
|
-
res.json({ counts, total: await storage.count() });
|
|
41
|
-
}, middleware);
|
|
42
|
-
// ── Prune ────────────────────────────────────────────────
|
|
43
|
-
router.delete(`${prefix}/entries`, async (req, res) => {
|
|
44
|
-
const type = req.query['type'];
|
|
45
|
-
if (type && ENTRY_TYPES.includes(type)) {
|
|
46
|
-
await storage.prune(type);
|
|
47
|
-
}
|
|
48
|
-
else {
|
|
49
|
-
await storage.prune();
|
|
50
|
-
}
|
|
51
|
-
res.json({ message: 'Entries pruned.' });
|
|
52
|
-
}, middleware);
|
|
53
|
-
}
|
|
54
5
|
// ─── Handlers ──────────────────────────────────────────────
|
|
55
|
-
|
|
6
|
+
//
|
|
7
|
+
// Pure handler functions invoked from `../routes.ts`. Kept separate from
|
|
8
|
+
// route registration so they can be reused or unit-tested without spinning
|
|
9
|
+
// up a router.
|
|
10
|
+
export async function listEntries(storage, type, req, res) {
|
|
56
11
|
const page = parseInt(req.query['page'] ?? '1', 10);
|
|
57
12
|
const perPage = parseInt(req.query['per_page'] ?? '50', 10);
|
|
58
13
|
const tag = req.query['tag'];
|
|
@@ -70,7 +25,7 @@ async function listEntries(storage, type, req, res) {
|
|
|
70
25
|
},
|
|
71
26
|
});
|
|
72
27
|
}
|
|
73
|
-
async function showEntry(storage, req, res) {
|
|
28
|
+
export async function showEntry(storage, req, res) {
|
|
74
29
|
const entry = await storage.find(req.params['id'] ?? '');
|
|
75
30
|
if (!entry) {
|
|
76
31
|
res.status(404).json({ message: 'Entry not found.' });
|
|
@@ -83,8 +38,41 @@ async function showEntry(storage, req, res) {
|
|
|
83
38
|
}
|
|
84
39
|
res.json({ data: entry, related });
|
|
85
40
|
}
|
|
86
|
-
|
|
87
|
-
|
|
41
|
+
export async function listBatch(storage, req, res) {
|
|
42
|
+
const batchId = req.params['batchId'] ?? '';
|
|
43
|
+
const entries = await storage.list({ batchId, perPage: 500 });
|
|
44
|
+
res.json({ data: entries });
|
|
45
|
+
}
|
|
46
|
+
export async function overview(storage, res) {
|
|
47
|
+
const counts = {};
|
|
48
|
+
for (const type of ENTRY_TYPES) {
|
|
49
|
+
counts[type] = await storage.count(type);
|
|
50
|
+
}
|
|
51
|
+
res.json({ counts, total: await storage.count() });
|
|
52
|
+
}
|
|
53
|
+
export async function prune(storage, req, res) {
|
|
54
|
+
const type = req.query['type'];
|
|
55
|
+
if (type && ENTRY_TYPES.includes(type)) {
|
|
56
|
+
await storage.prune(type);
|
|
57
|
+
}
|
|
58
|
+
else {
|
|
59
|
+
await storage.prune();
|
|
60
|
+
}
|
|
61
|
+
res.json({ message: 'Entries pruned.' });
|
|
62
|
+
}
|
|
63
|
+
// ─── Recording Toggle ─────────────────────────────────────
|
|
64
|
+
const _g = globalThis;
|
|
65
|
+
const _recKey = '__rudderjs_telescope_recording__';
|
|
66
|
+
export function getRecording(res) {
|
|
67
|
+
res.json({ recording: _g[_recKey] ?? true });
|
|
68
|
+
}
|
|
69
|
+
export function toggleRecording(res) {
|
|
70
|
+
const recording = !(_g[_recKey] ?? true);
|
|
71
|
+
_g[_recKey] = recording;
|
|
72
|
+
res.json({ recording });
|
|
73
|
+
}
|
|
74
|
+
// ─── Auth Middleware ───────────────────────────────────────
|
|
75
|
+
export function authMiddleware(config) {
|
|
88
76
|
return async (req, res, next) => {
|
|
89
77
|
if (config.auth) {
|
|
90
78
|
const allowed = await config.auth(req);
|
package/dist/api/routes.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"routes.js","sourceRoot":"","sources":["../../src/api/routes.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"routes.js","sourceRoot":"","sources":["../../src/api/routes.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Lightweight request-scoped batchId propagation. Uses a simple global
|
|
3
|
+
* variable — works because Prisma's `$on('query')` callback fires
|
|
4
|
+
* synchronously during the query, within the same call stack as the
|
|
5
|
+
* request handler.
|
|
6
|
+
*
|
|
7
|
+
* The RequestCollector sets the batchId before `next()` and clears it
|
|
8
|
+
* after. Any collector that fires during the request (query, cache,
|
|
9
|
+
* model) can read it via `currentBatchId()`.
|
|
10
|
+
*/
|
|
11
|
+
/** Set the current batchId for the duration of a request. */
|
|
12
|
+
export declare function setBatchId(id: string | null): void;
|
|
13
|
+
/** Returns the current request's batchId, or `null` if not inside a request. */
|
|
14
|
+
export declare function currentBatchId(): string | null;
|
|
15
|
+
/** Returns `{ batchId }` if inside a request, or `{}` if not. Safe to spread into createEntry options. */
|
|
16
|
+
export declare function batchOpts(): {
|
|
17
|
+
batchId?: string;
|
|
18
|
+
};
|
|
19
|
+
//# sourceMappingURL=batch-context.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"batch-context.d.ts","sourceRoot":"","sources":["../src/batch-context.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAIH,6DAA6D;AAC7D,wBAAgB,UAAU,CAAC,EAAE,EAAE,MAAM,GAAG,IAAI,GAAG,IAAI,CAElD;AAED,gFAAgF;AAChF,wBAAgB,cAAc,IAAI,MAAM,GAAG,IAAI,CAE9C;AAED,0GAA0G;AAC1G,wBAAgB,SAAS,IAAI;IAAE,OAAO,CAAC,EAAE,MAAM,CAAA;CAAE,CAEhD"}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Lightweight request-scoped batchId propagation. Uses a simple global
|
|
3
|
+
* variable — works because Prisma's `$on('query')` callback fires
|
|
4
|
+
* synchronously during the query, within the same call stack as the
|
|
5
|
+
* request handler.
|
|
6
|
+
*
|
|
7
|
+
* The RequestCollector sets the batchId before `next()` and clears it
|
|
8
|
+
* after. Any collector that fires during the request (query, cache,
|
|
9
|
+
* model) can read it via `currentBatchId()`.
|
|
10
|
+
*/
|
|
11
|
+
let _currentBatchId = null;
|
|
12
|
+
/** Set the current batchId for the duration of a request. */
|
|
13
|
+
export function setBatchId(id) {
|
|
14
|
+
_currentBatchId = id;
|
|
15
|
+
}
|
|
16
|
+
/** Returns the current request's batchId, or `null` if not inside a request. */
|
|
17
|
+
export function currentBatchId() {
|
|
18
|
+
return _currentBatchId;
|
|
19
|
+
}
|
|
20
|
+
/** Returns `{ batchId }` if inside a request, or `{}` if not. Safe to spread into createEntry options. */
|
|
21
|
+
export function batchOpts() {
|
|
22
|
+
return _currentBatchId ? { batchId: _currentBatchId } : {};
|
|
23
|
+
}
|
|
24
|
+
//# sourceMappingURL=batch-context.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"batch-context.js","sourceRoot":"","sources":["../src/batch-context.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,IAAI,eAAe,GAAkB,IAAI,CAAA;AAEzC,6DAA6D;AAC7D,MAAM,UAAU,UAAU,CAAC,EAAiB;IAC1C,eAAe,GAAG,EAAE,CAAA;AACtB,CAAC;AAED,gFAAgF;AAChF,MAAM,UAAU,cAAc;IAC5B,OAAO,eAAe,CAAA;AACxB,CAAC;AAED,0GAA0G;AAC1G,MAAM,UAAU,SAAS;IACvB,OAAO,eAAe,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,eAAe,EAAE,CAAC,CAAC,CAAC,EAAE,CAAA;AAC5D,CAAC"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { Collector, TelescopeStorage, TelescopeConfig } from '../types.js';
|
|
2
|
+
/**
|
|
3
|
+
* Records AI agent executions by hooking into @rudderjs/ai's observer registry.
|
|
4
|
+
*/
|
|
5
|
+
export declare class AiCollector implements Collector {
|
|
6
|
+
private readonly storage;
|
|
7
|
+
private readonly config;
|
|
8
|
+
readonly name = "AI Collector";
|
|
9
|
+
readonly type: "ai";
|
|
10
|
+
constructor(storage: TelescopeStorage, config: TelescopeConfig);
|
|
11
|
+
register(): Promise<void>;
|
|
12
|
+
}
|
|
13
|
+
//# sourceMappingURL=ai.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ai.d.ts","sourceRoot":"","sources":["../../src/collectors/ai.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,gBAAgB,EAAE,eAAe,EAAE,MAAM,aAAa,CAAA;AAI/E;;GAEG;AACH,qBAAa,WAAY,YAAW,SAAS;IAKzC,OAAO,CAAC,QAAQ,CAAC,OAAO;IACxB,OAAO,CAAC,QAAQ,CAAC,MAAM;IALzB,QAAQ,CAAC,IAAI,kBAAiB;IAC9B,QAAQ,CAAC,IAAI,EAAG,IAAI,CAAS;gBAGV,OAAO,EAAE,gBAAgB,EACzB,MAAM,EAAG,eAAe;IAGrC,QAAQ,IAAI,OAAO,CAAC,IAAI,CAAC;CA+ChC"}
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import { createEntry } from '../storage.js';
|
|
2
|
+
import { batchOpts } from '../batch-context.js';
|
|
3
|
+
/**
|
|
4
|
+
* Records AI agent executions by hooking into @rudderjs/ai's observer registry.
|
|
5
|
+
*/
|
|
6
|
+
export class AiCollector {
|
|
7
|
+
storage;
|
|
8
|
+
config;
|
|
9
|
+
name = 'AI Collector';
|
|
10
|
+
type = 'ai';
|
|
11
|
+
constructor(storage, config) {
|
|
12
|
+
this.storage = storage;
|
|
13
|
+
this.config = config;
|
|
14
|
+
}
|
|
15
|
+
async register() {
|
|
16
|
+
try {
|
|
17
|
+
const mod = await import('@rudderjs/ai/observers');
|
|
18
|
+
const { aiObservers } = mod;
|
|
19
|
+
const storage = this.storage;
|
|
20
|
+
const threshold = this.config.slowAiThreshold ?? 5000;
|
|
21
|
+
aiObservers.subscribe((event) => {
|
|
22
|
+
const tags = [
|
|
23
|
+
`model:${event.model}`,
|
|
24
|
+
`provider:${event.provider}`,
|
|
25
|
+
`agent:${event.agentName}`,
|
|
26
|
+
];
|
|
27
|
+
if (event.kind === 'agent.failed')
|
|
28
|
+
tags.push('error');
|
|
29
|
+
if (event.duration > threshold)
|
|
30
|
+
tags.push('slow');
|
|
31
|
+
if (event.streaming)
|
|
32
|
+
tags.push('streaming');
|
|
33
|
+
const toolCalls = event.steps.flatMap(s => s.toolCalls);
|
|
34
|
+
if (toolCalls.length > 0)
|
|
35
|
+
tags.push('has_tools');
|
|
36
|
+
storage.store(createEntry('ai', {
|
|
37
|
+
kind: event.kind,
|
|
38
|
+
agentName: event.agentName,
|
|
39
|
+
model: event.model,
|
|
40
|
+
provider: event.provider,
|
|
41
|
+
input: event.input,
|
|
42
|
+
output: event.output,
|
|
43
|
+
steps: event.steps,
|
|
44
|
+
tokens: event.tokens,
|
|
45
|
+
duration: event.duration,
|
|
46
|
+
finishReason: event.finishReason,
|
|
47
|
+
streaming: event.streaming,
|
|
48
|
+
conversationId: event.conversationId,
|
|
49
|
+
failoverAttempts: event.failoverAttempts,
|
|
50
|
+
toolCallCount: toolCalls.length,
|
|
51
|
+
toolCalls,
|
|
52
|
+
error: event.kind === 'agent.failed' ? event.error : undefined,
|
|
53
|
+
}, { tags, ...batchOpts() }));
|
|
54
|
+
});
|
|
55
|
+
}
|
|
56
|
+
catch {
|
|
57
|
+
// @rudderjs/ai not installed — skip
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
//# sourceMappingURL=ai.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ai.js","sourceRoot":"","sources":["../../src/collectors/ai.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,WAAW,EAAE,MAAM,eAAe,CAAA;AAC3C,OAAO,EAAE,SAAS,EAAE,MAAM,qBAAqB,CAAA;AAE/C;;GAEG;AACH,MAAM,OAAO,WAAW;IAKH;IACA;IALV,IAAI,GAAG,cAAc,CAAA;IACrB,IAAI,GAAG,IAAa,CAAA;IAE7B,YACmB,OAAyB,EACzB,MAAwB;QADxB,YAAO,GAAP,OAAO,CAAkB;QACzB,WAAM,GAAN,MAAM,CAAkB;IACxC,CAAC;IAEJ,KAAK,CAAC,QAAQ;QACZ,IAAI,CAAC;YACH,MAAM,GAAG,GAAG,MAAM,MAAM,CAAC,wBAAwB,CAEhD,CAAA;YACD,MAAM,EAAE,WAAW,EAAE,GAAG,GAAG,CAAA;YAE3B,MAAM,OAAO,GAAK,IAAI,CAAC,OAAO,CAAA;YAC9B,MAAM,SAAS,GAAG,IAAI,CAAC,MAAM,CAAC,eAAe,IAAI,IAAI,CAAA;YAErD,WAAW,CAAC,SAAS,CAAC,CAAC,KAAc,EAAE,EAAE;gBACvC,MAAM,IAAI,GAAa;oBACrB,SAAS,KAAK,CAAC,KAAK,EAAE;oBACtB,YAAY,KAAK,CAAC,QAAQ,EAAE;oBAC5B,SAAS,KAAK,CAAC,SAAS,EAAE;iBAC3B,CAAA;gBAED,IAAI,KAAK,CAAC,IAAI,KAAK,cAAc;oBAAE,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,CAAA;gBACrD,IAAI,KAAK,CAAC,QAAQ,GAAG,SAAS;oBAAK,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,CAAA;gBACpD,IAAI,KAAK,CAAC,SAAS;oBAAgB,IAAI,CAAC,IAAI,CAAC,WAAW,CAAC,CAAA;gBAEzD,MAAM,SAAS,GAAG,KAAK,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,SAAS,CAAC,CAAA;gBACvD,IAAI,SAAS,CAAC,MAAM,GAAG,CAAC;oBAAE,IAAI,CAAC,IAAI,CAAC,WAAW,CAAC,CAAA;gBAEhD,OAAO,CAAC,KAAK,CAAC,WAAW,CAAC,IAAI,EAAE;oBAC9B,IAAI,EAAc,KAAK,CAAC,IAAI;oBAC5B,SAAS,EAAS,KAAK,CAAC,SAAS;oBACjC,KAAK,EAAa,KAAK,CAAC,KAAK;oBAC7B,QAAQ,EAAU,KAAK,CAAC,QAAQ;oBAChC,KAAK,EAAa,KAAK,CAAC,KAAK;oBAC7B,MAAM,EAAY,KAAK,CAAC,MAAM;oBAC9B,KAAK,EAAa,KAAK,CAAC,KAAK;oBAC7B,MAAM,EAAY,KAAK,CAAC,MAAM;oBAC9B,QAAQ,EAAU,KAAK,CAAC,QAAQ;oBAChC,YAAY,EAAM,KAAK,CAAC,YAAY;oBACpC,SAAS,EAAS,KAAK,CAAC,SAAS;oBACjC,cAAc,EAAI,KAAK,CAAC,cAAc;oBACtC,gBAAgB,EAAE,KAAK,CAAC,gBAAgB;oBACxC,aAAa,EAAK,SAAS,CAAC,MAAM;oBAClC,SAAS;oBACT,KAAK,EAAa,KAAK,CAAC,IAAI,KAAK,cAAc,CAAC,CAAC,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,SAAS;iBAC1E,EAAE,EAAE,IAAI,EAAE,GAAG,SAAS,EAAE,EAAE,CAAC,CAAC,CAAA;YAC/B,CAAC,CAAC,CAAA;QACJ,CAAC;QAAC,MAAM,CAAC;YACP,oCAAoC;QACtC,CAAC;IACH,CAAC;CACF"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { Collector, TelescopeStorage } from '../types.js';
|
|
2
|
+
export declare class BroadcastCollector implements Collector {
|
|
3
|
+
private readonly storage;
|
|
4
|
+
readonly name = "Broadcast Collector";
|
|
5
|
+
readonly type: "broadcast";
|
|
6
|
+
constructor(storage: TelescopeStorage);
|
|
7
|
+
register(): Promise<void>;
|
|
8
|
+
private record;
|
|
9
|
+
}
|
|
10
|
+
//# sourceMappingURL=broadcast.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"broadcast.d.ts","sourceRoot":"","sources":["../../src/collectors/broadcast.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAA;AA0B9D,qBAAa,kBAAmB,YAAW,SAAS;IAItC,OAAO,CAAC,QAAQ,CAAC,OAAO;IAHpC,QAAQ,CAAC,IAAI,yBAAwB;IACrC,QAAQ,CAAC,IAAI,EAAG,WAAW,CAAS;gBAEP,OAAO,EAAE,gBAAgB;IAEhD,QAAQ,IAAI,OAAO,CAAC,IAAI,CAAC;IAW/B,OAAO,CAAC,MAAM;CA4Bf"}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import { createEntry } from '../storage.js';
|
|
2
|
+
export class BroadcastCollector {
|
|
3
|
+
storage;
|
|
4
|
+
name = 'Broadcast Collector';
|
|
5
|
+
type = 'broadcast';
|
|
6
|
+
constructor(storage) {
|
|
7
|
+
this.storage = storage;
|
|
8
|
+
}
|
|
9
|
+
async register() {
|
|
10
|
+
try {
|
|
11
|
+
const { broadcastObservers } = await import('@rudderjs/broadcast');
|
|
12
|
+
broadcastObservers.subscribe((event) => this.record(event));
|
|
13
|
+
}
|
|
14
|
+
catch {
|
|
15
|
+
// @rudderjs/broadcast not installed — skip
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
record(event) {
|
|
19
|
+
const tags = [`kind:${event.kind}`];
|
|
20
|
+
// Subscribe events get extra status tags so the dashboard can
|
|
21
|
+
// distinguish allowed/denied at a glance.
|
|
22
|
+
if (event.kind === 'subscribe') {
|
|
23
|
+
tags.push(event['allowed'] ? 'allowed' : 'denied');
|
|
24
|
+
if (event['channelType'])
|
|
25
|
+
tags.push(`channel:${event['channelType']}`);
|
|
26
|
+
}
|
|
27
|
+
if (event.kind === 'broadcast' && event['source']) {
|
|
28
|
+
tags.push(`source:${event['source']}`);
|
|
29
|
+
}
|
|
30
|
+
if (event.kind === 'connection.opened' || event.kind === 'connection.closed') {
|
|
31
|
+
tags.push(event.kind === 'connection.opened' ? 'opened' : 'closed');
|
|
32
|
+
}
|
|
33
|
+
// Use connectionId as the batchId so the existing batch grouping UI
|
|
34
|
+
// (Phase 2b) works for WebSocket connections too — clicking through
|
|
35
|
+
// a connection.opened entry shows every event from that socket.
|
|
36
|
+
const opts = { tags };
|
|
37
|
+
const connectionId = event['connectionId'];
|
|
38
|
+
if (connectionId)
|
|
39
|
+
opts.batchId = connectionId;
|
|
40
|
+
// Strip the kind from content (it's already in the entry-type metadata)
|
|
41
|
+
// but keep everything else verbatim.
|
|
42
|
+
const { kind: _kind, ...content } = event;
|
|
43
|
+
this.storage.store(createEntry('broadcast', { kind: event.kind, ...content }, opts));
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
//# sourceMappingURL=broadcast.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"broadcast.js","sourceRoot":"","sources":["../../src/collectors/broadcast.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,WAAW,EAAE,MAAM,eAAe,CAAA;AAyB3C,MAAM,OAAO,kBAAkB;IAIA;IAHpB,IAAI,GAAG,qBAAqB,CAAA;IAC5B,IAAI,GAAG,WAAoB,CAAA;IAEpC,YAA6B,OAAyB;QAAzB,YAAO,GAAP,OAAO,CAAkB;IAAG,CAAC;IAE1D,KAAK,CAAC,QAAQ;QACZ,IAAI,CAAC;YACH,MAAM,EAAE,kBAAkB,EAAE,GAAG,MAAM,MAAM,CAAC,qBAAqB,CAEhE,CAAA;YACD,kBAAkB,CAAC,SAAS,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAA;QAC7D,CAAC;QAAC,MAAM,CAAC;YACP,2CAA2C;QAC7C,CAAC;IACH,CAAC;IAEO,MAAM,CAAC,KAAqB;QAClC,MAAM,IAAI,GAAa,CAAC,QAAQ,KAAK,CAAC,IAAI,EAAE,CAAC,CAAA;QAE7C,8DAA8D;QAC9D,0CAA0C;QAC1C,IAAI,KAAK,CAAC,IAAI,KAAK,WAAW,EAAE,CAAC;YAC/B,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAA;YAClD,IAAI,KAAK,CAAC,aAAa,CAAC;gBAAE,IAAI,CAAC,IAAI,CAAC,WAAW,KAAK,CAAC,aAAa,CAAC,EAAE,CAAC,CAAA;QACxE,CAAC;QACD,IAAI,KAAK,CAAC,IAAI,KAAK,WAAW,IAAI,KAAK,CAAC,QAAQ,CAAC,EAAE,CAAC;YAClD,IAAI,CAAC,IAAI,CAAC,UAAU,KAAK,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAA;QACxC,CAAC;QACD,IAAI,KAAK,CAAC,IAAI,KAAK,mBAAmB,IAAI,KAAK,CAAC,IAAI,KAAK,mBAAmB,EAAE,CAAC;YAC7E,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,KAAK,mBAAmB,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAA;QACrE,CAAC;QAED,oEAAoE;QACpE,oEAAoE;QACpE,gEAAgE;QAChE,MAAM,IAAI,GAAyC,EAAE,IAAI,EAAE,CAAA;QAC3D,MAAM,YAAY,GAAG,KAAK,CAAC,cAAc,CAAuB,CAAA;QAChE,IAAI,YAAY;YAAE,IAAI,CAAC,OAAO,GAAG,YAAY,CAAA;QAE7C,wEAAwE;QACxE,qCAAqC;QACrC,MAAM,EAAE,IAAI,EAAE,KAAK,EAAE,GAAG,OAAO,EAAE,GAAG,KAAK,CAAA;QACzC,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC,WAAW,CAAC,WAAW,EAAE,EAAE,IAAI,EAAE,KAAK,CAAC,IAAI,EAAE,GAAG,OAAO,EAAE,EAAE,IAAI,CAAC,CAAC,CAAA;IACtF,CAAC;CACF"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cache.d.ts","sourceRoot":"","sources":["../../src/collectors/cache.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAA;
|
|
1
|
+
{"version":3,"file":"cache.d.ts","sourceRoot":"","sources":["../../src/collectors/cache.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAA;AAI9D;;;GAGG;AACH,qBAAa,cAAe,YAAW,SAAS;IAIlC,OAAO,CAAC,QAAQ,CAAC,OAAO;IAHpC,QAAQ,CAAC,IAAI,qBAAoB;IACjC,QAAQ,CAAC,IAAI,EAAG,OAAO,CAAS;gBAEH,OAAO,EAAE,gBAAgB;IAEhD,QAAQ,IAAI,OAAO,CAAC,IAAI,CAAC;CAsChC"}
|
package/dist/collectors/cache.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { createEntry } from '../storage.js';
|
|
2
|
+
import { batchOpts } from '../batch-context.js';
|
|
2
3
|
/**
|
|
3
4
|
* Records cache operations by wrapping the CacheRegistry adapter methods.
|
|
4
5
|
* Intercepts get/set/forget/flush and records hit/miss/set/forget ops.
|
|
@@ -24,20 +25,20 @@ export class CacheCollector {
|
|
|
24
25
|
original.get = async (key) => {
|
|
25
26
|
const value = await origGet(key);
|
|
26
27
|
const op = value !== null ? 'hit' : 'miss';
|
|
27
|
-
storage.store(createEntry('cache', { key, operation: op }, { tags: [`cache:${op}`] }));
|
|
28
|
+
storage.store(createEntry('cache', { key, operation: op }, { tags: [`cache:${op}`], ...batchOpts() }));
|
|
28
29
|
return value;
|
|
29
30
|
};
|
|
30
31
|
original.set = async (key, value, ttl) => {
|
|
31
32
|
await origSet(key, value, ttl);
|
|
32
|
-
storage.store(createEntry('cache', { key, operation: 'set', ttl }, { tags: ['cache:set'] }));
|
|
33
|
+
storage.store(createEntry('cache', { key, operation: 'set', ttl }, { tags: ['cache:set'], ...batchOpts() }));
|
|
33
34
|
};
|
|
34
35
|
original.forget = async (key) => {
|
|
35
36
|
await origForget(key);
|
|
36
|
-
storage.store(createEntry('cache', { key, operation: 'forget' }, { tags: ['cache:forget'] }));
|
|
37
|
+
storage.store(createEntry('cache', { key, operation: 'forget' }, { tags: ['cache:forget'], ...batchOpts() }));
|
|
37
38
|
};
|
|
38
39
|
original.flush = async () => {
|
|
39
40
|
await origFlush();
|
|
40
|
-
storage.store(createEntry('cache', { operation: 'flush' }, { tags: ['cache:flush'] }));
|
|
41
|
+
storage.store(createEntry('cache', { operation: 'flush' }, { tags: ['cache:flush'], ...batchOpts() }));
|
|
41
42
|
};
|
|
42
43
|
}
|
|
43
44
|
catch {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cache.js","sourceRoot":"","sources":["../../src/collectors/cache.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,WAAW,EAAE,MAAM,eAAe,CAAA;
|
|
1
|
+
{"version":3,"file":"cache.js","sourceRoot":"","sources":["../../src/collectors/cache.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,WAAW,EAAE,MAAM,eAAe,CAAA;AAC3C,OAAO,EAAE,SAAS,EAAE,MAAM,qBAAqB,CAAA;AAE/C;;;GAGG;AACH,MAAM,OAAO,cAAc;IAII;IAHpB,IAAI,GAAG,iBAAiB,CAAA;IACxB,IAAI,GAAG,OAAgB,CAAA;IAEhC,YAA6B,OAAyB;QAAzB,YAAO,GAAP,OAAO,CAAkB;IAAG,CAAC;IAE1D,KAAK,CAAC,QAAQ;QACZ,IAAI,CAAC;YACH,MAAM,EAAE,aAAa,EAAE,GAAG,MAAM,MAAM,CAAC,iBAAiB,CAAC,CAAA;YACzD,MAAM,QAAQ,GAAG,aAAa,CAAC,GAAG,EAAE,CAAA;YACpC,IAAI,CAAC,QAAQ;gBAAE,OAAM;YAErB,MAAM,OAAO,GAAG,IAAI,CAAC,OAAO,CAAA;YAE5B,MAAM,OAAO,GAAM,QAAQ,CAAC,GAAG,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAA;YAC9C,MAAM,OAAO,GAAM,QAAQ,CAAC,GAAG,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAA;YAC9C,MAAM,UAAU,GAAG,QAAQ,CAAC,MAAM,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAA;YACjD,MAAM,SAAS,GAAI,QAAQ,CAAC,KAAK,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAA;YAEhD,QAAQ,CAAC,GAAG,GAAG,KAAK,EAAe,GAAW,EAAqB,EAAE;gBACnE,MAAM,KAAK,GAAG,MAAO,OAA8C,CAAC,GAAG,CAAC,CAAA;gBACxE,MAAM,EAAE,GAAG,KAAK,KAAK,IAAI,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,CAAA;gBAC1C,OAAO,CAAC,KAAK,CAAC,WAAW,CAAC,OAAO,EAAE,EAAE,GAAG,EAAE,SAAS,EAAE,EAAE,EAAE,EAAE,EAAE,IAAI,EAAE,CAAC,SAAS,EAAE,EAAE,CAAC,EAAE,GAAG,SAAS,EAAE,EAAE,CAAC,CAAC,CAAA;gBACtG,OAAO,KAAK,CAAA;YACd,CAAC,CAAA;YAED,QAAQ,CAAC,GAAG,GAAG,KAAK,EAAE,GAAW,EAAE,KAAc,EAAE,GAAY,EAAiB,EAAE;gBAChF,MAAO,OAAwE,CAAC,GAAG,EAAE,KAAK,EAAE,GAAG,CAAC,CAAA;gBAChG,OAAO,CAAC,KAAK,CAAC,WAAW,CAAC,OAAO,EAAE,EAAE,GAAG,EAAE,SAAS,EAAE,KAAK,EAAE,GAAG,EAAE,EAAE,EAAE,IAAI,EAAE,CAAC,WAAW,CAAC,EAAE,GAAG,SAAS,EAAE,EAAE,CAAC,CAAC,CAAA;YAC9G,CAAC,CAAA;YAED,QAAQ,CAAC,MAAM,GAAG,KAAK,EAAE,GAAW,EAAiB,EAAE;gBACrD,MAAO,UAA6C,CAAC,GAAG,CAAC,CAAA;gBACzD,OAAO,CAAC,KAAK,CAAC,WAAW,CAAC,OAAO,EAAE,EAAE,GAAG,EAAE,SAAS,EAAE,QAAQ,EAAE,EAAE,EAAE,IAAI,EAAE,CAAC,cAAc,CAAC,EAAE,GAAG,SAAS,EAAE,EAAE,CAAC,CAAC,CAAA;YAC/G,CAAC,CAAA;YAED,QAAQ,CAAC,KAAK,GAAG,KAAK,IAAmB,EAAE;gBACzC,MAAO,SAAiC,EAAE,CAAA;gBAC1C,OAAO,CAAC,KAAK,CAAC,WAAW,CAAC,OAAO,EAAE,EAAE,SAAS,EAAE,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,CAAC,aAAa,CAAC,EAAE,GAAG,SAAS,EAAE,EAAE,CAAC,CAAC,CAAA;YACxG,CAAC,CAAA;QACH,CAAC;QAAC,MAAM,CAAC;YACP,uCAAuC;QACzC,CAAC;IACH,CAAC;CACF"}
|