Meltano → PostgreSQL → Superset

Meltano → PostgreSQL → Superset

Полностью self-host стек на 100 % open-source (обновлено 19 июня 2025 г.)


1. Почему именно эта связка

«Свобода, братцы, свобода!» Когда нужно выкачать сотни тысяч сделок из Bitrix24 и не платить ни Zapier, ни Albato, ни Fivetran, на сцену выходит Meltano — «оркестратор Singer-коннекторов в Docker-оболочке».

  • tap-bitrix24 (Singer) инкрементально читает crm.deal, crm.contact, tasks.task, не нарушая лимит 2 запроса/сек: Meltano ставит back-off и чекпоинты.
  • Postgres 16 служит «зоной стейджа» и витринами одновременно — без «двойной записи».
  • Superset 5.1 перехватывает таблицы, строит графики и отправляет алёрты — всё в браузере и без Pro-лицензий.

Что получаем:

Боль Как лечит связка
Платные SaaS-ETL «кушают» бюджет Meltano + Singer → 0 ₽
Сырые CSV «тонут» в папках Заливаем сразу в Postgres
Нужен self-service BI Superset строит живые дашборды

2. Компоненты и роли

Компонент Роль Ответственный
Bitrix24 Источник CRM-данных CRM-админ
tap-bitrix24 Singer-коннектор (Python) Data Engineer
Meltano 3.0 Orchestration + ELT CLI DevOps
PostgreSQL 16 DWH: raw + marts DBA
Superset 5.1 Self-service BI + RLS BI-аналитик
(опция) Power BI Презентации для CEO BI-аналитик

3. Подготовка окружения

3.1 Что установить

Что Где взять
Meltano 3.0 CLI meltano.com/docs
tap-bitrix24 pip install git+https://github.com/<fork>/tap-bitrix24.git
PostgreSQL 16 postgresql.org/download
Superset 5.1 (Docker) superset.apache.org

3.2 Docker-compose (dev)

version: "3.9"
services:
  meltano:
    image: meltano/meltano:latest
    volumes:
      - ./meltano:/project
    command: ["meltano", "ui"]
    ports: ["5000:5000"]

  postgres:
    image: postgres:16
    environment:
      POSTGRES_USER: etl
      POSTGRES_PASSWORD: etl_pwd
      POSTGRES_DB: datamart
    ports: ["5432:5432"]

  superset:
    image: apache/superset:5.1
    env_file: superset.env
    depends_on: [postgres]
    ports: ["8088:8088"]

Запускаем:

docker compose up -d

4. Настройка потоков данных

4.1 Инициализация проекта Meltano

meltano init b24_project
cd b24_project
meltano add loader target-postgres
meltano add extractor tap-bitrix24

meltano.yml (фрагмент):

plugins:
  extractors:
  - name: tap-bitrix24
    variant: custom
    pip_url: git+https://github.com/yourorg/tap-bitrix24.git
    config:
      base_url: https://yourportal.bitrix24.ru/rest/
      token: XXXXXXXX
      start_date: 2024-01-01T00:00:00Z
      streams: ["crm.deal", "crm.contact"]
      replication_method: INCREMENTAL
      user_agent: meltano-tap
  loaders:
  - name: target-postgres
    variant: transferwise
    pip_url: pipelinewise-target-postgres~=1.0
    config:
      host: postgres
      port: 5432
      user: etl
      password: etl_pwd
      dbname: datamart
      default_target_schema: stage
      preserve_csv_files: false

4.2 Запуск инкремента + расписание

# Первичная загрузка
meltano run tap-bitrix24 target-postgres

# Планировщик (внутренний)
meltano schedule add nightly_sync \
  tap-bitrix24 target-postgres \
  "@hourly"

Meltano сохранит STATE-файл (.meltano/state.json) — следующий запуск возьмёт только записи с новым DATE_MODIFY.

4.3 Проверяем в Postgres

SELECT COUNT(*) FROM stage."crm_deal";
CREATE INDEX IF NOT EXISTS ix_deal_updated ON stage."crm_deal"(updated_at DESC);

5. Трансформации и моделирование

5.1 Пример представления

CREATE SCHEMA stg;

CREATE OR REPLACE VIEW stg.deal AS
SELECT
    id::bigint,
    title,
    stage_id,
    (data->>'OPPORTUNITY')::numeric(14,2) AS amount,
    (data->>'ASSIGNED_BY_ID')::bigint      AS manager_id,
    updated_at
FROM stage."crm_deal";

5.2 Агрегат

CREATE SCHEMA mart;

CREATE MATERIALIZED VIEW mart.deal_monthly AS
SELECT
    date_trunc('month', updated_at)::date AS month,
    stage_id,
    COUNT(*)                              AS deals_cnt,
    SUM(amount)                           AS pipeline
FROM stg.deal
GROUP BY 1,2;

CREATE UNIQUE INDEX ON mart.deal_monthly(month, stage_id);

Refresh по крону:

psql -c "REFRESH MATERIALIZED VIEW CONCURRENTLY mart.deal_monthly;"

6. Визуализация в Power BI и Superset

6.1 Superset

  1. Databasepostgresql://superset:pwd@postgres:5432/datamart
  2. Datasetsmart.deal_monthly
  3. Chart → Time Series Bar
  4. Dashboard → KPI-карточка + линейный график

Row-level-security:

CREATE POLICY p_manager
ON stg.deal
USING (manager_id = current_setting('superset.user_id')::bigint);

6.2 Power BI (если нужно .pbix)

  1. Get Data → PostgreSQL (SSL)
  2. DirectQuery при объёме < 1 M строк
  3. Incremental Refresh: поле updated_at

7. Мониторинг и автоматизация

Объект Инструмент Порог
Meltano job logs meltano ui → Runs error > 0
Singer taps lag state.json diff отставание > 1 ч
Postgres bloat pg_stat_user_tables bloat > 20 %
Superset health /health endpoint latency > 500 мс
Backups pg_dump nightly пропуск > 1 сутки

8. Типичные ошибки и лайфхаки

Ошибка / вопрос Быстрое решение
tap-bitrix24 падает 429 Уменьшите RECORDS_PER_REQUEST до 25 и REQUEST_DELAY = 0.6 с
Таблицы с кавычками ("crm_deal") Создайте VIEW без кавычек — Superset не любит mixed-case
Meltano run «раскочегарил» CPU Поставьте --transform=flattening_skip и дайте --jobs 1 – один процесс
Superset не видит новые схемы Settings → Database → Sync metadata
STATE потерялся после перезапуска Храните .meltano/state.json в S3 или Git – meltano умеет state set/get

9. Заключение

Плюсы

  • 100 % open-source: нет подписок, нет vendor-lock.
  • Инкременты Singer → минимальный трафик и WAL.
  • Superset 5.1 подключается «одной строкой» и даёт RLS, алёрты, дашборды.

Минусы

  • tap-bitrix24 ещё молод: новые поля требуют форка.
  • Нет GUI для трансформаций — нужны SQL-скиллы.
  • При > 5 М строк/день Postgres потребует партиционирования.
Читай также:  RudderStack OSS → PostgreSQL → Power BI

Когда масштабировать?

  • 10 М строк/сутки — реплика в ClickHouse или TimescaleDB.

  • < 60 с lag — Kafka Connect вместо HTTP-пула.
  • CI/CD — подключить GitHub Actions + dbt Core.

Полезные ссылки

Теперь у вас нет SaaS-счётов, нет секретов за границей — только чистый open-source стек, который вы контролируете полностью. Настройте ⎯ и данные будут работать на вас, пока вы пьёте утренний раф.