@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.
@@ -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.addBreadcrumb({
792
- category: "http",
793
- message: `${req.method} ${req.url}`,
794
- level: "info",
795
- data: {
796
- method: req.method,
797
- url: req.url
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
- Statly.captureException(error, context);
812
- throw error;
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.addBreadcrumb({
819
- category: "http",
820
- message: `${request.method} ${request.nextUrl?.pathname || request.url}`,
821
- level: "info",
822
- data: {
823
- method: request.method,
824
- url: request.nextUrl?.pathname || request.url
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
- if (context?.params) {
843
- try {
844
- errorContext.params = await context.params;
845
- } catch {
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
- Statly.captureException(error, errorContext);
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.addBreadcrumb({
890
- category: "action",
891
- message: `Server action: ${actionName || "unknown"}`,
892
- level: "info"
893
- });
894
- try {
895
- return await action(...args);
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
- throw error;
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) {
@@ -5,7 +5,8 @@ import {
5
5
  withStatlyGetStaticProps,
6
6
  withStatlyPagesApi,
7
7
  withStatlyServerAction
8
- } from "../chunk-UNDSALI5.mjs";
8
+ } from "../chunk-HYFH22G6.mjs";
9
+ import "../chunk-J5AHUFP2.mjs";
9
10
  export {
10
11
  captureNextJsError,
11
12
  withStatly,
@@ -0,0 +1,8 @@
1
+ import {
2
+ TelemetryProvider,
3
+ trace
4
+ } from "./chunk-J5AHUFP2.mjs";
5
+ export {
6
+ TelemetryProvider,
7
+ trace
8
+ };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@statly/observe",
3
- "version": "0.1.2",
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
+ }