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
33 changes: 15 additions & 18 deletions .github/workflows/workflow.yml
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,8 @@ jobs:
name: Lint (ruff)
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6
- uses: astral-sh/ruff-action@v3
- uses: actions/checkout@v7
- uses: astral-sh/ruff-action@v4.1.0
with:
args: "check"

Expand All @@ -31,10 +31,12 @@ jobs:
run:
working-directory: ${{ github.workspace }}
steps:
- uses: actions/checkout@v6
- uses: actions/checkout@v7
with:
fetch-depth: 0

- name: Install uv
uses: astral-sh/setup-uv@v7
uses: astral-sh/setup-uv@v9.0.0
with:
enable-cache: true

Expand All @@ -45,33 +47,29 @@ jobs:
run: uv sync --locked --all-extras --all-groups

- name: Run tests with coverage
uses: nick-fields/retry@v3
uses: nick-fields/retry@v4
with:
timeout_minutes: 2
max_attempts: 3
command: uv run --no-sync pytest
command: uv run --no-sync poe test-unit
shell: bash

- name: Upload coverage to Codecov
- name: SonarQube Scan
if: matrix.python-version == env.LATEST_PYTHON_VERSION && matrix.os == 'ubuntu-latest'
uses: codecov/codecov-action@v5

- name: Upload test results to Codecov
if: matrix.python-version == env.LATEST_PYTHON_VERSION && matrix.os == 'ubuntu-latest'
uses: codecov/codecov-action@v5
with:
report_type: test_results
uses: SonarSource/sonarqube-scan-action@v8
env:
SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}

build:
name: Build Package
runs-on: ubuntu-latest
needs: test
if: startsWith(github.ref, 'refs/tags/v')
steps:
- uses: actions/checkout@v6
- uses: actions/checkout@v7

- name: Install uv
uses: astral-sh/setup-uv@v7
uses: astral-sh/setup-uv@v9.0.0
with:
enable-cache: true

Expand Down Expand Up @@ -109,13 +107,12 @@ jobs:
path: release-assets/

