Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
0c67cff
chore: bump version to 0.2.12 and update python-socketio dependencies
Msameim181 Mar 10, 2025
3e602f6
Merge pull request #10 from Msameim181/fix/package_management
Msameim181 Mar 10, 2025
3f89cf7
fix: enhance the main logger __init__ and remove fastapi, django, and…
Msameim181 Apr 29, 2025
57b65f5
test: fix the imports
Msameim181 Apr 29, 2025
2f12558
fix: resolve issue in importing
Msameim181 Apr 29, 2025
2f5348c
fix: resolve issue in importing
Msameim181 Apr 29, 2025
8dc2bc4
Merge branch 'develop' into fix/package_management
Msameim181 Apr 29, 2025
02f2700
fix: resolve issue in importing
Msameim181 Apr 29, 2025
4b06b6c
Merge pull request #12 from Msameim181/fix/package_management
Msameim181 Apr 29, 2025
b37c196
chore: change the license
Msameim181 Nov 26, 2025
4afa26b
fix: change the explicit version contorl for packages
Msameim181 Nov 26, 2025
e356dfb
fix: change the explicit version contorl for packages
Msameim181 Nov 26, 2025
a37a8e3
Update pyproject.toml
Msameim181 Nov 26, 2025
6124fc6
chore: update license
Msameim181 Nov 26, 2025
c6390e1
chore: remove asyncio from dep
Msameim181 Nov 26, 2025
0e9616f
chore: update the setup
Msameim181 Nov 26, 2025
8c0cf8e
Update pyproject.toml
Msameim181 Nov 26, 2025
023d1d7
chore: update setup
Msameim181 Nov 26, 2025
675f34f
chore: update dependencies and configuration
Msameim181 Nov 26, 2025
7097063
chore: refactor imports and clean up code
Msameim181 Nov 26, 2025
614f1f6
chore: fix asyncio_default_fixture_loop_scope value
Msameim181 Nov 26, 2025
5be4b55
Merge pull request #13 from Msameim181/fix/package_management
Msameim181 Nov 26, 2025
eae2f2d
chore: update version to `0.2.14`
Msameim181 Nov 26, 2025
af8d12a
Merge pull request #14 from Msameim181/fix/package_management
Msameim181 Nov 26, 2025
7e85fe7
chore: update license from GNU AGPL to MIT License
Msameim181 Nov 26, 2025
d536f17
Merge pull request #15 from Msameim181/fix/package_management
Msameim181 Nov 26, 2025
a163efd
feat(logging): add support for custom logging handlers
Msameim181 Nov 27, 2025
a827c1d
chore: update version to `0.2.16`
Msameim181 Nov 27, 2025
b95cec4
Merge pull request #16 from Msameim181/feat/custome_handler
Msameim181 Nov 27, 2025
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
682 changes: 21 additions & 661 deletions LICENSE

Large diffs are not rendered by default.

9 changes: 5 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -149,10 +149,11 @@ The two first log was out of trace and the trace ID was not added to the log mes
### FastAPI Integration

```python
from chromatrace import RequestIdMiddleware
from chromatrace.fastapi import RequestIdMiddleware as FastAPIRequestIdMiddleware
from chromatrace.django import RequestIdMiddleware as DjangoRequestIdMiddleware

app = FastAPI()
app.add_middleware(RequestIdMiddleware)
app.add_middleware(FastAPIRequestIdMiddleware)
```

Result:
Expand All @@ -176,7 +177,7 @@ As you can see, the request ID - `R-ffe0a9a2` is automatically added to the log
### SocketIO Integration

```python
from chromatrace import SocketRequestIdMiddleware
from chromatrace.socketio import SocketRequestIdMiddleware

socket_application = SocketRequestIdMiddleware(socket_application)
```
Expand Down Expand Up @@ -271,7 +272,7 @@ Now, check the logs in the both terminal.

## License

