AutoReportGenerator.js•17.4 kB
export class AutoReportGenerator {
constructor() {
this.templateEngine = new ReportTemplateEngine();
this.narrativeGenerator = new NarrativeGenerator();
}
// 메인 기능: 완전한 장애 보고서 자동 생성
async generateIncidentReport(timelineAnalysis, metadata = {}) {
const report = {
report_id: this.generateReportId(),
generated_at: new Date().toISOString(),
report_type: 'automated_incident_analysis',
analysis_period: timelineAnalysis.timeline_period,
// 경영진용 요약 (1분 안에 읽을 수 있는 핵심 내용)
executive_summary: await this.generateExecutiveSummary(timelineAnalysis),
// 기술진용 상세 분석
technical_analysis: await this.generateTechnicalAnalysis(timelineAnalysis),
// 사업 영향 평가
business_impact_assessment: this.generateBusinessImpactSection(timelineAnalysis.business_impact),
// 행동 계획
action_plan: await this.generateActionPlan(timelineAnalysis),
// 첨부자료
appendices: await this.generateAppendices(timelineAnalysis)
};
return report;
}
// 경영진용 요약 생성 (AI 자연어 생성)
async generateExecutiveSummary(analysis) {
const summary = {
incident_overview: '',
key_findings: [],
business_impact: '',
immediate_actions_taken: [],
recommendations: []
};
// 자연어로 상황 요약 생성
if (analysis.causal_chain.length > 0) {
const rootCause = analysis.root_cause_analysis.primary_root_cause;
const affectedServices = analysis.business_impact.affected_services.length;
summary.incident_overview =
`${this.formatTimeRange(analysis.timeline_period)} 동안 ${rootCause?.category || '시스템 이슈'}로 인한 ` +
`장애가 발생하여 ${affectedServices}개 서비스에 영향을 미쳤습니다. ` +
`전체 시스템 가용성이 ${100 - analysis.business_impact.metrics.service_availability}% 감소했습니다.`;
// 핵심 발견사항
summary.key_findings = [
`근본 원인: ${rootCause?.technical_explanation || '복합적 요인으로 추정'}`,
`전파 경로: ${this.summarizePropagationPath(analysis.causal_chain)}`,
`복구 시간: ${this.calculateRecoveryTime(analysis.causal_chain)}`,
`영향 범위: ${analysis.business_impact.user_impact_assessment}`
];
// 비즈니스 영향 요약
summary.business_impact =
`서비스 가용성 ${analysis.business_impact.metrics.service_availability}%, ` +
`응답시간 ${analysis.business_impact.metrics.response_time_degradation}% 증가, ` +
`예상 매출 영향 ${analysis.business_impact.estimated_revenue_impact}`;
} else {
summary.incident_overview =
`${this.formatTimeRange(analysis.timeline_period)} 동안 시스템이 안정적으로 운영되었으며, ` +
`특별한 장애나 성능 저하 없이 정상 서비스가 유지되었습니다.`;
}
return summary;
}
// 기술 분석 섹션 생성
async generateTechnicalAnalysis(analysis) {
const technicalSection = {
timeline_reconstruction: '',
causal_analysis: '',
system_behavior_analysis: '',
performance_metrics: '',
log_analysis_summary: ''
};
// 시간순 재구성 (기술진이 이해할 수 있도록)
if (analysis.causal_chain.length > 0) {
technicalSection.timeline_reconstruction = this.generateTimelineNarrative(analysis.causal_chain);
technicalSection.causal_analysis = this.generateCausalAnalysisText(analysis.causal_chain);
technicalSection.system_behavior_analysis = this.analyzeSystemBehaviorPatterns(analysis);
}
return technicalSection;
}
// 시간순 재구성 내러티브 생성 (핵심 기능)
generateTimelineNarrative(causalChain) {
let narrative = "## 장애 발생 시간순 재구성\n\n";
causalChain.forEach((segment, index) => {
const time = new Date(segment.trigger_event.timestamp).toLocaleTimeString();
const server = segment.trigger_event.server_id;
const issue = segment.trigger_event.description;
narrative += `**${time}** - ${server}: ${issue}\n`;
if (segment.cascading_effects.length > 0) {
narrative += " **연쇄 영향:**\n";
segment.cascading_effects.forEach(effect => {
const effectTime = new Date(effect.timestamp).toLocaleTimeString();
narrative += ` - ${effectTime} ${effect.server_id}: ${effect.description}\n`;
});
}
if (segment.causal_relationship.length > 0) {
narrative += " **분석된 인과관계:**\n";
segment.causal_relationship.forEach(rel => {
narrative += ` - ${rel.explanation} (신뢰도: ${(rel.confidence * 100).toFixed(0)}%)\n`;
});
}
narrative += "\n";
});
return narrative;
}
// 인과관계 분석 텍스트 생성
generateCausalAnalysisText(causalChain) {
if (causalChain.length === 0) return "인과관계 분석을 위한 이벤트가 충분하지 않습니다.";
let analysis = "## 인과관계 분석\n\n";
// 체인의 시작과 끝 이벤트
const firstEvent = causalChain[0].trigger_event;
const lastEvent = causalChain[causalChain.length - 1].trigger_event;
analysis += `분석된 장애 체인은 ${new Date(firstEvent.timestamp).toLocaleTimeString()}에 ` +
`${firstEvent.server_id}에서 발생한 ${firstEvent.description}으로 시작되었습니다.\n\n`;
// 인과관계 패턴 분석
const relationships = this.identifyRelationshipPatterns(causalChain);
if (relationships.length > 0) {
analysis += "### 주요 인과관계 패턴\n\n";
relationships.forEach(rel => {
analysis += `- **${rel.type}**: ${rel.explanation}\n`;
});
}
return analysis;
}
// 비즈니스 영향 섹션 생성
generateBusinessImpactSection(impact) {
if (!impact) return null;
const impactSection = {
summary: `총 ${impact.affected_services.length}개 서비스가 영향을 받았으며, 영향도 점수는 ${impact.total_impact_score}/100입니다.`,
service_availability: impact.metrics.service_availability,
response_time_degradation: impact.metrics.response_time_degradation,
revenue_impact: impact.estimated_revenue_impact,
user_impact: impact.user_impact_assessment,
affected_services_details: this.formatAffectedServices(impact.affected_services)
};
return impactSection;
}
// 액션 플랜 생성
async generateActionPlan(analysis) {
const actionPlan = {
immediate_actions: [],
short_term_improvements: [],
long_term_strategies: [],
monitoring_enhancements: []
};
if (analysis.root_cause_analysis && analysis.root_cause_analysis.primary_root_cause) {
const rootCause = analysis.root_cause_analysis.primary_root_cause;
// 즉시 조치사항
actionPlan.immediate_actions = [
`${rootCause.immediate_fix || '영향받은 서비스 재시작'}`,
'시스템 상태 확인 및 모니터링 강화',
'추가 이상 징후 감시'
];
// 단기 개선사항
actionPlan.short_term_improvements = analysis.prevention_recommendations?.filter(
rec => rec.timeline === 'short_term'
).map(rec => rec.description) || [];
// 장기 전략
actionPlan.long_term_strategies = analysis.prevention_recommendations?.filter(
rec => rec.timeline === 'long_term'
).map(rec => rec.description) || [];
// 모니터링 강화 방안
actionPlan.monitoring_enhancements = this.generateMonitoringEnhancements(analysis);
}
return actionPlan;
}
// 부록 생성
async generateAppendices(analysis) {
const appendices = {
raw_data_samples: [],
correlation_graphs: {},
incident_comparison: {},
technical_details: {}
};
if (analysis.causal_chain.length > 0) {
// 기술적 세부사항
appendices.technical_details = {
environment_information: this.generateEnvironmentInformation(),
system_configurations: this.generateSystemConfigurations(),
error_logs: this.generateErrorLogSummary(analysis.causal_chain)
};
}
return appendices;
}
// 유틸리티 메서드들
generateReportId() {
return `AUTO-${new Date().toISOString().slice(0,10)}-${Math.random().toString(36).substr(2, 6).toUpperCase()}`;
}
formatTimeRange(period) {
const start = new Date(period.start).toLocaleTimeString();
const end = new Date(period.end).toLocaleTimeString();
return `${start} ~ ${end}`;
}
summarizePropagationPath(causalChain) {
if (causalChain.length === 0) return '해당 없음';
const servers = causalChain.map(segment => segment.trigger_event.server_id);
return servers.join(' → ');
}
calculateRecoveryTime(causalChain) {
if (causalChain.length === 0) return '즉시';
const firstEvent = new Date(causalChain[0].trigger_event.timestamp);
const lastEvent = new Date(causalChain[causalChain.length - 1].trigger_event.timestamp);
const diffMinutes = (lastEvent - firstEvent) / (1000 * 60);
return `약 ${Math.round(diffMinutes)}분`;
}
identifyRelationshipPatterns(causalChain) {
const relationships = [];
// 체인에서 모든 관계 수집
const allRelationships = causalChain.flatMap(segment => segment.causal_relationship);
// 관계 유형 집계
const relationshipTypes = {};
allRelationships.forEach(rel => {
if (!relationshipTypes[rel.type]) {
relationshipTypes[rel.type] = {
count: 0,
confidence: 0,
explanations: []
};
}
relationshipTypes[rel.type].count++;
relationshipTypes[rel.type].confidence += rel.confidence;
relationshipTypes[rel.type].explanations.push(rel.explanation);
});
// 주요 관계 유형 추출
for (const [type, data] of Object.entries(relationshipTypes)) {
if (data.count > 0) {
relationships.push({
type,
count: data.count,
average_confidence: data.confidence / data.count,
explanation: this.getMostFrequentExplanation(data.explanations)
});
}
}
// 빈도 및 신뢰도 기준 정렬
return relationships.sort((a, b) =>
(b.count * b.average_confidence) - (a.count * a.average_confidence)
);
}
getMostFrequentExplanation(explanations) {
const counts = {};
let maxCount = 0;
let mostFrequent = '';
explanations.forEach(exp => {
counts[exp] = (counts[exp] || 0) + 1;
if (counts[exp] > maxCount) {
maxCount = counts[exp];
mostFrequent = exp;
}
});
return mostFrequent;
}
formatAffectedServices(services) {
if (!services || services.length === 0) return [];
return services.map(service => {
return {
name: service,
type: this.getServiceType(service),
importance: this.getServiceImportance(service)
};
});
}
getServiceType(serviceName) {
if (serviceName.includes('db-')) return 'database';
if (serviceName.includes('web-')) return 'web_server';
if (serviceName.includes('api-')) return 'api_service';
if (serviceName.includes('cache-')) return 'cache_service';
if (serviceName.includes('k8s-')) return 'kubernetes';
return 'other';
}
getServiceImportance(serviceName) {
// 실제로는 비즈니스 중요도 맵핑
const criticalServices = ['db-server-01', 'web-server-01', 'k8s-master-01'];
const highServices = ['api-server-01', 'cache-server-01', 'k8s-worker-01'];
if (criticalServices.includes(serviceName)) return 'critical';
if (highServices.includes(serviceName)) return 'high';
return 'medium';
}
generateMonitoringEnhancements(analysis) {
const enhancements = [];
if (analysis.root_cause_analysis?.primary_root_cause) {
const rootCause = analysis.root_cause_analysis.primary_root_cause;
switch (rootCause.category) {
case 'resource_exhaustion':
enhancements.push(
'CPU 사용률 임계치 조정 및 알림 추가',
'부하 예측 모니터링 추가'
);
break;
case 'memory_leak':
enhancements.push(
'메모리 증가 패턴 탐지 모니터링 추가',
'힙 덤프 자동화 설정'
);
break;
case 'database_bottleneck':
enhancements.push(
'느린 쿼리 모니터링 강화',
'DB 연결 풀 상태 모니터링 추가'
);
break;
case 'network_congestion':
enhancements.push(
'네트워크 트래픽 모니터링 세분화',
'패킷 손실률 지표 추가'
);
break;
}
}
// 공통 모니터링 강화 방안
enhancements.push('서비스 간 의존성 맵 기반 연쇄 장애 탐지 강화');
return enhancements;
}
analyzeSystemBehaviorPatterns(analysis) {
if (analysis.causal_chain.length === 0) {
return "특이 패턴 없음";
}
let behaviorAnalysis = "## 시스템 동작 패턴 분석\n\n";
// 리소스 사용 패턴
const resourcePatterns = this.analyzeResourceUsagePatterns(analysis.causal_chain);
if (resourcePatterns) {
behaviorAnalysis += `### 자원 사용 패턴\n${resourcePatterns}\n\n`;
}
// 장애 전파 패턴
if (analysis.root_cause_analysis?.propagation_analysis) {
const propagation = analysis.root_cause_analysis.propagation_analysis;
behaviorAnalysis += `### 장애 전파 패턴\n`;
behaviorAnalysis += `전파 유형: ${this.translatePropagationPattern(propagation.pattern)}\n`;
if (propagation.affected_tiers) {
behaviorAnalysis += "영향받은 계층:\n";
for (const [tier, count] of Object.entries(propagation.affected_tiers)) {
if (count > 0) {
behaviorAnalysis += `- ${tier}: ${count}개 서버\n`;
}
}
}
}
return behaviorAnalysis;
}
translatePropagationPattern(pattern) {
switch (pattern) {
case 'tiered_propagation': return '계층적 전파 (티어 간 순차적 전파)';
case 'radial_propagation': return '방사형 전파 (중앙에서 여러 노드로 확산)';
case 'random': return '불규칙 전파 (특정 패턴 없음)';
case 'none': return '전파 없음';
default: return pattern;
}
}
analyzeResourceUsagePatterns(causalChain) {
// 자원 사용 패턴 분석 로직
let cpuEvents = 0, memoryEvents = 0, networkEvents = 0, diskEvents = 0;
causalChain.forEach(segment => {
const eventType = segment.trigger_event.event_type;
if (eventType.includes('cpu')) cpuEvents++;
if (eventType.includes('memory')) memoryEvents++;
if (eventType.includes('network')) networkEvents++;
if (eventType.includes('disk')) diskEvents++;
});
let patterns = [];
if (cpuEvents > 0) {
patterns.push(`CPU 관련 이벤트: ${cpuEvents}회 발생`);
}
if (memoryEvents > 0) {
patterns.push(`메모리 관련 이벤트: ${memoryEvents}회 발생`);
}
if (networkEvents > 0) {
patterns.push(`네트워크 관련 이벤트: ${networkEvents}회 발생`);
}
if (diskEvents > 0) {
patterns.push(`디스크 관련 이벤트: ${diskEvents}회 발생`);
}
return patterns.join('\n');
}
generateEnvironmentInformation() {
// 실제 구현에서는 환경 정보 수집
return {
environment: 'Production',
region: 'ap-northeast-2',
cloud_provider: 'AWS',
kubernetes_version: '1.24.6',
infrastructure_type: 'Hybrid'
};
}
generateSystemConfigurations() {
// 실제 구현에서는 시스템 설정 수집
return {
load_balancer_config: 'Round Robin',
auto_scaling_config: 'CPU > 70% for 3 minutes',
database_connections: 'Max: 500, Pool Size: 50',
memory_limits: 'JVM: 8GB, Container: 16GB'
};
}
generateErrorLogSummary(causalChain) {
if (causalChain.length === 0) return [];
// 실제 구현에서는 로그 데이터 가져오기
// 여기서는 더미 데이터
return [
{
timestamp: causalChain[0].trigger_event.timestamp,
server: causalChain[0].trigger_event.server_id,
level: 'ERROR',
message: `Resource exhaustion detected: ${causalChain[0].trigger_event.description}`
},
{
timestamp: causalChain[causalChain.length - 1].trigger_event.timestamp,
server: causalChain[causalChain.length - 1].trigger_event.server_id,
level: 'WARN',
message: 'Service degradation detected'
}
];
}
}
// 리포트 템플릿 엔진 (더미 클래스)
class ReportTemplateEngine {
// 템플릿 엔진 메서드들
}
// 내러티브 생성기 (더미 클래스)
class NarrativeGenerator {
// 내러티브 생성 메서드들
}