@obtrace/browser 2.1.0 → 2.2.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/dist/browser/console.js +33 -3
- package/dist/browser/errors.js +18 -4
- package/dist/browser/index.js +6 -6
- package/dist/browser_entry.bundle.js +53 -13
- package/dist/browser_entry.bundle.js.map +2 -2
- package/dist/core/otel-web-setup.js +1 -0
- package/dist/types/browser/console.d.ts +1 -1
- package/dist/types/core/otel-web-setup.d.ts +3 -1
- package/dist/types/wrappers/frontend/react.d.ts +2 -0
- package/dist/wrappers/frontend/react.js +57 -0
- package/package.json +1 -1
package/dist/browser/console.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { SpanStatusCode } from "@opentelemetry/api";
|
|
1
2
|
import { addBreadcrumb } from "./breadcrumbs";
|
|
2
3
|
const LEVEL_MAP = {
|
|
3
4
|
debug: "debug",
|
|
@@ -31,8 +32,23 @@ export function installConsoleCapture(tracer, sessionId) {
|
|
|
31
32
|
return String(v);
|
|
32
33
|
}
|
|
33
34
|
};
|
|
34
|
-
|
|
35
|
-
|
|
35
|
+
const firstArg = args[0];
|
|
36
|
+
const isErrorObj = firstArg instanceof Error;
|
|
37
|
+
if (isErrorObj) {
|
|
38
|
+
const err = firstArg;
|
|
39
|
+
message = `${err.name}: ${err.message}`;
|
|
40
|
+
if (err.stack)
|
|
41
|
+
attrs["error.stack"] = err.stack.slice(0, 4096);
|
|
42
|
+
attrs["error.type"] = err.name;
|
|
43
|
+
for (let i = 1; i < args.length; i++) {
|
|
44
|
+
const extra = args[i];
|
|
45
|
+
if (typeof extra === "string" && extra.includes("\n at ")) {
|
|
46
|
+
attrs["error.component_stack"] = extra.slice(0, 4096);
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
else if (args.length === 1 && typeof firstArg === "object" && firstArg !== null && !Array.isArray(firstArg)) {
|
|
51
|
+
const obj = firstArg;
|
|
36
52
|
message = String(obj.msg || obj.message || safeStringify(obj));
|
|
37
53
|
for (const [k, v] of Object.entries(obj)) {
|
|
38
54
|
if (k === "msg" || k === "message")
|
|
@@ -44,9 +60,18 @@ export function installConsoleCapture(tracer, sessionId) {
|
|
|
44
60
|
}
|
|
45
61
|
else {
|
|
46
62
|
message = args.map(a => typeof a === "string" ? a : safeStringify(a)).join(" ");
|
|
63
|
+
if (method === "error") {
|
|
64
|
+
for (const a of args) {
|
|
65
|
+
if (typeof a === "string" && a.includes("\n at ")) {
|
|
66
|
+
attrs["error.stack"] = a.slice(0, 4096);
|
|
67
|
+
break;
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
}
|
|
47
71
|
}
|
|
48
72
|
addBreadcrumb({ timestamp: Date.now(), category: `console.${method}`, message, level, data: attrs });
|
|
49
|
-
const
|
|
73
|
+
const spanName = (method === "error" && (isErrorObj || attrs["error.stack"])) ? "browser.error" : "browser.console";
|
|
74
|
+
const span = tracer.startSpan(spanName, {
|
|
50
75
|
attributes: {
|
|
51
76
|
"log.severity": level.toUpperCase(),
|
|
52
77
|
"log.message": message.slice(0, 1024),
|
|
@@ -54,6 +79,11 @@ export function installConsoleCapture(tracer, sessionId) {
|
|
|
54
79
|
...attrs,
|
|
55
80
|
},
|
|
56
81
|
});
|
|
82
|
+
if (method === "error") {
|
|
83
|
+
span.setStatus({ code: SpanStatusCode.ERROR, message: message.slice(0, 1024) });
|
|
84
|
+
if (isErrorObj)
|
|
85
|
+
span.recordException(firstArg);
|
|
86
|
+
}
|
|
57
87
|
span.end();
|
|
58
88
|
}
|
|
59
89
|
catch { }
|
package/dist/browser/errors.js
CHANGED
|
@@ -5,21 +5,25 @@ export function installBrowserErrorHooks(tracer, sessionId) {
|
|
|
5
5
|
return () => undefined;
|
|
6
6
|
}
|
|
7
7
|
const onError = (ev) => {
|
|
8
|
-
|
|
8
|
+
const message = ev.message || "window.error";
|
|
9
|
+
addBreadcrumb({ timestamp: Date.now(), category: "error", message, level: "error" });
|
|
9
10
|
try {
|
|
10
11
|
const breadcrumbs = getBreadcrumbs();
|
|
12
|
+
const stack = ev.error instanceof Error ? ev.error.stack || "" : "";
|
|
11
13
|
const span = tracer.startSpan("browser.error", {
|
|
12
14
|
attributes: {
|
|
13
|
-
"error.message":
|
|
15
|
+
"error.message": message,
|
|
14
16
|
"error.file": ev.filename || "",
|
|
15
17
|
"error.line": ev.lineno || 0,
|
|
16
18
|
"error.column": ev.colno || 0,
|
|
19
|
+
"error.stack": stack.slice(0, 4096),
|
|
20
|
+
"error.type": ev.error?.constructor?.name || "Error",
|
|
17
21
|
"breadcrumbs.count": breadcrumbs.length,
|
|
18
22
|
"breadcrumbs.json": JSON.stringify(breadcrumbs.slice(-20)),
|
|
19
23
|
...(sessionId ? { "session.id": sessionId } : {}),
|
|
20
24
|
},
|
|
21
25
|
});
|
|
22
|
-
span.setStatus({ code: SpanStatusCode.ERROR, message
|
|
26
|
+
span.setStatus({ code: SpanStatusCode.ERROR, message });
|
|
23
27
|
if (ev.error instanceof Error) {
|
|
24
28
|
span.recordException(ev.error);
|
|
25
29
|
}
|
|
@@ -28,13 +32,23 @@ export function installBrowserErrorHooks(tracer, sessionId) {
|
|
|
28
32
|
catch { }
|
|
29
33
|
};
|
|
30
34
|
const onRejection = (ev) => {
|
|
31
|
-
|
|
35
|
+
let reason;
|
|
36
|
+
let stack = "";
|
|
37
|
+
if (ev.reason instanceof Error) {
|
|
38
|
+
reason = `${ev.reason.name}: ${ev.reason.message}`;
|
|
39
|
+
stack = ev.reason.stack || "";
|
|
40
|
+
}
|
|
41
|
+
else {
|
|
42
|
+
reason = typeof ev.reason === "string" ? ev.reason : JSON.stringify(ev.reason ?? {});
|
|
43
|
+
}
|
|
32
44
|
addBreadcrumb({ timestamp: Date.now(), category: "error", message: reason, level: "error" });
|
|
33
45
|
try {
|
|
34
46
|
const breadcrumbs = getBreadcrumbs();
|
|
35
47
|
const span = tracer.startSpan("browser.unhandledrejection", {
|
|
36
48
|
attributes: {
|
|
37
49
|
"error.message": reason,
|
|
50
|
+
"error.stack": stack.slice(0, 4096),
|
|
51
|
+
"error.type": ev.reason?.constructor?.name || "UnhandledRejection",
|
|
38
52
|
"breadcrumbs.count": breadcrumbs.length,
|
|
39
53
|
"breadcrumbs.json": JSON.stringify(breadcrumbs.slice(-20)),
|
|
40
54
|
...(sessionId ? { "session.id": sessionId } : {}),
|
package/dist/browser/index.js
CHANGED
|
@@ -157,7 +157,12 @@ export function initBrowserSDK(config) {
|
|
|
157
157
|
const sampleRate = config.tracesSampleRate ?? 1;
|
|
158
158
|
const replaySampleRate = config.replaySampleRate ?? 1;
|
|
159
159
|
const shouldReplay = Math.random() < replaySampleRate;
|
|
160
|
-
const
|
|
160
|
+
const replay = new BrowserReplayBuffer({
|
|
161
|
+
maxChunkBytes: config.replay?.maxChunkBytes ?? 480_000,
|
|
162
|
+
flushIntervalMs: config.replay?.flushIntervalMs ?? 5000,
|
|
163
|
+
sessionStorageKey: config.replay?.sessionStorageKey ?? "obtrace_session_id",
|
|
164
|
+
});
|
|
165
|
+
const otel = setupOtelWeb({ ...config, tracesSampleRate: sampleRate, sessionId: replay.sessionId });
|
|
161
166
|
const tracer = otel.tracer;
|
|
162
167
|
const meter = otel.meter;
|
|
163
168
|
const client = new ObtraceClient({
|
|
@@ -173,11 +178,6 @@ export function initBrowserSDK(config) {
|
|
|
173
178
|
vitals: { enabled: true, reportAllChanges: false, ...config.vitals },
|
|
174
179
|
propagation: { enabled: true, ...config.propagation },
|
|
175
180
|
});
|
|
176
|
-
const replay = new BrowserReplayBuffer({
|
|
177
|
-
maxChunkBytes: config.replay?.maxChunkBytes ?? 480_000,
|
|
178
|
-
flushIntervalMs: config.replay?.flushIntervalMs ?? 5000,
|
|
179
|
-
sessionStorageKey: config.replay?.sessionStorageKey ?? "obtrace_session_id",
|
|
180
|
-
});
|
|
181
181
|
const recipeSteps = [];
|
|
182
182
|
const cleanups = [];
|
|
183
183
|
const entry = { client, sessionId: replay.sessionId, replay, config, recipeSteps, otel };
|
|
@@ -27784,6 +27784,7 @@ function setupOtelWeb(config) {
|
|
|
27784
27784
|
...config.projectId ? { "obtrace.project_id": config.projectId } : {},
|
|
27785
27785
|
...config.appId ? { "obtrace.app_id": config.appId } : {},
|
|
27786
27786
|
...config.env ? { "obtrace.env": config.env } : {},
|
|
27787
|
+
...config.sessionId ? { "session.id": config.sessionId } : {},
|
|
27787
27788
|
"runtime.name": "browser"
|
|
27788
27789
|
});
|
|
27789
27790
|
const traceExporter = new OTLPTraceExporter({
|
|
@@ -27904,21 +27905,25 @@ function installBrowserErrorHooks(tracer, sessionId) {
|
|
|
27904
27905
|
return () => void 0;
|
|
27905
27906
|
}
|
|
27906
27907
|
const onError = (ev) => {
|
|
27907
|
-
|
|
27908
|
+
const message = ev.message || "window.error";
|
|
27909
|
+
addBreadcrumb({ timestamp: Date.now(), category: "error", message, level: "error" });
|
|
27908
27910
|
try {
|
|
27909
27911
|
const breadcrumbs = getBreadcrumbs();
|
|
27912
|
+
const stack = ev.error instanceof Error ? ev.error.stack || "" : "";
|
|
27910
27913
|
const span = tracer.startSpan("browser.error", {
|
|
27911
27914
|
attributes: {
|
|
27912
|
-
"error.message":
|
|
27915
|
+
"error.message": message,
|
|
27913
27916
|
"error.file": ev.filename || "",
|
|
27914
27917
|
"error.line": ev.lineno || 0,
|
|
27915
27918
|
"error.column": ev.colno || 0,
|
|
27919
|
+
"error.stack": stack.slice(0, 4096),
|
|
27920
|
+
"error.type": ev.error?.constructor?.name || "Error",
|
|
27916
27921
|
"breadcrumbs.count": breadcrumbs.length,
|
|
27917
27922
|
"breadcrumbs.json": JSON.stringify(breadcrumbs.slice(-20)),
|
|
27918
27923
|
...sessionId ? { "session.id": sessionId } : {}
|
|
27919
27924
|
}
|
|
27920
27925
|
});
|
|
27921
|
-
span.setStatus({ code: SpanStatusCode.ERROR, message
|
|
27926
|
+
span.setStatus({ code: SpanStatusCode.ERROR, message });
|
|
27922
27927
|
if (ev.error instanceof Error) {
|
|
27923
27928
|
span.recordException(ev.error);
|
|
27924
27929
|
}
|
|
@@ -27927,13 +27932,22 @@ function installBrowserErrorHooks(tracer, sessionId) {
|
|
|
27927
27932
|
}
|
|
27928
27933
|
};
|
|
27929
27934
|
const onRejection = (ev) => {
|
|
27930
|
-
|
|
27935
|
+
let reason;
|
|
27936
|
+
let stack = "";
|
|
27937
|
+
if (ev.reason instanceof Error) {
|
|
27938
|
+
reason = `${ev.reason.name}: ${ev.reason.message}`;
|
|
27939
|
+
stack = ev.reason.stack || "";
|
|
27940
|
+
} else {
|
|
27941
|
+
reason = typeof ev.reason === "string" ? ev.reason : JSON.stringify(ev.reason ?? {});
|
|
27942
|
+
}
|
|
27931
27943
|
addBreadcrumb({ timestamp: Date.now(), category: "error", message: reason, level: "error" });
|
|
27932
27944
|
try {
|
|
27933
27945
|
const breadcrumbs = getBreadcrumbs();
|
|
27934
27946
|
const span = tracer.startSpan("browser.unhandledrejection", {
|
|
27935
27947
|
attributes: {
|
|
27936
27948
|
"error.message": reason,
|
|
27949
|
+
"error.stack": stack.slice(0, 4096),
|
|
27950
|
+
"error.type": ev.reason?.constructor?.name || "UnhandledRejection",
|
|
27937
27951
|
"breadcrumbs.count": breadcrumbs.length,
|
|
27938
27952
|
"breadcrumbs.json": JSON.stringify(breadcrumbs.slice(-20)),
|
|
27939
27953
|
...sessionId ? { "session.id": sessionId } : {}
|
|
@@ -28245,8 +28259,21 @@ function installConsoleCapture(tracer, sessionId) {
|
|
|
28245
28259
|
return String(v);
|
|
28246
28260
|
}
|
|
28247
28261
|
};
|
|
28248
|
-
|
|
28249
|
-
|
|
28262
|
+
const firstArg = args[0];
|
|
28263
|
+
const isErrorObj = firstArg instanceof Error;
|
|
28264
|
+
if (isErrorObj) {
|
|
28265
|
+
const err = firstArg;
|
|
28266
|
+
message = `${err.name}: ${err.message}`;
|
|
28267
|
+
if (err.stack) attrs["error.stack"] = err.stack.slice(0, 4096);
|
|
28268
|
+
attrs["error.type"] = err.name;
|
|
28269
|
+
for (let i = 1; i < args.length; i++) {
|
|
28270
|
+
const extra = args[i];
|
|
28271
|
+
if (typeof extra === "string" && extra.includes("\n at ")) {
|
|
28272
|
+
attrs["error.component_stack"] = extra.slice(0, 4096);
|
|
28273
|
+
}
|
|
28274
|
+
}
|
|
28275
|
+
} else if (args.length === 1 && typeof firstArg === "object" && firstArg !== null && !Array.isArray(firstArg)) {
|
|
28276
|
+
const obj = firstArg;
|
|
28250
28277
|
message = String(obj.msg || obj.message || safeStringify(obj));
|
|
28251
28278
|
for (const [k, v] of Object.entries(obj)) {
|
|
28252
28279
|
if (k === "msg" || k === "message") continue;
|
|
@@ -28256,9 +28283,18 @@ function installConsoleCapture(tracer, sessionId) {
|
|
|
28256
28283
|
}
|
|
28257
28284
|
} else {
|
|
28258
28285
|
message = args.map((a) => typeof a === "string" ? a : safeStringify(a)).join(" ");
|
|
28286
|
+
if (method === "error") {
|
|
28287
|
+
for (const a of args) {
|
|
28288
|
+
if (typeof a === "string" && a.includes("\n at ")) {
|
|
28289
|
+
attrs["error.stack"] = a.slice(0, 4096);
|
|
28290
|
+
break;
|
|
28291
|
+
}
|
|
28292
|
+
}
|
|
28293
|
+
}
|
|
28259
28294
|
}
|
|
28260
28295
|
addBreadcrumb({ timestamp: Date.now(), category: `console.${method}`, message, level, data: attrs });
|
|
28261
|
-
const
|
|
28296
|
+
const spanName = method === "error" && (isErrorObj || attrs["error.stack"]) ? "browser.error" : "browser.console";
|
|
28297
|
+
const span = tracer.startSpan(spanName, {
|
|
28262
28298
|
attributes: {
|
|
28263
28299
|
"log.severity": level.toUpperCase(),
|
|
28264
28300
|
"log.message": message.slice(0, 1024),
|
|
@@ -28266,6 +28302,10 @@ function installConsoleCapture(tracer, sessionId) {
|
|
|
28266
28302
|
...attrs
|
|
28267
28303
|
}
|
|
28268
28304
|
});
|
|
28305
|
+
if (method === "error") {
|
|
28306
|
+
span.setStatus({ code: SpanStatusCode.ERROR, message: message.slice(0, 1024) });
|
|
28307
|
+
if (isErrorObj) span.recordException(firstArg);
|
|
28308
|
+
}
|
|
28269
28309
|
span.end();
|
|
28270
28310
|
} catch {
|
|
28271
28311
|
}
|
|
@@ -28552,7 +28592,12 @@ function initBrowserSDK(config) {
|
|
|
28552
28592
|
const sampleRate = config.tracesSampleRate ?? 1;
|
|
28553
28593
|
const replaySampleRate = config.replaySampleRate ?? 1;
|
|
28554
28594
|
const shouldReplay = Math.random() < replaySampleRate;
|
|
28555
|
-
const
|
|
28595
|
+
const replay = new BrowserReplayBuffer({
|
|
28596
|
+
maxChunkBytes: config.replay?.maxChunkBytes ?? 48e4,
|
|
28597
|
+
flushIntervalMs: config.replay?.flushIntervalMs ?? 5e3,
|
|
28598
|
+
sessionStorageKey: config.replay?.sessionStorageKey ?? "obtrace_session_id"
|
|
28599
|
+
});
|
|
28600
|
+
const otel = setupOtelWeb({ ...config, tracesSampleRate: sampleRate, sessionId: replay.sessionId });
|
|
28556
28601
|
const tracer = otel.tracer;
|
|
28557
28602
|
const meter = otel.meter;
|
|
28558
28603
|
const client = new ObtraceClient({
|
|
@@ -28568,11 +28613,6 @@ function initBrowserSDK(config) {
|
|
|
28568
28613
|
vitals: { enabled: true, reportAllChanges: false, ...config.vitals },
|
|
28569
28614
|
propagation: { enabled: true, ...config.propagation }
|
|
28570
28615
|
});
|
|
28571
|
-
const replay = new BrowserReplayBuffer({
|
|
28572
|
-
maxChunkBytes: config.replay?.maxChunkBytes ?? 48e4,
|
|
28573
|
-
flushIntervalMs: config.replay?.flushIntervalMs ?? 5e3,
|
|
28574
|
-
sessionStorageKey: config.replay?.sessionStorageKey ?? "obtrace_session_id"
|
|
28575
|
-
});
|
|
28576
28616
|
const recipeSteps = [];
|
|
28577
28617
|
const cleanups = [];
|
|
28578
28618
|
const entry = { client, sessionId: replay.sessionId, replay, config, recipeSteps, otel };
|