@statly/observe 0.1.2 → 1.1.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 +44 -5
- package/dist/{chunk-UNDSALI5.mjs → chunk-HYFH22G6.mjs} +132 -64
- package/dist/chunk-J5AHUFP2.mjs +135 -0
- package/dist/index.d.mts +79 -43
- package/dist/index.d.ts +79 -43
- package/dist/index.js +284 -64
- package/dist/index.mjs +8 -1
- package/dist/integrations/express.js +196 -1
- package/dist/integrations/express.mjs +2 -1
- package/dist/integrations/fastify.js +196 -1
- package/dist/integrations/fastify.mjs +2 -1
- package/dist/integrations/nextjs.js +278 -64
- package/dist/integrations/nextjs.mjs +2 -1
- package/dist/telemetry-CXHOTW3Y.mjs +8 -0
- package/package.json +2 -2
|
@@ -3,6 +3,9 @@ var __defProp = Object.defineProperty;
|
|
|
3
3
|
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
4
|
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
5
|
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
+
var __esm = (fn, res) => function __init() {
|
|
7
|
+
return fn && (res = (0, fn[__getOwnPropNames(fn)[0]])(fn = 0)), res;
|
|
8
|
+
};
|
|
6
9
|
var __export = (target, all) => {
|
|
7
10
|
for (var name in all)
|
|
8
11
|
__defProp(target, name, { get: all[name], enumerable: true });
|
|
@@ -17,6 +20,155 @@ var __copyProps = (to, from, except, desc) => {
|
|
|
17
20
|
};
|
|
18
21
|
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
22
|
|
|
23
|
+
// src/span.ts
|
|
24
|
+
var Span, TraceContext;
|
|
25
|
+
var init_span = __esm({
|
|
26
|
+
"src/span.ts"() {
|
|
27
|
+
"use strict";
|
|
28
|
+
Span = class {
|
|
29
|
+
constructor(name, context, tags) {
|
|
30
|
+
this._status = "ok" /* OK */;
|
|
31
|
+
this._tags = {};
|
|
32
|
+
this._metadata = {};
|
|
33
|
+
this._finished = false;
|
|
34
|
+
this.name = name;
|
|
35
|
+
this.context = context;
|
|
36
|
+
this.startTime = Date.now();
|
|
37
|
+
if (tags) this._tags = { ...tags };
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* Finish the span and calculate duration
|
|
41
|
+
*/
|
|
42
|
+
finish(endTime) {
|
|
43
|
+
if (this._finished) return;
|
|
44
|
+
this._endTime = endTime || Date.now();
|
|
45
|
+
this._durationMs = this._endTime - this.startTime;
|
|
46
|
+
this._finished = true;
|
|
47
|
+
}
|
|
48
|
+
setTag(key, value) {
|
|
49
|
+
this._tags[key] = value;
|
|
50
|
+
return this;
|
|
51
|
+
}
|
|
52
|
+
setMetadata(key, value) {
|
|
53
|
+
this._metadata[key] = value;
|
|
54
|
+
return this;
|
|
55
|
+
}
|
|
56
|
+
setStatus(status) {
|
|
57
|
+
this._status = status;
|
|
58
|
+
return this;
|
|
59
|
+
}
|
|
60
|
+
get status() {
|
|
61
|
+
return this._status;
|
|
62
|
+
}
|
|
63
|
+
get tags() {
|
|
64
|
+
return { ...this._tags };
|
|
65
|
+
}
|
|
66
|
+
get durationMs() {
|
|
67
|
+
return this._durationMs;
|
|
68
|
+
}
|
|
69
|
+
toDict() {
|
|
70
|
+
return {
|
|
71
|
+
name: this.name,
|
|
72
|
+
traceId: this.context.traceId,
|
|
73
|
+
spanId: this.context.spanId,
|
|
74
|
+
parentId: this.context.parentId,
|
|
75
|
+
startTime: this.startTime,
|
|
76
|
+
endTime: this._endTime,
|
|
77
|
+
durationMs: this._durationMs,
|
|
78
|
+
status: this._status,
|
|
79
|
+
tags: this._tags,
|
|
80
|
+
metadata: this._metadata
|
|
81
|
+
};
|
|
82
|
+
}
|
|
83
|
+
};
|
|
84
|
+
TraceContext = class {
|
|
85
|
+
static getActiveSpan() {
|
|
86
|
+
return this.currentSpan;
|
|
87
|
+
}
|
|
88
|
+
static setActiveSpan(span) {
|
|
89
|
+
this.currentSpan = span;
|
|
90
|
+
}
|
|
91
|
+
};
|
|
92
|
+
TraceContext.currentSpan = null;
|
|
93
|
+
}
|
|
94
|
+
});
|
|
95
|
+
|
|
96
|
+
// src/telemetry.ts
|
|
97
|
+
var telemetry_exports = {};
|
|
98
|
+
__export(telemetry_exports, {
|
|
99
|
+
TelemetryProvider: () => TelemetryProvider,
|
|
100
|
+
trace: () => trace
|
|
101
|
+
});
|
|
102
|
+
async function trace(name, operation, tags) {
|
|
103
|
+
const provider = TelemetryProvider.getInstance();
|
|
104
|
+
const span = provider.startSpan(name, tags);
|
|
105
|
+
try {
|
|
106
|
+
const result = await operation(span);
|
|
107
|
+
return result;
|
|
108
|
+
} catch (error) {
|
|
109
|
+
span.setStatus("error" /* ERROR */);
|
|
110
|
+
span.setTag("error", "true");
|
|
111
|
+
if (error instanceof Error) {
|
|
112
|
+
span.setTag("exception.type", error.name);
|
|
113
|
+
span.setTag("exception.message", error.message);
|
|
114
|
+
}
|
|
115
|
+
throw error;
|
|
116
|
+
} finally {
|
|
117
|
+
provider.finishSpan(span);
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
var TelemetryProvider;
|
|
121
|
+
var init_telemetry = __esm({
|
|
122
|
+
"src/telemetry.ts"() {
|
|
123
|
+
"use strict";
|
|
124
|
+
init_span();
|
|
125
|
+
TelemetryProvider = class _TelemetryProvider {
|
|
126
|
+
constructor() {
|
|
127
|
+
this.client = null;
|
|
128
|
+
}
|
|
129
|
+
static getInstance() {
|
|
130
|
+
if (!_TelemetryProvider.instance) {
|
|
131
|
+
_TelemetryProvider.instance = new _TelemetryProvider();
|
|
132
|
+
}
|
|
133
|
+
return _TelemetryProvider.instance;
|
|
134
|
+
}
|
|
135
|
+
setClient(client2) {
|
|
136
|
+
this.client = client2;
|
|
137
|
+
}
|
|
138
|
+
/**
|
|
139
|
+
* Start a new span
|
|
140
|
+
*/
|
|
141
|
+
startSpan(name, tags) {
|
|
142
|
+
const parent = TraceContext.getActiveSpan();
|
|
143
|
+
const traceId = parent ? parent.context.traceId : this.generateId();
|
|
144
|
+
const parentId = parent ? parent.context.spanId : null;
|
|
145
|
+
const span = new Span(name, {
|
|
146
|
+
traceId,
|
|
147
|
+
spanId: this.generateId(),
|
|
148
|
+
parentId
|
|
149
|
+
}, tags);
|
|
150
|
+
TraceContext.setActiveSpan(span);
|
|
151
|
+
return span;
|
|
152
|
+
}
|
|
153
|
+
/**
|
|
154
|
+
* Finish and report a span
|
|
155
|
+
*/
|
|
156
|
+
finishSpan(span) {
|
|
157
|
+
span.finish();
|
|
158
|
+
if (TraceContext.getActiveSpan() === span) {
|
|
159
|
+
TraceContext.setActiveSpan(null);
|
|
160
|
+
}
|
|
161
|
+
if (this.client) {
|
|
162
|
+
this.client.captureSpan(span);
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
generateId() {
|
|
166
|
+
return Math.random().toString(16).substring(2, 18);
|
|
167
|
+
}
|
|
168
|
+
};
|
|
169
|
+
}
|
|
170
|
+
});
|
|
171
|
+
|
|
20
172
|
// src/integrations/nextjs.ts
|
|
21
173
|
var nextjs_exports = {};
|
|
22
174
|
__export(nextjs_exports, {
|
|
@@ -373,6 +525,7 @@ var ConsoleIntegration = class {
|
|
|
373
525
|
};
|
|
374
526
|
|
|
375
527
|
// src/client.ts
|
|
528
|
+
init_telemetry();
|
|
376
529
|
var SDK_NAME = "@statly/observe-sdk";
|
|
377
530
|
var SDK_VERSION = "0.1.0";
|
|
378
531
|
var StatlyClient = class {
|
|
@@ -387,6 +540,7 @@ var StatlyClient = class {
|
|
|
387
540
|
this.breadcrumbs = new BreadcrumbManager(this.options.maxBreadcrumbs);
|
|
388
541
|
this.globalHandlers = new GlobalHandlers();
|
|
389
542
|
this.consoleIntegration = new ConsoleIntegration();
|
|
543
|
+
TelemetryProvider.getInstance().setClient(this);
|
|
390
544
|
}
|
|
391
545
|
mergeOptions(options) {
|
|
392
546
|
return {
|
|
@@ -472,6 +626,30 @@ var StatlyClient = class {
|
|
|
472
626
|
});
|
|
473
627
|
return this.sendEvent(event);
|
|
474
628
|
}
|
|
629
|
+
/**
|
|
630
|
+
* Capture a completed span
|
|
631
|
+
*/
|
|
632
|
+
captureSpan(span) {
|
|
633
|
+
const event = this.buildEvent({
|
|
634
|
+
message: `Span: ${span.name}`,
|
|
635
|
+
level: "span",
|
|
636
|
+
span: span.toDict()
|
|
637
|
+
});
|
|
638
|
+
return this.sendEvent(event);
|
|
639
|
+
}
|
|
640
|
+
/**
|
|
641
|
+
* Start a new tracing span
|
|
642
|
+
*/
|
|
643
|
+
startSpan(name, tags) {
|
|
644
|
+
return TelemetryProvider.getInstance().startSpan(name, tags);
|
|
645
|
+
}
|
|
646
|
+
/**
|
|
647
|
+
* Execute a function within a trace span
|
|
648
|
+
*/
|
|
649
|
+
async trace(name, operation, tags) {
|
|
650
|
+
const { trace: traceFn } = await Promise.resolve().then(() => (init_telemetry(), telemetry_exports));
|
|
651
|
+
return traceFn(name, operation, tags);
|
|
652
|
+
}
|
|
475
653
|
/**
|
|
476
654
|
* Internal method to capture an error
|
|
477
655
|
*/
|
|
@@ -772,6 +950,20 @@ async function close() {
|
|
|
772
950
|
function getClient() {
|
|
773
951
|
return client;
|
|
774
952
|
}
|
|
953
|
+
async function trace2(name, operation, tags) {
|
|
954
|
+
if (!client) {
|
|
955
|
+
return operation(null);
|
|
956
|
+
}
|
|
957
|
+
return client.trace(name, operation, tags);
|
|
958
|
+
}
|
|
959
|
+
function startSpan(name, tags) {
|
|
960
|
+
if (!client) return null;
|
|
961
|
+
return client.startSpan(name, tags);
|
|
962
|
+
}
|
|
963
|
+
function captureSpan(span) {
|
|
964
|
+
if (!client) return "";
|
|
965
|
+
return client.captureSpan(span);
|
|
966
|
+
}
|
|
775
967
|
var Statly = {
|
|
776
968
|
init,
|
|
777
969
|
captureException,
|
|
@@ -782,72 +974,90 @@ var Statly = {
|
|
|
782
974
|
addBreadcrumb,
|
|
783
975
|
flush,
|
|
784
976
|
close,
|
|
785
|
-
getClient
|
|
977
|
+
getClient,
|
|
978
|
+
trace: trace2,
|
|
979
|
+
startSpan,
|
|
980
|
+
captureSpan
|
|
786
981
|
};
|
|
787
982
|
|
|
788
983
|
// src/integrations/nextjs.ts
|
|
789
984
|
function withStatlyPagesApi(handler) {
|
|
790
985
|
return async (req, res) => {
|
|
791
|
-
Statly.
|
|
792
|
-
|
|
793
|
-
|
|
794
|
-
|
|
795
|
-
|
|
796
|
-
|
|
797
|
-
|
|
798
|
-
|
|
799
|
-
|
|
800
|
-
try {
|
|
801
|
-
return await handler(req, res);
|
|
802
|
-
} catch (error) {
|
|
803
|
-
const context = {
|
|
804
|
-
request: {
|
|
986
|
+
return Statly.trace(`${req.method} ${req.url}`, async (span) => {
|
|
987
|
+
span.setTag("component", "nextjs-pages-api");
|
|
988
|
+
span.setTag("http.method", req.method || "GET");
|
|
989
|
+
span.setTag("http.url", req.url || "unknown");
|
|
990
|
+
Statly.addBreadcrumb({
|
|
991
|
+
category: "http",
|
|
992
|
+
message: `${req.method} ${req.url}`,
|
|
993
|
+
level: "info",
|
|
994
|
+
data: {
|
|
805
995
|
method: req.method,
|
|
806
|
-
url: req.url
|
|
807
|
-
headers: sanitizeHeaders(req.headers),
|
|
808
|
-
query: req.query
|
|
996
|
+
url: req.url
|
|
809
997
|
}
|
|
810
|
-
};
|
|
811
|
-
|
|
812
|
-
|
|
813
|
-
|
|
998
|
+
});
|
|
999
|
+
try {
|
|
1000
|
+
const result = await handler(req, res);
|
|
1001
|
+
return result;
|
|
1002
|
+
} catch (error) {
|
|
1003
|
+
const context = {
|
|
1004
|
+
request: {
|
|
1005
|
+
method: req.method,
|
|
1006
|
+
url: req.url,
|
|
1007
|
+
headers: sanitizeHeaders(req.headers),
|
|
1008
|
+
query: req.query
|
|
1009
|
+
}
|
|
1010
|
+
};
|
|
1011
|
+
Statly.captureException(error, context);
|
|
1012
|
+
throw error;
|
|
1013
|
+
}
|
|
1014
|
+
});
|
|
814
1015
|
};
|
|
815
1016
|
}
|
|
816
1017
|
function withStatly(handler) {
|
|
817
1018
|
const wrappedHandler = async (request, context) => {
|
|
818
|
-
Statly.
|
|
819
|
-
|
|
820
|
-
|
|
821
|
-
|
|
822
|
-
|
|
823
|
-
|
|
824
|
-
|
|
825
|
-
|
|
826
|
-
|
|
827
|
-
try {
|
|
828
|
-
return await handler(request, context);
|
|
829
|
-
} catch (error) {
|
|
830
|
-
const headers = {};
|
|
831
|
-
request.headers.forEach((value, key) => {
|
|
832
|
-
headers[key] = value;
|
|
833
|
-
});
|
|
834
|
-
const errorContext = {
|
|
835
|
-
request: {
|
|
1019
|
+
return Statly.trace(`${request.method} ${request.nextUrl?.pathname || request.url}`, async (span) => {
|
|
1020
|
+
span.setTag("component", "nextjs-app-router");
|
|
1021
|
+
span.setTag("http.method", request.method);
|
|
1022
|
+
span.setTag("http.url", request.nextUrl?.pathname || request.url);
|
|
1023
|
+
Statly.addBreadcrumb({
|
|
1024
|
+
category: "http",
|
|
1025
|
+
message: `${request.method} ${request.nextUrl?.pathname || request.url}`,
|
|
1026
|
+
level: "info",
|
|
1027
|
+
data: {
|
|
836
1028
|
method: request.method,
|
|
837
|
-
url: request.nextUrl?.pathname || request.url
|
|
838
|
-
headers: sanitizeHeaders(headers),
|
|
839
|
-
searchParams: request.nextUrl?.searchParams?.toString()
|
|
1029
|
+
url: request.nextUrl?.pathname || request.url
|
|
840
1030
|
}
|
|
841
|
-
};
|
|
842
|
-
|
|
843
|
-
|
|
844
|
-
|
|
845
|
-
|
|
1031
|
+
});
|
|
1032
|
+
try {
|
|
1033
|
+
const result = await handler(request, context);
|
|
1034
|
+
if (result instanceof Response) {
|
|
1035
|
+
span.setTag("http.status_code", result.status.toString());
|
|
846
1036
|
}
|
|
1037
|
+
return result;
|
|
1038
|
+
} catch (error) {
|
|
1039
|
+
const headers = {};
|
|
1040
|
+
request.headers.forEach((value, key) => {
|
|
1041
|
+
headers[key] = value;
|
|
1042
|
+
});
|
|
1043
|
+
const errorContext = {
|
|
1044
|
+
request: {
|
|
1045
|
+
method: request.method,
|
|
1046
|
+
url: request.nextUrl?.pathname || request.url,
|
|
1047
|
+
headers: sanitizeHeaders(headers),
|
|
1048
|
+
searchParams: request.nextUrl?.searchParams?.toString()
|
|
1049
|
+
}
|
|
1050
|
+
};
|
|
1051
|
+
if (context?.params) {
|
|
1052
|
+
try {
|
|
1053
|
+
errorContext.params = await context.params;
|
|
1054
|
+
} catch {
|
|
1055
|
+
}
|
|
1056
|
+
}
|
|
1057
|
+
Statly.captureException(error, errorContext);
|
|
1058
|
+
throw error;
|
|
847
1059
|
}
|
|
848
|
-
|
|
849
|
-
throw error;
|
|
850
|
-
}
|
|
1060
|
+
});
|
|
851
1061
|
};
|
|
852
1062
|
return wrappedHandler;
|
|
853
1063
|
}
|
|
@@ -886,20 +1096,24 @@ function withStatlyGetStaticProps(handler) {
|
|
|
886
1096
|
}
|
|
887
1097
|
function withStatlyServerAction(action, actionName) {
|
|
888
1098
|
return async (...args) => {
|
|
889
|
-
Statly.
|
|
890
|
-
|
|
891
|
-
|
|
892
|
-
|
|
893
|
-
|
|
894
|
-
|
|
895
|
-
|
|
896
|
-
} catch (error) {
|
|
897
|
-
Statly.captureException(error, {
|
|
898
|
-
source: "server-action",
|
|
899
|
-
actionName
|
|
1099
|
+
return Statly.trace(`Action: ${actionName || "unknown"}`, async (span) => {
|
|
1100
|
+
span.setTag("component", "nextjs-server-action");
|
|
1101
|
+
span.setTag("action.name", actionName || "unknown");
|
|
1102
|
+
Statly.addBreadcrumb({
|
|
1103
|
+
category: "action",
|
|
1104
|
+
message: `Server action: ${actionName || "unknown"}`,
|
|
1105
|
+
level: "info"
|
|
900
1106
|
});
|
|
901
|
-
|
|
902
|
-
|
|
1107
|
+
try {
|
|
1108
|
+
return await action(...args);
|
|
1109
|
+
} catch (error) {
|
|
1110
|
+
Statly.captureException(error, {
|
|
1111
|
+
source: "server-action",
|
|
1112
|
+
actionName
|
|
1113
|
+
});
|
|
1114
|
+
throw error;
|
|
1115
|
+
}
|
|
1116
|
+
});
|
|
903
1117
|
};
|
|
904
1118
|
}
|
|
905
1119
|
function sanitizeHeaders(headers) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@statly/observe",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "1.1.0",
|
|
4
4
|
"description": "JavaScript SDK for Statly Observe - Error tracking and monitoring",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"module": "dist/index.mjs",
|
|
@@ -76,4 +76,4 @@
|
|
|
76
76
|
"publishConfig": {
|
|
77
77
|
"access": "public"
|
|
78
78
|
}
|
|
79
|
-
}
|
|
79
|
+
}
|