slogan3

Flask API Logging en Tracing voor Geavanceerde Foutopsporing

description

Met deze prompt kan de gebruiker een krachtig logging- en tracingframework opzetten dat diepgaande inzicht geeft in API-activiteiten en fouten. Dit helpt bij het snel identificeren en oplossen van problemen, verbetert de monitoring en maakt prestatieoptimalisaties mogelijk. Het is effectiever dan standaard logging doordat het ook gedistribueerde tracing omvat, wat cruciaal is in moderne microservices-architecturen.

prompt

Help me bij het implementeren van een uitgebreid logging- en tracing-systeem in mijn Flask API. Mijn huidige logging setup is: <beschrijf je huidige logging configuratie>. Leg uit hoe ik gedetailleerde logs kan vastleggen, inclusief ...

try_prompt

generate_helper
disclaimerOnPageApi

ai_answers

provider: openai
model: gpt-4.1-nano
Natuurlijk! Hier is een uitgebreide gids voor het verbeteren van je logging- en tracing-systeem in je Flask API: 1. Verbeteren van je bestaande logging setup a. Configuratie van gedetailleerde logging - Stel het logging niveau in op DEBUG of INFO afhankelijk van je behoefte: import logging logging.basicConfig(level=logging.DEBUG, format='%(asctime)s - %(name)s - %(levelname)s - %(message)s') - Gebruik loggers per module: logger = logging.getLogger(__name__) b. Log request- en responsegegevens - Gebruik Flask’s `before_request` en `after_request` hooks: from flask import Flask, request, g app = Flask(__name__) @app.before_request def log_request_info(): g.start_time = datetime.now() app.logger.info(f'Incoming request: {request.method} {request.url}') app.logger.debug(f'Headers: {dict(request.headers)}') if request.is_json: app.logger.debug(f'Request JSON: {request.get_json()}') @app.after_request def log_response_info(response): duration = (datetime.now() - g.start_time).total_seconds() app.logger.info(f'Response status: {response.status}') app.logger.info(f'Request processed in {duration} seconden') # Log response data indien nodig return response c. Log foutmeldingen - Gebruik exception handlers: import traceback @app.errorhandler(Exception) def handle_exception(e): app.logger.error(f'Fout opgetreden: {str(e)}') app.logger.debug(traceback.format_exc()) return {"error": "Server error"}, 500 2. Structureren van logs voor betere analyse - Gebruik gestructureerde logging met JSON-formaat: import json import logging from pythonjsonlogger import jsonlogger logger = logging.getLogger() logHandler = logging.StreamHandler() formatter = jsonlogger.JsonFormatter( '%(asctime)s %(name)s %(levelname)s %(message)s %(request_id)s %(trace_id)s' ) logHandler.setFormatter(formatter) logger.addHandler(logHandler) logger.setLevel(logging.INFO) - Voeg contextuele data toe via log filters of gebruik van contextvars: van Python 3.7+: import contextvars request_id = contextvars.ContextVar('request_id') @app.before_request def set_request_id(): request_id.set(str(uuid.uuid4())) # Voeg request_id toe aan logs via filter of formatter 3. Integratie met tracing tools (OpenTelemetry, Jaeger) a. OpenTelemetry integratie - Installeer benodigde packages: pip install opentelemetry-api opentelemetry-sdk opentelemetry-instrumentation-flask opentelemetry-exporter-jaeger - Configureer OpenTelemetry: from opentelemetry import trace from opentelemetry.sdk.resources import SERVICE_NAME, Resource from opentelemetry.sdk.trace import TracerProvider from opentelemetry.sdk.trace.export import BatchSpanProcessor from opentelemetry.exporter.jaeger.thrift import JaegerExporter from opentelemetry.instrumentation.flask import FlaskInstrumentor trace.set_tracer_provider( TracerProvider( resource=Resource.create({SERVICE_NAME: "mijn-flask-api"}) ) ) jaeger_exporter = JaegerExporter( agent_host_name='localhost', agent_port=6831, ) span_processor = BatchSpanProcessor(jaeger_exporter) trace.get_tracer_provider().add_span_processor(span_processor) app = Flask(__name__) FlaskInstrumentor().instrument_app(app) b. Logging trace-id en span-id in logs - Gebruik contextvars of OpenTelemetry hooks om tracegegevens in logberichten te embedden. 4. Best practices voor analyse en monitoring - Gebruik een log aggregator zoals ELK (Elasticsearch, Logstash, Kibana) of Graylog - Correlatie logs en traces door trace-id en span-id in logs op te nemen - Automatiseer alerting op basis van foutmeldingen of prestatieproblemen Kort samengevat: - Gebruik gestructureerde JSON-logs met contextuele data zoals request-id en trace-id. - Voeg gedetailleerde request-, response- en foutinformatie toe. - Integreer OpenTelemetry met Jaeger voor distributed tracing. - Correleer logs en traces voor betere inzichtelijkheid. Wil je dat ik een voorbeeldcode voor je opstel met alle bovengenoemde onderdelen?
provider: deepseek
model: deepseek-chat
Absoluut! Laten we stap voor stap je logging- en tracing-systeem naar een professioneel niveau tillen. Hier is een uitgebreide handleiding specifiek voor Flask. --- ### **Stap 1: Verbeter je Standaard Logging Setup** Je huidige console logging is een begin, maar we gaan het structureren, formatteren en naar bestanden schrijven. **1. Geavanceerde Logging Configuratie (`app.py` of `__init__.py`)** ```python import logging from logging.handlers import RotatingFileHandler, TimedRotatingFileHandler import os from pythonjsonlogger import jsonlogger # Installeer via: pip install python-json-logger def setup_logging(app): # Verwijder standaard handlers om dubbele logs te voorkomen for handler in list(app.logger.handlers): app.logger.removeHandler(handler) # Maak een log directory aan log_dir = 'logs' if not os.path.exists(log_dir): os.makedirs(log_dir) # 1. JSON Formatter voor gestructureerde logs (ideaal voor analyse) json_formatter = jsonlogger.JsonFormatter( '%(asctime)s %(levelname)s %(name)s %(message)s %(module)s %(funcName)s %(lineno)s' ) # 2. Gestructureerde Tekst Formatter (leesbaar voor mensen) detailed_formatter = logging.Formatter( '%(asctime)s - %(name)s - %(levelname)s - %(module)s:%(funcName)s:%(lineno)d - %(message)s' ) # Handlers # a) Console Handler (voor ontwikkeling) console_handler = logging.StreamHandler() console_handler.setLevel(logging.INFO) console_handler.setFormatter(detailed_formatter) # b) Roterend Bestand Handler voor ALLES (WARNING en hoger) file_handler_all = RotatingFileHandler( os.path.join(log_dir, 'app.log'), maxBytes=10*1024*1024, # 10 MB backupCount=5 ) file_handler_all.setLevel(logging.WARNING) file_handler_all.setFormatter(json_formatter) # Gebruik JSON voor bestanden # c) Roterend Bestand Handler voor FOUTEN (ERROR en CRITICAL) file_handler_errors = RotatingFileHandler( os.path.join(log_dir, 'errors.log'), maxBytes=5*1024*1024, # 5 MB backupCount=3 ) file_handler_errors.setLevel(logging.ERROR) file_handler_errors.setFormatter(json_formatter) # Voeg handlers toe aan de app logger app.logger.addHandler(console_handler) app.logger.addHandler(file_handler_all) app.logger.addHandler(file_handler_errors) # Stel het loglevel in voor de app logger zelf app.logger.setLevel(logging.INFO) # Onderdruk overmatige logging van dependencies (optioneel) logging.getLogger('werkzeug').setLevel(logging.WARNING) ``` **2. Logging in je Flask App Initialiseren** ```python from flask import Flask app = Flask(__name__) setup_logging(app) # Roep de setup functie aan @app.route('/') def home(): app.logger.info('Home endpoint was called') return "Hello, World!" if __name__ == '__main__': app.run(debug=True) ``` --- ### **Stap 2: Vastleggen van Request- en Responsegegevens** Hiervoor gebruiken we Flask's `before_request` en `after_request` hooks. ```python from flask import request, jsonify import time from datetime import datetime @app.before_request def log_request_info(): # Sla een timestamp op om de duur van het request te meten request.start_time = time.time() app.logger.info( 'Inkomend Request', extra={ 'http_method': request.method, 'url': request.url, 'user_agent': str(request.user_agent), 'remote_addr': request.remote_addr, 'headers': dict(request.headers) } ) @app.after_request def log_response_info(response): # Bereken de verstreken tijd duration = round((time.time() - request.start_time) * 1000, 2) # in milliseconden app.logger.info( 'Uitgaande Response', extra={ 'http_status': response.status_code, 'duration_ms': duration, # Prestatiegegevens! 'url': request.url, 'response_size': response.calculate_content_length(), 'timestamp': datetime.utcnow().isoformat() + 'Z' } ) return response # Voorbeeld van een foutlog @app.errorhandler(500) def internal_server_error(e): app.logger.error( 'Interne Serverfout', extra={ 'error': str(e), 'stack_trace': traceback.format_exc() # Importeer traceback }, exc_info=True # Voeg automatisch exception info toe ) return jsonify({'error': 'Internal Server Error'}), 500 ``` --- ### **Stap 3: Integratie met OpenTelemetry voor Gedistribueerde Tracing** OpenTelemetry is de standaard voor observability. Het koppelt logs, metrics en traces. **1. Installatie** ```bash pip install opentelemetry-api opentelemetry-sdk opentelemetry-instrumentation-flask opentelemetry-exporter-jaeger ``` **2. Basisconfiguratie in je App** ```python from opentelemetry import trace from opentelemetry.sdk.trace import TracerProvider from opentelemetry.sdk.trace.export import BatchSpanProcessor from opentelemetry.exporter.jaeger.thrift import JaegerExporter from opentelemetry.instrumentation.flask import FlaskInstrumentor from opentelemetry.sdk.resources import Resource def setup_tracing(app, service_name): # Stel een tracer provider in trace.set_tracer_provider( TracerProvider( resource=Resource.create({'service.name': service_name}) ) ) tracer = trace.get_tracer(__name__) # Configureer de Jaeger exporter jaeger_exporter = JaegerExporter( agent_host_name="localhost", # Pas aan naar je Jaeger host agent_port=6831, ) # Voeg een BatchSpanProcessor toe aan de tracer provider span_processor = BatchSpanProcessor(jaeger_exporter) trace.get_tracer_provider().add_span_processor(span_processor) # Instrumenteer je Flask app automatisch FlaskInstrumentor().instrument_app(app) return tracer # Initialiseer je app app = Flask(__name__) setup_logging(app) tracer = setup_tracing(app, "mijn-flask-api") # Gebruik de tracer in je endpoints @app.route('/api/data') def get_data(): with tracer.start_as_current_span("get_data_operation") as span: # Je bedrijfslogica hier span.set_attribute("http.method", "GET") span.set_attribute("custom.parameter", "some_value") app.logger.info("Verwerken van data request", extra={"span_id": span.get_span_context().span_id}) return jsonify({"data": "hier is je data"}) ``` --- ### **Stap 4: Logstructuur voor Betere Analyse & Monitoring** Gebruik consistent gestructureerde logs (JSON is ideaal). Hier is een voorbeeld van een logentry: ```json // Voorbeeld log entry in errors.log { "asctime": "2023-10-27 14:32:18,123", "levelname": "ERROR", "name": "flask.app", "message": "Interne Serverfout", "module": "app", "funcName": "internal_server_error", "lineno": 42, "error": "Division by zero", "stack_trace": "Traceback (most recent call last):\n File \"/app/app.py\", line 30, in dangerous_route\n result = 10 / 0\nZeroDivisionError: division by zero", "http_method": "GET", "url": "http://localhost:5000/api/broken", "remote_addr": "127.0.0.1", "trace_id": "abc123def456...", // Van OpenTelemetry "span_id": "789ghi012jkl..." // Van OpenTelemetry } ``` **Belangrijke velden om altijd op te nemen:** * `timestamp`: ISO 8601 timestamp. * `level`: log niveau (DEBUG, INFO, WARNING, ERROR, CRITICAL). * `service.name`: Naam van je service (consistent met OpenTelemetry). * `http_method`, `url`, `status_code`: Voor request context. * `duration_ms`: Prestatiemeting. * `trace_id` en `span_id**: **De heilige graal**. Dit koppelt je logs direct aan de specifieke trace in Jaeger/Zipkin, waardoor je de volledige reis van een request kunt volgen over meerdere services. --- ### **Samenvatting en Aanbevelingen** 1. **Logging Niveaus**: Gebruik `logger.debug()` voor gedetailleerde debug info, `logger.info()` voor normale operaties, `logger.warning()` voor waarschuwingen, en `logger.error()`/`logger.critical()` voor fouten. 2. **Centralisatie**: Gebruik tools zoals de **ELK Stack** (Elasticsearch, Logstash, Kibana), **Grafana Loki**, of cloudservices zoals **AWS CloudWatch** of **Google Cloud Logging** om je logs te centraliseren, doorzoeken en visualiseren. 3. **Tracing**: Draai **Jaeger** of **Zipkin** lokaal of in je cluster om de traces te visualiseren. OpenTelemetry exporteert daar naartoe. 4. **Performance**: Wees voorzichtig met het loggen van zeer grote request/response bodies in productie. Log enkel headers en metadata tenzij debuggen essentieel is. 5. **Gevoelige Data**: Filter gevoelige informatie (wachtwoorden, tokens, PII) *voordat* je logt. Schrijf een custom filter voor je logger. Door deze stappen te volgen, transformeer je je eenvoudige Flask API naar een goed observeerbare applicatie die klaar is voor productie en complexe, gedistribueerde architecturen.