Help me een Python-script te ontwerpen dat een aangepast logsysteem implementeert voor mijn toepassingen
description
Door het implementeren van een aangepast logsysteem krijg je beter inzicht in de prestaties en problemen van je toepassing, waardoor het gemakkelijker wordt om je code te onderhouden en te debuggen. Een goed gestructureerde logging-aanpak kan ook helpen bij het volgen van gebruikersactiviteiten en het snel detecteren van fouten.
prompt
try_prompt
Ik wil een Python-script maken dat een aangepast logsysteem opzet voor mijn toepassingen. Het script moet me toestaan verschillende logniveaus te definiëren, logoutputformaten te configureren en logs op te slaan op opgegeven locaties. Geef voorbeel ... more
generate_helper
...
tags
ai_answers
provider: openai
model: gpt-4.1-nano
Hier is een overzichtelijk Python-script dat een flexibel en aanpasbaar logsysteem opzet volgens jouw wensen, inclusief voorbeelden voor verschillende modules, effectieve uitzonderingsafhandeling en best practices voor onderhoud van logbestanden.
```python
import logging
import os
from logging.handlers import RotatingFileHandler
# Configuratie van het logsysteem
def setup_logging(log_dir='logs', log_file='app.log', log_level=logging.INFO, log_format='%(asctime)s - %(name)s - %(levelname)s - %(message)s'):
# Zorg dat de log directory bestaat
os.makedirs(log_dir, exist_ok=True)
log_path = os.path.join(log_dir, log_file)
# RotatingFileHandler om schijfruimte te beheren
handler = RotatingFileHandler(log_path, maxBytes=10*1024*1024, backupCount=5) # 10MB per bestand, max 5 backups
formatter = logging.Formatter(log_format)
handler.setFormatter(formatter)
# Root logger configureren
logger = logging.getLogger()
logger.setLevel(log_level)
logger.addHandler(handler)
# Voorbeeld van verschillende modules
def module_a():
logger = logging.getLogger('module_a')
try:
# Voorbeeld van een succesvolle operatie
logger.info("Module A gestart.")
# Simuleer een fout
result = 10 / 0
except ZeroDivisionError as e:
logger.exception("Fout in module A: deling door nul.")
finally:
logger.info("Module A beëindigd.")
def module_b():
logger = logging.getLogger('module_b')
logger.debug("Module B draait op debug niveau.")
# Voorbeeld van een waarschuwing
logger.warning("Dit is een waarschuwing in module B.")
# Voorbeeld van de setup en gebruik
if __name__ == "__main__":
setup_logging(log_level=logging.DEBUG)
# Modules uitvoeren
module_a()
module_b()
```
**Uitleg en beste praktijken:**
- **Logniveaus definiëren:** Je kunt het logniveau aanpassen via `setup_logging()`, bijvoorbeeld `DEBUG`, `INFO`, `WARNING`, `ERROR`, `CRITICAL`. Dit helpt om de hoeveelheid informatie te beheren.
- **Configuratie van outputformaten:** Pas de `log_format` parameter aan in `setup_logging()` om te bepalen welke gegevens worden gelogd, zoals tijd, module, niveau en bericht.
- **Logs opslaan op opgegeven locaties:** Stel `log_dir` en `log_file` in om de locatie en naam van het logbestand te bepalen.
- **Gebruik van RotatingFileHandler:** Hiermee worden logbestanden automatisch geroteerd zodra ze een maximale grootte bereiken (`maxBytes`), en worden oude logs geback-upt (`backupCount`), wat schijfruimte bespaart en overmatige groei voorkomt.
- **Effectieve uitzonderingen afhandelen:** Gebruik `logger.exception()` binnen except-blokken om volledige tracebacks te loggen, wat heel handig is voor debugging.
- **Onderhoud van logbestanden:**
- Gebruik `RotatingFileHandler` voor automatische rotatie.
- Periodiek oude logbestanden verwijderen of archiveren.
- Overweeg loglevel te verlagen naar `WARNING` of `ERROR` in productie om logvolume te beperken.
- Automatiseren van logrotatie en schoonmaak via scripts of geautomatiseerde taken (bijvoorbeeld cronjobs).
Met deze aanpak heb je een krachtig, flexibel en onderhoudsvriendelijk logsysteem dat je helpt bij het monitoren en troubleshooten van je toepassingen.
provider: deepseek
model: deepseek-chat
Hier is een uitgebreide implementatie van een aangepast logsysteem in Python:
## Basis Logging Configuratie
```python
import logging
import logging.handlers
import os
from datetime import datetime
import gzip
import shutil
class CustomLogger:
def __init__(self, name, log_level='INFO', log_format=None, log_dir='logs'):
self.name = name
self.log_dir = log_dir
self.setup_logging(log_level, log_format)
def setup_logging(self, log_level, log_format):
# Maak log directory aan als deze niet bestaat
if not os.path.exists(self.log_dir):
os.makedirs(self.log_dir)
# Stel log niveau in
level = getattr(logging, log_level.upper(), logging.INFO)
# Aangepast log formaat
if log_format is None:
log_format = '%(asctime)s - %(name)s - %(levelname)s - %(message)s'
# Configureer de logger
self.logger = logging.getLogger(self.name)
self.logger.setLevel(level)
# Voorkom dubbele handlers
if self.logger.handlers:
self.logger.handlers.clear()
# Console handler
console_handler = logging.StreamHandler()
console_handler.setLevel(level)
console_formatter = logging.Formatter(log_format)
console_handler.setFormatter(console_formatter)
self.logger.addHandler(console_handler)
# File handler met rotatie
log_file = os.path.join(self.log_dir, f'{self.name}.log')
file_handler = logging.handlers.RotatingFileHandler(
log_file,
maxBytes=10*1024*1024, # 10MB
backupCount=5
)
file_handler.setLevel(level)
file_formatter = logging.Formatter(log_format)
file_handler.setFormatter(file_formatter)
self.logger.addHandler(file_handler)
```
## Gebruik in Verschillende Modules
```python
# database_module.py
class DatabaseManager:
def __init__(self):
self.logger = CustomLogger('Database', 'DEBUG').logger
def connect(self, connection_string):
try:
self.logger.info(f"Verbinden met database: {connection_string}")
# Simuleer database verbinding
if "invalid" in connection_string:
raise ValueError("Ongeldige connection string")
self.logger.debug("Database verbinding succesvol")
except Exception as e:
self.logger.error(f"Database verbinding mislukt: {str(e)}")
raise
# api_module.py
class APIManager:
def __init__(self):
self.logger = CustomLogger('API', 'INFO',
'%(asctime)s - %(levelname)s - API - %(message)s').logger
def make_request(self, url):
try:
self.logger.info(f"API request naar: {url}")
# Simuleer API request
response = {"status": "success", "data": "voorbeeld"}
self.logger.debug(f"API response: {response}")
return response
except Exception as e:
self.logger.critical(f"API request gefaald: {str(e)}")
return None
# main_application.py
class MainApplication:
def __init__(self):
self.logger = CustomLogger('MainApp', 'INFO').logger
self.db_manager = DatabaseManager()
self.api_manager = APIManager()
def run(self):
try:
self.logger.info("Applicatie gestart")
# Database operatie
self.db_manager.connect("server=database;user=admin")
# API operatie
result = self.api_manager.make_request("https://api.voorbeeld.com/data")
self.logger.info("Applicatie voltooid")
except Exception as e:
self.logger.exception(f"Onverwachte fout in applicatie: {str(e)}")
```
## Geavanceerde Uitzonderingsafhandeling
```python
import traceback
from functools import wraps
def log_exceptions(logger):
"""Decorator voor het loggen van exceptions"""
def decorator(func):
@wraps(func)
def wrapper(*args, **kwargs):
try:
return func(*args, **kwargs)
except Exception as e:
logger.error(f"Fout in {func.__name__}: {str(e)}")
logger.debug(f"Stack trace:\n{traceback.format_exc()}")
raise
return wrapper
return decorator
# Gebruik van de decorator
class DataProcessor:
def __init__(self):
self.logger = CustomLogger('DataProcessor', 'DEBUG').logger
@log_exceptions(logger=None) # Wordt later ingesteld
def process_data(self, data):
if not data:
raise ValueError("Geen data om te verwerken")
self.logger.info(f"Verwerken van {len(data)} items")
return [item * 2 for item in data]
# Initialiseer de decorator
data_processor = DataProcessor()
DataProcessor.process_data = log_exceptions(data_processor.logger)(DataProcessor.process_data)
```
## Beste Praktijken voor Logbeheer
```python
class LogManager:
def __init__(self, log_dir='logs', max_total_size_mb=100, compress_old_logs=True):
self.log_dir = log_dir
self.max_total_size = max_total_size_mb * 1024 * 1024 # Converteer naar bytes
self.compress_old_logs = compress_old_logs
def cleanup_old_logs(self):
"""Verwijder oude logs wanneer de totale grootte de limiet overschrijdt"""
try:
log_files = []
total_size = 0
# Verzamel alle log bestanden
for filename in os.listdir(self.log_dir):
if filename.endswith(('.log', '.log.gz')):
filepath = os.path.join(self.log_dir, filename)
size = os.path.getsize(filepath)
log_files.append((filepath, os.path.getctime(filepath), size))
total_size += size
# Sorteer op aanmaakdatum (oudste eerst)
log_files.sort(key=lambda x: x[1])
# Verwijder oudste bestanden tot onder de limiet
while total_size > self.max_total_size and log_files:
oldest_file, ctime, size = log_files.pop(0)
try:
os.remove(oldest_file)
total_size -= size
logging.getLogger('LogManager').info(f"Verwijderd: {oldest_file}")
except OSError as e:
logging.getLogger('LogManager').error(f"Kon {oldest_file} niet verwijderen: {e}")
except Exception as e:
logging.getLogger('LogManager').error(f"Fout bij opschonen logs: {e}")
def compress_old_log_files(self):
"""Comprimeer oude log bestanden"""
try:
for filename in os.listdir(self.log_dir):
if filename.endswith('.log') and not filename.endswith('.gz'):
filepath = os.path.join(self.log_dir, filename)
compressed_path = filepath + '.gz'
# Comprimeer alleen als het gecomprimeerde bestand niet bestaat
if not os.path.exists(compressed_path):
with open(filepath, 'rb') as f_in:
with gzip.open(compressed_path, 'wb') as f_out:
shutil.copyfileobj(f_in, f_out)
os.remove(filepath)
logging.getLogger('LogManager').info(f"Gecomprimeerd: {filename}")
except Exception as e:
logging.getLogger('LogManager').error(f"Fout bij comprimeren: {e}")
```
## Gebruiksvoorbeeld
```python
if __name__ == "__main__":
# Initialiseer log manager
log_manager = LogManager(max_total_size_mb=50)
# Test verschillende modules
app = MainApplication()
try:
app.run()
# Test uitzondering
data_processor = DataProcessor()
data_processor.process_data([]) # Zal een ValueError veroorzaken
except Exception:
pass # Exception is al gelogd
# Onderhoudstaken
log_manager.cleanup_old_logs()
log_manager.compress_old_logs()
```
## Aanvullende Beste Praktijken:
1. **Log Niveaus Strategie**:
- DEBUG: Gedetailleerde informatie voor ontwikkelaars
- INFO: Algemene applicatie flow
- WARNING: Onverwachte gebeurtenissen die geen fout zijn
- ERROR: Serieuze problemen
- CRITICAL: Fatale fouten
2. **Log Rotatie**:
- Gebruik `RotatingFileHandler` voor grootte-based rotatie
- Gebruik `TimedRotatingFileHandler` voor tijd-based rotatie
3. **Performantie**:
- Vermijd string formatting in log statements tot nodig
- Gebruik `isEnabledFor()` voor dure operaties
4. **Beveiliging**:
- Log nooit gevoelige informatie (wachtwoorden, tokens)
- Beperk log toegangsrechten
Dit systeem biedt een robuuste logging oplossing met goede uitzonderingsafhandeling en automatisch onderhoud van logbestanden.

