Skip to content

Commit 287c507

Browse files
committed
Log but don't raise when publish fails
Closes #4
1 parent 4df1c20 commit 287c507

File tree

2 files changed

+26
-10
lines changed

2 files changed

+26
-10
lines changed

mqlog/__init__.py

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ def __init__(
3939
self.capacity = capacity
4040
self.buffer = []
4141
self.will_flush = asyncio.Event()
42+
self._logger = logging.getLogger("mqlog")
4243

4344
async def run(self):
4445
"""
@@ -69,8 +70,9 @@ def format(self, record):
6970
# Named with an underscore to avoid conflict with logging.Handler.flush
7071
async def _flush(self):
7172
if self.buffer:
72-
msg = ""
73-
while self.buffer:
74-
msg += self.buffer.pop(0) + "\n"
75-
await self.client.publish(self.topic, msg.strip(), qos=self.qos)
76-
self.will_flush.clear()
73+
try:
74+
msg = "\n".join([line for line in self.buffer])
75+
await self.client.publish(self.topic, msg, qos=self.qos)
76+
self.will_flush.clear()
77+
except Exception as e:
78+
self._logger.error("Failed to publish logs", exc_info=e)

tests/test_handler.py

Lines changed: 19 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,17 +4,14 @@
44
from unittest import TestCase, skipIf
55

66
from mqlog import MqttHandler
7+
from tests.utils import AsyncMock, Mock
78

89

910
class FakeClient:
1011
"""A fake MQTT client for testing purposes."""
1112

1213
def __init__(self):
13-
self.calls = []
14-
15-
# Store the call like a mock so we can check it later
16-
async def publish(self, topic, payload, qos=0):
17-
self.calls.append((topic, payload, qos))
14+
self.publish = AsyncMock()
1815

1916

2017
class TestMqttHandler(TestCase):
@@ -50,6 +47,23 @@ def test_flush_full_buffer(self):
5047
self.logger.info(f"Test message {i}")
5148
self.assertTrue(self.handler.will_flush.is_set())
5249

50+
def test_flush_fail(self):
51+
"""Flushing should log an error if publish fails"""
52+
self.handler._logger.error = Mock()
53+
self.client.publish = AsyncMock(side_effect=Exception("Publish failed"))
54+
asyncio.create_task(self.handler.run())
55+
56+
async def do_test(logger):
57+
await asyncio.sleep(0.1) # Allow handler to start
58+
logger.error("Test message") # should trigger flush
59+
60+
asyncio.run(do_test(self.logger))
61+
self.assertTrue(self.handler.will_flush.is_set())
62+
self.handler._logger.error.assert_called_with(
63+
"Failed to publish log message: Publish failed"
64+
)
65+
66+
5367
@skipIf(os.getenv("CI"), "Hangs in CI")
5468
def test_publish(self):
5569
"""Flushing should publish messages to MQTT topic"""

0 commit comments

Comments
 (0)