Перейти к основному содержимому
Перейти к основному содержимому

Трассировка ClickHouse с помощью OpenTelemetry

OpenTelemetry — это открытый стандарт для сбора трасс и метрик из распределённых приложений. ClickHouse частично поддерживает OpenTelemetry.

Передача контекста трассировки в ClickHouse

ClickHouse принимает HTTP-заголовки контекста трассировки, как описано в рекомендации W3C. Он также принимает контекст трассировки по нативному протоколу, который используется для обмена данными между серверами ClickHouse или между клиентом и сервером. Для ручного тестирования заголовки контекста трассировки, соответствующие спецификации Trace Context, можно передать в clickhouse-client с помощью флагов --opentelemetry-traceparent и --opentelemetry-tracestate.

Если родительский контекст трассировки не передан или переданный контекст трассировки не соответствует указанному выше стандарту W3C, ClickHouse может начать новую трассировку с вероятностью, задаваемой настройкой opentelemetry_start_trace_probability.

Распространение контекста трассировки

Контекст трассировки распространяется в последующие сервисы в следующих случаях:

  • Запросы к удалённым серверам ClickHouse, например, при использовании движка таблиц Distributed.

  • Табличная функция url. Информация о контексте трассировки передаётся в HTTP-заголовках.

Трассировка запросов ClickHouse Keeper

ClickHouse поддерживает трассировку с использованием OpenTelemetry для запросов ClickHouse Keeper (службы координации, совместимой с ZooKeeper). Эта функция обеспечивает детальную наблюдаемость жизненного цикла операций Keeper — от отправки клиентского запроса до обработки на стороне сервера.

Включение трассировки Keeper

Чтобы включить трассировку запросов к Keeper, задайте следующие настройки в конфигурации клиента ZooKeeper/Keeper:

<clickhouse>
    <zookeeper>
        <node>
            <host>keeper1</host>
            <port>9181</port>
        </node>
        <!-- Enable OpenTelemetry tracing context propagation -->
        <pass_opentelemetry_tracing_context>true</pass_opentelemetry_tracing_context>
    </zookeeper>
</clickhouse>

Типы спанов Keeper

Когда включена трассировка, ClickHouse создаёт спаны как для клиентских, так и для серверных операций Keeper:

Клиентские спаны:

  • zookeeper.create — Создание нового узла
  • zookeeper.get — Получение данных узла
  • zookeeper.set — Установка данных узла
  • zookeeper.remove — Удаление узла
  • zookeeper.list — Перечисление дочерних узлов
  • zookeeper.exists — Проверка существования узла
  • zookeeper.multi — Атомарное выполнение нескольких операций
  • zookeeper.client.requests_queue — Время ожидания запросов в очереди перед отправкой

Серверные спаны (Keeper):

  • keeper.receive_request — Получение и разбор запроса от клиента
  • keeper.dispatcher.requests_queue — Постановка запроса в очередь в диспетчере
  • keeper.write.pre_commit — Предварительная обработка запросов на запись до коммита Raft
  • keeper.write.commit — Обработка запросов на запись после коммита Raft
  • keeper.read.wait_for_write — Ожидание запросами на чтение завершения зависимых операций записи
  • keeper.read.process — Обработка запросов на чтение
  • keeper.dispatcher.responses_queue — Постановка ответа в очередь в диспетчере
  • keeper.send_response — Отправка ответа клиенту

Семплирование и производительность

Чтобы контролировать накладные расходы трассировки, Keeper использует динамическое семплирование. Частота семплирования автоматически подстраивается в диапазоне от 1/10 000 до 1/10 в зависимости от размера запроса. Для всех запросов (как попавших в выборку, так и нет) длительность записывается в гистограммные метрики для мониторинга производительности.

Трассировка самого ClickHouse

ClickHouse создаёт trace spans для каждого запроса и некоторых этапов его выполнения, таких как планирование запроса или распределённые запросы.

Чтобы эта информация была полезной, данные трассировки должны быть экспортированы в систему мониторинга, поддерживающую OpenTelemetry, такую как Jaeger или Prometheus. ClickHouse избегает зависимости от конкретной системы мониторинга и вместо этого предоставляет данные трассировки через системную таблицу. Информация о span'ах трассировки OpenTelemetry, требуемая стандартом, хранится в таблице system.opentelemetry_span_log.

Таблица должна быть включена в конфигурации сервера, см. элемент opentelemetry_span_log в файле конфигурации по умолчанию config.xml. По умолчанию она включена.

Теги или атрибуты сохраняются в виде двух параллельных массивов, содержащих ключи и значения. Для работы с ними используйте ARRAY JOIN.

Log-query-settings

Настройка log_query_settings позволяет логировать изменения параметров запроса во время его выполнения. При включении любые изменения настроек запроса будут записываться в журнал спанов OpenTelemetry. Эта функция особенно полезна в продуктивной среде для отслеживания изменений конфигурации, которые могут повлиять на производительность запросов.

Интеграция с системами мониторинга

На данный момент нет готового инструмента, позволяющего экспортировать данные трассировки из ClickHouse в систему мониторинга.

Для тестирования можно настроить экспорт с помощью materialized view с движком URL поверх таблицы system.opentelemetry_span_log, которое будет отправлять поступающие лог-записи на HTTP-эндпоинт коллектора трассировок. Например, чтобы отправлять минимальные данные о спане в экземпляр Zipkin, запущенный по адресу http://localhost:9411, в формате Zipkin v2 JSON:

CREATE MATERIALIZED VIEW default.zipkin_spans
ENGINE = URL('http://127.0.0.1:9411/api/v2/spans', 'JSONEachRow')
SETTINGS output_format_json_named_tuples_as_objects = 1,
    output_format_json_array_of_rows = 1 AS
SELECT
    lower(hex(trace_id)) AS traceId,
    CASE WHEN parent_span_id = 0 THEN '' ELSE lower(hex(parent_span_id)) END AS parentId,
    lower(hex(span_id)) AS id,
    operation_name AS name,
    start_time_us AS timestamp,
    finish_time_us - start_time_us AS duration,
    cast(tuple('clickhouse'), 'Tuple(serviceName text)') AS localEndpoint,
    cast(tuple(
        attribute.values[indexOf(attribute.names, 'db.statement')]),
        'Tuple("db.statement" text)') AS tags
FROM system.opentelemetry_span_log

В случае возникновения ошибок та часть данных журнала, для которой произошла ошибка, будет незаметно потеряна. Если данные не поступают, проверьте журнал сервера на наличие сообщений об ошибках.