feat(collector): capture additional smartctl diagnostics
Record host read and write commands, controller busy time, error log entries, warning and critical temperature time, and thermal management transitions from the existing smartctl -a -j acquisition. Schema 7 adds nullable columns to samples so legacy rows read as unknown, and the Diagnostics panel shows each counter with its change.
This commit is contained in:
@@ -51,8 +51,25 @@ DIAGNOSTIC_COUNTERS = (
|
||||
("unsafe_shutdowns", "Unsafe shutdowns", ""),
|
||||
("media_errors", "Media errors", ""),
|
||||
("available_spare", "Available spare", "%"),
|
||||
("host_reads", "Host reads", ""),
|
||||
("host_writes", "Host writes", ""),
|
||||
("controller_busy_time", "Controller busy time", " min"),
|
||||
("num_err_log_entries", "Error log entries", ""),
|
||||
("warning_temp_time", "Warning temperature time", " min"),
|
||||
("critical_comp_time", "Critical temperature time", " min"),
|
||||
("thm_temp1_trans_count", "Thermal management 1 transitions", ""),
|
||||
("thm_temp1_total_time", "Thermal management 1 time", " s"),
|
||||
("thm_temp2_trans_count", "Thermal management 2 transitions", ""),
|
||||
("thm_temp2_total_time", "Thermal management 2 time", " s"),
|
||||
)
|
||||
|
||||
# Reported only by drives that implement thermal management; with no value the
|
||||
# panel omits them instead of listing four permanent n/a rows.
|
||||
_OPTIONAL_DIAGNOSTICS = frozenset((
|
||||
"thm_temp1_trans_count", "thm_temp1_total_time",
|
||||
"thm_temp2_trans_count", "thm_temp2_total_time",
|
||||
))
|
||||
|
||||
LOCAL_ACTIVITY_STATE_LABELS = {
|
||||
"so_far": "totals so far",
|
||||
"incomplete": "incomplete",
|
||||
@@ -689,7 +706,10 @@ def _counter_deltas(
|
||||
inside the window; with fewer than two distinct samples, or across a
|
||||
controller-segment change, there is no delta.
|
||||
"""
|
||||
columns = ", ".join(key for key, _, _ in DIAGNOSTIC_COUNTERS)
|
||||
# A store not yet migrated lacks the newer counter columns: read them as unknown.
|
||||
present = {row[1] for row in conn.execute("PRAGMA table_info(samples)")}
|
||||
columns = ", ".join(
|
||||
key if key in present else "NULL" for key, _, _ in DIAGNOSTIC_COUNTERS)
|
||||
columns += ", segment_id"
|
||||
last = conn.execute(
|
||||
"SELECT id, %s FROM samples WHERE ts <= ? ORDER BY ts DESC, id DESC "
|
||||
@@ -1016,6 +1036,8 @@ def diagnostics_text(activity: ActivityReadout) -> str:
|
||||
for key, label, unit in DIAGNOSTIC_COUNTERS:
|
||||
counter = diag["counters"][key]
|
||||
if counter["value"] is None:
|
||||
if key in _OPTIONAL_DIAGNOSTICS:
|
||||
continue
|
||||
lines.append("%s n/a" % label)
|
||||
continue
|
||||
delta = "Δ n/a" if counter["delta"] is None else "Δ " + _signed(counter["delta"])
|
||||
|
||||
Reference in New Issue
Block a user