spanport 0.1.1 → 1.0.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 CHANGED
@@ -1,6 +1,6 @@
1
1
  # spanport (Node.js SDK)
2
2
 
3
- Send your Node.js app's logs to Spanport. Keep logging the way you already do.
3
+ Send your Node.js app's logs, and where each request spends its time, to Spanport. Keep logging the way you already do.
4
4
 
5
5
  ```bash
6
6
  npm install spanport
@@ -49,12 +49,42 @@ Node.js 22.15 or newer. ES module; CommonJS apps can `require("spanport")`.
49
49
  At start-up the SDK prints, on stderr:
50
50
 
51
51
  ```
52
- INFO spanport: sending logs for service orders-api to http://localhost:4318
52
+ INFO spanport: sending logs and traces for service orders-api to http://localhost:4318
53
53
  INFO spanport: data key ...a1b2 accepted
54
54
  ```
55
55
 
56
56
  If the second line is missing or says something else, see [Troubleshooting](#troubleshooting).
57
57
 
58
+ ## Request timing (traces)
59
+
60
+ `init()` also times each request your app handles and every step inside it, and sends them as traces; open **Requests** in Spanport to see them as a waterfall (request → controller → service → database / outgoing calls). Pass `traces: false` to send logs only.
61
+
62
+ - **Always on:** incoming HTTP requests and outgoing `http`/`https` calls. Outgoing calls carry a W3C `traceparent` header, so your other services running the SDK join the same trace (shown as a service call).
63
+ - **If your app has them installed**, also: route names for Express and NestJS (`npm install @opentelemetry/instrumentation-express`), Postgres queries (`@opentelemetry/instrumentation-pg`) and `fetch` calls (`@opentelemetry/instrumentation-undici`). On start-up the SDK says which it found: `spanport: also timing: ...`.
64
+ - **Call `init()` before your framework loads**, from a small file imported first, so Express and Postgres get timed:
65
+
66
+ ```ts
67
+ // src/spanport.ts
68
+ import * as spanport from "spanport";
69
+ spanport.init({ dataKey: process.env.SPANPORT_DATA_KEY ?? "", service: "kosha-backend" });
70
+
71
+ // src/main.ts: the very first import
72
+ import "./spanport";
73
+ import { NestFactory } from "@nestjs/core";
74
+ ```
75
+
76
+ **Your own code**: time every method of a controller or service, or any block:
77
+
78
+ ```ts
79
+ @spanport.trace() // "VariablesService.list", "VariablesService.find", ...
80
+ @Injectable()
81
+ export class VariablesService { ... }
82
+
83
+ const prompt = await spanport.withSpan("build prompt", () => render(template, data));
84
+ ```
85
+
86
+ Works with NestJS decorators (route paths and guards keep working) and with sync or async methods. A thrown error marks the step failed and is rethrown unchanged. Logs written during a step carry its trace, so **See logs** on a request in Spanport shows them.
87
+
58
88
  ## What Spanport receives
59
89
 
60
90
  | You write | Message | Level | Fields you can filter on |
@@ -3,6 +3,22 @@ export declare const DATA_KEY_PREFIX = "sp_ingest_";
3
3
  export declare const DEFAULT_COLLECTOR_URL = "http://localhost:4318";
4
4
  export declare const DEFAULT_SERVER_URL = "http://localhost:8000";
5
5
  export declare const OTLP_LOGS_PATH = "/v1/logs";
6
+ export declare const OTLP_TRACES_PATH = "/v1/traces";
7
+ /**
8
+ * Instrumentations switched on only when the app has installed them (they patch libraries the
9
+ * SDK doesn't depend on): Express and NestJS route names, Postgres queries, fetch calls.
10
+ */
11
+ export declare const OPTIONAL_INSTRUMENTATIONS: readonly {
12
+ module: string;
13
+ exportName: string;
14
+ }[];
15
+ /** Node built-ins the HTTP instrumentation patches; required once when tracing starts. */
16
+ export declare const PATCHED_BUILTINS: readonly string[];
17
+ /** Separates a decorated class's name from its method in span names, e.g. "UsersService.find". */
18
+ export declare const SPAN_NAME_SEPARATOR = ".";
19
+ export declare const CONSTRUCTOR_NAME = "constructor";
20
+ /** The name a class decorator falls back to for an anonymous class. */
21
+ export declare const ANONYMOUS_CLASS_NAME = "AnonymousClass";
6
22
  export declare const CURRENT_API_KEY_PATH = "/api/v1/api-keys/current";
7
23
  export declare const AUTHORIZATION_HEADER = "Authorization";
8
24
  export declare const BEARER_PREFIX = "Bearer ";
@@ -1 +1 @@
1
- {"version":3,"file":"constants.d.ts","sourceRoot":"","sources":["../src/constants.ts"],"names":[],"mappings":"AAAA,0EAA0E;AAE1E,eAAO,MAAM,eAAe,eAAe,CAAC;AAC5C,eAAO,MAAM,qBAAqB,0BAA0B,CAAC;AAC7D,eAAO,MAAM,kBAAkB,0BAA0B,CAAC;AAC1D,eAAO,MAAM,cAAc,aAAa,CAAC;AACzC,eAAO,MAAM,oBAAoB,6BAA6B,CAAC;AAC/D,eAAO,MAAM,oBAAoB,kBAAkB,CAAC;AACpD,eAAO,MAAM,aAAa,YAAY,CAAC;AACvC,eAAO,MAAM,qBAAqB,EAAE,SAAS,MAAM,EAAwB,CAAC;AAC5E,eAAO,MAAM,oBAAoB,OAAO,CAAC;AACzC,eAAO,MAAM,yBAAyB,IAAI,CAAC;AAC3C,eAAO,MAAM,iBAAiB,MAAM,CAAC;AAErC,oFAAoF;AACpF,eAAO,MAAM,wBAAwB,oDAAqD,CAAC;AAE3F,mDAAmD;AACnD,eAAO,MAAM,UAAU,KAAK,CAAC;AAC7B,eAAO,MAAM,UAAU,KAAK,CAAC;AAC7B,eAAO,MAAM,SAAS,KAAK,CAAC;AAC5B,eAAO,MAAM,SAAS,KAAK,CAAC;AAC5B,eAAO,MAAM,UAAU,KAAK,CAAC;AAC7B,eAAO,MAAM,UAAU,KAAK,CAAC;AAE7B,eAAO,MAAM,sBAAsB,iBAAiB,CAAC;AACrD,oEAAoE;AACpE,eAAO,MAAM,cAAc,aAAa,CAAC;AACzC,yEAAyE;AACzE,eAAO,MAAM,kBAAkB,cAAc,CAAC;AAE9C,qEAAqE;AACrE,eAAO,MAAM,oBAAoB,eAAe,CAAC;AACjD,eAAO,MAAM,cAAc,YAAY,CAAC;AACxC,eAAO,MAAM,iBAAiB,WAAW,CAAC;AAE1C,mGAAmG;AACnG,eAAO,MAAM,cAAc,EAAE,SAAS,MAAM,EAAuB,CAAC;AACpE,eAAO,MAAM,WAAW,UAAU,CAAC;AACnC,eAAO,MAAM,WAAW,EAAE,SAAS,MAAM,EAA0B,CAAC;AACpE,eAAO,MAAM,cAAc,aAAa,CAAC;AACzC,eAAO,MAAM,aAAa,YAAY,CAAC;AACvC,eAAO,MAAM,cAAc,OAAO,CAAC"}
1
+ {"version":3,"file":"constants.d.ts","sourceRoot":"","sources":["../src/constants.ts"],"names":[],"mappings":"AAAA,0EAA0E;AAE1E,eAAO,MAAM,eAAe,eAAe,CAAC;AAC5C,eAAO,MAAM,qBAAqB,0BAA0B,CAAC;AAC7D,eAAO,MAAM,kBAAkB,0BAA0B,CAAC;AAC1D,eAAO,MAAM,cAAc,aAAa,CAAC;AACzC,eAAO,MAAM,gBAAgB,eAAe,CAAC;AAE7C;;;GAGG;AACH,eAAO,MAAM,yBAAyB,EAAE,SAAS;IAAE,MAAM,EAAE,MAAM,CAAC;IAAC,UAAU,EAAE,MAAM,CAAA;CAAE,EAItF,CAAC;AACF,0FAA0F;AAC1F,eAAO,MAAM,gBAAgB,EAAE,SAAS,MAAM,EAAgC,CAAC;AAC/E,kGAAkG;AAClG,eAAO,MAAM,mBAAmB,MAAM,CAAC;AACvC,eAAO,MAAM,gBAAgB,gBAAgB,CAAC;AAC9C,uEAAuE;AACvE,eAAO,MAAM,oBAAoB,mBAAmB,CAAC;AACrD,eAAO,MAAM,oBAAoB,6BAA6B,CAAC;AAC/D,eAAO,MAAM,oBAAoB,kBAAkB,CAAC;AACpD,eAAO,MAAM,aAAa,YAAY,CAAC;AACvC,eAAO,MAAM,qBAAqB,EAAE,SAAS,MAAM,EAAwB,CAAC;AAC5E,eAAO,MAAM,oBAAoB,OAAO,CAAC;AACzC,eAAO,MAAM,yBAAyB,IAAI,CAAC;AAC3C,eAAO,MAAM,iBAAiB,MAAM,CAAC;AAErC,oFAAoF;AACpF,eAAO,MAAM,wBAAwB,oDAAqD,CAAC;AAE3F,mDAAmD;AACnD,eAAO,MAAM,UAAU,KAAK,CAAC;AAC7B,eAAO,MAAM,UAAU,KAAK,CAAC;AAC7B,eAAO,MAAM,SAAS,KAAK,CAAC;AAC5B,eAAO,MAAM,SAAS,KAAK,CAAC;AAC5B,eAAO,MAAM,UAAU,KAAK,CAAC;AAC7B,eAAO,MAAM,UAAU,KAAK,CAAC;AAE7B,eAAO,MAAM,sBAAsB,iBAAiB,CAAC;AACrD,oEAAoE;AACpE,eAAO,MAAM,cAAc,aAAa,CAAC;AACzC,yEAAyE;AACzE,eAAO,MAAM,kBAAkB,cAAc,CAAC;AAE9C,qEAAqE;AACrE,eAAO,MAAM,oBAAoB,eAAe,CAAC;AACjD,eAAO,MAAM,cAAc,YAAY,CAAC;AACxC,eAAO,MAAM,iBAAiB,WAAW,CAAC;AAE1C,mGAAmG;AACnG,eAAO,MAAM,cAAc,EAAE,SAAS,MAAM,EAAuB,CAAC;AACpE,eAAO,MAAM,WAAW,UAAU,CAAC;AACnC,eAAO,MAAM,WAAW,EAAE,SAAS,MAAM,EAA0B,CAAC;AACpE,eAAO,MAAM,cAAc,aAAa,CAAC;AACzC,eAAO,MAAM,aAAa,YAAY,CAAC;AACvC,eAAO,MAAM,cAAc,OAAO,CAAC"}
package/dist/constants.js CHANGED
@@ -3,6 +3,23 @@ export const DATA_KEY_PREFIX = "sp_ingest_";
3
3
  export const DEFAULT_COLLECTOR_URL = "http://localhost:4318";
4
4
  export const DEFAULT_SERVER_URL = "http://localhost:8000";
5
5
  export const OTLP_LOGS_PATH = "/v1/logs";
6
+ export const OTLP_TRACES_PATH = "/v1/traces";
7
+ /**
8
+ * Instrumentations switched on only when the app has installed them (they patch libraries the
9
+ * SDK doesn't depend on): Express and NestJS route names, Postgres queries, fetch calls.
10
+ */
11
+ export const OPTIONAL_INSTRUMENTATIONS = [
12
+ { module: "@opentelemetry/instrumentation-express", exportName: "ExpressInstrumentation" },
13
+ { module: "@opentelemetry/instrumentation-pg", exportName: "PgInstrumentation" },
14
+ { module: "@opentelemetry/instrumentation-undici", exportName: "UndiciInstrumentation" },
15
+ ];
16
+ /** Node built-ins the HTTP instrumentation patches; required once when tracing starts. */
17
+ export const PATCHED_BUILTINS = ["node:http", "node:https"];
18
+ /** Separates a decorated class's name from its method in span names, e.g. "UsersService.find". */
19
+ export const SPAN_NAME_SEPARATOR = ".";
20
+ export const CONSTRUCTOR_NAME = "constructor";
21
+ /** The name a class decorator falls back to for an anonymous class. */
22
+ export const ANONYMOUS_CLASS_NAME = "AnonymousClass";
6
23
  export const CURRENT_API_KEY_PATH = "/api/v1/api-keys/current";
7
24
  export const AUTHORIZATION_HEADER = "Authorization";
8
25
  export const BEARER_PREFIX = "Bearer ";
@@ -1 +1 @@
1
- {"version":3,"file":"constants.js","sourceRoot":"","sources":["../src/constants.ts"],"names":[],"mappings":"AAAA,0EAA0E;AAE1E,MAAM,CAAC,MAAM,eAAe,GAAG,YAAY,CAAC;AAC5C,MAAM,CAAC,MAAM,qBAAqB,GAAG,uBAAuB,CAAC;AAC7D,MAAM,CAAC,MAAM,kBAAkB,GAAG,uBAAuB,CAAC;AAC1D,MAAM,CAAC,MAAM,cAAc,GAAG,UAAU,CAAC;AACzC,MAAM,CAAC,MAAM,oBAAoB,GAAG,0BAA0B,CAAC;AAC/D,MAAM,CAAC,MAAM,oBAAoB,GAAG,eAAe,CAAC;AACpD,MAAM,CAAC,MAAM,aAAa,GAAG,SAAS,CAAC;AACvC,MAAM,CAAC,MAAM,qBAAqB,GAAsB,CAAC,OAAO,EAAE,QAAQ,CAAC,CAAC;AAC5E,MAAM,CAAC,MAAM,oBAAoB,GAAG,IAAI,CAAC;AACzC,MAAM,CAAC,MAAM,yBAAyB,GAAG,CAAC,CAAC;AAC3C,MAAM,CAAC,MAAM,iBAAiB,GAAG,GAAG,CAAC;AAErC,oFAAoF;AACpF,MAAM,CAAC,MAAM,wBAAwB,GAAG,CAAC,OAAO,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,CAAU,CAAC;AAE3F,mDAAmD;AACnD,MAAM,CAAC,MAAM,UAAU,GAAG,EAAE,CAAC;AAC7B,MAAM,CAAC,MAAM,UAAU,GAAG,EAAE,CAAC;AAC7B,MAAM,CAAC,MAAM,SAAS,GAAG,EAAE,CAAC;AAC5B,MAAM,CAAC,MAAM,SAAS,GAAG,EAAE,CAAC;AAC5B,MAAM,CAAC,MAAM,UAAU,GAAG,EAAE,CAAC;AAC7B,MAAM,CAAC,MAAM,UAAU,GAAG,EAAE,CAAC;AAE7B,MAAM,CAAC,MAAM,sBAAsB,GAAG,cAAc,CAAC;AACrD,oEAAoE;AACpE,MAAM,CAAC,MAAM,cAAc,GAAG,UAAU,CAAC;AACzC,yEAAyE;AACzE,MAAM,CAAC,MAAM,kBAAkB,GAAG,WAAW,CAAC;AAE9C,qEAAqE;AACrE,MAAM,CAAC,MAAM,oBAAoB,GAAG,YAAY,CAAC;AACjD,MAAM,CAAC,MAAM,cAAc,GAAG,SAAS,CAAC;AACxC,MAAM,CAAC,MAAM,iBAAiB,GAAG,QAAQ,CAAC;AAE1C,mGAAmG;AACnG,MAAM,CAAC,MAAM,cAAc,GAAsB,CAAC,KAAK,EAAE,SAAS,CAAC,CAAC;AACpE,MAAM,CAAC,MAAM,WAAW,GAAG,OAAO,CAAC;AACnC,MAAM,CAAC,MAAM,WAAW,GAAsB,CAAC,MAAM,EAAE,WAAW,CAAC,CAAC;AACpE,MAAM,CAAC,MAAM,cAAc,GAAG,UAAU,CAAC;AACzC,MAAM,CAAC,MAAM,aAAa,GAAG,SAAS,CAAC;AACvC,MAAM,CAAC,MAAM,cAAc,GAAG,IAAI,CAAC"}
1
+ {"version":3,"file":"constants.js","sourceRoot":"","sources":["../src/constants.ts"],"names":[],"mappings":"AAAA,0EAA0E;AAE1E,MAAM,CAAC,MAAM,eAAe,GAAG,YAAY,CAAC;AAC5C,MAAM,CAAC,MAAM,qBAAqB,GAAG,uBAAuB,CAAC;AAC7D,MAAM,CAAC,MAAM,kBAAkB,GAAG,uBAAuB,CAAC;AAC1D,MAAM,CAAC,MAAM,cAAc,GAAG,UAAU,CAAC;AACzC,MAAM,CAAC,MAAM,gBAAgB,GAAG,YAAY,CAAC;AAE7C;;;GAGG;AACH,MAAM,CAAC,MAAM,yBAAyB,GAAsD;IAC1F,EAAE,MAAM,EAAE,wCAAwC,EAAE,UAAU,EAAE,wBAAwB,EAAE;IAC1F,EAAE,MAAM,EAAE,mCAAmC,EAAE,UAAU,EAAE,mBAAmB,EAAE;IAChF,EAAE,MAAM,EAAE,uCAAuC,EAAE,UAAU,EAAE,uBAAuB,EAAE;CACzF,CAAC;AACF,0FAA0F;AAC1F,MAAM,CAAC,MAAM,gBAAgB,GAAsB,CAAC,WAAW,EAAE,YAAY,CAAC,CAAC;AAC/E,kGAAkG;AAClG,MAAM,CAAC,MAAM,mBAAmB,GAAG,GAAG,CAAC;AACvC,MAAM,CAAC,MAAM,gBAAgB,GAAG,aAAa,CAAC;AAC9C,uEAAuE;AACvE,MAAM,CAAC,MAAM,oBAAoB,GAAG,gBAAgB,CAAC;AACrD,MAAM,CAAC,MAAM,oBAAoB,GAAG,0BAA0B,CAAC;AAC/D,MAAM,CAAC,MAAM,oBAAoB,GAAG,eAAe,CAAC;AACpD,MAAM,CAAC,MAAM,aAAa,GAAG,SAAS,CAAC;AACvC,MAAM,CAAC,MAAM,qBAAqB,GAAsB,CAAC,OAAO,EAAE,QAAQ,CAAC,CAAC;AAC5E,MAAM,CAAC,MAAM,oBAAoB,GAAG,IAAI,CAAC;AACzC,MAAM,CAAC,MAAM,yBAAyB,GAAG,CAAC,CAAC;AAC3C,MAAM,CAAC,MAAM,iBAAiB,GAAG,GAAG,CAAC;AAErC,oFAAoF;AACpF,MAAM,CAAC,MAAM,wBAAwB,GAAG,CAAC,OAAO,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,CAAU,CAAC;AAE3F,mDAAmD;AACnD,MAAM,CAAC,MAAM,UAAU,GAAG,EAAE,CAAC;AAC7B,MAAM,CAAC,MAAM,UAAU,GAAG,EAAE,CAAC;AAC7B,MAAM,CAAC,MAAM,SAAS,GAAG,EAAE,CAAC;AAC5B,MAAM,CAAC,MAAM,SAAS,GAAG,EAAE,CAAC;AAC5B,MAAM,CAAC,MAAM,UAAU,GAAG,EAAE,CAAC;AAC7B,MAAM,CAAC,MAAM,UAAU,GAAG,EAAE,CAAC;AAE7B,MAAM,CAAC,MAAM,sBAAsB,GAAG,cAAc,CAAC;AACrD,oEAAoE;AACpE,MAAM,CAAC,MAAM,cAAc,GAAG,UAAU,CAAC;AACzC,yEAAyE;AACzE,MAAM,CAAC,MAAM,kBAAkB,GAAG,WAAW,CAAC;AAE9C,qEAAqE;AACrE,MAAM,CAAC,MAAM,oBAAoB,GAAG,YAAY,CAAC;AACjD,MAAM,CAAC,MAAM,cAAc,GAAG,SAAS,CAAC;AACxC,MAAM,CAAC,MAAM,iBAAiB,GAAG,QAAQ,CAAC;AAE1C,mGAAmG;AACnG,MAAM,CAAC,MAAM,cAAc,GAAsB,CAAC,KAAK,EAAE,SAAS,CAAC,CAAC;AACpE,MAAM,CAAC,MAAM,WAAW,GAAG,OAAO,CAAC;AACnC,MAAM,CAAC,MAAM,WAAW,GAAsB,CAAC,MAAM,EAAE,WAAW,CAAC,CAAC;AACpE,MAAM,CAAC,MAAM,cAAc,GAAG,UAAU,CAAC;AACzC,MAAM,CAAC,MAAM,aAAa,GAAG,SAAS,CAAC;AACvC,MAAM,CAAC,MAAM,cAAc,GAAG,IAAI,CAAC"}
package/dist/index.d.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  /**
2
- * Spanport SDK: send your Node.js app's logs to Spanport.
2
+ * Spanport SDK: send your Node.js app's logs and traces (request timings) to Spanport.
3
3
  *
4
4
  * import * as spanport from "spanport";
5
5
  * spanport.init({ dataKey: "sp_ingest_...", service: "orders-api" });
@@ -21,7 +21,10 @@ export interface SpanportOptions {
21
21
  checkKey?: boolean;
22
22
  /** Set false to stop copying console.* calls to Spanport. Default true. */
23
23
  captureConsole?: boolean;
24
+ /** Set false to send no traces (request timings). Default true. */
25
+ traces?: boolean;
24
26
  }
27
+ export { trace, withSpan } from "./spans.js";
25
28
  /**
26
29
  * Start sending this app's logs to Spanport. Call once at start-up. Never throws.
27
30
  *
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,EAAE,KAAK,QAAQ,EAAE,MAAM,aAAa,CAAC;AAqB5C,MAAM,WAAW,eAAe;IAC9B,8CAA8C;IAC9C,OAAO,EAAE,MAAM,CAAC;IAChB,gEAAgE;IAChE,OAAO,EAAE,MAAM,CAAC;IAChB,8EAA8E;IAC9E,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,oGAAoG;IACpG,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,4FAA4F;IAC5F,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,2EAA2E;IAC3E,cAAc,CAAC,EAAE,OAAO,CAAC;CAC1B;AAWD;;;;GAIG;AACH,wBAAgB,IAAI,CAAC,OAAO,EAAE,eAAe,GAAG,IAAI,CAMnD;AAED;;;GAGG;AACH,wBAAsB,QAAQ,IAAI,OAAO,CAAC,IAAI,CAAC,CAU9C;AAED;;;;;;;;GAQG;AACH,wBAAgB,SAAS,IAAI,QAAQ,CAIpC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,EAAE,KAAK,QAAQ,EAAE,MAAM,aAAa,CAAC;AAsB5C,MAAM,WAAW,eAAe;IAC9B,8CAA8C;IAC9C,OAAO,EAAE,MAAM,CAAC;IAChB,gEAAgE;IAChE,OAAO,EAAE,MAAM,CAAC;IAChB,8EAA8E;IAC9E,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,oGAAoG;IACpG,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,4FAA4F;IAC5F,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,2EAA2E;IAC3E,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB,mEAAmE;IACnE,MAAM,CAAC,EAAE,OAAO,CAAC;CAClB;AASD,OAAO,EAAE,KAAK,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAK7C;;;;GAIG;AACH,wBAAgB,IAAI,CAAC,OAAO,EAAE,eAAe,GAAG,IAAI,CAMnD;AAED;;;GAGG;AACH,wBAAsB,QAAQ,IAAI,OAAO,CAAC,IAAI,CAAC,CAU9C;AAED;;;;;;;;GAQG;AACH,wBAAgB,SAAS,IAAI,QAAQ,CAIpC"}
package/dist/index.js CHANGED
@@ -1,5 +1,5 @@
1
1
  /**
2
- * Spanport SDK: send your Node.js app's logs to Spanport.
2
+ * Spanport SDK: send your Node.js app's logs and traces (request timings) to Spanport.
3
3
  *
4
4
  * import * as spanport from "spanport";
5
5
  * spanport.init({ dataKey: "sp_ingest_...", service: "orders-api" });
@@ -17,7 +17,9 @@ import { createLogStream } from "./logStream.js";
17
17
  import { buildLoggerProvider, buildOtlpExporter, toLogRecord } from "./pipeline.js";
18
18
  import { sdkError, sdkInfo, sdkWarning } from "./sdkMessages.js";
19
19
  import { consoleSeverity } from "./severity.js";
20
+ import { buildTraceExporter, startTracing } from "./tracing.js";
20
21
  import { isHttpUrl } from "./urls.js";
22
+ export { trace, withSpan } from "./spans.js";
21
23
  let active;
22
24
  let exitFlushInstalled = false;
23
25
  /**
@@ -44,7 +46,7 @@ export async function shutdown() {
44
46
  return;
45
47
  pipeline.restoreConsole?.();
46
48
  try {
47
- await pipeline.provider.shutdown();
49
+ await Promise.all([pipeline.provider.shutdown(), pipeline.tracing?.stop()]);
48
50
  }
49
51
  catch (error) {
50
52
  sdkWarning(`shutdown failed; some queued logs may not have been sent: ${describe(error)}`);
@@ -82,11 +84,20 @@ function start(options) {
82
84
  : captureConsole((method, message) => {
83
85
  logger.emit(toLogRecord({ body: message, severity: consoleSeverity(method), attributes: {} }, CONSOLE_SOURCE));
84
86
  });
85
- active = { provider, logger, restoreConsole };
87
+ const serverUrl = options.serverUrl ?? DEFAULT_SERVER_URL;
88
+ const tracing = options.traces === false
89
+ ? undefined
90
+ : startTracing(options.service, buildTraceExporter(collectorUrl, options.dataKey), {
91
+ collectorUrl,
92
+ serverUrl: isHttpUrl(serverUrl) ? serverUrl : collectorUrl,
93
+ });
94
+ active = { provider, logger, restoreConsole, tracing };
86
95
  installExitFlush();
87
- sdkInfo(`sending logs for service ${options.service} to ${collectorUrl}`);
96
+ sdkInfo(`sending logs${tracing ? " and traces" : ""} for service ${options.service} to ${collectorUrl}`);
97
+ if (tracing?.optional.length)
98
+ sdkInfo(`also timing: ${tracing.optional.join(", ")}`);
88
99
  if (options.checkKey !== false) {
89
- void checkDataKey(options.serverUrl ?? DEFAULT_SERVER_URL, options.dataKey);
100
+ void checkDataKey(serverUrl, options.dataKey);
90
101
  }
91
102
  }
92
103
  /** Send what is queued when the app exits normally. Installed once, however often init runs. */
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,27 @@
1
+ /**
2
+ * Your own steps in a trace: `withSpan(name, fn)` for any block, and the `trace()` class decorator
3
+ * that times every method of a controller or service as "ClassName.method".
4
+ */
5
+ /**
6
+ * Run `work` inside a span named `name`, nested under the current one. Works for sync and async
7
+ * work; a thrown error or rejected promise marks the span failed and is rethrown unchanged.
8
+ *
9
+ * const user = await spanport.withSpan("load user", () => repo.find(id));
10
+ *
11
+ * @returns Whatever `work` returns.
12
+ */
13
+ export declare function withSpan<T>(name: string, work: () => T): T;
14
+ /**
15
+ * Class decorator: every method becomes a step of the trace, named "ClassName.method".
16
+ *
17
+ * @spanport.trace()
18
+ * @Injectable()
19
+ * export class VariablesService { ... }
20
+ *
21
+ * Works with TypeScript's legacy decorators (NestJS) and standard ones. Method metadata (e.g.
22
+ * NestJS route paths) is copied to the timed method, so frameworks keep working.
23
+ *
24
+ * @param name - The name used before the dot; the class's own name by default.
25
+ */
26
+ export declare function trace(name?: string): (target: abstract new (...args: never[]) => unknown) => void;
27
+ //# sourceMappingURL=spans.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"spans.d.ts","sourceRoot":"","sources":["../src/spans.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAoBH;;;;;;;GAOG;AACH,wBAAgB,QAAQ,CAAC,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,CAAC,GAAG,CAAC,CAuB1D;AAQD;;;;;;;;;;;GAWG;AACH,wBAAgB,KAAK,CAAC,IAAI,CAAC,EAAE,MAAM,IAEzB,QAAQ,QAAQ,MAAM,GAAG,IAAI,EAAE,KAAK,EAAE,KAAK,OAAO,KAAG,IAAI,CAUlE"}
package/dist/spans.js ADDED
@@ -0,0 +1,86 @@
1
+ /**
2
+ * Your own steps in a trace: `withSpan(name, fn)` for any block, and the `trace()` class decorator
3
+ * that times every method of a controller or service as "ClassName.method".
4
+ */
5
+ import { SpanStatusCode, trace as otelTrace } from "@opentelemetry/api";
6
+ import { ANONYMOUS_CLASS_NAME, CONSTRUCTOR_NAME, SDK_SCOPE_NAME, SPAN_NAME_SEPARATOR, } from "./constants.js";
7
+ /**
8
+ * Run `work` inside a span named `name`, nested under the current one. Works for sync and async
9
+ * work; a thrown error or rejected promise marks the span failed and is rethrown unchanged.
10
+ *
11
+ * const user = await spanport.withSpan("load user", () => repo.find(id));
12
+ *
13
+ * @returns Whatever `work` returns.
14
+ */
15
+ export function withSpan(name, work) {
16
+ return otelTrace.getTracer(SDK_SCOPE_NAME).startActiveSpan(name, (span) => {
17
+ try {
18
+ const result = work();
19
+ if (result instanceof Promise) {
20
+ return result.then((value) => {
21
+ span.end();
22
+ return value;
23
+ }, (error) => {
24
+ fail(span, error);
25
+ throw error;
26
+ });
27
+ }
28
+ span.end();
29
+ return result;
30
+ }
31
+ catch (error) {
32
+ fail(span, error);
33
+ throw error;
34
+ }
35
+ });
36
+ }
37
+ function fail(span, error) {
38
+ span.recordException(error instanceof Error ? error : String(error));
39
+ span.setStatus({ code: SpanStatusCode.ERROR, message: error instanceof Error ? error.message : String(error) });
40
+ span.end();
41
+ }
42
+ /**
43
+ * Class decorator: every method becomes a step of the trace, named "ClassName.method".
44
+ *
45
+ * @spanport.trace()
46
+ * @Injectable()
47
+ * export class VariablesService { ... }
48
+ *
49
+ * Works with TypeScript's legacy decorators (NestJS) and standard ones. Method metadata (e.g.
50
+ * NestJS route paths) is copied to the timed method, so frameworks keep working.
51
+ *
52
+ * @param name - The name used before the dot; the class's own name by default.
53
+ */
54
+ export function trace(name) {
55
+ // Standard decorators also pass a context object; it isn't needed, so it isn't declared.
56
+ return (target) => {
57
+ const className = name ?? (target.name || ANONYMOUS_CLASS_NAME);
58
+ const prototype = target.prototype;
59
+ for (const methodName of Object.getOwnPropertyNames(prototype)) {
60
+ const descriptor = Object.getOwnPropertyDescriptor(prototype, methodName);
61
+ if (methodName === CONSTRUCTOR_NAME || typeof descriptor?.value !== "function")
62
+ continue;
63
+ const timed = timedMethod(`${className}${SPAN_NAME_SEPARATOR}${methodName}`, descriptor.value);
64
+ Object.defineProperty(prototype, methodName, { ...descriptor, value: timed });
65
+ }
66
+ };
67
+ }
68
+ /** A method that runs the original inside a span, carrying over its name and metadata. */
69
+ function timedMethod(spanName, original) {
70
+ const timed = function (...args) {
71
+ return withSpan(spanName, () => original.apply(this, args));
72
+ };
73
+ Object.defineProperty(timed, "name", { value: original.name });
74
+ copyMetadata(original, timed);
75
+ return timed;
76
+ }
77
+ /** Copy reflect-metadata entries (NestJS route paths, guards...) from one function to another. */
78
+ function copyMetadata(from, to) {
79
+ const reflect = Reflect;
80
+ if (!reflect.getMetadataKeys || !reflect.getMetadata || !reflect.defineMetadata)
81
+ return;
82
+ for (const key of reflect.getMetadataKeys(from)) {
83
+ reflect.defineMetadata(key, reflect.getMetadata(key, from), to);
84
+ }
85
+ }
86
+ //# sourceMappingURL=spans.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"spans.js","sourceRoot":"","sources":["../src/spans.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,37 @@
1
+ /**
2
+ * Traces: each request the app handles, and each step inside it (outgoing HTTP, database calls,
3
+ * decorated controllers and services), sent in the background to the collector's /v1/traces.
4
+ */
5
+ import { OTLPTraceExporter } from "@opentelemetry/exporter-trace-otlp-http";
6
+ import { type SpanExporter, TracerProvider } from "@opentelemetry/sdk-trace";
7
+ export interface ActiveTracing {
8
+ provider: TracerProvider;
9
+ /** Names of the optional instrumentations the app had installed. */
10
+ optional: string[];
11
+ /** Send what is queued, then stop tracing and put the globals back. */
12
+ stop: () => Promise<void>;
13
+ }
14
+ /** Hosts the SDK itself talks to; requests to them are never traced, so Spanport never traces itself. */
15
+ export interface OwnHosts {
16
+ collectorUrl: string;
17
+ serverUrl: string;
18
+ }
19
+ /**
20
+ * Exporter that sends span batches to the collector with the data key as a bearer token.
21
+ *
22
+ * @param collectorUrl - Base URL of the OTel Collector, e.g. "http://localhost:4318".
23
+ * @param dataKey - The raw data key.
24
+ */
25
+ export declare function buildTraceExporter(collectorUrl: string, dataKey: string): OTLPTraceExporter;
26
+ /**
27
+ * Start tracing: keep the current request across awaits, register the tracer provider and switch
28
+ * on HTTP timing plus any optional instrumentation the app has installed.
29
+ *
30
+ * @param service - Service name shown in Spanport.
31
+ * @param exporter - Where span batches go; OTLP in real use, in-memory in tests.
32
+ * @param ownHosts - The SDK's own collector and server, never traced.
33
+ * @param loadModule - Loads an optional instrumentation by name; tests pass their own.
34
+ * @returns The running tracing, and how to stop it.
35
+ */
36
+ export declare function startTracing(service: string, exporter: SpanExporter, ownHosts: OwnHosts, loadModule?: (name: string) => unknown): ActiveTracing;
37
+ //# sourceMappingURL=tracing.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tracing.d.ts","sourceRoot":"","sources":["../src/tracing.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAOH,OAAO,EAAE,iBAAiB,EAAE,MAAM,yCAAyC,CAAC;AAI5E,OAAO,EAAsB,KAAK,YAAY,EAAE,cAAc,EAAE,MAAM,0BAA0B,CAAC;AAYjG,MAAM,WAAW,aAAa;IAC5B,QAAQ,EAAE,cAAc,CAAC;IACzB,oEAAoE;IACpE,QAAQ,EAAE,MAAM,EAAE,CAAC;IACnB,uEAAuE;IACvE,IAAI,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;CAC3B;AAED,yGAAyG;AACzG,MAAM,WAAW,QAAQ;IACvB,YAAY,EAAE,MAAM,CAAC;IACrB,SAAS,EAAE,MAAM,CAAC;CACnB;AAED;;;;;GAKG;AACH,wBAAgB,kBAAkB,CAAC,YAAY,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,iBAAiB,CAK3F;AAED;;;;;;;;;GASG;AACH,wBAAgB,YAAY,CAC1B,OAAO,EAAE,MAAM,EACf,QAAQ,EAAE,YAAY,EACtB,QAAQ,EAAE,QAAQ,EAClB,UAAU,GAAE,CAAC,IAAI,EAAE,MAAM,KAAK,OAA0B,GACvD,aAAa,CA8Bf"}
@@ -0,0 +1,128 @@
1
+ /**
2
+ * Traces: each request the app handles, and each step inside it (outgoing HTTP, database calls,
3
+ * decorated controllers and services), sent in the background to the collector's /v1/traces.
4
+ */
5
+ import { createRequire } from "node:module";
6
+ import { context, propagation, trace } from "@opentelemetry/api";
7
+ import { AsyncLocalStorageContextManager } from "@opentelemetry/context-async-hooks";
8
+ import { W3CTraceContextPropagator } from "@opentelemetry/core";
9
+ import { OTLPTraceExporter } from "@opentelemetry/exporter-trace-otlp-http";
10
+ import { registerInstrumentations } from "@opentelemetry/instrumentation";
11
+ import { HttpInstrumentation } from "@opentelemetry/instrumentation-http";
12
+ import { resourceFromAttributes } from "@opentelemetry/resources";
13
+ import { BatchSpanProcessor, TracerProvider } from "@opentelemetry/sdk-trace";
14
+ import { AUTHORIZATION_HEADER, BEARER_PREFIX, OPTIONAL_INSTRUMENTATIONS, OTLP_TRACES_PATH, PATCHED_BUILTINS, SERVICE_NAME_ATTRIBUTE, } from "./constants.js";
15
+ import { joinUrl } from "./urls.js";
16
+ /**
17
+ * Exporter that sends span batches to the collector with the data key as a bearer token.
18
+ *
19
+ * @param collectorUrl - Base URL of the OTel Collector, e.g. "http://localhost:4318".
20
+ * @param dataKey - The raw data key.
21
+ */
22
+ export function buildTraceExporter(collectorUrl, dataKey) {
23
+ return new OTLPTraceExporter({
24
+ url: joinUrl(collectorUrl, OTLP_TRACES_PATH),
25
+ headers: { [AUTHORIZATION_HEADER]: BEARER_PREFIX + dataKey },
26
+ });
27
+ }
28
+ /**
29
+ * Start tracing: keep the current request across awaits, register the tracer provider and switch
30
+ * on HTTP timing plus any optional instrumentation the app has installed.
31
+ *
32
+ * @param service - Service name shown in Spanport.
33
+ * @param exporter - Where span batches go; OTLP in real use, in-memory in tests.
34
+ * @param ownHosts - The SDK's own collector and server, never traced.
35
+ * @param loadModule - Loads an optional instrumentation by name; tests pass their own.
36
+ * @returns The running tracing, and how to stop it.
37
+ */
38
+ export function startTracing(service, exporter, ownHosts, loadModule = requireInstalled) {
39
+ const contextManager = new AsyncLocalStorageContextManager().enable();
40
+ context.setGlobalContextManager(contextManager);
41
+ // Outgoing calls carry a W3C traceparent header, so another service running the SDK joins
42
+ // the same trace (Spanport then shows the call as a service call).
43
+ propagation.setGlobalPropagator(new W3CTraceContextPropagator());
44
+ const provider = new TracerProvider({
45
+ resource: resourceFromAttributes({ [SERVICE_NAME_ATTRIBUTE]: service }),
46
+ spanProcessors: [new BatchSpanProcessor({ exporter })],
47
+ });
48
+ trace.setGlobalTracerProvider(provider);
49
+ useHttpInstrumentation(provider, ownHosts);
50
+ const optional = loadOptionalInstrumentations(loadModule);
51
+ const unregisterOptional = registerInstrumentations({
52
+ tracerProvider: provider,
53
+ instrumentations: optional.map((loaded) => loaded.instrumentation),
54
+ });
55
+ return {
56
+ provider,
57
+ optional: optional.map((loaded) => loaded.module),
58
+ stop: async () => {
59
+ unregisterOptional();
60
+ // The HTTP instrumentation stays on (see useHttpInstrumentation); with its provider shut
61
+ // down, the spans it makes go nowhere.
62
+ await provider.shutdown();
63
+ trace.disable();
64
+ context.disable();
65
+ propagation.disable();
66
+ },
67
+ };
68
+ }
69
+ // The HTTP instrumentation is switched on once per process and stays on. Node's http module is
70
+ // patched when it is require()d, which happens once; switched off, the instrumentation can't
71
+ // patch it again, so a later init() (after shutdown()) would time nothing.
72
+ let httpInstrumentation;
73
+ /**
74
+ * Time incoming requests and outgoing http/https calls (except the SDK's own) into `provider`.
75
+ */
76
+ function useHttpInstrumentation(provider, ownHosts) {
77
+ const ownOrigins = new Set([new URL(ownHosts.collectorUrl).host, new URL(ownHosts.serverUrl).host]);
78
+ const config = {
79
+ ignoreOutgoingRequestHook: (request) => ownOrigins.has(outgoingHost(request)),
80
+ };
81
+ if (httpInstrumentation) {
82
+ httpInstrumentation.setConfig(config);
83
+ httpInstrumentation.setTracerProvider(provider);
84
+ return;
85
+ }
86
+ httpInstrumentation = new HttpInstrumentation(config);
87
+ registerInstrumentations({ tracerProvider: provider, instrumentations: [httpInstrumentation] });
88
+ // Node's http/https are usually loaded already, and ESM imports never go through require, so
89
+ // require them once now: that patches the shared module object ESM and CommonJS code both use.
90
+ for (const builtin of PATCHED_BUILTINS)
91
+ requireFromApp(builtin);
92
+ }
93
+ /** "host:port" of an outgoing request, as URL.host writes it (no port for the default one). */
94
+ function outgoingHost(request) {
95
+ const host = request.hostname ?? request.host ?? "";
96
+ return request.port ? `${host}:${String(request.port)}` : host;
97
+ }
98
+ /** The optional instrumentations the app has installed; anything missing is skipped quietly. */
99
+ function loadOptionalInstrumentations(loadModule) {
100
+ const loaded = [];
101
+ for (const { module, exportName } of OPTIONAL_INSTRUMENTATIONS) {
102
+ const instrumentation = construct(loadModule(module), exportName);
103
+ if (instrumentation)
104
+ loaded.push({ module, instrumentation });
105
+ }
106
+ return loaded;
107
+ }
108
+ /** `new exports[exportName]()`, or undefined when the module or the class isn't there. */
109
+ function construct(moduleExports, exportName) {
110
+ if (typeof moduleExports !== "object" || moduleExports === null)
111
+ return undefined;
112
+ const exported = moduleExports[exportName];
113
+ if (typeof exported !== "function")
114
+ return undefined;
115
+ return new exported();
116
+ }
117
+ const requireFromApp = createRequire(import.meta.url);
118
+ /** The module if the app has it installed, else undefined. */
119
+ function requireInstalled(name) {
120
+ try {
121
+ return requireFromApp(name);
122
+ }
123
+ catch {
124
+ // Not installed: that instrumentation is simply off.
125
+ return undefined;
126
+ }
127
+ }
128
+ //# sourceMappingURL=tracing.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tracing.js","sourceRoot":"","sources":["../src/tracing.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAE5C,OAAO,EAAE,OAAO,EAAE,WAAW,EAAE,KAAK,EAAE,MAAM,oBAAoB,CAAC;AACjE,OAAO,EAAE,+BAA+B,EAAE,MAAM,oCAAoC,CAAC;AACrF,OAAO,EAAE,yBAAyB,EAAE,MAAM,qBAAqB,CAAC;AAChE,OAAO,EAAE,iBAAiB,EAAE,MAAM,yCAAyC,CAAC;AAC5E,OAAO,EAAwB,wBAAwB,EAAE,MAAM,gCAAgC,CAAC;AAChG,OAAO,EAAE,mBAAmB,EAAE,MAAM,qCAAqC,CAAC;AAC1E,OAAO,EAAE,sBAAsB,EAAE,MAAM,0BAA0B,CAAC;AAClE,OAAO,EAAE,kBAAkB,EAAqB,cAAc,EAAE,MAAM,0BAA0B,CAAC;AAEjG,OAAO,EACL,oBAAoB,EACpB,aAAa,EACb,yBAAyB,EACzB,gBAAgB,EAChB,gBAAgB,EAChB,sBAAsB,GACvB,MAAM,gBAAgB,CAAC;AACxB,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAgBpC;;;;;GAKG;AACH,MAAM,UAAU,kBAAkB,CAAC,YAAoB,EAAE,OAAe;IACtE,OAAO,IAAI,iBAAiB,CAAC;QAC3B,GAAG,EAAE,OAAO,CAAC,YAAY,EAAE,gBAAgB,CAAC;QAC5C,OAAO,EAAE,EAAE,CAAC,oBAAoB,CAAC,EAAE,aAAa,GAAG,OAAO,EAAE;KAC7D,CAAC,CAAC;AACL,CAAC;AAED;;;;;;;;;GASG;AACH,MAAM,UAAU,YAAY,CAC1B,OAAe,EACf,QAAsB,EACtB,QAAkB,EAClB,aAAwC,gBAAgB;IAExD,MAAM,cAAc,GAAG,IAAI,+BAA+B,EAAE,CAAC,MAAM,EAAE,CAAC;IACtE,OAAO,CAAC,uBAAuB,CAAC,cAAc,CAAC,CAAC;IAChD,0FAA0F;IAC1F,mEAAmE;IACnE,WAAW,CAAC,mBAAmB,CAAC,IAAI,yBAAyB,EAAE,CAAC,CAAC;IACjE,MAAM,QAAQ,GAAG,IAAI,cAAc,CAAC;QAClC,QAAQ,EAAE,sBAAsB,CAAC,EAAE,CAAC,sBAAsB,CAAC,EAAE,OAAO,EAAE,CAAC;QACvE,cAAc,EAAE,CAAC,IAAI,kBAAkB,CAAC,EAAE,QAAQ,EAAE,CAAC,CAAC;KACvD,CAAC,CAAC;IACH,KAAK,CAAC,uBAAuB,CAAC,QAAQ,CAAC,CAAC;IACxC,sBAAsB,CAAC,QAAQ,EAAE,QAAQ,CAAC,CAAC;IAC3C,MAAM,QAAQ,GAAG,4BAA4B,CAAC,UAAU,CAAC,CAAC;IAC1D,MAAM,kBAAkB,GAAG,wBAAwB,CAAC;QAClD,cAAc,EAAE,QAAQ;QACxB,gBAAgB,EAAE,QAAQ,CAAC,GAAG,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,MAAM,CAAC,eAAe,CAAC;KACnE,CAAC,CAAC;IACH,OAAO;QACL,QAAQ;QACR,QAAQ,EAAE,QAAQ,CAAC,GAAG,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,MAAM,CAAC,MAAM,CAAC;QACjD,IAAI,EAAE,KAAK,IAAI,EAAE;YACf,kBAAkB,EAAE,CAAC;YACrB,yFAAyF;YACzF,uCAAuC;YACvC,MAAM,QAAQ,CAAC,QAAQ,EAAE,CAAC;YAC1B,KAAK,CAAC,OAAO,EAAE,CAAC;YAChB,OAAO,CAAC,OAAO,EAAE,CAAC;YAClB,WAAW,CAAC,OAAO,EAAE,CAAC;QACxB,CAAC;KACF,CAAC;AACJ,CAAC;AAED,+FAA+F;AAC/F,6FAA6F;AAC7F,2EAA2E;AAC3E,IAAI,mBAAoD,CAAC;AAEzD;;GAEG;AACH,SAAS,sBAAsB,CAAC,QAAwB,EAAE,QAAkB;IAC1E,MAAM,UAAU,GAAG,IAAI,GAAG,CAAC,CAAC,IAAI,GAAG,CAAC,QAAQ,CAAC,YAAY,CAAC,CAAC,IAAI,EAAE,IAAI,GAAG,CAAC,QAAQ,CAAC,SAAS,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC;IACpG,MAAM,MAAM,GAAG;QACb,yBAAyB,EAAE,CAAC,OAA2C,EAAE,EAAE,CAAC,UAAU,CAAC,GAAG,CAAC,YAAY,CAAC,OAAO,CAAC,CAAC;KAClH,CAAC;IACF,IAAI,mBAAmB,EAAE,CAAC;QACxB,mBAAmB,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC;QACtC,mBAAmB,CAAC,iBAAiB,CAAC,QAAQ,CAAC,CAAC;QAChD,OAAO;IACT,CAAC;IACD,mBAAmB,GAAG,IAAI,mBAAmB,CAAC,MAAM,CAAC,CAAC;IACtD,wBAAwB,CAAC,EAAE,cAAc,EAAE,QAAQ,EAAE,gBAAgB,EAAE,CAAC,mBAAmB,CAAC,EAAE,CAAC,CAAC;IAChG,6FAA6F;IAC7F,+FAA+F;IAC/F,KAAK,MAAM,OAAO,IAAI,gBAAgB;QAAE,cAAc,CAAC,OAAO,CAAC,CAAC;AAClE,CAAC;AAED,+FAA+F;AAC/F,SAAS,YAAY,CAAC,OAIrB;IACC,MAAM,IAAI,GAAG,OAAO,CAAC,QAAQ,IAAI,OAAO,CAAC,IAAI,IAAI,EAAE,CAAC;IACpD,OAAO,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,GAAG,IAAI,IAAI,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC;AACjE,CAAC;AAOD,gGAAgG;AAChG,SAAS,4BAA4B,CAAC,UAAqC;IACzE,MAAM,MAAM,GAA4B,EAAE,CAAC;IAC3C,KAAK,MAAM,EAAE,MAAM,EAAE,UAAU,EAAE,IAAI,yBAAyB,EAAE,CAAC;QAC/D,MAAM,eAAe,GAAG,SAAS,CAAC,UAAU,CAAC,MAAM,CAAC,EAAE,UAAU,CAAC,CAAC;QAClE,IAAI,eAAe;YAAE,MAAM,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,eAAe,EAAE,CAAC,CAAC;IAChE,CAAC;IACD,OAAO,MAAM,CAAC;AAChB,CAAC;AAED,0FAA0F;AAC1F,SAAS,SAAS,CAAC,aAAsB,EAAE,UAAkB;IAC3D,IAAI,OAAO,aAAa,KAAK,QAAQ,IAAI,aAAa,KAAK,IAAI;QAAE,OAAO,SAAS,CAAC;IAClF,MAAM,QAAQ,GAAa,aAAyC,CAAC,UAAU,CAAC,CAAC;IACjF,IAAI,OAAO,QAAQ,KAAK,UAAU;QAAE,OAAO,SAAS,CAAC;IACrD,OAAO,IAAK,QAAsC,EAAE,CAAC;AACvD,CAAC;AAED,MAAM,cAAc,GAAG,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AAEtD,8DAA8D;AAC9D,SAAS,gBAAgB,CAAC,IAAY;IACpC,IAAI,CAAC;QACH,OAAO,cAAc,CAAC,IAAI,CAAC,CAAC;IAC9B,CAAC;IAAC,MAAM,CAAC;QACP,qDAAqD;QACrD,OAAO,SAAS,CAAC;IACnB,CAAC;AACH,CAAC"}
package/package.json CHANGED
@@ -1,9 +1,10 @@
1
1
  {
2
2
  "name": "spanport",
3
- "version": "0.1.1",
4
- "description": "Send your Node.js app's logs to Spanport. Keep logging the way you already do.",
3
+ "version": "1.0.0",
4
+ "description": "Send your Node.js app's logs and request traces to Spanport. Keep logging the way you already do.",
5
5
  "keywords": [
6
6
  "logging",
7
+ "tracing",
7
8
  "observability",
8
9
  "opentelemetry",
9
10
  "otlp",
@@ -11,7 +12,7 @@
11
12
  ],
12
13
  "license": "Apache-2.0",
13
14
  "author": "Nitish Bharadwaj <nitishbharadwaj2002@gmail.com>",
14
- "homepage": "https://github.com/span-port/spanport",
15
+ "homepage": "https://github.com/span-port/spanport/tree/sdk-node-v1.0.0/sdk/node#readme",
15
16
  "repository": {
16
17
  "type": "git",
17
18
  "url": "git+https://github.com/span-port/spanport.git",
@@ -42,14 +43,18 @@
42
43
  },
43
44
  "dependencies": {
44
45
  "@opentelemetry/api": ">=1.10.0 <1.11.0",
46
+ "@opentelemetry/context-async-hooks": ">=3.0.0 <4.0.0",
47
+ "@opentelemetry/core": ">=3.0.0 <4.0.0",
45
48
  "@opentelemetry/exporter-logs-otlp-http": ">=0.300.0 <0.301.0",
49
+ "@opentelemetry/exporter-trace-otlp-http": ">=0.300.0 <0.301.0",
50
+ "@opentelemetry/instrumentation": ">=0.300.0 <0.301.0",
51
+ "@opentelemetry/instrumentation-http": ">=0.300.0 <0.301.0",
46
52
  "@opentelemetry/resources": ">=3.0.0 <4.0.0",
47
- "@opentelemetry/sdk-logs": ">=3.0.0 <4.0.0"
53
+ "@opentelemetry/sdk-logs": ">=3.0.0 <4.0.0",
54
+ "@opentelemetry/sdk-trace": ">=3.0.0 <4.0.0"
48
55
  },
49
56
  "devDependencies": {
50
57
  "@eslint/js": "10.0.1",
51
- "@opentelemetry/context-async-hooks": "3.0.0",
52
- "@opentelemetry/sdk-trace": "3.0.0",
53
58
  "@types/node": "22.20.5",
54
59
  "eslint": "10.13.0",
55
60
  "typescript": "6.0.3",