traceperf 0.2.1 → 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 +608 -253
- 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
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Show tracked calls in the browser DevTools Performance panel (and in any
|
|
3
|
+
* User Timing consumer) via performance.measure().
|
|
4
|
+
*/
|
|
5
|
+
import { TracePerfPlugin } from './records';
|
|
6
|
+
export interface PerformanceTimelineOptions {
|
|
7
|
+
/** DevTools track name (default "traceperf") */
|
|
8
|
+
track?: string;
|
|
9
|
+
/** Optional DevTools track group */
|
|
10
|
+
trackGroup?: string;
|
|
11
|
+
/**
|
|
12
|
+
* Keep the entries in the performance timeline (default false). DevTools
|
|
13
|
+
* recordings and PerformanceObservers see every entry either way; keeping
|
|
14
|
+
* them makes performance.getEntriesByType('measure') return them but grows
|
|
15
|
+
* memory in long-running pages.
|
|
16
|
+
*/
|
|
17
|
+
keep?: boolean;
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* Emit a performance.measure() for every finished tracked call.
|
|
21
|
+
*
|
|
22
|
+
* tp.use(performanceTimeline());
|
|
23
|
+
*
|
|
24
|
+
* In Chrome 129+ the entries appear on a custom "traceperf" track in the
|
|
25
|
+
* Performance panel (errors in red, details in the tooltip); elsewhere they
|
|
26
|
+
* appear in the Timings track / User Timing API.
|
|
27
|
+
*/
|
|
28
|
+
export declare function performanceTimeline(options?: PerformanceTimelineOptions): TracePerfPlugin;
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.performanceTimeline = performanceTimeline;
|
|
4
|
+
/**
|
|
5
|
+
* Show tracked calls in the browser DevTools Performance panel (and in any
|
|
6
|
+
* User Timing consumer) via performance.measure().
|
|
7
|
+
*/
|
|
8
|
+
const records_1 = require("./records");
|
|
9
|
+
/**
|
|
10
|
+
* Emit a performance.measure() for every finished tracked call.
|
|
11
|
+
*
|
|
12
|
+
* tp.use(performanceTimeline());
|
|
13
|
+
*
|
|
14
|
+
* In Chrome 129+ the entries appear on a custom "traceperf" track in the
|
|
15
|
+
* Performance panel (errors in red, details in the tooltip); elsewhere they
|
|
16
|
+
* appear in the Timings track / User Timing API.
|
|
17
|
+
*/
|
|
18
|
+
function performanceTimeline(options = {}) {
|
|
19
|
+
var _a;
|
|
20
|
+
const perf = typeof performance !== 'undefined' ? performance : undefined;
|
|
21
|
+
const supported = !!perf && typeof perf.measure === 'function';
|
|
22
|
+
const track = (_a = options.track) !== null && _a !== void 0 ? _a : 'traceperf';
|
|
23
|
+
return {
|
|
24
|
+
name: 'performance-timeline',
|
|
25
|
+
onComplete(root) {
|
|
26
|
+
if (!supported)
|
|
27
|
+
return;
|
|
28
|
+
(0, records_1.walkRecords)(root, record => {
|
|
29
|
+
const failed = record.error !== undefined && record.error !== null;
|
|
30
|
+
const properties = [
|
|
31
|
+
['duration', `${record.duration.toFixed(3)} ms`],
|
|
32
|
+
['self', `${record.selfDuration.toFixed(3)} ms`],
|
|
33
|
+
];
|
|
34
|
+
if (record.async)
|
|
35
|
+
properties.push(['sync', `${record.syncDuration.toFixed(3)} ms`]);
|
|
36
|
+
if (record.memoryDelta !== undefined)
|
|
37
|
+
properties.push(['heap Δ', `${(record.memoryDelta / 1024).toFixed(2)} KB`]);
|
|
38
|
+
if (failed)
|
|
39
|
+
properties.push(['error', record.error instanceof Error ? record.error.message : String(record.error)]);
|
|
40
|
+
try {
|
|
41
|
+
perf.measure(record.label, {
|
|
42
|
+
start: record.startTime,
|
|
43
|
+
duration: record.duration,
|
|
44
|
+
detail: {
|
|
45
|
+
devtools: {
|
|
46
|
+
dataType: 'track-entry',
|
|
47
|
+
track,
|
|
48
|
+
...(options.trackGroup ? { trackGroup: options.trackGroup } : {}),
|
|
49
|
+
color: failed ? 'error' : 'primary',
|
|
50
|
+
properties,
|
|
51
|
+
tooltipText: `${record.label}: ${record.duration.toFixed(2)} ms`,
|
|
52
|
+
},
|
|
53
|
+
},
|
|
54
|
+
});
|
|
55
|
+
if (!options.keep && typeof perf.clearMeasures === 'function')
|
|
56
|
+
perf.clearMeasures(record.label);
|
|
57
|
+
}
|
|
58
|
+
catch (_a) {
|
|
59
|
+
// Older engines without measure(name, options): skip silently
|
|
60
|
+
}
|
|
61
|
+
});
|
|
62
|
+
},
|
|
63
|
+
};
|
|
64
|
+
}
|
|
65
|
+
//# sourceMappingURL=timeline.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"timeline.js","sourceRoot":"","sources":["../../src/core/timeline.ts"],"names":[],"mappings":";;AA6BA,kDAuCC;AApED;;;GAGG;AACH,uCAA0E;AAgB1E;;;;;;;;GAQG;AACH,SAAgB,mBAAmB,CAAC,UAAsC,EAAE;;IAC1E,MAAM,IAAI,GAAQ,OAAO,WAAW,KAAK,WAAW,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,SAAS,CAAC;IAC/E,MAAM,SAAS,GAAG,CAAC,CAAC,IAAI,IAAI,OAAO,IAAI,CAAC,OAAO,KAAK,UAAU,CAAC;IAC/D,MAAM,KAAK,GAAG,MAAA,OAAO,CAAC,KAAK,mCAAI,WAAW,CAAC;IAC3C,OAAO;QACL,IAAI,EAAE,sBAAsB;QAC5B,UAAU,CAAC,IAAqB;YAC9B,IAAI,CAAC,SAAS;gBAAE,OAAO;YACvB,IAAA,qBAAW,EAAC,IAAI,EAAE,MAAM,CAAC,EAAE;gBACzB,MAAM,MAAM,GAAG,MAAM,CAAC,KAAK,KAAK,SAAS,IAAI,MAAM,CAAC,KAAK,KAAK,IAAI,CAAC;gBACnE,MAAM,UAAU,GAA4B;oBAC1C,CAAC,UAAU,EAAE,GAAG,MAAM,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC,CAAC,KAAK,CAAC;oBAChD,CAAC,MAAM,EAAE,GAAG,MAAM,CAAC,YAAY,CAAC,OAAO,CAAC,CAAC,CAAC,KAAK,CAAC;iBACjD,CAAC;gBACF,IAAI,MAAM,CAAC,KAAK;oBAAE,UAAU,CAAC,IAAI,CAAC,CAAC,MAAM,EAAE,GAAG,MAAM,CAAC,YAAY,CAAC,OAAO,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC;gBACpF,IAAI,MAAM,CAAC,WAAW,KAAK,SAAS;oBAAE,UAAU,CAAC,IAAI,CAAC,CAAC,QAAQ,EAAE,GAAG,CAAC,MAAM,CAAC,WAAW,GAAG,IAAI,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC;gBAClH,IAAI,MAAM;oBAAE,UAAU,CAAC,IAAI,CAAC,CAAC,OAAO,EAAE,MAAM,CAAC,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;gBACpH,IAAI,CAAC;oBACH,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,KAAK,EAAE;wBACzB,KAAK,EAAE,MAAM,CAAC,SAAS;wBACvB,QAAQ,EAAE,MAAM,CAAC,QAAQ;wBACzB,MAAM,EAAE;4BACN,QAAQ,EAAE;gCACR,QAAQ,EAAE,aAAa;gCACvB,KAAK;gCACL,GAAG,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC,CAAC,EAAE,UAAU,EAAE,OAAO,CAAC,UAAU,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;gCACjE,KAAK,EAAE,MAAM,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,SAAS;gCACnC,UAAU;gCACV,WAAW,EAAE,GAAG,MAAM,CAAC,KAAK,KAAK,MAAM,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC,CAAC,KAAK;6BACjE;yBACF;qBACF,CAAC,CAAC;oBACH,IAAI,CAAC,OAAO,CAAC,IAAI,IAAI,OAAO,IAAI,CAAC,aAAa,KAAK,UAAU;wBAAE,IAAI,CAAC,aAAa,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;gBAClG,CAAC;gBAAC,WAAM,CAAC;oBACP,8DAA8D;gBAChE,CAAC;YACH,CAAC,CAAC,CAAC;QACL,CAAC;KACF,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Ready-made instrumentation for popular database and cloud clients.
|
|
3
|
+
*
|
|
4
|
+
* Each helper takes the library module (or client) you already import, so
|
|
5
|
+
* traceperf has no dependency on any of them, patches it in place, is
|
|
6
|
+
* idempotent, and returns an uninstall function.
|
|
7
|
+
*/
|
|
8
|
+
import type { OptimizedPerformanceMonitor } from './core/optimized-performance-monitor';
|
|
9
|
+
import type { TrackOptions } from './types/options';
|
|
10
|
+
import type { Uninstall } from './instrument';
|
|
11
|
+
export type DriverOptions = Omit<TrackOptions, 'label'>;
|
|
12
|
+
/**
|
|
13
|
+
* "SELECT users", "INSERT orders", "UPDATE accounts", "BEGIN": the SQL verb
|
|
14
|
+
* and the first table it touches, without values (labels stay low-cardinality).
|
|
15
|
+
*/
|
|
16
|
+
export declare function sqlLabel(sql: unknown): string;
|
|
17
|
+
/**
|
|
18
|
+
* node-postgres: tracks every query ("pg SELECT users"), including those
|
|
19
|
+
* made through Pool.query (it delegates to Client.query).
|
|
20
|
+
*
|
|
21
|
+
* instrumentPg(tp, require('pg'));
|
|
22
|
+
*/
|
|
23
|
+
export declare function instrumentPg(tp: OptimizedPerformanceMonitor, pg: any, options?: DriverOptions): Uninstall;
|
|
24
|
+
/**
|
|
25
|
+
* mysql2 (callback and promise APIs, connections and pools):
|
|
26
|
+
*
|
|
27
|
+
* instrumentMysql2(tp, require('mysql2'));
|
|
28
|
+
*/
|
|
29
|
+
export declare function instrumentMysql2(tp: OptimizedPerformanceMonitor, mysql2: any, options?: DriverOptions): Uninstall;
|
|
30
|
+
/**
|
|
31
|
+
* MongoDB Node driver, and therefore Mongoose: "mongo insertOne users",
|
|
32
|
+
* "mongo find users" (cursor reads are tracked when the results are fetched).
|
|
33
|
+
*
|
|
34
|
+
* instrumentMongo(tp, require('mongodb'));
|
|
35
|
+
* instrumentMongo(tp, require('mongoose').mongo); // Mongoose's bundled driver
|
|
36
|
+
*/
|
|
37
|
+
export declare function instrumentMongo(tp: OptimizedPerformanceMonitor, mongodb: any, options?: DriverOptions): Uninstall;
|
|
38
|
+
/**
|
|
39
|
+
* ioredis: every command, "redis GET", "redis HSET" (pipelines and
|
|
40
|
+
* transactions show their individual commands).
|
|
41
|
+
*
|
|
42
|
+
* instrumentRedis(tp, require('ioredis'));
|
|
43
|
+
*/
|
|
44
|
+
export declare function instrumentRedis(tp: OptimizedPerformanceMonitor, Redis: any, options?: DriverOptions): Uninstall;
|
|
45
|
+
/**
|
|
46
|
+
* AWS SDK v3 clients: "aws S3.GetObject", "aws DynamoDB.Query".
|
|
47
|
+
* Adds a middleware to the given client instance.
|
|
48
|
+
*
|
|
49
|
+
* instrumentAwsClient(tp, new S3Client({}));
|
|
50
|
+
*/
|
|
51
|
+
export declare function instrumentAwsClient(tp: OptimizedPerformanceMonitor, client: any, options?: DriverOptions): Uninstall;
|
package/dist/drivers.js
ADDED
|
@@ -0,0 +1,205 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.sqlLabel = sqlLabel;
|
|
4
|
+
exports.instrumentPg = instrumentPg;
|
|
5
|
+
exports.instrumentMysql2 = instrumentMysql2;
|
|
6
|
+
exports.instrumentMongo = instrumentMongo;
|
|
7
|
+
exports.instrumentRedis = instrumentRedis;
|
|
8
|
+
exports.instrumentAwsClient = instrumentAwsClient;
|
|
9
|
+
const PATCHED = Symbol.for('traceperf.instrumented');
|
|
10
|
+
const isPromiseLike = (value) => value !== null && (typeof value === 'object' || typeof value === 'function') && typeof value.then === 'function';
|
|
11
|
+
const isCommandObject = (value) => value !== null && typeof value === 'object' && !(value instanceof Promise) &&
|
|
12
|
+
typeof value.once === 'function' && typeof value.on === 'function' &&
|
|
13
|
+
typeof value.emit === 'function';
|
|
14
|
+
/**
|
|
15
|
+
* Run one driver call as a tracked span, whether it reports completion via
|
|
16
|
+
* a callback (last argument), a returned promise, or synchronously.
|
|
17
|
+
*/
|
|
18
|
+
function trackCall(tp, label, options, thisArg, original, args, callbackIndex = args.length - 1) {
|
|
19
|
+
const span = tp.start(label, options);
|
|
20
|
+
let ended = false;
|
|
21
|
+
const end = (error) => {
|
|
22
|
+
if (ended)
|
|
23
|
+
return;
|
|
24
|
+
ended = true;
|
|
25
|
+
span.end(error);
|
|
26
|
+
};
|
|
27
|
+
const cb = callbackIndex >= 0 ? args[callbackIndex] : undefined;
|
|
28
|
+
if (typeof cb === 'function') {
|
|
29
|
+
const wrappedArgs = args.slice();
|
|
30
|
+
wrappedArgs[callbackIndex] = function (error, ...rest) {
|
|
31
|
+
end(error || undefined);
|
|
32
|
+
return cb.call(this, error, ...rest);
|
|
33
|
+
};
|
|
34
|
+
try {
|
|
35
|
+
return span.run(() => original.apply(thisArg, wrappedArgs));
|
|
36
|
+
}
|
|
37
|
+
catch (error) {
|
|
38
|
+
end(error);
|
|
39
|
+
throw error;
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
let result;
|
|
43
|
+
try {
|
|
44
|
+
result = span.run(() => original.apply(thisArg, args));
|
|
45
|
+
}
|
|
46
|
+
catch (error) {
|
|
47
|
+
end(error);
|
|
48
|
+
throw error;
|
|
49
|
+
}
|
|
50
|
+
// Command objects (mysql2 Query, pg Query) are event emitters; some, like
|
|
51
|
+
// mysql2's, have a .then() that throws. Finish on their completion
|
|
52
|
+
// callback or 'end' event instead of treating them as promises.
|
|
53
|
+
if (isCommandObject(result)) {
|
|
54
|
+
const command = result;
|
|
55
|
+
if (typeof command.onResult === 'function') {
|
|
56
|
+
const onResult = command.onResult;
|
|
57
|
+
command.onResult = function (error, ...rest) {
|
|
58
|
+
end(error || undefined);
|
|
59
|
+
return onResult.call(this, error, ...rest);
|
|
60
|
+
};
|
|
61
|
+
}
|
|
62
|
+
command.once('end', () => end());
|
|
63
|
+
return result;
|
|
64
|
+
}
|
|
65
|
+
if (isPromiseLike(result)) {
|
|
66
|
+
result.then(() => end(), error => end(error));
|
|
67
|
+
return result;
|
|
68
|
+
}
|
|
69
|
+
end();
|
|
70
|
+
return result;
|
|
71
|
+
}
|
|
72
|
+
function patchMethod(target, name, makePatched, restores) {
|
|
73
|
+
if (!target)
|
|
74
|
+
return;
|
|
75
|
+
const original = target[name];
|
|
76
|
+
if (typeof original !== 'function' || original[PATCHED])
|
|
77
|
+
return;
|
|
78
|
+
const patched = makePatched(original);
|
|
79
|
+
Object.defineProperty(patched, 'name', { value: original.name, configurable: true });
|
|
80
|
+
Object.defineProperty(patched, 'length', { value: original.length, configurable: true });
|
|
81
|
+
patched[PATCHED] = original;
|
|
82
|
+
const hadOwn = Object.prototype.hasOwnProperty.call(target, name);
|
|
83
|
+
target[name] = patched;
|
|
84
|
+
restores.push(() => {
|
|
85
|
+
if (target[name] !== patched)
|
|
86
|
+
return;
|
|
87
|
+
if (hadOwn)
|
|
88
|
+
target[name] = original;
|
|
89
|
+
else
|
|
90
|
+
delete target[name];
|
|
91
|
+
});
|
|
92
|
+
}
|
|
93
|
+
/**
|
|
94
|
+
* "SELECT users", "INSERT orders", "UPDATE accounts", "BEGIN": the SQL verb
|
|
95
|
+
* and the first table it touches, without values (labels stay low-cardinality).
|
|
96
|
+
*/
|
|
97
|
+
function sqlLabel(sql) {
|
|
98
|
+
const text = typeof sql === 'string' ? sql : sql && typeof sql.text === 'string' ? sql.text
|
|
99
|
+
: sql && typeof sql.sql === 'string' ? sql.sql : '';
|
|
100
|
+
const cleaned = text.replace(/--[^\n]*|\/\*[\s\S]*?\*\//g, ' ').trim();
|
|
101
|
+
const verb = (cleaned.split(/\s+/)[0] || 'query').toUpperCase();
|
|
102
|
+
const table = /\b(?:from|into|update|join|table)\s+("?[\w.]+"?)/i.exec(cleaned);
|
|
103
|
+
return table ? `${verb} ${table[1].replace(/"/g, '')}` : verb;
|
|
104
|
+
}
|
|
105
|
+
/**
|
|
106
|
+
* node-postgres: tracks every query ("pg SELECT users"), including those
|
|
107
|
+
* made through Pool.query (it delegates to Client.query).
|
|
108
|
+
*
|
|
109
|
+
* instrumentPg(tp, require('pg'));
|
|
110
|
+
*/
|
|
111
|
+
function instrumentPg(tp, pg, options = {}) {
|
|
112
|
+
const restores = [];
|
|
113
|
+
patchMethod(pg && pg.Client && pg.Client.prototype, 'query', original => function (...args) {
|
|
114
|
+
return trackCall(tp, `pg ${sqlLabel(args[0])}`, options, this, original, args);
|
|
115
|
+
}, restores);
|
|
116
|
+
return () => restores.forEach(r => r());
|
|
117
|
+
}
|
|
118
|
+
/**
|
|
119
|
+
* mysql2 (callback and promise APIs, connections and pools):
|
|
120
|
+
*
|
|
121
|
+
* instrumentMysql2(tp, require('mysql2'));
|
|
122
|
+
*/
|
|
123
|
+
function instrumentMysql2(tp, mysql2, options = {}) {
|
|
124
|
+
const restores = [];
|
|
125
|
+
const proto = mysql2 && mysql2.Connection && mysql2.Connection.prototype;
|
|
126
|
+
for (const method of ['query', 'execute']) {
|
|
127
|
+
patchMethod(proto, method, original => function (...args) {
|
|
128
|
+
return trackCall(tp, `mysql ${sqlLabel(args[0])}`, options, this, original, args);
|
|
129
|
+
}, restores);
|
|
130
|
+
}
|
|
131
|
+
return () => restores.forEach(r => r());
|
|
132
|
+
}
|
|
133
|
+
const MONGO_COLLECTION_METHODS = [
|
|
134
|
+
'insertOne', 'insertMany', 'findOne', 'updateOne', 'updateMany', 'replaceOne', 'deleteOne', 'deleteMany',
|
|
135
|
+
'countDocuments', 'estimatedDocumentCount', 'distinct', 'findOneAndUpdate', 'findOneAndDelete',
|
|
136
|
+
'findOneAndReplace', 'bulkWrite', 'createIndex',
|
|
137
|
+
];
|
|
138
|
+
/**
|
|
139
|
+
* MongoDB Node driver, and therefore Mongoose: "mongo insertOne users",
|
|
140
|
+
* "mongo find users" (cursor reads are tracked when the results are fetched).
|
|
141
|
+
*
|
|
142
|
+
* instrumentMongo(tp, require('mongodb'));
|
|
143
|
+
* instrumentMongo(tp, require('mongoose').mongo); // Mongoose's bundled driver
|
|
144
|
+
*/
|
|
145
|
+
function instrumentMongo(tp, mongodb, options = {}) {
|
|
146
|
+
const restores = [];
|
|
147
|
+
const collection = mongodb && mongodb.Collection && mongodb.Collection.prototype;
|
|
148
|
+
for (const method of MONGO_COLLECTION_METHODS) {
|
|
149
|
+
patchMethod(collection, method, original => function (...args) {
|
|
150
|
+
// Modern driver methods are promise-only; never treat a filter as a callback
|
|
151
|
+
return trackCall(tp, `mongo ${method} ${this && this.collectionName}`, options, this, original, args, -1);
|
|
152
|
+
}, restores);
|
|
153
|
+
}
|
|
154
|
+
const cursorName = (cursor) => {
|
|
155
|
+
const ns = cursor && cursor.namespace;
|
|
156
|
+
return (ns && (ns.collection || ns.coll)) || '';
|
|
157
|
+
};
|
|
158
|
+
for (const [className, op] of [['FindCursor', 'find'], ['AggregationCursor', 'aggregate']]) {
|
|
159
|
+
const proto = mongodb && mongodb[className] && mongodb[className].prototype;
|
|
160
|
+
patchMethod(proto, 'toArray', original => function (...args) {
|
|
161
|
+
return trackCall(tp, `mongo ${op} ${cursorName(this)}`, options, this, original, args, -1);
|
|
162
|
+
}, restores);
|
|
163
|
+
}
|
|
164
|
+
return () => restores.forEach(r => r());
|
|
165
|
+
}
|
|
166
|
+
/**
|
|
167
|
+
* ioredis: every command, "redis GET", "redis HSET" (pipelines and
|
|
168
|
+
* transactions show their individual commands).
|
|
169
|
+
*
|
|
170
|
+
* instrumentRedis(tp, require('ioredis'));
|
|
171
|
+
*/
|
|
172
|
+
function instrumentRedis(tp, Redis, options = {}) {
|
|
173
|
+
const restores = [];
|
|
174
|
+
const RedisClass = Redis && (Redis.default || Redis.Redis || Redis);
|
|
175
|
+
patchMethod(RedisClass && RedisClass.prototype, 'sendCommand', original => function (command, ...rest) {
|
|
176
|
+
const name = command && command.name ? String(command.name).toUpperCase() : 'COMMAND';
|
|
177
|
+
return trackCall(tp, `redis ${name}`, options, this, original, [command, ...rest], -1);
|
|
178
|
+
}, restores);
|
|
179
|
+
return () => restores.forEach(r => r());
|
|
180
|
+
}
|
|
181
|
+
/**
|
|
182
|
+
* AWS SDK v3 clients: "aws S3.GetObject", "aws DynamoDB.Query".
|
|
183
|
+
* Adds a middleware to the given client instance.
|
|
184
|
+
*
|
|
185
|
+
* instrumentAwsClient(tp, new S3Client({}));
|
|
186
|
+
*/
|
|
187
|
+
function instrumentAwsClient(tp, client, options = {}) {
|
|
188
|
+
const stack = client && client.middlewareStack;
|
|
189
|
+
if (!stack || typeof stack.add !== 'function')
|
|
190
|
+
return () => undefined;
|
|
191
|
+
const name = 'traceperfMiddleware';
|
|
192
|
+
if (client[PATCHED])
|
|
193
|
+
return () => undefined;
|
|
194
|
+
const service = (context) => { var _a; return String((context && context.clientName) || ((_a = client.constructor) === null || _a === void 0 ? void 0 : _a.name) || 'AWS').replace(/Client$/, ''); };
|
|
195
|
+
stack.add((next, context) => (args) => tp.track(() => next(args), {
|
|
196
|
+
...options,
|
|
197
|
+
label: `aws ${service(context)}.${String((context && context.commandName) || 'Command').replace(/Command$/, '')}`,
|
|
198
|
+
}), { step: 'initialize', name, priority: 'high' });
|
|
199
|
+
client[PATCHED] = true;
|
|
200
|
+
return () => {
|
|
201
|
+
stack.remove(name);
|
|
202
|
+
delete client[PATCHED];
|
|
203
|
+
};
|
|
204
|
+
}
|
|
205
|
+
//# sourceMappingURL=drivers.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"drivers.js","sourceRoot":"","sources":["../src/drivers.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Zero-code instrumentation: incoming HTTP requests, outgoing http/fetch and
|
|
3
|
+
* the database clients the application depends on.
|
|
4
|
+
*
|
|
5
|
+
* const { uninstall, instrumented } = autoInstrument(tp);
|
|
6
|
+
*
|
|
7
|
+
* or without touching the code (see register.ts):
|
|
8
|
+
*
|
|
9
|
+
* node --require traceperf/auto app.js # CommonJS or ESM apps
|
|
10
|
+
* node --import traceperf/auto app.mjs # Node >= 18.19 / 20.6
|
|
11
|
+
*/
|
|
12
|
+
import type { OptimizedPerformanceMonitor } from './core/optimized-performance-monitor.js';
|
|
13
|
+
import { HttpServerInstrumentOptions, Uninstall } from './instrument.js';
|
|
14
|
+
export type AutoTarget = 'server' | 'http' | 'fetch' | 'pg' | 'mysql2' | 'mongodb' | 'ioredis';
|
|
15
|
+
export declare const AUTO_TARGETS: AutoTarget[];
|
|
16
|
+
export interface AutoInstrumentOptions {
|
|
17
|
+
/** Targets to skip, e.g. ['http'] */
|
|
18
|
+
disable?: AutoTarget[];
|
|
19
|
+
/** Directory whose package.json lists the app's dependencies (default process.cwd()) */
|
|
20
|
+
cwd?: string;
|
|
21
|
+
/** Options for incoming-request tracking (labels, ignored paths, error status) */
|
|
22
|
+
server?: HttpServerInstrumentOptions;
|
|
23
|
+
}
|
|
24
|
+
export interface AutoInstrumentResult {
|
|
25
|
+
/** What was instrumented, e.g. ['server', 'http', 'fetch', 'pg'] */
|
|
26
|
+
instrumented: AutoTarget[];
|
|
27
|
+
/** Remove every patch */
|
|
28
|
+
uninstall: Uninstall;
|
|
29
|
+
}
|
|
30
|
+
export declare function autoInstrument(tp: OptimizedPerformanceMonitor, options?: AutoInstrumentOptions): AutoInstrumentResult;
|
package/dist/esm/auto.js
ADDED
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
import { loadNodeBuiltin } from './core/env.js';
|
|
2
|
+
import { instrumentFetch, instrumentHttp, instrumentHttpServer } from './instrument.js';
|
|
3
|
+
import { instrumentMongo, instrumentMysql2, instrumentPg, instrumentRedis } from './drivers.js';
|
|
4
|
+
export const AUTO_TARGETS = ['server', 'http', 'fetch', 'pg', 'mysql2', 'mongodb', 'ioredis'];
|
|
5
|
+
/** Dependencies declared by the nearest package.json at or above `dir` */
|
|
6
|
+
function declaredDependencies(dir) {
|
|
7
|
+
const fs = loadNodeBuiltin('fs');
|
|
8
|
+
const path = loadNodeBuiltin('path');
|
|
9
|
+
if (!fs || !path)
|
|
10
|
+
return undefined;
|
|
11
|
+
let current = path.resolve(dir);
|
|
12
|
+
for (;;) {
|
|
13
|
+
const file = path.join(current, 'package.json');
|
|
14
|
+
if (fs.existsSync(file)) {
|
|
15
|
+
try {
|
|
16
|
+
const pkg = JSON.parse(fs.readFileSync(file, 'utf8'));
|
|
17
|
+
const names = new Set(Object.keys({
|
|
18
|
+
...pkg.dependencies, ...pkg.devDependencies, ...pkg.optionalDependencies, ...pkg.peerDependencies,
|
|
19
|
+
}));
|
|
20
|
+
return { names, dir: current };
|
|
21
|
+
}
|
|
22
|
+
catch (_a) {
|
|
23
|
+
return undefined;
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
const parent = path.dirname(current);
|
|
27
|
+
if (parent === current)
|
|
28
|
+
return undefined;
|
|
29
|
+
current = parent;
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
export function autoInstrument(tp, options = {}) {
|
|
33
|
+
var _a, _b;
|
|
34
|
+
const disabled = new Set((_a = options.disable) !== null && _a !== void 0 ? _a : []);
|
|
35
|
+
const instrumented = [];
|
|
36
|
+
const restores = [];
|
|
37
|
+
const add = (target, install) => {
|
|
38
|
+
if (disabled.has(target))
|
|
39
|
+
return;
|
|
40
|
+
try {
|
|
41
|
+
const restore = install();
|
|
42
|
+
if (restore) {
|
|
43
|
+
restores.push(restore);
|
|
44
|
+
instrumented.push(target);
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
catch (_a) {
|
|
48
|
+
// A client that cannot be loaded or patched is skipped, never fatal
|
|
49
|
+
}
|
|
50
|
+
};
|
|
51
|
+
const hasHttp = !!loadNodeBuiltin('http');
|
|
52
|
+
if (hasHttp)
|
|
53
|
+
add('server', () => instrumentHttpServer(tp, options.server));
|
|
54
|
+
if (hasHttp)
|
|
55
|
+
add('http', () => instrumentHttp(tp));
|
|
56
|
+
if (typeof globalThis.fetch === 'function')
|
|
57
|
+
add('fetch', () => instrumentFetch(tp));
|
|
58
|
+
// Database clients: only those the app itself depends on, loaded from the
|
|
59
|
+
// app's node_modules so the patched module is the one the app gets. They
|
|
60
|
+
// are CommonJS packages, so `import pg from 'pg'` returns the same object.
|
|
61
|
+
const moduleApi = loadNodeBuiltin('module');
|
|
62
|
+
const path = loadNodeBuiltin('path');
|
|
63
|
+
const deps = moduleApi && path && typeof moduleApi.createRequire === 'function'
|
|
64
|
+
? declaredDependencies((_b = options.cwd) !== null && _b !== void 0 ? _b : process.cwd())
|
|
65
|
+
: undefined;
|
|
66
|
+
if (deps) {
|
|
67
|
+
const appRequire = moduleApi.createRequire(path.join(deps.dir, 'package.json'));
|
|
68
|
+
const load = (name) => appRequire(name);
|
|
69
|
+
if (deps.names.has('pg'))
|
|
70
|
+
add('pg', () => instrumentPg(tp, load('pg')));
|
|
71
|
+
if (deps.names.has('mysql2'))
|
|
72
|
+
add('mysql2', () => instrumentMysql2(tp, load('mysql2')));
|
|
73
|
+
if (deps.names.has('ioredis'))
|
|
74
|
+
add('ioredis', () => instrumentRedis(tp, load('ioredis')));
|
|
75
|
+
if (deps.names.has('mongodb'))
|
|
76
|
+
add('mongodb', () => instrumentMongo(tp, load('mongodb')));
|
|
77
|
+
else if (deps.names.has('mongoose')) {
|
|
78
|
+
// Mongoose's own copy of the driver, without loading Mongoose itself
|
|
79
|
+
add('mongodb', () => {
|
|
80
|
+
const fromMongoose = moduleApi.createRequire(appRequire.resolve('mongoose'));
|
|
81
|
+
return instrumentMongo(tp, fromMongoose('mongodb'));
|
|
82
|
+
});
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
return { instrumented, uninstall: () => restores.splice(0).reverse().forEach(r => r()) };
|
|
86
|
+
}
|
|
87
|
+
//# sourceMappingURL=auto.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"auto.js","sourceRoot":"","sources":["../../src/auto.ts"],"names":[],"mappings":"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"}
|