@454creative/easy-email
Version:
A framework-agnostic email service library for Node.js with observability and monitoring
169 lines • 6.01 kB
JavaScript
;
/**
* 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