$hash, 'message' => $e['message'] ?? '', 'count' => 0, 'type' => $t]; } $topErrors[$hash]['count'] += $e['count'] ?? 1; } } $totalOccurrences = 0; foreach ($errors as $e) { $totalOccurrences += (int)($e['count'] ?? 1); } usort($topErrors, fn($a, $b) => $b['count'] - $a['count']); $topErrors = array_slice($topErrors, 0, 20); ksort($byDay); json_response([ 'success' => true, // total_errors = OCCURRENCES (sum of counts); unique_errors = distinct signatures. // Before 2026-10-23 the key held the record count while by_type held occurrences, // so two numbers on the same screen disagreed by ~3,500x. 'total_errors' => $totalOccurrences, 'unique_errors' => $total, 'total_sessions' => count($sessions), 'by_type' => $byType, 'by_severity' => $bySeverity, 'by_category' => $byCategory, 'by_module' => $byModule, 'by_day' => $byDay, 'top_errors' => $topErrors, 'generated_at' => date('c'), ]);