How to Manage Logs in Your Flask Application
Table of Contents
- Introduction to Logging in Flask
- Why Logging Matters
- Basic Logging Setup in Flask
- Log Levels
- Log Formatting
- Channels and Handlers
- Tips for Managing Logs
- Alternative Libraries
- Best Practices
- Troubleshooting
- FAQ
Introduction to Logging in Flask
Logging is the process of recording information about your application’s operations during runtime. In Flask, logging helps you track what’s happening in your web application, from simple HTTP requests to complex errors. With good logging, you can debug issues, monitor performance, and better understand user behavior.
Flask uses Python’s built-in logging module, which is powerful and flexible. You can configure logging to capture various types of information, from debug messages to critical errors.
Why Logging Matters
Logging provides several crucial benefits for application development and maintenance:
Effective Debugging: When your production application encounters issues, logs are the first source of information you check. Without proper logging, you’re like looking for a needle in a haystack.
Performance Monitoring: Logs can record response times, database queries, and resource usage, helping you identify bottlenecks and areas for optimization.
Security Auditing: Track suspicious activities, login attempts, and data changes for application security.
Business Intelligence: Analyze user behavior patterns, popular features, and usage statistics from logs.
Troubleshooting: When users report problems, logs help you reproduce and resolve issues quickly.
Without good logging, your Flask application is like a ship without radar at night - you don’t know what’s happening inside it.
Basic Logging Setup in Flask
Let’s start with basic logging setup in a Flask application. Python’s logging module is built-in, so you don’t need to install additional packages.
from flask import Flask
import logging
app = Flask(__name__)
# Setup basic logging
logging.basicConfig(level=logging.INFO)
@app.route('/')
def hello():
app.logger.info('Hello endpoint accessed')
return 'Hello World!'
if __name__ == '__main__':
app.run()
With the above code, Flask will log all INFO level and above messages to the console. You’ll see output like:
INFO:werkzeug:127.0.0.1 - - [05/Feb/2026 10:00:00] "GET / HTTP/1.1" 200 -
INFO:__main__:Hello endpoint accessed
The first line is from Werkzeug (Flask’s WSGI utility), the second from your application logger.
Log Levels
Python’s logging has several different levels, each with a specific purpose:
- DEBUG: Detailed information for debugging (level 10)
- INFO: General information about normal operations (level 20)
- WARNING: Indication of potential problems (level 30)
- ERROR: Errors that don’t stop the application (level 40)
- CRITICAL: Serious errors that might stop the application (level 50)
@app.route('/user/<int:user_id>')
def get_user(user_id):
app.logger.debug(f'Fetching user with ID: {user_id}')
# Simulate database operation
user = {'id': user_id, 'name': 'John Doe'}
app.logger.info(f'User {user_id} retrieved successfully')
return user
@app.route('/divide/<int:a>/<int:b>')
def divide(a, b):
try:
result = a / b
app.logger.info(f'Division result: {a}/{b} = {result}')
return str(result)
except ZeroDivisionError:
app.logger.error(f'Division by zero attempted: {a}/{b}')
return 'Error: Division by zero', 400
Use the appropriate level for each situation. Too much DEBUG in production can make logs bloated and hard to read.
Log Formatting
Log formatting determines how log messages are displayed. You can customize the format to include timestamp, level, module name, and other information.
import logging
# Custom format
formatter = logging.Formatter(
'%(asctime)s - %(name)s - %(levelname)s - %(message)s'
)
# Setup handler with format
handler = logging.StreamHandler()
handler.setFormatter(formatter)
# Setup logger
logger = logging.getLogger(__name__)
logger.setLevel(logging.INFO)
logger.addHandler(handler)
# In Flask app
app.logger.addHandler(handler)
More advanced format:
formatter = logging.Formatter(
'%(asctime)s [%(levelname)s] %(name)s:%(lineno)d - %(message)s',
datefmt='%Y-%m-%d %H:%M:%S'
)
This will produce output like:
2025-12-13 10:30:15 [INFO] app:45 - User login successful
Channels and Handlers
Channels or handlers determine where logs are sent. Python logging supports various handlers:
Console Handler (StreamHandler)
Default handler that outputs to console/terminal:
import sys
console_handler = logging.StreamHandler(sys.stdout)
console_handler.setLevel(logging.DEBUG)
app.logger.addHandler(console_handler)
File Handler
Saves logs to a file:
file_handler = logging.FileHandler('app.log')
file_handler.setLevel(logging.WARNING)
file_handler.setFormatter(formatter)
app.logger.addHandler(file_handler)
Rotating File Handler
Automatically rotates files when a certain size is reached:
from logging.handlers import RotatingFileHandler
rotating_handler = RotatingFileHandler(
'app.log',
maxBytes=1024*1024, # 1MB
backupCount=5
)
app.logger.addHandler(rotating_handler)
Timed Rotating File Handler
Rotate based on time (daily, weekly, etc.):
from logging.handlers import TimedRotatingFileHandler
time_handler = TimedRotatingFileHandler(
'app.log',
when='midnight', # Rotate every midnight
interval=1,
backupCount=30
)
app.logger.addHandler(time_handler)
Database Handler (Custom)
To store logs in a database:
import sqlite3
class DatabaseHandler(logging.Handler):
def emit(self, record):
conn = sqlite3.connect('logs.db')
cursor = conn.cursor()
cursor.execute(
'INSERT INTO logs (level, message, timestamp) VALUES (?, ?, ?)',
(record.levelname, record.getMessage(), record.created)
)
conn.commit()
conn.close()
db_handler = DatabaseHandler()
app.logger.addHandler(db_handler)
Email Handler (SMTPHandler)
Send error logs via email:
import logging.handlers
email_handler = logging.handlers.SMTPHandler(
mailhost=('smtp.gmail.com', 587),
fromaddr='[email protected]',
toaddrs=['[email protected]'],
subject='Application Error',
credentials=('username', 'password'),
secure=()
)
email_handler.setLevel(logging.ERROR)
app.logger.addHandler(email_handler)
Tips for Managing Logs
1. Structured Log Messages
Create consistent and informative log messages:
# Bad
app.logger.info('User login')
# Good
app.logger.info(f'User {user_id} logged in from IP {request.remote_addr}')
2. Context Information
Include relevant context:
@app.before_request
def log_request_info():
app.logger.info(f'Request: {request.method} {request.url} - User Agent: {request.headers.get("User-Agent")}')
@app.after_request
def log_response_info(response):
app.logger.info(f'Response: {response.status_code} - Size: {len(response.get_data())} bytes')
return response
3. Log Rotation
Implement log rotation to prevent log files from growing too large:
from logging.handlers import RotatingFileHandler
handler = RotatingFileHandler(
'app.log',
maxBytes=10*1024*1024, # 10MB
backupCount=10
)
4. Different Log Levels for Different Environments
import os
if os.environ.get('FLASK_ENV') == 'development':
app.logger.setLevel(logging.DEBUG)
else:
app.logger.setLevel(logging.WARNING)
5. Structured Logging
Use structured logging for easily parseable logs:
import json
class StructuredFormatter(logging.Formatter):
def format(self, record):
log_entry = {
'timestamp': self.formatTime(record),
'level': record.levelname,
'message': record.getMessage(),
'module': record.module,
'function': record.funcName,
'line': record.lineno
}
return json.dumps(log_entry)
# Setup structured logging
structured_handler = logging.FileHandler('structured.log')
structured_handler.setFormatter(StructuredFormatter())
app.logger.addHandler(structured_handler)
Alternative Libraries
Besides Python’s built-in logging, there are several alternative libraries that can enhance your logging capabilities:
Rich
A library for beautiful terminal output with colors and formatting:
from rich.logging import RichHandler
import logging
logging.basicConfig(
level=logging.INFO,
format="%(message)s",
handlers=[RichHandler(rich_tracebacks=True)]
)
app.logger.info("This will be displayed with colors!")
Rich provides syntax highlighting, progress bars, and table formatting for logs.
Loguru
A simplified logging library with a more user-friendly API:
from loguru import logger
# Replace default logger
logger.remove()
logger.add("app.log", rotation="1 day", retention="30 days")
logger.add(lambda msg: print(msg, end=""), colorize=True)
# In Flask
@app.route('/')
def index():
logger.info("Home page accessed")
return "Hello"
Loguru provides automatic rotation, compression, and powerful filtering.
Sentry
A monitoring platform for error tracking and performance monitoring:
import sentry_sdk
from sentry_sdk.integrations.flask import FlaskIntegration
sentry_sdk.init(
dsn="your_sentry_dsn",
integrations=[FlaskIntegration()],
traces_sample_rate=1.0
)
# Now all errors are automatically sent to Sentry
@app.route('/error')
def error():
1/0 # This will be captured by Sentry
Sentry provides dashboards for monitoring errors, performance issues, and user feedback.
ELK Stack (Elasticsearch, Logstash, Kibana)
For large-scale logging and analytics:
import logging
from pythonjsonlogger import jsonlogger
# Setup JSON logging for Logstash
handler = logging.StreamHandler()
formatter = jsonlogger.JsonFormatter(
'%(asctime)s %(name)s %(levelname)s %(message)s'
)
handler.setFormatter(formatter)
app.logger.addHandler(handler)
ELK stack enables centralized logging, search, and visualization.
Graylog
An open-source alternative for log management:
import logging
from graypy import GELFUDPHandler
handler = GELFUDPHandler('localhost', 12201)
app.logger.addHandler(handler)
Graylog provides a web interface for searching and analyzing logs.
Best Practices
✅ Best Practices for Logging in Flask:
-
Don’t Log Sensitive Information: Avoid logging passwords, API keys, or PII (Personally Identifiable Information).
-
Use Appropriate Log Levels: DEBUG for development, INFO for normal operations, WARNING for potential issues, ERROR for failures.
-
Consistent Formatting: Use consistent formatting across your application.
-
Log Rotation: Implement rotation to prevent disk space issues.
-
Structured Logging: Use JSON format for logs that will be processed by other tools.
-
Performance Consideration: Logging can slow down your application if too verbose. Use async logging if needed.
-
Centralized Logging: For multiple instances, use centralized log aggregation.
-
Monitoring Alerts: Set up alerts for critical errors or unusual patterns.
-
Log Retention Policy: Determine how long to keep logs based on compliance and storage constraints.
-
Testing Logging: Ensure logging configuration is tested in all environments.
Troubleshooting
Logs Not Appearing
Problem: Log messages not showing up.
Solutions:
- Check log level: Ensure handler level >= logger level
- Verify handler attached:
print(app.logger.handlers) - Check format: Ensure formatter isn’t corrupted
File Permission Issues
Problem: Can’t write to log file.
Solutions:
- Check file permissions:
chmod 644 app.log - Verify directory permissions
- Use absolute path if relative path causes issues
Performance Issues
Problem: Logging slows down the application.
Solutions:
- Reduce log verbosity in production
- Use async logging:
logging.handlers.QueueHandler - Buffer logs:
logging.handlers.BufferingHandler
Log Rotation Not Working
Problem: Log files not rotating.
Solutions:
- Check file size vs maxBytes
- Verify backupCount setting
- Check disk space
FAQ
Q: Does logging affect application performance? A: Yes, but the impact can be minimized with proper configuration. Use appropriate levels and avoid logging in hot paths.
Q: How long should logs be kept? A: Depends on business needs and regulations. Usually 30-90 days for operational logs, longer for audit logs.
Q: Can logging go to multiple destinations at once? A: Yes, you can attach multiple handlers to one logger.
Q: What’s the difference between logging and print statements? A: Logging is more powerful with levels, formatting, and handlers. Print statements only output to stdout.
Q: How to test logging configuration? A: Create unit tests that check if log messages are generated correctly in various scenarios.
Resources
- Flask Logging Documentation
- Python Logging Documentation
- Loguru Documentation
- Rich Documentation
- Sentry Documentation
Related Articles:
- Node.js Best Practices — Master Backend Development (though Node.js, similar concepts)
- API Development Best Practices — Building Secure & Scalable APIs
- Database Design Fundamentals — Building Efficient Databases
- Testing Strategies for Web Apps — Ensure Code Quality
Already implemented logging in your Flask app? Share your tips and tricks in the comments! 💬