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

Как спроектировать метрику

Подумайте, как и для чего вы будете пользоваться метрикой. Узнайте, как реализовать эти требования в StatsHouse:

Затем создайте метрику и начинайте отправлять данные.

Что представляют собой метрики в StatsHouse?

Под "мониторингом" мы понимаем получение статистических данных. Метрика — это минимальная единица настройки, сбора и просмотра статистики.

Структура метрики в StatsHouse выглядит так:

Здесь counter, value и unique — это основные типы метрик.

important

StatsHouse не хранит точное значение метрики за каждый момент времени. Вместо этого в системе хранятся агрегаты, относящиеся к временным интервалам.

Типы метрик

Одно и то же можно измерить по-разному. Разные способы измерений — это и есть типы метрик.

Определения и примеры можно посмотреть в таблице:

Тип метрикиЧто она измеряет?Примеры
counterПодсчитывает, сколько раз произошло то или иное событие.Количество вызовов методов API
Количество запросов к серверу
Количество ошибок, полученных при отправке сообщений
valueИзмеряет величину какого-либо параметра.
Также подсчитывается количество измерений.
Как долго сервис генерирует ленту новостей?
Какова загрузка процессора на этом хосте?
Каков размер ответа (в байтах)?
uniqueПодсчитывает количество уникальных событий.
Также подсчитывается общее количество событий.
Количество уникальных пользователей, отправивших пакеты в сервис
important

Тип метрики влияет на то, какие описательные статистики доступны и имеют смысл для метрики. Например, перцентили доступны только для value-метрик. А накопленные значения нельзя посмотреть для типа unique.

Узнайте, как включить запись перцентилей и настроить отображение описательных статистик в интерфейсе.

note

Не путайте типы метрик с типами данных в языках программирования.

Детали реализации

Метрики типа counter (счётчик) и value (значение) являются числами типа float64. Для counter и value StatsHouse обрезает всё, что выходит за пределы диапазона [-max(float32)..max(float32)]. Это сделано для того, чтобы при суммировании и других операциях над ними, в том числе внутри базы данных, никогда не получать значения, равные бесконечности.

Счётчики (тип counter)

Представьте себе гипотетический продукт. Для него нам нужно получить количество принятых пакетов в секунду. Пакеты могут иметь различные форматы и статусы.

Когда приложение получает пакет, оно отправляет событие в StatsHouse:

{"metrics":[ {"name": "toy_packets_count",
"tags":{"format": "JSON", "status": "ok"},
"counter": 1}] }

или

{"metrics":[ {"name": "toy_packets_count",
"tags":{"format": "TL", "status": "error_too_short"},
"counter": 1} ]}

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

timestampmetricformatstatuscounter
13:45:05toy_packets_countJSONok100
13:45:05toy_packets_countTLok200
13:45:05toy_packets_countTLerror_too_short5

Количество рядов в такой таблице - это кардинальность метрики.

Значения (тип value)

Предположим, нам нужно знать размер полученных пакетов. Вот как может выглядеть наша метрика:

{"metrics":[ {"name": "toy_packets_size",
"tags":{"format": "JSON", "status": "ok"},
"value": [150]} ]}

или

{"metrics":[ {"name": "toy_packets_size",
"tags":{"format": "JSON", "status": "error_too_short"},
"value": [0]} ]}

Для метрик с типом value помимо счётчика StatsHouse вычисляет агрегат: sum, min, max.

timestampmetricformatstatuscountersumminmax
13:45:05toy_packets_sizeJSONok10013000201200
13:45:05toy_packets_sizeTLok20070004800
13:45:05toy_packets_sizeTLerror_too_short51008

Метрика этого типа является массивом, так что можно отправлять несколько значений одновременно.

Приём регулярных значений

Для случаев, когда требуется записывать значение в секунду (т. е. отслеживать "уровень" какого-то показателя), клиентские библиотеки StatsHouse стараются отправлять каждое значение в середине календарной секунды. Агенты определяют секунду в соответствии с календарной секундой. StatsHouse не гарантирует, что каждая секунда содержит ровно одно измерение, но старается сделать вероятность этого максимальной. Если вы хотите отправлять значения именно так, укажите метку времени явным образом.

Счётчики уникальных значений (тип unique)

Этот тип метрики позволяет оценить число разных уникальных целых значений. Для строковых значений используется хеш строк.

Предположим: мы получаем пакеты, содержащие идентификаторы отправителей. Мы можем подсчитать, сколько существует разных отправителей:

{"metrics":[ {"name": "toy_packets_user",
"tags":{"format": "JSON", "status": "ok"},
"unique": [17]} ]}

Метрика этого типа является массивом, так что можно отправлять несколько значений одновременно.

timestampmetricformatstatuscounterunique
13:45:05toy_packets_userJSONok100uniq(17, 19, 13, 15)
13:45:05toy_packets_userTLok200uniq(17, 19, 13, 15, 11)
13:45:05toy_packets_userTLerror_too_short5uniq(51)

