Skip to content

Commit d3fc8c1

Browse files
committed
done
1 parent 22c54f2 commit d3fc8c1

File tree

1 file changed

+98
-76
lines changed

1 file changed

+98
-76
lines changed

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

Lines changed: 98 additions & 76 deletions
Original file line numberDiff line numberDiff line change
@@ -171,20 +171,6 @@ def _setup_format_string(
171171
return _DEFAULT_FORMATTING
172172

173173

174-
def _set_logging_handler(
175-
logger: logging.Logger,
176-
*,
177-
fmt: str,
178-
log_format_local_dev_enabled: bool,
179-
) -> None:
180-
for handler in logger.handlers:
181-
handler.setFormatter(
182-
CustomFormatter(
183-
fmt, log_format_local_dev_enabled=log_format_local_dev_enabled
184-
)
185-
)
186-
187-
188174
def _get_all_loggers() -> list[logging.Logger]:
189175
manager = logging.Logger.manager
190176
root_logger = logging.getLogger()
@@ -215,7 +201,12 @@ def setup_loggers(
215201
tracing_settings: TracingSettings | None,
216202
) -> None:
217203
"""
218-
Applies common configuration to ALL registered loggers.
204+
Applies comprehensive configuration to ALL registered loggers.
205+
206+
This function uses a comprehensive approach:
207+
- Removes all handlers from all loggers
208+
- Ensures all loggers propagate to root
209+
- Sets up root logger with properly formatted handler
219210
220211
Args:
221212
log_format_local_dev_enabled: Enable local development formatting
@@ -227,13 +218,17 @@ def setup_loggers(
227218
log_format_local_dev_enabled=log_format_local_dev_enabled,
228219
)
229220

221+
# Create a properly formatted handler for the root logger
222+
root_handler = logging.StreamHandler()
223+
root_handler.setFormatter(
224+
CustomFormatter(fmt, log_format_local_dev_enabled=log_format_local_dev_enabled)
225+
)
226+
230227
all_loggers = _get_all_loggers()
231-
for logger in all_loggers:
232-
_set_logging_handler(
233-
logger,
234-
fmt=fmt,
235-
log_format_local_dev_enabled=log_format_local_dev_enabled,
236-
)
228+
229+
# Apply comprehensive logging setup
230+
# Note: We don't store the original state here since this is a permanent setup
231+
_apply_comprehensive_logging_setup(all_loggers, root_handler)
237232

238233
# Apply filters
239234
_apply_logger_filters(logger_filter_mapping)
@@ -281,57 +276,11 @@ async def setup_async_loggers_lifespan(
281276
# Create queue handler for loggers
282277
queue_handler = logging.handlers.QueueHandler(log_queue)
283278

284-
# Comprehensive approach: ensure ALL logs go through async queue
285-
root_logger = logging.getLogger()
279+
# Apply comprehensive logging setup and store original state for restoration
286280
all_loggers = _get_all_loggers()
287-
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 = []
300-
for logger in all_loggers:
301-
if logger is root_logger:
302-
continue
303-
304-
# Track what we're modifying for logging purposes
305-
had_handlers = bool(logger.handlers)
306-
had_propagate_disabled = not logger.propagate
307-
308-
if had_handlers or had_propagate_disabled:
309-
loggers_modified.append(
310-
{
311-
"name": logger.name,
312-
"had_handlers": had_handlers,
313-
"had_propagate_disabled": had_propagate_disabled,
314-
"handlers": [type(h).__name__ for h in logger.handlers],
315-
}
316-
)
317-
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),
326-
[
327-
f"{info['name']}(removed_handlers={info['handlers']}, enabled_propagate={info['had_propagate_disabled']})"
328-
for info in loggers_modified[:3]
329-
], # Show first 3 to avoid spam
330-
)
331-
332-
# Set up root logger with queue handler only
333-
root_logger.handlers.clear()
334-
root_logger.addHandler(queue_handler)
281+
original_logger_state = _apply_comprehensive_logging_setup(
282+
all_loggers, queue_handler
283+
)
335284

336285
try:
337286
# Apply filters if provided
@@ -344,11 +293,7 @@ async def setup_async_loggers_lifespan(
344293
finally:
345294
# Cleanup: Restore all loggers to their original state
346295
try:
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"]
296+
_restore_logger_state(original_logger_state)
352297

353298
# Stop the queue listener
354299
with log_context(
@@ -606,3 +551,80 @@ def set_parent_module_log_level(
606551
) -> None:
607552
parent_module = ".".join(current_module.split(".")[:-1])
608553
logging.getLogger(parent_module).setLevel(desired_log_level)
554+
555+
556+
def _store_logger_state(loggers: list[logging.Logger]) -> list[dict[str, Any]]:
557+
"""Store the original state of loggers for later restoration."""
558+
return [
559+
{
560+
"logger": logger,
561+
"handlers": logger.handlers.copy(),
562+
"propagate": logger.propagate,
563+
}
564+
for logger in loggers
565+
]
566+
567+
568+
def _restore_logger_state(original_state: list[dict[str, Any]]) -> None:
569+
"""Restore loggers to their original state."""
570+
for state in original_state:
571+
logger = state["logger"]
572+
logger.handlers.clear()
573+
logger.handlers.extend(state["handlers"])
574+
logger.propagate = state["propagate"]
575+
576+
577+
def _apply_comprehensive_logging_setup(
578+
all_loggers: list[logging.Logger],
579+
root_handler: logging.Handler,
580+
) -> list[dict[str, Any]]:
581+
"""
582+
Apply comprehensive logging setup: clear all handlers, ensure propagation,
583+
and set up root logger with the provided handler.
584+
585+
Returns the original logger state for restoration.
586+
"""
587+
root_logger = logging.getLogger()
588+
589+
# Store original state for restoration
590+
original_logger_state = _store_logger_state(all_loggers)
591+
592+
# Remove all handlers from all loggers and ensure propagation
593+
loggers_modified = []
594+
for logger in all_loggers:
595+
if logger is root_logger:
596+
continue
597+
598+
# Track what we're modifying for logging purposes
599+
had_handlers = bool(logger.handlers)
600+
had_propagate_disabled = not logger.propagate
601+
602+
if had_handlers or had_propagate_disabled:
603+
loggers_modified.append(
604+
{
605+
"name": logger.name,
606+
"had_handlers": had_handlers,
607+
"had_propagate_disabled": had_propagate_disabled,
608+
"handlers": [type(h).__name__ for h in logger.handlers],
609+
}
610+
)
611+
612+
# Clear handlers and ensure propagation
613+
logger.handlers.clear()
614+
logger.propagate = True
615+
616+
if loggers_modified:
617+
_logger.info(
618+
"Modified %d loggers for comprehensive logging: %s",
619+
len(loggers_modified),
620+
[
621+
f"{info['name']}(removed_handlers={info['handlers']}, enabled_propagate={info['had_propagate_disabled']})"
622+
for info in loggers_modified[:3]
623+
], # Show first 3 to avoid spam
624+
)
625+
626+
# Set up root logger with the provided handler only
627+
root_logger.handlers.clear()
628+
root_logger.addHandler(root_handler)
629+
630+
return original_logger_state

0 commit comments

Comments
 (0)