A feature-rich, configurable logging module with structured JSON output
Project description
JH Logger
A feature-rich, configurable logging module that provides structured JSON output with comprehensive error tracking, third-party service integration, and enhanced security features. Built for Jacaranda Health's microservices ecosystem.
🌟 Features
✅ Configurable Log Levels
- Support for all standard log levels: DEBUG, INFO, WARNING, ERROR, CRITICAL
- Dynamic log level changes at runtime
- Enum-based level specification for type safety
✅ Enhanced Error Information
- DEBUG Level: Shows full traceback for detailed debugging
- ERROR Level: Captures exception details (type, message, traceback)
- File Context: Automatically captures filename, function name, class name, and line number
- Module Information: Includes module path and calling context
- Security: Uses relative file paths instead of full absolute paths to avoid exposing system information
✅ Structured JSON Output
- All logs are formatted as JSON with 4-space indentation for readability
- Consistent structure across all log entries with sorted keys
- Support for arbitrary data fields
✅ Third-Party Service Integration
- CloudWatch: Automatic CloudWatch logging in non-development environments
- Sentry: Exception capturing and monitoring for ERROR/CRITICAL levels
- Environment-aware configuration
✅ Rich Context Information
- System information (country, environment, service name, process ID)
- UTC timestamp in ISO format
- Caller information (filename, function, class, line number)
- Custom data fields support
📦 Installation
Development Installation
git clone https://github.com/Jacaranda-Health/jhlogger.git
cd jhlogger
uv sync --all-extras
With UV (recommended)
# Create virtual environment and install dependencies
uv sync
# For development with all extras
uv sync --all-extras
With Pip
# Basic installation
pip install -e .
# With development dependencies
pip install -e .[dev]
# With documentation dependencies
pip install -e .[docs]
# All extras
pip install -e .[dev,docs]
🚀 Quick Start
Basic Usage
from jhlogger import info, error, debug, ConfigurableLogger
# Simple logging
info("Application started successfully")
error("Something went wrong", data={"error_code": "E001"})
# With exception
try:
result = 10 / 0
except Exception as e:
error("Division failed", exception=e, data={"operation": "10/0"})
# Debug with full traceback
debug("Debug information", data={"step": "initialization"})
Custom Logger Instance
from jhlogger import ConfigurableLogger, LogLevel
logger = ConfigurableLogger(
name="my-service",
log_level=LogLevel.DEBUG,
enable_cloudwatch=True,
include_system_info=True
)
logger.info("Custom logger initialized")
Class-Based Usage
from jhlogger import create_logger
class UserService:
def __init__(self):
self.logger = create_logger(name="user-service")
def create_user(self, username, email):
self.logger.info("Creating user", data={
"username": username,
"email": email
})
try:
# Your logic here
self.logger.info("User created successfully")
except Exception as e:
self.logger.error("Failed to create user", exception=e)
📊 Log Output Format
Standard Log Entry
{
"class": "UserService",
"country": "KE",
"data": {
"ip_address": "192.168.1.100",
"user_id": "12345",
"username": "john_doe"
},
"environment": "production",
"event": "User logged in successfully",
"filename": "user_service.py",
"file_path": "app/services/user_service.py",
"function": "login_user",
"level": "info",
"line_number": 45,
"module": "services.user_service",
"process_id": 1234,
"service": "rapid-pro-service",
"timestamp": "2025-09-18T10:30:00.123456Z",
"timestamp_utc": "2025-09-18T10:30:00.123456+00:00"
}
DEBUG Level (includes traceback)
{
"event": "Debug information",
"level": "debug",
"timestamp": "2025-09-18T10:30:00.123456Z",
"traceback": [
" File \"main.py\", line 10, in <module>",
" debug_function()",
" File \"main.py\", line 5, in debug_function",
" logger.debug(\"Debug info\")"
]
}
ERROR Level (includes exception details)
{
"event": "Database connection failed",
"exception": {
"args": ["Unable to connect to database"],
"message": "Unable to connect to database",
"traceback": [
"Traceback (most recent call last):",
" File \"app.py\", line 25, in connect_db",
" conn = database.connect()",
"ConnectionError: Unable to connect to database"
],
"type": "ConnectionError"
},
"level": "error",
"timestamp": "2025-09-18T10:30:00.123456Z"
}
⚙️ Configuration
Environment Variables
The logger respects these environment variables:
APP_ENVorFLASK_ENV: Application environment (development, staging, production)COUNTRY: Country code for log grouping (defaults to system locale)
ConfigurableLogger Parameters
ConfigurableLogger(
name="service-name", # Logger name
log_level=LogLevel.INFO, # Minimum log level
enable_cloudwatch=True, # Enable CloudWatch logging
enable_sentry=True, # Enable Sentry integration
enable_bugsnag=True, # Enable Bugsnag integration (deprecated)
cloudwatch_log_group="custom-group", # Custom CloudWatch group
include_system_info=True, # Include system information
custom_processors=[] # Additional structlog processors
)
🔧 Advanced Usage
Bound Context Logging
# Bind context that applies to all subsequent logs
bound_logger = logger.bind(
request_id="req_123",
session_id="sess_456"
)
bound_logger.info("Processing request") # Includes bound context
bound_logger.warning("Rate limit approaching") # Also includes context
Dynamic Log Level Changes
logger = ConfigurableLogger(log_level=LogLevel.WARNING)
logger.info("This won't show") # Below WARNING level
logger.set_level(LogLevel.DEBUG)
logger.info("Now this will show") # Now visible
Structured Data Logging
complex_data = {
"user_profile": {
"id": "usr_123",
"name": "Jane Doe",
"roles": ["admin", "user"]
},
"request_info": {
"method": "POST",
"endpoint": "/api/users",
"duration_ms": 156
}
}
logger.info("User operation completed", data=complex_data)
🔒 Security Features
- Relative File Paths: Uses relative paths instead of absolute paths to prevent system information exposure
- Sanitized Output: Avoids leaking sensitive system details in logs
- Configurable Information: Control what system information is included
- Context Suppression: Uses
contextlib.suppressfor robust error handling
🧪 Development & Testing
Development Setup
# Clone the repository
git clone https://github.com/Jacaranda-Health/jhlogger.git
cd jhlogger
# Install with UV (recommended)
uv sync --all-extras
# Or with pip
pip install -e .[dev]
# Install pre-commit hooks
pre-commit install
Available Commands
# Format code
make format
# Run linting
make lint
# Run tests
make test
# Run tests with coverage
make test-cov
# Clean build artifacts
make clean
Running Tests
# Run all tests with coverage
make test
# Run tests with detailed coverage report
make test-cov
# View coverage report
open htmlcov/index.html
Current test coverage: 87% (173 statements, 22 missing)
📋 Development Standards
- Code Formatting: Black (100 character line length)
- Import Sorting: isort (Black-compatible profile)
- Linting: flake8 with flake8-simplify
- Type Checking: mypy (when available)
- Testing: pytest with coverage reporting
- Pre-commit Hooks: Automated formatting and linting
📄 License
This project is licensed under the MIT License - see the LICENSE file for details.
🤝 Support
- 📫 Issues: GitHub Issues
- 📖 Documentation: README.md
- 🔗 Repository: GitHub Repository
🏷️ Changelog
v1.0.0 (Initial Release)
- ✅ Configurable log levels with dynamic changes
- ✅ Structured JSON output with 4-space indentation and 100-char line length
- ✅ Full traceback for DEBUG, exception details for ERROR/CRITICAL
- ✅ Automatic caller information detection (file, function, class, line)
- ✅ Third-party service integration (CloudWatch, Sentry)
- ✅ Relative file paths for security
- ✅ Environment-aware configuration
- ✅ Comprehensive test suite (87% coverage, 36 tests)
- ✅ Pre-commit hooks for code quality
- ✅ Modern Python packaging with pyproject.toml
- ✅ UV-compatible dependency management
- ✅ Updated datetime handling (Python 3.13 compatible)
Made with ❤️ for Jacaranda Health's logging needs
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file jhlogger-1.0.1.tar.gz.
File metadata
- Download URL: jhlogger-1.0.1.tar.gz
- Upload date:
- Size: 20.8 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
42c734aa4d86309e5be86704a825157b70952959986cae453239a3cb824586de
|
|
| MD5 |
c3faef1144cc2f5e10e59f2e025a2f6a
|
|
| BLAKE2b-256 |
597f711484c7aa254442f31b55cc4076e8856242d1d217a4d75070d03eb6a71f
|
Provenance
The following attestation bundles were made for jhlogger-1.0.1.tar.gz:
Publisher:
publish-to-pypi.yml on Jacaranda-Health/jhlogger
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
jhlogger-1.0.1.tar.gz -
Subject digest:
42c734aa4d86309e5be86704a825157b70952959986cae453239a3cb824586de - Sigstore transparency entry: 551057305
- Sigstore integration time:
-
Permalink:
Jacaranda-Health/jhlogger@33543e0ac4b5074f4e9e65f338026d8ac7652193 -
Branch / Tag:
refs/tags/v1.0.1 - Owner: https://github.com/Jacaranda-Health
-
Access:
private
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish-to-pypi.yml@33543e0ac4b5074f4e9e65f338026d8ac7652193 -
Trigger Event:
release
-
Statement type:
File details
Details for the file jhlogger-1.0.1-py3-none-any.whl.
File metadata
- Download URL: jhlogger-1.0.1-py3-none-any.whl
- Upload date:
- Size: 10.2 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
842eaf6a54630fa2109468940e02286b5e9bf88be3fd75c171970ecc7a3041e2
|
|
| MD5 |
6ff98d55527dd88ba8b12545d9049807
|
|
| BLAKE2b-256 |
a6189089dd009e13d1e6009ad151699bbbd67c14600ae04f2cfc5b1eedac03d0
|
Provenance
The following attestation bundles were made for jhlogger-1.0.1-py3-none-any.whl:
Publisher:
publish-to-pypi.yml on Jacaranda-Health/jhlogger
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
jhlogger-1.0.1-py3-none-any.whl -
Subject digest:
842eaf6a54630fa2109468940e02286b5e9bf88be3fd75c171970ecc7a3041e2 - Sigstore transparency entry: 551057311
- Sigstore integration time:
-
Permalink:
Jacaranda-Health/jhlogger@33543e0ac4b5074f4e9e65f338026d8ac7652193 -
Branch / Tag:
refs/tags/v1.0.1 - Owner: https://github.com/Jacaranda-Health
-
Access:
private
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish-to-pypi.yml@33543e0ac4b5074f4e9e65f338026d8ac7652193 -
Trigger Event:
release
-
Statement type: