fix: query documents table for analytics instead of empty events table

The document_processing_events table was never populated. Analytics
endpoints now query the documents table directly using status and
timestamp columns. Also updated upload page labels to remove outdated
"Agentic RAG" references.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
admin
2026-02-25 12:05:25 -05:00
parent 8f9c225ebc
commit cbe7761558
3 changed files with 32 additions and 32 deletions

View File

@@ -170,8 +170,9 @@ export interface SessionAnalytics {
}
/**
* Returns per-day session statistics from document_processing_events.
* Groups upload_started events by date, then joins completed/failed counts.
* Returns per-day session statistics from the documents table.
* Groups documents by creation date, counts by status, and derives processing time
* from (updated_at - created_at) for completed documents.
*/
export async function getSessionAnalytics(days: number): Promise<SessionAnalytics> {
const pool = getPostgresPool();
@@ -186,11 +187,14 @@ export async function getSessionAnalytics(days: number): Promise<SessionAnalytic
}>(`
SELECT
DATE(created_at) AS date,
COUNT(*) FILTER (WHERE event_type = 'upload_started') AS total_sessions,
COUNT(*) FILTER (WHERE event_type = 'completed') AS successful_sessions,
COUNT(*) FILTER (WHERE event_type = 'failed') AS failed_sessions,
COALESCE(AVG(duration_ms) FILTER (WHERE event_type = 'completed'), 0) AS avg_processing_time
FROM document_processing_events
COUNT(*) AS total_sessions,
COUNT(*) FILTER (WHERE status = 'completed') AS successful_sessions,
COUNT(*) FILTER (WHERE status = 'failed') AS failed_sessions,
COALESCE(
AVG(EXTRACT(EPOCH FROM (updated_at - created_at)) * 1000)
FILTER (WHERE status = 'completed'), 0
) AS avg_processing_time
FROM documents
WHERE created_at >= NOW() - $1::interval
GROUP BY DATE(created_at)
ORDER BY date DESC
@@ -230,7 +234,7 @@ export interface ProcessingStatsFromEvents {
}
/**
* Returns processing pipeline statistics from document_processing_events.
* Returns processing pipeline statistics from the documents table.
*/
export async function getProcessingStatsFromEvents(): Promise<ProcessingStatsFromEvents> {
const pool = getPostgresPool();
@@ -241,10 +245,11 @@ export async function getProcessingStatsFromEvents(): Promise<ProcessingStatsFro
avg_processing_ms: string | null;
}>(`
SELECT
COUNT(DISTINCT document_id) AS total_documents,
COUNT(*) FILTER (WHERE event_type = 'completed') AS succeeded,
AVG(duration_ms) FILTER (WHERE event_type = 'completed') AS avg_processing_ms
FROM document_processing_events
COUNT(*) AS total_documents,
COUNT(*) FILTER (WHERE status = 'completed') AS succeeded,
AVG(EXTRACT(EPOCH FROM (updated_at - created_at)) * 1000)
FILTER (WHERE status = 'completed') AS avg_processing_ms
FROM documents
`);
const row = rows[0]!;
@@ -256,7 +261,7 @@ export async function getProcessingStatsFromEvents(): Promise<ProcessingStatsFro
documentAiAgenticRag: row.avg_processing_ms ? parseFloat(row.avg_processing_ms) : 0,
},
averageApiCalls: {
documentAiAgenticRag: 0, // API call counting not tracked in events table
documentAiAgenticRag: 0,
},
};
}
@@ -278,7 +283,7 @@ export interface HealthFromEvents {
}
/**
* Derives system health status from recent document_processing_events.
* Derives system health status from recent documents.
* Looks at the last 24 hours to determine health.
*/
export async function getHealthFromEvents(): Promise<HealthFromEvents> {
@@ -293,18 +298,14 @@ export async function getHealthFromEvents(): Promise<HealthFromEvents> {
}>(`
SELECT
COUNT(*) AS total,
COUNT(*) FILTER (WHERE event_type = 'completed') AS succeeded,
COUNT(*) FILTER (WHERE event_type = 'failed') AS failed,
AVG(duration_ms) FILTER (WHERE event_type = 'completed') AS avg_processing_ms,
COUNT(*) FILTER (WHERE status = 'completed') AS succeeded,
COUNT(*) FILTER (WHERE status = 'failed') AS failed,
AVG(EXTRACT(EPOCH FROM (updated_at - created_at)) * 1000)
FILTER (WHERE status = 'completed') AS avg_processing_ms,
COUNT(*) FILTER (
WHERE event_type = 'processing_started'
AND document_id NOT IN (
SELECT document_id FROM document_processing_events
WHERE event_type IN ('completed', 'failed')
AND created_at >= NOW() - INTERVAL '24 hours'
)
WHERE status NOT IN ('completed', 'failed')
) AS active
FROM document_processing_events
FROM documents
WHERE created_at >= NOW() - INTERVAL '24 hours'
`);

View File

@@ -226,7 +226,7 @@ const Analytics: React.FC = () => {
<h3 className="text-md font-medium text-gray-700">Average Processing Time</h3>
<div className="space-y-2">
<div className="flex justify-between">
<span className="text-sm text-gray-600">Document AI + Agentic RAG</span>
<span className="text-sm text-gray-600">Single-Pass + Quality Check</span>
<span className="text-sm font-medium">{formatTime(processingStats.averageProcessingTime?.documentAiAgenticRag ?? 0)}</span>
</div>
</div>
@@ -236,7 +236,7 @@ const Analytics: React.FC = () => {
<div className="space-y-2">
<div className="flex justify-between">
<span className="text-sm text-gray-600">Processing Method</span>
<span className="text-sm font-medium">Document AI + Agentic RAG</span>
<span className="text-sm font-medium">Single-Pass + Quality Check</span>
</div>
</div>
</div>

View File

@@ -325,7 +325,7 @@ const DocumentUpload: React.FC<DocumentUploadProps> = ({
case 'uploaded':
return 'Uploaded to Cloud Storage ✓';
case 'processing':
return 'Processing with Document AI + Optimized Agentic RAG...';
return 'Processing with AI-Powered CIM Analysis...';
case 'completed':
return 'Completed ✓ (PDF automatically deleted)';
case 'error':
@@ -344,10 +344,9 @@ const DocumentUpload: React.FC<DocumentUploadProps> = ({
<div className="flex items-center">
<CheckCircle className="h-5 w-5 text-blue-600 mr-2" />
<div>
<h3 className="text-sm font-medium text-blue-800">Document AI + Optimized Agentic RAG Processing</h3>
<h3 className="text-sm font-medium text-blue-800">AI-Powered CIM Analysis Processing</h3>
<p className="text-sm text-blue-700 mt-1">
All documents are automatically processed using Google Document AI for extraction and our advanced optimized agentic RAG system for analysis,
including intelligent chunking, vectorization, and multi-agent CIM review. PDFs are automatically deleted after processing.
All documents are automatically processed using AI-powered extraction and structured CIM review analysis. PDFs are automatically deleted after processing.
</p>
</div>
</div>
@@ -372,7 +371,7 @@ const DocumentUpload: React.FC<DocumentUploadProps> = ({
Drag and drop PDF files here, or click to browse
</p>
<p className="text-xs text-gray-500">
Maximum file size: 50MB Supported format: PDF Stored securely in Cloud Storage Automatic Document AI + Optimized Agentic RAG Processing PDFs deleted after processing
Maximum file size: 50MB Supported format: PDF Stored securely in Cloud Storage Automatic AI-Powered CIM Analysis Processing PDFs deleted after processing
</p>
</div>
@@ -401,7 +400,7 @@ const DocumentUpload: React.FC<DocumentUploadProps> = ({
<h4 className="text-sm font-medium text-success-800">Upload Complete</h4>
<p className="text-sm text-success-700 mt-1">
Files have been uploaded successfully! You can now navigate away from this page.
Processing will continue in the background using Document AI + Optimized Agentic RAG. This can take several minutes. PDFs will be automatically deleted after processing to save costs.
Processing will continue in the background using AI-Powered CIM Analysis. This can take several minutes. PDFs will be automatically deleted after processing to save costs.
</p>
</div>
</div>