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. * Returns per-day session statistics from the documents table.
* Groups upload_started events by date, then joins completed/failed counts. * 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> { export async function getSessionAnalytics(days: number): Promise<SessionAnalytics> {
const pool = getPostgresPool(); const pool = getPostgresPool();
@@ -186,11 +187,14 @@ export async function getSessionAnalytics(days: number): Promise<SessionAnalytic
}>(` }>(`
SELECT SELECT
DATE(created_at) AS date, DATE(created_at) AS date,
COUNT(*) FILTER (WHERE event_type = 'upload_started') AS total_sessions, COUNT(*) AS total_sessions,
COUNT(*) FILTER (WHERE event_type = 'completed') AS successful_sessions, COUNT(*) FILTER (WHERE status = 'completed') AS successful_sessions,
COUNT(*) FILTER (WHERE event_type = 'failed') AS failed_sessions, COUNT(*) FILTER (WHERE status = 'failed') AS failed_sessions,
COALESCE(AVG(duration_ms) FILTER (WHERE event_type = 'completed'), 0) AS avg_processing_time COALESCE(
FROM document_processing_events 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 WHERE created_at >= NOW() - $1::interval
GROUP BY DATE(created_at) GROUP BY DATE(created_at)
ORDER BY date DESC 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> { export async function getProcessingStatsFromEvents(): Promise<ProcessingStatsFromEvents> {
const pool = getPostgresPool(); const pool = getPostgresPool();
@@ -241,10 +245,11 @@ export async function getProcessingStatsFromEvents(): Promise<ProcessingStatsFro
avg_processing_ms: string | null; avg_processing_ms: string | null;
}>(` }>(`
SELECT SELECT
COUNT(DISTINCT document_id) AS total_documents, COUNT(*) AS total_documents,
COUNT(*) FILTER (WHERE event_type = 'completed') AS succeeded, COUNT(*) FILTER (WHERE status = 'completed') AS succeeded,
AVG(duration_ms) FILTER (WHERE event_type = 'completed') AS avg_processing_ms AVG(EXTRACT(EPOCH FROM (updated_at - created_at)) * 1000)
FROM document_processing_events FILTER (WHERE status = 'completed') AS avg_processing_ms
FROM documents
`); `);
const row = rows[0]!; 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, documentAiAgenticRag: row.avg_processing_ms ? parseFloat(row.avg_processing_ms) : 0,
}, },
averageApiCalls: { 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. * Looks at the last 24 hours to determine health.
*/ */
export async function getHealthFromEvents(): Promise<HealthFromEvents> { export async function getHealthFromEvents(): Promise<HealthFromEvents> {
@@ -293,18 +298,14 @@ export async function getHealthFromEvents(): Promise<HealthFromEvents> {
}>(` }>(`
SELECT SELECT
COUNT(*) AS total, COUNT(*) AS total,
COUNT(*) FILTER (WHERE event_type = 'completed') AS succeeded, COUNT(*) FILTER (WHERE status = 'completed') AS succeeded,
COUNT(*) FILTER (WHERE event_type = 'failed') AS failed, COUNT(*) FILTER (WHERE status = 'failed') AS failed,
AVG(duration_ms) FILTER (WHERE event_type = 'completed') AS avg_processing_ms, AVG(EXTRACT(EPOCH FROM (updated_at - created_at)) * 1000)
FILTER (WHERE status = 'completed') AS avg_processing_ms,
COUNT(*) FILTER ( COUNT(*) FILTER (
WHERE event_type = 'processing_started' WHERE status NOT IN ('completed', 'failed')
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'
)
) AS active ) AS active
FROM document_processing_events FROM documents
WHERE created_at >= NOW() - INTERVAL '24 hours' 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> <h3 className="text-md font-medium text-gray-700">Average Processing Time</h3>
<div className="space-y-2"> <div className="space-y-2">
<div className="flex justify-between"> <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> <span className="text-sm font-medium">{formatTime(processingStats.averageProcessingTime?.documentAiAgenticRag ?? 0)}</span>
</div> </div>
</div> </div>
@@ -236,7 +236,7 @@ const Analytics: React.FC = () => {
<div className="space-y-2"> <div className="space-y-2">
<div className="flex justify-between"> <div className="flex justify-between">
<span className="text-sm text-gray-600">Processing Method</span> <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> </div>
</div> </div>

View File

@@ -325,7 +325,7 @@ const DocumentUpload: React.FC<DocumentUploadProps> = ({
case 'uploaded': case 'uploaded':
return 'Uploaded to Cloud Storage ✓'; return 'Uploaded to Cloud Storage ✓';
case 'processing': case 'processing':
return 'Processing with Document AI + Optimized Agentic RAG...'; return 'Processing with AI-Powered CIM Analysis...';
case 'completed': case 'completed':
return 'Completed ✓ (PDF automatically deleted)'; return 'Completed ✓ (PDF automatically deleted)';
case 'error': case 'error':
@@ -344,10 +344,9 @@ const DocumentUpload: React.FC<DocumentUploadProps> = ({
<div className="flex items-center"> <div className="flex items-center">
<CheckCircle className="h-5 w-5 text-blue-600 mr-2" /> <CheckCircle className="h-5 w-5 text-blue-600 mr-2" />
<div> <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"> <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, All documents are automatically processed using AI-powered extraction and structured CIM review analysis. PDFs are automatically deleted after processing.
including intelligent chunking, vectorization, and multi-agent CIM review. PDFs are automatically deleted after processing.
</p> </p>
</div> </div>
</div> </div>
@@ -372,7 +371,7 @@ const DocumentUpload: React.FC<DocumentUploadProps> = ({
Drag and drop PDF files here, or click to browse Drag and drop PDF files here, or click to browse
</p> </p>
<p className="text-xs text-gray-500"> <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> </p>
</div> </div>
@@ -401,7 +400,7 @@ const DocumentUpload: React.FC<DocumentUploadProps> = ({
<h4 className="text-sm font-medium text-success-800">Upload Complete</h4> <h4 className="text-sm font-medium text-success-800">Upload Complete</h4>
<p className="text-sm text-success-700 mt-1"> <p className="text-sm text-success-700 mt-1">
Files have been uploaded successfully! You can now navigate away from this page. 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> </p>
</div> </div>
</div> </div>