Help me bij het implementeren van een aangepast logging-framework voor mijn Flask-toepassing
description
Door deze prompt te volgen, kunnen gebruikers een efficiënter en aanpasbaar logging-framework maken, waardoor de observeerbaarheid en foutopsporing van hun toepassing wordt verbeterd.
prompt
try_prompt
Help me een aangepast logging-framework te maken in mijn Flask-toepassing om de loggingmogelijkheden van mijn toepassing te verbeteren. Mijn huidige loggingstrategie is: {{huidige_loggingstrategie}}. Leg uit hoe ik aange ... more
generate_helper
...
ai_answers
provider: openai
model: gpt-4.1-nano
Natuurlijk! Hier is een uitgebreide uitleg over het verbeteren van je logging in een Flask-toepassing door aangepaste logniveaus te definiëren, berichten te formatteren en integratie met externe diensten zoals Logstash of ELK-stack.
1. Aangepaste logniveaus definiëren
-------------------------------------
- **Gebruik van standaard niveaus:** Python’s `logging` module biedt standaard niveaus zoals DEBUG, INFO, WARNING, ERROR, CRITICAL.
- **Aangepaste niveaus toevoegen:**
Je kunt eigen niveaus definiëren door `logging.addLevelName()` te gebruiken of door een subclass van `logging.Level` te maken.
Bijvoorbeeld:
```python
import logging
CUSTOM_LEVEL_NUM = 25
logging.addLevelName(CUSTOM_LEVEL_NUM, "NOTICE")
def notice(self, message, *args, **kwargs):
if self.isEnabledFor(CUSTOM_LEVEL_NUM):
self._log(CUSTOM_LEVEL_NUM, message, args, **kwargs)
logging.Logger.notice = notice
```
Hiermee voeg je een 'NOTICE' niveau toe tussen WARNING en INFO.
2. Logberichten formatteren
---------------------------
- **Gebruik van formatters:**
Definieer een formatter die de structuur van je logberichten bepaalt, bijvoorbeeld:
```python
formatter = logging.Formatter(
'%(asctime)s - %(name)s - %(levelname)s - %(message)s'
)
```
- **Handlers instellen:**
Koppel de formatter aan handlers (bijv. console, bestand, netwerk):
```python
console_handler = logging.StreamHandler()
console_handler.setFormatter(formatter)
logger = logging.getLogger(__name__)
logger.addHandler(console_handler)
logger.setLevel(logging.DEBUG)
```
3. Integratie met externe loggingdiensten (Logstash, ELK-stack)
--------------------------------------------------------------
- **Gebruik van netwerkhandlers:**
Logstash kan logs ontvangen via TCP/UDP of via HTTP. Gebruik hiervoor bijvoorbeeld `logging.handlers.SocketHandler` of `logging.handlers.HTTPHandler`.
```python
import logging
import logging.handlers
socket_handler = logging.handlers.SocketHandler('logstash_host', logstash_port)
logger.addHandler(socket_handler)
```
- **Logstash JSON output:**
Voor betere parsing in ELK, formatteer logs als JSON:
```python
import json
class JsonFormatter(logging.Formatter):
def format(self, record):
log_record = {
'time': self.formatTime(record, self.datefmt),
'name': record.name,
'level': record.levelname,
'message': record.getMessage(),
'module': record.module,
'line': record.lineno,
}
return json.dumps(log_record)
json_formatter = JsonFormatter()
json_handler = logging.StreamHandler()
json_handler.setFormatter(json_formatter)
logger.addHandler(json_handler)
```
4. Best practices voor efficiënt logbeheer en monitoring
--------------------------------------------------------
- **Log niveaus correct gebruiken:**
Gebruik verschillende niveaus passend bij het belang van de boodschap.
- **Structuur en consistentie:**
Log gestructureerde gegevens (bijvoorbeeld JSON) voor eenvoudige filtering en analyse.
- **Log rotatie en archivering:**
Beperk de grootte van logbestanden met `RotatingFileHandler` of `TimedRotatingFileHandler`.
- **Centraliseer logging:**
Verzamel logs op één plek via Logstash of een andere logmanager.
- **Filter en alerting:**
Stel dashboards en alerts in ELK-stack in voor kritieke gebeurtenissen.
- **Veiligheid en privacy:**
Vermijd het loggen van gevoelige informatie.
- **Performance:**
Asynchrone logging of buffering vermindert de impact op de applicatieprestaties.
Door deze aanpak toe te passen, verbeter je de controle, zichtbaarheid en analyse van je Flask-applicatie logs, wat de monitoring en probleemoplossing aanzienlijk versnelt.
provider: deepseek
model: deepseek-chat
Zeker! Hier is een uitgebreide handleiding voor het verbeteren van je logging in Flask met aangepaste logniveaus, formattering en integratie met externe diensten zoals de ELK-stack.
### 1. Basis Flask Logging Opzetten
Flask gebruikt standaard Python's `logging` module. Begin met een basisconfiguratie in je hoofdbestand (bijv. `app.py`):
```python
import logging
from flask import Flask
app = Flask(__name__)
# Basis logging configuratie
logging.basicConfig(level=logging.INFO)
logger = logging.getLogger(__name__)
@app.route('/')
def home():
app.logger.info('Homepagina bezocht')
return "Welkom!"
```
### 2. Aangepaste Logniveaus Toevoegen
Je kunt custom logniveaus definiëren door bestaande niveaus te gebruiken of nieuwe te creëren:
```python
# Custom logniveau definiëren (bijv. voor audit-doeleinden)
AUDIT_LEVEL_NUM = 25
logging.addLevelName(AUDIT_LEVEL_NUM, "AUDIT")
def audit(self, message, *args, **kwargs):
if self.isEnabledFor(AUDIT_LEVEL_NUM):
self._log(AUDIT_LEVEL_NUM, message, args, **kwargs)
logging.Logger.audit = audit
# Gebruik in je code
logger.audit("Gebruiker login succesvol")
```
### 3. Geavanceerde Log Formattering
Maak een custom formatter voor gestructureerde logs (JSON aanbevolen):
```python
import json
import logging
class JSONFormatter(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,
"logger_name": record.name
}
# Voeg extra velden toe als ze bestaan
if hasattr(record, 'user_id'):
log_entry['user_id'] = record.user_id
if hasattr(record, 'request_id'):
log_entry['request_id'] = record.request_id
return json.dumps(log_entry)
# Formatter toepassen
json_formatter = JSONFormatter()
handler = logging.StreamHandler()
handler.setFormatter(json_formatter)
logger = logging.getLogger()
logger.addHandler(handler)
logger.setLevel(logging.INFO)
```
### 4. Contextrijke Logging
Voeg contextinformatie toe aan je logs:
```python
from flask import g, request
import uuid
@app.before_request
def before_request():
g.request_id = str(uuid.uuid4())
def log_with_context(message, level=logging.INFO, **extra_fields):
extra = {'request_id': g.get('request_id', 'unknown')}
extra.update(extra_fields)
logger.log(level, message, extra=extra)
# Gebruik:
log_with_context("Betaling verwerkt", user_id=123, amount=50.00)
```
### 5. Externe Logging Diensten Integreren
#### **Logstash Integratie:**
```python
import logging
import logstash
# Logstash handler toevoegen
logstash_handler = logstash.TCPLogstashHandler('localhost', 5000, version=1)
logger.addHandler(logstash_handler)
# Of gebruik HTTP:
# logstash_handler = logstash.HTTPLogstashHandler('localhost', 8080)
```
#### **ELK Stack Configuratie:**
1. **Elasticsearch + Kibana + Logstash opzetten** (Docker aanbevolen)
2. **Logstash configuratie** (`logstash.conf`):
```input {
tcp {
port => 5000
codec => json
}
}
output {
elasticsearch {
hosts => ["elasticsearch:9200"]
index => "flask-logs-%{+YYYY.MM.dd}"
}
}
```
3. **Direct naar Elasticsearch** (alternatief):
```python
from elasticsearch import Elasticsearch
from elasticsearch_logging_handler import ElasticsearchHandler
es_handler = ElasticsearchHandler(
Elasticsearch(['localhost:9200']),
index_name="flask-logs"
)
logger.addHandler(es_handler)
```
### 6. Best Practices voor Log Management
#### **Log Levels Strategie:**
- `DEBUG`: Ontwikkeling en troubleshooting
- `INFO`: Normale applicatiegedrag
- `WARNING`: Onverwachte maar afhandelbare situaties
- `ERROR**: Fouten die aandacht vereisen
- `CRITICAL`: Kritieke systeemfouten
#### **Log Structuur Regels:**
- Gebruik consistent JSON-formaat
- Includeer altijd timestamp en correlation IDs
- Log gebeurtenissen, niet alleen fouten
- Vermijd gevoelige informatie (wachtwoorden, tokens)
#### **Performance Optimalisatie:**
```python
# Gebruik lazy evaluation voor dure operaties
logger.debug("User data: %s", expensive_serialization(user))
# Asynchrone logging overwegen
from concurrent.futures import ThreadPoolExecutor
class AsyncLogHandler(logging.Handler):
def __init__(self):
super().__init__()
self.executor = ThreadPoolExecutor(max_workers=1)
def emit(self, record):
self.executor.submit(super().emit, record)
```
#### **Configuratie Management:**
```python
# logging_config.py
import os
import logging.config
LOGGING_CONFIG = {
'version': 1,
'disable_existing_loggers': False,
'formatters': {
'json': {
'()': JSONFormatter,
},
'detailed': {
'format': '%(asctime)s %(name)-15s %(levelname)-8s %(message)s'
}
},
'handlers': {
'file': {
'class': 'logging.handlers.RotatingFileHandler',
'formatter': 'json',
'filename': '/var/log/flask-app.log',
'maxBytes': 10485760, # 10MB
'backupCount': 5
},
'logstash': {
'class': 'logstash.TCPLogstashHandler',
'host': os.getenv('LOGSTASH_HOST', 'localhost'),
'port': int(os.getenv('LOGSTASH_PORT', 5000)),
'version': 1
}
},
'root': {
'level': 'INFO',
'handlers': ['file', 'logstash']
}
}
# In je app.py:
logging.config.dictConfig(LOGGING_CONFIG)
```
### 7. Monitoring en Alerting
- **Gebruik Metric Collectors**: Prometheus + Grafana
- **Stel alerts in** voor ERROR/CIRTICAL logs
- **Implementeer health checks**:
```python
@app.route('/health')
def health_check():
try:
# Database check
# Externe service checks
logger.info("Health check passed")
return "OK", 200
except Exception as e:
logger.error("Health check failed: %s", str(e))
return "FAIL", 500
```
### 8. Security Overwegingen
- **Sanitize logs**: verwijder PII (Persoonlijk Identificeerbare Informatie)
- **Use log rotation** om disk space te managen
- **Encrypt logs** in transit en at rest
- **Implementeer access controls** voor logbestanden
### Volledig Voorbeeld:
```python
# app.py
import logging
import logging.config
from flask import Flask, g, request
import uuid
from logging_config import LOGGING_CONFIG
logging.config.dictConfig(LOGGING_CONFIG)
logger = logging.getLogger(__name__)
app = Flask(__name__)
@app.before_request
def assign_request_id():
g.request_id = request.headers.get('X-Request-ID', str(uuid.uuid4()))
@app.route('/api/payment', methods=['POST'])
def process_payment():
try:
logger.info("Payment processing started",
extra={'user_id': 123, 'amount': 50.00})
# Verwerk betaling...
logger.audit("Payment completed successfully",
extra={'user_id': 123, 'amount': 50.00})
return {"status": "success"}, 200
except Exception as e:
logger.error("Payment processing failed",
extra={'user_id': 123, 'error': str(e)})
return {"status": "error"}, 500
if __name__ == '__main__':
app.run(debug=False)
```
Deze aanpak geeft je een robuust, schaalbaar logging-systeem dat perfect integreert met moderne monitoringtools en best practices volgt voor onderhoudbaarheid en security.

