traceperf 0.2.0 → 1.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +612 -209
- package/dist/__tests__/helpers/console.d.ts +9 -0
- package/dist/__tests__/helpers/console.js +25 -0
- package/dist/__tests__/helpers/console.js.map +1 -0
- package/dist/auto.d.ts +30 -0
- package/dist/auto.js +91 -0
- package/dist/auto.js.map +1 -0
- package/dist/browser.d.ts +52 -144
- package/dist/browser.js +112 -439
- package/dist/browser.js.map +1 -1
- package/dist/cli.d.ts +68 -0
- package/dist/cli.js +528 -0
- package/dist/cli.js.map +1 -0
- package/dist/core/allocations.d.ts +38 -0
- package/dist/core/allocations.js +85 -0
- package/dist/core/allocations.js.map +1 -0
- package/dist/core/cpu-profile.d.ts +84 -0
- package/dist/core/cpu-profile.js +181 -0
- package/dist/core/cpu-profile.js.map +1 -0
- package/dist/core/env.d.ts +10 -0
- package/dist/core/env.js +40 -0
- package/dist/core/env.js.map +1 -0
- package/dist/core/event-loop.d.ts +30 -0
- package/dist/core/event-loop.js +43 -0
- package/dist/core/event-loop.js.map +1 -0
- package/dist/core/explain.d.ts +48 -0
- package/dist/core/explain.js +236 -0
- package/dist/core/explain.js.map +1 -0
- package/dist/core/exporters.d.ts +111 -0
- package/dist/core/exporters.js +236 -0
- package/dist/core/exporters.js.map +1 -0
- package/dist/core/index.d.ts +9 -3
- package/dist/core/index.js +9 -3
- package/dist/core/index.js.map +1 -1
- package/dist/core/optimized-performance-monitor.d.ts +180 -26
- package/dist/core/optimized-performance-monitor.js +687 -175
- package/dist/core/optimized-performance-monitor.js.map +1 -1
- package/dist/core/prometheus.d.ts +36 -0
- package/dist/core/prometheus.js +93 -0
- package/dist/core/prometheus.js.map +1 -0
- package/dist/core/records.d.ts +97 -0
- package/dist/core/records.js +87 -0
- package/dist/core/records.js.map +1 -0
- package/dist/core/stats.d.ts +45 -0
- package/dist/core/stats.js +136 -0
- package/dist/core/stats.js.map +1 -0
- package/dist/core/timeline.d.ts +28 -0
- package/dist/core/timeline.js +65 -0
- package/dist/core/timeline.js.map +1 -0
- package/dist/drivers.d.ts +51 -0
- package/dist/drivers.js +205 -0
- package/dist/drivers.js.map +1 -0
- package/dist/esm/auto.d.ts +30 -0
- package/dist/esm/auto.js +87 -0
- package/dist/esm/auto.js.map +1 -0
- package/dist/esm/browser.d.ts +52 -144
- package/dist/esm/browser.js +101 -445
- package/dist/esm/browser.js.map +1 -1
- package/dist/esm/cli.d.ts +68 -0
- package/dist/esm/cli.js +520 -0
- package/dist/esm/cli.js.map +1 -0
- package/dist/esm/core/allocations.d.ts +38 -0
- package/dist/esm/core/allocations.js +82 -0
- package/dist/esm/core/allocations.js.map +1 -0
- package/dist/esm/core/cpu-profile.d.ts +84 -0
- package/dist/esm/core/cpu-profile.js +176 -0
- package/dist/esm/core/cpu-profile.js.map +1 -0
- package/dist/esm/core/env.d.ts +10 -0
- package/dist/esm/core/env.js +35 -0
- package/dist/esm/core/env.js.map +1 -0
- package/dist/esm/core/event-loop.d.ts +30 -0
- package/dist/esm/core/event-loop.js +40 -0
- package/dist/esm/core/event-loop.js.map +1 -0
- package/dist/esm/core/explain.d.ts +48 -0
- package/dist/esm/core/explain.js +232 -0
- package/dist/esm/core/explain.js.map +1 -0
- package/dist/esm/core/exporters.d.ts +111 -0
- package/dist/esm/core/exporters.js +229 -0
- package/dist/esm/core/exporters.js.map +1 -0
- package/dist/esm/core/index.d.ts +10 -4
- package/dist/esm/core/index.js +10 -4
- package/dist/esm/core/index.js.map +1 -1
- package/dist/esm/core/optimized-performance-monitor.d.ts +180 -26
- package/dist/esm/core/optimized-performance-monitor.js +685 -173
- package/dist/esm/core/optimized-performance-monitor.js.map +1 -1
- package/dist/esm/core/prometheus.d.ts +36 -0
- package/dist/esm/core/prometheus.js +89 -0
- package/dist/esm/core/prometheus.js.map +1 -0
- package/dist/esm/core/records.d.ts +97 -0
- package/dist/esm/core/records.js +82 -0
- package/dist/esm/core/records.js.map +1 -0
- package/dist/esm/core/stats.d.ts +45 -0
- package/dist/esm/core/stats.js +131 -0
- package/dist/esm/core/stats.js.map +1 -0
- package/dist/esm/core/timeline.d.ts +28 -0
- package/dist/esm/core/timeline.js +62 -0
- package/dist/esm/core/timeline.js.map +1 -0
- package/dist/esm/drivers.d.ts +51 -0
- package/dist/esm/drivers.js +197 -0
- package/dist/esm/drivers.js.map +1 -0
- package/dist/esm/index.d.ts +13 -5
- package/dist/esm/index.js +21 -17
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/instrument.d.ts +88 -0
- package/dist/esm/instrument.js +274 -0
- package/dist/esm/instrument.js.map +1 -0
- package/dist/esm/integrations.d.ts +70 -0
- package/dist/esm/integrations.js +197 -0
- package/dist/esm/integrations.js.map +1 -0
- package/dist/esm/node-builtins.d.ts +1 -0
- package/dist/esm/node-builtins.js +32 -0
- package/dist/esm/node-builtins.js.map +1 -0
- package/dist/esm/package.json +3 -0
- package/dist/esm/register.d.ts +20 -0
- package/dist/esm/register.js +98 -0
- package/dist/esm/register.js.map +1 -0
- package/dist/esm/report-html.d.ts +11 -0
- package/dist/esm/report-html.js +106 -0
- package/dist/esm/report-html.js.map +1 -0
- package/dist/esm/types/index.d.ts +4 -80
- package/dist/esm/types/index.js +1 -2
- package/dist/esm/types/index.js.map +1 -1
- package/dist/esm/types/options.d.ts +72 -0
- package/dist/esm/types/options.js +2 -0
- package/dist/esm/types/options.js.map +1 -0
- package/dist/esm/watch.d.ts +17 -0
- package/dist/esm/watch.js +87 -0
- package/dist/esm/watch.js.map +1 -0
- package/dist/index.d.ts +10 -2
- package/dist/index.js +26 -29
- package/dist/index.js.map +1 -1
- package/dist/instrument.d.ts +88 -0
- package/dist/instrument.js +282 -0
- package/dist/instrument.js.map +1 -0
- package/dist/integrations.d.ts +70 -0
- package/dist/integrations.js +205 -0
- package/dist/integrations.js.map +1 -0
- package/dist/node-builtins.d.ts +1 -0
- package/dist/node-builtins.js +67 -0
- package/dist/node-builtins.js.map +1 -0
- package/dist/register.d.ts +20 -0
- package/dist/register.js +103 -0
- package/dist/register.js.map +1 -0
- package/dist/report-html.d.ts +11 -0
- package/dist/report-html.js +109 -0
- package/dist/report-html.js.map +1 -0
- package/dist/traceperf.browser.js +1910 -0
- package/dist/traceperf.browser.min.js +6 -0
- package/dist/types/index.d.ts +4 -80
- package/dist/types/index.js +1 -2
- package/dist/types/index.js.map +1 -1
- package/dist/types/options.d.ts +72 -0
- package/dist/types/{config.js → options.js} +1 -1
- package/dist/types/options.js.map +1 -0
- package/dist/watch.d.ts +17 -0
- package/dist/watch.js +90 -0
- package/dist/watch.js.map +1 -0
- package/package.json +99 -19
- package/dist/core/config.d.ts +0 -77
- package/dist/core/config.js +0 -116
- package/dist/core/config.js.map +0 -1
- package/dist/core/constants.d.ts +0 -78
- package/dist/core/constants.js +0 -109
- package/dist/core/constants.js.map +0 -1
- package/dist/core/logger.d.ts +0 -97
- package/dist/core/logger.js +0 -186
- package/dist/core/logger.js.map +0 -1
- package/dist/esm/core/config.d.ts +0 -77
- package/dist/esm/core/config.js +0 -112
- package/dist/esm/core/config.js.map +0 -1
- package/dist/esm/core/constants.d.ts +0 -78
- package/dist/esm/core/constants.js +0 -106
- package/dist/esm/core/constants.js.map +0 -1
- package/dist/esm/core/logger.d.ts +0 -97
- package/dist/esm/core/logger.js +0 -182
- package/dist/esm/core/logger.js.map +0 -1
- package/dist/esm/formatters/ascii.d.ts +0 -52
- package/dist/esm/formatters/ascii.js +0 -100
- package/dist/esm/formatters/ascii.js.map +0 -1
- package/dist/esm/formatters/cli.d.ts +0 -50
- package/dist/esm/formatters/cli.js +0 -96
- package/dist/esm/formatters/cli.js.map +0 -1
- package/dist/esm/formatters/index.d.ts +0 -3
- package/dist/esm/formatters/index.js +0 -4
- package/dist/esm/formatters/index.js.map +0 -1
- package/dist/esm/formatters/json.d.ts +0 -45
- package/dist/esm/formatters/json.js +0 -85
- package/dist/esm/formatters/json.js.map +0 -1
- package/dist/esm/trackers/execution.d.ts +0 -101
- package/dist/esm/trackers/execution.js +0 -226
- package/dist/esm/trackers/execution.js.map +0 -1
- package/dist/esm/trackers/index.d.ts +0 -2
- package/dist/esm/trackers/index.js +0 -3
- package/dist/esm/trackers/index.js.map +0 -1
- package/dist/esm/trackers/performance.d.ts +0 -68
- package/dist/esm/trackers/performance.js +0 -112
- package/dist/esm/trackers/performance.js.map +0 -1
- package/dist/esm/types/config.d.ts +0 -142
- package/dist/esm/types/config.js +0 -2
- package/dist/esm/types/config.js.map +0 -1
- package/dist/esm/types/logger.d.ts +0 -147
- package/dist/esm/types/logger.js +0 -2
- package/dist/esm/types/logger.js.map +0 -1
- package/dist/esm/utils/colors.d.ts +0 -87
- package/dist/esm/utils/colors.js +0 -146
- package/dist/esm/utils/colors.js.map +0 -1
- package/dist/esm/utils/index.d.ts +0 -3
- package/dist/esm/utils/index.js +0 -4
- package/dist/esm/utils/index.js.map +0 -1
- package/dist/esm/utils/proxy-tracker.d.ts +0 -68
- package/dist/esm/utils/proxy-tracker.js +0 -127
- package/dist/esm/utils/proxy-tracker.js.map +0 -1
- package/dist/esm/utils/stack.d.ts +0 -63
- package/dist/esm/utils/stack.js +0 -110
- package/dist/esm/utils/stack.js.map +0 -1
- package/dist/esm/utils/string.d.ts +0 -29
- package/dist/esm/utils/string.js +0 -45
- package/dist/esm/utils/string.js.map +0 -1
- package/dist/esm/utils/timing.d.ts +0 -65
- package/dist/esm/utils/timing.js +0 -99
- package/dist/esm/utils/timing.js.map +0 -1
- package/dist/formatters/ascii.d.ts +0 -52
- package/dist/formatters/ascii.js +0 -104
- package/dist/formatters/ascii.js.map +0 -1
- package/dist/formatters/cli.d.ts +0 -50
- package/dist/formatters/cli.js +0 -100
- package/dist/formatters/cli.js.map +0 -1
- package/dist/formatters/index.d.ts +0 -3
- package/dist/formatters/index.js +0 -20
- package/dist/formatters/index.js.map +0 -1
- package/dist/formatters/json.d.ts +0 -45
- package/dist/formatters/json.js +0 -89
- package/dist/formatters/json.js.map +0 -1
- package/dist/trackers/execution.d.ts +0 -101
- package/dist/trackers/execution.js +0 -230
- package/dist/trackers/execution.js.map +0 -1
- package/dist/trackers/index.d.ts +0 -2
- package/dist/trackers/index.js +0 -19
- package/dist/trackers/index.js.map +0 -1
- package/dist/trackers/performance.d.ts +0 -68
- package/dist/trackers/performance.js +0 -116
- package/dist/trackers/performance.js.map +0 -1
- package/dist/types/config.d.ts +0 -142
- package/dist/types/config.js.map +0 -1
- package/dist/types/logger.d.ts +0 -147
- package/dist/types/logger.js +0 -3
- package/dist/types/logger.js.map +0 -1
- package/dist/types.d.ts +0 -65
- package/dist/types.js +0 -6
- package/dist/types.js.map +0 -1
- package/dist/utils/colors.d.ts +0 -87
- package/dist/utils/colors.js +0 -160
- package/dist/utils/colors.js.map +0 -1
- package/dist/utils/index.d.ts +0 -3
- package/dist/utils/index.js +0 -20
- package/dist/utils/index.js.map +0 -1
- package/dist/utils/proxy-tracker.d.ts +0 -68
- package/dist/utils/proxy-tracker.js +0 -131
- package/dist/utils/proxy-tracker.js.map +0 -1
- package/dist/utils/stack.d.ts +0 -63
- package/dist/utils/stack.js +0 -116
- package/dist/utils/stack.js.map +0 -1
- package/dist/utils/string.d.ts +0 -29
- package/dist/utils/string.js +0 -50
- package/dist/utils/string.js.map +0 -1
- package/dist/utils/timing.d.ts +0 -65
- package/dist/utils/timing.js +0 -106
- package/dist/utils/timing.js.map +0 -1
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;AAeA,0CAEC;AAKD,wBAIC;AA1BD,iDAAiD;AACjD,wFAAkG;AAkCzF,4GAlCA,2DAA2B,OAkCA;AACV,6FAnCY,6CAAa,OAmCb;AAhCtC,2EAA2E;AAC3E,mEAAmE;AACnE,8DAA8D;AAC9D,MAAM,WAAW,GAAG,MAAM,CAAC,GAAG,CAAC,sBAAsB,CAAC,CAAC;AACvD,MAAM,MAAM,GAAG,UAAiB,CAAC;AACjC,MAAM,SAAS,GAAgC,MAAM,CAAC,WAAW,CAAC,IAAI,CAAC,MAAM,CAAC,WAAW,CAAC,GAAG,IAAI,2DAA2B,EAAE,CAAC,CAAC;AAEhI,sDAAsD;AACtD,kBAAe,SAAS,CAAC;AAEzB,uDAAuD;AACvD,SAAgB,eAAe,CAAC,SAA2B,EAAE;IAC3D,OAAO,IAAI,2DAA2B,CAAC,MAAM,CAAC,CAAC;AACjD,CAAC;AAED;;GAEG;AACH,SAAgB,MAAM,CAAC,UAAwB,EAAE;IAC/C,yEAAyE;IACzE,+DAA+D;IAC/D,OAAO,2DAA2B,CAAC,SAAS,CAAC,MAAM,CAAC,IAAI,CAAC,SAAS,EAAE,OAAO,CAAC,CAAC;AAC/E,CAAC;AAED,8CAA8C;AAC9C,0CAAwB;AACxB,yCAAuB;AACvB,iDAA+B;AAC/B,+CAA6B;AAC7B,4CAA0B;AAC1B,yCAAuB;AAIvB,eAAe;AACf,2EAA2E;AAC3E,8EAA8E;AAC9E,8EAA8E;AAC9E,IAAI,OAAO,MAAM,KAAK,WAAW,IAAI,MAAM,CAAC,OAAO,EAAE,CAAC;IACpD,MAAM,CAAC,OAAO,GAAG,MAAM,CAAC,MAAM,CAAC,SAAS,EAAE,MAAM,CAAC,OAAO,EAAE;QACxD,OAAO,EAAE,SAAS;QAClB,eAAe;QACf,MAAM;QACN,2BAA2B,EAA3B,2DAA2B;QAC3B,YAAY,EAAE,6CAAa;KAC5B,CAAC,CAAC;AACL,CAAC;AACD,gBAAgB"}
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Auto-instrumentation: track common I/O without wrapping each call by hand.
|
|
3
|
+
*
|
|
4
|
+
* Every instrument* function patches in place, is idempotent, and returns a
|
|
5
|
+
* function that removes the patch. Calls made inside a tracked call nest
|
|
6
|
+
* under it like any other tracked call.
|
|
7
|
+
*/
|
|
8
|
+
import type { OptimizedPerformanceMonitor } from './core/optimized-performance-monitor';
|
|
9
|
+
import type { TrackOptions } from './types/options';
|
|
10
|
+
export interface InstrumentOptions extends Omit<TrackOptions, 'label'> {
|
|
11
|
+
/** Treat HTTP responses with status >= this as failed (default 500) */
|
|
12
|
+
errorStatus?: number;
|
|
13
|
+
}
|
|
14
|
+
/** Removes an instrumentation patch */
|
|
15
|
+
export type Uninstall = () => void;
|
|
16
|
+
/**
|
|
17
|
+
* Track every `fetch()` call: label "fetch GET api.example.com/users".
|
|
18
|
+
* Timing covers the request until the response headers arrive (reading the
|
|
19
|
+
* body is not included). Responses with status >= 500 are marked failed.
|
|
20
|
+
*/
|
|
21
|
+
export declare function instrumentFetch(tp: OptimizedPerformanceMonitor, options?: InstrumentOptions): Uninstall;
|
|
22
|
+
/**
|
|
23
|
+
* Track outgoing Node.js http/https requests (`request` and `get`), which
|
|
24
|
+
* covers clients built on them such as axios and got. Label:
|
|
25
|
+
* "http GET api.example.com/users". Timing covers the full response
|
|
26
|
+
* (until the body has been read). Node.js only.
|
|
27
|
+
*/
|
|
28
|
+
export declare function instrumentHttp(tp: OptimizedPerformanceMonitor, options?: InstrumentOptions): Uninstall;
|
|
29
|
+
export interface InstrumentMethodsOptions extends TrackOptions {
|
|
30
|
+
/** Label prefix, e.g. "pg." (default: the constructor name of `target` plus ".") */
|
|
31
|
+
prefix?: string;
|
|
32
|
+
/** Compute the label per call, e.g. from the SQL text */
|
|
33
|
+
labelFor?: (method: string, args: unknown[]) => string;
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Patch methods of an object or prototype in place, e.g. a database client:
|
|
37
|
+
*
|
|
38
|
+
* instrumentMethods(tp, pg.Client.prototype, ['query'], {
|
|
39
|
+
* labelFor: (_m, [q]) => `pg ${String(q?.text ?? q).trim().split(/\s+/)[0]}`,
|
|
40
|
+
* });
|
|
41
|
+
*
|
|
42
|
+
* `methods` defaults to every own function property except the constructor.
|
|
43
|
+
*/
|
|
44
|
+
export declare function instrumentMethods(tp: OptimizedPerformanceMonitor, target: object, methods?: string[], options?: InstrumentMethodsOptions): Uninstall;
|
|
45
|
+
/**
|
|
46
|
+
* Prisma client extension: every model operation becomes a tracked call
|
|
47
|
+
* labelled "prisma.User.findMany".
|
|
48
|
+
*
|
|
49
|
+
* const prisma = new PrismaClient().$extends(prismaExtension(tp));
|
|
50
|
+
*/
|
|
51
|
+
export declare function prismaExtension(tp: OptimizedPerformanceMonitor, options?: TrackOptions): {
|
|
52
|
+
name: string;
|
|
53
|
+
query: {
|
|
54
|
+
$allModels: {
|
|
55
|
+
$allOperations(params: {
|
|
56
|
+
model?: string;
|
|
57
|
+
operation: string;
|
|
58
|
+
args: unknown;
|
|
59
|
+
query: (args: unknown) => Promise<unknown>;
|
|
60
|
+
}): Promise<unknown>;
|
|
61
|
+
};
|
|
62
|
+
};
|
|
63
|
+
};
|
|
64
|
+
/**
|
|
65
|
+
* Collapse ids in a URL path so labels stay few: /users/42/orders/9f1c... ->
|
|
66
|
+
* /users/:id/orders/:id. Numbers, UUIDs, long hex and long mixed tokens count as ids.
|
|
67
|
+
*/
|
|
68
|
+
export declare function normalizePath(url: string): string;
|
|
69
|
+
export interface HttpServerInstrumentOptions extends InstrumentOptions {
|
|
70
|
+
/** Label for a request (default "GET /users/:id", ids collapsed by normalizePath) */
|
|
71
|
+
labelFor?: (req: {
|
|
72
|
+
method?: string;
|
|
73
|
+
url?: string;
|
|
74
|
+
headers?: Record<string, unknown>;
|
|
75
|
+
}) => string;
|
|
76
|
+
/** Skip requests for which this returns true, e.g. health checks */
|
|
77
|
+
ignore?: (req: {
|
|
78
|
+
method?: string;
|
|
79
|
+
url?: string;
|
|
80
|
+
}) => boolean;
|
|
81
|
+
}
|
|
82
|
+
/**
|
|
83
|
+
* Track every incoming request of every Node http/https server as a
|
|
84
|
+
* top-level call, so work done while handling it (queries, fetches, tracked
|
|
85
|
+
* functions) nests under it, with no framework middleware. Responses with
|
|
86
|
+
* status >= 500 and connections closed before a response count as failed.
|
|
87
|
+
*/
|
|
88
|
+
export declare function instrumentHttpServer(tp: OptimizedPerformanceMonitor, options?: HttpServerInstrumentOptions): Uninstall;
|
|
@@ -0,0 +1,282 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.instrumentFetch = instrumentFetch;
|
|
4
|
+
exports.instrumentHttp = instrumentHttp;
|
|
5
|
+
exports.instrumentMethods = instrumentMethods;
|
|
6
|
+
exports.prismaExtension = prismaExtension;
|
|
7
|
+
exports.normalizePath = normalizePath;
|
|
8
|
+
exports.instrumentHttpServer = instrumentHttpServer;
|
|
9
|
+
const env_1 = require("./core/env");
|
|
10
|
+
const PATCHED = Symbol.for('traceperf.instrumented');
|
|
11
|
+
function describeUrl(input) {
|
|
12
|
+
try {
|
|
13
|
+
if (typeof input === 'string' || input instanceof URL) {
|
|
14
|
+
const url = new URL(String(input), 'http://localhost');
|
|
15
|
+
return { host: url.host, path: url.pathname };
|
|
16
|
+
}
|
|
17
|
+
if (input && typeof input.url === 'string') {
|
|
18
|
+
const url = new URL(input.url, 'http://localhost');
|
|
19
|
+
return { method: input.method, host: url.host, path: url.pathname };
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
catch (_a) {
|
|
23
|
+
// fall through
|
|
24
|
+
}
|
|
25
|
+
return { host: 'unknown', path: '' };
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Track every `fetch()` call: label "fetch GET api.example.com/users".
|
|
29
|
+
* Timing covers the request until the response headers arrive (reading the
|
|
30
|
+
* body is not included). Responses with status >= 500 are marked failed.
|
|
31
|
+
*/
|
|
32
|
+
function instrumentFetch(tp, options = {}) {
|
|
33
|
+
const g = typeof globalThis !== 'undefined' ? globalThis : undefined;
|
|
34
|
+
if (!g || typeof g.fetch !== 'function')
|
|
35
|
+
return () => undefined;
|
|
36
|
+
if (g.fetch[PATCHED])
|
|
37
|
+
return () => undefined;
|
|
38
|
+
const { errorStatus = 500, ...trackOptions } = options;
|
|
39
|
+
const original = g.fetch;
|
|
40
|
+
const patched = function fetch(input, init) {
|
|
41
|
+
const { method: inputMethod, host, path } = describeUrl(input);
|
|
42
|
+
const method = (init && init.method) || inputMethod || 'GET';
|
|
43
|
+
const span = tp.start(`fetch ${method.toUpperCase()} ${host}${path}`, trackOptions);
|
|
44
|
+
let promise;
|
|
45
|
+
try {
|
|
46
|
+
promise = span.run(() => original.call(this, input, init));
|
|
47
|
+
}
|
|
48
|
+
catch (error) {
|
|
49
|
+
span.end(error);
|
|
50
|
+
throw error;
|
|
51
|
+
}
|
|
52
|
+
return Promise.resolve(promise).then(response => {
|
|
53
|
+
span.end(response && response.status >= errorStatus ? new Error(`HTTP ${response.status}`) : undefined);
|
|
54
|
+
return response;
|
|
55
|
+
}, error => {
|
|
56
|
+
span.end(error);
|
|
57
|
+
throw error;
|
|
58
|
+
});
|
|
59
|
+
};
|
|
60
|
+
patched[PATCHED] = original;
|
|
61
|
+
g.fetch = patched;
|
|
62
|
+
return () => {
|
|
63
|
+
if (g.fetch === patched)
|
|
64
|
+
g.fetch = original;
|
|
65
|
+
};
|
|
66
|
+
}
|
|
67
|
+
/**
|
|
68
|
+
* Track outgoing Node.js http/https requests (`request` and `get`), which
|
|
69
|
+
* covers clients built on them such as axios and got. Label:
|
|
70
|
+
* "http GET api.example.com/users". Timing covers the full response
|
|
71
|
+
* (until the body has been read). Node.js only.
|
|
72
|
+
*/
|
|
73
|
+
function instrumentHttp(tp, options = {}) {
|
|
74
|
+
const { errorStatus = 500, ...trackOptions } = options;
|
|
75
|
+
const restores = [];
|
|
76
|
+
for (const moduleName of ['http', 'https']) {
|
|
77
|
+
const mod = (0, env_1.loadNodeBuiltin)(moduleName);
|
|
78
|
+
if (!mod)
|
|
79
|
+
continue;
|
|
80
|
+
for (const fnName of ['request', 'get']) {
|
|
81
|
+
const original = mod[fnName];
|
|
82
|
+
if (typeof original !== 'function' || original[PATCHED])
|
|
83
|
+
continue;
|
|
84
|
+
const patched = function (...args) {
|
|
85
|
+
const span = tp.start(`${moduleName} request`, trackOptions);
|
|
86
|
+
let req;
|
|
87
|
+
try {
|
|
88
|
+
req = span.run(() => original.apply(this, args));
|
|
89
|
+
}
|
|
90
|
+
catch (error) {
|
|
91
|
+
span.end(error);
|
|
92
|
+
throw error;
|
|
93
|
+
}
|
|
94
|
+
// The Host header includes a non-default port; req.host does not
|
|
95
|
+
const host = (typeof req.getHeader === 'function' && req.getHeader('host')) || req.host || 'unknown';
|
|
96
|
+
span.setLabel(`${moduleName} ${req.method || 'GET'} ${host}${String(req.path || '').split('?')[0]}`);
|
|
97
|
+
let ended = false;
|
|
98
|
+
let statusError;
|
|
99
|
+
// Whichever of res 'end' / res 'close' / req 'close' comes first ends
|
|
100
|
+
// the span (their order differs between Node versions)
|
|
101
|
+
const end = (error = statusError) => {
|
|
102
|
+
if (ended)
|
|
103
|
+
return;
|
|
104
|
+
ended = true;
|
|
105
|
+
span.end(error);
|
|
106
|
+
};
|
|
107
|
+
req.once('response', (res) => {
|
|
108
|
+
statusError = res.statusCode >= errorStatus ? new Error(`HTTP ${res.statusCode}`) : undefined;
|
|
109
|
+
res.once('end', () => end());
|
|
110
|
+
res.once('close', () => end());
|
|
111
|
+
});
|
|
112
|
+
req.once('error', (error) => end(error));
|
|
113
|
+
req.once('close', () => end());
|
|
114
|
+
return req;
|
|
115
|
+
};
|
|
116
|
+
patched[PATCHED] = original;
|
|
117
|
+
mod[fnName] = patched;
|
|
118
|
+
restores.push(() => {
|
|
119
|
+
if (mod[fnName] === patched)
|
|
120
|
+
mod[fnName] = original;
|
|
121
|
+
});
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
return () => restores.forEach(restore => restore());
|
|
125
|
+
}
|
|
126
|
+
/**
|
|
127
|
+
* Patch methods of an object or prototype in place, e.g. a database client:
|
|
128
|
+
*
|
|
129
|
+
* instrumentMethods(tp, pg.Client.prototype, ['query'], {
|
|
130
|
+
* labelFor: (_m, [q]) => `pg ${String(q?.text ?? q).trim().split(/\s+/)[0]}`,
|
|
131
|
+
* });
|
|
132
|
+
*
|
|
133
|
+
* `methods` defaults to every own function property except the constructor.
|
|
134
|
+
*/
|
|
135
|
+
function instrumentMethods(tp, target, methods, options = {}) {
|
|
136
|
+
const { prefix, labelFor, ...trackOptions } = options;
|
|
137
|
+
const ctor = target.constructor;
|
|
138
|
+
const ownerName = typeof target === 'function' ? target.name
|
|
139
|
+
: ctor && ctor.prototype === target ? ctor.name
|
|
140
|
+
: ctor && ctor !== Object ? ctor.name : '';
|
|
141
|
+
const labelPrefix = prefix !== null && prefix !== void 0 ? prefix : (ownerName ? `${ownerName}.` : '');
|
|
142
|
+
const names = methods !== null && methods !== void 0 ? methods : Object.getOwnPropertyNames(target).filter(name => {
|
|
143
|
+
if (name === 'constructor')
|
|
144
|
+
return false;
|
|
145
|
+
const descriptor = Object.getOwnPropertyDescriptor(target, name);
|
|
146
|
+
return !!descriptor && typeof descriptor.value === 'function';
|
|
147
|
+
});
|
|
148
|
+
const restores = [];
|
|
149
|
+
for (const name of names) {
|
|
150
|
+
const original = target[name];
|
|
151
|
+
if (typeof original !== 'function' || original[PATCHED])
|
|
152
|
+
continue;
|
|
153
|
+
const patched = function (...args) {
|
|
154
|
+
const label = labelFor ? labelFor(name, args) : `${labelPrefix}${name}`;
|
|
155
|
+
return tp.track(() => original.apply(this, args), { ...trackOptions, label });
|
|
156
|
+
};
|
|
157
|
+
Object.defineProperty(patched, 'name', { value: original.name, configurable: true });
|
|
158
|
+
Object.defineProperty(patched, 'length', { value: original.length, configurable: true });
|
|
159
|
+
patched[PATCHED] = original;
|
|
160
|
+
const hadOwn = Object.prototype.hasOwnProperty.call(target, name);
|
|
161
|
+
target[name] = patched;
|
|
162
|
+
restores.push(() => {
|
|
163
|
+
if (target[name] !== patched)
|
|
164
|
+
return;
|
|
165
|
+
if (hadOwn)
|
|
166
|
+
target[name] = original;
|
|
167
|
+
else
|
|
168
|
+
delete target[name];
|
|
169
|
+
});
|
|
170
|
+
}
|
|
171
|
+
return () => restores.forEach(restore => restore());
|
|
172
|
+
}
|
|
173
|
+
/**
|
|
174
|
+
* Prisma client extension: every model operation becomes a tracked call
|
|
175
|
+
* labelled "prisma.User.findMany".
|
|
176
|
+
*
|
|
177
|
+
* const prisma = new PrismaClient().$extends(prismaExtension(tp));
|
|
178
|
+
*/
|
|
179
|
+
function prismaExtension(tp, options = {}) {
|
|
180
|
+
return {
|
|
181
|
+
name: 'traceperf',
|
|
182
|
+
query: {
|
|
183
|
+
$allModels: {
|
|
184
|
+
$allOperations(params) {
|
|
185
|
+
var _a, _b;
|
|
186
|
+
const label = (_a = options.label) !== null && _a !== void 0 ? _a : `prisma.${(_b = params.model) !== null && _b !== void 0 ? _b : 'raw'}.${params.operation}`;
|
|
187
|
+
return tp.track(() => params.query(params.args), { ...options, label });
|
|
188
|
+
},
|
|
189
|
+
},
|
|
190
|
+
},
|
|
191
|
+
};
|
|
192
|
+
}
|
|
193
|
+
/**
|
|
194
|
+
* Collapse ids in a URL path so labels stay few: /users/42/orders/9f1c... ->
|
|
195
|
+
* /users/:id/orders/:id. Numbers, UUIDs, long hex and long mixed tokens count as ids.
|
|
196
|
+
*/
|
|
197
|
+
function normalizePath(url) {
|
|
198
|
+
let path = String(url || '/');
|
|
199
|
+
const q = path.search(/[?#]/);
|
|
200
|
+
if (q !== -1)
|
|
201
|
+
path = path.slice(0, q);
|
|
202
|
+
if (!path)
|
|
203
|
+
return '/';
|
|
204
|
+
// Fast path: ids always contain a digit
|
|
205
|
+
if (!/\d/.test(path))
|
|
206
|
+
return path;
|
|
207
|
+
const segments = path.split('/');
|
|
208
|
+
for (let i = 0; i < segments.length; i++) {
|
|
209
|
+
const seg = segments[i];
|
|
210
|
+
if (seg && /\d/.test(seg) && isIdSegment(seg))
|
|
211
|
+
segments[i] = ':id';
|
|
212
|
+
}
|
|
213
|
+
return segments.join('/');
|
|
214
|
+
}
|
|
215
|
+
const UUID = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
|
|
216
|
+
function isIdSegment(seg) {
|
|
217
|
+
if (/^\d+$/.test(seg))
|
|
218
|
+
return true;
|
|
219
|
+
if (seg.length === 36 && UUID.test(seg))
|
|
220
|
+
return true;
|
|
221
|
+
if (seg.length >= 16 && /^[0-9a-f]+$/i.test(seg))
|
|
222
|
+
return true;
|
|
223
|
+
return seg.length >= 20 && /^[A-Za-z0-9_-]+$/.test(seg);
|
|
224
|
+
}
|
|
225
|
+
/**
|
|
226
|
+
* Track every incoming request of every Node http/https server as a
|
|
227
|
+
* top-level call, so work done while handling it (queries, fetches, tracked
|
|
228
|
+
* functions) nests under it, with no framework middleware. Responses with
|
|
229
|
+
* status >= 500 and connections closed before a response count as failed.
|
|
230
|
+
*/
|
|
231
|
+
function instrumentHttpServer(tp, options = {}) {
|
|
232
|
+
const { errorStatus = 500, labelFor, ignore, ...trackOptions } = options;
|
|
233
|
+
const restores = [];
|
|
234
|
+
for (const moduleName of ['http', 'https']) {
|
|
235
|
+
const mod = (0, env_1.loadNodeBuiltin)(moduleName);
|
|
236
|
+
const proto = mod && mod.Server && mod.Server.prototype;
|
|
237
|
+
if (!proto)
|
|
238
|
+
continue;
|
|
239
|
+
const original = proto.emit;
|
|
240
|
+
if (typeof original !== 'function' || original[PATCHED])
|
|
241
|
+
continue;
|
|
242
|
+
const hadOwn = Object.prototype.hasOwnProperty.call(proto, 'emit');
|
|
243
|
+
const patched = function (event, req, res, ...rest) {
|
|
244
|
+
if (event !== 'request' || !req || !res || typeof res.once !== 'function' || (ignore && ignore(req))) {
|
|
245
|
+
return original.call(this, event, req, res, ...rest);
|
|
246
|
+
}
|
|
247
|
+
const label = labelFor ? labelFor(req) : `${req.method || 'GET'} ${normalizePath(req.url)}`;
|
|
248
|
+
const span = tp.start(label, trackOptions);
|
|
249
|
+
// Disabled or sampled out: nothing to finish
|
|
250
|
+
if (!span.id)
|
|
251
|
+
return original.call(this, event, req, res, ...rest);
|
|
252
|
+
let ended = false;
|
|
253
|
+
const end = (error) => {
|
|
254
|
+
if (ended)
|
|
255
|
+
return;
|
|
256
|
+
ended = true;
|
|
257
|
+
span.end(error);
|
|
258
|
+
};
|
|
259
|
+
res.once('finish', () => end(res.statusCode >= errorStatus ? new Error(`HTTP ${res.statusCode}`) : undefined));
|
|
260
|
+
res.once('close', () => end(res.writableFinished ? undefined : new Error('connection closed before the response was sent')));
|
|
261
|
+
try {
|
|
262
|
+
return span.run(() => original.call(this, event, req, res, ...rest));
|
|
263
|
+
}
|
|
264
|
+
catch (error) {
|
|
265
|
+
end(error);
|
|
266
|
+
throw error;
|
|
267
|
+
}
|
|
268
|
+
};
|
|
269
|
+
patched[PATCHED] = original;
|
|
270
|
+
proto.emit = patched;
|
|
271
|
+
restores.push(() => {
|
|
272
|
+
if (proto.emit !== patched)
|
|
273
|
+
return;
|
|
274
|
+
if (hadOwn)
|
|
275
|
+
proto.emit = original;
|
|
276
|
+
else
|
|
277
|
+
delete proto.emit;
|
|
278
|
+
});
|
|
279
|
+
}
|
|
280
|
+
return () => restores.forEach(restore => restore());
|
|
281
|
+
}
|
|
282
|
+
//# sourceMappingURL=instrument.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"instrument.js","sourceRoot":"","sources":["../src/instrument.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Framework integrations: one top-level execution per HTTP request, with
|
|
3
|
+
* tracked calls made while handling the request nested under it.
|
|
4
|
+
*
|
|
5
|
+
* Every helper takes the traceperf instance to record into, so they work
|
|
6
|
+
* with the default instance and with createTracePerf() instances alike.
|
|
7
|
+
*/
|
|
8
|
+
import type { OptimizedPerformanceMonitor } from './core/optimized-performance-monitor';
|
|
9
|
+
import type { TrackOptions } from './types/options';
|
|
10
|
+
/** What a label function gets to work with */
|
|
11
|
+
export interface RequestInfo {
|
|
12
|
+
method: string;
|
|
13
|
+
/** Route pattern when the framework knows it, e.g. "/users/:id" */
|
|
14
|
+
route?: string;
|
|
15
|
+
/** Path without the query string */
|
|
16
|
+
path: string;
|
|
17
|
+
}
|
|
18
|
+
export interface HttpTracingOptions extends Omit<TrackOptions, 'label'> {
|
|
19
|
+
/** Build the label; default "METHOD /route/pattern" (falls back to the path) */
|
|
20
|
+
label?: (request: RequestInfo) => string;
|
|
21
|
+
/** Treat responses with status >= this as failed (default 500) */
|
|
22
|
+
errorStatus?: number;
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Express / Connect middleware. Register it before your routes:
|
|
26
|
+
*
|
|
27
|
+
* app.use(expressMiddleware(tp));
|
|
28
|
+
*/
|
|
29
|
+
export declare function expressMiddleware(tp: OptimizedPerformanceMonitor, options?: HttpTracingOptions): (req: any, res: any, next: (err?: unknown) => void) => void;
|
|
30
|
+
/**
|
|
31
|
+
* Fastify plugin (applies to every route, no fastify-plugin needed):
|
|
32
|
+
*
|
|
33
|
+
* await app.register(fastifyPlugin(tp));
|
|
34
|
+
*/
|
|
35
|
+
export declare function fastifyPlugin(tp: OptimizedPerformanceMonitor, options?: HttpTracingOptions): (fastify: any, _opts: unknown, done: () => void) => void;
|
|
36
|
+
/**
|
|
37
|
+
* Hono middleware:
|
|
38
|
+
*
|
|
39
|
+
* app.use('*', honoMiddleware(tp));
|
|
40
|
+
*/
|
|
41
|
+
export declare function honoMiddleware(tp: OptimizedPerformanceMonitor, options?: HttpTracingOptions): (c: any, next: () => Promise<void>) => Promise<void>;
|
|
42
|
+
/**
|
|
43
|
+
* Wrap any request handler, e.g. a Next.js route handler:
|
|
44
|
+
*
|
|
45
|
+
* export const GET = withTracing(tp, async (request) => { ... });
|
|
46
|
+
*
|
|
47
|
+
* When the first argument looks like a Request, the label defaults to
|
|
48
|
+
* "METHOD /path"; otherwise the function name.
|
|
49
|
+
*/
|
|
50
|
+
export declare function withTracing<T extends (...args: any[]) => any>(tp: OptimizedPerformanceMonitor, handler: T, options?: Omit<HttpTracingOptions, 'errorStatus'>): (...args: Parameters<T>) => ReturnType<T>;
|
|
51
|
+
/**
|
|
52
|
+
* Koa middleware. Register it first:
|
|
53
|
+
*
|
|
54
|
+
* app.use(koaMiddleware(tp));
|
|
55
|
+
*
|
|
56
|
+
* Labels use the matched route when @koa/router sets ctx._matchedRoute.
|
|
57
|
+
*/
|
|
58
|
+
export declare function koaMiddleware(tp: OptimizedPerformanceMonitor, options?: HttpTracingOptions): (ctx: any, next: () => Promise<unknown>) => Promise<void>;
|
|
59
|
+
/**
|
|
60
|
+
* NestJS interceptor (works without importing Nest or rxjs into traceperf):
|
|
61
|
+
*
|
|
62
|
+
* app.useGlobalInterceptors(nestInterceptor(tp));
|
|
63
|
+
*
|
|
64
|
+
* Label: "GET /users/:id" for HTTP, otherwise "Controller.handler".
|
|
65
|
+
*/
|
|
66
|
+
export declare function nestInterceptor(tp: OptimizedPerformanceMonitor, options?: HttpTracingOptions): {
|
|
67
|
+
intercept(context: any, next: {
|
|
68
|
+
handle(): any;
|
|
69
|
+
}): any;
|
|
70
|
+
};
|
|
@@ -0,0 +1,205 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.expressMiddleware = expressMiddleware;
|
|
4
|
+
exports.fastifyPlugin = fastifyPlugin;
|
|
5
|
+
exports.honoMiddleware = honoMiddleware;
|
|
6
|
+
exports.withTracing = withTracing;
|
|
7
|
+
exports.koaMiddleware = koaMiddleware;
|
|
8
|
+
exports.nestInterceptor = nestInterceptor;
|
|
9
|
+
const stripQuery = (url) => {
|
|
10
|
+
if (!url)
|
|
11
|
+
return '/';
|
|
12
|
+
const q = url.indexOf('?');
|
|
13
|
+
return q === -1 ? url : url.slice(0, q);
|
|
14
|
+
};
|
|
15
|
+
const defaultLabel = (r) => `${r.method} ${r.route || r.path}`;
|
|
16
|
+
const statusError = (status, errorStatus) => status !== undefined && status >= errorStatus ? new Error(`HTTP ${status}`) : undefined;
|
|
17
|
+
function splitOptions(options) {
|
|
18
|
+
const { label = defaultLabel, errorStatus = 500, ...trackOptions } = options;
|
|
19
|
+
return { label, errorStatus, trackOptions };
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Express / Connect middleware. Register it before your routes:
|
|
23
|
+
*
|
|
24
|
+
* app.use(expressMiddleware(tp));
|
|
25
|
+
*/
|
|
26
|
+
function expressMiddleware(tp, options = {}) {
|
|
27
|
+
const { label, errorStatus, trackOptions } = splitOptions(options);
|
|
28
|
+
return function traceperfExpress(req, res, next) {
|
|
29
|
+
const path = stripQuery(req.originalUrl || req.url);
|
|
30
|
+
const span = tp.start(label({ method: req.method, path }), trackOptions);
|
|
31
|
+
let finished = false;
|
|
32
|
+
const finish = () => {
|
|
33
|
+
if (finished)
|
|
34
|
+
return;
|
|
35
|
+
finished = true;
|
|
36
|
+
const route = req.route && req.route.path ? `${req.baseUrl || ''}${req.route.path}` : undefined;
|
|
37
|
+
span.setLabel(label({ method: req.method, route, path }));
|
|
38
|
+
span.end(statusError(res.statusCode, errorStatus));
|
|
39
|
+
};
|
|
40
|
+
res.once('finish', finish);
|
|
41
|
+
res.once('close', finish);
|
|
42
|
+
span.run(() => next());
|
|
43
|
+
};
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* Fastify plugin (applies to every route, no fastify-plugin needed):
|
|
47
|
+
*
|
|
48
|
+
* await app.register(fastifyPlugin(tp));
|
|
49
|
+
*/
|
|
50
|
+
function fastifyPlugin(tp, options = {}) {
|
|
51
|
+
const { label, errorStatus, trackOptions } = splitOptions(options);
|
|
52
|
+
const spanKey = Symbol('traceperf.span');
|
|
53
|
+
const plugin = function traceperfFastify(fastify, _opts, done) {
|
|
54
|
+
fastify.addHook('onRequest', (request, _reply, hookDone) => {
|
|
55
|
+
const span = tp.start(label({ method: request.method, path: stripQuery(request.url) }), trackOptions);
|
|
56
|
+
request[spanKey] = span;
|
|
57
|
+
span.run(() => hookDone());
|
|
58
|
+
});
|
|
59
|
+
fastify.addHook('onResponse', (request, reply, hookDone) => {
|
|
60
|
+
const span = request[spanKey];
|
|
61
|
+
if (span) {
|
|
62
|
+
const route = (request.routeOptions && request.routeOptions.url) || request.routerPath;
|
|
63
|
+
span.setLabel(label({ method: request.method, route, path: stripQuery(request.url) }));
|
|
64
|
+
span.end(statusError(reply.statusCode, errorStatus));
|
|
65
|
+
}
|
|
66
|
+
hookDone();
|
|
67
|
+
});
|
|
68
|
+
done();
|
|
69
|
+
};
|
|
70
|
+
// Same effect as wrapping with fastify-plugin: hooks apply to the whole app
|
|
71
|
+
plugin[Symbol.for('skip-override')] = true;
|
|
72
|
+
plugin[Symbol.for('fastify.display-name')] = 'traceperf';
|
|
73
|
+
return plugin;
|
|
74
|
+
}
|
|
75
|
+
/**
|
|
76
|
+
* Hono middleware:
|
|
77
|
+
*
|
|
78
|
+
* app.use('*', honoMiddleware(tp));
|
|
79
|
+
*/
|
|
80
|
+
function honoMiddleware(tp, options = {}) {
|
|
81
|
+
const { label, errorStatus, trackOptions } = splitOptions(options);
|
|
82
|
+
return async function traceperfHono(c, next) {
|
|
83
|
+
var _a;
|
|
84
|
+
const path = c.req.path;
|
|
85
|
+
const span = tp.start(label({ method: c.req.method, path }), trackOptions);
|
|
86
|
+
let thrown;
|
|
87
|
+
try {
|
|
88
|
+
await span.run(() => next());
|
|
89
|
+
}
|
|
90
|
+
catch (error) {
|
|
91
|
+
thrown = error;
|
|
92
|
+
throw error;
|
|
93
|
+
}
|
|
94
|
+
finally {
|
|
95
|
+
const route = typeof c.req.routePath === 'string' && c.req.routePath !== '/*' && c.req.routePath !== '*'
|
|
96
|
+
? c.req.routePath : undefined;
|
|
97
|
+
span.setLabel(label({ method: c.req.method, route, path }));
|
|
98
|
+
span.end((_a = thrown !== null && thrown !== void 0 ? thrown : c.error) !== null && _a !== void 0 ? _a : statusError(c.res && c.res.status, errorStatus));
|
|
99
|
+
}
|
|
100
|
+
};
|
|
101
|
+
}
|
|
102
|
+
/**
|
|
103
|
+
* Wrap any request handler, e.g. a Next.js route handler:
|
|
104
|
+
*
|
|
105
|
+
* export const GET = withTracing(tp, async (request) => { ... });
|
|
106
|
+
*
|
|
107
|
+
* When the first argument looks like a Request, the label defaults to
|
|
108
|
+
* "METHOD /path"; otherwise the function name.
|
|
109
|
+
*/
|
|
110
|
+
function withTracing(tp, handler, options = {}) {
|
|
111
|
+
const { label, trackOptions } = splitOptions(options);
|
|
112
|
+
const wrapped = function (...args) {
|
|
113
|
+
const request = args[0];
|
|
114
|
+
let name = handler.name || 'handler';
|
|
115
|
+
if (request && typeof request.method === 'string' && typeof request.url === 'string') {
|
|
116
|
+
let path = stripQuery(request.url);
|
|
117
|
+
try {
|
|
118
|
+
path = new URL(request.url, 'http://localhost').pathname;
|
|
119
|
+
}
|
|
120
|
+
catch (_a) {
|
|
121
|
+
// keep the raw path
|
|
122
|
+
}
|
|
123
|
+
name = label({ method: request.method, path });
|
|
124
|
+
}
|
|
125
|
+
return tp.track(() => handler.apply(this, args), { ...trackOptions, label: name });
|
|
126
|
+
};
|
|
127
|
+
Object.defineProperty(wrapped, 'name', { value: handler.name, configurable: true });
|
|
128
|
+
Object.defineProperty(wrapped, 'length', { value: handler.length, configurable: true });
|
|
129
|
+
return wrapped;
|
|
130
|
+
}
|
|
131
|
+
/**
|
|
132
|
+
* Koa middleware. Register it first:
|
|
133
|
+
*
|
|
134
|
+
* app.use(koaMiddleware(tp));
|
|
135
|
+
*
|
|
136
|
+
* Labels use the matched route when @koa/router sets ctx._matchedRoute.
|
|
137
|
+
*/
|
|
138
|
+
function koaMiddleware(tp, options = {}) {
|
|
139
|
+
const { label, errorStatus, trackOptions } = splitOptions(options);
|
|
140
|
+
return async function traceperfKoa(ctx, next) {
|
|
141
|
+
const path = stripQuery(ctx.path || ctx.url);
|
|
142
|
+
const span = tp.start(label({ method: ctx.method, path }), trackOptions);
|
|
143
|
+
let thrown;
|
|
144
|
+
try {
|
|
145
|
+
await span.run(() => next());
|
|
146
|
+
}
|
|
147
|
+
catch (error) {
|
|
148
|
+
thrown = error;
|
|
149
|
+
throw error;
|
|
150
|
+
}
|
|
151
|
+
finally {
|
|
152
|
+
const route = typeof ctx._matchedRoute === 'string' ? ctx._matchedRoute : undefined;
|
|
153
|
+
span.setLabel(label({ method: ctx.method, route, path }));
|
|
154
|
+
const status = thrown ? (thrown.status || thrown.statusCode || 500) : ctx.status;
|
|
155
|
+
span.end(thrown && status >= errorStatus ? thrown : statusError(status, errorStatus));
|
|
156
|
+
}
|
|
157
|
+
};
|
|
158
|
+
}
|
|
159
|
+
/**
|
|
160
|
+
* NestJS interceptor (works without importing Nest or rxjs into traceperf):
|
|
161
|
+
*
|
|
162
|
+
* app.useGlobalInterceptors(nestInterceptor(tp));
|
|
163
|
+
*
|
|
164
|
+
* Label: "GET /users/:id" for HTTP, otherwise "Controller.handler".
|
|
165
|
+
*/
|
|
166
|
+
function nestInterceptor(tp, options = {}) {
|
|
167
|
+
const { label, errorStatus, trackOptions } = splitOptions(options);
|
|
168
|
+
return {
|
|
169
|
+
intercept(context, next) {
|
|
170
|
+
var _a, _b, _c, _d;
|
|
171
|
+
const type = typeof context.getType === 'function' ? context.getType() : 'http';
|
|
172
|
+
const request = type === 'http' ? context.switchToHttp().getRequest() : undefined;
|
|
173
|
+
const response = type === 'http' ? context.switchToHttp().getResponse() : undefined;
|
|
174
|
+
const handlerName = `${(_b = (_a = context.getClass) === null || _a === void 0 ? void 0 : _a.call(context).name) !== null && _b !== void 0 ? _b : 'Controller'}.${(_d = (_c = context.getHandler) === null || _c === void 0 ? void 0 : _c.call(context).name) !== null && _d !== void 0 ? _d : 'handler'}`;
|
|
175
|
+
const route = request && request.route && request.route.path
|
|
176
|
+
? `${request.baseUrl || ''}${request.route.path}` : request && request.routeOptions && request.routeOptions.url;
|
|
177
|
+
const name = request
|
|
178
|
+
? label({ method: request.method, route, path: stripQuery(request.originalUrl || request.url) })
|
|
179
|
+
: handlerName;
|
|
180
|
+
const span = tp.start(name, trackOptions);
|
|
181
|
+
const source = span.run(() => next.handle());
|
|
182
|
+
const Observable = source.constructor;
|
|
183
|
+
return new Observable((subscriber) => {
|
|
184
|
+
const subscription = span.run(() => source.subscribe({
|
|
185
|
+
next: (value) => subscriber.next(value),
|
|
186
|
+
error: (error) => {
|
|
187
|
+
span.end(error);
|
|
188
|
+
subscriber.error(error);
|
|
189
|
+
},
|
|
190
|
+
complete: () => {
|
|
191
|
+
var _a;
|
|
192
|
+
const status = response && ((_a = response.statusCode) !== null && _a !== void 0 ? _a : (typeof response.status === 'number' ? response.status : undefined));
|
|
193
|
+
span.end(statusError(status, errorStatus));
|
|
194
|
+
subscriber.complete();
|
|
195
|
+
},
|
|
196
|
+
}));
|
|
197
|
+
return () => {
|
|
198
|
+
subscription.unsubscribe();
|
|
199
|
+
span.end();
|
|
200
|
+
};
|
|
201
|
+
});
|
|
202
|
+
},
|
|
203
|
+
};
|
|
204
|
+
}
|
|
205
|
+
//# sourceMappingURL=integrations.js.map
|