Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ build-backend = "hatchling.build"

[project]
name = "chromatrace"
version = "0.2.15"
version = "0.2.16"
description = "Advanced Python logging with tracing, coloring and FastAPI, Django, and SocketIO integrations"
readme = "README.md"
authors = [
Expand Down
15 changes: 14 additions & 1 deletion src/chromatrace/logging_config.py
Original file line number Diff line number Diff line change
Expand Up @@ -40,12 +40,25 @@ def get_logger(self, name: str) -> logging.Logger:
# Add handlers if they don't exist
if not logger.handlers:
self._setup_handlers(logger)
self._setup_custom_handlers(logger)

return logger

def _setup_custom_handlers(self, logger: logging.Logger):
if not hasattr(self.settings, "custom_handlers"):
return

Comment on lines +48 to +50
Copy link

Copilot AI Nov 27, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The hasattr check on line 48 is unnecessary since custom_handlers is now a defined field in the LoggingSettings Pydantic model with a default value. The attribute will always exist, so this check can be removed.

The method can be simplified to:

def _setup_custom_handlers(self, logger: logging.Logger):
    for handler in self.settings.custom_handlers:
        if not isinstance(handler, logging.Handler):
            continue
        formatter = self._get_formatter(
            colored=self.settings.use_console_colored_formatter
        )
        self._set_logger_settings(handler, formatter, logger)
Suggested change
if not hasattr(self.settings, "custom_handlers"):
return

Copilot uses AI. Check for mistakes.
for handler in self.settings.custom_handlers:
if not isinstance(handler, logging.Handler):
Copy link

Copilot AI Nov 27, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Invalid handlers are silently skipped with continue, which could lead to confusion when a user's custom handler doesn't appear in the logger. Consider logging a warning when an invalid handler is encountered to help with debugging.

Suggested change:

for handler in self.settings.custom_handlers:
    if not isinstance(handler, logging.Handler):
        logging.getLogger(__name__).warning(
            f"Skipping invalid custom handler: {type(handler).__name__}. "
            "Expected logging.Handler instance."
        )
        continue
Suggested change
if not isinstance(handler, logging.Handler):
if not isinstance(handler, logging.Handler):
logging.getLogger(__name__).warning(
f"Skipping invalid custom handler: {type(handler).__name__}. "
"Expected logging.Handler instance."
)

Copilot uses AI. Check for mistakes.
continue
formatter = self._get_formatter(
colored=self.settings.use_console_colored_formatter
)
Comment on lines +54 to +56
Copy link

Copilot AI Nov 27, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Custom handlers always receive a formatter based on use_console_colored_formatter, which may not be appropriate for all custom handlers. For example, if a user adds a file-based custom handler, they might want use_file_colored_formatter instead, or a completely different formatter.

Consider one of these approaches:

  1. Allow users to pass handlers that already have formatters set, and only apply a formatter if the handler doesn't already have one
  2. Add a configuration option to specify which formatter setting applies to custom handlers
  3. Document this behavior clearly so users know custom handlers will use the console formatter settings

Copilot uses AI. Check for mistakes.
self._set_logger_settings(handler, formatter, logger)
Comment on lines +47 to +57
Copy link

Copilot AI Nov 27, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The new custom_handlers feature lacks test coverage. Since the repository has comprehensive test coverage for other logging features (see test/logger_test.py), this new functionality should also be tested. Consider adding tests that verify:

  1. Custom handlers are properly added to the logger
  2. Custom handlers receive the correct formatter
  3. Custom handlers get the appropriate filters (tracing, application level)
  4. Invalid handlers are handled gracefully

Copilot uses AI. Check for mistakes.

def _set_logger_settings(
self,
handler: logging.handlers,
handler: logging.Handler,
formatter: logging.Formatter,
logger: logging.Logger,
):
Expand Down
3 changes: 2 additions & 1 deletion src/chromatrace/logging_settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
from typing import Literal, Optional

import click
from pydantic import BaseModel
from pydantic import BaseModel, Field


class LoggingSettings(BaseModel):
Expand All @@ -26,6 +26,7 @@ class LoggingSettings(BaseModel):
use_syslog_colored_formatter: bool = False
use_file_colored_formatter: bool = False
show_process_id: bool = False
custom_handlers: list = Field(default_factory=list)
Copy link

Copilot AI Nov 27, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The type annotation for custom_handlers should be more specific. Since this field is expected to contain logging handlers, it should be typed as list[logging.Handler] instead of just list. This improves type safety and makes the API clearer to users.

Suggested change:

custom_handlers: list[logging.Handler] = Field(default_factory=list)
Suggested change
custom_handlers: list = Field(default_factory=list)
custom_handlers: list[logging.Handler] = Field(default_factory=list)

Copilot uses AI. Check for mistakes.

def __init__(self, **data):
super().__init__(**data)
Expand Down