К содержанию
ActionPulse

Загрузка истории: CSV, Amplitude, ClickHouse

Перенос накопленной истории событий в ActionPulse — требования к CSV, экспорт Amplitude, чтение из своего ClickHouse, состояния задачи и защита от дублей.

Кому
Инженерам данных и аналитикам
Проверено
На этой странице

Загрузка нужна один раз — когда вы подключили ActionPulse, а история продукта осталась в старой системе. Обычный приём событий для этого не подходит: он рассчитан на поток «здесь и сейчас» и время далеко в прошлом заменяет временем приёма. Загрузка — отдельный путь, который сохраняет исходное event_time каждой строки.

Экран — Данные и сбор → Загрузка данных, кнопка «Загрузить данные».

Три источника

Источник Что вы даёте Настройка колонок Границы одной задачи
CSV-файл файл до 512 МиБ вручную, в мастере размер загружаемого файла
Amplitude export архив gzip JSON Lines до 512 МиБ фиксирована форматом Amplitude 5 000 000 строк, 4 ГиБ распакованных данных
ClickHouse DSN строка подключения и SELECT вручную, по именам колонок результата 5 000 000 строк, 256 колонок, 15 минут

Мастер для CSV состоит из трёх шагов (тип → превью и маппинг → сводка), для Amplitude и ClickHouse — из двух. Задачи выполняются последовательно одна за другой, поэтому крупный перенос лучше разбить на несколько файлов или несколько детерминированных SELECT, а не ждать одну гигантскую задачу.

Требования к файлу CSV

  • Кодировка — UTF-8. Файл не перекодируется; текст в другой кодировке превратится в мусор в именах событий и свойств.
  • Разделитель — запятая. Кавычки экранируются удвоением (""), переводы строк — LF или CRLF.
  • Первая строка — заголовок с именами колонок. Именно по этим именам строится маппинг.
  • Размер — до 512 МиБ на запрос.

Превью в браузере читает первые 256 КБ файла и показывает 20 строк, чтобы вы проверили разбор до отправки. Если заголовок не распознан, мастер скажет об этом сразу и не даст перейти дальше.

Сопоставление колонок с полями события

Каждой колонке назначается одна роль:

Роль Поле события Обязательность
Событие (event_name) имя события ровно одна колонка
Время (time) event_time ровно одна колонка
user_id известный идентификатор нужна хотя бы одна из двух
anon_id анонимный идентификатор нужна хотя бы одна из двух
Свойство (prop) ключ в props не обязательно
Пропустить колонка не переносится

Мастер не даёт запустить загрузку, пока event_name или time не назначены или назначены сразу нескольким колонкам. Колонок-свойств — до 64 (столько же свойств принимает одно событие), имена свойств не должны повторяться. Имя свойства по умолчанию совпадает с именем колонки, но его можно переопределить.

Ограничения полей — те же, что у обычного приёма: имя события по правилу ^[a-z0-9_.]{1,128}$, идентификатор до 256 символов, ключ свойства до 64 символов, значение до 8 КБ. Полный состав события — в схеме событий.

Значения свойств из CSV и из ClickHouse записываются строками, даже если в источнике это число. Свойства из экспорта Amplitude переносятся как есть, с исходными типами. Если по свойству нужно считать суммы, заранее решите, из какого источника грузить и как потом приводить тип в запросах.

Время события

Формат времени выбирается один на всю задачу:

Формат Пример значения
ISO 8601 2026-07-01T10:15:00Z
Unix, секунды 1782000900
Unix, миллисекунды 1782000900000
YYYY-MM-DD HH:mm:ss 2026-07-01 10:15:00

Часовой пояс из мастера (по умолчанию — часовой пояс проекта) применяется только к формату YYYY-MM-DD HH:mm:ss: у Unix-времени смысла нет, а значение ISO 8601 обязано нести собственное смещение — Z или +03:00. ISO-значение без смещения отклоняется.

Загрузка истории намеренно строже обычного приёма и никогда не подставляет серверное время вместо непонятного:

Причина отклонения строки Что означает
missing_time колонка времени пустая
invalid_time значение не разбирается выбранным форматом
future_time время больше чем на 48 ч в будущем
time_too_old время старше срока хранения событий вашего тарифа

Отсюда прямое следствие: глубина загружаемой истории равна сроку хранения тарифа — от 6 месяцев до 25 месяцев в зависимости от плана, см. тарифы и лимиты. Строки старше этой границы не «дожидаются своего срока», а отклоняются сразу. Загрузить архив десятилетней давности не получится ни на одном тарифе.

Экспорт Amplitude

