84 lines
2.9 KiB
JavaScript
84 lines
2.9 KiB
JavaScript
#!/usr/bin/env node
|
|
// Diagnostic: check alignment between counts history dates and anomaly log dates
|
|
// Usage: node backend/scripts/diagnose-chart-alignment.js
|
|
|
|
const path = require('path');
|
|
const sqlite3 = require('sqlite3').verbose();
|
|
const DB_PATH = path.join(__dirname, '..', 'cve_database.db');
|
|
|
|
function dbAll(db, sql, params = []) {
|
|
return new Promise((resolve, reject) => {
|
|
db.all(sql, params, (err, rows) => {
|
|
if (err) reject(err);
|
|
else resolve(rows || []);
|
|
});
|
|
});
|
|
}
|
|
|
|
function fmtDate(d) {
|
|
if (!d) return '';
|
|
const p = d.split('-');
|
|
if (p.length === 3) return `${p[1]}/${p[2]}/${p[0].slice(2)}`;
|
|
return d;
|
|
}
|
|
|
|
function extractDate(ts) {
|
|
if (!ts) return '';
|
|
return ts.split('T')[0].split(' ')[0];
|
|
}
|
|
|
|
async function main() {
|
|
const db = new sqlite3.Database(DB_PATH);
|
|
|
|
// Get counts history dates (same query as the API)
|
|
const countsRows = await dbAll(db,
|
|
`SELECT date FROM (
|
|
SELECT DATE(recorded_at) AS date,
|
|
ROW_NUMBER() OVER (PARTITION BY DATE(recorded_at) ORDER BY recorded_at DESC) AS rn
|
|
FROM ivanti_counts_history
|
|
) WHERE rn = 1 ORDER BY date ASC`
|
|
);
|
|
const countsDates = new Set(countsRows.map(r => fmtDate(r.date)));
|
|
|
|
// Get anomaly history (same query as the API)
|
|
const anomalyRows = await dbAll(db,
|
|
`SELECT sync_timestamp, newly_archived_count, returned_count, return_classification_json
|
|
FROM ivanti_sync_anomaly_log
|
|
ORDER BY sync_timestamp DESC LIMIT 30`
|
|
);
|
|
|
|
console.log('=== Counts History Dates (last 10) ===');
|
|
const lastTen = countsRows.slice(-10);
|
|
for (const r of lastTen) {
|
|
console.log(` ${r.date} → ${fmtDate(r.date)}`);
|
|
}
|
|
|
|
console.log('\n=== Anomaly Log Entries with Activity ===');
|
|
for (const a of anomalyRows) {
|
|
if (a.newly_archived_count === 0 && a.returned_count === 0) continue;
|
|
const rawDate = extractDate(a.sync_timestamp);
|
|
const dateKey = fmtDate(rawDate);
|
|
const inCounts = countsDates.has(dateKey);
|
|
console.log(` ${a.sync_timestamp} → raw="${rawDate}" → key="${dateKey}" | archived=${a.newly_archived_count} returned=${a.returned_count} | in counts: ${inCounts ? 'YES' : '*** NO ***'}`);
|
|
}
|
|
|
|
console.log('\n=== All Anomaly Dates NOT in Counts History ===');
|
|
let missingCount = 0;
|
|
for (const a of anomalyRows) {
|
|
const rawDate = extractDate(a.sync_timestamp);
|
|
const dateKey = fmtDate(rawDate);
|
|
if (!countsDates.has(dateKey)) {
|
|
console.log(` MISSING: ${a.sync_timestamp} → "${dateKey}" (archived=${a.newly_archived_count}, returned=${a.returned_count})`);
|
|
missingCount++;
|
|
}
|
|
}
|
|
if (missingCount === 0) console.log(' (none — all anomaly dates have matching counts history)');
|
|
|
|
db.close();
|
|
}
|
|
|
|
main().catch(err => {
|
|
console.error('Fatal error:', err);
|
|
process.exit(1);
|
|
});
|