Files
cim_summary/backend/src/scripts/monitoring/monitor-system.ts
admin e406d33074 Refactor: Codebase cleanup and modularization
- Remove outdated documentation files (7 files)
- Remove deprecated code (database.ts, authController.ts, auth.ts)
- Extract constants to backend/src/config/constants.ts
- Consolidate shared types (processing, llm, document, job)
- Create LLM modularization structure:
  - llmPrompts/ directory for prompt builders
  - llmProviders/ directory for provider implementations
  - llmUtils/ directory for utility functions
- Extract common error handling patterns to errorHandlers.ts
- Organize scripts into subdirectories (monitoring/, testing/, debugging/, setup/)
- Update README.md with current documentation references

All functionality preserved, structure improved for maintainability.
2025-11-11 06:52:10 -05:00

172 lines
6.0 KiB
TypeScript
Raw Blame History

This file contains invisible Unicode characters
This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#!/usr/bin/env ts-node
/**
* Monitor system status - jobs, documents, and processing
*/
import dotenv from 'dotenv';
dotenv.config();
import { getPostgresPool } from '../config/supabase';
import { DocumentModel } from '../models/DocumentModel';
import { ProcessingJobModel } from '../models/ProcessingJobModel';
async function monitorSystem() {
console.log('🔍 Monitoring System Status...\n');
const pool = getPostgresPool();
try {
// Job status summary
const jobStatuses = await pool.query(`
SELECT status, COUNT(*) as count
FROM processing_jobs
GROUP BY status
ORDER BY status;
`);
console.log('📊 PROCESSING JOBS STATUS:');
if (jobStatuses.rows.length === 0) {
console.log(' No jobs found');
} else {
jobStatuses.rows.forEach(row => {
console.log(` ${row.status}: ${row.count}`);
});
}
// Recent jobs
const recentJobs = await pool.query(`
SELECT
id,
document_id,
status,
attempts,
max_attempts,
created_at,
started_at,
completed_at,
error
FROM processing_jobs
ORDER BY created_at DESC
LIMIT 10;
`);
console.log('\n📋 RECENT JOBS (last 10):');
if (recentJobs.rows.length === 0) {
console.log(' No jobs found');
} else {
recentJobs.rows.forEach(job => {
const id = job.id.substring(0, 8);
const docId = job.document_id.substring(0, 8);
const created = job.created_at ? new Date(job.created_at).toLocaleString() : 'N/A';
const started = job.started_at ? new Date(job.started_at).toLocaleString() : '-';
const completed = job.completed_at ? new Date(job.completed_at).toLocaleString() : '-';
const error = job.error ? ` | Error: ${job.error.substring(0, 50)}` : '';
console.log(` ${id}... | doc:${docId}... | ${job.status} | attempts: ${job.attempts}/${job.max_attempts}`);
console.log(` Created: ${created} | Started: ${started} | Completed: ${completed}${error}`);
});
}
// Stuck jobs (pending for more than 5 minutes)
const stuckJobs = await pool.query(`
SELECT id, document_id, status, created_at
FROM processing_jobs
WHERE status = 'pending'
AND created_at < NOW() - INTERVAL '5 minutes'
ORDER BY created_at ASC;
`);
if (stuckJobs.rows.length > 0) {
console.log(`\n⚠ STUCK JOBS (pending > 5 minutes): ${stuckJobs.rows.length}`);
stuckJobs.rows.forEach(job => {
const age = Math.round((Date.now() - new Date(job.created_at).getTime()) / 1000 / 60);
console.log(` ${job.id.substring(0, 8)}... | doc:${job.document_id.substring(0, 8)}... | pending for ${age} minutes`);
});
}
// Processing jobs (started but not completed)
const processingJobs = await pool.query(`
SELECT id, document_id, status, started_at
FROM processing_jobs
WHERE status = 'processing'
ORDER BY started_at DESC;
`);
if (processingJobs.rows.length > 0) {
console.log(`\n⏳ PROCESSING JOBS (currently running): ${processingJobs.rows.length}`);
processingJobs.rows.forEach(job => {
const duration = job.started_at
? Math.round((Date.now() - new Date(job.started_at).getTime()) / 1000 / 60)
: 0;
console.log(` ${job.id.substring(0, 8)}... | doc:${job.document_id.substring(0, 8)}... | running for ${duration} minutes`);
});
}
// Recent documents
const recentDocs = await pool.query(`
SELECT
id,
original_file_name,
status,
analysis_data IS NOT NULL as has_analysis,
generated_summary IS NOT NULL as has_summary,
created_at,
processing_completed_at
FROM documents
WHERE status IN ('processing_llm', 'processing', 'completed', 'failed')
ORDER BY created_at DESC
LIMIT 10;
`);
console.log('\n📄 RECENT DOCUMENTS (last 10):');
if (recentDocs.rows.length === 0) {
console.log(' No documents found');
} else {
recentDocs.rows.forEach(doc => {
const id = doc.id.substring(0, 8);
const name = doc.original_file_name || 'unnamed';
const created = doc.created_at ? new Date(doc.created_at).toLocaleString() : 'N/A';
const completed = doc.processing_completed_at ? new Date(doc.processing_completed_at).toLocaleString() : '-';
const analysis = doc.has_analysis ? '✅' : '❌';
const summary = doc.has_summary ? '✅' : '❌';
console.log(` ${id}... | ${name.substring(0, 40)}`);
console.log(` Status: ${doc.status} | Analysis: ${analysis} | Summary: ${summary}`);
console.log(` Created: ${created} | Completed: ${completed}`);
});
}
// Documents stuck in processing
const stuckDocs = await pool.query(`
SELECT id, original_file_name, status, created_at
FROM documents
WHERE status IN ('processing_llm', 'processing')
AND created_at < NOW() - INTERVAL '10 minutes'
ORDER BY created_at ASC;
`);
if (stuckDocs.rows.length > 0) {
console.log(`\n⚠ STUCK DOCUMENTS (processing > 10 minutes): ${stuckDocs.rows.length}`);
stuckDocs.rows.forEach(doc => {
const age = Math.round((Date.now() - new Date(doc.created_at).getTime()) / 1000 / 60);
console.log(` ${doc.id.substring(0, 8)}... | ${doc.original_file_name || 'unnamed'} | ${doc.status} for ${age} minutes`);
});
}
console.log('\n✅ Monitoring complete');
console.log('\n💡 To check Firebase logs:');
console.log(' firebase functions:log --only processDocumentJobs --limit 50');
console.log(' firebase functions:log --only api --limit 50');
await pool.end();
} catch (error) {
console.error('❌ Error monitoring system:', error instanceof Error ? error.message : String(error));
await pool.end();
process.exit(1);
}
}
monitorSystem().catch(console.error);