Files
workdock-platform/backend/workflows/observability_views.py

160 lines
6.2 KiB
Python

from datetime import timedelta
from django.contrib import messages
from django.db.models import Count, Q
from django.shortcuts import redirect, render
from django.utils import timezone
from django.utils.translation import gettext as _
from .backup_ops import create_backup_bundle, latest_backup_health_snapshot, list_backup_bundles, verify_backup_bundle
from .models import AdminAuditLog, AsyncTaskLog, UserNotification, UserProfile
from .roles import user_has_capability
def job_monitor_page_impl(request):
status_filter = (request.GET.get('status') or '').strip()
task_filter = (request.GET.get('task') or '').strip()
logs = AsyncTaskLog.objects.all()
if status_filter:
logs = logs.filter(status=status_filter)
if task_filter:
logs = logs.filter(task_name=task_filter)
logs = logs.order_by('-started_at', '-id')[:200]
task_names = list(AsyncTaskLog.objects.order_by('task_name').values_list('task_name', flat=True).distinct())
since = timezone.now() - timedelta(hours=24)
recent_logs = AsyncTaskLog.objects.filter(started_at__gte=since)
counts = {row['status']: row['count'] for row in recent_logs.values('status').annotate(count=Count('id'))}
recent_failed = list(AsyncTaskLog.objects.filter(status='failed').order_by('-started_at', '-id')[:5])
can_manage_backups = user_has_capability(request.user, 'manage_backups')
return render(
request,
'workflows/job_monitor.html',
{
'logs': logs,
'status_filter': status_filter,
'task_filter': task_filter,
'task_names': task_names,
'status_choices': [('started', _('Gestartet')), ('succeeded', _('Erfolgreich')), ('failed', _('Fehlgeschlagen'))],
'job_summary': {
'started_count_24h': counts.get('started', 0),
'success_count_24h': counts.get('succeeded', 0),
'failed_count_24h': counts.get('failed', 0),
'recent_failed': recent_failed,
'can_manage_backups': can_manage_backups,
'backup_health': latest_backup_health_snapshot() if can_manage_backups else None,
},
},
)
def audit_log_page_impl(request):
action = (request.GET.get('action') or '').strip()
user_query = (request.GET.get('user') or '').strip()
date_from = (request.GET.get('date_from') or '').strip()
date_to = (request.GET.get('date_to') or '').strip()
rows_qs = AdminAuditLog.objects.select_related('actor').all()
if action:
rows_qs = rows_qs.filter(action=action)
if user_query:
rows_qs = rows_qs.filter(
Q(actor_display__icontains=user_query)
| Q(actor__username__icontains=user_query)
| Q(actor__email__icontains=user_query)
)
if date_from:
rows_qs = rows_qs.filter(created_at__date__gte=date_from)
if date_to:
rows_qs = rows_qs.filter(created_at__date__lte=date_to)
rows = list(rows_qs[:300])
action_choices = AdminAuditLog.objects.order_by('action').values_list('action', flat=True).distinct()
return render(
request,
'workflows/audit_log.html',
{
'rows': rows,
'action_choices': action_choices,
'selected_action': action,
'user_query': user_query,
'date_from': date_from,
'date_to': date_to,
},
)
def backup_recovery_page_impl(request):
rows = list_backup_bundles()
return render(
request,
'workflows/backup_recovery.html',
{
'rows': rows,
'backup_health': latest_backup_health_snapshot(),
},
)
def create_backup_from_admin_impl(request, *, audit_fn, notify_user_fn, create_backup_bundle_fn):
try:
result = create_backup_bundle_fn()
audit_fn(
request,
'backup_created',
target_type='backup_bundle',
target_label=result['name'],
details={'path': result['path']},
)
notify_user_fn(
user=request.user,
title=_('Backup erstellt: %(name)s') % {'name': result['name']},
body=_('Das Backup-Bundle wurde erfolgreich erstellt.'),
level=UserNotification.LEVEL_SUCCESS,
link_url='/admin-tools/backups/',
event_key=UserProfile.NOTIFICATION_BACKUP_SUCCESS,
)
messages.success(request, _('Backup wurde erstellt: %(name)s') % {'name': result['name']})
except Exception as exc:
notify_user_fn(
user=request.user,
title=_('Backup fehlgeschlagen'),
body=str(exc),
level=UserNotification.LEVEL_ERROR,
link_url='/admin-tools/backups/',
event_key=UserProfile.NOTIFICATION_BACKUP_FAILURE,
)
messages.error(request, _('Backup konnte nicht erstellt werden: %(error)s') % {'error': exc})
return redirect('backup_recovery_page')
def verify_backup_from_admin_impl(request, backup_name: str, *, audit_fn, notify_user_fn, verify_backup_bundle_fn):
try:
result = verify_backup_bundle_fn(backup_name)
audit_fn(
request,
'backup_verified',
target_type='backup_bundle',
target_label=backup_name,
details={'summary': result['summary']},
)
notify_user_fn(
user=request.user,
title=_('Backup verifiziert: %(name)s') % {'name': result['name']},
body=result.get('summary') or _('Das Backup wurde erfolgreich verifiziert.'),
level=UserNotification.LEVEL_SUCCESS,
link_url='/admin-tools/backups/',
event_key=UserProfile.NOTIFICATION_BACKUP_SUCCESS,
)
messages.success(request, _('Backup wurde verifiziert: %(name)s') % {'name': result['name']})
except Exception as exc:
notify_user_fn(
user=request.user,
title=_('Backup-Verifikation fehlgeschlagen'),
body=str(exc),
level=UserNotification.LEVEL_ERROR,
link_url='/admin-tools/backups/',
event_key=UserProfile.NOTIFICATION_BACKUP_FAILURE,
)
messages.error(request, _('Backup-Verifikation fehlgeschlagen: %(error)s') % {'error': exc})
return redirect('backup_recovery_page')