Перейти к содержанию

Создание метрик

Одним из преимуществ Trisigma является наличие продвинутой системы расчета метрик и их разрезов. Эта система обеспечивает порядок и единообразие расчетов и интерпретации метрик на уровне всей компании, предотвращая ситуации, где два человека внутри одной компании могут посчитать одну и ту же метрику по-разному. Порядок определяется стандартизированной процедурой заведения метрик в систему. Об этой системе мы поговорим подробнее ниже.

Шаг 1. Получить доступ к репозиторию метрик#

О том, как его создать и как с ним работать, читайте здесь.

В репозитории, к которому вы получили доступ, лежат три папки: sources, metrics и dimensions. Рассмотрим подробнее их содержимое.

Image title

Папка sources#

Папка sources — это папка, в которой необходимо определить источники, из которых в дальнейшем мы будем считать метрики. Внутри этой папки:

  1. Папка sql: содержит все SQL-запросы для формирования источников расчета метрик.
  2. YAML файл: здесь описаны параметры источника данных, который определен в папке sql.

📌 Важно отметить, что в процессе интеграции команда Trisigma помогает с настройкой интеграции с DWH, поэтому от клиента требуется только правильно указать название источника и таблицы.

Папка metrics#

Папка metrics — это папка, в которой необходимо описать YAML файл для расчета метрик. Каждый YAML файл в этой папке содержит набор метрик, которые считаются на одном источнике.

Метрики внутри каждого YAML файла бывают трех типов. Каждый тип записывается в отдельном блоке файла:

metric.counter Простые каунтеры.#

Каунтеры — это тип метрик, которые получаются путем фильтрации нужных строк и сложения по выбранному полю. Можно перечислить несколько полей (столбцов), тогда все они будут сложены друг с другом.

Аргументы:

  • filter: условие, фильтрующее нужные строки перед тем, как их сложить. Синтаксис описан в Таблице 1 ниже.
  • obs: колонка (или список), значения которой нужно складывать. Если не указана, то подставляется 1 (по сути, будет считаться количество строк).

Таблица 1. Синтаксис формирования метрики-каунтера

(где a — имя поля, к которому применяется какая-то операция)

Оператор Примеры Аналог в SQL (Trino)
<=, >=, <, >, =, != a.>=: 1, a.!= 1 a >= 1, a <> 1
like, !like a.like: 'доставка', a.!like: 'доставка' a like 'доставка', a not like 'доставка'
ilike, !ilike a.ilike: 'доставка', a.!ilike: 'доставка' a ilike 'доставка', a not ilike 'доставка'
bit, !bit a.bit: 3, a.!bit: 3 bitwise_and(a, 3) > 0, bitwise_and(a, 3) = 0
in, !in a.in: [1, 2, 3], a.!in: [4, 5, 6] a in (1, 2, 3), a not in (4, 5, 6)

Условие в фильтре имеет формат ключ-значение. Ключом является имя столбца в источнике. В поле obs указываются столбцы, которые нужно сложить. Например, метрику с конфигом phone_views: {filter: [eid: 303], obs: [events_count]} в SQL можно вычислить как select sum(events_count) as phone_views from source where eid = 303.

Особенности синтаксиса:

  • К столбцам в фильтре можно применять операторы. Оператор применяется через точку, например filter_name.>: 30. Выбранный для фильтрации оператор, таким образом, всегда окружен точкой слева и двоеточием справа, после которого идет значение, по которому фильтруем.
  • Можно также сделать условие со сравнением колонок по типу col1.>: $col2, где доллар позволяет ссылаться на другое поле в пределах одного source.
  • В случае необходимости сложения нескольких полей (столбов) синтаксис выглядит как obs: [А, Б, С], что соответствует логике (сумма по полю А) + (сумма по полю Б) + (сумма по полю С).

❗️YAML файлы имеют преимущества, которые можно использовать при заведении метрик. Так, в YAML можно определять выражения вверху файла и использовать ссылки на эти выражения через символ &.

Пример:

Заведение метрики example_premium_user_payments

Без использования возможностей YAML:

metric.counter:
    example_premium_user_payments: {
        filter: [is_premium_user: true, event_id.in: [55, 57, 67]],
        obs: []
    } 

С использованием возможностей YAML:

definitions:
- &is_premium_user
    {is_premium_user: true}
- &payment_evnts
    {event_id.in: [55, 57, 67]}

metric.counter:
example_premium_user_payments:
    filter: [*is_premium_user, *payment_evnts]
    obs: []

Есть также ключевые слова $and, $or, которые позволяют писать более сложные конструкции. Например, если мы хотим фильтровать ИЛИ премиум пользователей, ИЛИ тех, кто совершили оплату, синтаксис будет следующий:

definitions:
  - &is_premium_user
      {is_premium_user: true}
  - &payment_evnts
      {event_id.in: [55, 57, 67]}