This project is licensed under the GNU AFFERO GENERAL PUBLIC LICENSE - see the [LICENSE](LICENSE) file for details.
This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details.

## Ideas and Sources

Expand Down
59 changes: 45 additions & 14 deletions 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.11"
version = "0.2.16"
description = "Advanced Python logging with tracing, coloring and FastAPI, Django, and SocketIO integrations"
readme = "README.md"
authors = [
Expand All @@ -14,24 +14,31 @@ license = { file = "LICENSE" }
requires-python = ">=3.10"
classifiers = [
"Intended Audience :: Developers",
"License :: OSI Approved :: GNU Affero General Public License v3",
"License :: OSI Approved :: MIT License",
"Operating System :: OS Independent",
"Programming Language :: Python :: 3.10",
"Topic :: Software Development :: Libraries :: Python Modules",
"Topic :: System :: Logging",
]
dependencies = [
"asyncio==3.4.3",
"lagom==2.6.0",
"pydantic==2.9.2",
"fastapi==0.100.0",
"socketio==0.2.1",
"python-socketio==5.11.4",
"python-socketio[client]==5.11.4",
"uvicorn[standard]==0.30.6",
"uvicorn-worker==0.2.0",
"python-multipart==0.0.10",
"httpx==0.27.2",
"lagom>=2.6.0",
"pydantic>=2.9.2",
"fastapi>=0.100.0",
"python-socketio>=5.12.1",
"python-socketio[client]>=5.12.1",
"uvicorn[standard]>=0.30.6",
"uvicorn-worker>=0.2.0",
"python-multipart>=0.0.10",
"httpx>=0.27.2",
]

[project.optional-dependencies]
django = ["django>=5.1.1"]
dev = [
"pytest>=8.3.3",
"pytest-asyncio>=0.24.0",
"pytest-cov>=6.0.0",
"ruff>=0.1.0",
]

[project.urls]
Expand All @@ -41,4 +48,28 @@ Repository = "https://github.com/Msameim181/Python-Logging-Best-Practice.git"
Issues = "https://github.com/Msameim181/Python-Logging-Best-Practice/issues"

[tool.hatch.build.targets.wheel]
packages = ["src/chromatrace"]
packages = ["src/chromatrace"]

[tool.ruff]
line-length = 100
target-version = "py310"

[tool.ruff.lint]
select = [
"E", # pycodestyle errors
"W", # pycodestyle warnings
"F", # pyflakes
"I", # isort
"C", # flake8-comprehensions
"B", # flake8-bugbear
]
ignore = ["E501"] # line length

[tool.ruff.lint.per-file-ignores]
"__init__.py" = ["F401"]

[tool.mypy]
python_version = "3.10"
warn_return_any = true
warn_unused_configs = true
disallow_untyped_defs = true
2 changes: 1 addition & 1 deletion pytest.ini
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
[pytest]
asyncio_mode=auto
asyncio_default_fixture_loop_scope="function"
asyncio_default_fixture_loop_scope=function
python_files = tests.py test_*.py *_tests.py *_test.py
34 changes: 19 additions & 15 deletions requirements.txt
Original file line number Diff line number Diff line change
@@ -1,15 +1,19 @@
asyncio==3.4.3
django==5.1.1
lagom==2.6.0
pydantic==2.9.2
fastapi==0.100.0
socketio==0.2.1
python-socketio==5.11.4
python-socketio[client]==5.11.4
pytest==8.3.3
pytest-asyncio==0.24.0
pytest-cov==6.0.0
uvicorn[standard]==0.30.6
uvicorn-worker==0.2.0
python-multipart==0.0.10
httpx==0.27.2
# Core dependencies
lagom>=2.6.0
pydantic>=2.9.2
fastapi>=0.100.0
python-socketio>=5.12.1
python-socketio[client]>=5.12.1
uvicorn[standard]>=0.30.6
uvicorn-worker>=0.2.0
python-multipart>=0.0.10
httpx>=0.27.2

# Optional: Django integration
django>=5.1.1

# Development dependencies
pytest>=8.3.3
pytest-asyncio>=0.24.0
pytest-cov>=6.0.0
ruff>=0.1.0
24 changes: 2 additions & 22 deletions setup.cfg
Original file line number Diff line number Diff line change
@@ -1,24 +1,4 @@
[metadata]
license_files = LICENSE

[tool.ruff]
line-length = 100
target-version = "py37"
select = [
"E", # pycodestyle errors
"W", # pycodestyle warnings
"F", # pyflakes
"I", # isort
"C", # flake8-comprehensions
"B", # flake8-bugbear
]
ignore = ["E501"] # line length

[tool.ruff.per-file-ignores]
"__init__.py" = ["F401"]

[mypy]
python_version = 3.10
warn_return_any = True
warn_unused_configs = True
disallow_untyped_defs = True
name = chromatrace
description = Advanced logging for Python
2 changes: 1 addition & 1 deletion src/chromatrace/RabbitMQ.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,4 +30,4 @@ def callback(ch, method, properties, body):
with rabbitmq_trace_context(ch, properties):
on_message_callback(ch, method, properties, body)
self.channel.basic_consume(queue=queue, on_message_callback=callback, auto_ack=auto_ack)
self.channel.start_consuming()
self.channel.start_consuming()
19 changes: 12 additions & 7 deletions src/chromatrace/__init__.py
Original file line number Diff line number Diff line change
@@ -1,12 +1,17 @@
from .django import RequestIdMiddleware as DjangoRequestIdMiddleware # noqa
from .fastapi import RequestIdMiddleware as FastAPIRequestIdMiddleware # noqa
from .logging_config import LoggingConfig # noqa
from .logging_settings import LoggingSettings # noqa
from .socketio import SocketRequestIdMiddleware # noqa
from .tracer import ( # noqa
from .logging_config import LoggingConfig
from .logging_settings import LoggingSettings
from .tracer import (
RequestIdContext,
get_trace_id,
trace_id_ctx,
tracer,
)
from .uvicorn import GetLoggingConfig, UvicornLoggingSettings # noqa: F401

__all__ = [
"LoggingConfig",
"LoggingSettings",
"RequestIdContext",
"get_trace_id",
"trace_id_ctx",
"tracer",
]
Comment on lines +1 to +17
Copy link

Copilot AI Nov 26, 2025

Choose a reason for hiding this comment

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

This is a breaking change in the public API. The middleware classes (FastAPIRequestIdMiddleware, DjangoRequestIdMiddleware, SocketRequestIdMiddleware) and uvicorn utilities (GetLoggingConfig, UvicornLoggingSettings) are no longer exported from the main chromatrace module. Users will need to update their imports to use chromatrace.fastapi, chromatrace.django, chromatrace.socketio, and chromatrace.uvicorn instead. This should be clearly documented in the release notes as a breaking change, and the version bump should ideally be a major version change (e.g., 0.3.0 instead of 0.2.13) to follow semantic versioning.

Copilot uses AI. Check for mistakes.
2 changes: 1 addition & 1 deletion src/chromatrace/fastapi.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,4 +10,4 @@ async def dispatch(self, request: Request, call_next):
with RequestIdContext(request_id):
response = await call_next(request)
response.headers["X-Request-ID"] = trace_id_ctx.get()
return response
return response
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

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)

def _set_logger_settings(
self,
handler: logging.handlers,
handler: logging.Handler,
formatter: logging.Formatter,
logger: logging.Logger,
):
Expand Down
4 changes: 2 additions & 2 deletions 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)

