syntropylog
Version:
An instance manager with observability for Node.js applications
172 lines • 7.62 kB
JavaScript
/**
* @file src/serialization/SerializationManager.ts
* @description Intelligent serialization manager with auto-detection and adaptive timeouts
*/
import { SerializationComplexity, } from './types';
import { SerializationPipeline } from './SerializationPipeline';
import { SerializationStep } from './pipeline/SerializationStep';
import { SanitizationStep } from './pipeline/SanitizationStep';
import { TimeoutStep } from './pipeline/TimeoutStep';
export class SerializationManager {
pipeline;
serializationStep;
sanitizationStep;
timeoutStep;
config;
metrics;
constructor(config = {}) {
this.config = {
timeoutMs: config.timeoutMs || 5000,
enableMetrics: config.enableMetrics ?? true,
sanitizeSensitiveData: config.sanitizeSensitiveData ?? true,
sanitizationContext: {
sensitiveFields: config.sanitizationContext?.sensitiveFields || [
'password',
'token',
'secret',
'key',
'auth',
'credential',
'api_key',
'private_key',
'connection_string',
'wallet_location',
],
redactPatterns: config.sanitizationContext?.redactPatterns || [
/password\s*=\s*['"][^'"]*['"]/gi,
/user\s*=\s*['"][^'"]*['"]/gi,
/token\s*=\s*['"][^'"]*['"]/gi,
/secret\s*=\s*['"][^'"]*['"]/gi,
],
maxStringLength: config.sanitizationContext?.maxStringLength || 300,
enableDeepSanitization: config.sanitizationContext?.enableDeepSanitization ?? true,
},
};
this.metrics = {
totalSerializations: 0,
successfulSerializations: 0,
failedSerializations: 0,
totalSerializationDuration: 0,
totalOperationTimeout: 0,
maxSerializationDuration: 0,
minSerializationDuration: 0,
complexityDistribution: { low: 0, medium: 0, high: 0 },
serializerDistribution: {},
timeoutStrategyDistribution: {},
};
// Inicializar pipeline
this.pipeline = new SerializationPipeline();
// Crear pasos del pipeline
this.serializationStep = new SerializationStep();
this.sanitizationStep = new SanitizationStep();
this.timeoutStep = new TimeoutStep(this.pipeline['timeoutStrategies']);
// Configurar pipeline
this.pipeline.addStep(this.serializationStep);
this.pipeline.addStep(this.sanitizationStep);
this.pipeline.addStep(this.timeoutStep);
}
register(serializer) {
this.serializationStep.addSerializer(serializer);
}
async serialize(data, context = {
depth: 0,
maxDepth: 10,
sensitiveFields: [],
sanitize: true,
}) {
const startTime = Date.now();
// Crear contexto del pipeline
const pipelineContext = {
serializationContext: context,
sanitizeSensitiveData: this.config.sanitizeSensitiveData,
sanitizationContext: this.config.sanitizationContext,
enableMetrics: this.config.enableMetrics,
};
// Ejecutar pipeline
const result = await this.pipeline.process(data, pipelineContext);
// Actualizar métricas
if (this.config.enableMetrics) {
this.updateMetrics(result, Date.now() - startTime);
}
return result;
}
updateMetrics(result, _totalDuration) {
this.metrics.totalSerializations++;
if (result.success) {
this.metrics.successfulSerializations++;
// Métricas de serialización (deberían ser muy bajas)
const serializationDuration = result.metadata.stepDurations?.serialization || 0;
this.metrics.totalSerializationDuration += serializationDuration;
this.metrics.maxSerializationDuration = Math.max(this.metrics.maxSerializationDuration, serializationDuration);
this.metrics.minSerializationDuration =
this.metrics.minSerializationDuration === 0
? serializationDuration
: Math.min(this.metrics.minSerializationDuration, serializationDuration);
// Métricas de timeout de operación
const operationTimeout = result.metadata.operationTimeout || 0;
this.metrics.totalOperationTimeout += operationTimeout;
// Distribución por complejidad
const complexity = result.complexity || SerializationComplexity.SIMPLE;
if (complexity === SerializationComplexity.SIMPLE)
this.metrics.complexityDistribution.low++;
else if (complexity === SerializationComplexity.COMPLEX)
this.metrics.complexityDistribution.medium++;
else if (complexity === SerializationComplexity.CRITICAL)
this.metrics.complexityDistribution.high++;
// Distribución por serializador
const serializer = result.serializer || 'unknown';
this.metrics.serializerDistribution[serializer] =
(this.metrics.serializerDistribution[serializer] || 0) + 1;
// Distribución por estrategia de timeout
const timeoutStrategy = result.metadata.timeoutStrategy || 'unknown';
this.metrics.timeoutStrategyDistribution[timeoutStrategy] =
(this.metrics.timeoutStrategyDistribution[timeoutStrategy] || 0) + 1;
}
else {
this.metrics.failedSerializations++;
}
}
getMetrics() {
return {
totalSerializations: this.metrics.totalSerializations,
successfulSerializations: this.metrics.successfulSerializations,
failedSerializations: this.metrics.failedSerializations,
averageSerializationDuration: this.metrics.totalSerializations > 0
? this.metrics.totalSerializationDuration /
this.metrics.totalSerializations
: 0,
averageOperationTimeout: this.metrics.successfulSerializations > 0
? this.metrics.totalOperationTimeout /
this.metrics.successfulSerializations
: 0,
maxSerializationDuration: this.metrics.maxSerializationDuration,
minSerializationDuration: this.metrics.minSerializationDuration,
complexityDistribution: { ...this.metrics.complexityDistribution },
serializerDistribution: { ...this.metrics.serializerDistribution },
timeoutStrategyDistribution: {
...this.metrics.timeoutStrategyDistribution,
},
};
}
resetMetrics() {
this.metrics = {
totalSerializations: 0,
successfulSerializations: 0,
failedSerializations: 0,
totalSerializationDuration: 0,
totalOperationTimeout: 0,
maxSerializationDuration: 0,
minSerializationDuration: 0,
complexityDistribution: { low: 0, medium: 0, high: 0 },
serializerDistribution: {},
timeoutStrategyDistribution: {},
};
}
getRegisteredSerializers() {
return this.serializationStep.getRegisteredSerializers();
}
getPipelineMetrics() {
return this.pipeline.getMetrics();
}
}
//# sourceMappingURL=SerializationManager.js.map