@selvajs/server 2.0.0-beta.22 → 2.0.0-beta.24
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/api/openapi.d.ts +6 -1
- package/dist/api/openapi.d.ts.map +1 -1
- package/dist/api/openapi.js +3 -1
- package/dist/api/openapi.js.map +1 -1
- package/dist/errors/SentryErrorReporter.d.ts +24 -2
- package/dist/errors/SentryErrorReporter.d.ts.map +1 -1
- package/dist/errors/SentryErrorReporter.js +21 -6
- package/dist/errors/SentryErrorReporter.js.map +1 -1
- package/dist/errors/index.d.ts +2 -1
- package/dist/errors/index.d.ts.map +1 -1
- package/dist/errors/index.js +3 -1
- package/dist/errors/index.js.map +1 -1
- package/dist/errors/scrub.d.ts +40 -0
- package/dist/errors/scrub.d.ts.map +1 -0
- package/dist/errors/scrub.js +67 -0
- package/dist/errors/scrub.js.map +1 -0
- package/dist/http/index.d.ts +1 -0
- package/dist/http/index.d.ts.map +1 -1
- package/dist/http/index.js +1 -0
- package/dist/http/index.js.map +1 -1
- package/dist/http/request-timing.d.ts +58 -0
- package/dist/http/request-timing.d.ts.map +1 -0
- package/dist/http/request-timing.js +219 -0
- package/dist/http/request-timing.js.map +1 -0
- package/package.json +4 -4
package/dist/api/openapi.d.ts
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
* Builds an OpenAPI 3.1 document for a host's `/api/v1` from its route registry.
|
|
3
3
|
*
|
|
4
4
|
* Shared so every host publishes the same shape: `@selvajs/mcp` reads
|
|
5
|
-
* `operationId`, `x-scope`, `x-internal` and the `Idempotency-Key` parameter
|
|
5
|
+
* `operationId`, `x-scope`, `x-internal`, `x-long-running` and the `Idempotency-Key` parameter
|
|
6
6
|
* from it, and nothing else.
|
|
7
7
|
*
|
|
8
8
|
* Request schemas come from `z.toJSONSchema` over the actual validators, so a
|
|
@@ -55,6 +55,11 @@ export interface Endpoint {
|
|
|
55
55
|
errors?: number[];
|
|
56
56
|
/** Honours `Idempotency-Key`; must match the route's `idempotent` mount option. */
|
|
57
57
|
idempotent?: boolean;
|
|
58
|
+
/**
|
|
59
|
+
* Runs a Compute solve or schema read without the `solve` scope (a preview, an upload).
|
|
60
|
+
* Emitted as `x-long-running`; MCP clients give it the solve timeout.
|
|
61
|
+
*/
|
|
62
|
+
longRunning?: boolean;
|
|
58
63
|
}
|
|
59
64
|
export interface OpenApiOptions {
|
|
60
65
|
/** Route prefix every endpoint is served under, e.g. `/api/v1`. */
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"openapi.d.ts","sourceRoot":"","sources":["../../src/api/openapi.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,OAAO,EAAK,KAAK,OAAO,EAAE,MAAM,KAAK,CAAC;AACtC,OAAO,EAAsC,KAAK,cAAc,EAAE,MAAM,mBAAmB,CAAC;AAG5F,MAAM,MAAM,IAAI,GAAG,MAAM,GAAG,MAAM,GAAG,OAAO,GAAG,IAAI,GAAG,IAAI,EAAE,GAAG;IAAE,CAAC,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;CAAE,CAAC;AAErF,MAAM,MAAM,UAAU,GAAG,KAAK,GAAG,MAAM,GAAG,OAAO,GAAG,KAAK,GAAG,QAAQ,CAAC;AAErE;;;;GAIG;AACH,MAAM,MAAM,YAAY,GAAG,YAAY,GAAG,QAAQ,GAAG,OAAO,GAAG,QAAQ,CAAC;AAExE,MAAM,WAAW,QAAQ;IACxB,MAAM,EAAE,UAAU,CAAC;IACnB,2EAA2E;IAC3E,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,oGAAoG;IACpG,KAAK,EAAE,cAAc,CAAC;IACtB,+DAA+D;IAC/D,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,QAAQ,EAAE,YAAY,CAAC;IACvB,2CAA2C;IAC3C,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,6DAA6D;IAC7D,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,4DAA4D;IAC5D,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,gFAAgF;IAChF,SAAS,CAAC,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,OAAO,CAAC;QAAC,WAAW,EAAE,MAAM,CAAA;KAAE,EAAE,CAAC;IACxE,uDAAuD;IACvD,KAAK,CAAC,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,WAAW,EAAE,MAAM,CAAA;KAAE,EAAE,CAAC;IAChD,yDAAyD;IACzD,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC;IAClB,mFAAmF;IACnF,UAAU,CAAC,EAAE,OAAO,CAAC;
|
|
1
|
+
{"version":3,"file":"openapi.d.ts","sourceRoot":"","sources":["../../src/api/openapi.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,OAAO,EAAK,KAAK,OAAO,EAAE,MAAM,KAAK,CAAC;AACtC,OAAO,EAAsC,KAAK,cAAc,EAAE,MAAM,mBAAmB,CAAC;AAG5F,MAAM,MAAM,IAAI,GAAG,MAAM,GAAG,MAAM,GAAG,OAAO,GAAG,IAAI,GAAG,IAAI,EAAE,GAAG;IAAE,CAAC,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;CAAE,CAAC;AAErF,MAAM,MAAM,UAAU,GAAG,KAAK,GAAG,MAAM,GAAG,OAAO,GAAG,KAAK,GAAG,QAAQ,CAAC;AAErE;;;;GAIG;AACH,MAAM,MAAM,YAAY,GAAG,YAAY,GAAG,QAAQ,GAAG,OAAO,GAAG,QAAQ,CAAC;AAExE,MAAM,WAAW,QAAQ;IACxB,MAAM,EAAE,UAAU,CAAC;IACnB,2EAA2E;IAC3E,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,oGAAoG;IACpG,KAAK,EAAE,cAAc,CAAC;IACtB,+DAA+D;IAC/D,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,QAAQ,EAAE,YAAY,CAAC;IACvB,2CAA2C;IAC3C,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,6DAA6D;IAC7D,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,4DAA4D;IAC5D,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,gFAAgF;IAChF,SAAS,CAAC,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,OAAO,CAAC;QAAC,WAAW,EAAE,MAAM,CAAA;KAAE,EAAE,CAAC;IACxE,uDAAuD;IACvD,KAAK,CAAC,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,WAAW,EAAE,MAAM,CAAA;KAAE,EAAE,CAAC;IAChD,yDAAyD;IACzD,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC;IAClB,mFAAmF;IACnF,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB;;;OAGG;IACH,WAAW,CAAC,EAAE,OAAO,CAAC;CACtB;AAED,MAAM,WAAW,cAAc;IAC9B,mEAAmE;IACnE,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAC;QAAC,WAAW,EAAE,MAAM,CAAC;QAAC,OAAO,CAAC,EAAE;YAAE,IAAI,EAAE,MAAM,CAAA;SAAE,CAAA;KAAE,CAAC;IAC1F,eAAe,EAAE,MAAM,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC;IACtC,QAAQ,EAAE,IAAI,EAAE,CAAC;IACjB,6DAA6D;IAC7D,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC;IAC/B,uDAAuD;IACvD,iBAAiB,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC3C,yCAAyC;IACzC,YAAY,CAAC,EAAE,MAAM,EAAE,CAAC;IACxB,0DAA0D;IAC1D,yBAAyB,CAAC,EAAE,MAAM,CAAC;CACnC;AAgKD,+FAA+F;AAC/F,wBAAgB,WAAW,CAAC,EAAE,EAAE,IAAI,CAAC,QAAQ,EAAE,QAAQ,GAAG,MAAM,CAAC,GAAG,MAAM,CAMzE;AAED,wBAAgB,oBAAoB,CAAC,SAAS,EAAE,QAAQ,EAAE,EAAE,OAAO,EAAE,cAAc,GAAG,IAAI,CAuGzF"}
|
package/dist/api/openapi.js
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
* Builds an OpenAPI 3.1 document for a host's `/api/v1` from its route registry.
|
|
3
3
|
*
|
|
4
4
|
* Shared so every host publishes the same shape: `@selvajs/mcp` reads
|
|
5
|
-
* `operationId`, `x-scope`, `x-internal` and the `Idempotency-Key` parameter
|
|
5
|
+
* `operationId`, `x-scope`, `x-internal`, `x-long-running` and the `Idempotency-Key` parameter
|
|
6
6
|
* from it, and nothing else.
|
|
7
7
|
*
|
|
8
8
|
* Request schemas come from `z.toJSONSchema` over the actual validators, so a
|
|
@@ -110,6 +110,8 @@ function operationFor(ep, errorDescriptions, alwaysErrors) {
|
|
|
110
110
|
};
|
|
111
111
|
if (ep.internal)
|
|
112
112
|
op['x-internal'] = true;
|
|
113
|
+
if (ep.longRunning)
|
|
114
|
+
op['x-long-running'] = true;
|
|
113
115
|
const params = parametersFor(ep);
|
|
114
116
|
if (params.length)
|
|
115
117
|
op.parameters = params;
|
package/dist/api/openapi.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"openapi.js","sourceRoot":"","sources":["../../src/api/openapi.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,OAAO,EAAE,CAAC,EAAgB,MAAM,KAAK,CAAC;AACtC,OAAO,EAAE,kBAAkB,EAAE,cAAc,EAAuB,MAAM,mBAAmB,CAAC;AAC5F,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;
|
|
1
|
+
{"version":3,"file":"openapi.js","sourceRoot":"","sources":["../../src/api/openapi.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,15 +1,37 @@
|
|
|
1
1
|
import type { ErrorContext, IErrorReporter } from '@selvajs/platform';
|
|
2
|
+
/**
|
|
3
|
+
* `IErrorReporter` backed by Sentry. `@sentry/node` is an OPTIONAL peer dependency: a
|
|
4
|
+
* deployment without a DSN never loads it, so the surface below is narrowed to the calls used
|
|
5
|
+
* here and the import stays dynamic — a static one would make the package mandatory.
|
|
6
|
+
*
|
|
7
|
+
* A host that already runs a Sentry SDK (a framework one that also traces requests) hands it
|
|
8
|
+
* to `fromClient` instead, so Sentry is initialized once.
|
|
9
|
+
*/
|
|
10
|
+
export interface SentryLike {
|
|
11
|
+
captureException(error: unknown, context?: {
|
|
12
|
+
tags?: Record<string, string>;
|
|
13
|
+
user?: {
|
|
14
|
+
id?: string;
|
|
15
|
+
};
|
|
16
|
+
level?: 'fatal' | 'error' | 'warning';
|
|
17
|
+
fingerprint?: string[];
|
|
18
|
+
}): unknown;
|
|
19
|
+
}
|
|
2
20
|
export declare class SentryErrorReporter implements IErrorReporter {
|
|
3
21
|
private readonly sentry;
|
|
4
22
|
private constructor();
|
|
23
|
+
/** A reporter over an SDK the host initialized itself; it should pass `scrub.ts`'s hooks. */
|
|
24
|
+
static fromClient(sentry: SentryLike): SentryErrorReporter;
|
|
5
25
|
/**
|
|
6
|
-
* Initialize
|
|
7
|
-
* won't load. Never throws — a broken error-tracker must not take down boot.
|
|
26
|
+
* Initialize `@sentry/node` with the scrubbing hooks and return a reporter, or `null` when
|
|
27
|
+
* it won't load. Never throws — a broken error-tracker must not take down boot.
|
|
8
28
|
*/
|
|
9
29
|
static create(opts: {
|
|
10
30
|
dsn: string;
|
|
11
31
|
environment?: string;
|
|
12
32
|
release?: string;
|
|
33
|
+
/** `SENTRY_TRACES_SAMPLE_RATE` as read from env; unset is 0, error tracking only. */
|
|
34
|
+
tracesSampleRate?: string | number;
|
|
13
35
|
}): Promise<SentryErrorReporter | null>;
|
|
14
36
|
capture(error: unknown, context?: ErrorContext): void;
|
|
15
37
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"SentryErrorReporter.d.ts","sourceRoot":"","sources":["../../src/errors/SentryErrorReporter.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;
|
|
1
|
+
{"version":3,"file":"SentryErrorReporter.d.ts","sourceRoot":"","sources":["../../src/errors/SentryErrorReporter.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AAGtE;;;;;;;GAOG;AACH,MAAM,WAAW,UAAU;IAC1B,gBAAgB,CACf,KAAK,EAAE,OAAO,EACd,OAAO,CAAC,EAAE;QACT,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;QAC9B,IAAI,CAAC,EAAE;YAAE,EAAE,CAAC,EAAE,MAAM,CAAA;SAAE,CAAC;QACvB,KAAK,CAAC,EAAE,OAAO,GAAG,OAAO,GAAG,SAAS,CAAC;QACtC,WAAW,CAAC,EAAE,MAAM,EAAE,CAAC;KACvB,GACC,OAAO,CAAC;CACX;AAeD,qBAAa,mBAAoB,YAAW,cAAc;IACrC,OAAO,CAAC,QAAQ,CAAC,MAAM;IAA3C,OAAO;IAEP,6FAA6F;IAC7F,MAAM,CAAC,UAAU,CAAC,MAAM,EAAE,UAAU,GAAG,mBAAmB;IAI1D;;;OAGG;WACU,MAAM,CAAC,IAAI,EAAE;QACzB,GAAG,EAAE,MAAM,CAAC;QACZ,WAAW,CAAC,EAAE,MAAM,CAAC;QACrB,OAAO,CAAC,EAAE,MAAM,CAAC;QACjB,qFAAqF;QACrF,gBAAgB,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;KACnC,GAAG,OAAO,CAAC,mBAAmB,GAAG,IAAI,CAAC;IAkCvC,OAAO,CAAC,KAAK,EAAE,OAAO,EAAE,OAAO,CAAC,EAAE,YAAY,GAAG,IAAI;CAoBrD"}
|
|
@@ -1,11 +1,16 @@
|
|
|
1
|
+
import { sampleRate, scrubBreadcrumb, scrubEvent } from './scrub.js';
|
|
1
2
|
export class SentryErrorReporter {
|
|
2
3
|
sentry;
|
|
3
4
|
constructor(sentry) {
|
|
4
5
|
this.sentry = sentry;
|
|
5
6
|
}
|
|
7
|
+
/** A reporter over an SDK the host initialized itself; it should pass `scrub.ts`'s hooks. */
|
|
8
|
+
static fromClient(sentry) {
|
|
9
|
+
return new SentryErrorReporter(sentry);
|
|
10
|
+
}
|
|
6
11
|
/**
|
|
7
|
-
* Initialize
|
|
8
|
-
* won't load. Never throws — a broken error-tracker must not take down boot.
|
|
12
|
+
* Initialize `@sentry/node` with the scrubbing hooks and return a reporter, or `null` when
|
|
13
|
+
* it won't load. Never throws — a broken error-tracker must not take down boot.
|
|
9
14
|
*/
|
|
10
15
|
static async create(opts) {
|
|
11
16
|
try {
|
|
@@ -20,9 +25,14 @@ export class SentryErrorReporter {
|
|
|
20
25
|
dsn: opts.dsn,
|
|
21
26
|
environment: opts.environment,
|
|
22
27
|
release: opts.release,
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
28
|
+
tracesSampleRate: typeof opts.tracesSampleRate === 'number'
|
|
29
|
+
? sampleRate(String(opts.tracesSampleRate))
|
|
30
|
+
: sampleRate(opts.tracesSampleRate),
|
|
31
|
+
// Streamed spans skip beforeSendTransaction, so the scrubber would never see them.
|
|
32
|
+
traceLifecycle: 'static',
|
|
33
|
+
beforeSend: scrubEvent,
|
|
34
|
+
beforeSendTransaction: scrubEvent,
|
|
35
|
+
beforeBreadcrumb: scrubBreadcrumb
|
|
26
36
|
});
|
|
27
37
|
return new SentryErrorReporter(sentry);
|
|
28
38
|
}
|
|
@@ -41,9 +51,14 @@ export class SentryErrorReporter {
|
|
|
41
51
|
tags.route = context.route;
|
|
42
52
|
if (context?.orgId)
|
|
43
53
|
tags.orgId = context.orgId;
|
|
54
|
+
if (context?.kind)
|
|
55
|
+
tags.kind = context.kind;
|
|
44
56
|
this.sentry.captureException(error, {
|
|
45
57
|
tags,
|
|
46
|
-
user: context?.userId ? { id: context.userId } : undefined
|
|
58
|
+
user: context?.userId ? { id: context.userId } : undefined,
|
|
59
|
+
...(context?.level && { level: context.level }),
|
|
60
|
+
// One issue per fault kind, split as Sentry would split it by stack.
|
|
61
|
+
...(context?.kind && { fingerprint: ['{{ default }}', context.kind] })
|
|
47
62
|
});
|
|
48
63
|
}
|
|
49
64
|
catch (err) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"SentryErrorReporter.js","sourceRoot":"","sources":["../../src/errors/SentryErrorReporter.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"SentryErrorReporter.js","sourceRoot":"","sources":["../../src/errors/SentryErrorReporter.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,UAAU,EAAE,eAAe,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAmCrE,MAAM,OAAO,mBAAmB;IACM;IAArC,YAAqC,MAAkB;QAAlB,WAAM,GAAN,MAAM,CAAY;IAAG,CAAC;IAE3D,6FAA6F;IAC7F,MAAM,CAAC,UAAU,CAAC,MAAkB;QACnC,OAAO,IAAI,mBAAmB,CAAC,MAAM,CAAC,CAAC;IACxC,CAAC;IAED;;;OAGG;IACH,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,IAMnB;QACA,IAAI,CAAC;YACJ,wEAAwE;YACxE,uEAAuE;YACvE,oEAAoE;YACpE,kEAAkE;YAClE,6DAA6D;YAC7D,sEAAsE;YACtE,MAAM,MAAM,GAAG,CAAC,MAAM,MAAM,CAAC,kBAAkB,CAAC,cAAc,CAAC,CAA8B,CAAC;YAC9F,MAAM,CAAC,IAAI,CAAC;gBACX,GAAG,EAAE,IAAI,CAAC,GAAG;gBACb,WAAW,EAAE,IAAI,CAAC,WAAW;gBAC7B,OAAO,EAAE,IAAI,CAAC,OAAO;gBACrB,gBAAgB,EACf,OAAO,IAAI,CAAC,gBAAgB,KAAK,QAAQ;oBACxC,CAAC,CAAC,UAAU,CAAC,MAAM,CAAC,IAAI,CAAC,gBAAgB,CAAC,CAAC;oBAC3C,CAAC,CAAC,UAAU,CAAC,IAAI,CAAC,gBAAgB,CAAC;gBACrC,mFAAmF;gBACnF,cAAc,EAAE,QAAQ;gBACxB,UAAU,EAAE,UAAU;gBACtB,qBAAqB,EAAE,UAAU;gBACjC,gBAAgB,EAAE,eAAe;aACjC,CAAC,CAAC;YACH,OAAO,IAAI,mBAAmB,CAAC,MAAM,CAAC,CAAC;QACxC,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACd,OAAO,CAAC,KAAK,CACZ,4EAA4E;gBAC3E,+EAA+E,EAChF,GAAG,CACH,CAAC;YACF,OAAO,IAAI,CAAC;QACb,CAAC;IACF,CAAC;IAED,OAAO,CAAC,KAAc,EAAE,OAAsB;QAC7C,IAAI,CAAC;YACJ,MAAM,IAAI,GAA2B,EAAE,GAAG,OAAO,EAAE,IAAI,EAAE,CAAC;YAC1D,IAAI,OAAO,EAAE,MAAM;gBAAE,IAAI,CAAC,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;YAClD,IAAI,OAAO,EAAE,KAAK;gBAAE,IAAI,CAAC,KAAK,GAAG,OAAO,CAAC,KAAK,CAAC;YAC/C,IAAI,OAAO,EAAE,KAAK;gBAAE,IAAI,CAAC,KAAK,GAAG,OAAO,CAAC,KAAK,CAAC;YAC/C,IAAI,OAAO,EAAE,IAAI;gBAAE,IAAI,CAAC,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC;YAC5C,IAAI,CAAC,MAAM,CAAC,gBAAgB,CAAC,KAAK,EAAE;gBACnC,IAAI;gBACJ,IAAI,EAAE,OAAO,EAAE,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,EAAE,OAAO,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC,SAAS;gBAC1D,GAAG,CAAC,OAAO,EAAE,KAAK,IAAI,EAAE,KAAK,EAAE,OAAO,CAAC,KAAK,EAAE,CAAC;gBAC/C,qEAAqE;gBACrE,GAAG,CAAC,OAAO,EAAE,IAAI,IAAI,EAAE,WAAW,EAAE,CAAC,eAAe,EAAE,OAAO,CAAC,IAAI,CAAC,EAAE,CAAC;aACtE,CAAC,CAAC;QACJ,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACd,kEAAkE;YAClE,uCAAuC;YACvC,OAAO,CAAC,KAAK,CAAC,0CAA0C,EAAE,GAAG,CAAC,CAAC;QAChE,CAAC;IACF,CAAC;CACD"}
|
package/dist/errors/index.d.ts
CHANGED
|
@@ -1,2 +1,3 @@
|
|
|
1
|
-
export { SentryErrorReporter } from './SentryErrorReporter.js';
|
|
1
|
+
export { SentryErrorReporter, type SentryLike } from './SentryErrorReporter.js';
|
|
2
|
+
export { sampleRate, scrubBreadcrumb, scrubEvent, withoutQuery, type ScrubbableBreadcrumb, type ScrubbableEvent } from './scrub.js';
|
|
2
3
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/errors/index.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/errors/index.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,mBAAmB,EAAE,KAAK,UAAU,EAAE,MAAM,0BAA0B,CAAC;AAChF,OAAO,EACN,UAAU,EACV,eAAe,EACf,UAAU,EACV,YAAY,EACZ,KAAK,oBAAoB,EACzB,KAAK,eAAe,EACpB,MAAM,YAAY,CAAC"}
|
package/dist/errors/index.js
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
-
// Error reporting
|
|
1
|
+
// Error reporting: the Sentry-backed IErrorReporter (optional @sentry/node peer) and the
|
|
2
|
+
// scrubbing hooks any Sentry SDK takes, server or browser.
|
|
2
3
|
export { SentryErrorReporter } from './SentryErrorReporter.js';
|
|
4
|
+
export { sampleRate, scrubBreadcrumb, scrubEvent, withoutQuery } from './scrub.js';
|
|
3
5
|
//# sourceMappingURL=index.js.map
|
package/dist/errors/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/errors/index.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/errors/index.ts"],"names":[],"mappings":"AAAA,yFAAyF;AACzF,2DAA2D;AAE3D,OAAO,EAAE,mBAAmB,EAAmB,MAAM,0BAA0B,CAAC;AAChF,OAAO,EACN,UAAU,EACV,eAAe,EACf,UAAU,EACV,YAAY,EAGZ,MAAM,YAAY,CAAC"}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* What an error tracker may receive: identifiers, never payloads. Applied to Sentry-shaped
|
|
3
|
+
* events (`beforeSend`, `beforeSendTransaction`, `beforeBreadcrumb`) without importing Sentry,
|
|
4
|
+
* so a host wires them into whichever SDK it runs, server or browser.
|
|
5
|
+
*
|
|
6
|
+
* No cookie, auth header, API key, request body or query string leaves: a query carries share
|
|
7
|
+
* tokens and search text, a body definitions and inputs. A user is its id. Console breadcrumbs
|
|
8
|
+
* stay local, since they can quote any of the above.
|
|
9
|
+
*/
|
|
10
|
+
/** The parts of a Sentry event these read. Structural, so any SDK version's events fit. */
|
|
11
|
+
export interface ScrubbableEvent {
|
|
12
|
+
request?: {
|
|
13
|
+
url?: string;
|
|
14
|
+
cookies?: unknown;
|
|
15
|
+
data?: unknown;
|
|
16
|
+
query_string?: unknown;
|
|
17
|
+
headers?: Record<string, string>;
|
|
18
|
+
};
|
|
19
|
+
user?: {
|
|
20
|
+
id?: string | number;
|
|
21
|
+
} & Record<string, unknown>;
|
|
22
|
+
breadcrumbs?: ScrubbableBreadcrumb[];
|
|
23
|
+
transaction?: string;
|
|
24
|
+
spans?: {
|
|
25
|
+
description?: string;
|
|
26
|
+
data?: Record<string, unknown>;
|
|
27
|
+
}[];
|
|
28
|
+
}
|
|
29
|
+
export interface ScrubbableBreadcrumb {
|
|
30
|
+
category?: string;
|
|
31
|
+
data?: Record<string, unknown>;
|
|
32
|
+
}
|
|
33
|
+
/** `https://h/p?q=1#f` → `https://h/p`; a relative path likewise. Anything else as it was. */
|
|
34
|
+
export declare function withoutQuery(url: string): string;
|
|
35
|
+
export declare function scrubBreadcrumb<B extends ScrubbableBreadcrumb>(crumb: B): B | null;
|
|
36
|
+
/** For `beforeSend` and `beforeSendTransaction` alike. Mutates and returns `event`. */
|
|
37
|
+
export declare function scrubEvent<E extends ScrubbableEvent>(event: E): E;
|
|
38
|
+
/** A sample-rate env value → 0–1; unset or unreadable is 0, out of range clamped. */
|
|
39
|
+
export declare function sampleRate(raw: string | undefined): number;
|
|
40
|
+
//# sourceMappingURL=scrub.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"scrub.d.ts","sourceRoot":"","sources":["../../src/errors/scrub.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,2FAA2F;AAC3F,MAAM,WAAW,eAAe;IAC/B,OAAO,CAAC,EAAE;QACT,GAAG,CAAC,EAAE,MAAM,CAAC;QACb,OAAO,CAAC,EAAE,OAAO,CAAC;QAClB,IAAI,CAAC,EAAE,OAAO,CAAC;QACf,YAAY,CAAC,EAAE,OAAO,CAAC;QACvB,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;KACjC,CAAC;IACF,IAAI,CAAC,EAAE;QAAE,EAAE,CAAC,EAAE,MAAM,GAAG,MAAM,CAAA;KAAE,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAC1D,WAAW,CAAC,EAAE,oBAAoB,EAAE,CAAC;IACrC,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,KAAK,CAAC,EAAE;QAAE,WAAW,CAAC,EAAE,MAAM,CAAC;QAAC,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;KAAE,EAAE,CAAC;CACnE;AAED,MAAM,WAAW,oBAAoB;IACpC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CAC/B;AAMD,8FAA8F;AAC9F,wBAAgB,YAAY,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAGhD;AAYD,wBAAgB,eAAe,CAAC,CAAC,SAAS,oBAAoB,EAAE,KAAK,EAAE,CAAC,GAAG,CAAC,GAAG,IAAI,CAIlF;AAED,uFAAuF;AACvF,wBAAgB,UAAU,CAAC,CAAC,SAAS,eAAe,EAAE,KAAK,EAAE,CAAC,GAAG,CAAC,CAuBjE;AAED,qFAAqF;AACrF,wBAAgB,UAAU,CAAC,GAAG,EAAE,MAAM,GAAG,SAAS,GAAG,MAAM,CAG1D"}
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* What an error tracker may receive: identifiers, never payloads. Applied to Sentry-shaped
|
|
3
|
+
* events (`beforeSend`, `beforeSendTransaction`, `beforeBreadcrumb`) without importing Sentry,
|
|
4
|
+
* so a host wires them into whichever SDK it runs, server or browser.
|
|
5
|
+
*
|
|
6
|
+
* No cookie, auth header, API key, request body or query string leaves: a query carries share
|
|
7
|
+
* tokens and search text, a body definitions and inputs. A user is its id. Console breadcrumbs
|
|
8
|
+
* stay local, since they can quote any of the above.
|
|
9
|
+
*/
|
|
10
|
+
// Headers that say what the request was, never who sent it.
|
|
11
|
+
const KEPT_HEADERS = new Set(['accept', 'content-type', 'content-length', 'user-agent']);
|
|
12
|
+
const URL_KEYS = ['url', 'to', 'from', 'http.url', 'server.address.full'];
|
|
13
|
+
/** `https://h/p?q=1#f` → `https://h/p`; a relative path likewise. Anything else as it was. */
|
|
14
|
+
export function withoutQuery(url) {
|
|
15
|
+
const cut = url.search(/[?#]/);
|
|
16
|
+
return cut === -1 ? url : url.slice(0, cut);
|
|
17
|
+
}
|
|
18
|
+
function scrubData(data) {
|
|
19
|
+
if (!data)
|
|
20
|
+
return;
|
|
21
|
+
for (const key of URL_KEYS) {
|
|
22
|
+
const value = data[key];
|
|
23
|
+
if (typeof value === 'string')
|
|
24
|
+
data[key] = withoutQuery(value);
|
|
25
|
+
}
|
|
26
|
+
delete data['http.query'];
|
|
27
|
+
delete data['http.fragment'];
|
|
28
|
+
}
|
|
29
|
+
export function scrubBreadcrumb(crumb) {
|
|
30
|
+
if (crumb.category === 'console')
|
|
31
|
+
return null;
|
|
32
|
+
scrubData(crumb.data);
|
|
33
|
+
return crumb;
|
|
34
|
+
}
|
|
35
|
+
/** For `beforeSend` and `beforeSendTransaction` alike. Mutates and returns `event`. */
|
|
36
|
+
export function scrubEvent(event) {
|
|
37
|
+
const request = event.request;
|
|
38
|
+
if (request) {
|
|
39
|
+
delete request.cookies;
|
|
40
|
+
delete request.data;
|
|
41
|
+
delete request.query_string;
|
|
42
|
+
if (request.url)
|
|
43
|
+
request.url = withoutQuery(request.url);
|
|
44
|
+
if (request.headers) {
|
|
45
|
+
request.headers = Object.fromEntries(Object.entries(request.headers).filter(([k]) => KEPT_HEADERS.has(k.toLowerCase())));
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
if (event.user)
|
|
49
|
+
event.user = event.user.id === undefined ? {} : { id: event.user.id };
|
|
50
|
+
if (event.breadcrumbs) {
|
|
51
|
+
event.breadcrumbs = event.breadcrumbs.flatMap((b) => scrubBreadcrumb(b) ?? []);
|
|
52
|
+
}
|
|
53
|
+
for (const span of event.spans ?? []) {
|
|
54
|
+
if (span.description)
|
|
55
|
+
span.description = withoutQuery(span.description);
|
|
56
|
+
scrubData(span.data);
|
|
57
|
+
}
|
|
58
|
+
if (event.transaction)
|
|
59
|
+
event.transaction = withoutQuery(event.transaction);
|
|
60
|
+
return event;
|
|
61
|
+
}
|
|
62
|
+
/** A sample-rate env value → 0–1; unset or unreadable is 0, out of range clamped. */
|
|
63
|
+
export function sampleRate(raw) {
|
|
64
|
+
const rate = Number(raw);
|
|
65
|
+
return raw !== undefined && Number.isFinite(rate) ? Math.min(1, Math.max(0, rate)) : 0;
|
|
66
|
+
}
|
|
67
|
+
//# sourceMappingURL=scrub.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"scrub.js","sourceRoot":"","sources":["../../src/errors/scrub.ts"],"names":[],"mappings":"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"}
|
package/dist/http/index.d.ts
CHANGED
|
@@ -11,4 +11,5 @@ export { createSessionRefresher, type SessionRefresher } from './session-refresh
|
|
|
11
11
|
export { createSessionResolver, type SessionResolver, type SessionResolverConfig } from './session-resolver.js';
|
|
12
12
|
export { createApiTokenResolutionCache, createHolderVerdictCache, resolveApiToken, type ApiTokenResolution, type ApiTokenResolutionCache, type HolderVerdictCache, type ResolveApiTokenDeps, type ResolveApiTokenOptions } from './api-token.js';
|
|
13
13
|
export { createRequestMemo, type RequestMemo } from './request-memo.js';
|
|
14
|
+
export { createRequestTiming, parseServerTimingHeader, type RequestTiming, type RequestTimingOptions, type TimedRequest, type Upstream } from './request-timing.js';
|
|
14
15
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/http/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/http/index.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,kBAAkB,EAAE,MAAM,eAAe,CAAC;AACnD,OAAO,EAAE,yBAAyB,EAAE,KAAK,WAAW,EAAE,MAAM,WAAW,CAAC;AACxE,OAAO,EAAE,uBAAuB,EAAE,KAAK,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAC3E,OAAO,EAAE,oBAAoB,EAAE,KAAK,qBAAqB,EAAE,MAAM,uBAAuB,CAAC;AACzF,OAAO,EACN,qBAAqB,EACrB,KAAK,eAAe,EACpB,KAAK,qBAAqB,EAC1B,MAAM,uBAAuB,CAAC;AAC/B,OAAO,EACN,sBAAsB,EACtB,oBAAoB,EACpB,KAAK,gBAAgB,EACrB,KAAK,sBAAsB,EAC3B,MAAM,uBAAuB,CAAC;AAC/B,OAAO,EAAE,qBAAqB,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC;AACxE,OAAO,EAAE,mBAAmB,EAAE,KAAK,wBAAwB,EAAE,MAAM,sBAAsB,CAAC;AAC1F,OAAO,EACN,qBAAqB,EACrB,KAAK,eAAe,EACpB,KAAK,qBAAqB,EAC1B,MAAM,wBAAwB,CAAC;AAChC,OAAO,EAAE,sBAAsB,EAAE,KAAK,gBAAgB,EAAE,MAAM,wBAAwB,CAAC;AACvF,OAAO,EACN,qBAAqB,EACrB,KAAK,eAAe,EACpB,KAAK,qBAAqB,EAC1B,MAAM,uBAAuB,CAAC;AAC/B,OAAO,EACN,6BAA6B,EAC7B,wBAAwB,EACxB,eAAe,EACf,KAAK,kBAAkB,EACvB,KAAK,uBAAuB,EAC5B,KAAK,kBAAkB,EACvB,KAAK,mBAAmB,EACxB,KAAK,sBAAsB,EAC3B,MAAM,gBAAgB,CAAC;AACxB,OAAO,EAAE,iBAAiB,EAAE,KAAK,WAAW,EAAE,MAAM,mBAAmB,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/http/index.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,kBAAkB,EAAE,MAAM,eAAe,CAAC;AACnD,OAAO,EAAE,yBAAyB,EAAE,KAAK,WAAW,EAAE,MAAM,WAAW,CAAC;AACxE,OAAO,EAAE,uBAAuB,EAAE,KAAK,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAC3E,OAAO,EAAE,oBAAoB,EAAE,KAAK,qBAAqB,EAAE,MAAM,uBAAuB,CAAC;AACzF,OAAO,EACN,qBAAqB,EACrB,KAAK,eAAe,EACpB,KAAK,qBAAqB,EAC1B,MAAM,uBAAuB,CAAC;AAC/B,OAAO,EACN,sBAAsB,EACtB,oBAAoB,EACpB,KAAK,gBAAgB,EACrB,KAAK,sBAAsB,EAC3B,MAAM,uBAAuB,CAAC;AAC/B,OAAO,EAAE,qBAAqB,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC;AACxE,OAAO,EAAE,mBAAmB,EAAE,KAAK,wBAAwB,EAAE,MAAM,sBAAsB,CAAC;AAC1F,OAAO,EACN,qBAAqB,EACrB,KAAK,eAAe,EACpB,KAAK,qBAAqB,EAC1B,MAAM,wBAAwB,CAAC;AAChC,OAAO,EAAE,sBAAsB,EAAE,KAAK,gBAAgB,EAAE,MAAM,wBAAwB,CAAC;AACvF,OAAO,EACN,qBAAqB,EACrB,KAAK,eAAe,EACpB,KAAK,qBAAqB,EAC1B,MAAM,uBAAuB,CAAC;AAC/B,OAAO,EACN,6BAA6B,EAC7B,wBAAwB,EACxB,eAAe,EACf,KAAK,kBAAkB,EACvB,KAAK,uBAAuB,EAC5B,KAAK,kBAAkB,EACvB,KAAK,mBAAmB,EACxB,KAAK,sBAAsB,EAC3B,MAAM,gBAAgB,CAAC;AACxB,OAAO,EAAE,iBAAiB,EAAE,KAAK,WAAW,EAAE,MAAM,mBAAmB,CAAC;AACxE,OAAO,EACN,mBAAmB,EACnB,uBAAuB,EACvB,KAAK,aAAa,EAClB,KAAK,oBAAoB,EACzB,KAAK,YAAY,EACjB,KAAK,QAAQ,EACb,MAAM,qBAAqB,CAAC"}
|
package/dist/http/index.js
CHANGED
|
@@ -12,4 +12,5 @@ export { createSessionRefresher } from './session-refresher.js';
|
|
|
12
12
|
export { createSessionResolver } from './session-resolver.js';
|
|
13
13
|
export { createApiTokenResolutionCache, createHolderVerdictCache, resolveApiToken } from './api-token.js';
|
|
14
14
|
export { createRequestMemo } from './request-memo.js';
|
|
15
|
+
export { createRequestTiming, parseServerTimingHeader } from './request-timing.js';
|
|
15
16
|
//# sourceMappingURL=index.js.map
|
package/dist/http/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/http/index.ts"],"names":[],"mappings":"AAAA,uEAAuE;AAEvE,OAAO,EAAE,kBAAkB,EAAE,MAAM,eAAe,CAAC;AACnD,OAAO,EAAE,yBAAyB,EAAoB,MAAM,WAAW,CAAC;AACxE,OAAO,EAAE,uBAAuB,EAAoB,MAAM,gBAAgB,CAAC;AAC3E,OAAO,EAAE,oBAAoB,EAA8B,MAAM,uBAAuB,CAAC;AACzF,OAAO,EACN,qBAAqB,EAGrB,MAAM,uBAAuB,CAAC;AAC/B,OAAO,EACN,sBAAsB,EACtB,oBAAoB,EAGpB,MAAM,uBAAuB,CAAC;AAC/B,OAAO,EAAE,qBAAqB,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC;AACxE,OAAO,EAAE,mBAAmB,EAAiC,MAAM,sBAAsB,CAAC;AAC1F,OAAO,EACN,qBAAqB,EAGrB,MAAM,wBAAwB,CAAC;AAChC,OAAO,EAAE,sBAAsB,EAAyB,MAAM,wBAAwB,CAAC;AACvF,OAAO,EACN,qBAAqB,EAGrB,MAAM,uBAAuB,CAAC;AAC/B,OAAO,EACN,6BAA6B,EAC7B,wBAAwB,EACxB,eAAe,EAMf,MAAM,gBAAgB,CAAC;AACxB,OAAO,EAAE,iBAAiB,EAAoB,MAAM,mBAAmB,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/http/index.ts"],"names":[],"mappings":"AAAA,uEAAuE;AAEvE,OAAO,EAAE,kBAAkB,EAAE,MAAM,eAAe,CAAC;AACnD,OAAO,EAAE,yBAAyB,EAAoB,MAAM,WAAW,CAAC;AACxE,OAAO,EAAE,uBAAuB,EAAoB,MAAM,gBAAgB,CAAC;AAC3E,OAAO,EAAE,oBAAoB,EAA8B,MAAM,uBAAuB,CAAC;AACzF,OAAO,EACN,qBAAqB,EAGrB,MAAM,uBAAuB,CAAC;AAC/B,OAAO,EACN,sBAAsB,EACtB,oBAAoB,EAGpB,MAAM,uBAAuB,CAAC;AAC/B,OAAO,EAAE,qBAAqB,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC;AACxE,OAAO,EAAE,mBAAmB,EAAiC,MAAM,sBAAsB,CAAC;AAC1F,OAAO,EACN,qBAAqB,EAGrB,MAAM,wBAAwB,CAAC;AAChC,OAAO,EAAE,sBAAsB,EAAyB,MAAM,wBAAwB,CAAC;AACvF,OAAO,EACN,qBAAqB,EAGrB,MAAM,uBAAuB,CAAC;AAC/B,OAAO,EACN,6BAA6B,EAC7B,wBAAwB,EACxB,eAAe,EAMf,MAAM,gBAAgB,CAAC;AACxB,OAAO,EAAE,iBAAiB,EAAoB,MAAM,mBAAmB,CAAC;AACxE,OAAO,EACN,mBAAmB,EACnB,uBAAuB,EAKvB,MAAM,qBAAqB,CAAC"}
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Per-request timing: where a request's wall time went, as named spans plus every outbound
|
|
3
|
+
* fetch grouped by upstream. One AsyncLocalStorage store per request, opened by `timeRequest`
|
|
4
|
+
* in the host's handle hook. The result goes out twice: a `Server-Timing` header on the
|
|
5
|
+
* response, and one structured record through `log` for a request that is slow, sampled, or the
|
|
6
|
+
* first the process served.
|
|
7
|
+
*
|
|
8
|
+
* Fetch time is time to response headers, not body: round-trip latency, which a chain of
|
|
9
|
+
* sequential awaits multiplies. Parallel fetches overlap, so a bucket's `ms` is a sum and can
|
|
10
|
+
* exceed the request's wall time.
|
|
11
|
+
*/
|
|
12
|
+
/** Which upstream a fetch reached, and optionally the table or endpoint within it. */
|
|
13
|
+
export interface Upstream {
|
|
14
|
+
key: string;
|
|
15
|
+
target?: string;
|
|
16
|
+
}
|
|
17
|
+
export interface TimedRequest {
|
|
18
|
+
method: string;
|
|
19
|
+
/** The route id (`/s/[token]`), so records aggregate across ids; the path when unrouted. */
|
|
20
|
+
route: string;
|
|
21
|
+
isDataRequest?: boolean;
|
|
22
|
+
}
|
|
23
|
+
export interface RequestTimingOptions {
|
|
24
|
+
/** Writes one record. Fields are typed JSON; never put payload values in them. */
|
|
25
|
+
log: (message: string, fields: Record<string, unknown>) => void;
|
|
26
|
+
/** Names the upstream of a fetch; unnamed ones bucket by host. */
|
|
27
|
+
upstream?: (url: URL) => Upstream | undefined;
|
|
28
|
+
/** A request at or over this is logged. Default 200 ms. */
|
|
29
|
+
slowMs?: number;
|
|
30
|
+
/**
|
|
31
|
+
* This share of requests is logged whatever its time, marked `sampled`: slow-only records
|
|
32
|
+
* lean toward whatever got slower, the sampled ones compare across a change. Default 0.1.
|
|
33
|
+
*/
|
|
34
|
+
sampleRate?: number;
|
|
35
|
+
/** Stamped on every record, e.g. the revision; `instance` is added per process. */
|
|
36
|
+
labels?: Record<string, string>;
|
|
37
|
+
}
|
|
38
|
+
export interface RequestTiming {
|
|
39
|
+
/**
|
|
40
|
+
* Runs one request inside a timing store, stamps `Server-Timing` on its response and logs it
|
|
41
|
+
* when due. A throw (a framework redirect included) is logged and rethrown.
|
|
42
|
+
*/
|
|
43
|
+
timeRequest(req: TimedRequest, fn: () => Promise<Response>): Promise<Response>;
|
|
44
|
+
/** Times `fn` as a named span of the current request; outside a request it just runs. */
|
|
45
|
+
span<T>(name: string, fn: () => Promise<T> | T): Promise<T>;
|
|
46
|
+
/** Attaches facts to the current request's record; a no-op outside a request. */
|
|
47
|
+
fact(facts: Record<string, unknown>): void;
|
|
48
|
+
/** Whether the current request is the first this process served. */
|
|
49
|
+
isCold(): boolean;
|
|
50
|
+
/** Called once the server can take requests: the cold-start record's `bootMs`. */
|
|
51
|
+
markBooted(): void;
|
|
52
|
+
/** Wraps the global `fetch` once; clients that look it up at call time are then timed. */
|
|
53
|
+
instrumentFetch(): void;
|
|
54
|
+
}
|
|
55
|
+
/** Parses a `Server-Timing` value into `{ name: ms }`, a desc-only entry into `{ name: desc }`. */
|
|
56
|
+
export declare function parseServerTimingHeader(header: string | null | undefined): Record<string, number | string>;
|
|
57
|
+
export declare function createRequestTiming(options: RequestTimingOptions): RequestTiming;
|
|
58
|
+
//# sourceMappingURL=request-timing.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"request-timing.d.ts","sourceRoot":"","sources":["../../src/http/request-timing.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAKH,sFAAsF;AACtF,MAAM,WAAW,QAAQ;IACxB,GAAG,EAAE,MAAM,CAAC;IACZ,MAAM,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,YAAY;IAC5B,MAAM,EAAE,MAAM,CAAC;IACf,4FAA4F;IAC5F,KAAK,EAAE,MAAM,CAAC;IACd,aAAa,CAAC,EAAE,OAAO,CAAC;CACxB;AAED,MAAM,WAAW,oBAAoB;IACpC,kFAAkF;IAClF,GAAG,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,IAAI,CAAC;IAChE,kEAAkE;IAClE,QAAQ,CAAC,EAAE,CAAC,GAAG,EAAE,GAAG,KAAK,QAAQ,GAAG,SAAS,CAAC;IAC9C,2DAA2D;IAC3D,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB;;;OAGG;IACH,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,mFAAmF;IACnF,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CAChC;AAED,MAAM,WAAW,aAAa;IAC7B;;;OAGG;IACH,WAAW,CAAC,GAAG,EAAE,YAAY,EAAE,EAAE,EAAE,MAAM,OAAO,CAAC,QAAQ,CAAC,GAAG,OAAO,CAAC,QAAQ,CAAC,CAAC;IAC/E,yFAAyF;IACzF,IAAI,CAAC,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC,GAAG,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,CAAC;IAC5D,iFAAiF;IACjF,IAAI,CAAC,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAAC;IAC3C,oEAAoE;IACpE,MAAM,IAAI,OAAO,CAAC;IAClB,kFAAkF;IAClF,UAAU,IAAI,IAAI,CAAC;IACnB,0FAA0F;IAC1F,eAAe,IAAI,IAAI,CAAC;CACxB;AAuCD,mGAAmG;AACnG,wBAAgB,uBAAuB,CACtC,MAAM,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,GAC/B,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAAC,CAYjC;AAED,wBAAgB,mBAAmB,CAAC,OAAO,EAAE,oBAAoB,GAAG,aAAa,CA2KhF"}
|
|
@@ -0,0 +1,219 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Per-request timing: where a request's wall time went, as named spans plus every outbound
|
|
3
|
+
* fetch grouped by upstream. One AsyncLocalStorage store per request, opened by `timeRequest`
|
|
4
|
+
* in the host's handle hook. The result goes out twice: a `Server-Timing` header on the
|
|
5
|
+
* response, and one structured record through `log` for a request that is slow, sampled, or the
|
|
6
|
+
* first the process served.
|
|
7
|
+
*
|
|
8
|
+
* Fetch time is time to response headers, not body: round-trip latency, which a chain of
|
|
9
|
+
* sequential awaits multiplies. Parallel fetches overlap, so a bucket's `ms` is a sum and can
|
|
10
|
+
* exceed the request's wall time.
|
|
11
|
+
*/
|
|
12
|
+
import { AsyncLocalStorage } from 'node:async_hooks';
|
|
13
|
+
import { randomUUID } from 'node:crypto';
|
|
14
|
+
const round = (ms) => Math.round(ms);
|
|
15
|
+
function median(values) {
|
|
16
|
+
const sorted = [...values].sort((a, b) => a - b);
|
|
17
|
+
const mid = sorted.length >> 1;
|
|
18
|
+
return sorted.length % 2 ? sorted[mid] : (sorted[mid - 1] + sorted[mid]) / 2;
|
|
19
|
+
}
|
|
20
|
+
function urlOf(input) {
|
|
21
|
+
try {
|
|
22
|
+
return new URL(input instanceof Request ? input.url : String(input));
|
|
23
|
+
}
|
|
24
|
+
catch {
|
|
25
|
+
return undefined;
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
function isRetry(init) {
|
|
29
|
+
const headers = init?.headers;
|
|
30
|
+
if (!headers)
|
|
31
|
+
return false;
|
|
32
|
+
if (headers instanceof Headers)
|
|
33
|
+
return headers.has('x-retry-count');
|
|
34
|
+
if (Array.isArray(headers))
|
|
35
|
+
return headers.some(([k]) => k.toLowerCase() === 'x-retry-count');
|
|
36
|
+
return Object.keys(headers).some((k) => k.toLowerCase() === 'x-retry-count');
|
|
37
|
+
}
|
|
38
|
+
/** Parses a `Server-Timing` value into `{ name: ms }`, a desc-only entry into `{ name: desc }`. */
|
|
39
|
+
export function parseServerTimingHeader(header) {
|
|
40
|
+
const out = {};
|
|
41
|
+
for (const entry of header?.split(',') ?? []) {
|
|
42
|
+
const [name, ...params] = entry.trim().split(';');
|
|
43
|
+
if (!name)
|
|
44
|
+
continue;
|
|
45
|
+
for (const p of params) {
|
|
46
|
+
const [k, v = ''] = p.trim().split('=');
|
|
47
|
+
if (k === 'dur')
|
|
48
|
+
out[name] = round(Number(v));
|
|
49
|
+
else if (k === 'desc' && !(name in out))
|
|
50
|
+
out[name] = v.replace(/^"|"$/g, '');
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
return out;
|
|
54
|
+
}
|
|
55
|
+
export function createRequestTiming(options) {
|
|
56
|
+
const slowMs = options.slowMs ?? 200;
|
|
57
|
+
const sampleRate = options.sampleRate ?? 0.1;
|
|
58
|
+
const labels = { instance: randomUUID().slice(0, 8), ...options.labels };
|
|
59
|
+
const als = new AsyncLocalStorage();
|
|
60
|
+
let bootMs = null;
|
|
61
|
+
let served = false;
|
|
62
|
+
let installed = false;
|
|
63
|
+
const log = (message, fields) => {
|
|
64
|
+
try {
|
|
65
|
+
options.log(message, { ...labels, ...fields });
|
|
66
|
+
}
|
|
67
|
+
catch {
|
|
68
|
+
// Telemetry never fails a request.
|
|
69
|
+
}
|
|
70
|
+
};
|
|
71
|
+
function upstreamOf(url) {
|
|
72
|
+
if (!url)
|
|
73
|
+
return { key: 'other' };
|
|
74
|
+
return options.upstream?.(url) ?? { key: url.host };
|
|
75
|
+
}
|
|
76
|
+
/** An upstream that times itself (`Server-Timing`) lands on the record by path. */
|
|
77
|
+
function recordUpstreamTiming(store, url, response) {
|
|
78
|
+
const timing = response.headers.get('server-timing');
|
|
79
|
+
if (!timing || !url)
|
|
80
|
+
return;
|
|
81
|
+
const byPath = store.facts.upstreamTiming ?? {};
|
|
82
|
+
byPath[url.pathname] = parseServerTimingHeader(timing);
|
|
83
|
+
store.facts.upstreamTiming = byPath;
|
|
84
|
+
}
|
|
85
|
+
function serverTiming(store, totalMs) {
|
|
86
|
+
const parts = store.spans.map((s) => `app_${s.name.replace(/[^\w-]/g, '_')};dur=${s.ms.toFixed(1)}`);
|
|
87
|
+
for (const [key, b] of store.upstream) {
|
|
88
|
+
parts.push(`up;desc="${key} x${b.count}";dur=${b.ms.toFixed(1)}`);
|
|
89
|
+
}
|
|
90
|
+
if (store.retries > 0)
|
|
91
|
+
parts.push(`retries;desc="${store.retries}"`);
|
|
92
|
+
parts.push(`app_total;dur=${totalMs.toFixed(1)}`);
|
|
93
|
+
return parts.join(', ');
|
|
94
|
+
}
|
|
95
|
+
function logTiming(req, status, totalMs, store, sampled) {
|
|
96
|
+
const upstream = Object.fromEntries([...store.upstream].map(([k, b]) => [
|
|
97
|
+
k,
|
|
98
|
+
{
|
|
99
|
+
count: b.count,
|
|
100
|
+
ms: round(b.ms),
|
|
101
|
+
p50: round(median(b.calls)),
|
|
102
|
+
max: round(Math.max(...b.calls))
|
|
103
|
+
}
|
|
104
|
+
]));
|
|
105
|
+
// A span name that ran more than once sums.
|
|
106
|
+
const spans = {};
|
|
107
|
+
for (const s of store.spans)
|
|
108
|
+
spans[s.name] = round((spans[s.name] ?? 0) + s.ms);
|
|
109
|
+
log(`[timing] ${req.method} ${req.route}${req.isDataRequest ? ' (data)' : ''} ${status} ${round(totalMs)}ms`, {
|
|
110
|
+
timing: {
|
|
111
|
+
route: req.route,
|
|
112
|
+
method: req.method,
|
|
113
|
+
data: req.isDataRequest ?? false,
|
|
114
|
+
status,
|
|
115
|
+
totalMs: round(totalMs),
|
|
116
|
+
...(store.cold && { cold: true }),
|
|
117
|
+
...(sampled && { sampled: true }),
|
|
118
|
+
spans,
|
|
119
|
+
upstream,
|
|
120
|
+
calls: Object.fromEntries(store.targets),
|
|
121
|
+
...(store.retries > 0 && { retries: store.retries }),
|
|
122
|
+
...store.facts
|
|
123
|
+
}
|
|
124
|
+
});
|
|
125
|
+
}
|
|
126
|
+
return {
|
|
127
|
+
async timeRequest(req, fn) {
|
|
128
|
+
const cold = !served;
|
|
129
|
+
served = true;
|
|
130
|
+
const store = {
|
|
131
|
+
spans: [],
|
|
132
|
+
upstream: new Map(),
|
|
133
|
+
targets: new Map(),
|
|
134
|
+
retries: 0,
|
|
135
|
+
facts: {},
|
|
136
|
+
cold
|
|
137
|
+
};
|
|
138
|
+
const start = performance.now();
|
|
139
|
+
if (cold) {
|
|
140
|
+
// Process start to `markBooted`, and to this request: their gap is idle time.
|
|
141
|
+
log(`[coldstart] ${req.method} ${req.route}`, {
|
|
142
|
+
coldstart: { bootMs, firstRequestMs: round(start), route: req.route }
|
|
143
|
+
});
|
|
144
|
+
}
|
|
145
|
+
let status = 'thrown';
|
|
146
|
+
try {
|
|
147
|
+
const response = await als.run(store, fn);
|
|
148
|
+
status = response.status;
|
|
149
|
+
try {
|
|
150
|
+
response.headers.append('Server-Timing', serverTiming(store, performance.now() - start));
|
|
151
|
+
}
|
|
152
|
+
catch {
|
|
153
|
+
// Immutable headers (a fetched Response passed through): the record still has it.
|
|
154
|
+
}
|
|
155
|
+
return response;
|
|
156
|
+
}
|
|
157
|
+
finally {
|
|
158
|
+
const totalMs = performance.now() - start;
|
|
159
|
+
const sampled = Math.random() < sampleRate;
|
|
160
|
+
// The cold request always: a comparison across a change must be able to drop it.
|
|
161
|
+
if (cold || sampled || totalMs >= slowMs)
|
|
162
|
+
logTiming(req, status, totalMs, store, sampled);
|
|
163
|
+
}
|
|
164
|
+
},
|
|
165
|
+
async span(name, fn) {
|
|
166
|
+
const store = als.getStore();
|
|
167
|
+
if (!store)
|
|
168
|
+
return fn();
|
|
169
|
+
const start = performance.now();
|
|
170
|
+
try {
|
|
171
|
+
return await fn();
|
|
172
|
+
}
|
|
173
|
+
finally {
|
|
174
|
+
store.spans.push({ name, ms: performance.now() - start });
|
|
175
|
+
}
|
|
176
|
+
},
|
|
177
|
+
fact(facts) {
|
|
178
|
+
const store = als.getStore();
|
|
179
|
+
if (store)
|
|
180
|
+
Object.assign(store.facts, facts);
|
|
181
|
+
},
|
|
182
|
+
isCold: () => als.getStore()?.cold ?? false,
|
|
183
|
+
markBooted() {
|
|
184
|
+
bootMs ??= round(performance.now());
|
|
185
|
+
},
|
|
186
|
+
instrumentFetch() {
|
|
187
|
+
if (installed)
|
|
188
|
+
return;
|
|
189
|
+
installed = true;
|
|
190
|
+
const original = globalThis.fetch;
|
|
191
|
+
globalThis.fetch = async (input, init) => {
|
|
192
|
+
const store = als.getStore();
|
|
193
|
+
if (!store)
|
|
194
|
+
return original(input, init);
|
|
195
|
+
const start = performance.now();
|
|
196
|
+
const url = urlOf(input);
|
|
197
|
+
const { key, target } = upstreamOf(url);
|
|
198
|
+
if (target)
|
|
199
|
+
store.targets.set(target, (store.targets.get(target) ?? 0) + 1);
|
|
200
|
+
if (isRetry(init))
|
|
201
|
+
store.retries += 1;
|
|
202
|
+
try {
|
|
203
|
+
const response = await original(input, init);
|
|
204
|
+
recordUpstreamTiming(store, url, response);
|
|
205
|
+
return response;
|
|
206
|
+
}
|
|
207
|
+
finally {
|
|
208
|
+
const bucket = store.upstream.get(key) ?? { count: 0, ms: 0, calls: [] };
|
|
209
|
+
const ms = performance.now() - start;
|
|
210
|
+
bucket.count += 1;
|
|
211
|
+
bucket.ms += ms;
|
|
212
|
+
bucket.calls.push(ms);
|
|
213
|
+
store.upstream.set(key, bucket);
|
|
214
|
+
}
|
|
215
|
+
};
|
|
216
|
+
}
|
|
217
|
+
};
|
|
218
|
+
}
|
|
219
|
+
//# sourceMappingURL=request-timing.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"request-timing.js","sourceRoot":"","sources":["../../src/http/request-timing.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@selvajs/server",
|
|
3
|
-
"version": "2.0.0-beta.
|
|
3
|
+
"version": "2.0.0-beta.24",
|
|
4
4
|
"description": "Transport-agnostic server building blocks for apps built on the Selva engine (limits, rate limiting, SSRF guard, remote-definition fetch, definition service + render loader); the solve core lives in @selvajs/solve/server",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": "VektorNode",
|
|
@@ -120,10 +120,10 @@
|
|
|
120
120
|
],
|
|
121
121
|
"dependencies": {
|
|
122
122
|
"zod": "^4.6.7",
|
|
123
|
+
"@selvajs/notifications": "^0.3.0-beta.11",
|
|
124
|
+
"@selvajs/platform": "^1.0.0-beta.11",
|
|
123
125
|
"@selvajs/compute": "^5.0.0-beta.9",
|
|
124
|
-
"@selvajs/
|
|
125
|
-
"@selvajs/schemas": "^5.3.0-beta.3",
|
|
126
|
-
"@selvajs/notifications": "^0.3.0-beta.10"
|
|
126
|
+
"@selvajs/schemas": "^5.3.0-beta.3"
|
|
127
127
|
},
|
|
128
128
|
"peerDependencies": {
|
|
129
129
|
"@sentry/node": ">=8",
|