Skip to content

Commit a452dea

Browse files
committed
ensure all loggers propagate
1 parent 1383cd4 commit a452dea

File tree

1 file changed

+37
-30
lines changed

1 file changed

+37
-30
lines changed

packages/service-library/src/servicelib/logging_utils.py

Lines changed: 37 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -281,51 +281,55 @@ async def setup_async_loggers_lifespan(
281281
# Create queue handler for loggers
282282
queue_handler = logging.handlers.QueueHandler(log_queue)
283283

284-
# Use root-only approach for better performance and simplicity
284+
# Comprehensive approach: ensure ALL logs go through async queue
285285
root_logger = logging.getLogger()
286-
original_root_handlers = root_logger.handlers.copy()
287-
288-
# Check for edge cases and warn if found
289286
all_loggers = _get_all_loggers()
290-
edge_case_loggers = []
291287

288+
# Store original state for restoration
289+
original_logger_state = [
290+
{
291+
"logger": logger,
292+
"handlers": logger.handlers.copy(),
293+
"propagate": logger.propagate,
294+
}
295+
for logger in all_loggers
296+
]
297+
298+
# Remove all handlers from all loggers and ensure propagation
299+
loggers_modified = []
292300
for logger in all_loggers:
293301
if logger is root_logger:
294302
continue
295303

296-
# Check for loggers that might bypass root logging
297-
has_handlers = bool(logger.handlers)
298-
propagate_disabled = not logger.propagate
304+
# Track what we're modifying for logging purposes
305+
had_handlers = bool(logger.handlers)
306+
had_propagate_disabled = not logger.propagate
299307

300-
# Filter out harmless cases: NullHandler with propagate=True is fine
301-
has_meaningful_handlers = (
302-
any(not isinstance(h, logging.NullHandler) for h in logger.handlers)
303-
if logger.handlers
304-
else False
305-
)
306-
307-
if has_meaningful_handlers or propagate_disabled:
308-
edge_case_loggers.append(
308+
if had_handlers or had_propagate_disabled:
309+
loggers_modified.append(
309310
{
310311
"name": logger.name,
311-
"has_handlers": has_handlers,
312-
"propagate": logger.propagate,
312+
"had_handlers": had_handlers,
313+
"had_propagate_disabled": had_propagate_disabled,
313314
"handlers": [type(h).__name__ for h in logger.handlers],
314315
}
315316
)
316317

317-
if edge_case_loggers:
318-
_logger.warning(
319-
"Found %d loggers that may bypass async logging: %s. "
320-
"Consider reviewing logger configuration.",
321-
len(edge_case_loggers),
318+
# Clear handlers and ensure propagation
319+
logger.handlers.clear()
320+
logger.propagate = True
321+
322+
if loggers_modified:
323+
_logger.info(
324+
"Modified %d loggers for async logging: %s",
325+
len(loggers_modified),
322326
[
323-
f"{logger_info['name']}(handlers={logger_info['handlers']}, propagate={logger_info['propagate']})"
324-
for logger_info in edge_case_loggers[:3]
327+
f"{info['name']}(removed_handlers={info['handlers']}, enabled_propagate={info['had_propagate_disabled']})"
328+
for info in loggers_modified[:3]
325329
], # Show first 3 to avoid spam
326330
)
327331

328-
# Replace only root logger handlers
332+
# Set up root logger with queue handler only
329333
root_logger.handlers.clear()
330334
root_logger.addHandler(queue_handler)
331335

@@ -338,10 +342,13 @@ async def setup_async_loggers_lifespan(
338342
yield
339343

340344
finally:
341-
# Cleanup: Restore original root logger handlers
345+
# Cleanup: Restore all loggers to their original state
342346
try:
343-
root_logger.handlers.clear()
344-
root_logger.handlers.extend(original_root_handlers)
347+
for state in original_logger_state:
348+
logger = state["logger"]
349+
logger.handlers.clear()
350+
logger.handlers.extend(state["handlers"])
351+
logger.propagate = state["propagate"]
345352

346353
# Stop the queue listener
347354
with log_context(

0 commit comments

Comments
 (0)