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
|
@@ -12,7 +12,11 @@
|
|
|
12
12
|
* 7. Enhanced visualization
|
|
13
13
|
*/
|
|
14
14
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
15
|
-
exports.OptimizedPerformanceMonitor = exports.OptimizedExecutionTracker = exports.getDuration = exports.getTimestamp = exports.getMemoryUsage = exports.TrackingModes = void 0;
|
|
15
|
+
exports.OptimizedPerformanceMonitor = exports.OptimizedExecutionTracker = exports.formatArg = exports.getDuration = exports.getTimestamp = exports.getMemoryUsage = exports.TrackingModes = void 0;
|
|
16
|
+
const records_1 = require("./records");
|
|
17
|
+
const stats_1 = require("./stats");
|
|
18
|
+
const exporters_1 = require("./exporters");
|
|
19
|
+
const env_1 = require("./env");
|
|
16
20
|
// Define tracking mode constants directly to avoid circular dependency
|
|
17
21
|
exports.TrackingModes = {
|
|
18
22
|
PERFORMANCE: 'performance',
|
|
@@ -22,12 +26,21 @@ exports.TrackingModes = {
|
|
|
22
26
|
};
|
|
23
27
|
// Define default tracking mode separately to avoid circular dependency
|
|
24
28
|
const DEFAULT_TRACKING_MODE = exports.TrackingModes.BALANCED;
|
|
29
|
+
// v8.getHeapStatistics() reports the same heap figure as
|
|
30
|
+
// process.memoryUsage().heapUsed but ~20x faster (it skips measuring RSS).
|
|
31
|
+
const v8Module = (0, env_1.loadNodeBuiltin)('v8');
|
|
32
|
+
const readHeapUsed = v8Module && typeof v8Module.getHeapStatistics === 'function'
|
|
33
|
+
? () => v8Module.getHeapStatistics().used_heap_size
|
|
34
|
+
: undefined;
|
|
25
35
|
/**
|
|
26
36
|
* Get current memory usage with environment detection
|
|
27
37
|
* @returns Memory usage in bytes
|
|
28
38
|
*/
|
|
29
39
|
const getMemoryUsage = () => {
|
|
30
40
|
var _a;
|
|
41
|
+
if (readHeapUsed) {
|
|
42
|
+
return readHeapUsed();
|
|
43
|
+
}
|
|
31
44
|
// Safe check for Node.js process.memoryUsage()
|
|
32
45
|
if (typeof process !== 'undefined' && process.memoryUsage) {
|
|
33
46
|
const mem = process.memoryUsage();
|
|
@@ -35,8 +48,7 @@ const getMemoryUsage = () => {
|
|
|
35
48
|
}
|
|
36
49
|
// Browser memory API if available
|
|
37
50
|
else if (typeof performance !== 'undefined' && 'memory' in performance) {
|
|
38
|
-
|
|
39
|
-
return ((_a = window.performance.memory) === null || _a === void 0 ? void 0 : _a.usedJSHeapSize) || 0;
|
|
51
|
+
return ((_a = performance.memory) === null || _a === void 0 ? void 0 : _a.usedJSHeapSize) || 0;
|
|
40
52
|
}
|
|
41
53
|
// Fallback when no memory API available
|
|
42
54
|
return 0;
|
|
@@ -46,20 +58,16 @@ exports.getMemoryUsage = getMemoryUsage;
|
|
|
46
58
|
* Get high-resolution timestamp with environment detection
|
|
47
59
|
* @returns Timestamp in nanoseconds
|
|
48
60
|
*/
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
// Fallback to Date.now() (converted to nanoseconds)
|
|
60
|
-
return Date.now() * 1000000;
|
|
61
|
-
};
|
|
62
|
-
exports.getTimestamp = getTimestamp;
|
|
61
|
+
exports.getTimestamp =
|
|
62
|
+
// Clock chosen once at load time (the hot path should not re-detect it)
|
|
63
|
+
typeof performance !== 'undefined' && typeof performance.now === 'function'
|
|
64
|
+
? () => performance.now() * 1000000
|
|
65
|
+
: typeof process !== 'undefined' && typeof process.hrtime === 'function'
|
|
66
|
+
? () => {
|
|
67
|
+
const hrTime = process.hrtime();
|
|
68
|
+
return hrTime[0] * 1000000000 + hrTime[1];
|
|
69
|
+
}
|
|
70
|
+
: () => Date.now() * 1000000;
|
|
63
71
|
/**
|
|
64
72
|
* Calculate time difference between two timestamps
|
|
65
73
|
* @param startTime Starting timestamp in nanoseconds
|
|
@@ -69,6 +77,92 @@ const getDuration = (startTime) => {
|
|
|
69
77
|
return (0, exports.getTimestamp)() - startTime;
|
|
70
78
|
};
|
|
71
79
|
exports.getDuration = getDuration;
|
|
80
|
+
// Offset from the monotonic clock (ms) to Unix epoch ms, fixed at load time
|
|
81
|
+
const EPOCH_OFFSET_MS = Date.now() - (0, exports.getTimestamp)() / 1000000;
|
|
82
|
+
const MAX_ARG_LENGTH = 50;
|
|
83
|
+
/**
|
|
84
|
+
* Render one captured argument as a short, safe string.
|
|
85
|
+
* Never throws and never walks large structures in full.
|
|
86
|
+
*/
|
|
87
|
+
const formatArg = (arg) => {
|
|
88
|
+
var _a, _b;
|
|
89
|
+
let text;
|
|
90
|
+
try {
|
|
91
|
+
if (typeof arg === 'string') {
|
|
92
|
+
text = JSON.stringify(arg.length > MAX_ARG_LENGTH ? arg.slice(0, MAX_ARG_LENGTH) : arg);
|
|
93
|
+
}
|
|
94
|
+
else if (typeof arg === 'function') {
|
|
95
|
+
text = `[Function ${arg.name || 'anonymous'}]`;
|
|
96
|
+
}
|
|
97
|
+
else if (Array.isArray(arg)) {
|
|
98
|
+
text = `Array(${arg.length})`;
|
|
99
|
+
}
|
|
100
|
+
else if (arg !== null && typeof arg === 'object') {
|
|
101
|
+
const keys = Object.keys(arg);
|
|
102
|
+
if (keys.length <= 5) {
|
|
103
|
+
text = JSON.stringify(arg);
|
|
104
|
+
}
|
|
105
|
+
else {
|
|
106
|
+
const name = ((_a = arg.constructor) === null || _a === void 0 ? void 0 : _a.name) || 'Object';
|
|
107
|
+
text = `${name}{${keys.length} keys}`;
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
else {
|
|
111
|
+
text = String(arg);
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
catch (_c) {
|
|
115
|
+
// circular structures, null prototypes, throwing getters/toJSON, ...
|
|
116
|
+
const name = (_b = arg === null || arg === void 0 ? void 0 : arg.constructor) === null || _b === void 0 ? void 0 : _b.name;
|
|
117
|
+
text = typeof name === 'string' && name ? `[${name}]` : '[object]';
|
|
118
|
+
}
|
|
119
|
+
return text.length > MAX_ARG_LENGTH ? `${text.slice(0, MAX_ARG_LENGTH - 1)}…` : text;
|
|
120
|
+
};
|
|
121
|
+
exports.formatArg = formatArg;
|
|
122
|
+
const loadAsyncLocalStorage = () => {
|
|
123
|
+
var _a, _b;
|
|
124
|
+
return (_b = (_a = (0, env_1.loadNodeBuiltin)('async_hooks')) === null || _a === void 0 ? void 0 : _a.AsyncLocalStorage) !== null && _b !== void 0 ? _b :
|
|
125
|
+
// Edge runtimes (e.g. Next.js Edge) expose it as a global
|
|
126
|
+
(typeof globalThis !== 'undefined' ? globalThis.AsyncLocalStorage : undefined);
|
|
127
|
+
};
|
|
128
|
+
const createExecutionContext = (provided) => {
|
|
129
|
+
const AsyncLocalStorage = provided !== null && provided !== void 0 ? provided : loadAsyncLocalStorage();
|
|
130
|
+
if (AsyncLocalStorage) {
|
|
131
|
+
const storage = new AsyncLocalStorage();
|
|
132
|
+
return {
|
|
133
|
+
current: () => { var _a; return (_a = storage.getStore()) !== null && _a !== void 0 ? _a : null; },
|
|
134
|
+
run: (executionId, fn) => storage.run(executionId, fn),
|
|
135
|
+
// AsyncLocalStorage.run forwards extra arguments to the callback
|
|
136
|
+
apply: (executionId, fn, thisArg, args) => storage.run(executionId, Reflect.apply, fn, thisArg, args)
|
|
137
|
+
};
|
|
138
|
+
}
|
|
139
|
+
let current = null;
|
|
140
|
+
const run = (executionId, fn) => {
|
|
141
|
+
const previous = current;
|
|
142
|
+
current = executionId;
|
|
143
|
+
try {
|
|
144
|
+
return fn();
|
|
145
|
+
}
|
|
146
|
+
finally {
|
|
147
|
+
current = previous;
|
|
148
|
+
}
|
|
149
|
+
};
|
|
150
|
+
return {
|
|
151
|
+
current: () => current,
|
|
152
|
+
run,
|
|
153
|
+
apply: (executionId, fn, thisArg, args) => run(executionId, () => fn.apply(thisArg, args))
|
|
154
|
+
};
|
|
155
|
+
};
|
|
156
|
+
const NOOP_SPAN = {
|
|
157
|
+
id: '',
|
|
158
|
+
setLabel: () => undefined,
|
|
159
|
+
run: (fn) => fn(),
|
|
160
|
+
end: () => undefined
|
|
161
|
+
};
|
|
162
|
+
const clampRate = (rate) => Math.max(0, Math.min(1, rate));
|
|
163
|
+
const isNativePromise = (value) => value !== null && typeof value === 'object' &&
|
|
164
|
+
(value instanceof Promise ||
|
|
165
|
+
(typeof value.then === 'function' && Object.prototype.toString.call(value) === '[object Promise]'));
|
|
72
166
|
/**
|
|
73
167
|
* Optimized tracker for individual function executions
|
|
74
168
|
*/
|
|
@@ -78,25 +172,85 @@ class OptimizedExecutionTracker {
|
|
|
78
172
|
* @param options Tracker configuration options
|
|
79
173
|
*/
|
|
80
174
|
constructor(options = {}) {
|
|
81
|
-
var _a, _b, _c, _d, _e;
|
|
82
|
-
this.executionTree =
|
|
175
|
+
var _a, _b, _c, _d, _e, _f, _g, _h, _j;
|
|
176
|
+
this.executionTree = new Map();
|
|
83
177
|
this.currentExecutionId = 0;
|
|
84
178
|
this.activeExecutions = new Map();
|
|
85
|
-
|
|
86
|
-
this.
|
|
87
|
-
|
|
88
|
-
childPrefix: '├─ ',
|
|
89
|
-
lastChildPrefix: '└─ ',
|
|
90
|
-
linePrefix: '│ ',
|
|
91
|
-
emptyPrefix: ' ',
|
|
92
|
-
errorMarker: '✖ ',
|
|
93
|
-
memoryLabel: '📊 '
|
|
94
|
-
};
|
|
179
|
+
this.plugins = [];
|
|
180
|
+
this.wrappers = [];
|
|
181
|
+
this.failedPlugins = new Set();
|
|
95
182
|
this.showMemoryUsage = (_a = options.showMemoryUsage) !== null && _a !== void 0 ? _a : true;
|
|
96
183
|
this.enableNestedTracking = (_b = options.enableNestedTracking) !== null && _b !== void 0 ? _b : true;
|
|
97
184
|
this.silent = (_c = options.silent) !== null && _c !== void 0 ? _c : false;
|
|
98
185
|
this.trackingMode = (_d = options.trackingMode) !== null && _d !== void 0 ? _d : exports.TrackingModes.BALANCED;
|
|
99
|
-
this.defaultThreshold = (_e = options.threshold) !== null && _e !== void 0 ? _e :
|
|
186
|
+
this.defaultThreshold = (_e = options.threshold) !== null && _e !== void 0 ? _e : 0;
|
|
187
|
+
this.defaultSampleRate = clampRate((_f = options.sampleRate) !== null && _f !== void 0 ? _f : 1);
|
|
188
|
+
this.context = createExecutionContext(options.asyncLocalStorage);
|
|
189
|
+
this.enabled = (_g = options.enabled) !== null && _g !== void 0 ? _g : true;
|
|
190
|
+
this.blockingThreshold = (_h = options.blockingThreshold) !== null && _h !== void 0 ? _h : 50;
|
|
191
|
+
this.reporter = (_j = options.reporter) !== null && _j !== void 0 ? _j : null;
|
|
192
|
+
this.stats = options.stats === false ? null :
|
|
193
|
+
new stats_1.StatsCollector(typeof options.stats === 'object' ? options.stats : {});
|
|
194
|
+
(options.plugins || []).forEach(plugin => this.use(plugin));
|
|
195
|
+
}
|
|
196
|
+
/**
|
|
197
|
+
* Register a plugin. Returns a function that removes it again.
|
|
198
|
+
*/
|
|
199
|
+
use(plugin) {
|
|
200
|
+
this.plugins = [...this.plugins, plugin];
|
|
201
|
+
this.wrappers = this.plugins.filter(p => typeof p.wrap === 'function');
|
|
202
|
+
return () => {
|
|
203
|
+
this.plugins = this.plugins.filter(p => p !== plugin);
|
|
204
|
+
this.wrappers = this.plugins.filter(p => typeof p.wrap === 'function');
|
|
205
|
+
};
|
|
206
|
+
}
|
|
207
|
+
/**
|
|
208
|
+
* Run `run` inside every plugin's wrap() (first registered = outermost).
|
|
209
|
+
* A wrap() that throws before calling run is reported once and skipped.
|
|
210
|
+
*/
|
|
211
|
+
_wrap(execution, run) {
|
|
212
|
+
let next = run;
|
|
213
|
+
for (let i = this.wrappers.length - 1; i >= 0; i--) {
|
|
214
|
+
const plugin = this.wrappers[i];
|
|
215
|
+
const inner = next;
|
|
216
|
+
next = () => {
|
|
217
|
+
let ran = false;
|
|
218
|
+
const once = () => {
|
|
219
|
+
ran = true;
|
|
220
|
+
return inner();
|
|
221
|
+
};
|
|
222
|
+
try {
|
|
223
|
+
return plugin.wrap(execution, once);
|
|
224
|
+
}
|
|
225
|
+
catch (error) {
|
|
226
|
+
if (ran)
|
|
227
|
+
throw error; // the tracked code itself threw
|
|
228
|
+
this._pluginFailed(plugin, 'wrap', error);
|
|
229
|
+
return inner();
|
|
230
|
+
}
|
|
231
|
+
};
|
|
232
|
+
}
|
|
233
|
+
return next();
|
|
234
|
+
}
|
|
235
|
+
_pluginFailed(plugin, hook, error) {
|
|
236
|
+
if (!this.failedPlugins.has(plugin)) {
|
|
237
|
+
this.failedPlugins.add(plugin);
|
|
238
|
+
console.warn(`traceperf: plugin ${plugin.name || '(unnamed)'} threw in ${hook}:`, error);
|
|
239
|
+
}
|
|
240
|
+
}
|
|
241
|
+
_callPlugins(hook, payload) {
|
|
242
|
+
for (const plugin of this.plugins) {
|
|
243
|
+
const fn = plugin[hook];
|
|
244
|
+
if (!fn)
|
|
245
|
+
continue;
|
|
246
|
+
try {
|
|
247
|
+
fn.call(plugin, payload);
|
|
248
|
+
}
|
|
249
|
+
catch (error) {
|
|
250
|
+
// Never let a plugin break the tracked code; warn once per plugin
|
|
251
|
+
this._pluginFailed(plugin, hook, error);
|
|
252
|
+
}
|
|
253
|
+
}
|
|
100
254
|
}
|
|
101
255
|
/**
|
|
102
256
|
* Start timing a function execution
|
|
@@ -105,9 +259,13 @@ class OptimizedExecutionTracker {
|
|
|
105
259
|
* @param options Additional options
|
|
106
260
|
* @returns Execution ID
|
|
107
261
|
*/
|
|
108
|
-
startTimer(label, parentExecutionId = null, options = {}) {
|
|
262
|
+
startTimer(label, parentExecutionId = null, options = {}, args = options.args) {
|
|
263
|
+
var _a, _b, _c, _d;
|
|
264
|
+
// Per-execution settings, falling back to the tracker's current config
|
|
265
|
+
const trackingMode = (_a = options.trackingMode) !== null && _a !== void 0 ? _a : this.trackingMode;
|
|
266
|
+
const trackMemory = (_b = options.trackMemory) !== null && _b !== void 0 ? _b : this.showMemoryUsage;
|
|
109
267
|
// Skip detailed tracking in performance mode
|
|
110
|
-
const collectMemory =
|
|
268
|
+
const collectMemory = trackingMode !== exports.TrackingModes.PERFORMANCE && trackMemory;
|
|
111
269
|
const startTime = (0, exports.getTimestamp)();
|
|
112
270
|
const executionId = (++this.currentExecutionId).toString();
|
|
113
271
|
const execution = {
|
|
@@ -118,9 +276,12 @@ class OptimizedExecutionTracker {
|
|
|
118
276
|
duration: 0,
|
|
119
277
|
parentId: parentExecutionId,
|
|
120
278
|
children: [],
|
|
121
|
-
args: options.captureArgs &&
|
|
122
|
-
Array.from(
|
|
123
|
-
complete: false
|
|
279
|
+
args: options.captureArgs && args ?
|
|
280
|
+
Array.from(args).map(exports.formatArg) : undefined,
|
|
281
|
+
complete: false,
|
|
282
|
+
silent: (_c = options.silent) !== null && _c !== void 0 ? _c : this.silent,
|
|
283
|
+
trackingMode,
|
|
284
|
+
threshold: (_d = options.threshold) !== null && _d !== void 0 ? _d : this.defaultThreshold
|
|
124
285
|
};
|
|
125
286
|
// Collect memory usage if enabled
|
|
126
287
|
if (collectMemory) {
|
|
@@ -137,6 +298,14 @@ class OptimizedExecutionTracker {
|
|
|
137
298
|
}
|
|
138
299
|
// Store in active executions map
|
|
139
300
|
this.activeExecutions.set(executionId, execution);
|
|
301
|
+
if (this.plugins.length > 0) {
|
|
302
|
+
this._callPlugins('onStart', {
|
|
303
|
+
id: executionId,
|
|
304
|
+
label: execution.label,
|
|
305
|
+
parentId: parentExecutionId,
|
|
306
|
+
startEpochMs: EPOCH_OFFSET_MS + startTime / 1000000
|
|
307
|
+
});
|
|
308
|
+
}
|
|
140
309
|
return executionId;
|
|
141
310
|
}
|
|
142
311
|
/**
|
|
@@ -151,69 +320,185 @@ class OptimizedExecutionTracker {
|
|
|
151
320
|
return null;
|
|
152
321
|
}
|
|
153
322
|
const execution = this.activeExecutions.get(executionId);
|
|
323
|
+
this.activeExecutions.delete(executionId);
|
|
154
324
|
execution.endTime = (0, exports.getTimestamp)();
|
|
155
325
|
execution.duration = execution.endTime - execution.startTime;
|
|
156
326
|
execution.result = result;
|
|
157
327
|
execution.error = error;
|
|
158
328
|
execution.complete = true;
|
|
159
|
-
// Only collect memory
|
|
160
|
-
if (
|
|
329
|
+
// Only collect memory if it was collected at start
|
|
330
|
+
if (execution.memoryAtStart !== undefined) {
|
|
161
331
|
execution.memoryAtEnd = (0, exports.getMemoryUsage)();
|
|
162
332
|
execution.memoryDelta = execution.memoryAtEnd - (execution.memoryAtStart || 0);
|
|
163
333
|
}
|
|
164
|
-
//
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
if (
|
|
168
|
-
|
|
169
|
-
|
|
334
|
+
// A child whose parent is still running is reported as part of the
|
|
335
|
+
// parent's tree once the parent finishes.
|
|
336
|
+
const parentRunning = execution.parentId !== null && this.activeExecutions.has(execution.parentId);
|
|
337
|
+
if (parentRunning) {
|
|
338
|
+
this.executionTree.set(executionId, execution);
|
|
339
|
+
return execution;
|
|
340
|
+
}
|
|
341
|
+
// Root (or a child that outlived its parent): build the record tree once
|
|
342
|
+
// and hand it to stats, the console reporter and plugins.
|
|
343
|
+
const record = this._toRecord(execution);
|
|
344
|
+
// Release the finished tree so memory use does not grow with call count
|
|
345
|
+
if (execution.children.length > 0) {
|
|
346
|
+
this._release(execution);
|
|
347
|
+
}
|
|
348
|
+
if (this.stats) {
|
|
349
|
+
this.stats.addTree(record);
|
|
350
|
+
}
|
|
351
|
+
if (!record.silent &&
|
|
352
|
+
record.trackingMode !== exports.TrackingModes.PERFORMANCE &&
|
|
353
|
+
record.duration >= record.threshold) {
|
|
354
|
+
this._report(record);
|
|
355
|
+
}
|
|
356
|
+
if (this.plugins.length > 0) {
|
|
357
|
+
this._callPlugins('onComplete', record);
|
|
170
358
|
}
|
|
171
359
|
return execution;
|
|
172
360
|
}
|
|
173
361
|
/**
|
|
174
|
-
*
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
const
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
for (let i = 0; i < childExecutions.length; i++) {
|
|
211
|
-
const isLast = i === childExecutions.length - 1;
|
|
212
|
-
const childFlowChart = this._generateExecutionFlowChart(childExecutions[i], depth + 1, isLast, [...ancestors, !isLastChild]);
|
|
213
|
-
flowChart += childFlowChart;
|
|
362
|
+
* Drop a finished execution and its finished descendants
|
|
363
|
+
*/
|
|
364
|
+
_release(execution) {
|
|
365
|
+
for (const childId of execution.children) {
|
|
366
|
+
const child = this.executionTree.get(childId);
|
|
367
|
+
if (child) {
|
|
368
|
+
this.executionTree.delete(childId);
|
|
369
|
+
this._release(child);
|
|
370
|
+
}
|
|
371
|
+
}
|
|
372
|
+
}
|
|
373
|
+
/**
|
|
374
|
+
* Mark the end of the synchronous part of an execution that returned a promise
|
|
375
|
+
*/
|
|
376
|
+
markSyncEnd(executionId) {
|
|
377
|
+
const execution = this.activeExecutions.get(executionId);
|
|
378
|
+
if (execution) {
|
|
379
|
+
execution.syncEndTime = (0, exports.getTimestamp)();
|
|
380
|
+
}
|
|
381
|
+
}
|
|
382
|
+
/**
|
|
383
|
+
* Convert a finished execution (and its finished children) to a record tree
|
|
384
|
+
*/
|
|
385
|
+
_toRecord(execution) {
|
|
386
|
+
var _a, _b, _c;
|
|
387
|
+
const startTime = execution.startTime / 1000000;
|
|
388
|
+
const endTime = execution.endTime / 1000000;
|
|
389
|
+
const duration = execution.duration / 1000000;
|
|
390
|
+
const children = [];
|
|
391
|
+
let covered = 0;
|
|
392
|
+
if (execution.children.length > 0) {
|
|
393
|
+
for (const childId of execution.children) {
|
|
394
|
+
const child = this.executionTree.get(childId);
|
|
395
|
+
if (child) {
|
|
396
|
+
children.push(this._toRecord(child));
|
|
397
|
+
}
|
|
214
398
|
}
|
|
399
|
+
covered = (0, records_1.coveredLength)(children.map(c => [Math.max(c.startTime, startTime), Math.min(c.endTime, endTime)]));
|
|
400
|
+
}
|
|
401
|
+
const isAsync = execution.syncEndTime !== undefined;
|
|
402
|
+
const record = {
|
|
403
|
+
id: execution.id,
|
|
404
|
+
label: execution.label,
|
|
405
|
+
parentId: execution.parentId,
|
|
406
|
+
startTime,
|
|
407
|
+
endTime,
|
|
408
|
+
startEpochMs: EPOCH_OFFSET_MS + startTime,
|
|
409
|
+
duration,
|
|
410
|
+
selfDuration: Math.max(0, duration - covered),
|
|
411
|
+
syncDuration: isAsync ? (execution.syncEndTime - execution.startTime) / 1000000 : duration,
|
|
412
|
+
async: isAsync,
|
|
413
|
+
children,
|
|
414
|
+
threshold: (_a = execution.threshold) !== null && _a !== void 0 ? _a : 0,
|
|
415
|
+
trackingMode: (_b = execution.trackingMode) !== null && _b !== void 0 ? _b : this.trackingMode,
|
|
416
|
+
silent: (_c = execution.silent) !== null && _c !== void 0 ? _c : this.silent,
|
|
417
|
+
};
|
|
418
|
+
if (execution.memoryAtStart !== undefined && execution.memoryDelta !== undefined) {
|
|
419
|
+
record.memoryDelta = execution.memoryDelta;
|
|
420
|
+
}
|
|
421
|
+
if (execution.error !== null && execution.error !== undefined) {
|
|
422
|
+
record.error = execution.error;
|
|
423
|
+
}
|
|
424
|
+
if (execution.args && execution.args.length > 0) {
|
|
425
|
+
record.args = execution.args;
|
|
215
426
|
}
|
|
216
|
-
return
|
|
427
|
+
return record;
|
|
428
|
+
}
|
|
429
|
+
/**
|
|
430
|
+
* Print a finished tree (or hand it to the custom reporter)
|
|
431
|
+
*/
|
|
432
|
+
_report(record) {
|
|
433
|
+
if (this.reporter) {
|
|
434
|
+
this.reporter(record);
|
|
435
|
+
return;
|
|
436
|
+
}
|
|
437
|
+
const detailed = record.trackingMode === exports.TrackingModes.DETAILED || record.trackingMode === exports.TrackingModes.DEBUG;
|
|
438
|
+
console.log((0, records_1.formatTree)(record, {
|
|
439
|
+
detailed,
|
|
440
|
+
showErrors: detailed,
|
|
441
|
+
blockingThreshold: this.blockingThreshold
|
|
442
|
+
}));
|
|
443
|
+
}
|
|
444
|
+
/**
|
|
445
|
+
* Run one call of `fn` with tracking (shared by createTrackable and track)
|
|
446
|
+
*/
|
|
447
|
+
_invoke(fn, thisArg, args, options, label) {
|
|
448
|
+
// Disabled: call straight through
|
|
449
|
+
if (!this.enabled) {
|
|
450
|
+
return fn.apply(thisArg, args);
|
|
451
|
+
}
|
|
452
|
+
// Apply sampling - randomly decide whether to track this call
|
|
453
|
+
const sampleRate = options.sampleRate !== undefined ?
|
|
454
|
+
clampRate(options.sampleRate) : this.defaultSampleRate;
|
|
455
|
+
const shouldSample = Math.random() < sampleRate;
|
|
456
|
+
// If not sampling this call, just execute the function directly
|
|
457
|
+
if (!shouldSample) {
|
|
458
|
+
return fn.apply(thisArg, args);
|
|
459
|
+
}
|
|
460
|
+
const nested = this.enableNestedTracking && options.enableNestedTracking !== false;
|
|
461
|
+
const explicitParentId = options.parentExecutionId || null;
|
|
462
|
+
const parentExecutionId = explicitParentId !== null && explicitParentId !== void 0 ? explicitParentId : (nested ? this.context.current() : null);
|
|
463
|
+
// Start tracking the execution
|
|
464
|
+
// The options object already has the TimerOptions fields; pass it as is
|
|
465
|
+
const executionId = this.startTimer(label, parentExecutionId, options, args);
|
|
466
|
+
let result;
|
|
467
|
+
try {
|
|
468
|
+
// Execute the function with the caller's `this`, as the current
|
|
469
|
+
// execution so nested tracked calls attach to it
|
|
470
|
+
if (this.wrappers.length > 0) {
|
|
471
|
+
result = this._wrap({ id: executionId, label, parentId: parentExecutionId }, () => (nested ?
|
|
472
|
+
this.context.apply(executionId, fn, thisArg, args) :
|
|
473
|
+
fn.apply(thisArg, args)));
|
|
474
|
+
}
|
|
475
|
+
else {
|
|
476
|
+
result = nested ?
|
|
477
|
+
this.context.apply(executionId, fn, thisArg, args) :
|
|
478
|
+
fn.apply(thisArg, args);
|
|
479
|
+
}
|
|
480
|
+
}
|
|
481
|
+
catch (error) {
|
|
482
|
+
// Handle synchronous errors
|
|
483
|
+
this.endTimer(executionId, undefined, error);
|
|
484
|
+
throw error; // Re-throw to preserve error behavior
|
|
485
|
+
}
|
|
486
|
+
// Native promises (incl. async functions): time until settled.
|
|
487
|
+
// Other thenables are returned untouched - calling their then() could
|
|
488
|
+
// trigger side effects (e.g. query builders) or change their type.
|
|
489
|
+
if (isNativePromise(result)) {
|
|
490
|
+
this.markSyncEnd(executionId);
|
|
491
|
+
return result.then((resolvedValue) => {
|
|
492
|
+
this.endTimer(executionId, resolvedValue);
|
|
493
|
+
return resolvedValue;
|
|
494
|
+
}, (error) => {
|
|
495
|
+
this.endTimer(executionId, undefined, error);
|
|
496
|
+
throw error; // Re-throw to preserve error behavior
|
|
497
|
+
});
|
|
498
|
+
}
|
|
499
|
+
// Handle synchronous functions
|
|
500
|
+
this.endTimer(executionId, result);
|
|
501
|
+
return result;
|
|
217
502
|
}
|
|
218
503
|
/**
|
|
219
504
|
* Create a trackable version of a function
|
|
@@ -222,65 +507,80 @@ class OptimizedExecutionTracker {
|
|
|
222
507
|
* @returns Tracked version of the function
|
|
223
508
|
*/
|
|
224
509
|
createTrackable(fn, options = {}) {
|
|
510
|
+
var _a;
|
|
225
511
|
if (typeof fn !== 'function') {
|
|
226
512
|
throw new Error('First argument must be a function');
|
|
227
513
|
}
|
|
228
514
|
const label = options.label || fn.name || 'anonymous';
|
|
229
|
-
const
|
|
230
|
-
const silent = options.hasOwnProperty('silent') ? options.silent : this.silent;
|
|
515
|
+
const silent = (_a = options.silent) !== null && _a !== void 0 ? _a : this.silent;
|
|
231
516
|
const trackingMode = options.trackingMode || this.trackingMode;
|
|
232
|
-
const sampleRate = options.hasOwnProperty('sampleRate') ?
|
|
233
|
-
Math.max(0, Math.min(1, options.sampleRate)) : 1.0;
|
|
234
517
|
// Performance optimization - if in performance mode and silent, return original function
|
|
235
518
|
if (trackingMode === exports.TrackingModes.PERFORMANCE &&
|
|
236
|
-
|
|
519
|
+
silent &&
|
|
237
520
|
!this.enableNestedTracking) {
|
|
238
521
|
return fn;
|
|
239
522
|
}
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
// If not sampling this call, just execute the function directly
|
|
245
|
-
if (!shouldSample) {
|
|
246
|
-
return fn.apply(this, args);
|
|
247
|
-
}
|
|
248
|
-
// Start tracking the execution
|
|
249
|
-
const executionId = this.startTimer(label, parentExecutionId, {
|
|
250
|
-
trackMemory: options.trackMemory !== undefined ? options.trackMemory : this.showMemoryUsage,
|
|
251
|
-
captureArgs: options.captureArgs,
|
|
252
|
-
args: args
|
|
253
|
-
});
|
|
254
|
-
try {
|
|
255
|
-
// Execute the function with correct this context
|
|
256
|
-
const result = fn.apply(this, args);
|
|
257
|
-
// Handle promises
|
|
258
|
-
if (result && typeof result.then === 'function') {
|
|
259
|
-
return result
|
|
260
|
-
.then((resolvedValue) => {
|
|
261
|
-
this.endTimer(executionId, resolvedValue);
|
|
262
|
-
return resolvedValue;
|
|
263
|
-
})
|
|
264
|
-
.catch((error) => {
|
|
265
|
-
this.endTimer(executionId, undefined, error);
|
|
266
|
-
throw error; // Re-throw to preserve error behavior
|
|
267
|
-
});
|
|
268
|
-
}
|
|
269
|
-
// Handle synchronous functions
|
|
270
|
-
this.endTimer(executionId, result);
|
|
271
|
-
return result;
|
|
272
|
-
}
|
|
273
|
-
catch (error) {
|
|
274
|
-
// Handle synchronous errors
|
|
275
|
-
this.endTimer(executionId, undefined, error);
|
|
276
|
-
throw error; // Re-throw to preserve error behavior
|
|
277
|
-
}
|
|
523
|
+
const invoke = (thisArg, args) => this._invoke(fn, thisArg, args, options, label);
|
|
524
|
+
// A regular function (not an arrow) so callers keep their own `this`
|
|
525
|
+
const trackedFn = function (...args) {
|
|
526
|
+
return invoke(this, args);
|
|
278
527
|
};
|
|
279
528
|
// Preserve function properties
|
|
280
529
|
Object.defineProperty(trackedFn, 'name', { value: fn.name, configurable: true });
|
|
281
530
|
Object.defineProperty(trackedFn, 'length', { value: fn.length });
|
|
282
531
|
return trackedFn;
|
|
283
532
|
}
|
|
533
|
+
/**
|
|
534
|
+
* Start a manually-ended execution (a "span"). Use `run()` to execute code
|
|
535
|
+
* as part of it, so tracked calls inside attach as children, and `end()`
|
|
536
|
+
* when the work is finished.
|
|
537
|
+
*/
|
|
538
|
+
startSpan(label, options = {}) {
|
|
539
|
+
if (!this.enabled) {
|
|
540
|
+
return NOOP_SPAN;
|
|
541
|
+
}
|
|
542
|
+
const sampleRate = options.sampleRate !== undefined ? clampRate(options.sampleRate) : this.defaultSampleRate;
|
|
543
|
+
if (!(Math.random() < sampleRate)) {
|
|
544
|
+
return NOOP_SPAN;
|
|
545
|
+
}
|
|
546
|
+
const nested = this.enableNestedTracking && options.enableNestedTracking !== false;
|
|
547
|
+
const explicitParentId = options.parentExecutionId || null;
|
|
548
|
+
const parentExecutionId = explicitParentId !== null && explicitParentId !== void 0 ? explicitParentId : (nested ? this.context.current() : null);
|
|
549
|
+
const executionId = this.startTimer(label || 'anonymous', parentExecutionId, {
|
|
550
|
+
trackMemory: options.trackMemory,
|
|
551
|
+
silent: options.silent,
|
|
552
|
+
trackingMode: options.trackingMode,
|
|
553
|
+
threshold: options.threshold
|
|
554
|
+
});
|
|
555
|
+
let ended = false;
|
|
556
|
+
return {
|
|
557
|
+
id: executionId,
|
|
558
|
+
setLabel: (newLabel) => {
|
|
559
|
+
const execution = this.activeExecutions.get(executionId);
|
|
560
|
+
if (execution && newLabel) {
|
|
561
|
+
execution.label = newLabel;
|
|
562
|
+
}
|
|
563
|
+
},
|
|
564
|
+
run: (fn) => {
|
|
565
|
+
const runInContext = () => (nested ? this.context.run(executionId, fn) : fn());
|
|
566
|
+
const result = this.wrappers.length > 0 ?
|
|
567
|
+
this._wrap({ id: executionId, label: label || 'anonymous', parentId: parentExecutionId }, runInContext) :
|
|
568
|
+
runInContext();
|
|
569
|
+
// The span's synchronous part ends when its first run() returns
|
|
570
|
+
const execution = this.activeExecutions.get(executionId);
|
|
571
|
+
if (execution && execution.syncEndTime === undefined) {
|
|
572
|
+
execution.syncEndTime = (0, exports.getTimestamp)();
|
|
573
|
+
}
|
|
574
|
+
return result;
|
|
575
|
+
},
|
|
576
|
+
end: (error) => {
|
|
577
|
+
if (ended)
|
|
578
|
+
return;
|
|
579
|
+
ended = true;
|
|
580
|
+
this.endTimer(executionId, undefined, (error !== null && error !== void 0 ? error : null));
|
|
581
|
+
}
|
|
582
|
+
};
|
|
583
|
+
}
|
|
284
584
|
/**
|
|
285
585
|
* Track a module's methods
|
|
286
586
|
* @param module Module to track
|
|
@@ -288,6 +588,7 @@ class OptimizedExecutionTracker {
|
|
|
288
588
|
* @returns Tracked module
|
|
289
589
|
*/
|
|
290
590
|
trackModule(module, options = {}) {
|
|
591
|
+
var _a;
|
|
291
592
|
if (!module || typeof module !== 'object') {
|
|
292
593
|
throw new Error('Module must be an object');
|
|
293
594
|
}
|
|
@@ -295,7 +596,7 @@ class OptimizedExecutionTracker {
|
|
|
295
596
|
const trackingMode = options.trackingMode || this.trackingMode;
|
|
296
597
|
// Performance optimization - if in performance mode and silent, return original module
|
|
297
598
|
if (trackingMode === exports.TrackingModes.PERFORMANCE &&
|
|
298
|
-
(options.silent
|
|
599
|
+
((_a = options.silent) !== null && _a !== void 0 ? _a : this.silent) &&
|
|
299
600
|
!this.enableNestedTracking) {
|
|
300
601
|
return module;
|
|
301
602
|
}
|
|
@@ -328,17 +629,29 @@ class OptimizedExecutionTracker {
|
|
|
328
629
|
* @returns Function result
|
|
329
630
|
*/
|
|
330
631
|
track(fn, options = {}) {
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
632
|
+
var _a;
|
|
633
|
+
if (typeof fn !== 'function') {
|
|
634
|
+
throw new Error('First argument must be a function');
|
|
635
|
+
}
|
|
636
|
+
// Same fast path as createTrackable, without building a wrapper per call
|
|
637
|
+
if ((options.trackingMode || this.trackingMode) === exports.TrackingModes.PERFORMANCE &&
|
|
638
|
+
((_a = options.silent) !== null && _a !== void 0 ? _a : this.silent) &&
|
|
639
|
+
!this.enableNestedTracking) {
|
|
640
|
+
return fn.apply(options.thisContext, options.args || []);
|
|
641
|
+
}
|
|
642
|
+
const label = options.label || fn.name || 'anonymous';
|
|
643
|
+
return this._invoke(fn, options.thisContext, (options.args || []), options, label);
|
|
334
644
|
}
|
|
335
645
|
/**
|
|
336
646
|
* Reset the tracker state
|
|
337
647
|
*/
|
|
338
648
|
reset() {
|
|
339
|
-
this.executionTree =
|
|
649
|
+
this.executionTree = new Map();
|
|
340
650
|
this.currentExecutionId = 0;
|
|
341
651
|
this.activeExecutions = new Map();
|
|
652
|
+
if (this.stats) {
|
|
653
|
+
this.stats.reset();
|
|
654
|
+
}
|
|
342
655
|
}
|
|
343
656
|
}
|
|
344
657
|
exports.OptimizedExecutionTracker = OptimizedExecutionTracker;
|
|
@@ -351,22 +664,34 @@ class OptimizedPerformanceMonitor {
|
|
|
351
664
|
* @param options Configuration options
|
|
352
665
|
*/
|
|
353
666
|
constructor(options = {}) {
|
|
667
|
+
var _a, _b, _c;
|
|
354
668
|
this.config = {
|
|
355
669
|
trackingMode: options.trackingMode || DEFAULT_TRACKING_MODE,
|
|
356
670
|
silent: options.silent || false,
|
|
357
671
|
trackMemory: options.trackMemory !== undefined ? options.trackMemory : true,
|
|
358
672
|
enableNestedTracking: options.enableNestedTracking !== undefined ? options.enableNestedTracking : true,
|
|
359
|
-
threshold: options.threshold
|
|
360
|
-
sampleRate: options.sampleRate !== undefined ?
|
|
361
|
-
|
|
673
|
+
threshold: (_a = options.threshold) !== null && _a !== void 0 ? _a : 0,
|
|
674
|
+
sampleRate: options.sampleRate !== undefined ? clampRate(options.sampleRate) : 1.0,
|
|
675
|
+
enabled: (_b = options.enabled) !== null && _b !== void 0 ? _b : true,
|
|
676
|
+
blockingThreshold: (_c = options.blockingThreshold) !== null && _c !== void 0 ? _c : 50
|
|
362
677
|
};
|
|
363
678
|
this.executionTracker = new OptimizedExecutionTracker({
|
|
364
679
|
trackingMode: this.config.trackingMode,
|
|
365
680
|
silent: this.config.silent,
|
|
366
681
|
showMemoryUsage: this.config.trackMemory,
|
|
367
682
|
enableNestedTracking: this.config.enableNestedTracking,
|
|
368
|
-
threshold: this.config.threshold
|
|
683
|
+
threshold: this.config.threshold,
|
|
684
|
+
sampleRate: this.config.sampleRate,
|
|
685
|
+
enabled: this.config.enabled,
|
|
686
|
+
blockingThreshold: this.config.blockingThreshold,
|
|
687
|
+
stats: options.stats,
|
|
688
|
+
reporter: options.reporter,
|
|
689
|
+
plugins: options.plugins,
|
|
690
|
+
asyncLocalStorage: options.asyncLocalStorage
|
|
369
691
|
});
|
|
692
|
+
if (options.onComplete) {
|
|
693
|
+
this.onComplete(options.onComplete);
|
|
694
|
+
}
|
|
370
695
|
}
|
|
371
696
|
/**
|
|
372
697
|
* Track a function execution
|
|
@@ -378,20 +703,9 @@ class OptimizedPerformanceMonitor {
|
|
|
378
703
|
if (typeof fn !== 'function') {
|
|
379
704
|
throw new Error('First argument must be a function');
|
|
380
705
|
}
|
|
381
|
-
//
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
trackingMode: options.trackingMode || this.config.trackingMode,
|
|
385
|
-
silent: options.hasOwnProperty('silent') ? options.silent : this.config.silent,
|
|
386
|
-
trackMemory: options.hasOwnProperty('trackMemory') ? options.trackMemory : this.config.trackMemory,
|
|
387
|
-
sampleRate: options.hasOwnProperty('sampleRate') ? options.sampleRate : this.config.sampleRate,
|
|
388
|
-
captureArgs: options.hasOwnProperty('captureArgs') ? options.captureArgs : false,
|
|
389
|
-
parentExecutionId: options.parentExecutionId || null,
|
|
390
|
-
thisContext: options.thisContext,
|
|
391
|
-
args: options.args
|
|
392
|
-
};
|
|
393
|
-
// Use the tracker to directly track the function
|
|
394
|
-
return this.executionTracker.track(fn, trackingOptions);
|
|
706
|
+
// Only per-call options are passed down; anything left out falls back to
|
|
707
|
+
// this instance's *current* configuration when the call runs.
|
|
708
|
+
return this.executionTracker.track(fn, options);
|
|
395
709
|
}
|
|
396
710
|
/**
|
|
397
711
|
* Create a trackable version of a function
|
|
@@ -403,17 +717,7 @@ class OptimizedPerformanceMonitor {
|
|
|
403
717
|
if (typeof fn !== 'function') {
|
|
404
718
|
throw new Error('First argument must be a function');
|
|
405
719
|
}
|
|
406
|
-
|
|
407
|
-
const trackingOptions = {
|
|
408
|
-
label: options.label || fn.name || 'anonymous',
|
|
409
|
-
trackingMode: options.trackingMode || this.config.trackingMode,
|
|
410
|
-
silent: options.hasOwnProperty('silent') ? options.silent : this.config.silent,
|
|
411
|
-
trackMemory: options.hasOwnProperty('trackMemory') ? options.trackMemory : this.config.trackMemory,
|
|
412
|
-
sampleRate: options.hasOwnProperty('sampleRate') ? options.sampleRate : this.config.sampleRate,
|
|
413
|
-
captureArgs: options.hasOwnProperty('captureArgs') ? options.captureArgs : false,
|
|
414
|
-
parentExecutionId: options.parentExecutionId || null
|
|
415
|
-
};
|
|
416
|
-
return this.executionTracker.createTrackable(fn, trackingOptions);
|
|
720
|
+
return this.executionTracker.createTrackable(fn, options);
|
|
417
721
|
}
|
|
418
722
|
/**
|
|
419
723
|
* Register a module for tracking
|
|
@@ -425,16 +729,201 @@ class OptimizedPerformanceMonitor {
|
|
|
425
729
|
if (!module || typeof module !== 'object') {
|
|
426
730
|
throw new Error('Module must be an object');
|
|
427
731
|
}
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
732
|
+
return this.executionTracker.trackModule(module, options);
|
|
733
|
+
}
|
|
734
|
+
/**
|
|
735
|
+
* Track every method of an object or class instance, including methods
|
|
736
|
+
* inherited from its prototype, without copying it. Returns a proxy:
|
|
737
|
+
* state changes go to the original object, and methods run with the
|
|
738
|
+
* original object as `this` (so private #fields keep working).
|
|
739
|
+
*/
|
|
740
|
+
trackObject(target, options = {}) {
|
|
741
|
+
var _a;
|
|
742
|
+
if (!target || (typeof target !== 'object' && typeof target !== 'function')) {
|
|
743
|
+
throw new Error('trackObject expects an object');
|
|
744
|
+
}
|
|
745
|
+
const ctorName = target.constructor && target.constructor !== Object
|
|
746
|
+
? target.constructor.name : '';
|
|
747
|
+
const prefix = (_a = options.prefix) !== null && _a !== void 0 ? _a : (ctorName ? `${ctorName}.` : '');
|
|
748
|
+
const trackOptions = { ...options };
|
|
749
|
+
delete trackOptions.prefix;
|
|
750
|
+
const cache = new Map();
|
|
751
|
+
const wrap = (original, key, proxy) => {
|
|
752
|
+
var _a;
|
|
753
|
+
const tracked = this.createTrackable(original, {
|
|
754
|
+
...trackOptions,
|
|
755
|
+
label: (_a = trackOptions.label) !== null && _a !== void 0 ? _a : `${prefix}${key}`
|
|
756
|
+
});
|
|
757
|
+
return function (...args) {
|
|
758
|
+
return tracked.apply(this === proxy ? target : this, args);
|
|
759
|
+
};
|
|
436
760
|
};
|
|
437
|
-
|
|
761
|
+
const proxy = new Proxy(target, {
|
|
762
|
+
get: (obj, key, receiver) => {
|
|
763
|
+
const value = Reflect.get(obj, key, receiver);
|
|
764
|
+
if (typeof value !== 'function' || typeof key === 'symbol' || key === 'constructor' ||
|
|
765
|
+
Object.prototype[key] === value) {
|
|
766
|
+
return value;
|
|
767
|
+
}
|
|
768
|
+
const hit = cache.get(key);
|
|
769
|
+
if (hit && hit.original === value) {
|
|
770
|
+
return hit.tracked;
|
|
771
|
+
}
|
|
772
|
+
const tracked = wrap(value, key, proxy);
|
|
773
|
+
cache.set(key, { original: value, tracked });
|
|
774
|
+
return tracked;
|
|
775
|
+
}
|
|
776
|
+
});
|
|
777
|
+
return proxy;
|
|
778
|
+
}
|
|
779
|
+
/**
|
|
780
|
+
* Method decorator. Works with TypeScript 5 / TC39 standard decorators and
|
|
781
|
+
* with legacy `experimentalDecorators`. The label defaults to
|
|
782
|
+
* "ClassName.method".
|
|
783
|
+
*
|
|
784
|
+
* class UserService {
|
|
785
|
+
* @tp.traced()
|
|
786
|
+
* async getUser(id: string) { ... }
|
|
787
|
+
* }
|
|
788
|
+
*/
|
|
789
|
+
traced(options = {}) {
|
|
790
|
+
const trackables = new Map();
|
|
791
|
+
const trackedFor = (fn, label) => {
|
|
792
|
+
let tracked = trackables.get(label);
|
|
793
|
+
if (!tracked) {
|
|
794
|
+
tracked = this.createTrackable(fn, { ...options, label });
|
|
795
|
+
trackables.set(label, tracked);
|
|
796
|
+
}
|
|
797
|
+
return tracked;
|
|
798
|
+
};
|
|
799
|
+
const ownerName = (receiver) => { var _a; return typeof receiver === 'function' ? receiver.name : ((_a = receiver === null || receiver === void 0 ? void 0 : receiver.constructor) === null || _a === void 0 ? void 0 : _a.name) || 'anonymous'; };
|
|
800
|
+
const wrapMethod = (fn, methodName) => {
|
|
801
|
+
const wrapped = function (...args) {
|
|
802
|
+
var _a;
|
|
803
|
+
const label = (_a = options.label) !== null && _a !== void 0 ? _a : `${ownerName(this)}.${methodName}`;
|
|
804
|
+
return trackedFor(fn, label).apply(this, args);
|
|
805
|
+
};
|
|
806
|
+
Object.defineProperty(wrapped, 'name', { value: fn.name, configurable: true });
|
|
807
|
+
Object.defineProperty(wrapped, 'length', { value: fn.length, configurable: true });
|
|
808
|
+
return wrapped;
|
|
809
|
+
};
|
|
810
|
+
return (target, context, descriptor) => {
|
|
811
|
+
// Standard decorators: (method, context)
|
|
812
|
+
if (typeof target === 'function' && context && typeof context === 'object' && 'kind' in context) {
|
|
813
|
+
if (context.kind !== 'method') {
|
|
814
|
+
throw new TypeError('@traced can only decorate methods');
|
|
815
|
+
}
|
|
816
|
+
return wrapMethod(target, String(context.name));
|
|
817
|
+
}
|
|
818
|
+
// Legacy decorators: (prototype or constructor, key, descriptor)
|
|
819
|
+
if (descriptor && typeof descriptor.value === 'function') {
|
|
820
|
+
descriptor.value = wrapMethod(descriptor.value, String(context));
|
|
821
|
+
return descriptor;
|
|
822
|
+
}
|
|
823
|
+
throw new TypeError('@traced can only decorate methods');
|
|
824
|
+
};
|
|
825
|
+
}
|
|
826
|
+
/**
|
|
827
|
+
* Start a manually-ended execution (a span), e.g. for a request:
|
|
828
|
+
*
|
|
829
|
+
* const span = tp.start('GET /users');
|
|
830
|
+
* span.run(() => next()); // tracked calls inside become children
|
|
831
|
+
* res.on('finish', () => span.end());
|
|
832
|
+
*/
|
|
833
|
+
start(label, options = {}) {
|
|
834
|
+
return this.executionTracker.startSpan(label, options);
|
|
835
|
+
}
|
|
836
|
+
/**
|
|
837
|
+
* Register a plugin (exporter, custom sink). Returns an unsubscribe function.
|
|
838
|
+
*/
|
|
839
|
+
use(plugin) {
|
|
840
|
+
return this.executionTracker.use(plugin);
|
|
841
|
+
}
|
|
842
|
+
/**
|
|
843
|
+
* Call `listener` with every finished top-level execution tree (even when
|
|
844
|
+
* silent or below threshold). Returns an unsubscribe function.
|
|
845
|
+
*/
|
|
846
|
+
onComplete(listener) {
|
|
847
|
+
return this.use({ name: 'onComplete', onComplete: listener });
|
|
848
|
+
}
|
|
849
|
+
/**
|
|
850
|
+
* Call `listener` for every finished call (nested ones included) that
|
|
851
|
+
* took at least `threshold` ms. Pass a number, or per-label thresholds
|
|
852
|
+
* with an optional '*' default:
|
|
853
|
+
*
|
|
854
|
+
* tp.onSlow(200, (call, root) => logger.warn(`${call.label} took ${call.duration}ms in ${root.label}`));
|
|
855
|
+
* tp.onSlow({ 'db.query': 50, 'GET /search': 500, '*': 1000 }, alert);
|
|
856
|
+
*
|
|
857
|
+
* Works in every tracking mode and when silent. Returns an unsubscribe function.
|
|
858
|
+
*/
|
|
859
|
+
onSlow(threshold, listener) {
|
|
860
|
+
const limitFor = typeof threshold === 'number'
|
|
861
|
+
? () => threshold
|
|
862
|
+
: (label) => (label in threshold ? threshold[label] : threshold['*']);
|
|
863
|
+
return this.use({
|
|
864
|
+
name: 'onSlow',
|
|
865
|
+
onComplete: root => {
|
|
866
|
+
(0, records_1.walkRecords)(root, record => {
|
|
867
|
+
const limit = limitFor(record.label);
|
|
868
|
+
if (limit !== undefined && record.duration >= limit)
|
|
869
|
+
listener(record, root);
|
|
870
|
+
});
|
|
871
|
+
}
|
|
872
|
+
});
|
|
873
|
+
}
|
|
874
|
+
getStats(label) {
|
|
875
|
+
const stats = this.executionTracker.stats;
|
|
876
|
+
if (label !== undefined) {
|
|
877
|
+
return stats ? stats.get(label) : undefined;
|
|
878
|
+
}
|
|
879
|
+
return stats ? stats.all() : {};
|
|
880
|
+
}
|
|
881
|
+
/** Clear collected statistics */
|
|
882
|
+
resetStats() {
|
|
883
|
+
if (this.executionTracker.stats) {
|
|
884
|
+
this.executionTracker.stats.reset();
|
|
885
|
+
}
|
|
886
|
+
return this;
|
|
887
|
+
}
|
|
888
|
+
/** Statistics as a text table, slowest total first */
|
|
889
|
+
formatStats() {
|
|
890
|
+
return (0, stats_1.formatStatsTable)(this.getStats());
|
|
891
|
+
}
|
|
892
|
+
/** Print the statistics table to the console */
|
|
893
|
+
printStats() {
|
|
894
|
+
console.log(this.formatStats());
|
|
895
|
+
return this;
|
|
896
|
+
}
|
|
897
|
+
/**
|
|
898
|
+
* Start recording finished calls for a Chrome/Perfetto trace.
|
|
899
|
+
*
|
|
900
|
+
* const recording = tp.startTrace();
|
|
901
|
+
* await work();
|
|
902
|
+
* fs.writeFileSync('trace.json', JSON.stringify(recording.stop()));
|
|
903
|
+
*
|
|
904
|
+
* Open the file in https://ui.perfetto.dev or chrome://tracing.
|
|
905
|
+
*/
|
|
906
|
+
startTrace(options = {}) {
|
|
907
|
+
let unsubscribe = () => undefined;
|
|
908
|
+
const recorder = (0, exporters_1.createTraceRecorder)({ maxRoots: options.maxRoots, onStop: () => unsubscribe() });
|
|
909
|
+
unsubscribe = this.use(recorder);
|
|
910
|
+
return recorder;
|
|
911
|
+
}
|
|
912
|
+
/** Turn tracking on */
|
|
913
|
+
enable() {
|
|
914
|
+
this.config.enabled = true;
|
|
915
|
+
this.executionTracker.enabled = true;
|
|
916
|
+
return this;
|
|
917
|
+
}
|
|
918
|
+
/** Turn tracking off: tracked functions become plain pass-through calls */
|
|
919
|
+
disable() {
|
|
920
|
+
this.config.enabled = false;
|
|
921
|
+
this.executionTracker.enabled = false;
|
|
922
|
+
return this;
|
|
923
|
+
}
|
|
924
|
+
/** Whether tracking is on */
|
|
925
|
+
isEnabled() {
|
|
926
|
+
return this.config.enabled;
|
|
438
927
|
}
|
|
439
928
|
/**
|
|
440
929
|
* Set configuration options
|
|
@@ -469,7 +958,25 @@ class OptimizedPerformanceMonitor {
|
|
|
469
958
|
}
|
|
470
959
|
// Update sampleRate if specified
|
|
471
960
|
if (config.sampleRate !== undefined) {
|
|
472
|
-
this.config.sampleRate =
|
|
961
|
+
this.config.sampleRate = clampRate(config.sampleRate);
|
|
962
|
+
this.executionTracker.defaultSampleRate = this.config.sampleRate;
|
|
963
|
+
}
|
|
964
|
+
if (config.enabled !== undefined) {
|
|
965
|
+
this.config.enabled = config.enabled;
|
|
966
|
+
this.executionTracker.enabled = config.enabled;
|
|
967
|
+
}
|
|
968
|
+
if (config.blockingThreshold !== undefined) {
|
|
969
|
+
this.config.blockingThreshold = config.blockingThreshold;
|
|
970
|
+
this.executionTracker.blockingThreshold = config.blockingThreshold;
|
|
971
|
+
}
|
|
972
|
+
if (config.reporter !== undefined) {
|
|
973
|
+
this.executionTracker.reporter = config.reporter;
|
|
974
|
+
}
|
|
975
|
+
if (config.plugins) {
|
|
976
|
+
config.plugins.forEach(plugin => this.use(plugin));
|
|
977
|
+
}
|
|
978
|
+
if (config.onComplete) {
|
|
979
|
+
this.onComplete(config.onComplete);
|
|
473
980
|
}
|
|
474
981
|
return { ...this.config };
|
|
475
982
|
}
|
|
@@ -501,6 +1008,12 @@ class OptimizedPerformanceMonitor {
|
|
|
501
1008
|
this.executionTracker.trackingMode = mode;
|
|
502
1009
|
return this;
|
|
503
1010
|
}
|
|
1011
|
+
/**
|
|
1012
|
+
* Get the current tracking mode
|
|
1013
|
+
*/
|
|
1014
|
+
getTrackingMode() {
|
|
1015
|
+
return this.config.trackingMode;
|
|
1016
|
+
}
|
|
504
1017
|
/**
|
|
505
1018
|
* Enable memory usage tracking
|
|
506
1019
|
* @returns This instance for chaining
|
|
@@ -525,11 +1038,12 @@ class OptimizedPerformanceMonitor {
|
|
|
525
1038
|
* @returns This instance for chaining
|
|
526
1039
|
*/
|
|
527
1040
|
setSampleRate(rate) {
|
|
528
|
-
this.config.sampleRate =
|
|
1041
|
+
this.config.sampleRate = clampRate(rate);
|
|
1042
|
+
this.executionTracker.defaultSampleRate = this.config.sampleRate;
|
|
529
1043
|
return this;
|
|
530
1044
|
}
|
|
531
1045
|
/**
|
|
532
|
-
* Reset the tracker state
|
|
1046
|
+
* Reset the tracker state (in-flight executions and statistics)
|
|
533
1047
|
* @returns This instance for chaining
|
|
534
1048
|
*/
|
|
535
1049
|
reset() {
|
|
@@ -538,6 +1052,4 @@ class OptimizedPerformanceMonitor {
|
|
|
538
1052
|
}
|
|
539
1053
|
}
|
|
540
1054
|
exports.OptimizedPerformanceMonitor = OptimizedPerformanceMonitor;
|
|
541
|
-
// Remove singleton instance to avoid circular dependency - it will be created in index.ts
|
|
542
|
-
// export const optimizedTracePerf = new OptimizedPerformanceMonitor();
|
|
543
1055
|
//# sourceMappingURL=optimized-performance-monitor.js.map
|