Сбор и запись логов в ClickHouse с помощью Vector | AdminWiki

Сбор и запись логов в ClickHouse с помощью Vector

07 сентября 2026 7 мин. чтения
Содержание статьи

Как записывать логи в ClickHouse: схема и минимальный pipeline

Для централизованного сбора и анализа логов часто используют связку Vector и ClickHouse. Vector принимает события из разных источников, нормализует их и отправляет в ClickHouse пакетами. ClickHouse хранит логи в таблицах семейства MergeTree, позволяя быстро выполнять аналитические запросы.

Минимальный pipeline состоит из трех компонентов: source, transform и sink. Source читает логи из файла, journald или stdin. Transform разбирает сообщения и приводит поля к нужным типам. Sink ClickHouse формирует INSERT-запросы и отправляет их на HTTP-интерфейс сервера.

Пример минимальной конфигурации Vector:

[sources.app_logs]
type = "file"
include = ["/var/log/app/*.log"]

[transforms.parse_logs]
type = "remap"
inputs = ["app_logs"]
source = '''
  . = parse_json!(.message)
  .timestamp = parse_timestamp!(.timestamp, "%Y-%m-%dT%H:%M:%S%.fZ")
'''

[sinks.clickhouse]
type = "clickhouse"
inputs = ["parse_logs"]
endpoint = "http://clickhouse:8123"
database = "logs"
table = "app_events"
auth.strategy = "basic"
auth.user = "vector"
auth.password = "${CLICKHOUSE_PASSWORD}"
skip_unknown_fields = true

Замените endpoint, database, table и учетные данные на свои. Перед запуском создайте таблицу в ClickHouse, иначе события будут отклонены.

Что должно быть готово перед настройкой

Проверьте, что у вас установлен Vector версии 0.31 или новее, доступен ClickHouse 22.8+ и создана база данных. Пользователь Vector должен иметь права INSERT на целевую таблицу и SELECT на системные таблицы для проверки схемы.

Убедитесь, что Vector может подключиться к HTTP-порту ClickHouse (обычно 8123). Если используется HTTPS, настройте TLS. Подготовьте пример лог-события, чтобы проверить парсинг и типы полей.

Минимальная конфигурация доставки

В конфигурации выше source file читает все файлы по шаблону. Transform remap разбирает JSON из поля message и преобразует timestamp в DateTime64. Sink clickhouse отправляет события в таблицу app_events, пропуская неизвестные поля.

Ключевые параметры sink: endpoint, database, table, auth. Формат по умолчанию JSONEachRow, имена полей должны совпадать со столбцами таблицы. Если поле отсутствует в таблице, оно будет пропущено при skip_unknown_fields=true.

Подготовка ClickHouse: таблица для логов и схема данных

Правильная схема таблицы предотвращает большинство ошибок вставки и ускоряет запросы. Минимальный набор полей: время события, уровень, источник, сообщение, хост и идентификатор запроса.

Какие поля хранить в событии

Разделите поля на временные, идентификационные, классификационные и диагностические. Временные: timestamp (время события), ingested_at (время приема). Идентификационные: request_id, trace_id. Классификационные: level, source, service, host. Диагностические: message, raw, metadata.

Для фильтрации и агрегаций чаще всего используются timestamp, level, source и host. Поэтому их стоит вынести в отдельные столбцы с подходящими типами.

Типы данных и преобразование перед INSERT

Используйте DateTime64(3) для timestamp с миллисекундной точностью. Для повторяющихся строковых значений, таких как level или source, подойдет LowCardinality(String). Числовые коды ответов храните в UInt16 или Int32. Необязательные поля объявляйте как Nullable.

Не передавайте timestamp в виде строки, если столбец ожидает DateTime64. Это вызовет ошибку TYPE_MISMATCH. Преобразуйте время в Vector с помощью parse_timestamp.

Engine, PARTITION BY и ORDER BY

