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:
@@ -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)
|
||||
|
||||
@@ -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}")
|
||||
|
||||
Reference in New Issue
Block a user