UNPKG

@454creative/easy-email

Version:

A framework-agnostic email service library for Node.js with observability and monitoring

169 lines 6.01 kB
"use strict"; /** * Performance monitoring utilities for the email library */ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } return new (P || (P = Promise))(function (resolve, reject) { function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } step((generator = generator.apply(thisArg, _arguments || [])).next()); }); }; Object.defineProperty(exports, "__esModule", { value: true }); exports.PerformanceMonitor = void 0; exports.trackPerformance = trackPerformance; class PerformanceMonitor { constructor(config = {}) { this.metrics = []; this.startTimes = new Map(); this.metadataStore = new Map(); this.config = Object.assign({ enabled: true, thresholdMs: 1000, logSlowOperations: true, trackMemoryUsage: false }, config); } static getInstance(config) { if (!PerformanceMonitor.instance) { PerformanceMonitor.instance = new PerformanceMonitor(config); } return PerformanceMonitor.instance; } /** * Start timing an operation */ startOperation(operation, metadata) { if (!this.config.enabled) return; this.startTimes.set(operation, Date.now()); if (metadata) { this.metadataStore.set(operation, JSON.stringify(metadata)); } } /** * End timing an operation and record metrics */ endOperation(operation, success, error) { if (!this.config.enabled) return null; const startTime = this.startTimes.get(operation); if (!startTime) { console.warn(`PerformanceMonitor: No start time found for operation: ${operation}`); return null; } const duration = Date.now() - startTime; const timestamp = new Date(); const metric = { operation, duration, timestamp, success, error, metadata: this.getMetadata(operation) }; this.metrics.push(metric); this.startTimes.delete(operation); this.metadataStore.delete(operation); // Log slow operations if (this.config.logSlowOperations && duration > this.config.thresholdMs) { console.warn(`Slow operation detected: ${operation} took ${duration}ms`); } return metric; } /** * Get performance summary */ getSummary() { if (this.metrics.length === 0) { return { totalOperations: 0, averageDuration: 0, slowOperations: [], successRate: 0, topOperations: [] }; } const totalOperations = this.metrics.length; const averageDuration = this.metrics.reduce((sum, m) => sum + m.duration, 0) / totalOperations; const slowOperations = this.metrics.filter(m => m.duration > this.config.thresholdMs); const successRate = this.metrics.filter(m => m.success).length / totalOperations; // Group by operation const operationStats = new Map(); this.metrics.forEach(metric => { const existing = operationStats.get(metric.operation) || { count: 0, totalDuration: 0 }; existing.count++; existing.totalDuration += metric.duration; operationStats.set(metric.operation, existing); }); const topOperations = Array.from(operationStats.entries()) .map(([operation, stats]) => ({ operation, count: stats.count, avgDuration: stats.totalDuration / stats.count })) .sort((a, b) => b.count - a.count) .slice(0, 10); return { totalOperations, averageDuration, slowOperations, successRate, topOperations }; } /** * Clear all metrics */ clearMetrics() { this.metrics = []; this.startTimes.clear(); } /** * Get all metrics */ getMetrics() { return [...this.metrics]; } /** * Update configuration */ updateConfig(config) { this.config = Object.assign(Object.assign({}, this.config), config); } getMetadata(operation) { const metadataStr = this.metadataStore.get(operation); if (metadataStr) { try { return JSON.parse(metadataStr); } catch (_a) { return undefined; } } return undefined; } } exports.PerformanceMonitor = PerformanceMonitor; /** * Performance decorator for methods */ function trackPerformance(operationName) { return function (target, propertyName, descriptor) { const method = descriptor.value; const monitor = PerformanceMonitor.getInstance(); descriptor.value = function (...args) { return __awaiter(this, void 0, void 0, function* () { const operation = operationName || `${target.constructor.name}.${propertyName}`; monitor.startOperation(operation); try { const result = yield method.apply(this, args); monitor.endOperation(operation, true); return result; } catch (error) { monitor.endOperation(operation, false, error instanceof Error ? error.message : String(error)); throw error; } }); }; }; } //# sourceMappingURL=performance.js.map