Skip to content
Open
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
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -8,3 +8,6 @@
/.vs
/Tic_Tac_Toe/tic_tac_toe -OOP.py
/.vscode
.venv
.log
/__pycache__/
72 changes: 72 additions & 0 deletions LoggerLibrary/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
<!--Please do not remove this part-->
![Star Badge](https://img.shields.io/static/v1?label=%F0%9F%8C%9F&message=If%20Useful&style=style=flat&color=BC4E99)
![Open Source Love](https://badges.frapsoft.com/os/v1/open-source.svg?v=103)

# LoggerLibrary

## Description

A simple Python logging utility with console/file output and automatic log cleanup. This library provides an easy-to-use interface for setting up logging in your Python projects with minimal configuration.

**Key Features:**
- Simple setup with one function call
- Session tracking with auto-generated UUID to trace logs from the same execution
- Dual output: log to console for debugging and file for persistent records
- Auto cleanup: keep only recent logs (default: 3 days), no manual deletion needed

## Languages or Frameworks Used

This project uses Python 3.x with only standard library modules (no external dependencies required).

## How to run

### Quick Start

1. create `demo.py`

2. Import the logger setup function:
```python
from logger import setup_logger
```

3. Choose your setup method:

**Method 1: Customized Configuration**
```python
logger = setup_logger(
name=__name__,
enable_console=True,
enable_file=True,
level=logging.INFO,
dir='./logs'
)
logger.debug('Debug message')
logger.info('Info message')
```

**Method 2: Default Configuration**
```python
logger = setup_logger()
logger.debug('Debug message')
logger.info('Info message')
```

4. Run your Python script:
```bash
python3 demo.py
```

### Log Output Format

```
2025-11-16 00:41:00,951 | demo.py | INFO | 49e1e65d-2734-4807-81de-306ee628d788 | Your message
```

## Demo

See the result of running the logger with both console and file output:
<img src="result.jpg" width=80% height=80%>

## Author

Shyin Lim -> https://github.com/shyinlim
14 changes: 14 additions & 0 deletions LoggerLibrary/demo.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
from logger import setup_logger

logger = setup_logger(name=__name__, enable_console=True, enable_file=False)

class Sample:
def print_log(self):
logger.debug(f'[PRINT LOG] DEBUG')
logger.info(f'[PRINT LOG] INFO')
logger.warning(f'[PRINT LOG] WARNING')
logger.error(f'[PRINT LOG] ERROR')


s = Sample()
s.print_log()
102 changes: 102 additions & 0 deletions LoggerLibrary/logger.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
import logging
import os
import re
import sys
import uuid as uuid_module
from datetime import datetime, timedelta

# === Configuration ===
ENABLE_CONSOLE = True
ENABLE_FILE = True
LOG_LEVEL = logging.DEBUG
LOG_DIR = './.log'
KEEP_DAYS = 3


def setup_logger(
name: str = None,
enable_console: bool = ENABLE_CONSOLE,
enable_file: bool = ENABLE_FILE,
level: int = LOG_LEVEL,
dir: str = LOG_DIR
) -> logging.Logger:
"""Setup logger with console and file handlers

Args:
name: Logger name (use __name__ to get current file), default None (root logger)
enable_console: Enable console output, default True
enable_file: Enable file output, default True
level: Logging level, default DEBUG
dir: Log file directory, default './.log'

Returns:
Configured logger instance

Example:
from logger import setup_logger

logger = setup_logger(name=__name__, enable_console=True, enable_file=False)
logger.info('Test message')
"""
# Setup logger
logger = logging.getLogger(name=name if name else '')
logger.setLevel(level=level)


logger.handlers.clear() # Clear existing handlers to prevent duplicate logs

session_uuid = uuid_module.uuid4()
formatter = logging.Formatter(
f'%(asctime)s | %(filename)s | %(levelname)s | {session_uuid} | %(message)s'
)

# Console handler
if enable_console:
console_handler = logging.StreamHandler(stream=sys.stderr)
console_handler.setLevel(level=level)
console_handler.setFormatter(fmt=formatter)
logger.addHandler(hdlr=console_handler)

# File handler
if enable_file:
os.makedirs(name=dir, mode=0o777, exist_ok=True)
timestamp = datetime.now().strftime('%Y%m%d')
file_path = os.path.join(dir, f'{timestamp}.log')

file_handler = logging.FileHandler(filename=file_path, encoding='utf-8')
file_handler.setLevel(level=level)
file_handler.setFormatter(fmt=formatter)
logger.addHandler(hdlr=file_handler)

logger.info(f'Log file created: {file_path}')

# Clean old log files
cleanup_old_logs(directory=dir, keep_days=KEEP_DAYS, logger=logger)

return logger


def cleanup_old_logs(directory: str, keep_days: int = 3, logger: logging.Logger = None) -> None:
"""Clean up log files older than specified days

Args:
directory: Directory containing log files
keep_days: Number of days to keep log files, default 3
logger: Logger instance for logging cleanup results
"""
now = datetime.now()
pattern = re.compile(r'(\d{8})_\d{6}\.log')

for filename in os.listdir(directory):
match = pattern.match(filename)
if match:
date_str = match.group(1)
try:
file_date = datetime.strptime(date_str, '%Y%m%d')
if now - file_date > timedelta(days=keep_days):
os.remove(path=os.path.join(directory, filename))
if logger:
logger.info(f'Deleted old log: {filename}')
except Exception as e:
if logger:
logger.warning(f'Failed to delete log: {filename}; {e}')
Binary file added LoggerLibrary/result.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.