diff options
Diffstat (limited to 'api/debug/ingest.php')
| -rw-r--r-- | api/debug/ingest.php | 16 |
1 files changed, 16 insertions, 0 deletions
diff --git a/api/debug/ingest.php b/api/debug/ingest.php index 98354fe..dc425b8 100644 --- a/api/debug/ingest.php +++ b/api/debug/ingest.php @@ -94,6 +94,18 @@ function first_frame($stack) { return null; } +// Cross-language contract: MUST match norm_key() in scripts/newos4-ledger.py. +// One outage produced two signatures (`/ollama//api/tags` 18 203x, `/ollama/api/tags` 16 540x) because +// the client hash covers the raw source URL. `norm` is what the triage and the fix ledger group on. +function norm_key($message, $type = '') { + $s = mb_strtolower((string)$message); + $s = preg_replace('#https?://[^\s/]+#', '', $s); + $s = preg_replace('#/{2,}#', '/', $s); + $s = preg_replace('#\?v=[\w.]+#', '', $s); + $s = trim(preg_replace('#\s+#', ' ', $s)); + return substr(mb_strtolower(trim((string)$type)) . '|' . $s, 0, 400); +} + $processed = 0; // entries handled (NOT occurrences) — the client's truncation warning uses this foreach ($errors as $e) { $processed++; @@ -119,6 +131,9 @@ foreach ($errors as $e) { $allErrors[$idx]['stack'] = substr($e['stack'], 0, 2000); $allErrors[$idx]['frame'] = first_frame($e['stack']) ?? ($allErrors[$idx]['frame'] ?? null); } + if (empty($allErrors[$idx]['norm']) && !empty($e['message'])) { + $allErrors[$idx]['norm'] = norm_key($e['message'], $e['type'] ?? ''); + } $ingested += $delta; } continue; @@ -134,6 +149,7 @@ foreach ($errors as $e) { 'module' => $e['module'] ?? null, 'stack' => isset($e['stack']) ? substr($e['stack'], 0, 2000) : null, 'frame' => first_frame($e['stack'] ?? null), + 'norm' => norm_key($e['message'] ?? '', $e['type'] ?? ''), 'session_id' => $sessionId, 'count' => $delta, 'first_seen' => norm_ts($e['firstSeen'] ?? null, $now), |