@tracepanel/js 0.3.1 → 0.3.3

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
@@ -216,9 +216,13 @@ page's, such as a dev server's client.
216
216
  - SQL from `pg` and `mysql2` (and so Drizzle, Knex, Sequelize, TypeORM and
217
217
  Prisma's driver adapters), with the line of your code that ran each
218
218
  statement. Prisma's operations show as steps.
219
+ - Transactions: BEGIN … COMMIT (or ROLLBACK) on a `pg` client or a `mysql2`
220
+ connection, with its statements and the calls made inside it, and its
221
+ savepoints.
219
222
  - Redis commands (`ioredis`, `redis`) and MongoDB commands, with their own
220
223
  N+1 and duplicates.
221
- - Outgoing HTTP calls: `fetch()`, and `node:http` clients such as axios.
224
+ - Outgoing HTTP calls: `fetch()`, and `node:http` clients such as axios, on
225
+ Node and on Bun.
222
226
  - BullMQ: each job a worker runs is a task, each job the app adds a step.
223
227
  - `console` calls made during a request, and Nest's `Logger`.
224
228
  - Errors thrown in a handler, with your frames and their source.
@@ -240,6 +244,20 @@ request it is a step. `span()` is a step of the current trace. Outside
240
244
  development they run the function and nothing else. Run a script with
241
245
  `npx tracepanel run node script.js`.
242
246
 
247
+ ## The signed-in user
248
+
249
+ ```js
250
+ import { setUser } from "@tracepanel/js";
251
+
252
+ setUser({ id: customer.id, username: customer.email });
253
+ ```
254
+
255
+ Call `setUser()` where the app knows who is signed in, such as its auth
256
+ middleware. The request's trace gets `user.id`, and `user.username` and
257
+ `user.email` when given, as the Python SDK records them. `setUser(null)`
258
+ marks a request nobody signed in to. The username and email stay on your
259
+ machine. Outside a trace it does nothing.
260
+
243
261
  ## Settings
244
262
 
245
263
  Environment variables, as in the Python SDK:
package/dist/api.d.ts CHANGED
@@ -9,3 +9,15 @@ export interface TraceOptions {
9
9
  export declare function trace<T>(name: string, fn: () => T | Promise<T>, options?: TraceOptions): Promise<Awaited<T>>;
10
10
  /** Runs the function as a step of the current trace, with its SQL, calls and logs inside it. */
11
11
  export declare function span<T>(name: string, fn: () => T | Promise<T>, attrs?: Attributes): Promise<Awaited<T>>;
12
+ /** The signed-in user, as the Python SDK names one: `user.id`, and the username and email if the app gives them. */
13
+ export interface User {
14
+ id: string | number;
15
+ username?: string;
16
+ email?: string;
17
+ }
18
+ /**
19
+ * Names the signed-in user on the current trace (`null`: nobody is signed in), so the console shows whose request
20
+ * it was and finds a user's traces. The username and email stay on this machine: the agent drops them before
21
+ * anything leaves it.
22
+ */
23
+ export declare function setUser(user: User | null): void;
package/dist/api.js CHANGED
@@ -1,8 +1,10 @@
1
- // The app's own steps and traces. Outside development, and outside a trace, these run the function and nothing else.
1
+ // The app's own steps and traces, and who the request is for. Outside development, and outside a trace, these run
2
+ // the function and nothing else.
2
3
  //
3
4
  // await trace("rebuild index", async () => {
4
5
  // await span("load rows", () => loadRows());
5
6
  // });
7
+ // setUser({ id: customer.id, username: customer.email });
6
8
  import { trace as otel, SpanKind, SpanStatusCode } from "@opentelemetry/api";
7
9
  const tracer = otel.getTracer("tracepanel");
8
10
  async function run(name, attributes, kind, fn) {
@@ -31,4 +33,25 @@ export function trace(name, fn, options = {}) {
31
33
  export function span(name, fn, attrs = {}) {
32
34
  return run(name, attrs, SpanKind.INTERNAL, fn);
33
35
  }
36
+ const RUNTIME = Symbol.for("tracepanel.runtime");
37
+ /**
38
+ * Names the signed-in user on the current trace (`null`: nobody is signed in), so the console shows whose request
39
+ * it was and finds a user's traces. The username and email stay on this machine: the agent drops them before
40
+ * anything leaves it.
41
+ */
42
+ export function setUser(user) {
43
+ // From the process's Tracepanel on globalThis: code bundled apart from the SDK (a Next.js route) reaches it too.
44
+ const tracepanel = globalThis[RUNTIME];
45
+ if (!tracepanel)
46
+ return;
47
+ if (user === null) {
48
+ tracepanel.processor.setTraceAttrs({ "user.id": null });
49
+ return;
50
+ }
51
+ tracepanel.processor.setTraceAttrs({
52
+ "user.id": String(user.id),
53
+ ...(user.username === undefined ? {} : { "user.username": user.username }),
54
+ ...(user.email === undefined ? {} : { "user.email": user.email }),
55
+ });
56
+ }
34
57
  //# sourceMappingURL=api.js.map
package/dist/api.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"api.js","sourceRoot":"","sources":["../src/api.ts"],"names":[],"mappings":"AAAA,qHAAqH;AACrH,EAAE;AACF,+CAA+C;AAC/C,iDAAiD;AACjD,QAAQ;AAER,OAAO,EAAmB,KAAK,IAAI,IAAI,EAAE,QAAQ,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAC;AAE9F,MAAM,MAAM,GAAG,IAAI,CAAC,SAAS,CAAC,YAAY,CAAC,CAAC;AAE5C,KAAK,UAAU,GAAG,CAChB,IAAY,EACZ,UAAsB,EACtB,IAAc,EACd,EAAwB;IAExB,OAAO,MAAM,CAAC,eAAe,CAAC,IAAI,EAAE,EAAE,IAAI,EAAE,UAAU,EAAE,EAAE,KAAK,EAAE,OAAO,EAAuB,EAAE;QAC/F,IAAI,CAAC;YACH,OAAO,MAAM,EAAE,EAAE,CAAC;QACpB,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,OAAO,CAAC,eAAe,CAAC,KAAc,CAAC,CAAC;YACxC,OAAO,CAAC,SAAS,CAAC,EAAE,IAAI,EAAE,cAAc,CAAC,KAAK,EAAE,CAAC,CAAC;YAClD,MAAM,KAAK,CAAC;QACd,CAAC;gBAAS,CAAC;YACT,OAAO,CAAC,GAAG,EAAE,CAAC;QAChB,CAAC;IACH,CAAC,CAAC,CAAC;AACL,CAAC;AASD,kHAAkH;AAClH,MAAM,UAAU,KAAK,CAAI,IAAY,EAAE,EAAwB,EAAE,OAAO,GAAiB,EAAE;IACzF,IAAI,IAAI,CAAC,aAAa,EAAE;QAAE,OAAO,IAAI,CAAC,IAAI,EAAE,EAAE,EAAE,OAAO,CAAC,KAAK,CAAC,CAAC;IAC/D,MAAM,UAAU,GAAG,EAAE,GAAG,OAAO,CAAC,KAAK,EAAE,iBAAiB,EAAE,OAAO,CAAC,IAAI,IAAI,SAAS,EAAE,iBAAiB,EAAE,IAAI,EAAE,CAAC;IAC/G,OAAO,GAAG,CAAC,IAAI,EAAE,UAAU,EAAE,QAAQ,CAAC,QAAQ,EAAE,EAAE,CAAC,CAAC;AACtD,CAAC;AAED,gGAAgG;AAChG,MAAM,UAAU,IAAI,CAAI,IAAY,EAAE,EAAwB,EAAE,KAAK,GAAe,EAAE;IACpF,OAAO,GAAG,CAAC,IAAI,EAAE,KAAK,EAAE,QAAQ,CAAC,QAAQ,EAAE,EAAE,CAAC,CAAC;AACjD,CAAC"}
1
+ {"version":3,"file":"api.js","sourceRoot":"","sources":["../src/api.ts"],"names":[],"mappings":"AAAA,kHAAkH;AAClH,iCAAiC;AACjC,EAAE;AACF,+CAA+C;AAC/C,iDAAiD;AACjD,QAAQ;AACR,4DAA4D;AAE5D,OAAO,EAAmB,KAAK,IAAI,IAAI,EAAE,QAAQ,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAC;AAG9F,MAAM,MAAM,GAAG,IAAI,CAAC,SAAS,CAAC,YAAY,CAAC,CAAC;AAE5C,KAAK,UAAU,GAAG,CAChB,IAAY,EACZ,UAAsB,EACtB,IAAc,EACd,EAAwB;IAExB,OAAO,MAAM,CAAC,eAAe,CAAC,IAAI,EAAE,EAAE,IAAI,EAAE,UAAU,EAAE,EAAE,KAAK,EAAE,OAAO,EAAuB,EAAE;QAC/F,IAAI,CAAC;YACH,OAAO,MAAM,EAAE,EAAE,CAAC;QACpB,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,OAAO,CAAC,eAAe,CAAC,KAAc,CAAC,CAAC;YACxC,OAAO,CAAC,SAAS,CAAC,EAAE,IAAI,EAAE,cAAc,CAAC,KAAK,EAAE,CAAC,CAAC;YAClD,MAAM,KAAK,CAAC;QACd,CAAC;gBAAS,CAAC;YACT,OAAO,CAAC,GAAG,EAAE,CAAC;QAChB,CAAC;IACH,CAAC,CAAC,CAAC;AACL,CAAC;AASD,kHAAkH;AAClH,MAAM,UAAU,KAAK,CAAI,IAAY,EAAE,EAAwB,EAAE,OAAO,GAAiB,EAAE;IACzF,IAAI,IAAI,CAAC,aAAa,EAAE;QAAE,OAAO,IAAI,CAAC,IAAI,EAAE,EAAE,EAAE,OAAO,CAAC,KAAK,CAAC,CAAC;IAC/D,MAAM,UAAU,GAAG,EAAE,GAAG,OAAO,CAAC,KAAK,EAAE,iBAAiB,EAAE,OAAO,CAAC,IAAI,IAAI,SAAS,EAAE,iBAAiB,EAAE,IAAI,EAAE,CAAC;IAC/G,OAAO,GAAG,CAAC,IAAI,EAAE,UAAU,EAAE,QAAQ,CAAC,QAAQ,EAAE,EAAE,CAAC,CAAC;AACtD,CAAC;AAED,gGAAgG;AAChG,MAAM,UAAU,IAAI,CAAI,IAAY,EAAE,EAAwB,EAAE,KAAK,GAAe,EAAE;IACpF,OAAO,GAAG,CAAC,IAAI,EAAE,KAAK,EAAE,QAAQ,CAAC,QAAQ,EAAE,EAAE,CAAC,CAAC;AACjD,CAAC;AASD,MAAM,OAAO,GAAG,MAAM,CAAC,GAAG,CAAC,oBAAoB,CAAC,CAAC;AAEjD;;;;GAIG;AACH,MAAM,UAAU,OAAO,CAAC,IAAiB;IACvC,iHAAiH;IACjH,MAAM,UAAU,GAAI,UAAsC,CAAC,OAAO,CAAC,CAAC;IACpE,IAAI,CAAC,UAAU;QAAE,OAAO;IACxB,IAAI,IAAI,KAAK,IAAI,EAAE,CAAC;QAClB,UAAU,CAAC,SAAS,CAAC,aAAa,CAAC,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QACxD,OAAO;IACT,CAAC;IACD,UAAU,CAAC,SAAS,CAAC,aAAa,CAAC;QACjC,SAAS,EAAE,MAAM,CAAC,IAAI,CAAC,EAAE,CAAC;QAC1B,GAAG,CAAC,IAAI,CAAC,QAAQ,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,eAAe,EAAE,IAAI,CAAC,QAAQ,EAAE,CAAC;QAC1E,GAAG,CAAC,IAAI,CAAC,KAAK,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,YAAY,EAAE,IAAI,CAAC,KAAK,EAAE,CAAC;KAClE,CAAC,CAAC;AACL,CAAC"}
package/dist/bun.js CHANGED
@@ -5,7 +5,7 @@
5
5
  // serve({ routes: { "/api/books/:id": (req) => ... }, fetch: (req) => ... });
6
6
  //
7
7
  // Start the app with `bun --preload @tracepanel/js/register server.ts` so the database driver is hooked as it loads.
8
- import { SpanKind, SpanStatusCode, trace } from "@opentelemetry/api";
8
+ import { propagation, ROOT_CONTEXT, SpanKind, SpanStatusCode, trace } from "@opentelemetry/api";
9
9
  import { start } from "./setup.js";
10
10
  import { exposedHeaders, inject } from "./widget.js";
11
11
  const tracer = trace.getTracer("tracepanel-bun");
@@ -32,7 +32,13 @@ export function withTracepanel(handler, route, onError) {
32
32
  ...(route ? { "http.route": route } : {}),
33
33
  };
34
34
  const startedMs = performance.now();
35
- return tracer.startActiveSpan(`${request.method}`, { kind: SpanKind.SERVER, attributes }, async (span) => {
35
+ // The caller's traceparent, as Node's http instrumentation reads it: the agent links the caller's trace to this.
36
+ const caller = propagation.extract(ROOT_CONTEXT, request.headers, {
37
+ get: (headers, key) => headers.get(key) ?? undefined,
38
+ keys: (headers) => [...headers.keys()],
39
+ });
40
+ const options = { kind: SpanKind.SERVER, attributes };
41
+ return tracer.startActiveSpan(`${request.method}`, options, caller, async (span) => {
36
42
  tracepanel.processor.setFramework("Bun.serve");
37
43
  try {
38
44
  let response;
package/dist/bun.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"bun.js","sourceRoot":"","sources":["../src/bun.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"bun.js","sourceRoot":"","sources":["../src/bun.ts"],"names":[],"mappings":"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"}
package/dist/explain.js CHANGED
@@ -4,7 +4,8 @@
4
4
  // The app's databases are the ones its queries ran on: each pg or mysql2 connection that queries is remembered by
5
5
  // its settings (the password among them), and EXPLAIN opens one of its own with them, so it never runs inside the
6
6
  // app's transaction. Whatever EXPLAIN ANALYZE does is rolled back.
7
- import { InstrumentationBase, InstrumentationNodeModuleDefinition } from "@opentelemetry/instrumentation";
7
+ import { InstrumentationBase, InstrumentationNodeModuleDefinition, InstrumentationNodeModuleFile, } from "@opentelemetry/instrumentation";
8
+ import { commonJs } from "./transactions.js";
8
9
  const DATABASES = new Map();
9
10
  function remember(database) {
10
11
  const key = `${database.vendor} ${database.server}:${database.port}/${database.database}`;
@@ -35,6 +36,8 @@ export async function explain(request) {
35
36
  }
36
37
  }
37
38
  const MARK = Symbol.for("tracepanel.explain");
39
+ /** Nothing to undo: the watchers stay, and only note connections. */
40
+ const keep = (exports) => exports;
38
41
  /** Records pg's and mysql2's connections as they query: where they are, and their settings. */
39
42
  export class DatabasesInstrumentation extends InstrumentationBase {
40
43
  constructor() {
@@ -43,11 +46,20 @@ export class DatabasesInstrumentation extends InstrumentationBase {
43
46
  init() {
44
47
  return [
45
48
  new InstrumentationNodeModuleDefinition("pg", [">=8"], (exports) => {
46
- this.watch(exports.Client?.prototype, (client) => rememberPg(client));
49
+ this.watch(commonJs(exports)?.Client?.prototype, (client) => rememberPg(client));
47
50
  return exports;
48
- }),
51
+ }, keep, [
52
+ // pg imported by its ES module's file URL (Nitro's dev server) loads without the hook above: its client
53
+ // class is watched as it loads, once the file's other hooks are done.
54
+ new InstrumentationNodeModuleFile("pg/lib/client.js", [">=8"], (exports) => {
55
+ const proto = commonJs(exports)?.prototype;
56
+ queueMicrotask(() => this.watch(proto, (client) => rememberPg(client)));
57
+ return exports;
58
+ }, keep),
59
+ ]),
49
60
  new InstrumentationNodeModuleDefinition("mysql2", [">=3"], (exports) => {
50
- this.watch(exports.Connection?.prototype, (client) => rememberMysql(client, exports));
61
+ const mysql2 = commonJs(exports);
62
+ this.watch(mysql2?.Connection?.prototype, (client) => rememberMysql(client, mysql2));
51
63
  return exports;
52
64
  }),
53
65
  ];
@@ -1 +1 @@
1
- {"version":3,"file":"explain.js","sourceRoot":"","sources":["../src/explain.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"explain.js","sourceRoot":"","sources":["../src/explain.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,8 @@
1
+ /** The app's line that made the call (`file:line in function`), in the context of the call. */
2
+ export declare const CALL_ORIGIN: symbol;
3
+ type Fetch = (...args: never[]) => Promise<Response>;
4
+ /** The fetch, taking the app's line as it is called. */
5
+ export declare function wrapFetch<F extends Fetch>(fetch: F, root: string): F;
6
+ /** globalThis.fetch, wrapped once per process. */
7
+ export declare function traceFetch(root: string): void;
8
+ export {};
package/dist/fetch.js ADDED
@@ -0,0 +1,27 @@
1
+ // fetch() as the app calls it. Node's undici starts the call's span from inside fetch, where none of the app's code is
2
+ // on the stack: the app's line is taken here, as the call is made, and handed to the span in its context.
3
+ import { context, createContextKey, trace } from "@opentelemetry/api";
4
+ import { origin } from "./stack.js";
5
+ /** The app's line that made the call (`file:line in function`), in the context of the call. */
6
+ export const CALL_ORIGIN = createContextKey("tracepanel.call_origin");
7
+ const WRAPPED = Symbol.for("tracepanel.fetch");
8
+ /** The fetch, taking the app's line as it is called. */
9
+ export function wrapFetch(fetch, root) {
10
+ if (fetch[WRAPPED])
11
+ return fetch;
12
+ const wrapped = function (...args) {
13
+ const found = trace.getActiveSpan() ? origin(root) : null;
14
+ if (!found)
15
+ return fetch.apply(this, args);
16
+ return context.with(context.active().setValue(CALL_ORIGIN, found), () => fetch.apply(this, args));
17
+ };
18
+ Object.defineProperty(wrapped, WRAPPED, { value: true });
19
+ return wrapped;
20
+ }
21
+ /** globalThis.fetch, wrapped once per process. */
22
+ export function traceFetch(root) {
23
+ if (typeof globalThis.fetch !== "function")
24
+ return;
25
+ globalThis.fetch = wrapFetch(globalThis.fetch, root);
26
+ }
27
+ //# sourceMappingURL=fetch.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fetch.js","sourceRoot":"","sources":["../src/fetch.ts"],"names":[],"mappings":"AAAA,uHAAuH;AACvH,0GAA0G;AAE1G,OAAO,EAAE,OAAO,EAAE,gBAAgB,EAAE,KAAK,EAAE,MAAM,oBAAoB,CAAC;AACtE,OAAO,EAAE,MAAM,EAAE,MAAM,YAAY,CAAC;AAEpC,+FAA+F;AAC/F,MAAM,CAAC,MAAM,WAAW,GAAG,gBAAgB,CAAC,wBAAwB,CAAC,CAAC;AAEtE,MAAM,OAAO,GAAG,MAAM,CAAC,GAAG,CAAC,kBAAkB,CAAC,CAAC;AAI/C,wDAAwD;AACxD,MAAM,UAAU,SAAS,CAAkB,KAAQ,EAAE,IAAY;IAC/D,IAAK,KAAiC,CAAC,OAAO,CAAC;QAAE,OAAO,KAAK,CAAC;IAC9D,MAAM,OAAO,GAAG,UAAyB,GAAG,IAAmB;QAC7D,MAAM,KAAK,GAAG,KAAK,CAAC,aAAa,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;QAC1D,IAAI,CAAC,KAAK;YAAE,OAAO,KAAK,CAAC,KAAK,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;QAC3C,OAAO,OAAO,CAAC,IAAI,CAAC,OAAO,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,WAAW,EAAE,KAAK,CAAC,EAAE,GAAG,EAAE,CAAC,KAAK,CAAC,KAAK,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC,CAAC;IACpG,CAAC,CAAC;IACF,MAAM,CAAC,cAAc,CAAC,OAAO,EAAE,OAAO,EAAE,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;IACzD,OAAO,OAAuB,CAAC;AACjC,CAAC;AAED,kDAAkD;AAClD,MAAM,UAAU,UAAU,CAAC,IAAY;IACrC,IAAI,OAAO,UAAU,CAAC,KAAK,KAAK,UAAU;QAAE,OAAO;IACnD,UAAU,CAAC,KAAK,GAAG,SAAS,CAAC,UAAU,CAAC,KAAK,EAAE,IAAI,CAAC,CAAC;AACvD,CAAC"}
package/dist/index.d.ts CHANGED
@@ -1,5 +1,5 @@
1
- export type { TraceOptions } from "./api.js";
2
- export { span, trace } from "./api.js";
1
+ export type { TraceOptions, User } from "./api.js";
2
+ export { setUser, span, trace } from "./api.js";
3
3
  export type { Config, Thresholds } from "./config.js";
4
4
  export { loadConfig } from "./config.js";
5
5
  export type { Trace } from "./model.js";
package/dist/index.js CHANGED
@@ -1,3 +1,3 @@
1
- export { span, trace } from "./api.js";
1
+ export { setUser, span, trace } from "./api.js";
2
2
  export { loadConfig } from "./config.js";
3
3
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,IAAI,EAAE,KAAK,EAAE,MAAM,UAAU,CAAC;AAEvC,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,KAAK,EAAE,MAAM,UAAU,CAAC;AAEhD,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC"}
@@ -0,0 +1,10 @@
1
+ import type { request as httpRequest } from "node:http";
2
+ type Fetch = typeof globalThis.fetch;
3
+ /** fetch(), each call an http.client span with the traceparent in its headers. */
4
+ export declare function tracedFetch(fetch: Fetch): Fetch;
5
+ type HttpRequest = typeof httpRequest;
6
+ /** node:http's (or https's) request(): each call an http.client span, its traceparent a header of the request. */
7
+ export declare function tracedRequest(request: HttpRequest, scheme: "http" | "https"): HttpRequest;
8
+ /** Bun's fetch and node:http/https, traced: what the undici and http instrumentations do on Node. */
9
+ export declare function traceBunCalls(): void;
10
+ export {};
@@ -0,0 +1,145 @@
1
+ // Outgoing HTTP on Bun. Node's instrumentations see fetch() through undici's diagnostics channel and node:http by
2
+ // patching the module as it loads; Bun's fetch has no such channel and its node:http is built in. Here both make the
3
+ // same http.client span as on Node, and send its W3C traceparent, so the callee's trace links to it.
4
+ import { createRequire } from "node:module";
5
+ import { context, propagation, SpanKind, SpanStatusCode, trace } from "@opentelemetry/api";
6
+ const tracer = trace.getTracer("tracepanel-outgoing");
7
+ const WRAPPED = Symbol.for("tracepanel.outgoing");
8
+ function attributes(method, url) {
9
+ return {
10
+ "http.request.method": method,
11
+ "url.full": url.href,
12
+ "url.scheme": url.protocol.replace(":", ""),
13
+ "server.address": url.hostname,
14
+ "server.port": url.port ? Number(url.port) : url.protocol === "https:" ? 443 : 80,
15
+ };
16
+ }
17
+ function marked(wrapped) {
18
+ Object.defineProperty(wrapped, WRAPPED, { value: true });
19
+ return wrapped;
20
+ }
21
+ function failed(span, error) {
22
+ span.recordException(error instanceof Error ? error : new Error(String(error)));
23
+ span.setStatus({ code: SpanStatusCode.ERROR });
24
+ }
25
+ /** fetch(), each call an http.client span with the traceparent in its headers. */
26
+ export function tracedFetch(fetch) {
27
+ if (fetch[WRAPPED])
28
+ return fetch;
29
+ const traced = async function (input, init) {
30
+ if (!trace.getActiveSpan())
31
+ return fetch.call(this, input, init);
32
+ const request = input instanceof Request ? input : undefined;
33
+ let url;
34
+ try {
35
+ url = new URL(request ? request.url : String(input));
36
+ }
37
+ catch {
38
+ return fetch.call(this, input, init);
39
+ }
40
+ const method = (init?.method ?? request?.method ?? "GET").toUpperCase();
41
+ const span = tracer.startSpan(method, { kind: SpanKind.CLIENT, attributes: attributes(method, url) });
42
+ const inside = trace.setSpan(context.active(), span);
43
+ const headers = new Headers(init?.headers ?? request?.headers);
44
+ propagation.inject(inside, headers, { set: (carrier, key, value) => carrier.set(key, value) });
45
+ try {
46
+ const response = await context.with(inside, () => fetch.call(this, input, { ...init, headers }));
47
+ span.setAttribute("http.response.status_code", response.status);
48
+ if (response.status >= 500)
49
+ span.setStatus({ code: SpanStatusCode.ERROR });
50
+ return response;
51
+ }
52
+ catch (error) {
53
+ failed(span, error);
54
+ throw error;
55
+ }
56
+ finally {
57
+ span.end();
58
+ }
59
+ };
60
+ return marked(Object.assign(traced, fetch));
61
+ }
62
+ /** Where a node:http request goes: request(url, options?, callback?) or request(options, callback?). */
63
+ function target(args, scheme) {
64
+ try {
65
+ const [first, second] = args;
66
+ const given = typeof first === "string" || first instanceof URL ? new URL(first) : undefined;
67
+ const options = (given ? (typeof second === "object" && second ? second : {}) : (first ?? {}));
68
+ const method = String(options.method ?? "GET").toUpperCase();
69
+ if (given)
70
+ return { method, url: given };
71
+ const host = options.hostname ?? options.host ?? "localhost";
72
+ const port = options.port ? `:${options.port}` : "";
73
+ const protocol = options.protocol ?? `${scheme}:`;
74
+ return { method, url: new URL(`${protocol}//${host}${port}${options.path ?? "/"}`) };
75
+ }
76
+ catch {
77
+ return undefined;
78
+ }
79
+ }
80
+ /** node:http's (or https's) request(): each call an http.client span, its traceparent a header of the request. */
81
+ export function tracedRequest(request, scheme) {
82
+ if (request[WRAPPED])
83
+ return request;
84
+ const send = request;
85
+ const traced = function (...args) {
86
+ const found = trace.getActiveSpan() ? target(args, scheme) : undefined;
87
+ if (!found)
88
+ return send.apply(this, args);
89
+ const span = tracer.startSpan(found.method, {
90
+ kind: SpanKind.CLIENT,
91
+ attributes: attributes(found.method, found.url),
92
+ });
93
+ const inside = trace.setSpan(context.active(), span);
94
+ const sent = context.with(inside, () => send.apply(this, args));
95
+ let ended = false;
96
+ const end = () => {
97
+ if (ended)
98
+ return;
99
+ ended = true;
100
+ span.end();
101
+ };
102
+ try {
103
+ propagation.inject(inside, sent, { set: (carrier, key, value) => carrier.setHeader(key, value) });
104
+ }
105
+ catch {
106
+ // The headers went out already: the call is recorded all the same.
107
+ }
108
+ sent.once("response", (response) => {
109
+ span.setAttribute("http.response.status_code", response.statusCode ?? 0);
110
+ if ((response.statusCode ?? 0) >= 500)
111
+ span.setStatus({ code: SpanStatusCode.ERROR });
112
+ response.once("end", end);
113
+ response.once("close", end);
114
+ });
115
+ sent.once("error", (error) => {
116
+ failed(span, error);
117
+ end();
118
+ });
119
+ sent.once("close", end);
120
+ return sent;
121
+ };
122
+ return marked(traced);
123
+ }
124
+ /** get(): request() that ends the request itself, as node:http's does. */
125
+ function tracedGet(request) {
126
+ const send = request;
127
+ return marked(function (...args) {
128
+ const sent = send.apply(this, args);
129
+ sent.end();
130
+ return sent;
131
+ });
132
+ }
133
+ /** Bun's fetch and node:http/https, traced: what the undici and http instrumentations do on Node. */
134
+ export function traceBunCalls() {
135
+ globalThis.fetch = tracedFetch(globalThis.fetch);
136
+ const require = createRequire(import.meta.url);
137
+ for (const scheme of ["http", "https"]) {
138
+ const target = require(`node:${scheme}`);
139
+ if (target.request[WRAPPED])
140
+ continue;
141
+ target.request = tracedRequest(target.request, scheme);
142
+ target.get = tracedGet(target.request);
143
+ }
144
+ }
145
+ //# sourceMappingURL=outgoing.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"outgoing.js","sourceRoot":"","sources":["../src/outgoing.ts"],"names":[],"mappings":"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"}
@@ -1,7 +1,7 @@
1
1
  import { type Context } from "@opentelemetry/api";
2
2
  import type { ReadableSpan, Span as SdkSpan, SpanProcessor } from "@opentelemetry/sdk-trace-base";
3
3
  import type { Config } from "./config.js";
4
- import { type Log, micros, type Trace } from "./model.js";
4
+ import { type Attrs, type Log, micros, type Trace } from "./model.js";
5
5
  /** Where a trace goes once its request ends. */
6
6
  export interface Sink {
7
7
  submit(trace: Trace): void;
@@ -33,6 +33,10 @@ interface Building {
33
33
  replaced: Set<string>;
34
34
  /** OTel span id: the Express route handlers' ones, so a Nest span under one can take its place. */
35
35
  expressHandlers: Set<string>;
36
+ /** OTel span ids of transaction and savepoint spans. */
37
+ transactions: Set<string>;
38
+ /** OTel span id → the app's line behind a span that is left out, for the span it stands over (Next's fetch). */
39
+ passedOrigins: Map<string, string | null>;
36
40
  /**
37
41
  * The app's line behind the latest span that had one. A driver often starts its query span later, from a callback
38
42
  * (pg's pool runs the query once it has a connection), where the stack holds none of the app's code; the
@@ -51,8 +55,13 @@ export declare class TracepanelProcessor implements SpanProcessor {
51
55
  */
52
56
  private readonly owner;
53
57
  constructor(config: Config, sink: Sink);
54
- onStart(span: SdkSpan, _parentContext: Context): void;
58
+ onStart(span: SdkSpan, parentContext: Context): void;
55
59
  onEnd(span: ReadableSpan): void;
60
+ /**
61
+ * BEGIN, COMMIT and the like in a transaction span, which stands for them. Told as the span ends: the pg
62
+ * instrumentation sets the statement after it starts.
63
+ */
64
+ private control;
56
65
  forceFlush(): Promise<void>;
57
66
  shutdown(): Promise<void>;
58
67
  /** The trace being built for the active request, with the current span's Tracepanel id. */
@@ -80,6 +89,8 @@ export declare class TracepanelProcessor implements SpanProcessor {
80
89
  setFramework(name: string): void;
81
90
  /** The route pattern the framework matched, when the root span doesn't carry one (Nitro). */
82
91
  setRoute(route: string): void;
92
+ /** Attributes of the active request's trace: the signed-in user (setUser()). */
93
+ setTraceAttrs(attrs: Attrs): void;
83
94
  /** The framework the active request ran on, as the panel shows it. */
84
95
  framework(): string | undefined;
85
96
  private start;
package/dist/processor.js CHANGED
@@ -3,10 +3,12 @@
3
3
  import { createHash } from "node:crypto";
4
4
  import { SpanKind, SpanStatusCode, trace } from "@opentelemetry/api";
5
5
  import { httpCall, isMongo, isRedis, mongoCall, redisCall } from "./calls.js";
6
+ import { CALL_ORIGIN } from "./fetch.js";
6
7
  import { withVersion } from "./frameworks.js";
7
8
  import { countDropped, limited, MAX_LOGS, micros, newId, } from "./model.js";
8
9
  import { fingerprint, spanName, statement } from "./sql.js";
9
10
  import { frames, origin } from "./stack.js";
11
+ import { CONTROL } from "./transactions.js";
10
12
  // A request's span can end after the response does (Express ends an async handler's span when its promise settles):
11
13
  // the trace goes out this long after the request's span ends, with the spans that ended meanwhile.
12
14
  const LATE_SPANS_MS = 25;
@@ -27,6 +29,8 @@ const SKIPPED_NEXT = new Set([
27
29
  "LoadComponents.loadRouteModule",
28
30
  "RouteModule.prepare",
29
31
  "ResolveMetadata.generateMetadata",
32
+ // Next's own span of a fetch(): undici's under it is the call, with the traceparent the callee got.
33
+ "AppRender.fetch",
30
34
  ]);
31
35
  // What runs a Next.js route: an app or pages render, a route handler, getServerSideProps.
32
36
  const NEXT_HANDLERS = new Set([
@@ -83,7 +87,7 @@ export class TracepanelProcessor {
83
87
  this.config = config;
84
88
  this.sink = sink;
85
89
  }
86
- onStart(span, _parentContext) {
90
+ onStart(span, parentContext) {
87
91
  const context = span.spanContext();
88
92
  const parent = span.parentSpanContext;
89
93
  let building = parent ? this.owner.get(parent.spanId) : undefined;
@@ -111,11 +115,14 @@ export class TracepanelProcessor {
111
115
  const found = origin(this.config.root);
112
116
  if (found)
113
117
  building.lastOrigin = found;
118
+ const attrs = attrsOf(span);
114
119
  if (!local && parent && skipped(span)) {
115
120
  building.ids.set(context.spanId, building.ids.get(parent.spanId) ?? null);
121
+ building.passedOrigins.set(context.spanId, found ?? building.passedOrigins.get(parent.spanId) ?? null);
116
122
  return;
117
123
  }
118
- const attrs = attrsOf(span);
124
+ if (attrs["tracepanel.span_kind"] === "transaction")
125
+ building.transactions.add(context.spanId);
119
126
  if (attrs["express.type"] === "request_handler")
120
127
  building.expressHandlers.add(context.spanId);
121
128
  if (parent && attrs["nestjs.type"] === "request_context" && building.expressHandlers.has(parent.spanId)) {
@@ -128,7 +135,11 @@ export class TracepanelProcessor {
128
135
  if (!parent && attrs["next.span_type"] === "BaseServer.handleRequest")
129
136
  building.framework = "Next.js";
130
137
  building.ids.set(context.spanId, newId());
131
- building.origins.set(context.spanId, found ?? building.lastOrigin);
138
+ // A span started outside the app's code (undici's, under Next's fetch span) is the call the app made there.
139
+ // So is one a call made from its context, which took the app's line as the app called it (fetch()).
140
+ const passed = (parent ? building.passedOrigins.get(parent.spanId) : undefined) ??
141
+ parentContext.getValue(CALL_ORIGIN);
142
+ building.origins.set(context.spanId, found ?? passed ?? building.lastOrigin);
132
143
  }
133
144
  onEnd(span) {
134
145
  if (process.env.TRACEPANEL_DEBUG) {
@@ -141,7 +152,7 @@ export class TracepanelProcessor {
141
152
  const root = context.spanId === building.rootSpanId;
142
153
  if (building.replaced.has(context.spanId))
143
154
  return;
144
- if (root || !skipped(span))
155
+ if (root || !(skipped(span) || this.control(building, span)))
145
156
  this.convert(building, span, root);
146
157
  if (!root)
147
158
  return;
@@ -151,6 +162,14 @@ export class TracepanelProcessor {
151
162
  this.sink.submit(limited(building.trace));
152
163
  }, LATE_SPANS_MS).unref();
153
164
  }
165
+ /**
166
+ * BEGIN, COMMIT and the like in a transaction span, which stands for them. Told as the span ends: the pg
167
+ * instrumentation sets the statement after it starts.
168
+ */
169
+ control(building, span) {
170
+ const parent = span.parentSpanContext?.spanId;
171
+ return parent !== undefined && building.transactions.has(parent) && CONTROL.test(statementOf(attrsOf(span)));
172
+ }
154
173
  forceFlush() {
155
174
  return Promise.resolve();
156
175
  }
@@ -247,6 +266,12 @@ export class TracepanelProcessor {
247
266
  if (current)
248
267
  current.building.route = route;
249
268
  }
269
+ /** Attributes of the active request's trace: the signed-in user (setUser()). */
270
+ setTraceAttrs(attrs) {
271
+ const current = this.current();
272
+ if (current)
273
+ Object.assign(current.building.trace.attrs, attrs);
274
+ }
250
275
  /** The framework the active request ran on, as the panel shows it. */
251
276
  framework() {
252
277
  return this.current()?.building.framework;
@@ -280,6 +305,8 @@ export class TracepanelProcessor {
280
305
  replaced: new Set(),
281
306
  nestViews: new Set(),
282
307
  expressHandlers: new Set(),
308
+ transactions: new Set(),
309
+ passedOrigins: new Map(),
283
310
  parents: new Map(),
284
311
  lastOrigin: null,
285
312
  };
@@ -333,6 +360,11 @@ export class TracepanelProcessor {
333
360
  "code.origin": codeOrigin,
334
361
  };
335
362
  }
363
+ else if (attrs["tracepanel.span_kind"] === "transaction") {
364
+ converted.kind = "transaction";
365
+ const { "tracepanel.span_kind": _, ...own } = attrs;
366
+ converted.attrs = { ...own, "code.origin": codeOrigin };
367
+ }
336
368
  else if (isRedis(attrs)) {
337
369
  const call = redisCall(attrs, span.name);
338
370
  converted.kind = "redis";