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
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,9 @@ coverage.xml
# Django stuff:
*.log

# Application logs
logs/

# Sphinx documentation
docs/_build/

Expand Down
62 changes: 62 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -203,6 +203,68 @@ class TestNewFeature(unittest.TestCase):
pass
```

## Logging

The application includes comprehensive logging to improve debugging capabilities and operational visibility. Logs are written to both console and rotating log files.

### Log Files Location
- **Directory:** `logs/`
- **Main log file:** `logs/app.log`
- **Rotation:** Files rotate at 10MB with up to 5 backup files

### Log Levels
- **DEBUG:** Detailed diagnostic information (file operations, API calls, data flow)
- **INFO:** General informational messages (successful operations, state changes)
- **WARNING:** Warning messages for recoverable issues (fallbacks, empty files)
- **ERROR:** Error messages for failures that don't stop execution
- **CRITICAL:** Critical failures requiring immediate attention

### Configuring Log Levels
Set the `LOG_LEVEL` environment variable to control logging verbosity:

```bash
export LOG_LEVEL=DEBUG # For detailed debugging
export LOG_LEVEL=INFO # For normal operation
export LOG_LEVEL=WARNING # For production with minimal logs
```

### Interpreting Common Log Messages

#### File Operations (generate_meet_link)
- `"Attempting to read meet_links.txt"` - Starting file read operation
- `"Retrieved Meet link from file: {link}"` - Successfully read link from file
- `"meet_links.txt not found. Falling back to API."` - File missing, using API fallback
- `"meet_links.txt is empty. Falling back to API."` - File exists but no links available

#### API Operations
- `"Starting event details extraction from message"` - Beginning OpenAI API call for event parsing
- `"Successfully extracted event details: {details}"` - Event parsing completed
- `"Starting Google Calendar event scheduling"` - Beginning calendar API call
- `"Successfully scheduled event: {title}"` - Calendar event created

#### Error Scenarios
- `"OpenAI API error while extracting event details: {error}"` - OpenAI API failure
- `"Google Calendar API HTTP error: {status} - {content}"` - Calendar API error
- `"Error uploading file {path}: {error}"` - File upload failure

### Security Considerations
- Sensitive data (API keys, tokens, personal information) is never logged
- Meet link URLs in logs are sanitized if they contain query parameters
- Log files are excluded from version control via `.gitignore`

### Enabling Debug Logging
For troubleshooting issues, enable DEBUG logging:

1. Set environment variable: `export LOG_LEVEL=DEBUG`
2. Restart the application
3. Check `logs/app.log` for detailed diagnostic information

### Log Rotation
Logs automatically rotate when they reach 10MB to prevent disk space issues. The rotation creates backup files:
- `app.log.1` (most recent backup)
- `app.log.2` (older backup)
- Up to `app.log.5` (oldest backup)

## Contributing

Contributions are welcome! Please fork the repository and submit a pull request with your improvements.
Expand Down
8 changes: 3 additions & 5 deletions app/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
import os
from dotenv import load_dotenv
import logging
from .logging_config import setup_logging


def load_configurations(app):
Expand All @@ -18,8 +19,5 @@ def load_configurations(app):


def configure_logging():
logging.basicConfig(
level=logging.INFO,
format="%(asctime)s - %(name)s - %(levelname)s - %(message)s",
stream=sys.stdout,
)
"""Configure logging using the centralized logging configuration."""
setup_logging()
66 changes: 66 additions & 0 deletions app/logging_config.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
import logging.config
import os

LOGGING_CONFIG = {
'version': 1,
'disable_existing_loggers': False,
'formatters': {
'standard': {
'format': '%(asctime)s - %(name)s - %(levelname)s - %(message)s'
},
'detailed': {
'format': '%(asctime)s - %(name)s - %(levelname)s - %(funcName)s:%(lineno)d - %(message)s'
},
},
'handlers': {
'console': {
'class': 'logging.StreamHandler',
'level': 'INFO',
'formatter': 'standard',
'stream': 'ext://sys.stdout',
},
'file': {
'class': 'logging.handlers.RotatingFileHandler',
'level': 'DEBUG',
'formatter': 'detailed',
'filename': 'logs/app.log',
'maxBytes': 10485760, # 10MB
'backupCount': 5,
},
},
'loggers': {
'app.services.openai_service': {
'level': 'DEBUG',
'handlers': ['console', 'file'],
'propagate': False,
},
'app': {
'level': 'INFO',
'handlers': ['console', 'file'],
'propagate': False,
},
},
'root': {
'level': 'INFO',
'handlers': ['console', 'file'],
},
}

def setup_logging():
"""Setup logging configuration."""
# Create logs directory if it doesn't exist
os.makedirs('logs', exist_ok=True)

# Apply logging configuration
logging.config.dictConfig(LOGGING_CONFIG)

# Set log level from environment variable if provided
log_level = os.getenv('LOG_LEVEL', 'INFO').upper()
try:
numeric_level = getattr(logging, log_level)
logging.getLogger().setLevel(numeric_level)
logging.getLogger('app').setLevel(numeric_level)
logging.getLogger('app.services.openai_service').setLevel(logging.DEBUG)
except AttributeError:
logging.warning(f"Invalid LOG_LEVEL '{log_level}', using INFO")
logging.getLogger().setLevel(logging.INFO)
Loading