| 147 | } |
| 148 | |
| 149 | function printMarkdown(result, since) { |
| 150 | const sinceStr = since ? new Date(since).toISOString() : 'all time'; |
| 151 | console.log('# RecallVerify Report (since ' + sinceStr + ')'); |
| 152 | console.log(''); |
| 153 | if (result.rows.length === 0) { |
| 154 | console.log('_No `recall_verify` events found in memory graph._'); |
| 155 | console.log(''); |
| 156 | console.log('Ship gate: **RED** (no data — feature may be disabled or daemon has not run a publish cycle yet)'); |
| 157 | return; |
| 158 | } |
| 159 | console.log('| asset_type | total | ok | missing | mismatch | skipped | success_rate | p50_latency | p99_latency | p50_age | p99_age |'); |
| 160 | console.log('|--------------|------:|----:|--------:|---------:|--------:|-------------:|------------:|------------:|--------:|--------:|'); |
| 161 | for (const r of result.rows) { |
| 162 | console.log('| ' + r.type.padEnd(12) + |
| 163 | ' | ' + String(r.total).padStart(5) + |
| 164 | ' | ' + String(r.ok).padStart(3) + |
| 165 | ' | ' + String(r.missing).padStart(7) + |
| 166 | ' | ' + String(r.mismatch).padStart(8) + |
| 167 | ' | ' + String(r.skipped).padStart(7) + |
| 168 | ' | ' + fmtPct(r.success_rate).padStart(12) + |
| 169 | ' | ' + fmtMs(r.p50_latency_ms).padStart(11) + |
| 170 | ' | ' + fmtMs(r.p99_latency_ms).padStart(11) + |
| 171 | ' | ' + fmtMs(r.p50_age_ms).padStart(7) + |
| 172 | ' | ' + fmtMs(r.p99_age_ms).padStart(7) + |
| 173 | ' |'); |
| 174 | } |
| 175 | const t = result.totals; |
| 176 | console.log('| ' + 'TOTAL'.padEnd(12) + |
| 177 | ' | ' + String(t.total).padStart(5) + |
| 178 | ' | ' + String(t.ok).padStart(3) + |
| 179 | ' | ' + String(t.missing).padStart(7) + |
| 180 | ' | ' + String(t.mismatch).padStart(8) + |
| 181 | ' | ' + String(t.skipped).padStart(7) + |
| 182 | ' | ' + fmtPct(t.success_rate).padStart(12) + |
| 183 | ' | ' + '—'.padStart(11) + |
| 184 | ' | ' + '—'.padStart(11) + |
| 185 | ' | ' + '—'.padStart(7) + |
| 186 | ' | ' + '—'.padStart(7) + |
| 187 | ' |'); |
| 188 | console.log(''); |
| 189 | console.log('Ship gate: **' + result.gate + '**' + (result.gate === 'GREEN' ? ' (exit 0)' : ' (exit 2)')); |
| 190 | } |
| 191 | |
| 192 | function main() { |
| 193 | const args = parseArgs(process.argv); |