Skip to content

Commit b8a4e6f

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 b8a4e6f

2 files changed

Lines changed: 66 additions & 3 deletions

File tree

codecarbon/external/logger.py

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,9 +13,11 @@ 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 for h in logger.handlers
18+
if isinstance(h, logging.FileHandler)
19+
or not isinstance(h,logging.StreamHandler)
20+
]
1921
logger.addHandler(handler)
2022

2123

tests/test_logger.py

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
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
33+
if isinstance(h, logging.FileHandler)
34+
]
35+
self.assertEqual(
36+
len(file_handlers),
37+
1,
38+
"FileHandler must survive a call to set_logger_format()",
39+
)
40+
finally:
41+
fh.close()
42+
os.unlink(tmp_path)
43+
44+
def test_stream_handler_not_duplicated(self):
45+
"""Calling set_logger_format() twice must not duplicate the StreamHandler."""
46+
set_logger_format()
47+
set_logger_format()
48+
49+
stream_handlers = [
50+
h for h in logger.handlers
51+
if type(h) is logging.StreamHandler
52+
]
53+
self.assertEqual(
54+
len(stream_handlers),
55+
1,
56+
"Only one StreamHandler should exist after two calls to set_logger_format()",
57+
)
58+
59+
60+
if __name__ == "__main__":
61+
unittest.main()

0 commit comments

Comments
 (0)