sourcemap view
Build and Publish / Metadata (push) Successful in 2s
Build and Publish / BuildAndDeployAmd64 (push) Successful in 1m4s

This commit is contained in:
mats committed 2026-09-19 15:49:44 +02:00
1 parent 412e430cac
commit 97743ea21c
10 files changed
+452 -147

No files matched your search

@@ -0,0 +1,93 @@
import { AlertTriangle, ArrowRight } from "lucide-react"
import React from "react"
import { useObservabilityData } from "../hooks/useObservabilityData"
import { useIssues } from "../hooks/useIssues"
import { getServiceName, isSpanError } from "../lib/otel-utils"
/** Full-width alert strip docked under the top bar; renders nothing when there is nothing anomalous. */
export const AnomalyRadarBar: React.FC = () => {
const { logs, traces, showErrorsOnly, setShowErrorsOnly, setActiveTab } = useObservabilityData()
const { issues } = useIssues()
const errorStats = React.useMemo(() => {
let errorCount = 0
const services = new Set<string>()
const note = (name: string) => { if (name !== "unknown-service") services.add(name) }
logs.forEach((l) =>
(l.scopeLogs ?? []).forEach((sl) =>
(sl.logRecords ?? []).forEach((r) => {
if ((r.severityNumber ?? 0) >= 17) {
errorCount++
note(getServiceName(l.resource?.attributes ?? [], r.attributes ?? []))
}
}),
),
)
traces.forEach((t) =>
(t.resourceSpans ?? []).forEach((rs) =>
(rs.scopeSpans ?? []).forEach((ss) =>
(ss.spans ?? []).forEach((s) => {
if (isSpanError(s)) {
errorCount++
note(getServiceName(rs.resource?.attributes ?? [], s.attributes ?? []))
}
}),
),
),
)
return { errorCount, services: Array.from(services) }
}, [logs, traces])
const topOpenIssue = React.useMemo(
() => issues.filter((i) => !i.status || i.status === "open").sort((a, b) => b.count - a.count)[0] ?? null,
[issues],
)
if (errorStats.errorCount === 0 && !topOpenIssue) return null
const services = errorStats.services.slice(0, 3).join(", ") + (errorStats.services.length > 3 ? ` +${errorStats.services.length - 3}` : "")
return (
<div
role="alert"
className="sticky top-[58px] z-30 flex flex-wrap items-center gap-x-4 gap-y-1.5 border-b-2 border-ds-critical bg-ds-critical-bg px-6 py-2 font-[family-name:var(--font-ui)]"
>
<span className="inline-flex shrink-0 items-center gap-1.5 text-[11px] font-bold uppercase tracking-[0.1em] text-ds-critical">
<AlertTriangle className="h-3.5 w-3.5" aria-hidden="true" />
Anomaly radar
</span>
<span className="min-w-0 flex-1 truncate text-[12.5px] text-ds-text">
{errorStats.errorCount > 0 && (
<><strong className="font-semibold">{errorStats.errorCount} errors</strong> in the active window{services && <span className="text-ds-text-2"> · {services}</span>}</>
)}
{topOpenIssue && (
<span className="text-ds-text-2">
{errorStats.errorCount > 0 ? " · top issue " : ""}
<span className="font-medium text-ds-text">{topOpenIssue.title}</span> ×{topOpenIssue.count} ({topOpenIssue.service})
</span>
)}
</span>
<div className="flex shrink-0 items-center gap-2">
{!showErrorsOnly && (
<button
type="button"
onClick={() => setShowErrorsOnly(true)}
className="inline-flex h-7 items-center rounded-[8px] border border-ds-critical/40 px-2.5 text-[12px] font-medium text-ds-critical hover:bg-ds-critical/10"
>
Isolate errors
</button>
)}
<button
type="button"
onClick={() => setActiveTab("tab0")}
className="inline-flex h-7 items-center gap-1 rounded-[8px] bg-ds-critical px-2.5 text-[12px] font-semibold text-white hover:opacity-90"
>
Triage issues <ArrowRight className="h-3 w-3" aria-hidden="true" />
</button>
</div>
</div>
)
}
export default AnomalyRadarBar