Введение
Архитектура
Обработка входящих запросов
Коммуникация сервисов
Руководство пользователя
Получение данных из сервисов
Использование Панели управления
Туториалы
Получение данных из других сервисов
Построение истории отдельного пользователя
Классические модели атрибуции
Вероятностное прохождение воронки
Атрибуция по индексу активности
Воронки
X
Выберите раздел

Конфигурация сервиса

Конфигурация сервиса — это YAML-файлы в папке config/. Их читает класс AppConfig из rock-me-ts: собирает все файлы, прогоняет через шаблонизатор EJS, склеивает документы и отдаёт сервису один объект с типизированным доступом к секциям.

Как загружается

  1. dotenv читает .env, затем .env.local (значения из него перекрывают .env). Оба файла нужны только для локального запуска, в Docker переменные задаются окружением контейнера.
  2. По маске config/**/*.yml собираются все файлы, включая вложенные папки вроде config/custom/. Порядок не сортируется, поэтому файлы принято нумеровать: 02_config.yml, 11_clickhouse_struct.yml, custom/14_rst.yml.
  3. Содержимое всех файлов склеивается в один текст и рендерится EJS. В шаблонах доступны: env (переменные окружения), pkg (содержимое package.json), envName (dev, stage или production) и consts.
  4. Результат читается как многодокументный YAML и глубоко сливается слева направо: что встретилось позже, перекрывает более раннее. Массивы заменяются целиком.
  5. Из итогового объекта вынимаются секции dev и prod, и поверх общей части накладывается одна из них в зависимости от NODE_ENV (production или prod — секция prod, иначе dev).

Так в chwriter базовая схема таблиц лежит в config/11_clickhouse_struct.yml, а дополнительные колонки под конкретную инсталляцию — в config/custom/*.yml, которые просто добавляют ключи в ту же секцию clickhouse.tables.

Стандартные секции

Их ждёт фреймворк, они есть в каждом сервисе:

---
title: Rockstat kafka streamer
version: "<%= pkg.version %>"

rpc:
  name: kafkastream          # имя сервиса = имя прямого канала в Redis
  listen_all: true
  listen_direct: true

log:
  use: pino
  pino:
    safe: true
    level: <%= env.LOG_LEVEL || 'info' %>
    prettyPrint: false

redis:
  dsn: <%= env.REDIS_DSN %>

metrics:
  statsd:
    host: <%= env.STATSD_HOST || '127.0.0.1' %>
    port: 8125
    debug: false
    prefix: krn
СекцияДоступ в кодеНазначение
rpcconfig.rpcname — имя сервиса; service_group — группа для обогатителей; channels — список каналов; listen_all, listen_direct — флаги для AppRunner
logconfig.logнастройки pino: level, name, safe
redisconfig.redisdsn вида redis://host:6379/0
metricsconfig.meterstatsd — хост, порт, префикс метрик; без секции метрики просто не отправляются

Поле rpc.channels из конфигурации имеет приоритет над списком каналов, собранным в коде: в AppServer опции RPC формируются как { channels, ...config.rpc }, и значение из YAML перекрывает channels. Так mmgeo задаёт каналы прямо в конфигурации.

Своя секция

Настройки сервиса кладите в отдельную секцию с его именем и опишите её тип в src/types.ts. AppConfig параметризуется этим типом, и config.get('kafkastream') возвращает типизированный объект:

kafkastream:
  clientId: "rst-kafkastream"
  brokers: [<%= env.KAFKA_BROKERS || '' %>]
  ssl: false
  mappings:
    - ['in.gen.track.ping', null]
    - ['in.gen.track.', [rstat.web, uid]]
// src/types.ts
export type KafkaConfig = {
  clientId: string;
  brokers: Array<string>;
  ssl?: boolean;
  mappings: Array<[string, [string, string] | null]>;
};

export type ModuleConfig = {
  name: string;
  kafkastream: KafkaConfig;
};
const config = new AppConfig<ModuleConfig>();
const options = config.get('kafkastream');   // KafkaConfig

Секции dev: и prod: позволяют держать разные значения для окружений в одном файле:

clickhouse:
  uploadInterval: 2

dev:
  clickhouse:
    uploadInterval: 1

Переменные окружения

Фреймворк и сервисы читают переменные напрямую или через шаблоны конфигурации:

ПеременнаяКто читаетЗначение
NODE_ENVAppConfigproduction включает секцию prod, всё остальное — dev
REDIS_DSNконфигурацияадрес Redis, в Docker по умолчанию redis://redis:6379
LOG_LEVELконфигурацияуровень pino: debug, info, warn
STATSD_HOSTконфигурацияхост StatsD, по умолчанию 127.0.0.1
TZNode.jsвсегда UTC: даты событий считаются в UTC
DATACENTER_ID, WORKER_IDTheIdsчасти snowflake-идентификатора, по умолчанию 1 и 1
SERVICE_GROUPmmgeoгруппа обогатителя, ключ его результата в событии

Локальный .env обычно выглядит так:

TZ=UTC
LOG_LEVEL=debug
REDIS_DSN=redis://127.0.0.1:6379/0
STATSD_HOST=127.0.0.1

Секреты (DSN с паролем, SASL для Kafka) не пишите в YAML. Подставляйте их из окружения через <%= env.NAME %>, а в репозитории держите только .env с локальными значениями без паролей.

Несколько экземпляров одного сервиса

Если сервис запускается в нескольких копиях, каждой нужно своё имя, иначе они будут отвечать на одни и те же прямые запросы. mmgeo собирает имя из группы и номера воркера:

rpc:
  service_group: <%= env.SERVICE_GROUP || 'unknown_enrich' %>
  name: <%= env.SERVICE_GROUP || 'unknown_enrich' %>_<%= env.WORKER_ID || '1' %>
  channels:
    - enrich
    - <%= env.SERVICE_GROUP || 'unknown_enrich' %>_<%= env.WORKER_ID || '1' %>

Так же устроен Front: его экземпляры называются front_1, front_2 и так далее.