metric.counter:
  example_premium_user_payments:
    filter:
      [$or: [*is_premium_user, *payment_evnts]]
    obs: []

metric.uniq Уникальные.#

Уникальные — это тип метрик, которые считают уникальные ключи (уникальных пользователей, события и т.д.).

Аргументы:

  • counter: имя каунтера из первого блока (metric.counter). Обязательное поле.
  • key: колонка, уникальные значения которой мы считаем. Может быть составным ключом, и все перечисленные в этом поле колонки будут использованы для сбора хэша. По сути является сокращённым способом записи для key_seq, состоящего из одного уровня группировки. Обязательное поле.
  • key_seq: иерархия колонок, по которым по порядку будут проверяться threshold и выполняться группировки (см. пример ниже).
  • thresholds: пороги, по которым учитываем уникальные значения при условии sum(counter) > threshold. Если не указан, то 0.

Пример:

Пример использования key_seq:

Допустим, что мы хотим завести метрику, которая будет считать количество премиум-пользователей, совершивших более 10 оплат (example_prem_user_10plus_payments). Она будет считаться так же, как метрика количество премиум-пользователей, совершивших оплату (example_premium_user_payments), но с применением порога по числу оплат (>10).

example_prem_user_10plus_payments: 
    {   
        counter: example_premium_user_payments, 
        key_seq: [user_id, event_id], 
        thresholds: [10, 0]
    }

В данном случае будет выполняться следующий запрос:

SELECT SUM(CASE WHEN payments > 0 THEN 1 END) AS num  -- посчитали юзеров, тут не нужен трешхолд
FROM (
    SELECT user_id,
        SUM(CASE WHEN payments > 10 THEN 1 END) AS payments  -- посчитали число оплат на каждого юзера, проверили трешхолд в 10 оплат
    FROM (
        SELECT user_id,
            event_id,
            COUNT(*) AS payments  -- сгруппировали по юзеру и типу оплаты, посчитали, сколько было оплат каждого типа (event_id), трешхолд не проверяем
        FROM example_table
        GROUP BY user_id, event_id
    ) AS temp1
    GROUP BY user_id
) AS temp2

❗️ metric.uniq имеют особенности расчета: ключ считается как уникальный только в рамках одного дня. Например, если user_id — это ключ, и мы хотим посчитать метрику "число заходов в приложение" по этому ключу, то если пользователь зашел 5 раз в течение одного дня, число заходов в приложение по ключу user_id посчитается как 1. Если пользователь заходил по одному разу в день в течение 5 дней, то число заходов в приложение посчитается как 5.

metric.ratio Метрики отношения.#

Это метрики, представляющие собой отношение каких-то других величин. Например, можно рассчитать соотношение: CR в добавление в корзину/CR в добавление в заказ. Оба аргумента — ссылки на существующие метрики (имена метрик) из пп. 1-2.

Аргументы:

  • num: числитель. Обязательное поле.
  • den: знаменатель. Обязательное поле.

❗️Числитель и знаменатель ratio-метрики могут быть прописаны в любом файле, даже если у них разные источники. Это возможно, потому что ratio метрики состоят из метрик, расчет которых вы уже объявили заранее, и программа знает, как посчитать числитель и знаменатель, независимо от того, в каком YAML файле они находятся.

💡 Мы рекомендуем прописывать ratio-метрику в том конфиге, где содержится числитель.

Папка dimensions#

dimensions (разрезы) — это папка, предназначение которой напоминает справочник. В ней необходимо определить разрезы, которые могут быть у метрики (например, регион, категория товара, сегмент пользователей) и описать, как эти разрезы читать в отчете. Внутри этой папки:

  • Папка sql: здесь находятся SQL-скрипты, "справочники", которые содержат поля-маппинги для описания dimensions.

    В этих скриптах описывается, какие значения соответствуют ключам (value_id), а какие — значениям (value). Например, region_id — это value_id, а region — это value.

    Описав таким образом регион, мы передаем алгоритму информацию о том, как нужно читать id регионов для дальнейшего использования, например, в отчетах по А/В тестам (если там будет использован данный разрез).

  • YAML файл: здесь описаны параметры каждого dimension, который определен в папке dimensions/sql.

Новые dimensions заводятся для того, чтобы иметь возможность добавлять их в слайсы (брейкдауны) в отчетах по АБ тестам в Trisigma.

📌 Важно отметить, что заводить dimensions нужно относительно редко. Один и тот же dimension можно использовать для тысяч метрик. Главное — проверить, что у источника в source.yaml, на котором вы строите метрику, есть нужное поле для создания dimension.

Шаг 2. Определяем источники данных#

