Настроить логирование в ClickHouse
ТЕХНИЧЕСКОЕ ЗАДАНИЕ: Настроить логирование в ClickHouse
1. Цель задачи
Научиться проектировать и развёртывать высоконагруженную систему сбора JSON-логов на базе ClickHouse. Освоить оптимальную схему таблицы для логов, настройку партиционирования и индексов, обеспечивающих быстрый поиск по trace_id. Сымитировать нагрузку и проверить, что система выдерживает прием 1 млн записей в секунду.
Ключевой результат Полностью рабочая инсталляция ClickHouse с таблицей для логов, скриптами загрузки синтетических данных, демонстрацией поиска по trace_id и измерением пропускной способности не менее 1 млн логов/сек.
2. Исходные данные
| Что нужно | Откуда взять |
|---|---|
| ClickHouse (сервер, клиент) | Официальный сайт clickhouse.com – установка локально или через Docker |
| Язык Python с библиотеками | clickhouse-driver, json, uuid, time, random |
| Инструмент генерации логов | Собственный Python-скрипт |
| Инструмент мониторинга | Grafana (опционально) – для визуализации |
| Тестовый дашборд | Графана + altinity/clickhouse-grafana плагин |
Если нет реального инструмента — симулируем:
- Устанавливаем ClickHouse одной командой Docker:
docker run -d --name ch-logging -p 8123:8123 -p 9000:9000 clickhouse/clickhouse-server:latest - Генерируем синтетические логи в формате JSON с полями: timestamp,
level, service,message, trace_id. - Нагрузку создаём multiprocessing-скриптом, отправляющим пакеты по 10 000 строк через HTTP Bulk Insert.
3. Технологический стек
| Компонент | Инструменты | Назначение |
|---|---|---|
| Хранилище логов | ClickHouse 24+ | Высокопроизводительная колоночная БД для логов |
| Клиент для вставки | Python + clickhouse-driver | Вставка JSON-логов через Native Protocol |
| Генератор логов | Python + json, uuid, datetime | Создание синтетических логов с заданной интенсивностью |
| Анализатор | clickhouse-client | Выполнение SQL-запросов, поиск по trace_id |
| Визуализация | Grafana + ClickHouse data source | Дашборд с QPS (queries per second), задержками |
| Нагрузочное тестирование | Python multiprocessing + time | Измерение пропускной способности до 1 млн логов/сек |
4. Этапы выполнения
Этап 1: Поднятие ClickHouse и создание таблицы (30 минут)
Действия
-
Запустить ClickHouse в Docker:
docker run -d --name ch-logging -p 8123:8123 -p 9000:9000 \ -e CLICKHOUSE_DB=logs_db \ clickhouse/clickhouse-server:latest -
Подключиться через clickhouse-client внутри контейнера или через docker exec:
docker exec -it ch-logging clickhouse-client -
Создать базу данных:
CREATE DATABASE IF NOT EXISTS logs_db; -
Создать таблицу для JSON-логов с учётом высокой нагрузки и поиска по trace_id:
CREATE TABLE logs_db.json_logs ( timestamp DateTime64(3) CODEC(Delta, ZSTD), level LowCardinality(String), service LowCardinality(String), message String, trace_id UUID, additional String DEFAULT '' ) ENGINE = MergeTree() PARTITION BY toYYYYMM(timestamp) ORDER BY (trace_id, timestamp) SETTINGS index_granularity = 4096;Важно ORDER BY (trace_id, timestamp) создаёт первичный индекс по trace_id, что критично для быстрого поиска. Партиционирование по месяцу облегчает удаление старых данных.
-
Проверить создание: SHOW CREATE TABLE logs_db.json_logs;
Ожидаемый результат этапа Работающий ClickHouse с пустой таблицей, готовой принимать логи.
Этап 2: Скрипт генерации синтетических логов (45 минут)
Действия
- Написать Python-файл
log_generator.py, который: - Добавить функцию generate_batch(batch_size=10000), возвращающую список словарей.
- Сгенерировать 100 000 строк для первичной загрузки (debug).
- Вывести пример строки:
{"timestamp": "2025-03-25 10:00:00.123", "level": "INFO", "service": "api-gateway", "message": "request processed", "trace_id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890"}
Ожидаемый результат этапа Рабочий генератор, способный создавать миллионы строк за разумное время.
Этап 3: Вставка логов в ClickHouse (60 минут)
Действия
- Использовать clickhouse-driver (установить pip install clickhouse-driver).
- Подключиться к ClickHouse:
from clickhouse_driver import Client client = Client('localhost') - Оптимальная вставка – через INSERT INTO ... VALUES с пакетом кортежей:
data = [(row['timestamp'], row['level'], row['service'], row['message'], row['trace_id']) for row in batch] client.execute('INSERT INTO logs_db.json_logs VALUES', data) - Настроить буферизацию и повторные попытки при ошибках.
- Вставить 100 000 строк, проверить количество:
SELECT count() FROM logs_db.json_logs; - Провести поиск по одному trace_id и замерить время:
Убедиться, что время < 50 мс.SELECT * FROM logs_db.json_logs WHERE trace_id = '...' FORMAT JSON;
Ожидаемый результат этапа Таблица заполнена данными, поиск по trace_id работает быстро.
Этап 4: Нагрузочное тестирование – 1 млн логов/сек (90 минут)
Действия
- Написать скрипт
load_test.py, который:- Использует multiprocessing.Pool с 8–16 воркерами.
- Каждый воркер генерирует пачки по 10 000 строк и отправляет через
client.execute. - Засекает время начала и окончания.
- Вычисляет throughput =
общее количество / затраченное время (сек).
- Настроить ClickHouse на приём высокой нагрузки:
- Отключить fsync на время теста (для чистоты замера): SETTINGS fsync_after_insert = 0 (в конфиге).
- Увеличить max_insert_block_size до 1 048 576.
- Убедиться, что сетевые каналы не узкие (использовать локальный хост).
- Запустить тест с целью достичь 1 млн строк в секунду (суммарно на всех воркерах).
- Если не хватает – увеличить количество воркеров или размер пачки.
- Зафиксировать результат в консоли:
Inserted 1,000,000 rows in 1.02 sec → 980,392 rows/sec - Одновременно в другом окне проверить, что поиск по trace_id остаётся быстрым (с помощью отдельного процесса).
Ожидаемый результат этапа Измеренный throughput не менее 1 млн записей/сек.
Этап 5: Визуализация в Grafana (40 минут)
Действия
- Установить Grafana (Docker):
docker run -d --name=grafana -p 3000:3000 grafana/grafana-oss - Добавить источник данных ClickHouse (плагин
altinity-clickhouse-datasource). - Создать дашборд с панелями:
- QPS (вставок в секунду) – используя system.query_log.
- Распределение уровней – pie chart.
- Последние ошибки – таблица с последними 20 ERROR-логами.
- Поиск по trace_id – text-виджет с переменной trace_id.
- Экспортировать дашборд в JSON и сохранить в репозиторий.
Ожидаемый результат этапа Дашборд Grafana, отображающий текущее состояние логов.
5. Критерии приемки (Definition of Done)
- ClickHouse запущен в Docker или нативно, таблица
logs_db.json_logsсоздана с указанной схемой. - Python-скрипт генерации логов работает и создаёт строки с полями
timestamp,level,service,message,trace_id. - Вставка 100 000 строк завершается без ошибок.
- Поиск по произвольному
trace_idвозвращает результат за < 100 мс. - Нагрузочный тест показывает пропускную способность ≥ 1 млн строк/сек (средняя за 10 секунд).
- Дашборд Grafana подключён к ClickHouse и отображает хотя бы одну полезную панель.
- Весь код и конфигурация зафиксированы в Git-репозитории.
6. Ожидаемый результат
Основной артефакт Папка проекта со следующей структурой:
logging-clickhouse/
├── docker-compose.yml # ClickHouse + Grafana
├── schema.sql # DDL таблицы
├── log_generator.py # генератор логов
├── load_test.py # нагрузочный тест
├── grafana_dashboard.json # экспортированный дашборд
└── README.md # инструкция по запуску
Дополнительно Видео/скриншот консоли с результатом throughput > 1 млн/сек и скриншот дашборда.
7. Возможные сложности и их решение
| Сложность | Решение |
|---|---|
| ClickHouse не принимает вставки с высокой скоростью | Проверить max_insert_block_size, увеличить max_threads до 16; отключить fsync |
Поиск по trace_id медленный | Убедиться, что trace_id – первая колонка в ORDER BY. Использовать UUID тип |
| Docker потребляет слишком много памяти | Ограничить память контейнера: --memory=4g |
| Python-скрипт падает при большой нагрузке | Увеличить таймауты client.execute(timeout=60); использовать connection_pool |
| JSON с произвольными полями | Использовать тип String для additional или Nested для структурированных |
8. Бюджет времени (оценка)
| Этап | Время |
|---|---|
| Этап 1: Поднятие ClickHouse и таблица | 30 мин |
| Этап 2: Скрипт генерации логов | 45 мин |
| Этап 3: Вставка и базовая проверка | 60 мин |
| Этап 4: Нагрузочное тестирование | 90 мин |
| Этап 5: Визуализация в Grafana | 40 мин |
| Итого | ~4 ч |
При первом выполнении возможны задержки на отладку производительности – заложите дополнительно 1-2 часа.
9. Связанные вопросы из базы знаний
| Вопрос | Тема |
|---|---|
| 12 | Хранение логов в ClickHouse |
| 45 | Индексы и партиционирование |
| 78 | Bulk Insert в ClickHouse |
| 101 | Мониторинг производительности БД |
| 203 | Эфемерные UUID и их хранение |
| 256 | Оптимизация запросов по trace_id |
| 302 | Настройка Grafana для логов |
| 401 | Утилиты нагрузочного тестирования |
| 567 | Docker Compose для ClickHouse |
| 612 | JSON-логи и их парсинг |
10. Чек-лист самопроверки
- Я запустил ClickHouse через Docker и проверил, что порты 8123 и 9000 открыты.
- Я выполнил DDL-скрипт и убедился, что таблица создана с
ORDER BY (trace_id, timestamp). - Мой
log_generator.pyвыдаёт строки в нужном формате и может сгенерировать миллион строк менее чем за 2 минуты. - Я измерил поиск по одному
trace_id– время выполнения меньше 50 мс. - Нагрузочный тест показал throughput не ниже 1 млн/сек (например:
1,050,000 rows in 1.04 sec). - В Grafana я добавил источник данных ClickHouse и создал хотя бы одну панель.
- Все файлы проекта сохранены в Git с осмысленными commit’ами.