tackbox 0.1.65 → 0.1.66
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/js/README.md +25 -12
- package/js/report.js +3 -14
- package/package.json +1 -1
package/js/README.md
CHANGED
|
@@ -151,7 +151,7 @@ mode.
|
|
|
151
151
|
## Report helper
|
|
152
152
|
|
|
153
153
|
```js
|
|
154
|
-
import { init, reportError, reportWarn,
|
|
154
|
+
import { init, reportError, reportWarn, flush } from 'tackbox/report'
|
|
155
155
|
|
|
156
156
|
init({
|
|
157
157
|
dsn: import.meta.env.VITE_SENTRY_DSN || '',
|
|
@@ -159,7 +159,6 @@ init({
|
|
|
159
159
|
verify: true, // confirm connectivity at startup
|
|
160
160
|
debug: false,
|
|
161
161
|
})
|
|
162
|
-
setupGlobalHandlers()
|
|
163
162
|
// ... on shutdown:
|
|
164
163
|
await flush(2000)
|
|
165
164
|
|
|
@@ -176,6 +175,22 @@ and stays log-only. `init({ verify: true })` sends one healthcheck
|
|
|
176
175
|
event with `fingerprint: ["report.startup"]` and flushes; glitchtip
|
|
177
176
|
groups all startups under one issue, no spam.
|
|
178
177
|
|
|
178
|
+
### Global handlers
|
|
179
|
+
|
|
180
|
+
The helper installs no process-global hook. To route uncaught errors and
|
|
181
|
+
promise rejections into the report lane, the app owns the listeners:
|
|
182
|
+
|
|
183
|
+
```js
|
|
184
|
+
window.addEventListener('error', e => {
|
|
185
|
+
reportError('uncaught global error', e.error || e.message,
|
|
186
|
+
{ source: 'window.error' }, 'global.uncaught')
|
|
187
|
+
})
|
|
188
|
+
window.addEventListener('unhandledrejection', e => {
|
|
189
|
+
reportError('unhandled promise rejection', e.reason,
|
|
190
|
+
{ source: 'window.unhandledrejection' }, 'global.unhandled')
|
|
191
|
+
})
|
|
192
|
+
```
|
|
193
|
+
|
|
179
194
|
## Bundled API
|
|
180
195
|
|
|
181
196
|
- `init(opts)`, `flush(timeout)`, `verify(timeout)`, `isReady()`
|
|
@@ -188,22 +203,20 @@ groups all startups under one issue, no spam.
|
|
|
188
203
|
the user lost connectivity)
|
|
189
204
|
- `reportSynthError(msg, tags, dedupKey)`
|
|
190
205
|
- `reportPanic(name, recovered)`
|
|
191
|
-
- `setupGlobalHandlers()` wires `window.error` and
|
|
192
|
-
`window.unhandledrejection` to `reportError`
|
|
193
206
|
|
|
194
|
-
|
|
195
|
-
window
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
207
|
+
Sink ordering, the never-suppressed user lane, and the per-`dedupKey` capture
|
|
208
|
+
rate window are the cross-language runtime contract:
|
|
209
|
+
[`../docs/report-contracts.md`](../docs/report-contracts.md). JS-specific: the
|
|
210
|
+
user lane is the `tackbox:error` custom event, dispatched on the window after
|
|
211
|
+
each `reportError` / `reportWarn` / `notify` / `reportPanic` call (`reportQuiet`
|
|
212
|
+
does not dispatch it). The event `detail` carries `{ msg, cause, tags, dedupKey,
|
|
213
|
+
level }`; the listener coalesces on `dedupKey`.
|
|
201
214
|
|
|
202
215
|
Platform limit: a `tackbox:error` listener that throws is not observable from
|
|
203
216
|
`dispatchEvent` - the browser routes a listener failure to `window.onerror` by
|
|
204
217
|
design. So the JS user lane cannot capture its own listener's failure the way
|
|
205
218
|
Go, Python, and Java capture a throwing `report.notifier`. A module-level
|
|
206
219
|
re-entrancy guard stops the one loop this opens (a throwing listener reaching
|
|
207
|
-
`window.onerror`, which
|
|
220
|
+
`window.onerror`, which an app-owned global handler turns back into
|
|
208
221
|
`reportError` -> dispatch): a dispatch already in progress on the stack skips
|
|
209
222
|
the nested one and logs locally instead. Sequential dispatches are unaffected.
|
package/js/report.js
CHANGED
|
@@ -128,16 +128,6 @@ function reportPanic(name, recovered) {
|
|
|
128
128
|
})
|
|
129
129
|
}
|
|
130
130
|
|
|
131
|
-
function setupGlobalHandlers() {
|
|
132
|
-
if (typeof window === 'undefined') return
|
|
133
|
-
window.addEventListener('error', e => {
|
|
134
|
-
reportError('uncaught global error from window', e.error || e.message, { source: 'window.error' }, 'global.uncaught')
|
|
135
|
-
})
|
|
136
|
-
window.addEventListener('unhandledrejection', e => {
|
|
137
|
-
reportError('unhandled promise rejection from window', e.reason, { source: 'window.unhandledrejection' }, 'global.unhandled')
|
|
138
|
-
})
|
|
139
|
-
}
|
|
140
|
-
|
|
141
131
|
function maskDSN(dsn) {
|
|
142
132
|
// no-report: malformed user DSN, opaque marker is the recovery
|
|
143
133
|
try {
|
|
@@ -154,9 +144,9 @@ function dispatchEventSafely(name, detail) {
|
|
|
154
144
|
if (typeof window === 'undefined' || typeof CustomEvent === 'undefined') return
|
|
155
145
|
// Re-entrancy guard: a throwing `tackbox:error` listener surfaces via
|
|
156
146
|
// window.onerror (the DOM routes listener failures there, not to dispatchEvent),
|
|
157
|
-
// which
|
|
158
|
-
// stack. Skip the nested dispatch so that cannot loop; sequential
|
|
159
|
-
// are unaffected (D005 deliver-always intact).
|
|
147
|
+
// which an app-owned global handler can turn back into reportError -> dispatch
|
|
148
|
+
// on the same stack. Skip the nested dispatch so that cannot loop; sequential
|
|
149
|
+
// dispatches are unaffected (D005 deliver-always intact).
|
|
160
150
|
if (dispatching) {
|
|
161
151
|
console.warn('[tackbox] report: nested tackbox:error dispatch skipped (listener-failure re-entry)')
|
|
162
152
|
return
|
|
@@ -183,5 +173,4 @@ module.exports = {
|
|
|
183
173
|
reportSynthError,
|
|
184
174
|
notify,
|
|
185
175
|
reportPanic,
|
|
186
|
-
setupGlobalHandlers,
|
|
187
176
|
}
|
package/package.json
CHANGED