Logging & Replay¶
ILogWriter¶
Logging is built on a small interface, ILogWriter, with one
implementation per file format:
AscLogWriter- a CANalyzer-compatible baseline ASC trace format.CsvLogWriter- a flat CSV, one row per frame (see Logging Tab for the exact column list).
MainWindow::onFrameReceived() calls logWriter_->writeFrame() for every
single frame, unconditionally, before any of the display-rate throttling
described in Data Flow - logging is deliberately never
subject to that throttle, it exists purely to keep the UI responsive, never
to drop what gets written to disk.
Both writers handle the Rx/Tx direction on DecodedCanFrame the same
way: a frame MessageSender transmitted logs
identically to one actually received, just tagged by direction.
LogReplaySource¶
Log Replay loads a previously-saved file back and feeds it through
MainWindow::onFrameReceived() - the exact same slot a live
TsharkCapture and a live MessageSender feed. There is no separate
"replay mode" rendering path: Trace view, Graph view, and DBC decode all
behave completely identically whether the frame came from real hardware
seconds ago or a log file from last week. This is the same non-GUI-class
discipline followed throughout CANtrip - see
Headless Mode, which relies on exactly this.
Where signal-level decode lives¶
Neither ILogWriter nor LogReplaySource decode DBC signals themselves -
both only work with the raw DecodedCanFrame. The MessageName column
CsvLogWriter/AscLogWriter write comes from a small injected callback
(MessageNameResolver, a std::function), backed by DbcDecoder's
resolveMessageName() (app/DbcDecoder.h/.cpp, see
Data Flow) -
either MainWindow's own instance or, headless,
HeadlessRunner's. Full per-signal
decode (DbcDecoder::decodeSignals(), used for the Trace view's expandable
rows and Graph view plotting) is a separate call MainWindow makes for
its own UI needs - logging was never coupled to that heavier path, and
never needed MainWindow to have "already decoded" anything first.