aboutsummaryrefslogtreecommitdiff
path: root/api
diff options
context:
space:
mode:
Diffstat (limited to 'api')
-rw-r--r--api/debug/dashboard.php18
-rw-r--r--api/debug/ingest.php16
2 files changed, 29 insertions, 5 deletions
diff --git a/api/debug/dashboard.php b/api/debug/dashboard.php
index 9b717c8..a20271f 100644
--- a/api/debug/dashboard.php
+++ b/api/debug/dashboard.php
@@ -203,14 +203,15 @@ if (is_array($rawChecks)) {
<?php else: ?>
<div class="table-scroll">
<table>
- <tr><th>Signatures</th><th>Occurrences</th><th>Real</th><th>Noise</th><th>Self-ref</th><th>New reports</th><th>Generated</th></tr>
+ <tr><th>Signatures</th><th>Clusters</th><th>Active &lt;24h</th><th>Stale &gt;7d</th><th>Occurrences</th><th>Regressed</th><th>Generated</th></tr>
<tr>
<td><?= (int)($tri['records'] ?? 0) ?></td>
+ <td><?= (int)($tri['clusters'] ?? 0) ?></td>
+ <td><?= (int)($tri['active_records'] ?? 0) ?></td>
+ <td><?= (int)($tri['stale_records'] ?? 0) ?></td>
<td><?= (int)($tri['occurrences'] ?? 0) ?></td>
- <td><?= (int)($tri['real_records'] ?? 0) ?></td>
- <td><?= (int)($tri['noise_records'] ?? 0) ?></td>
- <td><?= (int)($tri['self_referential_records'] ?? 0) ?></td>
- <td><?= (int)($tri['reports_new'] ?? 0) ?></td>
+ <td><?php $rg = (int)($tri['fixes_regressed'] ?? 0); ?>
+ <?php if ($rg > 0): ?><span class="status-pill degraded"><?= $rg ?> regressed</span><?php else: ?><span class="status-pill ok">none</span><?php endif; ?></td>
<td><?= htmlspecialchars(substr($triage['generated_at'] ?? '', 5, 11)) ?>Z</td>
</tr>
</table>
@@ -221,6 +222,13 @@ if (is_array($rawChecks)) {
<div class="thread"><div class="body" style="font-size:.82em;"><?= (int)($t['count'] ?? 0) ?>× <span class="tag"><?= htmlspecialchars($t['type'] ?? '?') ?></span> <?= htmlspecialchars(mb_substr($t['message'] ?? '', 0, 110)) ?></div></div>
<?php endforeach; ?>
<?php endif; ?>
+ <?php foreach (($triage['fixes']['regressed'] ?? []) as $fx): ?>
+ <div style="color:var(--error);font-size:.85em;margin-top:8px;">
+ <b>REGRESSED</b> <?= htmlspecialchars((string)($fx['commit'] ?? '?')) ?> —
+ <?= htmlspecialchars(substr((string)($fx['message'] ?? ''), 0, 90)) ?>
+ <span style="color:var(--muted)">(<?= htmlspecialchars((string)($fx['detail'] ?? '')) ?>)</span>
+ </div>
+ <?php endforeach; ?>
<?php if ($triChecks): ?>
<div style="margin-top:10px;font-size:.82em;color:var(--warn);">
<?php foreach (array_slice($triChecks, 0, 4) as $c): ?><div class="body"><?= htmlspecialchars($c) ?></div><?php endforeach; ?>
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),