Используйте MergeTree. Партиционируйте по дате события: PARTITION BY toYYYYMM(timestamp) для месячных партиций или toYYYYMMDD(timestamp) для дневных. Ключ сортировки должен соответствовать частым условиям WHERE: ORDER BY (timestamp, service, level).

Пример DDL:

CREATE TABLE logs.app_events (
    timestamp DateTime64(3),
    ingested_at DateTime DEFAULT now(),
    level LowCardinality(String),
    source LowCardinality(String),
    service LowCardinality(String),
    host String,
    message String,
    request_id String DEFAULT '',
    metadata String DEFAULT ''
)
ENGINE = MergeTree
PARTITION BY toYYYYMM(timestamp)
ORDER BY (timestamp, service, level)
TTL timestamp + INTERVAL 30 DAY;

Такая таблица готова к приему данных из Vector.

Подключение источников логов к Vector

Vector поддерживает множество источников. Для файлов используйте source file, для journald - source journald, для Docker - source docker_logs. Настройте чтение с учетом multiline и позиции.

JSON-логи приложений и контейнеров

Если приложение пишет JSON, Vector может разобрать его напрямую. Пример события:

{"timestamp":"2026-09-07T12:34:56.789Z","level":"info","message":"User login","service":"auth","host":"web-01","request_id":"abc123"}

В transform remap используйте parse_json для всего сообщения, затем переименуйте поля при необходимости. Вложенные объекты можно извлечь через точку: .user.id.

Текстовые логи и syslog

Для неструктурированных логов используйте регулярные выражения или специализированные парсеры. Например, для syslog-формата:

. = parse_syslog!(.message)
.timestamp = parse_timestamp!(.timestamp, "%Y-%m-%dT%H:%M:%S%.fZ")

Учитывайте разные форматы дат и возможные multiline stack trace. Настройте source file с параметром multiline.

Преобразование логов в Vector с помощью VRL

VRL (Vector Remap Language) позволяет манипулировать событиями. Основные операции: parse_json, parse_timestamp, переименование полей, условная логика.

Разбор JSON и выделение ключевых полей

Пример transform:

[transforms.normalize]
type = "remap"
inputs = ["app_logs"]
source = '''
  . = parse_json!(.message)
  .timestamp = parse_timestamp!(.timestamp, "%Y-%m-%dT%H:%M:%S%.fZ")
  .level = downcase!(string!(.level))
  .source = .service
  del(.service)
'''

Сохраните исходное сообщение в поле raw, если нужно диагностировать ошибки парсинга.

Преобразование timestamp в корректный тип времени

Используйте parse_timestamp с явным форматом. Для ISO 8601: "%Y-%m-%dT%H:%M:%S%.fZ". Если timestamp отсутствует или некорректен, подставьте время приема Vector: .timestamp = now().

Нормализация level, source и необязательных полей

Приведите level к нижнему регистру и ограниченному набору значений: info, warn, error, debug. Заполните source из имени сервиса или файла. Пустые строки замените на null, если столбец Nullable.

Настройка Vector sink ClickHouse

Sink ClickHouse отправляет события через HTTP-интерфейс. Основные параметры: endpoint, database, table, auth, encoding, batch, buffer.

Endpoint, база, таблица и авторизация

Endpoint указывает на HTTP-порт ClickHouse, обычно http://clickhouse:8123. Для HTTPS используйте https:// и настройте TLS. Авторизация может быть basic или через заголовки. Рекомендуется хранить пароль в переменных окружения.

Создайте отдельного пользователя с правами только на нужную базу:

CREATE USER vector IDENTIFIED WITH sha256_password BY 'strong_password';
GRANT INSERT ON logs.app_events TO vector;

Формат отправляемых строк и соответствие схеме

По умолчанию Vector использует формат JSONEachRow. Имена полей в событии должны совпадать со столбцами таблицы. Если поле лишнее, оно будет пропущено при skip_unknown_fields=true. Если поле отсутствует, ClickHouse использует значение по умолчанию или NULL, если столбец Nullable.

Обработка ошибок отправки

