@extends('layouts.app') @section('title', __('Operational metrics')) @section('page-title', __('Operational metrics')) @section('page-subtitle', __('Live view of the analysis pipeline + queue config.')) @push('head') @endpush @php $errorTone = $errorRatePct === null ? ['text' => 'text-slate-500 dark:text-slate-400', 'bar' => 'bg-slate-200 dark:bg-slate-700'] : ($errorRatePct >= 10 ? ['text' => 'text-rose-600 dark:text-rose-400', 'bar' => 'bg-rose-500'] : ($errorRatePct >= 3 ? ['text' => 'text-amber-600 dark:text-amber-400', 'bar' => 'bg-amber-500'] : ['text' => 'text-emerald-600 dark:text-emerald-400', 'bar' => 'bg-emerald-500'])); $errorBudget = $errorRatePct === null ? 0 : min(100, max(0, $errorRatePct)); $oldestHuman = function ($s) { if ($s === null) return '—'; if ($s < 60) return $s.'s'; if ($s < 3600) return floor($s / 60).'m '.($s % 60).'s'; return floor($s / 3600).'h '.floor(($s % 3600) / 60).'m'; }; // 8 unified stat tiles. Single visual system: heading + number + caption. $tiles = [ ['label' => __('Pending'), 'value' => number_format($pending), 'caption' => __('Awaiting a worker'), 'tone' => $pending > 50 ? 'amber' : 'neutral'], ['label' => __('Running'), 'value' => number_format($running), 'caption' => __('Currently with the LLM'), 'tone' => 'brand'], ['label' => __('Awaiting review'), 'value' => number_format($awaiting), 'caption' => __('Tenant admin queue'), 'tone' => 'neutral'], ['label' => __('Failed (24h)'), 'value' => number_format($failedRuns24h), 'caption' => __('Out of :n total runs', ['n' => $totalRuns24h]), 'tone' => $failedRuns24h > 0 ? 'rose' : 'neutral'], ['label' => __('Error rate (24h)'),'value' => $errorRatePct === null ? '—' : $errorRatePct.'%', 'caption' => null, 'tone' => 'error'], ['label' => __('Tokens (24h)'), 'value' => number_format($tokens24h), 'caption' => __('7d:').' '.number_format($tokens7d), 'tone' => 'neutral'], ['label' => __('p95 runtime'), 'value' => $runtimeP95 !== null ? $runtimeP95.'s' : '—', 'caption' => $runsCount.' '.__('runs'), 'tone' => $runtimeP95 !== null && $runtimeP95 > 180 ? 'amber' : 'neutral'], ['label' => __('Active workers'), 'value' => $activeWorkers === null ? '—' : (string) $activeWorkers, 'caption' => $oldestHuman($oldestPendingSeconds), 'tone' => $activeWorkers === 0 && ($pending > 0 || $running > 0) ? 'rose' : 'neutral'], ]; $toneClass = function (string $tone): string { return match ($tone) { 'brand' => 'text-brand-600 dark:text-brand-400', 'amber' => 'text-amber-600 dark:text-amber-400', 'rose' => 'text-rose-600 dark:text-rose-400', 'emerald' => 'text-emerald-600 dark:text-emerald-400', default => 'text-slate-900 dark:text-slate-100', }; }; @endphp @section('content')
{{ __('Workers are OS processes — they cannot be started or stopped from the web UI for security reasons. Run the command below under Supervisor (Linux) or NSSM/Task Scheduler (Windows).') }}
{{ $recommendedCommand }}
{{ __('The "analyses-priority" queue is consumed first, then "analyses", then "default". Start 8 workers per host to begin with — bump up only if you raise the LLM RPM cap.') }}
{{ __('Toggle the priority lane and override the in-flight cap per tenant. Sorted by 24-hour activity.') }}
| {{ __('Tenant') }} | {{ __('Priority') }} | {{ __('Cap (override)') }} | {{ __('In-flight') }} | {{ __('24h') }} | |
|---|---|---|---|---|---|
{{ __('Connection') }}: {{ $queueConnection }}
{{ __('Wall-clock time from the worker picking up the job to the analysis finishing. p95 above 180 s suggests the LLM is throttling or the prompt is too large for the chosen token budget.') }}
{{ __('From the failed_jobs table — Laravel-level failures (timeouts, OOM, etc.).') }}