@crudmates/profiler
Version:
A comprehensive performance profiling utility for Node.js applications with timing, memory monitoring, and garbage collection tracking. Perfect for debugging performance issues, memory leaks, and optimizing application performance.
427 lines • 11.8 kB
TypeScript
/**
* Logger interface for profiling output
*/
export interface Logger {
debug?: (message: string | object, ...args: unknown[]) => void;
log?: (message: string | object, ...args: unknown[]) => void;
warn?: (message: string | object, ...args: unknown[]) => void;
error?: (message: string | object, ...args: unknown[]) => void;
verbose?: (message: string | object, ...args: unknown[]) => void;
[key: string]: ((message: string | object, ...args: unknown[]) => void) | undefined;
}
/**
* Performance profiling utility options
*/
export interface ProfileConfig {
/** Enable memory profiling */
trackMemory?: boolean;
/** Enable garbage collection monitoring */
enableGC?: boolean;
/** Memory threshold in MB to trigger GC */
gcThresholdMB?: number;
/** Logger instance to use (defaults to console) */
logger?: Logger | Console;
/** Custom tags to include in logs */
tags?: Record<string, unknown>;
/** Log level for profiling output */
logLevel?: 'debug' | 'log' | 'verbose';
/** Whether to log individual checkpoints (default: true) */
logSteps?: boolean;
/** Enable verbose logging with detailed intermediate steps (default: false) */
verbose?: boolean;
/** Whether to log any output at all (default: true) */
silent?: boolean;
}
/**
* Performance profiling result
*/
export interface ProfileResult {
/** Function name or identifier */
name: string;
/** Execution duration in milliseconds */
duration: number;
/** Memory usage before execution */
memBefore?: NodeJS.MemoryUsage;
/** Memory usage after execution */
memAfter?: NodeJS.MemoryUsage;
/** Memory delta (difference) */
memDelta?: {
heapUsed: number;
heapTotal: number;
external: number;
rss: number;
};
/** Whether GC was triggered */
gcTriggered?: boolean;
/** Custom tags */
tags?: Record<string, unknown>;
/** Result of the profiled function */
result?: unknown;
/** Error if function threw */
error?: unknown;
}
/**
* Profile a function execution with timing and memory monitoring
*
* @example
* ```typescript
* // As a wrapper function
* const result = await profile(
* () => someAsyncOperation(),
* 'MyOperation',
* { trackMemory: true, enableGC: true }
* );
*
* // Using with CarService method
* const { result: cars } = await profile(
* () => this.carRepository.find({ where: { marketplaceVisible: true } }),
* 'fetchMarketplaceCars',
* {
* trackMemory: true,
* enableGC: true,
* gcThresholdMB: 100,
* logger: this.logger,
* tags: { operation: 'database-query' }
* }
* );
* ```
*/
export declare function profile<T>(fn: () => T | Promise<T>, name: string, config?: ProfileConfig): Promise<{
result: T;
profile: ProfileResult;
}>;
/**
* Decorator for profiling class methods
*
* @example
* ```typescript
* class CarService {
* @Profile('listCars', { trackMemory: true, enableGC: true })
* async listCar(data: AdminListCarRequestPayload.AsObject) {
* // method implementation
* }
*
* @Profile('searchCars', {
* trackMemory: true,
* gcThresholdMB: 150,
* tags: { operation: 'search' }
* })
* async searchCar(data: MarketplaceSearchRequestPayload.AsObject) {
* // method implementation
* }
* }
* ```
*/
export declare function Profile(name?: string, config?: ProfileConfig): <T extends (...args: any[]) => any>(target: T, context: {
name: string | symbol;
}) => T;
/**
* Simple timing utility for quick performance checks
*
* @example
* ```typescript
* // Basic usage
* const timer = new Timer('database-query');
* const cars = await this.carRepository.find();
* timer.stop({ carCount: cars.length });
*
* // Static method usage
* const result = await Timer.time(
* () => this.processLargeBatch(data),
* 'processLargeBatch'
* );
* ```
*/
export declare class Timer {
private startTime;
private name;
private logger;
constructor(name: string, logger?: Logger | Console);
stop(data?: Record<string, unknown>): number;
static time<T>(fn: () => T | Promise<T>, name: string, logger?: Logger | Console): Promise<T>;
}
/**
* Memory monitoring utility for tracking memory usage over time
*
* @example
* ```typescript
* const monitor = new MemMonitor(this.logger);
*
* monitor.snap('start');
* await this.processAlerts(alerts);
* monitor.snap('after-processing');
*
* // Compare memory usage
* monitor.compare('start', 'after-processing');
*
* // Get all snapshots for analysis
* const snapshots = monitor.getSnaps();
* ```
*/
export declare class MemMonitor {
private snaps;
private logger;
constructor(logger?: Logger | Console);
snap(label?: string): NodeJS.MemoryUsage;
compare(fromLabel?: string, toLabel?: string): void;
clear(): void;
getSnaps(): Array<{
timestamp: number;
usage: NodeJS.MemoryUsage;
label?: string;
}>;
}
/**
* Advanced profiler for continuous monitoring
* Useful for monitoring memory-intensive operations like alert processing
*
* @example
* ```typescript
* const profiler = new Profiler('alert-processing', {
* enableGC: true,
* gcThresholdMB: 100,
* logger: this.logger
* });
*
* profiler.start();
*
* for (const alert of alerts) {
* profiler.mark(`processing-alert-${alert.id}`);
* await this.processAlert(alert);
* }
*
* const summary = profiler.end();
* // Returns detailed performance summary
* ```
*/
export declare class Profiler {
private name;
private config;
private startTime;
private marks;
private gcCount;
constructor(name: string, config?: ProfileConfig);
start(): void;
mark(label: string): void;
/**
* Get current performance summary without ending the profiler
*/
getSummary(): {
name: string;
elapsed: number;
markCount: number;
gcCount: number;
lastStep?: string;
lastStepDuration?: number;
};
/**
* Get detailed phase breakdown up to current point
*/
getSteps(): Array<{
step: string;
duration: number;
durationFormatted: string;
percentage: number;
}>;
end(): {
name: string;
totalDuration: number;
totalGCCount: number;
marks: Array<{
label: string;
timestamp: number;
timestampFormatted: string;
stepDuration?: number;
stepDurationFormatted?: string;
memory?: {
heap: string;
rss: string;
};
gcTriggered?: boolean;
}>;
memDeltas?: Array<{
from: string;
to: string;
duration: string;
heapDelta: string;
rssDelta: string;
}>;
steps?: Array<{
step: string;
duration: number;
durationFormatted: string;
startTime: number;
endTime: number;
gcTriggered?: boolean;
}>;
};
private log;
}
/**
* Utility function to monitor memory leaks
* Useful for detecting memory growth patterns
*/
export declare function detectMemLeak(measurements: NodeJS.MemoryUsage[], threshold?: number): {
isLeaking: boolean;
trend: 'increasing' | 'decreasing' | 'stable';
avgGrowth: number;
};
/**
* V8 profiling options configuration
*/
export interface V8Options {
/** Required memory budget in MB for V8 profiling data */
maxMemoryBudgetMB: number;
/** Interval in minutes for automatic logging and data clearing (default: 60) */
intervalMinutes?: number;
/** Process V8 data incrementally vs accumulating (default: true) */
streamingMode?: boolean;
/** Enable CPU profiling for performance bottleneck analysis (default: true) */
cpuProfiling?: boolean;
/** Enable sampling heap profiler for memory allocation tracking (default: true) */
samplingHeapProfiler?: boolean;
/** Logger instance to use (defaults to console) */
logger?: Logger | Console;
/** Suppress configuration warnings (default: false) */
suppressWarnings?: boolean;
}
/**
* V8 profiling insights result
*/
export interface V8Insights {
/** Duration of the profiling session */
duration: number;
/** Top CPU-consuming functions */
topFunctions: Array<{
functionName: string;
selfTime: number;
totalTime: number;
percentage: number;
}>;
/** Memory allocation hot spots */
memoryHotspots: Array<{
allocation: string;
size: number;
count: number;
}>;
/** Garbage collection impact metrics */
gcImpact: {
gcTime: number;
gcCount: number;
avgGcDuration: number;
};
/** Memory usage at interval end */
memoryUsage: {
heap: string;
rss: string;
external: string;
};
}
/**
* Advanced V8 profiler for long-running application analysis
* Provides CPU profiling and memory allocation tracking with automatic
* interval-based logging to prevent memory buildup
*
* @example
* ```typescript
* // Start continuous profiling with 60-minute intervals
* const v8Profiler = new V8Profiler('production-app', {
* maxMemoryBudgetMB: 100,
* intervalMinutes: 60,
* cpuProfiling: true,
* samplingHeapProfiler: true
* });
*
* await v8Profiler.startContinuousProfiling();
* // Runs indefinitely, auto-logs insights every 60 minutes
*
* // Later, stop profiling
* await v8Profiler.stopContinuousProfiling();
* ```
*/
export declare class V8Profiler {
private options;
private session;
private intervalTimer?;
private currentMemoryUsage;
private profilingStartTime;
private isRunning;
constructor(_name: string, options: V8Options);
/**
* Initialize V8 Inspector session
*/
private initializeInspector;
/**
* Validate configuration and show warnings if needed
*/
private validateConfiguration;
/**
* Calculate estimated memory usage per minute
*/
private calculateEstimatedUsage;
/**
* Log warning message if warnings are not suppressed
*/
private warn;
/**
* Log info message
*/
private log;
/**
* Start continuous V8 profiling with automatic interval logging
*/
startContinuousProfiling(): Promise<void>;
/**
* Stop continuous V8 profiling
*/
stopContinuousProfiling(): Promise<V8Insights>;
/**
* Manually flush current interval (useful for testing)
*/
flushCurrentInterval(): Promise<V8Insights>;
/**
* Check if memory budget is exceeded
*/
isMemoryBudgetExceeded(): boolean;
/**
* Get current memory usage by V8 profiler
*/
getCurrentMemoryUsage(): number;
/**
* Start V8 profiling session
*/
private startProfilingSession;
/**
* Stop V8 profiling session
*/
private stopProfilingSession;
/**
* Reset profiling session (for interval flushing)
*/
private resetProfilingSession;
/**
* Setup interval timer for automatic flushing
*/
private setupIntervalTimer;
/**
* Collect and process V8 insights
*/
private collectInsights;
/**
* Collect CPU profiling insights
*/
private collectCPUProfile;
/**
* Collect heap profiling insights
*/
private collectHeapProfile;
/**
* Collect current memory usage
*/
private collectMemoryUsage;
/**
* Estimate memory size of profile data
*/
private estimateProfileSize;
}
//# sourceMappingURL=index.d.ts.map