@statly/observe 1.0.0 → 1.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/README.md +142 -1
- package/dist/chunk-7AITSJLP.mjs +1422 -0
- package/dist/chunk-J5AHUFP2.mjs +135 -0
- package/dist/{chunk-UNDSALI5.mjs → chunk-SJ7C46AP.mjs} +190 -122
- package/dist/index.d.mts +80 -43
- package/dist/index.d.ts +80 -43
- package/dist/index.js +1883 -207
- package/dist/index.mjs +62 -1
- package/dist/integrations/express.js +259 -35
- package/dist/integrations/express.mjs +3 -1
- package/dist/integrations/fastify.js +271 -47
- package/dist/integrations/fastify.mjs +3 -1
- package/dist/integrations/nextjs.js +347 -104
- package/dist/integrations/nextjs.mjs +3 -1
- package/dist/logger/index.d.mts +671 -0
- package/dist/logger/index.d.ts +671 -0
- package/dist/logger/index.js +1483 -0
- package/dist/logger/index.mjs +56 -0
- package/dist/telemetry-CXHOTW3Y.mjs +8 -0
- package/package.json +7 -2
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
// src/span.ts
|
|
2
|
+
var Span = class {
|
|
3
|
+
constructor(name, context, tags) {
|
|
4
|
+
this._status = "ok" /* OK */;
|
|
5
|
+
this._tags = {};
|
|
6
|
+
this._metadata = {};
|
|
7
|
+
this._finished = false;
|
|
8
|
+
this.name = name;
|
|
9
|
+
this.context = context;
|
|
10
|
+
this.startTime = Date.now();
|
|
11
|
+
if (tags) this._tags = { ...tags };
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* Finish the span and calculate duration
|
|
15
|
+
*/
|
|
16
|
+
finish(endTime) {
|
|
17
|
+
if (this._finished) return;
|
|
18
|
+
this._endTime = endTime || Date.now();
|
|
19
|
+
this._durationMs = this._endTime - this.startTime;
|
|
20
|
+
this._finished = true;
|
|
21
|
+
}
|
|
22
|
+
setTag(key, value) {
|
|
23
|
+
this._tags[key] = value;
|
|
24
|
+
return this;
|
|
25
|
+
}
|
|
26
|
+
setMetadata(key, value) {
|
|
27
|
+
this._metadata[key] = value;
|
|
28
|
+
return this;
|
|
29
|
+
}
|
|
30
|
+
setStatus(status) {
|
|
31
|
+
this._status = status;
|
|
32
|
+
return this;
|
|
33
|
+
}
|
|
34
|
+
get status() {
|
|
35
|
+
return this._status;
|
|
36
|
+
}
|
|
37
|
+
get tags() {
|
|
38
|
+
return { ...this._tags };
|
|
39
|
+
}
|
|
40
|
+
get durationMs() {
|
|
41
|
+
return this._durationMs;
|
|
42
|
+
}
|
|
43
|
+
toDict() {
|
|
44
|
+
return {
|
|
45
|
+
name: this.name,
|
|
46
|
+
traceId: this.context.traceId,
|
|
47
|
+
spanId: this.context.spanId,
|
|
48
|
+
parentId: this.context.parentId,
|
|
49
|
+
startTime: this.startTime,
|
|
50
|
+
endTime: this._endTime,
|
|
51
|
+
durationMs: this._durationMs,
|
|
52
|
+
status: this._status,
|
|
53
|
+
tags: this._tags,
|
|
54
|
+
metadata: this._metadata
|
|
55
|
+
};
|
|
56
|
+
}
|
|
57
|
+
};
|
|
58
|
+
var TraceContext = class {
|
|
59
|
+
static getActiveSpan() {
|
|
60
|
+
return this.currentSpan;
|
|
61
|
+
}
|
|
62
|
+
static setActiveSpan(span) {
|
|
63
|
+
this.currentSpan = span;
|
|
64
|
+
}
|
|
65
|
+
};
|
|
66
|
+
TraceContext.currentSpan = null;
|
|
67
|
+
|
|
68
|
+
// src/telemetry.ts
|
|
69
|
+
var TelemetryProvider = class _TelemetryProvider {
|
|
70
|
+
constructor() {
|
|
71
|
+
this.client = null;
|
|
72
|
+
}
|
|
73
|
+
static getInstance() {
|
|
74
|
+
if (!_TelemetryProvider.instance) {
|
|
75
|
+
_TelemetryProvider.instance = new _TelemetryProvider();
|
|
76
|
+
}
|
|
77
|
+
return _TelemetryProvider.instance;
|
|
78
|
+
}
|
|
79
|
+
setClient(client) {
|
|
80
|
+
this.client = client;
|
|
81
|
+
}
|
|
82
|
+
/**
|
|
83
|
+
* Start a new span
|
|
84
|
+
*/
|
|
85
|
+
startSpan(name, tags) {
|
|
86
|
+
const parent = TraceContext.getActiveSpan();
|
|
87
|
+
const traceId = parent ? parent.context.traceId : this.generateId();
|
|
88
|
+
const parentId = parent ? parent.context.spanId : null;
|
|
89
|
+
const span = new Span(name, {
|
|
90
|
+
traceId,
|
|
91
|
+
spanId: this.generateId(),
|
|
92
|
+
parentId
|
|
93
|
+
}, tags);
|
|
94
|
+
TraceContext.setActiveSpan(span);
|
|
95
|
+
return span;
|
|
96
|
+
}
|
|
97
|
+
/**
|
|
98
|
+
* Finish and report a span
|
|
99
|
+
*/
|
|
100
|
+
finishSpan(span) {
|
|
101
|
+
span.finish();
|
|
102
|
+
if (TraceContext.getActiveSpan() === span) {
|
|
103
|
+
TraceContext.setActiveSpan(null);
|
|
104
|
+
}
|
|
105
|
+
if (this.client) {
|
|
106
|
+
this.client.captureSpan(span);
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
generateId() {
|
|
110
|
+
return Math.random().toString(16).substring(2, 18);
|
|
111
|
+
}
|
|
112
|
+
};
|
|
113
|
+
async function trace(name, operation, tags) {
|
|
114
|
+
const provider = TelemetryProvider.getInstance();
|
|
115
|
+
const span = provider.startSpan(name, tags);
|
|
116
|
+
try {
|
|
117
|
+
const result = await operation(span);
|
|
118
|
+
return result;
|
|
119
|
+
} catch (error) {
|
|
120
|
+
span.setStatus("error" /* ERROR */);
|
|
121
|
+
span.setTag("error", "true");
|
|
122
|
+
if (error instanceof Error) {
|
|
123
|
+
span.setTag("exception.type", error.name);
|
|
124
|
+
span.setTag("exception.message", error.message);
|
|
125
|
+
}
|
|
126
|
+
throw error;
|
|
127
|
+
} finally {
|
|
128
|
+
provider.finishSpan(span);
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
export {
|
|
133
|
+
TelemetryProvider,
|
|
134
|
+
trace
|
|
135
|
+
};
|
|
@@ -1,3 +1,7 @@
|
|
|
1
|
+
import {
|
|
2
|
+
TelemetryProvider
|
|
3
|
+
} from "./chunk-J5AHUFP2.mjs";
|
|
4
|
+
|
|
1
5
|
// src/transport.ts
|
|
2
6
|
var Transport = class {
|
|
3
7
|
constructor(options) {
|
|
@@ -58,10 +62,10 @@ var Transport = class {
|
|
|
58
62
|
this.queue = [];
|
|
59
63
|
try {
|
|
60
64
|
await this.sendBatch(events);
|
|
61
|
-
} catch (
|
|
65
|
+
} catch (error2) {
|
|
62
66
|
this.queue = [...events, ...this.queue].slice(0, this.maxQueueSize);
|
|
63
67
|
if (this.debug) {
|
|
64
|
-
console.error("[Statly] Failed to send events:",
|
|
68
|
+
console.error("[Statly] Failed to send events:", error2);
|
|
65
69
|
}
|
|
66
70
|
} finally {
|
|
67
71
|
this.isSending = false;
|
|
@@ -101,13 +105,13 @@ var Transport = class {
|
|
|
101
105
|
console.log(`[Statly] Sent ${events.length} event(s)`);
|
|
102
106
|
}
|
|
103
107
|
return { success: true, status: response.status };
|
|
104
|
-
} catch (
|
|
108
|
+
} catch (error2) {
|
|
105
109
|
if (this.debug) {
|
|
106
|
-
console.error("[Statly] Network error:",
|
|
110
|
+
console.error("[Statly] Network error:", error2);
|
|
107
111
|
}
|
|
108
112
|
return {
|
|
109
113
|
success: false,
|
|
110
|
-
error:
|
|
114
|
+
error: error2 instanceof Error ? error2.message : "Network error"
|
|
111
115
|
};
|
|
112
116
|
}
|
|
113
117
|
}
|
|
@@ -174,16 +178,16 @@ var GlobalHandlers = class {
|
|
|
174
178
|
if (!this.errorCallback) {
|
|
175
179
|
return;
|
|
176
180
|
}
|
|
177
|
-
let
|
|
181
|
+
let error2;
|
|
178
182
|
if (event.reason instanceof Error) {
|
|
179
|
-
|
|
183
|
+
error2 = event.reason;
|
|
180
184
|
} else if (typeof event.reason === "string") {
|
|
181
|
-
|
|
185
|
+
error2 = new Error(event.reason);
|
|
182
186
|
} else {
|
|
183
|
-
|
|
184
|
-
|
|
187
|
+
error2 = new Error("Unhandled Promise Rejection");
|
|
188
|
+
error2.reason = event.reason;
|
|
185
189
|
}
|
|
186
|
-
this.errorCallback(
|
|
190
|
+
this.errorCallback(error2, {
|
|
187
191
|
mechanism: { type: "onunhandledrejection", handled: false }
|
|
188
192
|
});
|
|
189
193
|
};
|
|
@@ -226,13 +230,13 @@ var GlobalHandlers = class {
|
|
|
226
230
|
}
|
|
227
231
|
installOnError() {
|
|
228
232
|
this.originalOnError = window.onerror;
|
|
229
|
-
window.onerror = (message, source, lineno, colno,
|
|
233
|
+
window.onerror = (message, source, lineno, colno, error2) => {
|
|
230
234
|
if (this.originalOnError) {
|
|
231
|
-
this.originalOnError.call(window, message, source, lineno, colno,
|
|
235
|
+
this.originalOnError.call(window, message, source, lineno, colno, error2);
|
|
232
236
|
}
|
|
233
237
|
if (this.errorCallback) {
|
|
234
|
-
const errorObj =
|
|
235
|
-
if (!
|
|
238
|
+
const errorObj = error2 || new Error(String(message));
|
|
239
|
+
if (!error2 && source) {
|
|
236
240
|
errorObj.filename = source;
|
|
237
241
|
errorObj.lineno = lineno;
|
|
238
242
|
errorObj.colno = colno;
|
|
@@ -356,6 +360,7 @@ var StatlyClient = class {
|
|
|
356
360
|
this.breadcrumbs = new BreadcrumbManager(this.options.maxBreadcrumbs);
|
|
357
361
|
this.globalHandlers = new GlobalHandlers();
|
|
358
362
|
this.consoleIntegration = new ConsoleIntegration();
|
|
363
|
+
TelemetryProvider.getInstance().setClient(this);
|
|
359
364
|
}
|
|
360
365
|
mergeOptions(options) {
|
|
361
366
|
return {
|
|
@@ -395,8 +400,8 @@ var StatlyClient = class {
|
|
|
395
400
|
}
|
|
396
401
|
this.initialized = true;
|
|
397
402
|
if (this.options.autoCapture) {
|
|
398
|
-
this.globalHandlers.install((
|
|
399
|
-
this.captureError(
|
|
403
|
+
this.globalHandlers.install((error2, context) => {
|
|
404
|
+
this.captureError(error2, context);
|
|
400
405
|
});
|
|
401
406
|
}
|
|
402
407
|
if (this.options.captureConsole) {
|
|
@@ -419,15 +424,15 @@ var StatlyClient = class {
|
|
|
419
424
|
/**
|
|
420
425
|
* Capture an exception/error
|
|
421
426
|
*/
|
|
422
|
-
captureException(
|
|
427
|
+
captureException(error2, context) {
|
|
423
428
|
let errorObj;
|
|
424
|
-
if (
|
|
425
|
-
errorObj =
|
|
426
|
-
} else if (typeof
|
|
427
|
-
errorObj = new Error(
|
|
429
|
+
if (error2 instanceof Error) {
|
|
430
|
+
errorObj = error2;
|
|
431
|
+
} else if (typeof error2 === "string") {
|
|
432
|
+
errorObj = new Error(error2);
|
|
428
433
|
} else {
|
|
429
434
|
errorObj = new Error("Unknown error");
|
|
430
|
-
errorObj.originalError =
|
|
435
|
+
errorObj.originalError = error2;
|
|
431
436
|
}
|
|
432
437
|
return this.captureError(errorObj, context);
|
|
433
438
|
}
|
|
@@ -441,21 +446,45 @@ var StatlyClient = class {
|
|
|
441
446
|
});
|
|
442
447
|
return this.sendEvent(event);
|
|
443
448
|
}
|
|
449
|
+
/**
|
|
450
|
+
* Capture a completed span
|
|
451
|
+
*/
|
|
452
|
+
captureSpan(span) {
|
|
453
|
+
const event = this.buildEvent({
|
|
454
|
+
message: `Span: ${span.name}`,
|
|
455
|
+
level: "span",
|
|
456
|
+
span: span.toDict()
|
|
457
|
+
});
|
|
458
|
+
return this.sendEvent(event);
|
|
459
|
+
}
|
|
460
|
+
/**
|
|
461
|
+
* Start a new tracing span
|
|
462
|
+
*/
|
|
463
|
+
startSpan(name, tags) {
|
|
464
|
+
return TelemetryProvider.getInstance().startSpan(name, tags);
|
|
465
|
+
}
|
|
466
|
+
/**
|
|
467
|
+
* Execute a function within a trace span
|
|
468
|
+
*/
|
|
469
|
+
async trace(name, operation, tags) {
|
|
470
|
+
const { trace: traceFn } = await import("./telemetry-CXHOTW3Y.mjs");
|
|
471
|
+
return traceFn(name, operation, tags);
|
|
472
|
+
}
|
|
444
473
|
/**
|
|
445
474
|
* Internal method to capture an error
|
|
446
475
|
*/
|
|
447
|
-
captureError(
|
|
476
|
+
captureError(error2, context) {
|
|
448
477
|
if (Math.random() > this.options.sampleRate) {
|
|
449
478
|
return "";
|
|
450
479
|
}
|
|
451
480
|
const event = this.buildEvent({
|
|
452
|
-
message:
|
|
481
|
+
message: error2.message,
|
|
453
482
|
level: "error",
|
|
454
|
-
stack:
|
|
483
|
+
stack: error2.stack,
|
|
455
484
|
exception: {
|
|
456
|
-
type:
|
|
457
|
-
value:
|
|
458
|
-
stacktrace: this.parseStackTrace(
|
|
485
|
+
type: error2.name,
|
|
486
|
+
value: error2.message,
|
|
487
|
+
stacktrace: this.parseStackTrace(error2.stack)
|
|
459
488
|
},
|
|
460
489
|
extra: context
|
|
461
490
|
});
|
|
@@ -652,73 +681,88 @@ var StatlyClient = class {
|
|
|
652
681
|
// src/integrations/nextjs.ts
|
|
653
682
|
function withStatlyPagesApi(handler) {
|
|
654
683
|
return async (req, res) => {
|
|
655
|
-
Statly.
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
try {
|
|
665
|
-
return await handler(req, res);
|
|
666
|
-
} catch (error) {
|
|
667
|
-
const context = {
|
|
668
|
-
request: {
|
|
684
|
+
return Statly.trace(`${req.method} ${req.url}`, async (span) => {
|
|
685
|
+
span.setTag("component", "nextjs-pages-api");
|
|
686
|
+
span.setTag("http.method", req.method || "GET");
|
|
687
|
+
span.setTag("http.url", req.url || "unknown");
|
|
688
|
+
Statly.addBreadcrumb({
|
|
689
|
+
category: "http",
|
|
690
|
+
message: `${req.method} ${req.url}`,
|
|
691
|
+
level: "info",
|
|
692
|
+
data: {
|
|
669
693
|
method: req.method,
|
|
670
|
-
url: req.url
|
|
671
|
-
headers: sanitizeHeaders(req.headers),
|
|
672
|
-
query: req.query
|
|
694
|
+
url: req.url
|
|
673
695
|
}
|
|
674
|
-
};
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
|
|
696
|
+
});
|
|
697
|
+
try {
|
|
698
|
+
const result = await handler(req, res);
|
|
699
|
+
return result;
|
|
700
|
+
} catch (error2) {
|
|
701
|
+
const context = {
|
|
702
|
+
request: {
|
|
703
|
+
method: req.method,
|
|
704
|
+
url: req.url,
|
|
705
|
+
headers: sanitizeHeaders(req.headers),
|
|
706
|
+
query: req.query
|
|
707
|
+
}
|
|
708
|
+
};
|
|
709
|
+
Statly.captureException(error2, context);
|
|
710
|
+
throw error2;
|
|
711
|
+
}
|
|
712
|
+
});
|
|
678
713
|
};
|
|
679
714
|
}
|
|
680
715
|
function withStatly(handler) {
|
|
681
716
|
const wrappedHandler = async (request, context) => {
|
|
682
|
-
Statly.
|
|
683
|
-
|
|
684
|
-
|
|
685
|
-
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
try {
|
|
692
|
-
return await handler(request, context);
|
|
693
|
-
} catch (error) {
|
|
694
|
-
const headers = {};
|
|
695
|
-
request.headers.forEach((value, key) => {
|
|
696
|
-
headers[key] = value;
|
|
697
|
-
});
|
|
698
|
-
const errorContext = {
|
|
699
|
-
request: {
|
|
717
|
+
return Statly.trace(`${request.method} ${request.nextUrl?.pathname || request.url}`, async (span) => {
|
|
718
|
+
span.setTag("component", "nextjs-app-router");
|
|
719
|
+
span.setTag("http.method", request.method);
|
|
720
|
+
span.setTag("http.url", request.nextUrl?.pathname || request.url);
|
|
721
|
+
Statly.addBreadcrumb({
|
|
722
|
+
category: "http",
|
|
723
|
+
message: `${request.method} ${request.nextUrl?.pathname || request.url}`,
|
|
724
|
+
level: "info",
|
|
725
|
+
data: {
|
|
700
726
|
method: request.method,
|
|
701
|
-
url: request.nextUrl?.pathname || request.url
|
|
702
|
-
headers: sanitizeHeaders(headers),
|
|
703
|
-
searchParams: request.nextUrl?.searchParams?.toString()
|
|
727
|
+
url: request.nextUrl?.pathname || request.url
|
|
704
728
|
}
|
|
705
|
-
};
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
|
|
729
|
+
});
|
|
730
|
+
try {
|
|
731
|
+
const result = await handler(request, context);
|
|
732
|
+
if (result instanceof Response) {
|
|
733
|
+
span.setTag("http.status_code", result.status.toString());
|
|
734
|
+
}
|
|
735
|
+
return result;
|
|
736
|
+
} catch (error2) {
|
|
737
|
+
const headers = {};
|
|
738
|
+
request.headers.forEach((value, key) => {
|
|
739
|
+
headers[key] = value;
|
|
740
|
+
});
|
|
741
|
+
const errorContext = {
|
|
742
|
+
request: {
|
|
743
|
+
method: request.method,
|
|
744
|
+
url: request.nextUrl?.pathname || request.url,
|
|
745
|
+
headers: sanitizeHeaders(headers),
|
|
746
|
+
searchParams: request.nextUrl?.searchParams?.toString()
|
|
747
|
+
}
|
|
748
|
+
};
|
|
749
|
+
if (context?.params) {
|
|
750
|
+
try {
|
|
751
|
+
errorContext.params = await context.params;
|
|
752
|
+
} catch {
|
|
753
|
+
}
|
|
710
754
|
}
|
|
755
|
+
Statly.captureException(error2, errorContext);
|
|
756
|
+
throw error2;
|
|
711
757
|
}
|
|
712
|
-
|
|
713
|
-
throw error;
|
|
714
|
-
}
|
|
758
|
+
});
|
|
715
759
|
};
|
|
716
760
|
return wrappedHandler;
|
|
717
761
|
}
|
|
718
|
-
function captureNextJsError(
|
|
719
|
-
return Statly.captureException(
|
|
762
|
+
function captureNextJsError(error2, context) {
|
|
763
|
+
return Statly.captureException(error2, {
|
|
720
764
|
...context,
|
|
721
|
-
digest:
|
|
765
|
+
digest: error2.digest,
|
|
722
766
|
source: "nextjs-error-boundary"
|
|
723
767
|
});
|
|
724
768
|
}
|
|
@@ -726,12 +770,12 @@ function withStatlyGetServerSideProps(handler) {
|
|
|
726
770
|
return async (context) => {
|
|
727
771
|
try {
|
|
728
772
|
return await handler(context);
|
|
729
|
-
} catch (
|
|
730
|
-
Statly.captureException(
|
|
773
|
+
} catch (error2) {
|
|
774
|
+
Statly.captureException(error2, {
|
|
731
775
|
source: "getServerSideProps",
|
|
732
776
|
url: context.req?.url || context.resolvedUrl
|
|
733
777
|
});
|
|
734
|
-
throw
|
|
778
|
+
throw error2;
|
|
735
779
|
}
|
|
736
780
|
};
|
|
737
781
|
}
|
|
@@ -739,31 +783,35 @@ function withStatlyGetStaticProps(handler) {
|
|
|
739
783
|
return async (context) => {
|
|
740
784
|
try {
|
|
741
785
|
return await handler(context);
|
|
742
|
-
} catch (
|
|
743
|
-
Statly.captureException(
|
|
786
|
+
} catch (error2) {
|
|
787
|
+
Statly.captureException(error2, {
|
|
744
788
|
source: "getStaticProps",
|
|
745
789
|
params: context.params
|
|
746
790
|
});
|
|
747
|
-
throw
|
|
791
|
+
throw error2;
|
|
748
792
|
}
|
|
749
793
|
};
|
|
750
794
|
}
|
|
751
795
|
function withStatlyServerAction(action, actionName) {
|
|
752
796
|
return async (...args) => {
|
|
753
|
-
Statly.
|
|
754
|
-
|
|
755
|
-
|
|
756
|
-
|
|
757
|
-
|
|
758
|
-
|
|
759
|
-
|
|
760
|
-
} catch (error) {
|
|
761
|
-
Statly.captureException(error, {
|
|
762
|
-
source: "server-action",
|
|
763
|
-
actionName
|
|
797
|
+
return Statly.trace(`Action: ${actionName || "unknown"}`, async (span) => {
|
|
798
|
+
span.setTag("component", "nextjs-server-action");
|
|
799
|
+
span.setTag("action.name", actionName || "unknown");
|
|
800
|
+
Statly.addBreadcrumb({
|
|
801
|
+
category: "action",
|
|
802
|
+
message: `Server action: ${actionName || "unknown"}`,
|
|
803
|
+
level: "info"
|
|
764
804
|
});
|
|
765
|
-
|
|
766
|
-
|
|
805
|
+
try {
|
|
806
|
+
return await action(...args);
|
|
807
|
+
} catch (error2) {
|
|
808
|
+
Statly.captureException(error2, {
|
|
809
|
+
source: "server-action",
|
|
810
|
+
actionName
|
|
811
|
+
});
|
|
812
|
+
throw error2;
|
|
813
|
+
}
|
|
814
|
+
});
|
|
767
815
|
};
|
|
768
816
|
}
|
|
769
817
|
function sanitizeHeaders(headers) {
|
|
@@ -816,16 +864,16 @@ function statlyFastifyPlugin(fastify, options, done) {
|
|
|
816
864
|
});
|
|
817
865
|
hookDone();
|
|
818
866
|
});
|
|
819
|
-
fastify.setErrorHandler((
|
|
820
|
-
const statusCode =
|
|
867
|
+
fastify.setErrorHandler((error2, request, reply) => {
|
|
868
|
+
const statusCode = error2.statusCode || 500;
|
|
821
869
|
if (skipStatusCodes.includes(statusCode)) {
|
|
822
|
-
throw
|
|
870
|
+
throw error2;
|
|
823
871
|
}
|
|
824
|
-
if (!captureValidationErrors &&
|
|
825
|
-
throw
|
|
872
|
+
if (!captureValidationErrors && error2.validation) {
|
|
873
|
+
throw error2;
|
|
826
874
|
}
|
|
827
|
-
if (shouldCapture && !shouldCapture(
|
|
828
|
-
throw
|
|
875
|
+
if (shouldCapture && !shouldCapture(error2)) {
|
|
876
|
+
throw error2;
|
|
829
877
|
}
|
|
830
878
|
const context = {
|
|
831
879
|
request: {
|
|
@@ -838,27 +886,27 @@ function statlyFastifyPlugin(fastify, options, done) {
|
|
|
838
886
|
params: request.params
|
|
839
887
|
},
|
|
840
888
|
error: {
|
|
841
|
-
statusCode:
|
|
842
|
-
code:
|
|
889
|
+
statusCode: error2.statusCode,
|
|
890
|
+
code: error2.code
|
|
843
891
|
}
|
|
844
892
|
};
|
|
845
893
|
if (request.ip) {
|
|
846
894
|
context.ip = request.ip;
|
|
847
895
|
}
|
|
848
|
-
if (
|
|
849
|
-
context.validation =
|
|
896
|
+
if (error2.validation) {
|
|
897
|
+
context.validation = error2.validation;
|
|
850
898
|
}
|
|
851
899
|
Statly.setTag("http.method", request.method);
|
|
852
900
|
Statly.setTag("http.url", request.routerPath || request.url);
|
|
853
901
|
Statly.setTag("http.status_code", String(statusCode));
|
|
854
|
-
Statly.captureException(
|
|
855
|
-
throw
|
|
902
|
+
Statly.captureException(error2, context);
|
|
903
|
+
throw error2;
|
|
856
904
|
});
|
|
857
905
|
done();
|
|
858
906
|
}
|
|
859
907
|
var statlyPlugin = statlyFastifyPlugin;
|
|
860
908
|
function createRequestCapture(request) {
|
|
861
|
-
return (
|
|
909
|
+
return (error2, additionalContext) => {
|
|
862
910
|
const context = {
|
|
863
911
|
request: {
|
|
864
912
|
id: request.id,
|
|
@@ -868,7 +916,7 @@ function createRequestCapture(request) {
|
|
|
868
916
|
},
|
|
869
917
|
...additionalContext
|
|
870
918
|
};
|
|
871
|
-
return Statly.captureException(
|
|
919
|
+
return Statly.captureException(error2, context);
|
|
872
920
|
};
|
|
873
921
|
}
|
|
874
922
|
function sanitizeHeaders2(headers) {
|
|
@@ -918,12 +966,12 @@ function init(options) {
|
|
|
918
966
|
client = new StatlyClient(finalOptions);
|
|
919
967
|
client.init();
|
|
920
968
|
}
|
|
921
|
-
function captureException(
|
|
969
|
+
function captureException(error2, context) {
|
|
922
970
|
if (!client) {
|
|
923
971
|
console.warn("[Statly] SDK not initialized. Call Statly.init() first.");
|
|
924
972
|
return "";
|
|
925
973
|
}
|
|
926
|
-
return client.captureException(
|
|
974
|
+
return client.captureException(error2, context);
|
|
927
975
|
}
|
|
928
976
|
function captureMessage(message, level = "info") {
|
|
929
977
|
if (!client) {
|
|
@@ -976,6 +1024,20 @@ async function close() {
|
|
|
976
1024
|
function getClient() {
|
|
977
1025
|
return client;
|
|
978
1026
|
}
|
|
1027
|
+
async function trace2(name, operation, tags) {
|
|
1028
|
+
if (!client) {
|
|
1029
|
+
return operation(null);
|
|
1030
|
+
}
|
|
1031
|
+
return client.trace(name, operation, tags);
|
|
1032
|
+
}
|
|
1033
|
+
function startSpan(name, tags) {
|
|
1034
|
+
if (!client) return null;
|
|
1035
|
+
return client.startSpan(name, tags);
|
|
1036
|
+
}
|
|
1037
|
+
function captureSpan(span) {
|
|
1038
|
+
if (!client) return "";
|
|
1039
|
+
return client.captureSpan(span);
|
|
1040
|
+
}
|
|
979
1041
|
var Statly = {
|
|
980
1042
|
init,
|
|
981
1043
|
captureException,
|
|
@@ -986,7 +1048,10 @@ var Statly = {
|
|
|
986
1048
|
addBreadcrumb,
|
|
987
1049
|
flush,
|
|
988
1050
|
close,
|
|
989
|
-
getClient
|
|
1051
|
+
getClient,
|
|
1052
|
+
trace: trace2,
|
|
1053
|
+
startSpan,
|
|
1054
|
+
captureSpan
|
|
990
1055
|
};
|
|
991
1056
|
|
|
992
1057
|
// src/integrations/express.ts
|
|
@@ -1028,8 +1093,8 @@ function requestHandler() {
|
|
|
1028
1093
|
}
|
|
1029
1094
|
function expressErrorHandler(options = {}) {
|
|
1030
1095
|
return (err, req, res, next) => {
|
|
1031
|
-
const
|
|
1032
|
-
if (options.shouldHandleError && !options.shouldHandleError(
|
|
1096
|
+
const error2 = err instanceof Error ? err : new Error(String(err));
|
|
1097
|
+
if (options.shouldHandleError && !options.shouldHandleError(error2)) {
|
|
1033
1098
|
return next(err);
|
|
1034
1099
|
}
|
|
1035
1100
|
const context = {
|
|
@@ -1053,7 +1118,7 @@ function expressErrorHandler(options = {}) {
|
|
|
1053
1118
|
if (req.statlyContext?.transactionName) {
|
|
1054
1119
|
Statly.setTag("transaction", req.statlyContext.transactionName);
|
|
1055
1120
|
}
|
|
1056
|
-
Statly.captureException(
|
|
1121
|
+
Statly.captureException(error2, context);
|
|
1057
1122
|
next(err);
|
|
1058
1123
|
};
|
|
1059
1124
|
}
|
|
@@ -1110,5 +1175,8 @@ export {
|
|
|
1110
1175
|
flush,
|
|
1111
1176
|
close,
|
|
1112
1177
|
getClient,
|
|
1178
|
+
trace2 as trace,
|
|
1179
|
+
startSpan,
|
|
1180
|
+
captureSpan,
|
|
1113
1181
|
Statly
|
|
1114
1182
|
};
|