@djangocfg/monitor 2.1.229 → 2.1.231
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 +16 -1
- package/dist/client.cjs +69 -1
- package/dist/client.cjs.map +1 -1
- package/dist/client.d.cts +17 -1
- package/dist/client.d.ts +17 -1
- package/dist/client.mjs +69 -1
- package/dist/client.mjs.map +1 -1
- package/package.json +2 -2
- package/src/client/hooks/useDebugMode.ts +84 -0
- package/src/client/index.ts +2 -0
- package/src/client/store/index.ts +2 -0
- package/src/client/utils/env.ts +16 -0
- package/src/client/window.ts +3 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@djangocfg/monitor",
|
|
3
|
-
"version": "2.1.
|
|
3
|
+
"version": "2.1.231",
|
|
4
4
|
"description": "Browser error and event monitoring SDK for django-cfg backends. Captures JS errors, network failures, console logs, and performance metrics.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"django",
|
|
@@ -83,7 +83,7 @@
|
|
|
83
83
|
}
|
|
84
84
|
},
|
|
85
85
|
"devDependencies": {
|
|
86
|
-
"@djangocfg/typescript-config": "^2.1.
|
|
86
|
+
"@djangocfg/typescript-config": "^2.1.231",
|
|
87
87
|
"p-retry": "^6.2.0",
|
|
88
88
|
"@types/node": "^24.7.2",
|
|
89
89
|
"@types/react": "^19.1.0",
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
'use client'
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* useDebugMode — shared debug mode detection hook.
|
|
5
|
+
*
|
|
6
|
+
* Logic:
|
|
7
|
+
* - development: always true (no localStorage needed)
|
|
8
|
+
* - production:
|
|
9
|
+
* - ?debug=1 in URL → persist to localStorage, remove param from URL
|
|
10
|
+
* - ?debug=0 in URL → clear localStorage, disable debug mode
|
|
11
|
+
* - localStorage.__debug_mode__ === '1' → true
|
|
12
|
+
* - otherwise → false
|
|
13
|
+
*
|
|
14
|
+
* @example
|
|
15
|
+
* const isDebug = useDebugMode()
|
|
16
|
+
*/
|
|
17
|
+
|
|
18
|
+
import { useEffect, useState } from 'react'
|
|
19
|
+
import { isDevelopment } from '../utils/env'
|
|
20
|
+
|
|
21
|
+
const LS_KEY = '__debug_mode__'
|
|
22
|
+
|
|
23
|
+
function readFromStorage(): boolean {
|
|
24
|
+
try {
|
|
25
|
+
return localStorage.getItem(LS_KEY) === '1'
|
|
26
|
+
} catch {
|
|
27
|
+
return false
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
function persistToStorage(): void {
|
|
32
|
+
try {
|
|
33
|
+
localStorage.setItem(LS_KEY, '1')
|
|
34
|
+
} catch {
|
|
35
|
+
// ignore — private browsing or quota exceeded
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
function clearFromStorage(): void {
|
|
40
|
+
try {
|
|
41
|
+
localStorage.removeItem(LS_KEY)
|
|
42
|
+
} catch {
|
|
43
|
+
// ignore
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
function consumeDebugParam(): boolean | null {
|
|
48
|
+
if (typeof window === 'undefined') return null
|
|
49
|
+
const params = new URLSearchParams(window.location.search)
|
|
50
|
+
const value = params.get('debug')
|
|
51
|
+
if (value === null) return null
|
|
52
|
+
|
|
53
|
+
if (value === '1') {
|
|
54
|
+
persistToStorage()
|
|
55
|
+
} else {
|
|
56
|
+
// ?debug=0 or any other value → explicitly disable and clear stored flag
|
|
57
|
+
clearFromStorage()
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
params.delete('debug')
|
|
61
|
+
const newUrl = `${window.location.pathname}${params.toString() ? `?${params.toString()}` : ''}${window.location.hash}`
|
|
62
|
+
window.history.replaceState(null, '', newUrl)
|
|
63
|
+
return value === '1'
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
export function useDebugMode(): boolean {
|
|
67
|
+
// In development, always true — no side effects needed
|
|
68
|
+
if (isDevelopment) return true
|
|
69
|
+
|
|
70
|
+
// eslint-disable-next-line react-hooks/rules-of-hooks
|
|
71
|
+
const [isDebug, setIsDebug] = useState(false)
|
|
72
|
+
|
|
73
|
+
// eslint-disable-next-line react-hooks/rules-of-hooks
|
|
74
|
+
useEffect(() => {
|
|
75
|
+
const fromUrl = consumeDebugParam()
|
|
76
|
+
if (fromUrl !== null) {
|
|
77
|
+
setIsDebug(fromUrl)
|
|
78
|
+
return
|
|
79
|
+
}
|
|
80
|
+
setIsDebug(readFromStorage())
|
|
81
|
+
}, [])
|
|
82
|
+
|
|
83
|
+
return isDebug
|
|
84
|
+
}
|
package/src/client/index.ts
CHANGED
|
@@ -36,6 +36,8 @@ export type { MonitorProviderProps } from './MonitorProvider'
|
|
|
36
36
|
export { initWindowMonitor } from './window'
|
|
37
37
|
export type { WindowMonitorAPI } from './window'
|
|
38
38
|
export { monitorStore } from './store'
|
|
39
|
+
export { useDebugMode } from './hooks/useDebugMode'
|
|
40
|
+
export { isDevelopment, isProduction, MONITOR_VERSION } from './utils/env'
|
|
39
41
|
|
|
40
42
|
let flushInterval: ReturnType<typeof setInterval> | null = null
|
|
41
43
|
const cleanupFns: Array<() => void> = []
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { createStore } from 'zustand/vanilla'
|
|
2
2
|
import type { MonitorEvent, MonitorConfig } from '../../types'
|
|
3
3
|
import { sendBatch } from '../transport/ingest'
|
|
4
|
+
import { MONITOR_VERSION } from '../utils/env'
|
|
4
5
|
|
|
5
6
|
// Circuit breaker: pause flushing after N consecutive transport failures
|
|
6
7
|
const CIRCUIT_BREAKER_THRESHOLD = 3
|
|
@@ -28,6 +29,7 @@ export const monitorStore = createStore<MonitorState>((set, get) => ({
|
|
|
28
29
|
const { config, buffer } = get()
|
|
29
30
|
const maxSize = config.maxBufferSize ?? 20
|
|
30
31
|
const sanitized: MonitorEvent = {
|
|
32
|
+
build_id: event.build_id ?? config.buildId ?? `sdk:${MONITOR_VERSION}`,
|
|
31
33
|
...event,
|
|
32
34
|
// Enforce field size limits before buffering (last-resort backstop)
|
|
33
35
|
message: event.message && event.message.length > 4997
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Environment utilities.
|
|
3
|
+
*
|
|
4
|
+
* Use these constants instead of inline process.env.NODE_ENV checks.
|
|
5
|
+
* Webpack/esbuild replaces process.env.NODE_ENV statically at build time,
|
|
6
|
+
* so these are zero-cost — they tree-shake correctly in both client and server bundles.
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
/** True only in `next dev` / jest / vitest */
|
|
10
|
+
export const isDevelopment = process.env.NODE_ENV === 'development'
|
|
11
|
+
|
|
12
|
+
/** True in production builds and test environments */
|
|
13
|
+
export const isProduction = process.env.NODE_ENV !== 'development'
|
|
14
|
+
|
|
15
|
+
/** Package version — injected at build time via tsup define, falls back to package.json value */
|
|
16
|
+
export const MONITOR_VERSION: string = (process.env.MONITOR_VERSION as string) ?? '2.1.230'
|
package/src/client/window.ts
CHANGED
|
@@ -16,6 +16,7 @@
|
|
|
16
16
|
import { monitorStore } from './store'
|
|
17
17
|
import { EventType, EventLevel } from '../_api'
|
|
18
18
|
import { getSessionId } from './capture/session'
|
|
19
|
+
import { MONITOR_VERSION } from './utils/env'
|
|
19
20
|
import type { MonitorEvent } from '../types'
|
|
20
21
|
|
|
21
22
|
export interface WindowMonitorAPI {
|
|
@@ -105,6 +106,8 @@ export function initWindowMonitor(): void {
|
|
|
105
106
|
status() {
|
|
106
107
|
const state = monitorStore.getState()
|
|
107
108
|
console.group('[monitor] status')
|
|
109
|
+
console.log('sdk version:', MONITOR_VERSION)
|
|
110
|
+
console.log('build_id:', state.config.buildId ?? `sdk:${MONITOR_VERSION}`)
|
|
108
111
|
console.log('config:', state.config)
|
|
109
112
|
console.log('buffer size:', state.buffer.length)
|
|
110
113
|
console.log('initialized:', state.initialized)
|