Для определения источника нам необходимо:

  1. Написать SQL-запрос, который сформирует таблицу со всеми необходимыми для расчета метрик и разрезов полями.
  2. Сохранить этот SQL-запрос в файл с расширением .sql.
  3. Поместить файл с расширением .sql в папку sources/sql.
  4. Описать параметры источника в файле sources.yaml.
  5. Сохранить изменения.

❗️SQL-запрос должен содержать параметры :first_date и :last_date (эти параметры определяют период, за который будет рассчитана метрика. Подробнее здесь).

Как описывать поля в YAML файле?

Необходимо указать следующие параметры:

  • sql — имя файла с SQL-кодом источника. Обязательное поле.
  • dimensions — список дименшенов (ключи из dimensions.yaml), которые есть в источнике.
  • participant — маппинг, какой столбец отвечает за visitor, а какой за user (обычно cookie_id и user_id). Обязательное поле, если метрика будет использоваться в А/В тестах (отвечает за единицу рандомизации в эксперименте).
  • primary_subject — по какому participant распараллеливать вычисления метрики. Обычно это user, если он есть. Обязательное поле (в будущих релизах поле будет упразднено).
  • dtm — колонка с датой/таймстампом. Обязательное поле.

💡 При первичной настройке источников мы рекомендуем ответить на вопрос: "Из какой таблицы в нашей инфраструктуре данных мы сможем посчитать наибольшее количество полезных метрик?" Если у вас есть такая таблица, заведите её в папку sources самой первой простым запросом через select * from ваша_таблица (не забывая про :first_date и :last_date). Это позволит вам быстро и эффективно начать обогащать Trisigma метриками, не тратя время на создание большого количества источников.

❗️ Один источник может иметь только один primary_subject, то есть данные для расчета разных метрик на одном источнике всегда будут считаться по одному primary_subject. Если один и тот же источник необходимо посчитать с разными primary_subject, нужно завести отдельные источники под разные primary_subject.

Шаг 3. Создаем метрику#

Для создания метрики необходимо:

  1. Создать YAML файл в котором будут находиться метрики, привязанные к одному источнику данных (см. рисунок 1).
  2. Связать YAML файл с источником данных Для этого в конфиге источника (в sources.yaml) укажите имя созданного YAML файла с метрикой в поле metric_configs.
  3. Определить тип метрики которую вы хотите создать (metric.counter, metric.uniq или metric.ratio).
  4. Определить поля и фильтры по которым метрика будет считаться.
  5. Написать YAML конфиг для данной метрики, используя описанный выше синтаксис.
  6. Сохранить изменения

📌 Важно отметить, что на один источник можно создавать несколько YAML файлов с метриками. В таком случае в YAML конфиге источника необходимо добавлять имена зависящих от него YAML файлов с метриками через запятую в поле metric_configs, например: metric_configs: [metric_config1, metric_config2, metric_config3].

💡 Мы рекомендуем заранее договориться внутри вашей компании о системе нейминга метрик, если сейчас такой системы нет. С ростом количества метрик ориентироваться в них будет все сложнее. Прозрачная система нейминга поможет упростить поиск метрик и навигацию по ним.

Шаг 4. Создаем Dimension#

Для создания dimensions (разрезов) метрики необходимо:

  1. Написать SQL-запрос, который сформирует таблицу с маппингами <dimension_name>_id → dimension_name.
  2. Переименовать <dimension_name>_id в value_id и dimension_name в value. Это важно, так как Trisigma распознает только value_id и value как допустимые имена полей для dimension.
  3. Сохранить этот SQL-запрос в файл с расширением .sql.
  4. Поместить файл с расширением .sql в папку dimensions/sql.
  5. Описать файл с SQL-запросом** в файле dimensions.yaml.

❗️Если поле для создания dimension не имеет вид <dimension_name>_id, то SQL-запрос может выгружать единственное поле, которое будет содержать все значения dimension_name.

❗️Не забывайте переименовывать поля в value и value_id.

Пример:

SELECT  segment_id AS value_id,     -- <dimension_name>_id
        segment AS value            -- dimension_name
FROM    dict.segments_df

Как описывать поля в YAML файле?

  • has_id — в источниках dimension представлен в виде id, столбец имеет имя <dimension_name>_id.
  • is_bool — уточнение того, является ли dimension булевым. В таком случае dimension не требуется YAML-справочник.
  • parent — слаг parent dimension, если есть.
  • description — краткое описание dimension.
  • slug — сокращенное имя dimension, то, как имя dimension будет отображаться в отчете по результатам А/В теста (например, logical_categoryslug: logcat).

Шаг 5. Создаем PR и мерджим ветку с новой метрикой#

  1. Создаем PR.
  2. Делаем доработки
  3. Пушим изменения
  4. Билд валидации запустится автоматически
  5. Результат работы билда отобразится в комментариях PR
  6. В случае успеха введите команду run merge

