122 lines
4.2 KiB
Python
122 lines
4.2 KiB
Python
from django.core.management.base import BaseCommand, CommandError
|
|
from django.utils import timezone
|
|
from datetime import timedelta
|
|
from incident_intelligence.models import Incident
|
|
from knowledge_learning.services.postmortem_generator import PostmortemGenerator
|
|
from knowledge_learning.models import Postmortem
|
|
|
|
|
|
class Command(BaseCommand):
|
|
help = 'Generate automated postmortems for resolved incidents'
|
|
|
|
def add_arguments(self, parser):
|
|
parser.add_argument(
|
|
'--days',
|
|
type=int,
|
|
default=7,
|
|
help='Number of days back to look for resolved incidents (default: 7)'
|
|
)
|
|
parser.add_argument(
|
|
'--severity',
|
|
type=str,
|
|
choices=['LOW', 'MEDIUM', 'HIGH', 'CRITICAL', 'EMERGENCY'],
|
|
help='Only generate postmortems for incidents with specific severity'
|
|
)
|
|
parser.add_argument(
|
|
'--force',
|
|
action='store_true',
|
|
help='Force generation even if postmortem already exists'
|
|
)
|
|
parser.add_argument(
|
|
'--dry-run',
|
|
action='store_true',
|
|
help='Show what would be generated without actually creating postmortems'
|
|
)
|
|
|
|
def handle(self, *args, **options):
|
|
days = options['days']
|
|
severity = options['severity']
|
|
force = options['force']
|
|
dry_run = options['dry_run']
|
|
|
|
# Calculate date range
|
|
end_date = timezone.now()
|
|
start_date = end_date - timedelta(days=days)
|
|
|
|
self.stdout.write(
|
|
self.style.SUCCESS(f'Looking for resolved incidents from {start_date.date()} to {end_date.date()}')
|
|
)
|
|
|
|
# Build queryset for resolved incidents
|
|
queryset = Incident.objects.filter(
|
|
status__in=['RESOLVED', 'CLOSED'],
|
|
resolved_at__gte=start_date,
|
|
resolved_at__lte=end_date
|
|
)
|
|
|
|
if severity:
|
|
queryset = queryset.filter(severity=severity)
|
|
|
|
# Filter out incidents that already have postmortems (unless force is used)
|
|
if not force:
|
|
existing_postmortem_incidents = Postmortem.objects.values_list('incident_id', flat=True)
|
|
queryset = queryset.exclude(id__in=existing_postmortem_incidents)
|
|
|
|
incidents = list(queryset)
|
|
|
|
if not incidents:
|
|
self.stdout.write(
|
|
self.style.WARNING('No resolved incidents found matching criteria')
|
|
)
|
|
return
|
|
|
|
self.stdout.write(
|
|
self.style.SUCCESS(f'Found {len(incidents)} incidents to process')
|
|
)
|
|
|
|
if dry_run:
|
|
self.stdout.write(self.style.WARNING('DRY RUN - No postmortems will be created'))
|
|
for incident in incidents:
|
|
self.stdout.write(f' - {incident.title} ({incident.severity}) - {incident.resolved_at}')
|
|
return
|
|
|
|
# Initialize postmortem generator
|
|
generator = PostmortemGenerator()
|
|
|
|
success_count = 0
|
|
error_count = 0
|
|
|
|
for incident in incidents:
|
|
try:
|
|
self.stdout.write(f'Generating postmortem for: {incident.title}')
|
|
|
|
result = generator.generate_postmortem_for_incident(
|
|
incident_id=str(incident.id),
|
|
include_timeline=True,
|
|
include_logs=True,
|
|
trigger='management_command'
|
|
)
|
|
|
|
self.stdout.write(
|
|
self.style.SUCCESS(f' ✓ Generated postmortem {result["postmortem_id"]}')
|
|
)
|
|
success_count += 1
|
|
|
|
except Exception as e:
|
|
self.stdout.write(
|
|
self.style.ERROR(f' ✗ Failed to generate postmortem: {str(e)}')
|
|
)
|
|
error_count += 1
|
|
|
|
# Summary
|
|
self.stdout.write('\n' + '='*50)
|
|
self.stdout.write(
|
|
self.style.SUCCESS(f'Postmortem generation completed:')
|
|
)
|
|
self.stdout.write(f' Successfully generated: {success_count}')
|
|
if error_count > 0:
|
|
self.stdout.write(
|
|
self.style.ERROR(f' Failed: {error_count}')
|
|
)
|
|
self.stdout.write('='*50)
|