chore: reorganize docs, document migrations, gitignore operational files for v1.0.0 release
This commit is contained in:
83
docs/troubleshooting/diagnose-chart-alignment.js
Normal file
83
docs/troubleshooting/diagnose-chart-alignment.js
Normal file
@@ -0,0 +1,83 @@
|
||||
#!/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);
|
||||
});
|
||||
Reference in New Issue
Block a user