Skip to content

Commit 917610d

Browse files
fix(logger): preserve user-defined handlers in set_logger_format()
Previously, set_logger_format() called logger.handlers.clear() which removed all handlers including user-defined FileHandlers. This made it impossible to capture initialization logs to a file. Fix: only remove pure StreamHandlers, preserving FileHandlers and other custom handlers added by the user. Closes #375
1 parent caf4db8 commit 917610d

2 files changed

Lines changed: 65 additions & 3 deletions

File tree

codecarbon/external/logger.py

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,9 +13,12 @@ def set_logger_format(custom_preamble: Optional[str] = ""):
1313
handler = logging.StreamHandler()
1414
handler.setFormatter(formatter)
1515

16-
if logger.hasHandlers():
17-
logger.handlers.clear()
18-
16+
logger.handlers = [
17+
h
18+
for h in logger.handlers
19+
if isinstance(h, logging.FileHandler)
20+
or not isinstance(h, logging.StreamHandler)
21+
]
1922
logger.addHandler(handler)
2023

2124

tests/test_logger.py

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
import logging
2+
import os
3+
import tempfile
4+
import unittest
5+
6+
from codecarbon.external.logger import logger, set_logger_format
7+
8+
9+
class TestSetLoggerFormat(unittest.TestCase):
10+
"""Tests for issue #375 — set_logger_format() must not clear user-defined handlers."""
11+
12+
def setUp(self):
13+
self._original_handlers = logger.handlers[:]
14+
15+
def tearDown(self):
16+
logger.handlers = self._original_handlers
17+
18+
def test_file_handler_preserved_after_set_logger_format(self):
19+
"""A FileHandler added by the user must survive a call to set_logger_format()."""
20+
with tempfile.NamedTemporaryFile(suffix=".log", delete=False) as tmp:
21+
tmp_path = tmp.name
22+
try:
23+
fh = logging.FileHandler(tmp_path)
24+
fh.setLevel(logging.DEBUG)
25+
logger.addHandler(fh)
26+
27+
# set_logger_format() is called automatically inside EmissionsTracker.__init__
28+
# It must NOT remove the user's FileHandler
29+
set_logger_format()
30+
31+
file_handlers = [
32+
h for h in logger.handlers if isinstance(h, logging.FileHandler)
33+
]
34+
self.assertEqual(
35+
len(file_handlers),
36+
1,
37+
"FileHandler must survive a call to set_logger_format()",
38+
)
39+
finally:
40+
fh.close()
41+
os.unlink(tmp_path)
42+
43+
def test_stream_handler_not_duplicated(self):
44+
"""Calling set_logger_format() twice must not duplicate the StreamHandler."""
45+
set_logger_format()
46+
set_logger_format()
47+
48+
stream_handlers = [
49+
h for h in logger.handlers if type(h) is logging.StreamHandler
50+
]
51+
self.assertEqual(
52+
len(stream_handlers),
53+
1,
54+
"Only one StreamHandler should exist after two calls to set_logger_format()",
55+
)
56+
57+
58+
if __name__ == "__main__":
59+
unittest.main()

0 commit comments

Comments
 (0)