fix: OpsPipeline dashboard — use time-filtered doc stages, add time labels
Document Stages now shows time-filtered counts from /health endpoint (consistent with Parsing/Extraction/Trends sections) with all-time totals shown as a subtle subtitle from the SSE stream. Added "(last Xh)" labels to all sections so the time window context is always visible.
This commit is contained in:
@@ -63,15 +63,18 @@ export function OpsPipelinePage() {
|
||||
const aggregation = (data?.aggregation ?? {}) as Record<string, unknown>;
|
||||
const pipelineEnabled = (data?.pipeline_enabled ?? true) as boolean;
|
||||
|
||||
// Prefer live stream data for queue depths and doc stages, fall back to initial fetch
|
||||
// Queue depths come from live stream (always current)
|
||||
// Document stages: show time-filtered from /health endpoint so numbers are consistent
|
||||
// with Parsing/Extraction/Trends sections. Stream provides live queue data only.
|
||||
const queueDepths = stream?.queue_depths
|
||||
?? (data?.queue_depths as Record<string, number> | undefined)
|
||||
?? {};
|
||||
const docStages = stream?.document_stages
|
||||
?? Object.fromEntries(
|
||||
const docStages = Object.fromEntries(
|
||||
((data?.document_stages as Array<{ status: string; doc_count: number }>) ?? [])
|
||||
.map((s) => [s.status, s.doc_count]),
|
||||
);
|
||||
// All-time totals from stream for reference
|
||||
const allTimeStages = stream?.document_stages ?? {};
|
||||
|
||||
const failedCount = docStages['extraction_failed'] ?? 0;
|
||||
|
||||
@@ -150,9 +153,13 @@ export function OpsPipelinePage() {
|
||||
|
||||
{/* Document Stage Counts */}
|
||||
<Card>
|
||||
<h2 className="mb-3 text-sm font-medium text-gray-400">Document Stages</h2>
|
||||
<h2 className="mb-3 text-sm font-medium text-gray-400">
|
||||
Document Stages
|
||||
<span className="ml-2 text-xs text-gray-600">(last {hours}h)</span>
|
||||
</h2>
|
||||
<div className="grid grid-cols-2 gap-3 sm:grid-cols-4">
|
||||
{Object.entries(docStages).map(([status, count]) => {
|
||||
const allTime = allTimeStages[status];
|
||||
const color = status === 'extracted' ? 'text-green-400'
|
||||
: status === 'parsed' ? 'text-yellow-400'
|
||||
: status === 'extraction_failed' ? 'text-red-400'
|
||||
@@ -162,6 +169,9 @@ export function OpsPipelinePage() {
|
||||
<div key={status} className="rounded-lg border border-surface-700 bg-surface-950 p-3 text-center">
|
||||
<div className={`text-2xl font-bold tabular-nums ${color}`}>{count}</div>
|
||||
<div className="text-xs capitalize text-gray-500">{status.replace('_', ' ')}</div>
|
||||
{allTime != null && allTime !== count && (
|
||||
<div className="mt-0.5 text-[10px] text-gray-600">{allTime} total</div>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
})}
|
||||
@@ -170,7 +180,10 @@ export function OpsPipelinePage() {
|
||||
|
||||
{/* Parsing Quality */}
|
||||
<Card>
|
||||
<h2 className="mb-3 text-sm font-medium text-gray-400">Parsing Quality</h2>
|
||||
<h2 className="mb-3 text-sm font-medium text-gray-400">
|
||||
Parsing Quality
|
||||
<span className="ml-2 text-xs text-gray-600">(last {hours}h)</span>
|
||||
</h2>
|
||||
<dl className="grid grid-cols-2 gap-3 text-sm sm:grid-cols-5">
|
||||
<Stat label="Total Parsed" value={parsing.total_parsed} />
|
||||
<Stat label="High Confidence" value={parsing.high_confidence} color="text-green-400" />
|
||||
@@ -182,7 +195,10 @@ export function OpsPipelinePage() {
|
||||
|
||||
{/* Extraction Stats */}
|
||||
<Card>
|
||||
<h2 className="mb-3 text-sm font-medium text-gray-400">Extraction Validation</h2>
|
||||
<h2 className="mb-3 text-sm font-medium text-gray-400">
|
||||
Extraction Validation
|
||||
<span className="ml-2 text-xs text-gray-600">(last {hours}h)</span>
|
||||
</h2>
|
||||
<dl className="grid grid-cols-2 gap-3 text-sm sm:grid-cols-5">
|
||||
<Stat label="Total" value={extraction.total_extractions} />
|
||||
<Stat label="Valid" value={extraction.valid} color="text-green-400" />
|
||||
@@ -194,7 +210,10 @@ export function OpsPipelinePage() {
|
||||
|
||||
{/* Aggregation */}
|
||||
<Card>
|
||||
<h2 className="mb-3 text-sm font-medium text-gray-400">Trend Generation</h2>
|
||||
<h2 className="mb-3 text-sm font-medium text-gray-400">
|
||||
Trend Generation
|
||||
<span className="ml-2 text-xs text-gray-600">(last {hours}h)</span>
|
||||
</h2>
|
||||
<dl className="grid grid-cols-2 gap-3 text-sm sm:grid-cols-4">
|
||||
<Stat label="Trends Generated" value={aggregation.trends_generated} />
|
||||
<Stat label="Symbols Covered" value={aggregation.symbols_covered} />
|
||||
|
||||
Reference in New Issue
Block a user