fix(logging): keep records of a live profile whose logs/ was removed

When logs/ disappears but the profile itself is live (removed by hand,
no tombstone), the handler skipped the write and the router only
re-routed after a confirmed delete, so every record was silently dropped
until restart. Before the skip they were lost too, but loudly. Send a
skipped record to the default log whether or not the home is released.
This commit is contained in:
kshitijk4poor
2026-10-02 14:25:14 +05:30
committed by kshitij
parent 17553bd6f8
commit 346eaef707
2 changed files with 10 additions and 5 deletions

View File

@@ -689,8 +689,10 @@ class _ProfileRoutingFileHandler(logging.Handler):
finally:
reset_hermes_home_override(token)
# The write was skipped because logs/ is gone (an rmtree inside the liveness interval,
# see _ManagedRotatingFileHandler.emit): re-check now so this record is not dropped.
if handler.skipped_missing_dir and self._release_if_deleted(home):
# see _ManagedRotatingFileHandler.emit): re-check now, and keep the record in the
# default log either way (a live profile whose logs/ was removed by hand included).
if handler.skipped_missing_dir:
self._release_if_deleted(home)
self._handler_for_home(self._default_home).handle(record)
except Exception:
self.handleError(record)

View File

@@ -348,13 +348,14 @@ class TestSetupLogging:
# No "--- Logging error ---" FileNotFoundError loop on stderr.
assert "FileNotFoundError" not in capsys.readouterr().err
@pytest.mark.parametrize("removal", ["tombstone", "rmtree"])
@pytest.mark.parametrize("removal", ["tombstone", "rmtree", "logs-only"])
def test_out_of_band_profile_delete_releases_routed_handler(
self, hermes_home, capsys, liveness_clock, removal
):
"""A CLI delete tombstones then removes the home behind a running serve: the router must
stop writing there on either signal alone and close the stale file, like an in-process
delete. The rmtree case has no tombstone so it exercises the missing-dir branch."""
delete. The rmtree case has no tombstone so it exercises the missing-dir branch; logs-only
removes just logs/ of a live profile, whose records must still land somewhere."""
import shutil
from hermes_constants import (
@@ -382,8 +383,10 @@ class TestSetupLogging:
if removal == "tombstone":
mark_named_profile_deleted(profile_home)
liveness_clock() # a tombstone alone is seen on the next interval check
else:
elif removal == "rmtree":
shutil.rmtree(profile_home) # caught by the write itself, inside the interval
else:
shutil.rmtree(profile_home / "logs")
capsys.readouterr()
for i in range(3):
emit(f"after delete {i}")