autotel-web 1.10.1 → 1.11.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 +142 -0
- package/dist/{chunk-FYEN2WET.js → chunk-L3S7LTIH.js} +7 -3
- package/dist/chunk-L3S7LTIH.js.map +1 -0
- package/dist/full.d.ts +61 -1
- package/dist/full.js +354 -87
- package/dist/full.js.map +1 -1
- package/dist/index.d.ts +10 -1
- package/dist/index.js +124 -6
- package/dist/index.js.map +1 -1
- package/package.json +16 -16
- package/src/error-tracking/error-tracking.test.ts +156 -0
- package/src/error-tracking/exception-builder.test.ts +72 -0
- package/src/error-tracking/exception-builder.ts +58 -0
- package/src/error-tracking/index.ts +143 -0
- package/src/error-tracking/rate-limiter.test.ts +47 -0
- package/src/error-tracking/rate-limiter.ts +47 -0
- package/src/error-tracking/redact-values.test.ts +50 -0
- package/src/error-tracking/redact-values.ts +74 -0
- package/src/error-tracking/stack-parser.test.ts +66 -0
- package/src/error-tracking/stack-parser.ts +69 -0
- package/src/error-tracking/suppression.test.ts +48 -0
- package/src/error-tracking/suppression.ts +37 -0
- package/src/error-tracking/types.test.ts +37 -0
- package/src/error-tracking/types.ts +78 -0
- package/src/full.ts +24 -2
- package/src/index.ts +3 -0
- package/src/init.ts +67 -6
- package/src/span-exporter.ts +94 -0
- package/dist/chunk-FYEN2WET.js.map +0 -1
- package/src/errors.ts +0 -65
package/README.md
CHANGED
|
@@ -85,6 +85,120 @@ app.get('/api/users', async (req, res) => {
|
|
|
85
85
|
|
|
86
86
|
Open your observability platform (Honeycomb, Datadog, Jaeger, etc.) and see the complete trace from browser → backend → database!
|
|
87
87
|
|
|
88
|
+
## Browser Span Export (lean mode)
|
|
89
|
+
|
|
90
|
+
By default, lean mode only injects `traceparent` headers — no spans are exported from the browser. This means trace UIs like Jaeger may show "missing parent span" because the browser's spanId doesn't exist in the collector.
|
|
91
|
+
|
|
92
|
+
To fix this, set the `endpoint` option. autotel-web will export a lightweight span via `navigator.sendBeacon` for each fetch, so the browser span appears in your collector as the trace root:
|
|
93
|
+
|
|
94
|
+
```typescript
|
|
95
|
+
init({
|
|
96
|
+
service: 'my-frontend',
|
|
97
|
+
endpoint: '', // same-origin — requires /v1/traces proxy (see below)
|
|
98
|
+
})
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
### Collector Proxy
|
|
102
|
+
|
|
103
|
+
Browsers can't send directly to most collectors (CORS). Add a simple proxy route to your API:
|
|
104
|
+
|
|
105
|
+
**Hono:**
|
|
106
|
+
|
|
107
|
+
```typescript
|
|
108
|
+
app.post('/v1/traces', async (c) => {
|
|
109
|
+
const body = await c.req.arrayBuffer()
|
|
110
|
+
await fetch(`${process.env.OTEL_EXPORTER_OTLP_ENDPOINT}/v1/traces`, {
|
|
111
|
+
method: 'POST',
|
|
112
|
+
headers: { 'Content-Type': 'application/json' },
|
|
113
|
+
body,
|
|
114
|
+
})
|
|
115
|
+
return c.json({ ok: true })
|
|
116
|
+
})
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
**Express:**
|
|
120
|
+
|
|
121
|
+
```typescript
|
|
122
|
+
app.post('/v1/traces', express.raw({ type: 'application/json' }), async (req, res) => {
|
|
123
|
+
await fetch(`${process.env.OTEL_EXPORTER_OTLP_ENDPOINT}/v1/traces`, {
|
|
124
|
+
method: 'POST',
|
|
125
|
+
headers: { 'Content-Type': 'application/json' },
|
|
126
|
+
body: req.body,
|
|
127
|
+
})
|
|
128
|
+
res.json({ ok: true })
|
|
129
|
+
})
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
If using Vite in dev, proxy `/v1/traces` to your API:
|
|
133
|
+
|
|
134
|
+
```typescript
|
|
135
|
+
// vite.config.ts
|
|
136
|
+
server: {
|
|
137
|
+
proxy: {
|
|
138
|
+
'/v1/traces': { target: 'http://localhost:8787', changeOrigin: true },
|
|
139
|
+
},
|
|
140
|
+
},
|
|
141
|
+
```
|
|
142
|
+
|
|
143
|
+
### PostHog Reverse Proxy
|
|
144
|
+
|
|
145
|
+
If you use PostHog for analytics, route events through the same API to bypass ad blockers (typically increases event capture by 10-30%):
|
|
146
|
+
|
|
147
|
+
**Hono:**
|
|
148
|
+
|
|
149
|
+
```typescript
|
|
150
|
+
const POSTHOG_HOST = process.env.POSTHOG_HOST || 'https://eu.i.posthog.com'
|
|
151
|
+
|
|
152
|
+
app.post('/ingest/*', async (c) => {
|
|
153
|
+
const path = c.req.path.replace('/ingest', '')
|
|
154
|
+
const body = await c.req.arrayBuffer()
|
|
155
|
+
const resp = await fetch(`${POSTHOG_HOST}${path}`, {
|
|
156
|
+
method: 'POST',
|
|
157
|
+
headers: { 'Content-Type': c.req.header('content-type') || 'application/json' },
|
|
158
|
+
body,
|
|
159
|
+
})
|
|
160
|
+
return new Response(resp.body, { status: resp.status, headers: resp.headers })
|
|
161
|
+
})
|
|
162
|
+
|
|
163
|
+
app.get('/ingest/decide*', async (c) => {
|
|
164
|
+
const url = new URL(c.req.url)
|
|
165
|
+
const resp = await fetch(`${POSTHOG_HOST}/decide${url.search}`)
|
|
166
|
+
return new Response(resp.body, { status: resp.status, headers: resp.headers })
|
|
167
|
+
})
|
|
168
|
+
```
|
|
169
|
+
|
|
170
|
+
**Browser (posthog-js):**
|
|
171
|
+
|
|
172
|
+
```typescript
|
|
173
|
+
import posthog from 'posthog-js'
|
|
174
|
+
|
|
175
|
+
posthog.init('phc_your_key', {
|
|
176
|
+
api_host: '/ingest', // same-origin proxy
|
|
177
|
+
ui_host: 'https://eu.i.posthog.com', // keep toolbar working
|
|
178
|
+
})
|
|
179
|
+
```
|
|
180
|
+
|
|
181
|
+
**Vite proxy (dev):**
|
|
182
|
+
|
|
183
|
+
```typescript
|
|
184
|
+
proxy: {
|
|
185
|
+
'/ingest': { target: 'http://localhost:8787', changeOrigin: true },
|
|
186
|
+
}
|
|
187
|
+
```
|
|
188
|
+
|
|
189
|
+
See [PostHog reverse proxy docs](https://posthog.com/docs/advanced/proxy) for production setups (managed proxy, Cloudflare Workers, etc.).
|
|
190
|
+
|
|
191
|
+
The resulting trace tree:
|
|
192
|
+
|
|
193
|
+
```
|
|
194
|
+
browser /api/transfer (CLIENT, root) ← autotel-web
|
|
195
|
+
└─ POST /api/transfer (SERVER) ← autotel / autotel-hono
|
|
196
|
+
└─ sendMoney (INTERNAL) ← your app
|
|
197
|
+
├─ validate
|
|
198
|
+
├─ fetchRate
|
|
199
|
+
└─ ...
|
|
200
|
+
```
|
|
201
|
+
|
|
88
202
|
## Full mode (real spans)
|
|
89
203
|
|
|
90
204
|
When you need real browser spans, network timing events, and optional export from the client, use full mode. Same install: `autotel-web`. No Zone.js.
|
|
@@ -354,6 +468,14 @@ interface AutotelWebConfig {
|
|
|
354
468
|
/** Enable debug logging (default: false) */
|
|
355
469
|
debug?: boolean
|
|
356
470
|
|
|
471
|
+
/**
|
|
472
|
+
* OTLP endpoint for exporting browser spans.
|
|
473
|
+
* When set, a real span is sent via sendBeacon for each fetch,
|
|
474
|
+
* so the traceparent spanId exists in the collector.
|
|
475
|
+
* Use '' for same-origin (requires /v1/traces proxy).
|
|
476
|
+
*/
|
|
477
|
+
endpoint?: string
|
|
478
|
+
|
|
357
479
|
/** Privacy controls for traceparent header injection */
|
|
358
480
|
privacy?: PrivacyConfig
|
|
359
481
|
}
|
|
@@ -1059,6 +1181,26 @@ app.use(cors({
|
|
|
1059
1181
|
|
|
1060
1182
|
3. For custom frameworks, manually extract context (see "Backend Integration" above)
|
|
1061
1183
|
|
|
1184
|
+
### Browser spans not appearing in collector
|
|
1185
|
+
|
|
1186
|
+
If you've set `endpoint` but spans don't appear:
|
|
1187
|
+
|
|
1188
|
+
1. Check the proxy is working: `curl -X POST http://localhost:8787/v1/traces -H 'Content-Type: application/json' -d '{}'`
|
|
1189
|
+
2. Verify Vite proxy config includes `/v1/traces`
|
|
1190
|
+
3. Enable `debug: true` — you should see `[autotel-web] flushSpans: sending N span(s)` in the console
|
|
1191
|
+
|
|
1192
|
+
### Vite dev server caching stale autotel-web
|
|
1193
|
+
|
|
1194
|
+
When using `file:` linked autotel packages in development, Vite caches pre-bundled dependencies in `node_modules/.vite/`. After rebuilding autotel-web, clear this cache:
|
|
1195
|
+
|
|
1196
|
+
```bash
|
|
1197
|
+
rm -rf node_modules/.vite
|
|
1198
|
+
# or for monorepos
|
|
1199
|
+
rm -rf apps/web/node_modules/.vite
|
|
1200
|
+
```
|
|
1201
|
+
|
|
1202
|
+
Then restart the Vite dev server. Without this, the browser may run an old version of autotel-web even after rebuilding.
|
|
1203
|
+
|
|
1062
1204
|
### TypeScript errors
|
|
1063
1205
|
|
|
1064
1206
|
Ensure you're using TypeScript 5.0+ and have `@types/node` installed:
|
|
@@ -1,3 +1,7 @@
|
|
|
1
|
+
var __defProp = Object.defineProperty;
|
|
2
|
+
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
3
|
+
var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
|
|
4
|
+
|
|
1
5
|
// src/traceparent.ts
|
|
2
6
|
function randomHex(bytes) {
|
|
3
7
|
const buffer = new Uint8Array(bytes);
|
|
@@ -84,6 +88,6 @@ function extractContext(traceparent) {
|
|
|
84
88
|
};
|
|
85
89
|
}
|
|
86
90
|
|
|
87
|
-
export { createTraceparent, extractContext, generateSpanId, generateTraceId, getActiveContext, getTraceparent, parseTraceparent, trace };
|
|
88
|
-
//# sourceMappingURL=chunk-
|
|
89
|
-
//# sourceMappingURL=chunk-
|
|
91
|
+
export { __publicField, createTraceparent, extractContext, generateSpanId, generateTraceId, getActiveContext, getTraceparent, parseTraceparent, trace };
|
|
92
|
+
//# sourceMappingURL=chunk-L3S7LTIH.js.map
|
|
93
|
+
//# sourceMappingURL=chunk-L3S7LTIH.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/traceparent.ts","../src/functional.ts"],"names":[],"mappings":"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","file":"chunk-L3S7LTIH.js","sourcesContent":["/**\n * Minimal W3C Trace Context implementation for browser\n *\n * Generates traceparent headers in the W3C format:\n * traceparent: 00-{trace-id}-{span-id}-{flags}\n *\n * No OpenTelemetry dependencies - just crypto.getRandomValues()\n */\n\n/**\n * Generate random hex string of specified byte length\n */\nfunction randomHex(bytes: number): string {\n const buffer = new Uint8Array(bytes);\n crypto.getRandomValues(buffer);\n return Array.from(buffer)\n .map((b) => b.toString(16).padStart(2, '0'))\n .join('');\n}\n\n/**\n * Generate a random 128-bit (16 byte) trace ID\n * @returns 32 character hex string\n */\nexport function generateTraceId(): string {\n return randomHex(16); // 16 bytes = 32 hex chars\n}\n\n/**\n * Generate a random 64-bit (8 byte) span ID\n * @returns 16 character hex string\n */\nexport function generateSpanId(): string {\n return randomHex(8); // 8 bytes = 16 hex chars\n}\n\n/**\n * Create a W3C traceparent header value\n *\n * Format: version-traceId-spanId-flags\n * - version: 00 (W3C Trace Context spec)\n * - traceId: 128-bit hex (32 chars)\n * - spanId: 64-bit hex (16 chars)\n * - flags: 01 (sampled)\n *\n * @param traceId - Optional existing trace ID (for continuing traces)\n * @param parentSpanId - Optional parent span ID (unused in browser, included for API compat)\n * @returns W3C traceparent header value\n *\n * @example\n * ```typescript\n * const header = createTraceparent()\n * // \"00-4bf92f3577b34da6a3ce929d0e0e4736-00f067aa0ba902b7-01\"\n * ```\n */\nexport function createTraceparent(\n traceId?: string,\n _parentSpanId?: string\n): string {\n const tid = traceId ?? generateTraceId();\n const sid = generateSpanId();\n const flags = '01'; // sampled=1\n\n return `00-${tid}-${sid}-${flags}`;\n}\n\n/**\n * Parse a traceparent header value\n * Useful for extracting trace context from incoming headers\n *\n * @param traceparent - W3C traceparent header value\n * @returns Parsed components or null if invalid\n *\n * @example\n * ```typescript\n * const parsed = parseTraceparent('00-4bf92f...0e4736-00f067...902b7-01')\n * console.log(parsed?.traceId) // \"4bf92f...0e4736\"\n * ```\n */\nexport function parseTraceparent(traceparent: string): {\n version: string;\n traceId: string;\n spanId: string;\n flags: string;\n} | null {\n const parts = traceparent.split('-');\n\n if (parts.length !== 4) {\n return null;\n }\n\n const [version, traceId, spanId, flags] = parts;\n\n // Validate format\n if (\n version.length !== 2 ||\n traceId.length !== 32 ||\n spanId.length !== 16 ||\n flags.length !== 2\n ) {\n return null;\n }\n\n return { version, traceId, spanId, flags };\n}\n","/**\n * Minimal functional API for browser tracing\n *\n * These are DX wrappers that DON'T create real browser spans.\n * The real spans and timing happen on the backend via Autotel.\n *\n * The browser's job is just to propagate trace context via headers.\n */\n\nimport { createTraceparent, parseTraceparent } from './traceparent';\n\n/**\n * Minimal trace context (browser-side)\n *\n * This is a lightweight version that just holds IDs.\n * NO actual span object - the real span lives on the backend.\n */\nexport interface TraceContext {\n /** Current trace ID (may be extracted from request) */\n readonly traceId: string;\n /** Current span ID (generated for this browser \"span\") */\n readonly spanId: string;\n /** Correlation ID (same as trace ID) */\n readonly correlationId: string;\n}\n\n// Store current trace context (if any)\nlet currentContext: TraceContext | undefined;\n\n/**\n * Wrap a function with trace() for better DX\n *\n * **Important:** This does NOT create real spans in the browser.\n * It's purely for API consistency. The real tracing happens on the backend.\n *\n * The traceparent header is automatically injected by init() on fetch/XHR calls.\n *\n * @example Basic usage\n * ```typescript\n * const fetchUser = trace(async (id: string) => {\n * const response = await fetch(`/api/users/${id}`)\n * return response.json()\n * })\n * ```\n *\n * @example With context (for accessing trace IDs)\n * ```typescript\n * const fetchUser = trace(ctx => async (id: string) => {\n * console.log('Trace ID:', ctx.traceId)\n * const response = await fetch(`/api/users/${id}`)\n * return response.json()\n * })\n * ```\n */\nexport function trace<T extends (...args: any[]) => any>(\n fn: T | ((ctx: TraceContext) => T)\n): T {\n // Check if function expects a context parameter (factory pattern)\n const expectsContext = isFactoryPattern(fn);\n\n if (expectsContext) {\n // Factory pattern: trace(ctx => async (data) => ...)\n return ((...args: any[]) => {\n // Generate a new trace context for this call\n const ctx = createContext();\n\n // Call factory to get the actual function\n const actualFn = (fn as (ctx: TraceContext) => T)(ctx);\n\n // Execute the function\n return actualFn(...args);\n }) as T;\n }\n\n // Direct pattern: trace(async (data) => ...)\n // Just return the function as-is since headers are auto-injected\n return fn as T;\n}\n\n/**\n * Check if a function expects a context parameter (factory pattern)\n */\nfunction isFactoryPattern(fn: unknown): boolean {\n if (typeof fn !== 'function') return false;\n\n const fnStr = fn.toString();\n\n // Look for common parameter names that indicate context\n const contextHints = ['ctx', 'context', 'traceContext'];\n\n return contextHints.some((hint) => {\n // Match parameter name at start of function\n const regex = new RegExp(`^\\\\s*(?:async\\\\s+)?(?:function\\\\s*)?\\\\(?\\\\s*${hint}\\\\s*[,)]`);\n return regex.test(fnStr);\n });\n}\n\n/**\n * Create a minimal trace context\n * Generates new IDs for this \"span\" (browser-side only)\n */\nfunction createContext(): TraceContext {\n // Parse the current traceparent if we have one\n // (This would come from SSR or previous span)\n const traceparent = createTraceparent();\n const parsed = parseTraceparent(traceparent);\n\n if (!parsed) {\n // Fallback if parsing fails\n return {\n traceId: '',\n spanId: '',\n correlationId: '',\n };\n }\n\n const ctx: TraceContext = {\n traceId: parsed.traceId,\n spanId: parsed.spanId,\n correlationId: parsed.traceId,\n };\n\n currentContext = ctx;\n return ctx;\n}\n\n/**\n * Get the current trace context (if any)\n *\n * @returns Current trace context or undefined\n *\n * @example\n * ```typescript\n * const ctx = getActiveContext()\n * if (ctx) {\n * console.log('Trace ID:', ctx.traceId)\n * }\n * ```\n */\nexport function getActiveContext(): TraceContext | undefined {\n return currentContext;\n}\n\n/**\n * Manual helper to create a traceparent header\n *\n * Useful if you need to manually set headers or disable auto-instrumentation.\n *\n * @returns W3C traceparent header value\n *\n * @example\n * ```typescript\n * import { init, getTraceparent } from 'autotel-web'\n *\n * // Disable auto-instrumentation\n * init({ service: 'my-app', instrumentFetch: false })\n *\n * // Manually inject headers\n * fetch('/api/data', {\n * headers: {\n * 'traceparent': getTraceparent()\n * }\n * })\n * ```\n */\nexport function getTraceparent(): string {\n return createTraceparent();\n}\n\n/**\n * Extract trace context from a traceparent header\n *\n * Useful for SSR scenarios where you want to continue a trace from the server.\n *\n * @param traceparent - W3C traceparent header value\n * @returns Parsed trace context or undefined if invalid\n *\n * @example\n * ```typescript\n * // In an SSR handler\n * const traceparent = request.headers.get('traceparent')\n * if (traceparent) {\n * const ctx = extractContext(traceparent)\n * console.log('Continuing trace:', ctx?.traceId)\n * }\n * ```\n */\nexport function extractContext(traceparent: string): TraceContext | undefined {\n const parsed = parseTraceparent(traceparent);\n if (!parsed) return undefined;\n\n return {\n traceId: parsed.traceId,\n spanId: parsed.spanId,\n correlationId: parsed.traceId,\n };\n}\n"]}
|
package/dist/full.d.ts
CHANGED
|
@@ -3,6 +3,52 @@ import { SpanProcessor, Sampler } from '@opentelemetry/sdk-trace-base';
|
|
|
3
3
|
import { P as PrivacyConfig } from './functional-04Wr-1U_.js';
|
|
4
4
|
export { T as TraceContext, e as extractContext, g as getActiveContext, a as getTraceparent, t as trace } from './functional-04Wr-1U_.js';
|
|
5
5
|
|
|
6
|
+
/**
|
|
7
|
+
* Browser-safe string redaction. Duplicate of autotel's redact-values.ts.
|
|
8
|
+
* Must NOT import from `autotel` (Node.js package).
|
|
9
|
+
*/
|
|
10
|
+
type StringRedactor = (value: string) => string;
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* Structured error types for autotel-web error tracking.
|
|
14
|
+
* Compatible with PostHog's $exception_list format and OTel semantic conventions.
|
|
15
|
+
*/
|
|
16
|
+
|
|
17
|
+
interface SuppressionRule {
|
|
18
|
+
/** Field to match against */
|
|
19
|
+
key: 'type' | 'value';
|
|
20
|
+
/** Match operator */
|
|
21
|
+
operator: 'exact' | 'contains' | 'regex';
|
|
22
|
+
/** Value or pattern to match */
|
|
23
|
+
value: string;
|
|
24
|
+
}
|
|
25
|
+
interface RateLimitConfig {
|
|
26
|
+
/** Max exceptions per type within the window (default: 10) */
|
|
27
|
+
maxPerType: number;
|
|
28
|
+
/** Time window in milliseconds (default: 10000) */
|
|
29
|
+
windowMs: number;
|
|
30
|
+
}
|
|
31
|
+
interface ErrorTrackingConfig {
|
|
32
|
+
/** Rate limit per exception type */
|
|
33
|
+
rateLimit?: RateLimitConfig;
|
|
34
|
+
/** Suppression rules to filter known noise */
|
|
35
|
+
suppressionRules?: SuppressionRule[];
|
|
36
|
+
/** Capture console.error as exceptions (default: false) */
|
|
37
|
+
captureConsoleErrors?: boolean;
|
|
38
|
+
/** Skip autocapture if window.posthog is detected (default: true) */
|
|
39
|
+
deferToPostHog?: boolean;
|
|
40
|
+
/** Debug logging */
|
|
41
|
+
debug?: boolean;
|
|
42
|
+
/** String redactor for PII in error messages and stack traces */
|
|
43
|
+
redactor?: StringRedactor;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
* Manually capture an exception.
|
|
48
|
+
* Use this for caught errors you want to track.
|
|
49
|
+
*/
|
|
50
|
+
declare function captureException(error: unknown): void;
|
|
51
|
+
|
|
6
52
|
/**
|
|
7
53
|
* Full browser tracing with OpenTelemetry SDK
|
|
8
54
|
*
|
|
@@ -74,6 +120,20 @@ interface AutotelWebFullConfig {
|
|
|
74
120
|
* @default false
|
|
75
121
|
*/
|
|
76
122
|
captureLongTasks?: boolean;
|
|
123
|
+
/**
|
|
124
|
+
* Advanced error tracking configuration.
|
|
125
|
+
* When captureErrors is true (default), this configures rate limiting, suppression, etc.
|
|
126
|
+
*/
|
|
127
|
+
errorTracking?: Omit<ErrorTrackingConfig, 'debug'>;
|
|
128
|
+
/** Redact PII from error messages and stack traces before export. Preset or custom config. */
|
|
129
|
+
attributeRedactor?: 'default' | 'strict' | 'pci-dss' | {
|
|
130
|
+
valuePatterns?: Array<{
|
|
131
|
+
name: string;
|
|
132
|
+
pattern: RegExp;
|
|
133
|
+
replacement?: string;
|
|
134
|
+
}>;
|
|
135
|
+
replacement?: string;
|
|
136
|
+
};
|
|
77
137
|
/** Privacy controls (origin filtering, DNT, GPC). Applied to which requests get traced. */
|
|
78
138
|
privacy?: PrivacyConfig;
|
|
79
139
|
/** Enable debug logging. @default false */
|
|
@@ -123,4 +183,4 @@ declare function runWithContext<T>(ctx: ReturnType<typeof context.active>, fn: (
|
|
|
123
183
|
*/
|
|
124
184
|
declare function resetFullForTesting(): void;
|
|
125
185
|
|
|
126
|
-
export { type AutotelWebFullConfig, addEvent, initFull, resetFullForTesting, runWithContext, setAttribute, span };
|
|
186
|
+
export { type AutotelWebFullConfig, addEvent, captureException, initFull, resetFullForTesting, runWithContext, setAttribute, span };
|