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

Аналитика (ClickHouse)

Платформа автоматически собирает аналитические события по всем сервисам — выполнения воркфлоу, вызовы LLM, голосовые сессии, биллинг, API-запросы. Данные хранятся в ClickHouse и доступны для анализа через любой BI-инструмент.

Какие данные собираются

Платформа фиксирует следующие типы событий:

Выполнение рабочих процессов

Тип событияОписаниеЗаполняемые поля
execution.startedРабочий процесс запущен на выполнение. Фиксируется в момент старта Celery-задачи или SSE-стрима.workflow_id, execution_id, project_id, user_id, thread_id
execution.completedРабочий процесс успешно завершён.workflow_id, execution_id, project_id, user_id, thread_id, duration_ms (общая длительность), value_int (количество шагов)
execution.failedРабочий процесс завершился с ошибкой.workflow_id, execution_id, project_id, user_id, thread_id, duration_ms, dim1 (тип ошибки)
execution.interruptedВыполнение прервано пользователем или по таймауту.workflow_id, execution_id, project_id, user_id, thread_id, duration_ms
execution.node.completedОтдельная нода рабочего процесса успешно выполнена.workflow_id, execution_id, node_id, project_id, user_id, thread_id, duration_ms (время выполнения ноды), dim1 (тип ноды: agent, http, function и т.д.)
execution.node.failedНода завершилась с ошибкой.workflow_id, execution_id, node_id, project_id, user_id, thread_id, duration_ms, dim1 (тип ноды), dim2 (сообщение об ошибке)

Вызовы LLM

Тип событияОписаниеЗаполняемые поля
llm.callКаждый вызов языковой модели (OpenAI, Anthropic, Groq и др.). Фиксируется при биллинг-трекинге после получения ответа от LLM.workflow_id, execution_id, project_id, user_id, dim1 (название модели, например gpt-4o), value_int (общее количество токенов — input + output), value_float (стоимость в кредитах)

Голосовые сессии

Тип событияОписаниеЗаполняемые поля
voice.session.endedГолосовая сессия завершена. Записывается при сохранении метрик сессии.agent_id, session_id, project_id, user_id, thread_id, dim1 (режим: realtime или pipeline), dim2 (канал: web, sip и т.д.), value_int (количество реплик / turn count), value_float (длительность в секундах), duration_ms

Биллинг

Тип событияОписаниеЗаполняемые поля
billing.credits.consumedСписание кредитов за использование ресурсов платформы.workflow_id, execution_id, user_id, value_int (количество кредитов), dim1 (модель, если применимо), dim2 (тип операции: credits_consumed, seats и т.д.), properties (JSON с дополнительными метаданными)

API-запросы

Тип событияОписаниеЗаполняемые поля
user.api_callВходящий HTTP-запрос к Published API, Execution API или Webhook-эндпоинтам. Не фиксирует внутренние CRUD-запросы, health-check и документацию.user_id, dim1 (путь запроса, например /api/v1/published/run/...), dim2 (HTTP-метод: POST, GET), value_int (HTTP-статус ответа: 200, 400, 500), value_float (время ответа в мс), duration_ms
Общие поля

Все события автоматически содержат organization_id, project_id, timestamp (UTC), service (имя сервиса-источника) и environment. Это обеспечивает полную изоляцию данных между организациями и проектами.

Агрегированные представления

Помимо сырых событий, доступны предагрегированные таблицы для быстрых запросов:

  • execution_stats_hourly — почасовая статистика выполнений (количество, средняя длительность, шаги)
  • llm_usage_hourly — почасовое потребление LLM (количество вызовов, токены, кредиты)

Эти таблицы обновляются автоматически через ClickHouse Materialized Views и оптимальны для дашбордов с большими временными диапазонами.

Создание ключа аналитики

Для подключения BI-инструмента необходимо создать ключ аналитики. Ключ даёт read-only доступ к данным вашей организации.

Шаги

  1. Перейдите в Интеграции → вкладка Аналитика.
  2. Нажмите Создать ключ аналитики.
  3. В карточке ключа отобразятся реквизиты подключения:
    • Хост — адрес сервера ClickHouse
    • Порт — порт для подключения (обычно 8124)
    • Пользователь — сгенерированное имя пользователя
    • Пароль — отображается один раз при создании
    • База данныхanalytics
Важно

Пароль показывается только в момент создания ключа. Скопируйте его сразу. Если пароль утерян — используйте Сменить пароль для генерации нового.

Безопасность и ограничения

Каждый ключ создаёт отдельного пользователя в ClickHouse со следующими ограничениями:

ОграничениеЗначениеОписание
Режим доступаreadonly = 1Только SELECT — запись, изменение и удаление данных невозможны
Максимум памяти на запрос2 ГБЗапросы, превышающие лимит, автоматически прерываются
Таймаут запроса30 секундДолгие запросы завершаются по таймауту
Изоляция данныхRow-level securityПользователь видит только события своей организации
Привязка к проектуОпциональноКлюч можно ограничить данными одного проекта
Доступные таблицы3 таблицыevents, execution_stats_hourly, llm_usage_hourly
Права доступа

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

Подключение BI-инструментов

Grafana

  1. Установите плагин grafana-clickhouse-datasource:
    grafana-cli plugins install grafana-clickhouse-datasource
  2. В Grafana перейдите в ConfigurationData SourcesAdd data source.
  3. Выберите ClickHouse.
  4. Заполните реквизиты из карточки ключа:
    • Server address — хост
    • Server port — порт
    • Username — пользователь
    • Password — пароль
    • Databaseanalytics
  5. Нажмите Save & Test.