Единственное поле мастера — файл .jsonl.gz или .gz. Маппинг не настраивается, он задан форматом Amplitude: event_type → имя события, user_id и device_id → идентификаторы, time (Unix, миллисекунды) → время события, event_properties → свойства. Строка без имени события или без обоих идентификаторов отклоняется.

Идентификатор события берётся из самого экспорта — uuid, $insert_id, insert_id или event_id, в этом порядке; если ни одного нет, он выводится из содержимого строки. Границы одной задачи: 5 000 000 строк источника и 4 ГиБ распакованных данных. Крупный экспорт нужно разбить на несколько файлов и загрузить несколькими задачами.

Чтение из вашего ClickHouse

Понадобится строка подключения вида clickhouse://user:pass@host:9000/db и SELECT, возвращающий по строке на событие. Дальше указываются имена колонок результата: событие, необязательный event_id, user_id, anon_id, время и список колонок-свойств через запятую. Кнопка «Начать загрузку» становится активной, когда заданы DSN, запрос, колонка события, колонка времени и хотя бы один из идентификаторов.

Прогресс такой задачи держится на 50 %, пока она идёт: общее число строк заранее неизвестно, а спрашивать count() у вашего сервера продукт не пытается. Задача останавливается через 15 минут — это защита от бесконечного SELECT, который иначе заблокировал бы очередь. Долгий перенос разбивайте на детерминированные запросы по диапазонам.

Состояния задачи

Карточка задачи обновляется сама, пока задача не завершится.

Статус Что происходит Что делать
В очереди задача принята, воркер её ещё не взял можно отменить
Выполняется строки читаются и принимаются следите за счётчиками, можно отменить
Отменяется отмена запрошена подождите: воркер остановится после ближайшего безопасного чекпоинта
Отменён задача остановлена вами для CSV доступна кнопка «Продолжить загрузку»
Готово источник прочитан до конца сверьте «Принято» и «Отклонено»
Ошибка задача упала текст ошибки — на карточке

Счётчики на карточке — «Принято» и «Отклонено». Отдельного счётчика дублей задача не ведёт: подавленные повторы попадают в «Принято», а совпадений с уже загруженной ранее историей продукт не ищет вовсе.

Типичные причины статуса «Ошибка»: источник ClickHouse не отвечает или запрос к нему упал, превышена граница 5 000 000 строк, архив Amplitude распаковался больше чем в 4 ГиБ, задача ClickHouse не уложилась в 15 минут. Эти отказы касаются задачи целиком — уже принятые строки остаются в проекте.

Отмена и продолжение

Отменить можно задачу в статусе «В очереди» или «Выполняется». Отмена идемпотентна: повторное нажатие ничего не ломает. Воркер не обрывается посередине батча — он доводит текущий безопасный чекпоинт и только потом останавливается, поэтому статус какое-то время держится на «Отменяется».

Продолжить можно только CSV и только из статуса «Отменён»: кнопка «Продолжить загрузку» возобновляет чтение с последнего сохранённого чекпоинта, а карточка показывает, сколько строк уже надёжно принято. Для Amplitude и ClickHouse продолжения нет — создайте задачу заново.

Повторная загрузка и дубли

Продолжение отменённой CSV-задачи дублей не создаёт: чтение возобновляется с сохранённого чекпоинта, а строки из окна между чекпоинтом и остановкой получают те же идентификаторы событий, поэтому повторно не записываются.

А вот новая задача по тому же файлу создаёт вторую копию событий. Ключа идемпотентности на уровне файла или задачи нет, и продукт не сравнивает содержимое новой загрузки с уже принятой историей. Отсюда рабочий порядок:

  1. Проверьте маленький срез.
  2. Загрузите полный файл одной задачей.
  3. Если задача упала на середине — не запускайте её заново «на всякий случай». Сначала посмотрите в отчётах или в SQL-консоли, что уже попало в проект, и грузите только недостающий диапазон.

Своя колонка идентификатора события есть только у загрузки из ClickHouse; в маппинге CSV такой роли нет. Но и указанный event_id не спасает от повторной загрузки: защита от дублей действует внутри задачи, а не между задачами.

Перед загрузкой

  • Убедитесь, что user_id в истории тот же, что вы отправляете сейчас. Иначе один человек разделится на двух, и удержание посчитается неверно.
  • Приведите имена событий к ^[a-z0-9_.]{1,128}$ заранее, особенно для CSV.
  • Не кладите персональные данные в свойства — приём вырезает то, что распознал как персональные данные и как секрет, но полагаться на это как на политику нельзя. См. приватность.
  • Помните про порядок: события, загруженные историей, получают ваше event_time, но время приёма у них — момент загрузки. Выгрузки событий фильтруются по времени приёма, см. выгрузки.
  • После загрузки откройте проверку интеграции и сверьте, что имена событий совпали с теми, что приходят из живого потока.