@djangocfg/monitor 2.1.216

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.
Files changed (62) hide show
  1. package/README.md +341 -0
  2. package/dist/client.cjs +1273 -0
  3. package/dist/client.cjs.map +1 -0
  4. package/dist/client.d.cts +123 -0
  5. package/dist/client.d.ts +123 -0
  6. package/dist/client.mjs +1243 -0
  7. package/dist/client.mjs.map +1 -0
  8. package/dist/index.cjs +18 -0
  9. package/dist/index.cjs.map +1 -0
  10. package/dist/index.d.cts +101 -0
  11. package/dist/index.d.ts +101 -0
  12. package/dist/index.mjs +1 -0
  13. package/dist/index.mjs.map +1 -0
  14. package/dist/server.cjs +947 -0
  15. package/dist/server.cjs.map +1 -0
  16. package/dist/server.d.cts +117 -0
  17. package/dist/server.d.ts +117 -0
  18. package/dist/server.mjs +917 -0
  19. package/dist/server.mjs.map +1 -0
  20. package/package.json +82 -0
  21. package/src/.claude/.sidecar/activity.jsonl +1 -0
  22. package/src/.claude/.sidecar/map_cache.json +38 -0
  23. package/src/.claude/.sidecar/usage.json +5 -0
  24. package/src/.claude/project-map.md +29 -0
  25. package/src/_api/BaseClient.ts +18 -0
  26. package/src/_api/generated/cfg_monitor/CLAUDE.md +60 -0
  27. package/src/_api/generated/cfg_monitor/_utils/fetchers/index.ts +30 -0
  28. package/src/_api/generated/cfg_monitor/_utils/fetchers/monitor.ts +51 -0
  29. package/src/_api/generated/cfg_monitor/_utils/hooks/index.ts +30 -0
  30. package/src/_api/generated/cfg_monitor/_utils/hooks/monitor.ts +43 -0
  31. package/src/_api/generated/cfg_monitor/_utils/schemas/FrontendEventIngestRequest.schema.ts +34 -0
  32. package/src/_api/generated/cfg_monitor/_utils/schemas/IngestBatchRequest.schema.ts +20 -0
  33. package/src/_api/generated/cfg_monitor/_utils/schemas/index.ts +22 -0
  34. package/src/_api/generated/cfg_monitor/api-instance.ts +181 -0
  35. package/src/_api/generated/cfg_monitor/client.ts +322 -0
  36. package/src/_api/generated/cfg_monitor/enums.ts +36 -0
  37. package/src/_api/generated/cfg_monitor/errors.ts +118 -0
  38. package/src/_api/generated/cfg_monitor/http.ts +137 -0
  39. package/src/_api/generated/cfg_monitor/index.ts +317 -0
  40. package/src/_api/generated/cfg_monitor/logger.ts +261 -0
  41. package/src/_api/generated/cfg_monitor/monitor/client.ts +25 -0
  42. package/src/_api/generated/cfg_monitor/monitor/index.ts +4 -0
  43. package/src/_api/generated/cfg_monitor/monitor/models.ts +48 -0
  44. package/src/_api/generated/cfg_monitor/retry.ts +177 -0
  45. package/src/_api/generated/cfg_monitor/schema.json +184 -0
  46. package/src/_api/generated/cfg_monitor/storage.ts +163 -0
  47. package/src/_api/generated/cfg_monitor/validation-events.ts +135 -0
  48. package/src/_api/index.ts +6 -0
  49. package/src/client/capture/console.ts +72 -0
  50. package/src/client/capture/fingerprint.ts +27 -0
  51. package/src/client/capture/js-errors.ts +70 -0
  52. package/src/client/capture/network.ts +47 -0
  53. package/src/client/capture/session.ts +33 -0
  54. package/src/client/capture/validation.ts +38 -0
  55. package/src/client/index.ts +72 -0
  56. package/src/client/store/index.ts +41 -0
  57. package/src/client/transport/ingest.ts +31 -0
  58. package/src/index.ts +12 -0
  59. package/src/server/index.ts +85 -0
  60. package/src/types/config.ts +33 -0
  61. package/src/types/events.ts +5 -0
  62. package/src/types/index.ts +6 -0
