Skip to content

Feat (Logging) - Add optional rotating file logging#44

Open
WACHIFOO wants to merge 2 commits into
pachterlab:releasefrom
WACHIFOO:feature/logging-module
Open

Feat (Logging) - Add optional rotating file logging#44
WACHIFOO wants to merge 2 commits into
pachterlab:releasefrom
WACHIFOO:feature/logging-module

Conversation

@WACHIFOO

@WACHIFOO WACHIFOO commented Jun 7, 2026

Copy link
Copy Markdown

Summary

Adds an optional, additive logging system to the controller software. It mirrors
everything the app already prints to the terminal (status messages and tracebacks)
into a rotating log file, without changing the existing terminal behaviour and
without modifying any of the existing print() calls.

Motivation

The controller currently has no logging — status and errors are only written to the
terminal. That terminal is invisible in the two most common deployments:

  • the packaged single-click executable, and
  • a Raspberry Pi launched from a desktop icon.

So when a pump misbehaves or the serial connection to the Arduino fails, there is no
persistent record
to diagnose the problem or attach to a bug report. This is exactly
the kind of failure users hit in a wet-lab setup.

What this PR does

  • Adds SOFTWARE/poseidon_logging.py, a small self-contained module.
  • main() calls setup_logging() once at startup (a 2-line change in
    poseidon_main.py; no existing print() is touched).
  • Writes to logs/poseidon.log (rotating, ~1 MB × 3 backups) with timestamps, level
    and thread name.
  • On by default, disabled with the environment variable POSEIDON_LOG=0.
  • Documents the feature in the README and ignores logs/ and *.log.

Design notes

  • Additive / non-invasive: sys.stdout and sys.stderr are wrapped so the existing
    print() calls and tracebacks are captured transparently. The console output is
    unchanged (plain text, no prefixes; stdout→stdout, stderr→stderr).
  • Safe fallbacks: if the log file can't be created (e.g. a read-only folder) or there
    is no console (frozen .exe), it degrades gracefully and the app behaves exactly as
    before.
  • Thread-safe: the app is multithreaded (QThread); each thread buffers its own
    lines, and a re-entrancy guard prevents a failing log handler from recursing.
  • No new dependencies — standard library only.

Example

The same status/errors you see in the terminal, now also captured with context:

2026-06-07 07:28:12,986 INFO [MainThread] RUN command sent. 2026-06-07 07:28:12,990 ERROR [PumpWorker] Traceback (most recent call last): 2026-06-07 07:28:12,991 ERROR [PumpWorker] ... 2026-06-07 07:28:12,992 ERROR [PumpWorker] OSError: could not open serial port 'COM3' ​

Testing

Pure-Python module, no hardware/PyQt/serial needed. From the SOFTWARE/ folder:

python -m unittest test_poseidon_logging ​

17 tests cover: the POSEIDON_LOG off switch, file capture of stdout and stderr
tracebacks, line buffering and blank-line preservation, idempotent setup, the
no-console (frozen exe) fallback, the file-creation failure fallback, thread-safe
concurrent writes, stdout/stderr console separation, the file-like interface, and the
re-entrancy guard.

Testing notes

I don't have the pump/microscope hardware, so I haven't run this on a physical
device. The change is additive and doesn't touch the pump, serial, or GUI logic —
it only adds a log file and wraps stdout/stderr — so runtime behaviour should be
unaffected. I verified the logging module with the unit tests above and a standalone
script reproducing the app's real output patterns (status prints, a worker-thread
traceback, concurrent output). A maintainer with hardware may want a quick smoke test
to confirm startup is unaffected.

Backwards compatibility

Fully backwards compatible. With POSEIDON_LOG=0 the behaviour is identical to before;
with logging on, the terminal output is unchanged and only a log file is added.

Files changed

File Change
SOFTWARE/poseidon_logging.py new module
SOFTWARE/test_poseidon_logging.py new tests
SOFTWARE/poseidon_main.py +2 lines (import + setup_logging() call)
README.MD new "Logging" section
.gitignore ignore logs/ and *.log

Checklist

  • Additive — no existing print() modified
  • No new dependencies (stdlib only)
  • On by default, opt-out via POSEIDON_LOG=0
  • Tests added and passing (python -m unittest test_poseidon_logging)
  • README updated
  • Minimal diff to existing files

Happy to adjust scope or close this if it doesn't fit the project's direction.❤️

WACHIFOO and others added 2 commits June 7, 2026 07:41
The controller had no logging: status and errors were only printed to the
terminal, which is invisible when running the packaged executable or
launching from a Raspberry Pi desktop icon, so hardware/serial failures
left no trace.

Add poseidon_logging.py, a small additive module that mirrors stdout and
stderr (every existing print() and any traceback) into a rotating log file
at logs/poseidon.log, without changing the terminal output. It is on by
default and disabled with POSEIDON_LOG=0. main() calls setup_logging() at
startup; no existing print() is touched.

Document it in the README and ignore logs/ and *.log.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
unittest suite (stdlib, no new dependencies) covering: the POSEIDON_LOG
off switch, file capture of stdout and stderr tracebacks, line buffering
and blank-line preservation, idempotent setup, the no-console (frozen exe)
fallback, the file-creation failure fallback, thread-safe concurrent
writes, stdout/stderr console separation, the file-like interface, and the
re-entrancy guard against handler-error recursion.

Run from SOFTWARE/: python -m unittest test_poseidon_logging

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant