Дешево и сердито: как организовать сбор логов с удалённых клиентов по HTTP
Опубликовано 12.11.2025
У вас есть приложение, разбросанное по сотням клиентских устройств? Или парк IoT-датчиков, которые отправляют телеметрию? Рано или поздно возникает вопрос: «А что там вообще происходит?» И сразу за ним — «Как собрать логи, не разорившись на Splunk или Datadog?»
Если ваши клиенты способны отправлять HTTP-запросы, то у вас уже есть девяносто процентов решения. HTTP(S) — это универсальный и дружелюбный к брандмауэрам протокол. Всё, что нам требуется — это «слушатель» (endpoint), который будет принимать эти логи.
В этой статье мы разберём три бюджетных способа организовать сбор логов по HTTP — от «быстро, просто, но работает» до «масштабируемо и почти бесплатно».
Почему именно HTTP
- Универсальность — HTTP-клиент есть в любом языке программирования и на любой платформе.
- Простота — формат POST-запроса с JSON-телом интуитивно понятен.
- Доступность — порт 443 (HTTPS) практически никогда не закрыт, в отличие от специфических портов для syslog или GELF.
Золотое правило: всегда используйте HTTPS. Бесплатные сертификаты Let’s Encrypt настраиваются за десять минут и защищают ваши данные от перехвата.
Вариант 1. Скрипт на VPS (быстро и очень дёшево)
Самый простой, «кустарный», но и самый быстрый в развёртывании способ. Подходит для пет-проектов или сбора логов с небольшого числа клиентов.
Что потребуется
- Недорогой VPS (Vultr, DigitalOcean, Hetzner и другие) стоимостью около пяти долларов в месяц.
- Стек: Nginx + любой бэкенд-скрипт (Python/Flask, Node.js/Express, PHP).
Как это работает
Арендуете виртуальный сервер.
Поднимаете Nginx как реверс-прокси и для терминирования SSL.
Пишете крошечное веб-приложение (двадцать строк кода), которое:
- принимает POST-запросы на
/log; - при необходимости проверяет секретный ключ в заголовке
X-API-Key; - записывает JSON-лог в файл.
- принимает POST-запросы на
Пример на Python (Flask)
from flask import Flask, request, abort
import os
import json
app = Flask(__name__)
API_KEY = os.environ.get("LOG_API_KEY", "super-secret-key")
@app.route('/log', methods=['POST'])
def receive_log():
if request.headers.get('X-API-Key') != API_KEY:
abort(401)
data = request.get_json(silent=True)
if not data:
abort(400)
try:
with open("/var/log/my-app/events.log", "a") as f:
f.write(json.dumps(data) + "\n")
except Exception as e:
print(f"Failed to write log: {e}")
abort(500)
return "OK", 200
if __name__ == '__main__':
app.run(host='127.0.0.1', port=5000)
Преимущества
- Минимальные затраты (около пяти долларов в месяц).
- Простота и контроль над хранением.
- Развёртывание за полчаса.
Недостатки
- Слабая масштабируемость: запись в один файл быстро становится узким местом.
- Требуется обслуживание (ротация логов, мониторинг диска, безопасность).
- Анализ — вручную через SSH и
grep.
Вариант 2. Серверный сборщик (надёжно и гибко)
Эволюция первого варианта — используем готовый оптимизированный open-source стек.
Что потребуется
- VPS за 5–10 долларов в месяц.
- Стек: Vector, Loki, Grafana.
Как это работает
- Vector — это HTTP-сервер, принимающий логи.
- Loki — база логов от Grafana, индексирует только метки (labels), что делает хранение дешёвым.
- Grafana — удобный интерфейс для поиска и анализа логов с помощью LogQL.
Пример конфигурации Vector (vector.yaml)
sources:
http_logs:
type: "http"
address: "0.0.0.0:8080"
decoding:
codec: "json"
auth:
strategy: "header"
header_key: "X-API-Key"
api_keys: ["super-secret-key"]
transforms:
my_transform:
type: "remap"
inputs: ["http_logs"]
source: |
.app = "my_mobile_app"
.level = get!(.level, default: "info")
sinks:
loki:
type: "loki"
inputs: ["my_transform"]
endpoint: "http://localhost:3100"
labels:
app: "{{ app }}"
level: "{{ level }}"
encoding:
codec: "json"
Преимущества
- Высокая производительность (тысячи логов в секунду).
- Удобный поиск и фильтрация через Grafana.
- Vector может отправлять логи не только в Loki, но и в S3, ClickHouse и другие хранилища.
Недостатки
- Более сложная настройка: три компонента, требующих Docker или systemd.
Вариант 3. Serverless (почти бесплатно и бесконечно масштабируемо)
Самый современный и гибкий вариант. Никаких серверов — вы платите только за количество запросов и объём данных.
Что потребуется
- Аккаунт в облаке (AWS, Google Cloud или Yandex Cloud).
- Стек (на примере AWS): API Gateway + Lambda + S3 или CloudWatch Logs.
Как это работает
Клиент отправляет POST-запрос.
API Gateway принимает запрос как управляемый HTTP-эндпоинт.
Он вызывает Lambda.
Lambda:
- сохраняет JSON в S3 по дате;
- отправляет лог в CloudWatch Logs.
Пример Lambda на Python (запись в S3)
import json
import boto3
import time
import os
s3 = boto3.client('s3')
BUCKET_NAME = os.environ['LOG_BUCKET_NAME']
def lambda_handler(event, context):
body = event.get('body')
if not body:
return {'statusCode': 400, 'body': 'No data'}
try:
log_data = json.loads(body)
except json.JSONDecodeError:
return {'statusCode': 400, 'body': 'Invalid JSON'}
now = time.strftime('%Y/%m/%d/%H', time.gmtime())
file_name = f"{context.aws_request_id}.json"
s3_key = f"logs/{now}/{file_name}"
try:
s3.put_object(
Bucket=BUCKET_NAME,
Key=s3_key,
Body=json.dumps(log_data),
ContentType='application/json'
)
return {'statusCode': 200, 'body': 'OK'}
except Exception as e:
print(e)
return {'statusCode': 500, 'body': 'Error saving log'}
Преимущества
- Бесплатные лимиты AWS/Google/Yandex покрывают миллионы логов в месяц.
- Автоматическая масштабируемость.
- Нет серверов и обновлений — минимум обслуживания.
Недостатки
- Анализ требует настройки (например, AWS Athena или BigQuery).
- Привязка к конкретному облачному провайдеру (vendor lock-in).
Лучшие практики на стороне клиента
- Асинхронная отправка — не блокируйте основной поток приложения.
- Пакетная передача — собирайте логи в массив и отправляйте партиями (раз в 30 секунд или после 50 событий).
- Повторные попытки (retry) — сохраняйте офлайн-логи локально (например, в SQLite) и отправляйте их позже.
- Фильтрация — отправляйте только важные уровни (INFO, WARN, ERROR).
Заключение
Собрать логи с удалённых клиентов дёшево — вполне реально. Главное — выбрать подход под свои задачи.
| Сценарий | Рекомендация |
|---|---|
| Начинаете проект | Serverless |
Уже есть VPS и нужен grep | Скрипт на VPS |
| Требуется мощное self-hosted решение | Vector + Loki |