Metabase

  1. В Metabase перейдите в AdminDatabasesAdd database.
  2. Выберите тип ClickHouse (встроенный драйвер).
  3. Заполните реквизиты из карточки ключа.
  4. Нажмите Save.

SQL-клиент

Подключение через clickhouse-client:

clickhouse-client --host <хост> \
--port <порт> \
--user <пользователь> \
--password <пароль> \
--database analytics

Управление ключами

Ротация пароля

Нажмите Сменить пароль на карточке ключа. Старый пароль немедленно перестаёт работать, новый отображается один раз.

Отзыв ключа

Нажмите Отозвать на карточке ключа. Пользователь ClickHouse и все политики доступа будут удалены. BI-инструменты, использующие этот ключ, потеряют доступ.

Совет

Вы можете создать несколько ключей — например, отдельный для Grafana и отдельный для Metabase. Это позволяет отозвать доступ одного инструмента, не затрагивая другой.

Схема данных

Таблица events

Основная таблица со всеми аналитическими событиями.

КолонкаТипОписание
event_idUUIDУникальный идентификатор события (генерируется автоматически)
event_typeStringТип события (например, execution.completed, llm.call)
event_categoryStringКатегория, вычисляемая из типа: execution, llm, voice, billing, user
organization_idStringID организации
project_idStringID проекта (может быть пустым)
user_idStringID пользователя, инициировавшего действие
workflow_idStringID рабочего процесса
execution_idStringID конкретного выполнения
agent_idStringID агента (для голосовых сессий и агентных нод)
session_idStringID голосовой сессии
node_idStringID ноды рабочего процесса
thread_idStringID потока диалога
timestampDateTime64Время события в UTC
duration_msInt64Длительность операции в миллисекундах
value_intInt64Целочисленная метрика (токены, кредиты, HTTP-статус, количество реплик)
value_floatFloat64Дробная метрика (стоимость в кредитах, длительность в секундах, latency в мс)
dim1StringИзмерение 1 — зависит от типа события (модель, тип ноды, путь запроса, режим)
dim2StringИзмерение 2 — зависит от типа события (HTTP-метод, канал, тип операции)
dim3StringИзмерение 3 — резервное поле для дополнительных данных
propertiesStringПроизвольные свойства в формате JSON
serviceStringИмя сервиса-источника (backend-api, execution-service)
environmentStringОкружение (production, development)

Таблица execution_stats_hourly

Предагрегированная почасовая статистика выполнений.

КолонкаОписание
hourНачало часа
organization_idID организации
project_idID проекта
workflow_idID рабочего процесса
executionsКоличество выполнений
avg_duration_msСредняя длительность
total_stepsОбщее количество шагов

Таблица llm_usage_hourly

Предагрегированная почасовая статистика использования LLM.

КолонкаОписание
hourНачало часа
organization_idID организации
project_idID проекта
modelНазвание модели (берётся из dim1)
callsКоличество вызовов
total_tokensСуммарное количество токенов
total_creditsСуммарная стоимость в кредитах

Примеры SQL-запросов

Статистика выполнений за последние 7 дней

SELECT
toDate(timestamp) AS day,
countIf(event_type = 'execution.completed') AS success,
countIf(event_type = 'execution.failed') AS failed,
avg(duration_ms) / 1000 AS avg_duration_sec
FROM events
WHERE event_category = 'execution'
AND timestamp >= now() - INTERVAL 7 DAY
GROUP BY day
ORDER BY day

Потребление токенов по моделям

SELECT
dim1 AS model,
count() AS calls,
sum(value_int) AS total_tokens,
round(sum(value_float), 2) AS total_credits
FROM events
WHERE event_type = 'llm.call'
AND timestamp >= now() - INTERVAL 30 DAY
GROUP BY model
ORDER BY total_credits DESC

Активность по Published API

SELECT
toStartOfHour(timestamp) AS hour,
dim1 AS endpoint,
count() AS requests,
avg(duration_ms) AS avg_latency_ms
FROM events
WHERE event_type = 'user.api_call'
AND timestamp >= now() - INTERVAL 24 HOUR
GROUP BY hour, endpoint
ORDER BY hour, requests DESC

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

SELECT
dim1 AS node_type,
count() AS executions,
round(avg(duration_ms)) AS avg_ms,
round(quantile(0.95)(duration_ms)) AS p95_ms
FROM events
WHERE event_type = 'execution.node.completed'
AND timestamp >= now() - INTERVAL 7 DAY
GROUP BY node_type
ORDER BY avg_ms DESC

Голосовые сессии: длительность и реплики

SELECT
toDate(timestamp) AS day,
dim1 AS mode,
count() AS sessions,
round(avg(value_float)) AS avg_duration_sec,
round(avg(value_int)) AS avg_turns
FROM events
WHERE event_type = 'voice.session.ended'
AND timestamp >= now() - INTERVAL 30 DAY
GROUP BY day, mode
ORDER BY day

Использование агрегированных таблиц

Для дашбордов с большими временными диапазонами используйте предагрегированные таблицы — они работают значительно быстрее:

-- Выполнения по воркфлоу за месяц (из агрегированной таблицы)
SELECT
workflow_id,
sum(executions) AS total,
avg(avg_duration_ms) / 1000 AS avg_sec
FROM execution_stats_hourly
WHERE hour >= now() - INTERVAL 30 DAY
GROUP BY workflow_id
ORDER BY total DESC
LIMIT 10
-- Расход токенов по моделям за квартал (из агрегированной таблицы)
SELECT
model,
sum(calls) AS total_calls,
sum(total_tokens) AS tokens,
round(sum(total_credits), 2) AS credits
FROM llm_usage_hourly
WHERE hour >= now() - INTERVAL 90 DAY
GROUP BY model
ORDER BY credits DESC