fix(log): record each message once in the journal, with its real priority - #9
Merged
Conversation
…rity Every CUEMS log line was reaching journald three times, and none of the copies could be filtered by level. 1. pyossia calls the module-level logging.info() helper at import time (reached via cuemsengine.osc). With no handler on the root logger yet, Python runs logging.basicConfig() implicitly, attaching a StreamHandler(stderr) using BASIC_FORMAT. Module loggers here propagate, so from then on every record was re-emitted through it as a second, differently formatted line. Seeding root with a NullHandler makes that implicit basicConfig() a no-op. Propagation is left enabled on purpose: pytest's caplog captures through a root handler and depends on it. 2. Under systemd, stdout and /dev/log both terminate in the same journal, so attaching both handlers recorded every message twice more. Keep only the syslog handler there — it is the only copy carrying the record's real priority, because systemd stamps every stdout line PRIORITY=6 regardless of level, which left journalctl -p (and so `cuems-logs -l/--level` and `-e/--errors`) unable to tell DEBUG from ERROR. Detection is JOURNAL_STREAM, set by systemd exactly when stdout is wired to the journal, so interactive runs and pytest still print to stdout. 3. Give the syslog handler an ident. journald parses SYSLOG_IDENTIFIER off a leading 'TAG:'; without one the entry has no identifier and journalctl falls back to _COMM, truncated by the kernel to 15 characters, so 'controller-engine' appeared as 'controller-engi' and read as a separate process. The PID is left out of the tag so journald's _PID, taken from the socket credentials, stays correct across a fork. Verified on the test2 controller: one journal entry per message, priorities DEBUG=7/WARNING=4/ERROR=3, full identifier, and stdout still used when JOURNAL_STREAM is absent. Test suite 552 passed, unchanged from baseline.
|
Bugbot is not enabled for your account, so this pull request was not reviewed. Enable Bugbot in the Cursor dashboard to get automatic reviews on future PRs. |
Codecov Report❌ Patch coverage is
📢 Thoughts on this report? Let us know! |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Every CUEMS log line was reaching journald three times, and none of the copies could be filtered by level. Found while debugging why
cuems-logslooked broken on the test2 controller.The three copies
StreamHandler(sys.stdout)stdoutcontroller-engine[…]: [ts][DEBUG] FormitGo…SysLogHandler('/dev/log')syslogcontroller-engi[…]: [ts][DEBUG] FormitGo…StreamHandler(stderr)stdoutcontroller-engine[…]: DEBUG:cuemsengine.…Measured on a controller:
cuems-controller-engineproduced 2781 journal entries for 927 logical messages;cuems-node-engine927 for 309.cuems-editor, which does not importcuemsengine.osc, sat at 1:1 stdout:syslog — which is what pinned down copy #3.What this changes
Copy Release v0.0.5 - Ensure proper xml and json reading and writing. #3 —
pyossiacalls the module-levellogging.info()helper at import time (reached viacuemsengine.osc). With no handler on root yet, Python runslogging.basicConfig()implicitly and attaches aStreamHandler(stderr)usingBASIC_FORMAT; module loggers here propagate, so every record was re-emitted through it. Seeding root with aNullHandlermakes that implicit call a no-op. Traced with anaddHandler/basicConfigprobe:Propagation is deliberately left enabled: pytest's
caplogcaptures through a root handler and depends on it. Settingpropagate = Falsewas the obvious fix and would have broken a chunk of the suite.Copy Extra optional, rename logging functions to shorter names #1 vs Parser fixxes #2 — under systemd both terminate in the same journal. Keep only syslog there, because systemd stamps every stdout line
PRIORITY=6regardless of the Python level, sojournalctl -p(and thereforecuems-logs -l/--leveland-e/--errors) cannot tell DEBUG from ERROR on the stdout copy. Detection isJOURNAL_STREAM, which systemd sets exactly when stdout is wired to the journal, so interactive runs and pytest still print to stdout.Identifier — journald parses
SYSLOG_IDENTIFIERoff a leadingTAG:. Without one the entry has no identifier and journalctl falls back to_COMM, truncated by the kernel to 15 chars, socontroller-engineshowed up ascontroller-engiand read as a separate process. The PID is left out of the tag so journald's_PID, taken from socket credentials, stays correct across a fork.Verification (test2 controller)
controller-engi(truncated)controller-enginePost-restart, controller engine: 95 records / 95 unique / ratio 1.00. Node engine reads 1.07 — verified to be the
@loggeddecorator firing on real repeatedapply_volume/set_valuecalls, not handler duplication.Test suite 552 passed, identical to baseline.
Note
cuems-commond1c2109 is the companion change (cuems-logsfixes + journal retention).