Множества хранятся в сжатом виде. StatsHouse использует функцию наподобие HyperLogLog: сами значения недоступны, поэтому можно узнать только оценку кардинальности множеств.

Для счётчиков уникальных значений StatsHouse хранит агрегаты: sum, min, max (те же, что и для метрик-значений, интерпретированных как int64 и округленных до float64). Знание диапазона значений бывает полезно для отладки.

Детали реализации

Счётчики уникальных значений имеют тип int64, который интерпретируется как 64 бита. Этот тип выбран вместо uint64 потому, что в некоторых языках нет uint64. Эти значения рассматриваются как хеши. При оценке кардинальности множеств, составленных из этих значений, StatsHouse проверяет их на равенство и неравенство.

При записи агрегатов (sum, min, max) StatsHouse сначала интерпретирует эти значения как int64 и затем конвертирует их в тип float64 — они пишутся в те же колонки, что и агрегаты обычных значений.

Как сочетаются типы метрик

В таблице показано, как значения разных типов сочетаются в рамках одной метрики:

Что вы отправитеЧто вы получите
"counter":100counter
"value":[1, 2, 3]counter (размер массива), value (sum, min, max)
"unique":[17, 25, 37]counter (размер массива), value (sum, min, max), unique
"counter":6, "value":[1, 2, 3]Пользовательское семплирование
"value":100,"unique":100Такое сочетание недопустимо

Если вы меняете тип существующей метрики, данные могут стать непонятными или неинформативными.

important

Рекомендуем отправлять в метрику данные одного и того же типа.

Счётчики для метрик с типом value и unique

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

Теги

Теги помогают учитывать дополнительные характеристики данных, влияющие факторы или контекст. С помощью тегов можно фильтровать и группировать данные. Иногда их называют лейблами или ключами. Теги — это пары имя—значение.

Представьте, что вы проводите A/B-тест: кнопки с каким сочетанием цвета и текста будут работать эффективнее? Чтобы ответить на этот вопрос, можно измерить количество нажатий на кнопку и использовать такие теги:

Метрики с тегами помогают проверять гипотезы о данных. Можно задавать, например, такие вопросы:

"Различается ли количество ошибок для разных платформ?"

или

"Из какого региона приходит наибольшее количество запросов? Различно ли оно для разных окружений?"

Чтобы ответить на эти вопросы, можно создать следующие метрики (используется клиентская библиотека для Python):

statshouse.value("error_rate", {"platform": "web"}, 42.5)
↑ ↑ ↑ ↑
metric name ↑ ↑ measurement
tag name ↑
tag value

или

statshouse.value("request_rate", {"env": "production", "region": "moscow"}, 42.5)
↑ ↑ ↑ ↑ ↑ ↑
metric name ↑ ↑ ↑ ↑ measurement
tag name ↑ tag name ↑
tag value tag value

Затем можно отфильтровать или сгруппировать данные с помощью тегов. По умолчанию в UI группировка отключена.

Сколько тегов можно использовать?

Для каждой метрики можно использовать 16 тегов:

Тег String top (Топ строк) дополнительный, он ведёт себя не так, как другие:

  • тег __s.

"А если мне нужно больше тегов?"

К сожалению, пока увеличить количество тегов нельзя. Мы планируем добавить такую возможность позже.

Имена тегов

При отправке данных можно использовать системные имена тегов (0..15). Для удобства можно использовать алиасы (пользовательские имена).

Допускаются следующие символы:

  • латинский алфавит,
  • целые числа,
  • подчёркивание.
note

Не начинайте имена тегов с подчёркиваний. Они предназначены для служебных метрик StatsHouse.

Одни и те же имена тегов можно использовать для разных метрик.

В интерфейсе StatsHouse можно редактировать имена тегов и добавлять к ним описания.

Значения тегов

Значения тегов обычно являются строками. Чтобы работать с ними быстрее, StatsHouse отображает их в значения int32. Этот огромный маппинг stringint32 общий для всех метрик. Чтобы не допустить его неконтролируемого увеличения, бюджет на создание значений тегов ограничен. При превышении этого бюджета возникает ошибка типа Mapping flood.

Длина и символы

Значения тегов должны содержать только печатаемые символы UTF-8. Все непечатаемые символы заменяются дорожным знаком.

Максимальная длина значения тега — 128 байтов (остальное обрезается). Также выполнется нормализация: с обеих сторон делается TRIM, все последовательности Unicode-пробелов внутри значения тега заменяются на один ASCII пробел.

Сколько значений тегов можно использовать?

Формального ограничения на количество значений тегов нет, но их должно быть не слишком много.

Бывают теги с большим числом разнообразных значений. Например, вам может быть нужен тег "идентификатор пользователя". Такие теги могут вызывать ошибки типа "mapping flood" или увеличивать семплирование из-за высокой кардинальности.

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

Если у тега слишком много значений, то вскоре они исчерпают бюджет на создание новых значений и будут потеряны (превратятся в пустые строки).

