UNPKG

traceperf

Version:

High-performance function execution tracking and monitoring for Node.js

127 lines 4.28 kB
/** * Proxy-based function tracking utility * * This module provides utilities for automatically tracking nested function calls * using JavaScript Proxies without modifying the original code structure. */ /** * A tracking context that manages function tracking using proxies */ export class ProxyTracker { /** * Create a new ProxyTracker * * @param trackFn - The function to use for tracking */ constructor(trackFn) { this._originalFunctions = new Map(); this._trackedFunctions = new Map(); this._isEnabled = true; this._trackFn = trackFn; } /** * Enable or disable tracking * * @param enabled - Whether tracking is enabled */ setEnabled(enabled) { this._isEnabled = enabled; } /** * Check if tracking is enabled * * @returns Whether tracking is enabled */ isEnabled() { return this._isEnabled; } /** * Make a function trackable * * @param fn - The function to make trackable * @param name - The name to use for tracking * @returns A tracked version of the function */ makeTrackable(fn, name) { // If tracking is disabled, return the original function if (!this._isEnabled) { return fn; } // If we've already tracked this function, return the tracked version if (this._trackedFunctions.has(fn)) { return this._trackedFunctions.get(fn); } // Create a tracked version of the function const self = this; const trackedFn = function (...args) { return self._trackFn(() => fn.apply(this, args), { label: name || fn.name || 'anonymous' }); }; // Store the tracked version this._trackedFunctions.set(fn, trackedFn); return trackedFn; } /** * Create a proxy for an object to track all its methods * * @param obj - The object to proxy * @param namespace - The namespace to use for tracking * @returns A proxied version of the object */ createProxy(obj, namespace = '') { // If tracking is disabled, return the original object if (!this._isEnabled) { return obj; } const self = this; return new Proxy(obj, { get(target, prop, receiver) { const value = Reflect.get(target, prop, receiver); // If the property is a function, make it trackable if (typeof value === 'function' && prop !== 'constructor') { const name = namespace ? `${namespace}.${String(prop)}` : String(prop); return self.makeTrackable(value, name); } // If the property is an object (but not a built-in), proxy it too if (value && typeof value === 'object' && !Array.isArray(value) && Object.getPrototypeOf(value) === Object.prototype) { const nestedNamespace = namespace ? `${namespace}.${String(prop)}` : String(prop); return self.createProxy(value, nestedNamespace); } return value; }, apply(target, thisArg, args) { // This handles the case when the proxy itself is called as a function const name = namespace || target.name || 'anonymous'; return self._trackFn(() => Reflect.apply(target, thisArg, args), { label: name }); } }); } /** * Track a module's exports * * @param moduleExports - The module's exports * @param namespace - The namespace to use for tracking * @returns A proxied version of the module's exports */ trackModule(moduleExports, namespace) { return this.createProxy(moduleExports, namespace); } /** * Clear all tracked functions */ clear() { this._trackedFunctions.clear(); this._originalFunctions.clear(); } } //# sourceMappingURL=proxy-tracker.js.map