Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Log level #1

Open
wants to merge 4 commits into
base: master
Choose a base branch
from
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
168 changes: 168 additions & 0 deletions log_level_filter_usage.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,168 @@
# ModelLogger Usage Guide

ModelLogger is a flexible and feature-rich logging solution that provides colored console output and automatic log rotation capabilities.

## Installation

```bash
pip install django-logging-easy
```

## Basic Usage

### Simple Console Logging

```python
from model_logger import ModelLogger

# Create a basic logger
logger = ModelLogger(name="MyApp")

# Log messages with different levels
logger.debug("Debug message")
logger.info("Information message")
logger.success("Success message")
logger.warning("Warning message")
logger.error("Error message")
```

### File Logging with Rotation

```python
# Create a logger with file output
logger = ModelLogger(
name="MyApp",
file_path="logs/app.log",
max_file_size=1024 * 1024, # 1MB
backup_count=5
)

# Logs will be written to both console and file
logger.info("This message goes to both console and file")
```

## Advanced Configuration

### Custom Archive Directory

```python
logger = ModelLogger(
name="MyApp",
file_path="logs/app.log",
archive_dir="logs/custom_archives",
max_file_size=5 * 1024 * 1024, # 5MB
backup_count=10
)
```

### Custom Timestamp Format

```python
logger = ModelLogger(
name="MyApp",
timestamp_format="%Y-%m-%d %H:%M:%S.%f"
)
```

### Setting Log Level

```python
# Set minimum log level during initialization
logger = ModelLogger(name="MyApp", level="WARNING")

# Or change it dynamically
logger.set_level("DEBUG")
```

## Log Levels

ModelLogger supports five log levels (in order of increasing priority):

1. DEBUG (lowest)
2. INFO
3. SUCCESS
4. WARNING
5. ERROR (highest)

Messages below the set log level will not be displayed or written to file.

## Output Colors

Each log level has a distinct color in the console:
- DEBUG: Magenta
- INFO: Blue
- SUCCESS: Green
- WARNING: Yellow
- ERROR: Red

## Log Rotation Features

The logger automatically manages log files by:
- Creating compressed backups when file size limit is reached
- Maintaining a specified number of backup files
- Adding timestamps to backup files
- Organizing backups in a dedicated archive directory

### Default Directory Structure

```
logs/
├── app.log # Current log file
└── archive/
├── app.log_20240315_143022.gz # Most recent backup
├── app.log_20240315_142501.gz
└── app.log_20240315_141955.gz
```

## Complete Configuration Example

```python
from model_logger import ModelLogger

logger = ModelLogger(
name="MyApplication", # Logger name
file_path="logs/app.log", # Log file path
timestamp_format="%Y-%m-%d %H:%M:%S", # Custom timestamp format
level="DEBUG", # Minimum log level
max_file_size=10 * 1024 * 1024, # 10MB max file size
backup_count=5, # Keep 5 backup files
archive_dir="logs/archives" # Custom archive directory
)

# Example usage
logger.debug("Debug information")
logger.info("Processing started")
logger.success("Task completed successfully")
logger.warning("Resource usage high")
logger.error("Connection failed")
```

## Best Practices

1. **Log Level Selection**
- Use DEBUG for detailed debugging information
- Use INFO for general operational messages
- Use SUCCESS for successful operations
- Use WARNING for concerning but non-critical issues
- Use ERROR for critical issues that need immediate attention

2. **File Management**
- Set appropriate `max_file_size` based on your application's logging volume
- Choose `backup_count` based on how long you need to retain logs
- Use descriptive logger names to identify the source of logs

3. **Archive Organization**
- Use custom `archive_dir` for better organization in large applications
- Monitor archive directory size periodically

## Error Handling

The logger handles various errors gracefully:
- Invalid log levels
- File permission issues
- Directory creation failures
- Rotation and compression errors

## Thread Safety

The logger is designed to be thread-safe and can be used in multi-threaded applications.
3 changes: 3 additions & 0 deletions model_logger/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
from .log_level import ModelLogger

__all__ = ['ModelLogger']
11 changes: 11 additions & 0 deletions model_logger/admin.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
from django.contrib import admin
from .models import LogEntry

class LogEntryAdmin(admin.ModelAdmin):
list_display = ('timestamp', 'level', 'message')
search_fields = ('message',)
list_filter = ('level',)
ordering = ('-timestamp',)
readonly_fields = ('timestamp',)

admin.site.register(LogEntry, LogEntryAdmin)
48 changes: 43 additions & 5 deletions model_logger/decorators.py
Original file line number Diff line number Diff line change
@@ -1,23 +1,61 @@
from functools import wraps
import time
import inspect
from django.contrib.contenttypes.models import ContentType
from django.conf import settings
from .models import ModelLog

def log_action(name=None, description=None):
def log_action(name=None, description=None, action_type='OTHER'):
def decorator(func):
@wraps(func)
def wrapper(self, *args, **kwargs):
# Execute the original function/method
start_time = time.time()

previous_instance = None
if action_type == 'UPDATE' and hasattr(self, 'pk') and self.pk:
previous_instance = self.__class__.objects.filter(pk=self.pk).first()

result = func(self, *args, **kwargs)

# Create the log entry
execution_time = (time.time() - start_time) * 1000

request = None
for frame_record in inspect.stack():
if frame_record[3] == 'get_response':
request = frame_record[0].f_locals.get('request')
break

content_type = ContentType.objects.get_for_model(self.__class__)
ModelLog.objects.create(
log_entry = ModelLog.objects.create(
name=name or func.__name__,
description=description or f"Action performed: {func.__name__}",
content_type=content_type,
object_id=self.id
object_id=self.id,
action_type=action_type,
execution_time=execution_time
)

if request:
log_entry.user = getattr(request, 'user', None)
log_entry.ip_address = get_client_ip(request)
log_entry.user_agent = request.META.get('HTTP_USER_AGENT', '')

log_entry.save_changes(
previous_instance=previous_instance,
current_instance=self if hasattr(self, 'pk') and self.pk else None
)

return result
return wrapper
return decorator

def get_client_ip(request):
"""
İstemci IP adresini al
"""
x_forwarded_for = request.META.get('HTTP_X_FORWARDED_FOR')
if x_forwarded_for:
ip = x_forwarded_for.split(',')[0]
else:
ip = request.META.get('REMOTE_ADDR')
return ip
Loading