Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 7 additions & 3 deletions src/ezmsg/baseproc/util/profile.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,10 @@ def _setup_logger(append: bool = False) -> logging.Logger:
try:
with open(logpath) as f:
first_line = f.readline().rstrip()
if first_line == HEADER:
if not first_line:
# Empty file; nothing to mismatch against, write the header ourselves.
pass
elif first_line == HEADER:
write_header = False
else:
# Remove the file if appending, but headers do not match
Expand All @@ -61,8 +64,9 @@ def _setup_logger(append: bool = False) -> logging.Logger:
# Set the logger's level to EZMSG_LOGLEVEL env var value if it exists, otherwise INFO
_logger.setLevel(os.environ.get("EZMSG_LOGLEVEL", "INFO").upper())

# Create a file handler to write log messages to the log file
fh = logging.FileHandler(logpath)
# Create a file handler to write log messages to the log file.
# delay=True so a run with profiling disabled doesn't leave a zero-byte file behind.
fh = logging.FileHandler(logpath, delay=True)
fh.setLevel(logging.DEBUG) # Set the file handler log level to DEBUG

# Add the file handler to the logger
Expand Down
41 changes: 41 additions & 0 deletions tests/test_profile.py
Original file line number Diff line number Diff line change
Expand Up @@ -135,6 +135,47 @@ def test_logger_append_header_match(mock_logger_path):
handler.close()


def test_logger_append_empty_file(mock_logger_path, caplog):
"""An existing but empty log file is not a header mismatch and must not warn."""
test_logpath = mock_logger_path
with open(test_logpath, "w") as f:
f.truncate(0)

with caplog.at_level(logging.WARNING, logger="ezmsg"):
logger = _setup_logger(append=True)

assert "header mismatch" not in caplog.text.lower()

# The header is still written to the empty file.
with open(test_logpath, "r") as f:
first_line = f.readline().strip()
assert first_line == HEADER

for handler in list(logger.handlers):
logger.removeHandler(handler)
handler.close()


def test_no_empty_file_when_profiling_disabled(mock_logger_path):
"""With profiling off (level > DEBUG) no zero-byte log file is left behind."""
test_logpath = mock_logger_path
test_logpath.unlink(missing_ok=True)

# _setup_logger mutates the shared "ezprofile" logger; restore its level afterwards.
prev_level = logging.getLogger("ezprofile").level
try:
with patch.dict(os.environ, {"EZMSG_LOGLEVEL": "INFO"}):
logger = _setup_logger(append=True)

assert not test_logpath.exists()

for handler in list(logger.handlers):
logger.removeHandler(handler)
handler.close()
finally:
logging.getLogger("ezprofile").setLevel(prev_level)


def test_profile_method_decorator():
"""Test the profile_method decorator."""

Expand Down
Loading