@glasstrace/sdk 1.7.0 → 1.9.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/dist/async-context/index.cjs +15005 -0
- package/dist/async-context/index.cjs.map +1 -0
- package/dist/async-context/index.d.cts +174 -0
- package/dist/async-context/index.d.ts +174 -0
- package/dist/async-context/index.js +13 -0
- package/dist/{capture-error-CTgSYxek.d.ts → capture-error-BeuEXXJO.d.cts} +40 -2
- package/dist/{capture-error-BmQz7xF6.d.cts → capture-error-D02pzB7q.d.ts} +40 -2
- package/dist/chunk-CL3OVHPO.js +23 -0
- package/dist/chunk-CL3OVHPO.js.map +1 -0
- package/dist/{chunk-WL6BXEJ5.js → chunk-DKV53A2C.js} +2 -2
- package/dist/{chunk-3PJP5Y3U.js → chunk-GWIEUBFR.js} +3 -3
- package/dist/{chunk-H57MQGNU.js → chunk-H6WJ63X2.js} +2 -2
- package/dist/{chunk-NN5YCETI.js → chunk-HD6JIFKN.js} +2 -2
- package/dist/{chunk-P45NZR4J.js → chunk-JHUNLPSS.js} +35 -1
- package/dist/{chunk-P45NZR4J.js.map → chunk-JHUNLPSS.js.map} +1 -1
- package/dist/{chunk-UQKI476D.js → chunk-M6EWJCAT.js} +2 -2
- package/dist/chunk-QHV7NFON.js +130 -0
- package/dist/chunk-QHV7NFON.js.map +1 -0
- package/dist/{chunk-M2TLX6NM.js → chunk-QXITSNYM.js} +3 -3
- package/dist/chunk-RQ5BIWDT.js +119 -0
- package/dist/chunk-RQ5BIWDT.js.map +1 -0
- package/dist/{chunk-OWPA7GHV.js → chunk-XEPC4NFL.js} +1398 -1037
- package/dist/chunk-XEPC4NFL.js.map +1 -0
- package/dist/cli/init.cjs +4 -4
- package/dist/cli/init.cjs.map +1 -1
- package/dist/cli/init.js +7 -7
- package/dist/cli/mcp-add.cjs +1 -1
- package/dist/cli/mcp-add.cjs.map +1 -1
- package/dist/cli/mcp-add.js +3 -3
- package/dist/cli/uninit.js +3 -3
- package/dist/cli/upgrade-instructions.cjs +1 -1
- package/dist/cli/upgrade-instructions.js +3 -3
- package/dist/cli/validate.cjs.map +1 -1
- package/dist/cli/validate.js +2 -2
- package/dist/{edge-entry-AWO70gje.d.ts → correlation-id-B_K8adD6.d.ts} +1 -1
- package/dist/{edge-entry-DaeG7D7S.d.cts → correlation-id-NAapJ5jn.d.cts} +1 -1
- package/dist/edge-entry.cjs +295 -26
- package/dist/edge-entry.cjs.map +1 -1
- package/dist/edge-entry.d.cts +5 -2
- package/dist/edge-entry.d.ts +5 -2
- package/dist/edge-entry.js +12 -3
- package/dist/index.cjs +3613 -3211
- package/dist/index.cjs.map +1 -1
- package/dist/{index.d-Dq33YwFT.d.cts → index.d-CkTf_boH.d.cts} +1 -1
- package/dist/{index.d-Dq33YwFT.d.ts → index.d-CkTf_boH.d.ts} +1 -1
- package/dist/index.d.cts +7 -4
- package/dist/index.d.ts +7 -4
- package/dist/index.js +6 -5
- package/dist/index.js.map +1 -1
- package/dist/middleware/index.cjs +15014 -0
- package/dist/middleware/index.cjs.map +1 -0
- package/dist/middleware/index.d.cts +183 -0
- package/dist/middleware/index.d.ts +183 -0
- package/dist/middleware/index.js +13 -0
- package/dist/middleware/index.js.map +1 -0
- package/dist/node-entry.cjs +3613 -3211
- package/dist/node-entry.cjs.map +1 -1
- package/dist/node-entry.d.cts +3 -3
- package/dist/node-entry.d.ts +3 -3
- package/dist/node-entry.js +8 -7
- package/dist/node-subpath.cjs.map +1 -1
- package/dist/node-subpath.d.cts +1 -1
- package/dist/node-subpath.d.ts +1 -1
- package/dist/node-subpath.js +3 -3
- package/dist/{source-map-uploader-XFUEVV7I.js → source-map-uploader-MMJ2WCL4.js} +3 -3
- package/dist/source-map-uploader-MMJ2WCL4.js.map +1 -0
- package/package.json +13 -1
- package/dist/chunk-OWPA7GHV.js.map +0 -1
- /package/dist/{source-map-uploader-XFUEVV7I.js.map → async-context/index.js.map} +0 -0
- /package/dist/{chunk-WL6BXEJ5.js.map → chunk-DKV53A2C.js.map} +0 -0
- /package/dist/{chunk-3PJP5Y3U.js.map → chunk-GWIEUBFR.js.map} +0 -0
- /package/dist/{chunk-H57MQGNU.js.map → chunk-H6WJ63X2.js.map} +0 -0
- /package/dist/{chunk-NN5YCETI.js.map → chunk-HD6JIFKN.js.map} +0 -0
- /package/dist/{chunk-UQKI476D.js.map → chunk-M6EWJCAT.js.map} +0 -0
- /package/dist/{chunk-M2TLX6NM.js.map → chunk-QXITSNYM.js.map} +0 -0
|
@@ -0,0 +1,183 @@
|
|
|
1
|
+
import { AttributeValue } from './common/Attributes';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Request-middleware-ownership instrumentation for Glasstrace.
|
|
5
|
+
*
|
|
6
|
+
* Subpath: `@glasstrace/sdk/middleware`
|
|
7
|
+
*
|
|
8
|
+
* This module exposes {@link tracedRequestMiddleware}, a wrapper that
|
|
9
|
+
* turns a Next.js `middleware.ts` function (or any generic
|
|
10
|
+
* `Request → Response`-shaped handler) into a span-emitting middleware
|
|
11
|
+
* function. Each invocation opens a child span and tags it with the
|
|
12
|
+
* `glasstrace.causal.middleware_for_request` causal-evidence attribute
|
|
13
|
+
* carrying the originating request's normalized path so the
|
|
14
|
+
* product-side trace-summary transform can link the middleware span
|
|
15
|
+
* to the owning HTTP request trace (DISC-1537 / SDK-046).
|
|
16
|
+
*
|
|
17
|
+
* Edge-runtime safety
|
|
18
|
+
* -------------------
|
|
19
|
+
* The wrapper is included in the SDK's edge bundle
|
|
20
|
+
* (`packages/sdk/src/edge-entry.ts`). Its closure imports only the
|
|
21
|
+
* OTel API, the protocol constants, and the
|
|
22
|
+
* `./optional-lifecycle.js` bridge — none of which reach into
|
|
23
|
+
* `node:*` built-ins or the `process` global. The F003 closure scan
|
|
24
|
+
* (`packages/sdk/scripts/check-edge-bundle.mjs`) enforces this on
|
|
25
|
+
* every build.
|
|
26
|
+
*
|
|
27
|
+
* Causal-evidence form
|
|
28
|
+
* --------------------
|
|
29
|
+
* The wrapper attaches the originating request path as a span
|
|
30
|
+
* attribute (`glasstrace.causal.middleware_for_request`). It does NOT
|
|
31
|
+
* emit an OTel `Link`. Reasons:
|
|
32
|
+
*
|
|
33
|
+
* 1. The Next.js Edge runtime does not propagate AsyncLocalStorage
|
|
34
|
+
* into `middleware.ts`, so there is no in-process
|
|
35
|
+
* `SpanContext` to link to in that environment. Attribute-only
|
|
36
|
+
* causality works in both Node and Edge runtimes; a Link would
|
|
37
|
+
* degrade to a no-op (no parent context) on Edge.
|
|
38
|
+
* 2. The product-side trace-summary transform reconstructs
|
|
39
|
+
* ownership from `glasstrace.causal.*` attributes per
|
|
40
|
+
* DISC-1539 §51-58; it does not require a Link.
|
|
41
|
+
*
|
|
42
|
+
* Invariants
|
|
43
|
+
* ----------
|
|
44
|
+
*
|
|
45
|
+
* - The wrapped function preserves the user's call-site type so
|
|
46
|
+
* Next.js's `middleware` export contract (`(req: NextRequest) =>
|
|
47
|
+
* NextResponse | Response`) flows through unchanged.
|
|
48
|
+
* - The middleware span MUST NOT overwrite `glasstrace.route`,
|
|
49
|
+
* `glasstrace.http.status_code`, or `glasstrace.http.duration_ms`
|
|
50
|
+
* on the parent HTTP span — root-request semantics are owned by
|
|
51
|
+
* the enriching exporter (`packages/sdk/src/enriching-exporter.ts`).
|
|
52
|
+
* - On a thrown handler error: span ends with `ERROR` status +
|
|
53
|
+
* `recordException`; rethrows. The exception is normalized to
|
|
54
|
+
* `Error | string` first so non-Error throwables (number, plain
|
|
55
|
+
* object) do not crash `recordException`.
|
|
56
|
+
* - Always ends the span (`finally`), even on `throw`.
|
|
57
|
+
*
|
|
58
|
+
* @module @glasstrace/sdk/middleware
|
|
59
|
+
*/
|
|
60
|
+
|
|
61
|
+
/**
|
|
62
|
+
* INTERNAL — clears the once-flag for the
|
|
63
|
+
* `middleware:skipped_uninstalled` lifecycle event. Invoked by
|
|
64
|
+
* Vitest fixtures only; not part of the public surface.
|
|
65
|
+
*/
|
|
66
|
+
declare function _resetForTesting(): void;
|
|
67
|
+
/**
|
|
68
|
+
* Permissive structural bound for a request-middleware function. The
|
|
69
|
+
* shape is the intersection of Next.js's `middleware.ts` export
|
|
70
|
+
* (`(req: NextRequest, event?: NextFetchEvent) => NextResponse |
|
|
71
|
+
* Response | Promise<NextResponse | Response> | undefined`) and the
|
|
72
|
+
* generic Web Fetch API (`(req: Request, ...rest: any[]) => Response
|
|
73
|
+
* | Promise<Response>`). The parameter list is typed with `any[]` for
|
|
74
|
+
* the rest position so any caller-narrowed signature is assignable
|
|
75
|
+
* without the wrapper having to import `next/server` types.
|
|
76
|
+
*
|
|
77
|
+
* Exported so consumers can reference it for type-inference assertions
|
|
78
|
+
* (e.g., proving a strongly-typed handler fits the bound). The
|
|
79
|
+
* runtime contract is fixed by the Web Fetch API: the first argument
|
|
80
|
+
* is a `Request`-shaped object and the return is a `Response`-shaped
|
|
81
|
+
* value (or a Promise of one).
|
|
82
|
+
*/
|
|
83
|
+
type RequestMiddlewareFunction = (req: any, ...rest: any[]) => unknown;
|
|
84
|
+
/**
|
|
85
|
+
* Options for {@link tracedRequestMiddleware}.
|
|
86
|
+
*
|
|
87
|
+
* @example
|
|
88
|
+
* ```ts
|
|
89
|
+
* import { tracedRequestMiddleware } from "@glasstrace/sdk/middleware";
|
|
90
|
+
* import type { NextRequest } from "next/server";
|
|
91
|
+
*
|
|
92
|
+
* export const middleware = tracedRequestMiddleware(
|
|
93
|
+
* { name: "auth-middleware", attributes: { "auth.required": true } },
|
|
94
|
+
* async (req: NextRequest) => {
|
|
95
|
+
* // … your auth logic here …
|
|
96
|
+
* return NextResponse.next();
|
|
97
|
+
* },
|
|
98
|
+
* );
|
|
99
|
+
* ```
|
|
100
|
+
*/
|
|
101
|
+
interface TracedRequestMiddlewareOptions {
|
|
102
|
+
/**
|
|
103
|
+
* Span name. Required, non-empty string. Used as the OTel span name
|
|
104
|
+
* and appears in trace timelines. Names should be stable across
|
|
105
|
+
* runs so the product-side transform can reason about middleware
|
|
106
|
+
* identity (e.g., "auth-middleware", "rate-limiter"); avoid
|
|
107
|
+
* embedding request data in the name.
|
|
108
|
+
*/
|
|
109
|
+
name: string;
|
|
110
|
+
/**
|
|
111
|
+
* Optional attributes attached to the span before the wrapped
|
|
112
|
+
* handler runs. Forwarded to OTel as-is via `span.setAttributes()`.
|
|
113
|
+
* The SDK does not redact, sanitize, or scan values here — callers
|
|
114
|
+
* MUST avoid placing tokens, credentials, or other sensitive data
|
|
115
|
+
* in `attributes`.
|
|
116
|
+
*
|
|
117
|
+
* Sensitive request/response data is captured through gated SDK
|
|
118
|
+
* paths (e.g., `glasstrace.error.response_body`), not through this
|
|
119
|
+
* surface.
|
|
120
|
+
*/
|
|
121
|
+
attributes?: Record<string, AttributeValue>;
|
|
122
|
+
}
|
|
123
|
+
/**
|
|
124
|
+
* Wrap a Next.js / generic-fetch request-middleware function in an
|
|
125
|
+
* OTel span tagged with `glasstrace.causal.middleware_for_request`.
|
|
126
|
+
*
|
|
127
|
+
* Each call to the returned function:
|
|
128
|
+
*
|
|
129
|
+
* 1. Detects the SDK's registration state. When the OTel API is
|
|
130
|
+
* still on the noop tracer (SDK not registered, or
|
|
131
|
+
* `OtelState.UNCONFIGURED`), runs the wrapped handler directly
|
|
132
|
+
* and emits a `middleware:skipped_uninstalled` lifecycle event
|
|
133
|
+
* (at most once per process). No span is opened.
|
|
134
|
+
* 2. Otherwise opens a span named `options.name` under the active
|
|
135
|
+
* OTel context (typically the HTTP server span on Node;
|
|
136
|
+
* detached on Edge where AsyncLocalStorage is not available).
|
|
137
|
+
* Sets `options.attributes` first, then attaches the originating
|
|
138
|
+
* request's path (via {@link extractRequestPath}) as
|
|
139
|
+
* `glasstrace.causal.middleware_for_request`. The path is
|
|
140
|
+
* omitted when extraction returns `undefined` so absent evidence
|
|
141
|
+
* is preferred over guessed evidence.
|
|
142
|
+
* 3. Awaits the wrapped handler.
|
|
143
|
+
* 4. On a thrown error: normalizes the throwable to `Error | string`
|
|
144
|
+
* so `recordException` does not throw on non-Error values; sets
|
|
145
|
+
* `span.status` to `ERROR` with the error's message; rethrows the
|
|
146
|
+
* original (un-normalized) error verbatim.
|
|
147
|
+
* 5. On a successful return: leaves the span status `UNSET` per OTel
|
|
148
|
+
* instrumentation-library guidance (explicit `OK` would shadow
|
|
149
|
+
* downstream consumers' error transitions).
|
|
150
|
+
* 6. Always ends the span, even on `throw` or `return`.
|
|
151
|
+
*
|
|
152
|
+
* Type-inference: the returned function preserves the input function's
|
|
153
|
+
* type `H`, so caller-narrowed signatures (e.g., `(req: NextRequest)
|
|
154
|
+
* => NextResponse`) flow through unchanged.
|
|
155
|
+
*
|
|
156
|
+
* @param options - Span name and optional pre-start attributes.
|
|
157
|
+
* @param handler - The user's middleware handler. Must accept a
|
|
158
|
+
* request-shaped object as its first argument and return (or
|
|
159
|
+
* resolve to) a response-shaped value.
|
|
160
|
+
* @returns The wrapped handler with the same call signature and
|
|
161
|
+
* return type as `handler`.
|
|
162
|
+
*
|
|
163
|
+
* @example Next.js middleware.ts
|
|
164
|
+
* ```ts
|
|
165
|
+
* import { tracedRequestMiddleware } from "@glasstrace/sdk/middleware";
|
|
166
|
+
* import { NextResponse, type NextRequest } from "next/server";
|
|
167
|
+
*
|
|
168
|
+
* export const middleware = tracedRequestMiddleware(
|
|
169
|
+
* { name: "auth-middleware" },
|
|
170
|
+
* async (req: NextRequest) => {
|
|
171
|
+
* if (!req.cookies.get("session")) {
|
|
172
|
+
* return NextResponse.redirect(new URL("/login", req.url));
|
|
173
|
+
* }
|
|
174
|
+
* return NextResponse.next();
|
|
175
|
+
* },
|
|
176
|
+
* );
|
|
177
|
+
*
|
|
178
|
+
* export const config = { matcher: ["/dashboard/:path*"] };
|
|
179
|
+
* ```
|
|
180
|
+
*/
|
|
181
|
+
declare function tracedRequestMiddleware<H extends RequestMiddlewareFunction>(options: TracedRequestMiddlewareOptions, handler: H): H;
|
|
182
|
+
|
|
183
|
+
export { type RequestMiddlewareFunction, type TracedRequestMiddlewareOptions, _resetForTesting, tracedRequestMiddleware };
|
|
@@ -0,0 +1,183 @@
|
|
|
1
|
+
import { AttributeValue } from './common/Attributes';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Request-middleware-ownership instrumentation for Glasstrace.
|
|
5
|
+
*
|
|
6
|
+
* Subpath: `@glasstrace/sdk/middleware`
|
|
7
|
+
*
|
|
8
|
+
* This module exposes {@link tracedRequestMiddleware}, a wrapper that
|
|
9
|
+
* turns a Next.js `middleware.ts` function (or any generic
|
|
10
|
+
* `Request → Response`-shaped handler) into a span-emitting middleware
|
|
11
|
+
* function. Each invocation opens a child span and tags it with the
|
|
12
|
+
* `glasstrace.causal.middleware_for_request` causal-evidence attribute
|
|
13
|
+
* carrying the originating request's normalized path so the
|
|
14
|
+
* product-side trace-summary transform can link the middleware span
|
|
15
|
+
* to the owning HTTP request trace (DISC-1537 / SDK-046).
|
|
16
|
+
*
|
|
17
|
+
* Edge-runtime safety
|
|
18
|
+
* -------------------
|
|
19
|
+
* The wrapper is included in the SDK's edge bundle
|
|
20
|
+
* (`packages/sdk/src/edge-entry.ts`). Its closure imports only the
|
|
21
|
+
* OTel API, the protocol constants, and the
|
|
22
|
+
* `./optional-lifecycle.js` bridge — none of which reach into
|
|
23
|
+
* `node:*` built-ins or the `process` global. The F003 closure scan
|
|
24
|
+
* (`packages/sdk/scripts/check-edge-bundle.mjs`) enforces this on
|
|
25
|
+
* every build.
|
|
26
|
+
*
|
|
27
|
+
* Causal-evidence form
|
|
28
|
+
* --------------------
|
|
29
|
+
* The wrapper attaches the originating request path as a span
|
|
30
|
+
* attribute (`glasstrace.causal.middleware_for_request`). It does NOT
|
|
31
|
+
* emit an OTel `Link`. Reasons:
|
|
32
|
+
*
|
|
33
|
+
* 1. The Next.js Edge runtime does not propagate AsyncLocalStorage
|
|
34
|
+
* into `middleware.ts`, so there is no in-process
|
|
35
|
+
* `SpanContext` to link to in that environment. Attribute-only
|
|
36
|
+
* causality works in both Node and Edge runtimes; a Link would
|
|
37
|
+
* degrade to a no-op (no parent context) on Edge.
|
|
38
|
+
* 2. The product-side trace-summary transform reconstructs
|
|
39
|
+
* ownership from `glasstrace.causal.*` attributes per
|
|
40
|
+
* DISC-1539 §51-58; it does not require a Link.
|
|
41
|
+
*
|
|
42
|
+
* Invariants
|
|
43
|
+
* ----------
|
|
44
|
+
*
|
|
45
|
+
* - The wrapped function preserves the user's call-site type so
|
|
46
|
+
* Next.js's `middleware` export contract (`(req: NextRequest) =>
|
|
47
|
+
* NextResponse | Response`) flows through unchanged.
|
|
48
|
+
* - The middleware span MUST NOT overwrite `glasstrace.route`,
|
|
49
|
+
* `glasstrace.http.status_code`, or `glasstrace.http.duration_ms`
|
|
50
|
+
* on the parent HTTP span — root-request semantics are owned by
|
|
51
|
+
* the enriching exporter (`packages/sdk/src/enriching-exporter.ts`).
|
|
52
|
+
* - On a thrown handler error: span ends with `ERROR` status +
|
|
53
|
+
* `recordException`; rethrows. The exception is normalized to
|
|
54
|
+
* `Error | string` first so non-Error throwables (number, plain
|
|
55
|
+
* object) do not crash `recordException`.
|
|
56
|
+
* - Always ends the span (`finally`), even on `throw`.
|
|
57
|
+
*
|
|
58
|
+
* @module @glasstrace/sdk/middleware
|
|
59
|
+
*/
|
|
60
|
+
|
|
61
|
+
/**
|
|
62
|
+
* INTERNAL — clears the once-flag for the
|
|
63
|
+
* `middleware:skipped_uninstalled` lifecycle event. Invoked by
|
|
64
|
+
* Vitest fixtures only; not part of the public surface.
|
|
65
|
+
*/
|
|
66
|
+
declare function _resetForTesting(): void;
|
|
67
|
+
/**
|
|
68
|
+
* Permissive structural bound for a request-middleware function. The
|
|
69
|
+
* shape is the intersection of Next.js's `middleware.ts` export
|
|
70
|
+
* (`(req: NextRequest, event?: NextFetchEvent) => NextResponse |
|
|
71
|
+
* Response | Promise<NextResponse | Response> | undefined`) and the
|
|
72
|
+
* generic Web Fetch API (`(req: Request, ...rest: any[]) => Response
|
|
73
|
+
* | Promise<Response>`). The parameter list is typed with `any[]` for
|
|
74
|
+
* the rest position so any caller-narrowed signature is assignable
|
|
75
|
+
* without the wrapper having to import `next/server` types.
|
|
76
|
+
*
|
|
77
|
+
* Exported so consumers can reference it for type-inference assertions
|
|
78
|
+
* (e.g., proving a strongly-typed handler fits the bound). The
|
|
79
|
+
* runtime contract is fixed by the Web Fetch API: the first argument
|
|
80
|
+
* is a `Request`-shaped object and the return is a `Response`-shaped
|
|
81
|
+
* value (or a Promise of one).
|
|
82
|
+
*/
|
|
83
|
+
type RequestMiddlewareFunction = (req: any, ...rest: any[]) => unknown;
|
|
84
|
+
/**
|
|
85
|
+
* Options for {@link tracedRequestMiddleware}.
|
|
86
|
+
*
|
|
87
|
+
* @example
|
|
88
|
+
* ```ts
|
|
89
|
+
* import { tracedRequestMiddleware } from "@glasstrace/sdk/middleware";
|
|
90
|
+
* import type { NextRequest } from "next/server";
|
|
91
|
+
*
|
|
92
|
+
* export const middleware = tracedRequestMiddleware(
|
|
93
|
+
* { name: "auth-middleware", attributes: { "auth.required": true } },
|
|
94
|
+
* async (req: NextRequest) => {
|
|
95
|
+
* // … your auth logic here …
|
|
96
|
+
* return NextResponse.next();
|
|
97
|
+
* },
|
|
98
|
+
* );
|
|
99
|
+
* ```
|
|
100
|
+
*/
|
|
101
|
+
interface TracedRequestMiddlewareOptions {
|
|
102
|
+
/**
|
|
103
|
+
* Span name. Required, non-empty string. Used as the OTel span name
|
|
104
|
+
* and appears in trace timelines. Names should be stable across
|
|
105
|
+
* runs so the product-side transform can reason about middleware
|
|
106
|
+
* identity (e.g., "auth-middleware", "rate-limiter"); avoid
|
|
107
|
+
* embedding request data in the name.
|
|
108
|
+
*/
|
|
109
|
+
name: string;
|
|
110
|
+
/**
|
|
111
|
+
* Optional attributes attached to the span before the wrapped
|
|
112
|
+
* handler runs. Forwarded to OTel as-is via `span.setAttributes()`.
|
|
113
|
+
* The SDK does not redact, sanitize, or scan values here — callers
|
|
114
|
+
* MUST avoid placing tokens, credentials, or other sensitive data
|
|
115
|
+
* in `attributes`.
|
|
116
|
+
*
|
|
117
|
+
* Sensitive request/response data is captured through gated SDK
|
|
118
|
+
* paths (e.g., `glasstrace.error.response_body`), not through this
|
|
119
|
+
* surface.
|
|
120
|
+
*/
|
|
121
|
+
attributes?: Record<string, AttributeValue>;
|
|
122
|
+
}
|
|
123
|
+
/**
|
|
124
|
+
* Wrap a Next.js / generic-fetch request-middleware function in an
|
|
125
|
+
* OTel span tagged with `glasstrace.causal.middleware_for_request`.
|
|
126
|
+
*
|
|
127
|
+
* Each call to the returned function:
|
|
128
|
+
*
|
|
129
|
+
* 1. Detects the SDK's registration state. When the OTel API is
|
|
130
|
+
* still on the noop tracer (SDK not registered, or
|
|
131
|
+
* `OtelState.UNCONFIGURED`), runs the wrapped handler directly
|
|
132
|
+
* and emits a `middleware:skipped_uninstalled` lifecycle event
|
|
133
|
+
* (at most once per process). No span is opened.
|
|
134
|
+
* 2. Otherwise opens a span named `options.name` under the active
|
|
135
|
+
* OTel context (typically the HTTP server span on Node;
|
|
136
|
+
* detached on Edge where AsyncLocalStorage is not available).
|
|
137
|
+
* Sets `options.attributes` first, then attaches the originating
|
|
138
|
+
* request's path (via {@link extractRequestPath}) as
|
|
139
|
+
* `glasstrace.causal.middleware_for_request`. The path is
|
|
140
|
+
* omitted when extraction returns `undefined` so absent evidence
|
|
141
|
+
* is preferred over guessed evidence.
|
|
142
|
+
* 3. Awaits the wrapped handler.
|
|
143
|
+
* 4. On a thrown error: normalizes the throwable to `Error | string`
|
|
144
|
+
* so `recordException` does not throw on non-Error values; sets
|
|
145
|
+
* `span.status` to `ERROR` with the error's message; rethrows the
|
|
146
|
+
* original (un-normalized) error verbatim.
|
|
147
|
+
* 5. On a successful return: leaves the span status `UNSET` per OTel
|
|
148
|
+
* instrumentation-library guidance (explicit `OK` would shadow
|
|
149
|
+
* downstream consumers' error transitions).
|
|
150
|
+
* 6. Always ends the span, even on `throw` or `return`.
|
|
151
|
+
*
|
|
152
|
+
* Type-inference: the returned function preserves the input function's
|
|
153
|
+
* type `H`, so caller-narrowed signatures (e.g., `(req: NextRequest)
|
|
154
|
+
* => NextResponse`) flow through unchanged.
|
|
155
|
+
*
|
|
156
|
+
* @param options - Span name and optional pre-start attributes.
|
|
157
|
+
* @param handler - The user's middleware handler. Must accept a
|
|
158
|
+
* request-shaped object as its first argument and return (or
|
|
159
|
+
* resolve to) a response-shaped value.
|
|
160
|
+
* @returns The wrapped handler with the same call signature and
|
|
161
|
+
* return type as `handler`.
|
|
162
|
+
*
|
|
163
|
+
* @example Next.js middleware.ts
|
|
164
|
+
* ```ts
|
|
165
|
+
* import { tracedRequestMiddleware } from "@glasstrace/sdk/middleware";
|
|
166
|
+
* import { NextResponse, type NextRequest } from "next/server";
|
|
167
|
+
*
|
|
168
|
+
* export const middleware = tracedRequestMiddleware(
|
|
169
|
+
* { name: "auth-middleware" },
|
|
170
|
+
* async (req: NextRequest) => {
|
|
171
|
+
* if (!req.cookies.get("session")) {
|
|
172
|
+
* return NextResponse.redirect(new URL("/login", req.url));
|
|
173
|
+
* }
|
|
174
|
+
* return NextResponse.next();
|
|
175
|
+
* },
|
|
176
|
+
* );
|
|
177
|
+
*
|
|
178
|
+
* export const config = { matcher: ["/dashboard/:path*"] };
|
|
179
|
+
* ```
|
|
180
|
+
*/
|
|
181
|
+
declare function tracedRequestMiddleware<H extends RequestMiddlewareFunction>(options: TracedRequestMiddlewareOptions, handler: H): H;
|
|
182
|
+
|
|
183
|
+
export { type RequestMiddlewareFunction, type TracedRequestMiddlewareOptions, _resetForTesting, tracedRequestMiddleware };
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import {
|
|
2
|
+
_resetForTesting,
|
|
3
|
+
tracedRequestMiddleware
|
|
4
|
+
} from "../chunk-QHV7NFON.js";
|
|
5
|
+
import "../chunk-CL3OVHPO.js";
|
|
6
|
+
import "../chunk-DQ25VOKK.js";
|
|
7
|
+
import "../chunk-JHUNLPSS.js";
|
|
8
|
+
import "../chunk-NSBPE2FW.js";
|
|
9
|
+
export {
|
|
10
|
+
_resetForTesting,
|
|
11
|
+
tracedRequestMiddleware
|
|
12
|
+
};
|
|
13
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}
|