Это последний шаг по заведению метрик. После успешного создания метрики и мерджа, на странице метрики в Trisigma можно увидеть сгенерированный SQL и проверить логику расчета.

Cheat Sheet: связь между конфигами#

В процессе заведения метрик необходимо не забывать возвращаться к source файлу и устанавливать с ним связи из конфигов метрик или разрезов. Чтобы не запутаться, пользуйтесь схемой ниже.

Image title

Мастер-класс по заведению метрик#

В этом разделе мы решим практическую задачу по заведению метрики example_premium_user_payments_u: количество уникальных премиум-пользователей, совершивших оплату.

  1. Заводим источник

    Напишем SQL запрос и положим его в папку sources/sql.

    Файл с этим запросом назовем example_source.sql:

    SELECT event_date, 
        cookie_id, 
        user_id, 
        event_id,
        is_premium_user, 
        device_type
    FROM dwh.clickstream_events
    WHERE event_date :: date BETWEEN :first_date AND :last_date
    

    Опишем источник в YAML конфиге sources.yaml:

    example_source:  # называем также, как SQL, чтобы не запутаться
        metric_configs: 
            - example_config_clickstream_evnts
        sql: example_source
        dimensions: 
            - device_type
        participant: 
            user: user_id
            visitor: cookie_id
        primary_subject: user
        dtm: event_date
    

    📌 Все поля из source не обязательно описывать в конфиге. Какая-то часть полей может быть использована для расчета метрик или разрезов, но не быть описанной в конфиге источника.

  2. Заводим метрику example_premium_user_payments_u

    Создадим файл example_config_clickstream_evnts.yaml в папке metrics, где будут описаны все метрики, рассчитанные по источнику example_source:

    metric.counter:
        example_premium_user_payments: 
            filter: 
                - is_premium_user: true
                - event_id.in: 
                    - 55
                    - 57
                    - 67
            obs: []
    
    metric.uniq:
        example_premium_user_payments_u: 
            counter: example_premium_user_payments
            key: 
                - user  # не user_id, а user
    
    В этом конфиге сначала создается метрика counter, которая отбирает только премиум клиентов, которые совершили оплату (event_id = 55, 57 или 67 это ID совершения оплаты). Параметр obs не заполняется в данном кейсе, поэтому для метрики посчитается число строк в отфильтрованной таблице. Далее со ссылкой на counter создается uniq метрика, где уникализация (count distinct) будет происходить по user.

    ❗️ Проверяем, что в конфиге источника, по которому будет рассчитываться наша метрика example_premium_user_payments_u, в поле metric_configs вписано название конфига метрик, которые будут рассчитываться на этом источнике.

  3. Заводим dimensions Допустим, мы хотим, чтобы для нашей метрики можно было смотреть отчет с разрезами по device_type. Напишем SQL запрос и положим его в папку dimensions/sql. Файл с этим запросом назовем device_type.sql:

    SELECT device_type AS value
    FROM dict.device_types
    
    Внесем описание этого dimension в YAML конфиг со всеми существующими dimensions:
    device_type: 
        description: "Тип устройства, с которого была произведена оплата"
    
    has_id не заполняем, поскольку в источниках dimension имеет имя device_type, а не представлен в виде <dimension_name>_id.

    ❗️ Проверяем, что в конфиге источника, по которому будет рассчитываться наша метрика example_premium_user_payments_u, в поле dimensions вписан dimension - device_type.

  4. Создаем PR и мерджим ветку с новой метрикой по инструкции выше.

  5. Смотрим сгенерированный SQL и проверяем логику расчета на странице метрики в Trisigma. Готово!

Ответы на популярные вопросы#

  1. Как часто будут обновляться данные по метрикам?

    Данные отчета обновляются раз в 24 часа.

  2. Зачем нужны параметры :first_date и :last_date?

    Эти параметры нужны для того, чтобы более эффективно отфильтровать данные при выполнении SQL-запросов. Конфиг источников метрик уже содержит информацию о том, какая колонка отвечает за дату, и фильтр по дате применяется следующим образом:

    SELECT ...
    FROM ( {{ source_sql }} ) 
    WHERE date_col BETWEEN :first_date AND :last_date
    
    Однако compute движок (например, Trino) не всегда эффективно применяет этот фильтр, что может привести к чтению избыточного количества данных из хранилища. Использование параметров first_date и last_date прямо внутри SQL источника позволяет разместить фильтры в любом месте запроса. Это особенно актуально для сложных SQL запросов, включающих вложенные запросы, группировки и т.д.

  3. Что делать, если при заведении источника/метрики/разреза произошла ошибка?

    Попробуйте исправить ошибку самостоятельно: внимательно прочитайте текст ошибки в комментарии к PR и исправьте ее. Если не удается решить проблему, обратитесь в чат, где обсуждали интеграцию, или напишите на почту contact@trisigma.io.