Czym jest monitorowanie aplikacji?
Monitorowanie to proces zbierania i analizowania danych o działaniu aplikacji. Obejmuje:
- logowanie błędów i wyjątków — rejestrowanie wszystkich nieoczekiwanych sytuacji,
- śledzenie metryk wydajności — CPU, RAM, czas odpowiedzi, liczba requestów,
- alertowanie w czasie rzeczywistym — automatyczne powiadomienia o problemach,
- analizę trendów — długoterminowe obserwowanie zmian w zachowaniu aplikacji.
Celem monitoringu nie jest „mieć dashboard", tylko szybko wykrywać i diagnozować problemy, zanim zauważy je użytkownik. Dobrze skonfigurowany system monitorowania pozwala na proaktywne reagowanie na problemy, zamiast czekania na zgłoszenia użytkowników.
Logowanie błędów w Pythonie
Python ma wbudowany moduł logging, który wystarcza do większości przypadków — o ile jest dobrze skonfigurowany. Moduł logging oferuje elastyczny system poziomów logowania (DEBUG, INFO, WARNING, ERROR, CRITICAL) i różne handlery do zapisu logów.
Przykład konfiguracji logowania
Python1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17import logging logging.basicConfig( level=logging.INFO, format="%(asctime)s [%(levelname)s] %(name)s: %(message)s", handlers=[ logging.FileHandler("app.log"), logging.StreamHandler() ] ) logger = logging.getLogger(__name__) try: result = 1 / 0 except Exception as e: logger.exception("Błąd w obliczeniach")
Funkcja logger.exception() automatycznie dodaje pełny stack trace do logu, co jest kluczowe przy debugowaniu. Dzięki logging.FileHandler logi są zapisywane do pliku, a StreamHandler wyświetla je w konsoli.
Zaawansowana konfiguracja logowania
Dla bardziej zaawansowanych zastosowań możesz użyć konfiguracji słownikowej:
Python1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35import logging.config LOGGING_CONFIG = { 'version': 1, 'disable_existing_loggers': False, 'formatters': { 'standard': { 'format': '%(asctime)s [%(levelname)s] %(name)s: %(message)s' }, 'detailed': { 'format': '%(asctime)s [%(levelname)s] %(name)s [%(pathname)s:%(lineno)d]: %(message)s' }, }, 'handlers': { 'file': { 'class': 'logging.handlers.RotatingFileHandler', 'filename': 'app.log', 'maxBytes': 10485760,# 10MB 'backupCount': 5, 'formatter': 'detailed', }, 'console': { 'class': 'logging.StreamHandler', 'formatter': 'standard', }, }, 'loggers': { '': {# root logger 'handlers': ['file', 'console'], 'level': 'INFO', }, }, } logging.config.dictConfig(LOGGING_CONFIG)
RotatingFileHandler automatycznie rotuje pliki logów, gdy osiągną maksymalny rozmiar, co zapobiega przepełnieniu dysku. To szczególnie ważne w aplikacjach produkcyjnych.
Logowanie w Django
Django ma wbudowany system logowania, który można skonfigurować w settings.py. Django automatycznie loguje błędy 500, requesty i inne zdarzenia.
Konfiguracja logowania w Django
Python1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40# settings.py LOGGING = { 'version': 1, 'disable_existing_loggers': False, 'formatters': { 'verbose': { 'format': '{levelname} {asctime} {module} {process:d} {thread:d} {message}', 'style': '{', }, 'simple': { 'format': '{levelname} {message}', 'style': '{', }, }, 'handlers': { 'file': { 'level': 'INFO', 'class': 'logging.handlers.RotatingFileHandler', 'filename': 'logs/django.log', 'maxBytes': 1024*1024*15,# 15MB 'backupCount': 10, 'formatter': 'verbose', }, 'console': { 'level': 'DEBUG', 'class': 'logging.StreamHandler', 'formatter': 'simple' }, }, 'loggers': { 'django': { 'handlers': ['file', 'console'], 'level': 'INFO', }, 'myapp': { 'handlers': ['file', 'console'], 'level': 'DEBUG', }, }, }
Użycie logowania w widokach Django
Python1 2 3 4 5 6 7 8 9 10 11 12 13 14import logging logger = logging.getLogger(__name__) def my_view(request): logger.info(f'User {request.user} accessed the view') try: # Logika biznesowa widoku result = some_operation() logger.debug(f'Operation result: {result}') return JsonResponse({'status': 'success'}) except Exception as e: logger.error(f'Error in my_view: {str(e)}', exc_info=True) return JsonResponse({'status': 'error'}, status=500)
Django automatycznie loguje błędy 500 do loggera django.request, więc nie musisz ręcznie logować każdego wyjątku w widoku. Wystarczy, że użyjesz middleware do logowania requestów.
Logowanie w FastAPI
FastAPI nie ma wbudowanego systemu logowania, ale możesz łatwo skonfigurować logowanie używając standardowego modułu logging Pythona.
Konfiguracja logowania w FastAPI
Python1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26import logging from fastapi import FastAPI # Konfiguracja logowania logging.basicConfig( level=logging.INFO, format="%(asctime)s - %(name)s - %(levelname)s - %(message)s", handlers=[ logging.FileHandler("app.log"), logging.StreamHandler() ] ) logger = logging.getLogger(__name__) app = FastAPI() @app.get("/items/{item_id}") async def read_item(item_id: int): logger.info(f"Requested item {item_id}") try: # Logika biznesowa endpointu return {"item_id": item_id} except Exception as e: logger.error(f"Error getting item {item_id}: {str(e)}", exc_info=True) raise
Middleware do logowania requestów
Możesz stworzyć middleware do automatycznego logowania wszystkich requestów:
Python1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17import time import logging from fastapi import Request logger = logging.getLogger(__name__) @app.middleware("http") async def log_requests(request: Request, call_next): start_time = time.time() response = await call_next(request) process_time = time.time() - start_time logger.info( f"{request.method} {request.url.path} - " f"Status: {response.status_code} - " f"Time: {process_time:.3f}s" ) return response
To automatycznie loguje wszystkie requesty z informacją o metodzie HTTP, ścieżce, statusie odpowiedzi i czasie przetwarzania.
Sentry – profesjonalny tracking błędów
Sentry to popularne narzędzie do trackingu błędów, które automatycznie zbiera informacje o wyjątkach, stack traces, kontekście wykonania i informacje o użytkowniku. Sentry oferuje darmowy plan dla małych projektów i płatne plany dla większych aplikacji.
Instalacja Sentry
Bash1pip install sentry-sdk
Konfiguracja Sentry w Django
Python1 2 3 4 5 6 7 8 9 10 11# settings.py import sentry_sdk from sentry_sdk.integrations.django import DjangoIntegration sentry_sdk.init( dsn="https://your-sentry-dsn@sentry.io/project-id", integrations=[DjangoIntegration()], traces_sample_rate=1.0, send_default_pii=True, environment="production", )
DjangoIntegration automatycznie przechwytuje wszystkie błędy Django. traces_sample_rate kontroluje, jaki procent requestów jest śledzony dla analizy wydajności.
Konfiguracja Sentry w FastAPI
Python1 2 3 4 5 6 7 8 9 10 11 12 13import sentry_sdk from sentry_sdk.integrations.fastapi import FastApiIntegration from sentry_sdk.integrations.starlette import StarletteIntegration sentry_sdk.init( dsn="https://your-sentry-dsn@sentry.io/project-id", integrations=[ FastApiIntegration(), StarletteIntegration(), ], traces_sample_rate=1.0, environment="production", )
Po skonfigurowaniu, Sentry automatycznie przechwytuje wszystkie nieobsłużone wyjątki. Możesz też ręcznie raportować błędy:
Python1 2 3 4 5 6 7 8 9 10 11import sentry_sdk try: risky_operation() except Exception as e: sentry_sdk.capture_exception(e) # lub z dodatkowym kontekstem with sentry_sdk.push_scope() as scope: scope.set_tag("user_id", user.id) scope.set_extra("operation_data", operation_data) sentry_sdk.capture_exception(e)
Metryki wydajności
Metryki to dane numeryczne o działaniu aplikacji — czas odpowiedzi, wykorzystanie CPU, liczba requestów, błędy itp. Popularne narzędzia do zbierania metryk to Prometheus i Grafana.
Prometheus – zbieranie metryk
Prometheus to system monitorowania i alertowania, który zbiera metryki przez HTTP endpoint. Możesz użyć biblioteki prometheus-client w Pythonie:
Bash1pip install prometheus-client
Python1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21from prometheus_client import Counter, Histogram, start_http_server # Licznik requestów request_count = Counter('http_requests_total', 'Total HTTP requests', ['method', 'endpoint']) # Histogram czasu odpowiedzi request_duration = Histogram('http_request_duration_seconds', 'HTTP request duration') @app.middleware("http") async def track_metrics(request: Request, call_next): start_time = time.time() response = await call_next(request) duration = time.time() - start_time request_count.labels(method=request.method, endpoint=request.url.path).inc() request_duration.observe(duration) return response # Uruchom serwer metryk na porcie 8001 start_http_server(8001)
Prometheus będzie zbierać metryki z endpointu http://localhost:8001/metrics. Następnie możesz wizualizować je w Grafanie.
Integracja z Grafana
Grafana to narzędzie do wizualizacji metryk z Prometheusa. Tworzysz dashboardy z wykresami, które pokazują trendy wydajności, wykorzystanie zasobów i inne kluczowe metryki. Dzięki Grafanie możesz szybko zidentyfikować problemy i trendy w działaniu aplikacji.
Alerty i powiadomienia
Alerty to automatyczne powiadomienia o krytycznych problemach — wysokim współczynniku błędów, spowolnieniu aplikacji, braku dostępności itp. Możesz skonfigurować alerty w Sentry, Prometheus/Grafanie lub innych narzędziach monitorowania.
Alerty w Sentry
W Sentry możesz skonfigurować alerty, które wyzwalają się, gdy:
- występuje określona liczba błędów w czasie,
- pojawia się nowy typ błędu,
- błąd wpływa na wielu użytkowników.
Alerty mogą być wysyłane przez e-mail, Slack, PagerDuty lub inne kanały komunikacji.
Alerty w Prometheus/Grafanie
Prometheus pozwala na definiowanie reguł alertów (Alertmanager), które wyzwalają się na podstawie zapytań PromQL:
YAML1 2 3 4 5 6 7 8 9groups: - name: application_alerts rules: - alert: HighErrorRate expr: rate(http_requests_total{status=~"5.."}[5m]) > 0.05 for: 5m annotations: summary: "High error rate detected" description: "Error rate is above 5% for 5 minutes"
Grafana również oferuje alerty, które mogą powiadamiać Cię o przekroczeniu progów metryk bezpośrednio z dashboardów.
Dobre praktyki monitorowania
Przy implementowaniu monitorowania warto pamiętać o kilku kluczowych zasadach:
-
Loguj kontekst, nie tylko błędy — dodawaj informacje o użytkowniku, request ID, parametry funkcji. To ułatwia debugowanie.
-
Używaj odpowiednich poziomów logowania — DEBUG dla szczegółów deweloperskich, INFO dla normalnych operacji, WARNING dla potencjalnych problemów, ERROR dla błędów wymagających uwagi.
-
Strukturyzuj logi — używaj JSON formatów dla łatwiejszej analizy (np.
structlogw Pythonie):
Python1 2 3 4import structlog logger = structlog.get_logger() logger.info("user_login", user_id=123, ip="192.168.1.1")
-
Nie loguj wrażliwych danych — hasła, tokeny, numery kart kredytowych nigdy nie powinny trafiać do logów.
-
Rotuj logi — używaj
RotatingFileHandlerlub podobnych, aby uniknąć przepełnienia dysku. -
Monitoruj same logi — śledź liczbę błędów, rozmiar plików logów, tempo rotacji.
-
Korzystaj z agregacji — narzędzia takie jak ELK Stack (Elasticsearch, Logstash, Kibana) lub Loki pozwalają na centralizację i analizę logów z wielu źródeł.
-
Ustaw odpowiednie progi alertów — zbyt czułe alerty prowadzą do zmęczenia alertami, zbyt mało czułe — do przegapienia problemów.
Podsumowanie
Monitorowanie i logowanie błędów to niezbędne elementy utrzymania profesjonalnej aplikacji webowej. Właściwie skonfigurowany system monitorowania pozwala na szybkie wykrywanie i diagnozowanie problemów, zanim wpłyną one na doświadczenia użytkowników. Połączenie logowania w Pythonie, Sentry do trackingu błędów oraz Prometheus/Grafany do metryk wydajności daje pełny obraz działania aplikacji.
Zacznij od podstawowego logowania w Pythonie, dodaj Sentry do trackingu błędów, a następnie rozbuduj system o metryki i alerty w miarę potrzeb projektu. Pamiętaj, że monitorowanie to inwestycja w stabilność i niezawodność aplikacji — im lepiej monitorujesz, tym szybciej możesz reagować na problemy.