def __init__(self, **data):
super().__init__(**data)
Expand Down Expand Up @@ -132,7 +133,6 @@ def __init__(
super().__init__(
message_splitter=message_splitter,
log_splitter=log_splitter,
*args,
**kwargs,
)

Expand Down
3 changes: 2 additions & 1 deletion src/examples/adaptors/socket_client.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,10 @@
from typing import Dict, List, Optional

import socketio
from pydantic import BaseModel, Field

from chromatrace import LoggingConfig, LoggingSettings
from chromatrace.tracer import trace_id_ctx
from pydantic import BaseModel, Field

logging_config = LoggingConfig(
LoggingSettings(
Expand Down
7 changes: 4 additions & 3 deletions src/examples/frameworks/api_app.py
Original file line number Diff line number Diff line change
@@ -1,13 +1,14 @@
import multiprocessing

import uvicorn
from chromatrace import LoggingConfig
from chromatrace.fastapi import RequestIdMiddleware
from chromatrace.uvicorn import GetLoggingConfig, UvicornLoggingSettings
from fastapi import FastAPI
from fastapi.middleware.cors import CORSMiddleware
from usecases import AnotherSample, ExampleService

from chromatrace import LoggingConfig
from chromatrace.fastapi import RequestIdMiddleware
from chromatrace.uvicorn import GetLoggingConfig, UvicornLoggingSettings


class APIService:
def __init__(
Expand Down
6 changes: 3 additions & 3 deletions src/examples/frameworks/socket_app.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,12 @@

import socketio
import uvicorn

from chromatrace import (
GetLoggingConfig,
LoggingConfig,
SocketRequestIdMiddleware,
UvicornLoggingSettings,
)
from chromatrace.socketio import SocketRequestIdMiddleware
from chromatrace.uvicorn import GetLoggingConfig, UvicornLoggingSettings


class SocketServerConfig:
Expand Down
3 changes: 2 additions & 1 deletion src/examples/injection.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
from chromatrace import LoggingSettings
from dependency import container
from frameworks.api_app import APIService
from frameworks.socket_app import SocketService
from lagom import Singleton

from chromatrace import LoggingSettings

container[LoggingSettings] = LoggingSettings(
application_level="Development",
enable_tracing=True,
Expand Down
3 changes: 2 additions & 1 deletion src/examples/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,14 @@
import sys

import injection # noqa
from chromatrace import LoggingConfig, LoggingSettings, tracer
from dependency import container
from frameworks.api_app import APIService
from frameworks.socket_app import SocketService
from usecases.example_service import ExampleService
from usecases.sample import AnotherSample

from chromatrace import LoggingConfig, LoggingSettings, tracer

sys.stdout.reconfigure(encoding="utf-8")


Expand Down
3 changes: 2 additions & 1 deletion src/examples/tests/chromatrace_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,14 @@
import injection # noqa
import pytest
from adaptors.socket_client import SocketClient, SocketClientConfig
from chromatrace import LoggingConfig
from dependency import container
from frameworks.api_app import APIService
from frameworks.socket_app import SocketService
from usecases.example_service import ExampleService, InnerService
from usecases.sample import AnotherSample

from chromatrace import LoggingConfig


class TestChromatrace:
@pytest.fixture(scope="class")
Expand Down
9 changes: 5 additions & 4 deletions test/logger_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,19 +4,20 @@
from io import StringIO

import pytest
from chromatrace import FastAPIRequestIdMiddleware as FastAPIMiddleware
from fastapi import FastAPI
from fastapi.testclient import TestClient

from chromatrace import (
LoggingConfig,
LoggingSettings,
RequestIdContext,
SocketRequestIdMiddleware,
trace_id_ctx,
tracer,
)
from chromatrace.fastapi import RequestIdMiddleware as FastAPIMiddleware
from chromatrace.logging_settings import ApplicationLevelFilter, BasicFormatter
from chromatrace.socketio import SocketRequestIdMiddleware
from chromatrace.tracer import RequestIdFilter
from fastapi import FastAPI
from fastapi.testclient import TestClient


class TestLoggingConfiguration:
Expand Down