- name: Create Release
uses: softprops/action-gh-release@v2
uses: softprops/action-gh-release@v3
with:
name: Release ${{ github.ref_name }}
generate_release_notes: true
files: release-assets/*


publish:
name: Publish to PyPI
runs-on: ubuntu-latest
Expand Down
2 changes: 1 addition & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -156,6 +156,6 @@ cython_debug/
.idea/

# Custom
/junit.xml
*.prof
/requirements.txt
/junit.xml
55 changes: 26 additions & 29 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
<a href="https://opensource.org/licenses/MIT"><img src="https://img.shields.io/badge/License-MIT-yellow.svg?style=plastic&logo=creativecommons&logoColor=white" alt="License: MIT"/></a>
<br>
<a href="https://github.com/ddc/pythonlogs/issues"><img src="https://img.shields.io/github/issues/ddc/pythonlogs?style=plastic&logo=github&logoColor=white" alt="issues"/></a>
<a href="https://codecov.io/gh/ddc/pythonlogs"><img src="https://img.shields.io/codecov/c/github/ddc/pythonlogs?token=XWB53034GI&style=plastic&logo=codecov" alt="codecov"/></a>
<a href="https://sonarcloud.io/component_measures?id=ddc_pythonlogs&metric=coverage"><img src="https://img.shields.io/sonar/coverage/ddc_pythonlogs?server=https%3A%2F%2Fsonarcloud.io&style=plastic&logo=sonarqubecloud&logoColor=white" alt="SonarCloud Coverage"/></a>
<a href="https://sonarcloud.io/dashboard?id=ddc_pythonlogs"><img src="https://img.shields.io/sonar/quality_gate/ddc_pythonlogs?server=https%3A%2F%2Fsonarcloud.io&style=plastic&logo=sonarqubecloud&logoColor=white" alt="Quality Gate Status"/></a>
<a href="https://github.com/ddc/pythonlogs/actions/workflows/workflow.yml"><img src="https://img.shields.io/github/actions/workflow/status/ddc/pythonlogs/workflow.yml?style=plastic&logo=github&logoColor=white&label=CI%2FCD%20Pipeline" alt="CI/CD Pipeline"/></a>
<a href="https://actions-badge.atrox.dev/ddc/pythonlogs/goto?ref=main"><img src="https://img.shields.io/endpoint.svg?url=https%3A//actions-badge.atrox.dev/ddc/pythonlogs/badge?ref=main&label=build&logo=github&style=plastic" alt="Build Status"/></a>
Expand Down Expand Up @@ -91,7 +91,7 @@ logger = BasicLog(
name="my_app",
level="debug", # "debug", "info", "warning", "error", "critical"
timezone="America/Sao_Paulo",
showlocation=False
showlocation=False,
)
logger.warning("This is a warning example")
```
Expand Down Expand Up @@ -126,7 +126,7 @@ logger = SizeRotatingLog(
daystokeep=7,
timezone="America/Chicago",
streamhandler=True,
showlocation=False
showlocation=False,
)
logger.warning("This is a warning example")
```
Expand Down Expand Up @@ -162,7 +162,7 @@ logger = TimedRotatingLog(
daystokeep=7,
timezone="UTC",
streamhandler=True,
showlocation=False
showlocation=False,
)
logger.warning("This is a warning example")
```
Expand Down Expand Up @@ -223,8 +223,8 @@ app_logger = SizeRotatingLog(
daystokeep=30, # Keep 30 days
level=LogLevel.INFO,
streamhandler=True, # Also log to console
showlocation=True, # Show file:function:line
timezone="UTC"
showlocation=True, # Show file:function:line
timezone="UTC",
)

# Error logger with longer retention
Expand All @@ -235,16 +235,12 @@ error_logger = SizeRotatingLog(
maxmbytes=10,
daystokeep=90, # Keep errors longer
level=LogLevel.ERROR,
streamhandler=False
streamhandler=False,
)

# Audit logger with daily rotation
audit_logger = TimedRotatingLog(
name="audit_log",
directory="/var/log/myapp",
filenames=["audit.log"],
when=RotateWhen.MIDNIGHT,
level=LogLevel.INFO
name="audit_log", directory="/var/log/myapp", filenames=["audit.log"], when=RotateWhen.MIDNIGHT, level=LogLevel.INFO
)

# Use the loggers
Expand All @@ -263,6 +259,7 @@ If not specified inside the .env file, it will use the default value.\
This is a good approach for production environments, since options can be changed easily.
```python
from pythonlogs import TimedRotatingLog

log = TimedRotatingLog()
```

Expand Down Expand Up @@ -297,8 +294,8 @@ from pythonlogs import get_log_settings, clear_settings_cache

# Inspect current settings
settings = get_log_settings()
print(settings.level) # Current log level
print(settings.timezone) # Current timezone
print(settings.level) # Current log level
print(settings.timezone) # Current timezone

# Clear cache and reload .env on next access (default)
clear_settings_cache()
Expand All @@ -320,27 +317,27 @@ You can use either enums (for type safety) or strings (for simplicity):
from pythonlogs import LogLevel, RotateWhen

# Option 1: Type-safe enums (recommended)
LogLevel.DEBUG # "DEBUG"
LogLevel.INFO # "INFO"
LogLevel.WARNING # "WARNING"
LogLevel.ERROR # "ERROR"
LogLevel.DEBUG # "DEBUG"
LogLevel.INFO # "INFO"
LogLevel.WARNING # "WARNING"
LogLevel.ERROR # "ERROR"
LogLevel.CRITICAL # "CRITICAL"

# Option 2: String values (case-insensitive)
"debug" # Same as LogLevel.DEBUG
"info" # Same as LogLevel.INFO
"warning" # Same as LogLevel.WARNING
"warn" # Same as LogLevel.WARN (alias)
"error" # Same as LogLevel.ERROR
"critical" # Same as LogLevel.CRITICAL
"crit" # Same as LogLevel.CRIT (alias)
"debug" # Same as LogLevel.DEBUG
"info" # Same as LogLevel.INFO
"warning" # Same as LogLevel.WARNING
"warn" # Same as LogLevel.WARN (alias)
"error" # Same as LogLevel.ERROR
"critical" # Same as LogLevel.CRITICAL
"crit" # Same as LogLevel.CRIT (alias)
# Also supports: "DEBUG", "Info", "Warning", etc.

# RotateWhen values
RotateWhen.MIDNIGHT # "midnight"
RotateWhen.HOURLY # "H"
RotateWhen.DAILY # "D"
RotateWhen.MONDAY # "W0"
RotateWhen.MIDNIGHT # "midnight"
RotateWhen.HOURLY # "H"
RotateWhen.DAILY # "D"
RotateWhen.MONDAY # "W0"
# ... through SUNDAY # "W6"
# String equivalents: "midnight", "H", "D", "W0"-"W6"
```
Expand Down
20 changes: 10 additions & 10 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ packages = ["pythonlogs"]

[project]
name = "pythonlogs"
version = "7.0.1"
version = "7.0.2"
description = "High-performance Python logging library with file rotation and optimized caching for better performance"
urls.Repository = "https://github.com/ddc/pythonlogs"
urls.Homepage = "https://pypi.org/project/pythonlogs"
Expand Down Expand Up @@ -45,29 +45,29 @@ classifiers = [
]
requires-python = ">=3.12"
dependencies = [
"pydantic-settings>=2.11.0",
"pydantic-settings>=2.15.0",
]

[dependency-groups]
dev = [
"psutil>=7.2.2",
"pytest-cov>=7.1.0",
"poethepoet>=0.43.0",
"ruff>=0.15.9",
"poethepoet>=0.48.0",
"ruff>=0.16.3",
]

[tool.poe.tasks]
linter.shell = "uv run ruff check --fix . && uv run ruff format ."
snyk-export.shell = "rm -f requirements.txt && uv export --no-hashes --no-annotate --format requirements-txt > requirements.txt && uvx pre-commit run --all-files || uvx pre-commit run --all-files"
snyk-export.shell = "uv export --no-hashes --no-annotate --format requirements-txt > requirements.txt && uvx pre-commit run --all-files || uvx pre-commit run --all-files"
snyk.sequence = ["snyk-export", { shell = "uv pip install pip && snyk test --file=requirements.txt && snyk code test; uv pip uninstall pip" }]
profile = "uv run python -m cProfile -o cprofile_unit.prof -m pytest --no-cov"
tests.sequence = ["linter", {shell = "uv run pytest"}]
updatedev.sequence = ["linter", {shell = "uv lock --upgrade && uv sync --all-extras --all-groups"}]
test-unit = "uv run pytest"
tests.sequence = ["linter", "test-unit"]
updatedev.sequence = [{shell = "uv lock --upgrade && uv sync --all-extras --all-groups"}, "snyk-export"]
build.sequence = ["updatedev", "tests", {shell = "uv build --wheel"}]

[tool.pytest.ini_options]
addopts = "-v --import-mode=importlib --cov --cov-report=term --cov-report=xml --junitxml=junit.xml"
junit_family = "legacy"
addopts = "-v --import-mode=importlib --cov --cov-report=term --cov-report=xml"
testpaths = ["tests"]
markers = [
"slow: marks tests as slow (deselect with '-m \"not slow\"')",
Expand Down Expand Up @@ -96,8 +96,8 @@ exclude_lines = [
]

[tool.ruff]
line-length = 120
target-version = "py312"
line-length = 120

[tool.ruff.lint]
select = ["E", "W", "F", "I", "B", "C4", "UP", "S", "SLF"]
Expand Down
9 changes: 4 additions & 5 deletions pythonlogs/.env.example
Original file line number Diff line number Diff line change
Expand Up @@ -11,20 +11,19 @@ LOG_FILENAME=app.log
LOG_DIRECTORY=/app/logs
LOG_DAYS_TO_KEEP=30
LOG_DATE_FORMAT=%Y-%m-%dT%H:%M:%S
LOG_STREAM_HANDLER=True
LOG_SHOW_LOCATION=False
LOG_STREAM_HANDLER=true
LOG_SHOW_LOCATION=false
# Memory Management Settings
LOG_MAX_LOGGERS=50
LOG_MAX_FORMATTERS=50
LOG_LOGGER_TTL_SECONDS=1800

# SizeRotatingLog Settings (only needed when using SizeRotatingLog)
LOG_MAX_FILE_SIZE_MB=10

# TimedRotatingLog Settings (only needed when using TimedRotatingLog)
LOG_ROTATE_WHEN=midnight
LOG_ROTATE_FILE_SUFIX=%Y%m%d

# SizeRotatingLog Settings (only needed when using SizeRotatingLog)
LOG_MAX_FILE_SIZE_MB=10

# Available LOG_LEVEL values: DEBUG, INFO, WARNING, ERROR, CRITICAL
# Available LOG_TIMEZONE values: UTC, localtime, or any valid timezone (e.g., America/New_York)
Expand Down
17 changes: 17 additions & 0 deletions sonar-project.properties
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
sonar.projectKey=ddc_pythonlogs
sonar.organization=ddc1

sonar.sources=pythonlogs
sonar.tests=tests

sonar.python.version=3.14
sonar.python.coverage.reportPaths=coverage.xml
sonar.scm.exclusions.disabled=true

sonar.exclusions=\
.github/**,\
tests/**

sonar.coverage.exclusions=\
.github/**/*,\
tests/**/*
Loading