sourcemap view
This commit is contained in:
1 parent
412e430cac
commit
97743ea21c
10 files changed
+452
-147
No files matched your search
@@ -1,8 +1,6 @@
|
||||
import { AlertTriangle, Download } from "lucide-react"
|
||||
import { Download } from "lucide-react"
|
||||
import React from "react";
|
||||
import { useObservabilityData } from "../hooks/useObservabilityData";
|
||||
import { useIssues } from "../hooks/useIssues";
|
||||
import { getServiceName, isSpanError } from "../lib/otel-utils";
|
||||
|
||||
export const CommandAndQueryBar: React.FC = () => {
|
||||
const {
|
||||
@@ -21,58 +19,8 @@ export const CommandAndQueryBar: React.FC = () => {
|
||||
setMinDurationMs,
|
||||
timeWindow,
|
||||
setTimeWindow,
|
||||
setActiveTab,
|
||||
} = useObservabilityData();
|
||||
|
||||
const { issues } = useIssues();
|
||||
|
||||
// Compute real error metrics from filtered signals
|
||||
const errorStats = React.useMemo(() => {
|
||||
let errorCount = 0;
|
||||
const servicesWithErrors = new Set<string>();
|
||||
|
||||
logs.forEach((l) =>
|
||||
(l.scopeLogs ?? []).forEach((sl) =>
|
||||
(sl.logRecords ?? []).forEach((r) => {
|
||||
if ((r.severityNumber ?? 0) >= 17) {
|
||||
errorCount++;
|
||||
const sName = getServiceName(l.resource?.attributes ?? [], r.attributes ?? []);
|
||||
if (sName !== "unknown-service") {
|
||||
servicesWithErrors.add(sName);
|
||||
}
|
||||
}
|
||||
}),
|
||||
),
|
||||
);
|
||||
|
||||
traces.forEach((t) =>
|
||||
(t.resourceSpans ?? []).forEach((rs) =>
|
||||
(rs.scopeSpans ?? []).forEach((ss) =>
|
||||
(ss.spans ?? []).forEach((s) => {
|
||||
if (isSpanError(s)) {
|
||||
errorCount++;
|
||||
const sName = getServiceName(rs.resource?.attributes ?? [], s.attributes ?? []);
|
||||
if (sName !== "unknown-service") {
|
||||
servicesWithErrors.add(sName);
|
||||
}
|
||||
}
|
||||
}),
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
return {
|
||||
errorCount,
|
||||
services: Array.from(servicesWithErrors),
|
||||
};
|
||||
}, [logs, traces]);
|
||||
|
||||
// Top open issue if available
|
||||
const topOpenIssue = React.useMemo(() => {
|
||||
const open = issues.filter((i) => !i.status || i.status === "open");
|
||||
return open.sort((a, b) => b.count - a.count)[0] || null;
|
||||
}, [issues]);
|
||||
|
||||
const totalFilteredEvents = logs.length + traces.length + metrics.length;
|
||||
|
||||
const exportNDJSON = () => {
|
||||
@@ -100,53 +48,6 @@ export const CommandAndQueryBar: React.FC = () => {
|
||||
|
||||
return (
|
||||
<div className="flex flex-col gap-2.5 mb-4 font-body">
|
||||
{/* Real Anomaly Radar Banner */}
|
||||
{(errorStats.errorCount > 0 || topOpenIssue) && (
|
||||
<div className="rounded-xl border border-ds-critical/30 bg-ds-surface-2 p-3 flex flex-col sm:flex-row sm:items-center justify-between gap-3 animate-in fade-in duration-300">
|
||||
<div className="flex items-center gap-2.5 min-w-0">
|
||||
<div className="flex h-7 w-7 shrink-0 items-center justify-center rounded-lg bg-ds-critical-bg text-ds-critical border border-ds-critical/40">
|
||||
<AlertTriangle className="h-[18px] w-[18px] shrink-0" aria-hidden="true" />
|
||||
</div>
|
||||
<div className="flex flex-col min-w-0">
|
||||
<div className="flex items-center gap-2">
|
||||
<span className="font-mono text-xs font-bold text-ds-critical uppercase tracking-wider">
|
||||
Anomaly Radar:
|
||||
</span>
|
||||
<span className="font-mono text-xs text-ds-text truncate">
|
||||
{errorStats.errorCount > 0
|
||||
? `${errorStats.errorCount} errors in active window (${errorStats.services.join(", ") || "various"})`
|
||||
: `${topOpenIssue?.count} occurrences of "${topOpenIssue?.title}"`}
|
||||
</span>
|
||||
</div>
|
||||
{topOpenIssue && (
|
||||
<span className="text-[11px] text-ds-text-2 truncate">
|
||||
Top Issue: <span className="text-ds-text font-semibold">{topOpenIssue.title}</span> (Service: {topOpenIssue.service}, ×{topOpenIssue.count})
|
||||
</span>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="flex items-center gap-2 shrink-0">
|
||||
<button
|
||||
type="button"
|
||||
onClick={() => setActiveTab("tab0")}
|
||||
className="px-3 py-1 rounded-lg bg-ds-critical hover:bg-ds-critical text-ds-text font-mono text-xs font-bold transition-colors"
|
||||
>
|
||||
Triage Issues
|
||||
</button>
|
||||
{!showErrorsOnly && (
|
||||
<button
|
||||
type="button"
|
||||
onClick={() => setShowErrorsOnly(true)}
|
||||
className="px-2.5 py-1 rounded-lg bg-ds-fill hover:bg-ds-fill text-ds-text font-mono text-xs transition-colors"
|
||||
>
|
||||
Isolate Errors
|
||||
</button>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{/* Filter and Telemetry Status Bar */}
|
||||
<div className="flex flex-wrap items-center justify-between gap-2.5 p-3 rounded-xl bg-ds-bg border border-ds-line">
|
||||
<div className="flex items-center gap-2 flex-wrap">
|
||||
|
||||
Reference in new issue
Block a user