Research Labs

2026-09-17 20:38 UTCopen field data · live

pages/health.php

Snapshot 2026.09.17-a2894de (current) · 27 lines · 2,545 bytes · tree · plain text

SHA-256 a2a14e6519d2740f43d4aea19f91992e789f306323442c8c13fc6cb908078147
1<?php
2require_once __DIR__.'/../inc/layout.php';
3page_header('Health','health');
4echo '<h1>Instrumentation health</h1><p class="lede">Status, freshness, 7-day completeness and a simple failure-risk read for every instrument. The same checks run by cron and email the administrator when something degrades; the laboratory admits its own gaps the moment they open.</p>';
5$insts=db()->query("SELECT * FROM instruments ORDER BY zone, name")->fetchAll();
6echo '<table class="data"><tr><th>Instrument</th><th>Zone</th><th>Status</th><th>Last reading</th><th>Freshness</th><th>7-day completeness</th><th>Risk</th></tr>';
7foreach($insts as $i){
8 $q=db()->prepare("SELECT MAX(r.ts) m FROM readings r JOIN streams s ON s.id=r.stream_id WHERE s.instrument_id=? AND r.is_placeholder=(SELECT IF(MIN(mode)='live',0,1) FROM streams WHERE instrument_id=?)");
9 $q->execute([$i['id'],$i['id']]); $last=$q->fetch()['m'];
10 $age=$last?(time()-strtotime($last))/60:1e9;
11 $fresh=$last?($age<max(90,$i['cadence_min']*2)?'fresh':($age<$i['cadence_min']*6?'late':'silent')):'none';
12 $exp = max(1, intdiv(7*24*60, max(1,$i['cadence_min'])));
13 $q2=db()->prepare("SELECT COUNT(*) c FROM readings r JOIN streams s ON s.id=r.stream_id WHERE s.instrument_id=? AND r.ts>DATE_SUB(NOW(),INTERVAL 7 DAY)");
14 $q2->execute([$i['id']]); $got=$q2->fetch()['c'];
15 $comp=min(100,round(100*$got/ max(1,$exp*max(1,db()->query("SELECT COUNT(*) c FROM streams WHERE instrument_id=".$i['id'])->fetch()['c']))));
16 $q3=db()->prepare("SELECT COUNT(*) c FROM events WHERE instrument_id=? AND class IN ('fault','gap') AND ts>DATE_SUB(NOW(),INTERVAL 14 DAY)");
17 $q3->execute([$i['id']]); $recent_faults=$q3->fetch()['c'];
18 $risk = $fresh==='silent'||$fresh==='none' ? 'HIGH' : ($comp<70||$recent_faults>2 ? 'ELEVATED' : ($comp<90||$recent_faults>0 ? 'WATCH' : 'LOW'));
19 $rc=['LOW'=>C_GOOD,'WATCH'=>C_WARN,'ELEVATED'=>C_SERIOUS,'HIGH'=>C_CRIT][$risk];
20 echo '<tr><td>'.h($i['name']).'<div class="kv">'.h($i['product']).'</div></td><td>'.h($i['zone']).'</td>';
21 echo '<td>'.inst_status_badge($i['status']).'</td><td>'.h($last?:'never').'</td><td>'.h($fresh).'</td>';
22 echo '<td>'.$comp.'%</td><td class="risk" style="color:'.$rc.'">●&nbsp;'.$risk.'</td></tr>';
23}
24echo '</table>';
25echo '<p class="note">Risk heuristic v0: silence and completeness plus recent fault frequency. As the record grows this page gains trend-based prediction (rising gap frequency, battery and signal telemetry where instruments expose them) so failures are anticipated, not discovered.</p>';
26page_footer();
27

Lines can be cited as pages/health.php L120-L140, platform code 2026.09.17-a2894de; add #L120-L140 to this page's address to highlight them. Source shown for scrutiny of the research platform. All rights reserved. Not offered as installable software.