При временной недоступности ClickHouse Vector выполняет повторные попытки с экспоненциальной задержкой. Настройте request.retry_attempts и request.retry_max_duration_secs. Если ошибка связана с неверной схемой, повторы не помогут, нужно исправить данные или таблицу.

Батчинг и буферизация: как снизить число мелких вставок

ClickHouse эффективнее обрабатывает пакеты, чем одиночные INSERT. Vector по умолчанию буферизует события и отправляет их батчами.

Настройка размера и времени batch

Параметры batch.max_events, batch.max_bytes и batch.timeout_secs управляют размером пакета. Например:

[sinks.clickhouse.batch]
max_events = 1000
max_bytes = 10485760  # 10 MB
timeout_secs = 1

Пакет отправляется, когда достигнут любой из лимитов. Это балансирует задержку и пропускную способность.

Памятный и дисковый buffer

Буфер может быть в памяти или на диске. Memory buffer быстрее, но теряет данные при сбое. Disk buffer надежнее, но требует места и прав на запись. Настройте buffer.type = "disk" и buffer.max_size для ограничения использования диска.

Задержка доставки, повторы и дубликаты

Большие батчи увеличивают задержку, но снижают нагрузку. Повторы после сетевых ошибок могут привести к дубликатам. Учитывайте это в аналитических запросах, используя функции для дедупликации.

Партиционирование, поиск и TTL в таблице логов

Партиционирование и ключ сортировки определяют скорость запросов и управление хранением.

Как выбрать партицию по времени

Для логов с объемом до 100 ГБ в месяц достаточно месячных партиций. Дневные партиции полезны, если нужно часто удалять старые данные. Избегайте партиционирования по высококардинальным полям.

ORDER BY для типовых запросов к логам

Ключ сортировки должен начинаться с timestamp, затем service, level. Это ускоряет фильтрацию по времени и сервису. Пример запроса:

SELECT count() FROM logs.app_events
WHERE timestamp >= now() - INTERVAL 1 HOUR
  AND service = 'auth'
  AND level = 'error';

TTL и политика хранения

TTL автоматически удаляет старые данные. Укажите TTL timestamp + INTERVAL 30 DAY в определении таблицы. Проверяйте фактическое удаление с помощью system.parts. Учитывайте требования аудита при выборе срока хранения.

Проверка доставки и диагностика типовых ошибок

После настройки проверьте, что события доходят до ClickHouse.

Проверка конфигурации и тестового события

Запустите Vector с флагом --config-toml для проверки синтаксиса. Затем отправьте тестовое событие через stdin и проверьте логи Vector. Убедитесь, что timestamp и другие поля имеют ожидаемые типы.

Ошибки timestamp и типов данных

Частые ошибки: неверный формат даты, отсутствие часового пояса, передача null в непустой столбец, числовое значение как строка. Исправляйте данные в transform VRL.

Таймауты, переполнение буфера и недоступный ClickHouse

Смотрите метрики Vector: processed_events_total, sent_events_total, buffer_events. При росте буфера проверьте доступность ClickHouse, права пользователя, лимиты на вставку.

Контроль полноты и задержки доставки

Сравните количество событий на источнике и в ClickHouse за интервал. Проверьте максимальный timestamp в таблице и задержку относительно текущего времени. Используйте запрос:

SELECT max(timestamp), now() - max(timestamp) AS lag
FROM logs.app_events;

Production-чеклист для эксплуатации Vector и ClickHouse

Перед запуском в production выполните следующие шаги.

Безопасность подключения и права

Используйте отдельного пользователя с минимальными правами. Храните пароль в переменной окружения или секрете. Включите TLS при передаче по открытым сетям. Ограничьте сетевой доступ к ClickHouse.

Наблюдаемость и регламент проверки

Настройте мониторинг метрик Vector: скорость входящих событий, успешные и неуспешные отправки, размер буфера, retries. Периодически проверяйте объем таблицы и эффективность TTL.

Дополнительно изучите настройку централизованного сбора логов в S3 и оптимизацию хранения логов.

Поделиться:
Сохранить гайд? В закладки браузера