Даже если все значения тегов уже есть в маппинге, и вы избежали ошибок типа "mapping flood", однако продолжаете отправлять данные с большим количеством значений тегов, к вашим данным, вероятно, будет применено семплирование. Семплирование означает, что StatsHouse выбрасывает часть данных, чтобы уменьшить их общий объём. Чтобы сохранить значения агрегатов и статистик, StatsHouse домножает оставшиеся данные на коэффициент семплирования.

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

tip

Если вам нужны теги с большим количеством значений, которые являются 32-битными числами (например, тег user_ID), используйте Raw теги, чтобы избежать ошибок mapping flood.

Если вам нужен тег с разнообразными строковыми значениями (например, тег search_request), используйте тег String top (Топ строк).

"Сырые" (Raw) теги

Если значения тегов изначально являются 32-битными числами, вы можете пометить их как "сырые" (Raw), чтобы избежать переполнения маппинга.

Такие значения тегов (Raw) StatsHouse будет воспринимать как (u)int32 (возможные значения: -2^31..2^32-1) и вставлять в базу ClickHouse, не добавляя в маппинг.

Чтобы не забыть, что означают "сырые" значения тегов, укажите формат, который будет отображаться в интерфейсе, и добавьте комментарии.

Тег String top (Топ строк)

Используйте тег String top (__s), когда вам нужен тег с большим числом строковых значений, например тег referrer или search request.

Используя обычные теги для такого случая, вы очень скоро получите ошибку переполнения маппинга. Тег String top отличается от других тем, что его значения не добавляются в маппинг. Он позволяет избежать переполнения маппинга и роста семплирования.

StatsHouse сохраняет только строки с наиболее часто используемыми значениями тега String top — строки с наибольшим счётчиком. Остальные значения тега String top превращаются в empty и агрегируются. Узнайте больше о том, как работает тег String top.

Чтобы фильтровать данные с помощью тега String top на графике, добавьте ему имя или описание.

Имя хоста как тег

Вам может быть нужно просматривать статистику по отдельным хостам. Часто пользователи хотят использовать имя хоста в качестве тега. Попробуйте вместо этого использовать функцию Max host. Вам не нужно ничего менять в отправляемых данных — просто включите Max host в интерфейсе.

Когда имя хоста используется в качестве тега, данные становится сложно агрегировать. Такие данные приходится сильнее семплировать. Включение Max host не приводит к росту семплирования, но позволяет найти хост, который отправляет максимальное значение для конкретной метрики.

Max host помогает ответить, например, на такие вопросы:

  • "На каком хосте занят максимальный объём дискового пространства?"
  • "На каком хосте количество ошибок заданного типа максимально?"

Агрегируя данные, StatsHouse помещает в отдельную колонку max_host в базе данных имя хоста, который отвечает за отправку максимального значения (для value-метрик) или за максимальный вклад в счётчик (для counter-метрик).

Например, StatsHouse агрегирует ряды от двух агентов:

timestampmetricformatminmaxmax_host
13:45:05toy_latencyJSON2001200nginx001

и

timestampmetricformatminmaxmax_host
13:45:05toy_latencyJSON480nginx003

Максимальное значение toy_latency (равно 1200) связано с хостом nginx001 в получившемся агрегате:

timestampmetricformatminmaxmax_host
13:45:05toy_latencyJSON41200nginx001
Детали реализации

Значение в столбце max_host имеет тип float32, а не float64: это сделано для лучшего сжатия, так как высокая точность здесь не нужна. Имя хоста хранится в маппинге stringint32, как значения тегов.

Иногда вместо тега host_name можно использовать тег environment (или аналогичный): когда вы внедряете функциональность в экспериментальном режиме на одном или нескольких хостах, пометьте их значениями staging или development.

Настройка тега environment

StatsHouse хранит метрики в базе данных ClickHouse: 16 колонок в ней предназначены для тегов. Эти колонки тегов по умолчанию названы системными именами: 1...15.

Вам может быть нужно назвать теги по-своему, например "format" и "status". Можно отредактировать метрику так, чтобы имя "format" относилось к колонке 1, а "status" - к колонке 2. Можно оставить и системные имена 1...15.

Но как обращаться с нулевой колонкой? С помощью неё можно обозначить окружение, например production или staging. Например, если экспериментальная версия программы установлена на нескольких хостах, вы можете связать тег 0 со своим экспериментом. Укажите тег в клиентской библиотеке во время инициализации. В остальном тег 0 похож на другие теги.

Метки времени

Запись актуальных данных является приоритетом для StatsHouse.

important

Исторические данные записываются только для последних полутора часов.

Если метка времени находится в будущем, StatsHouse заменяет ее текущим временем.

Если данные появились раньше, чем полтора часа назад, StatsHouse заменит метку времени на текущее время минус полтора часа.

Если вы используете cron для отправки данных, отправляйте данные раз в час, а не раз в день.

Мы не рекомендуем явно указывать метки времени, поскольку строки с разными метками не получится агрегировать, а это может привести к увеличению семплирования. Кроме того, база данных ClickHouse при вставке исторических данных работает довольно медленно.