Как подсчитать количество входящих HTTP-запросов в веб-приложении на Python

«Как подсчитать количество входящих HTTP-запросов в веб-приложении на Python» — вопрос из категории Devops, который задают на 10% собеседований Python Разработчик. Ниже — развёрнутый ответ с разбором ключевых моментов.

Ответ

Подсчет HTTP-запросов — базовая задача мониторинга. Подход кардинально отличается для локальной отладки и production-окружения.

1. Для отладки: Middleware

В рамках веб-фреймворка можно создать промежуточное ПО (middleware), которое будет перехватывать каждый запрос и инкрементировать счетчик. Этот метод подходит для простых сценариев и демонстраций, но не для production, так как счетчик в памяти не является потокобезопасным и сбрасывается при перезапуске процесса.

Пример для Django в middleware.py:

from django.db import connection

class RequestCounterMiddleware:
    def __init__(self, get_response):
        self.get_response = get_response
        self.request_count = 0

    def __call__(self, request):
        self.request_count += 1
        print(f"Обработан запрос №{self.request_count}")
        response = self.get_response(request)
        return response

2. Для Production: Система мониторинга (Prometheus)

В production-системах для сбора метрик используется стандартный индустриальный подход — система мониторинга Prometheus.

Принцип работы:

  1. Приложение с помощью клиентской библиотеки (например, prometheus-client) предоставляет специальный эндпоинт (/metrics), на котором публикует свои метрики в текстовом формате.
  2. Сервер Prometheus периодически опрашивает этот эндпоинт и сохраняет значения метрик в свою базу данных временных рядов.
  3. Данные визуализируются с помощью Grafana или используются для настройки алертов.

Пример для Flask с prometheus-flask-exporter:

# pip install prometheus-flask-exporter
from flask import Flask
from prometheus_flask_exporter import PrometheusMetrics

app = Flask(__name__)
metrics = PrometheusMetrics(app) # Автоматически добавляет /metrics

@app.route('/')
def home():
    return "Hello, World!"

# При обращении к '/' счетчик http_requests_total будет увеличен

Этот подход является масштабируемым, надежным и позволяет собирать не только количество запросов, но и их длительность, статусы ответов и другие важные метрики.