package/README.md ADDED
@@ -0,0 +1,341 @@
1
+ # @djangocfg/monitor
2
+
3
+ Browser error and event monitoring SDK for django-cfg backends.
4
+
5
+ **Part of [DjangoCFG](https://djangocfg.com)** — modern Django framework for production-ready SaaS applications.
6
+
7
+ ## Install
8
+
9
+ ```bash
10
+ pnpm add @djangocfg/monitor
11
+ ```
12
+
13
+ ## What's Inside
14
+
15
+ - **JS Error Capture** — `window.onerror` + `unhandledrejection` with SHA-256 fingerprinting
16
+ - **Console Capture** — intercepts `console.warn` / `console.error` (consola reporter or native patch)
17
+ - **Network Monitoring** — `monitoredFetch` wrapper reports non-2xx responses
18
+ - **Zod Validation Errors** — listens to `zod-validation-error` custom events (auto-integrates with `@djangocfg/api`)
19
+ - **Session Tracking** — anonymous `fm_session_id` UUID in localStorage + cookie
20
+ - **Server-side Capture** — Node.js / Edge Runtime safe, no browser APIs
21
+ - **Auto-flush** — batched delivery via generated API client; `KeepAliveFetchAdapter` survives page unload
22
+ - **Type-safe** — types generated from Django OpenAPI schema via `make gen`
23
+
24
+ ## Entry Points
25
+
26
+ | Entry | Import | Description |
27
+ |-------|--------|-------------|
28
+ | **Main** | `@djangocfg/monitor` | Types only, server-safe |
29
+ | **Client** | `@djangocfg/monitor/client` | Browser SDK (`"use client"`) |
30
+ | **Server** | `@djangocfg/monitor/server` | Node.js / Edge Runtime |
31
+
32
+ ## Package Structure
33
+
34
+ ```
35
+ src/
36
+ ├── _api/
37
+ │ ├── BaseClient.ts # monitorApi singleton (MemoryStorageAdapter)
38
+ │ ├── index.ts # Re-exports types, enums, monitorApi
39
+ │ └── generated/
40
+ │ └── cfg_monitor/ # Auto-generated — do not edit
41
+ │ ├── http.ts # FetchAdapter, KeepAliveFetchAdapter
42
+ │ └── ...
43
+ ├── types/
44
+ │ ├── events.ts # EventType, EventLevel, MonitorEvent
45
+ │ └── config.ts # MonitorConfig, ServerMonitorConfig
46
+ ├── client/
47
+ │ ├── index.ts # FrontendMonitor, monitoredFetch, getSessionId
48
+ │ ├── capture/
49
+ │ │ ├── js-errors.ts # window.onerror + unhandledrejection
50
+ │ │ ├── console.ts # consola reporter / console.* patch
51
+ │ │ ├── network.ts # monitoredFetch wrapper
52
+ │ │ ├── validation.ts # zod-validation-error CustomEvent listener
53
+ │ │ ├── session.ts # UUID session management
54
+ │ │ └── fingerprint.ts # SHA-256 deduplication fingerprint
55
+ │ ├── store/
56
+ │ │ └── index.ts # zustand vanilla event buffer
57
+ │ └── transport/
58
+ │ └── ingest.ts # sendBatch via monitorApi / KeepAliveFetchAdapter
59
+ ├── server/
60
+ │ └── index.ts # serverMonitor singleton
61
+ └── index.ts # Types-only re-export
62
+ ```
63
+
64
+ ## How It Works
65
+
66
+ All transport uses the **generated API client** (`monitorApi`) — no hardcoded URLs or raw `fetch` calls.
67
+
68
+ - **Normal flush** → `monitorApi.monitor.ingestCreate(batch)` (standard `FetchAdapter`)
69
+ - **Page unload flush** → separate `monitorApiBeacon` instance with `KeepAliveFetchAdapter` — sets `keepalive: true` on every request, so the browser completes delivery even after navigation
70
+
71
+ **Automatic error collection** (no extra setup after `FrontendMonitor.init()`):
72
+
73
+ | Source | Mechanism |
74
+ |--------|-----------|
75
+ | JS exceptions | `window.onerror` + `unhandledrejection` |
76
+ | Console warnings/errors | consola reporter or `console.*` patch |
77
+ | `@djangocfg/api` Zod failures | `zod-validation-error` CustomEvent |
78
+ | Network errors | `monitoredFetch` wrapper |
79
+ | Server exceptions | `serverMonitor.captureError()` |
80
+
81
+ ## Client Usage (React / Next.js)
82
+
83
+ ### MonitorProvider
84
+
85
+ ```tsx
86
+ // components/MonitorProvider.tsx
87
+ 'use client'
88
+
89
+ import { useEffect } from 'react'
90
+ import { FrontendMonitor } from '@djangocfg/monitor/client'
91
+
92
+ export function MonitorProvider() {
93
+ useEffect(() => {
94
+ FrontendMonitor.init({
95
+ project: process.env.NEXT_PUBLIC_PROJECT_NAME ?? 'my-app',
96
+ environment: process.env.NODE_ENV,
97
+ // baseUrl: 'https://api.myapp.com', // default: same origin
98
+ // flushInterval: 5000, // default: 5s
99
+ // captureJsErrors: true, // default: true
100
+ // captureConsole: true, // default: true
101
+ // debug: false,
102
+ })
103
+ return () => FrontendMonitor.destroy()
104
+ }, [])
105
+
106
+ return null
107
+ }
108
+ ```
109
+
110
+ ```tsx
111
+ // app/layout.tsx
112
+ import { MonitorProvider } from '@/components/MonitorProvider'
113
+
114
+ export default function RootLayout({ children }) {
115
+ return (
116
+ <html lang="en">
117
+ <body>
118
+ <MonitorProvider />
119
+ {children}
120
+ </body>
121
+ </html>
122
+ )
123
+ }
124
+ ```
125
+
126
+ ### Network Monitoring
127
+
128
+ ```typescript
129
+ import { monitoredFetch } from '@djangocfg/monitor/client'
130
+
131
+ const response = await monitoredFetch('/api/orders', {
132
+ method: 'POST',
133
+ body: JSON.stringify(order),
134
+ })
135
+ ```
136
+
137
+ ### Manual Event Capture
138
+
139
+ ```typescript
140
+ import { FrontendMonitor } from '@djangocfg/monitor/client'
141
+ import { EventType, EventLevel } from '@djangocfg/monitor'
142
+
143
+ FrontendMonitor.capture({
144
+ event_type: EventType.JS_ERROR,
145
+ level: EventLevel.ERROR,
146
+ message: 'Payment failed',
147
+ url: window.location.href,
148
+ extra: { orderId: '123' },
149
+ })
150
+ ```
151
+
152
+ ### Session ID
153
+
154
+ ```typescript
155
+ import { getSessionId } from '@djangocfg/monitor/client'
156
+
157
+ const sessionId = getSessionId() // UUID stored in localStorage + cookie
158
+ ```
159
+
160
+ ## Server Usage (Next.js Route Handlers / Server Components)
161
+
162
+ ### Configure once
163
+
164
+ ```typescript
165
+ // lib/monitor.ts
166
+ import { serverMonitor } from '@djangocfg/monitor/server'
167
+
168
+ serverMonitor.configure({
169
+ project: process.env.PROJECT_NAME ?? 'my-app',
170
+ environment: process.env.NODE_ENV,
171
+ // baseUrl: 'https://api.myapp.com', // required if backend is on different origin
172
+ })
173
+
174
+ export { serverMonitor }
175
+ ```
176
+
177
+ ### Route Handler
178
+
179
+ ```typescript
180
+ // app/api/orders/route.ts
181
+ import { serverMonitor } from '@/lib/monitor'
182
+
183
+ export async function POST(req: Request) {
184
+ try {
185
+ // ... handle request
186
+ } catch (err) {
187
+ await serverMonitor.captureError(err, { url: req.url })
188
+ return new Response('Internal Server Error', { status: 500 })
189
+ }
190
+ }
191
+ ```
192
+
193
+ ### Network Error
194
+
195
+ ```typescript
196
+ const response = await fetch(upstreamUrl)
197
+ if (!response.ok) {
198
+ await serverMonitor.captureNetworkError(
199
+ response.status,
200
+ 'GET',
201
+ upstreamUrl,
202
+ { pageUrl: req.url },
203
+ )
204
+ }
205
+ ```
206
+
207
+ ### Arbitrary Event
208
+
209
+ ```typescript
210
+ import { EventType, EventLevel } from '@djangocfg/monitor/server'
211
+
212
+ await serverMonitor.capture({
213
+ event_type: EventType.WARNING,
214
+ level: EventLevel.WARN,
215
+ message: 'Rate limit approaching',
216
+ url: req.url,
217
+ extra: { remaining: 5 },
218
+ })
219
+ ```
220
+
221
+ ## Types
222
+
223
+ ```typescript
224
+ import type { MonitorConfig, MonitorEvent } from '@djangocfg/monitor'
225
+ import { EventType, EventLevel } from '@djangocfg/monitor'
226
+
227
+ EventType.JS_ERROR // 'js_error'
228
+ EventType.NETWORK_ERROR // 'network_error'
229
+ EventType.WARNING // 'warning'
230
+ EventType.ERROR // 'error'
231
+ EventType.INFO // 'info'
232
+
233
+ EventLevel.ERROR // 'error'
234
+ EventLevel.WARN // 'warn'
235
+ EventLevel.INFO // 'info'
236
+ ```
237
+
238
+ ### MonitorConfig
239
+
240
+ | Option | Type | Default | Description |
241
+ |--------|------|---------|-------------|
242
+ | `project` | `string` | `''` | Project name sent with every event |
243
+ | `environment` | `string` | `''` | `production` / `staging` / `development` |
244
+ | `baseUrl` | `string` | `''` | Base URL of the django-cfg backend (same origin by default) |
245
+ | `flushInterval` | `number` | `5000` | Buffer flush interval (ms) |
246
+ | `maxBufferSize` | `number` | `20` | Max events before immediate flush |
247
+ | `captureJsErrors` | `boolean` | `true` | Capture `window.onerror` + unhandled rejections |
248
+ | `captureConsole` | `boolean` | `true` | Intercept `console.warn` / `console.error` |
249
+ | `debug` | `boolean` | `false` | Log init info to console |
250
+
251
+ ### ServerMonitorConfig
252
+
253
+ | Option | Type | Default | Description |
254
+ |--------|------|---------|-------------|
255
+ | `project` | `string` | `''` | Project name |
256
+ | `environment` | `string` | `''` | Environment name |
257
+ | `baseUrl` | `string` | `''` | Base URL of the django-cfg backend (absolute required on server) |
258
+
259
+ ## Zod Validation Integration
260
+
261
+ `@djangocfg/api` automatically dispatches a `zod-validation-error` CustomEvent whenever a response fails schema validation. `@djangocfg/monitor/client` listens and forwards it as a `WARNING` — zero setup needed.
262
+
263
+ ```
264
+ @djangocfg/api fetcher validates response with Zod
265
+ → dispatches window CustomEvent('zod-validation-error', { detail })
266
+ → @djangocfg/monitor/client capture/validation.ts catches it
267
+ → pushed to store → flushed to backend
268
+ ```
269
+
270
+ ## Custom HTTP Adapter
271
+
272
+ The generated `KeepAliveFetchAdapter` is also available if you need it elsewhere:
273
+
274
+ ```typescript
275
+ import { KeepAliveFetchAdapter } from '@djangocfg/monitor/client'
276
+ // or directly from generated:
277
+ import { API, KeepAliveFetchAdapter } from '@djangocfg/monitor/client'
278
+
279
+ const api = new API('https://api.myapp.com', {
280
+ httpClient: new KeepAliveFetchAdapter(),
281
+ })
282
+ ```
283
+
284
+ ## Django Backend
285
+
286
+ Enable the `cfg_monitor` extension:
287
+
288
+ ```python
289
+ # cfg.py
290
+ from django_cfg import DjangoConfig
291
+
292
+ class Config(DjangoConfig):
293
+ installed_apps = [
294
+ ...
295
+ 'django_cfg.apps.system.monitor',
296
+ ]
297
+ ```
298
+
299
+ | | |
300
+ |---|---|
301
+ | Endpoint | `POST /cfg/monitor/ingest/` |
302
+ | Auth | not required |
303
+ | Rate limit | 100 req/min per IP |
304
+ | Batch size | up to 50 events |
305
+
306
+ ## Development
307
+
308
+ ```bash
309
+ # Regenerate API client from Django OpenAPI schema
310
+ make generate
311
+
312
+ # Build package
313
+ make build
314
+
315
+ # Watch mode
316
+ pnpm dev
317
+
318
+ # Type check
319
+ pnpm check
320
+ ```
321
+
322
+ ## Peer Dependencies
323
+
324
+ | Package | Required | Description |
325
+ |---------|----------|-------------|
326
+ | `consola` | optional | Uses consola reporter instead of patching `console.*` |
327
+ | `zustand` | optional | Required for the client entry point event buffer |
328
+
329
+ ## Requirements
330
+
331
+ - Next.js >= 15 (or any React >= 19 app)
332
+ - Django with `django_cfg >= 1.7` and `monitor` extension
333
+
334
+ ## License
335
+
336
+ MIT
337
+
338
+ ## Links
339
+
340
+ - [DjangoCFG Documentation](https://djangocfg.com)
341
+ - [GitHub](https://github.com/markolofsen/django-cfg)