Many-to-many matching not allowed в PromQL: как сопоставить серии
На dashboard нужно показать скорость запросов вместе с командой, отвечающей за сервис. Первая метрика содержит запросы по экземплярам, вторая — справочные labels. Умножение через on(service) group_left(team) заканчивается ошибкой many-to-many. Добавление ещё одного модификатора обычно не помогает: сначала придётся понять, какие строки должны соответствовать друг другу.
PromQL выполняет арифметическую операцию между временными сериями. Для каждой серии слева нужно найти подходящую справа. По умолчанию сопоставление учитывает labels, а on задаёт выбранный набор ключей. Если выбран слишком короткий ключ, несколько разных объектов оказываются неразличимыми.
Посмотрим на обе стороны отдельно
Пусть слева находятся скорости запросов с labels cluster, service, instance. Справа — service_owner_info со значением 1 и labels cluster, service, team. Имя сервиса повторяется в разных кластерах. Соединение только по service объединяет разные окружения в одну группу и теряет необходимое различие.
count by (service) (service_owner_info)
count by (cluster, service) (service_owner_info)
Первая проверка может показать 2, вторая — по единице для каждого кластера. Это указывает на недостаточный ключ. Если и вторая возвращает значения больше единицы, разберите конкретные labels справочной метрики: возможно, её собирают с двух targets или для сервиса одновременно объявлены две команды.
Количество проверяется на том же времени, где ломается исходный запрос. Дубли могли существовать только во время выкладки, поэтому успешная проверка сейчас не опровергает вчерашнюю ошибку. Зафиксируйте момент и сравнивайте обе стороны именно на нём.
Выберем направление связи
sum by (cluster, service) (
rate(http_requests_total[5m])
)
* on (cluster, service) group_left(team)
service_owner_info
В этом варианте запросы уже объединены по сервису. Справочная сторона должна давать ровно одну строку на cluster и service. Значение 1 сохраняет скорость при умножении, а label team добавляется в результат. Если справочник содержит 2 вместо 1, скорость тоже удвоится: название info само по себе арифметику не меняет.
Если оставить слева отдельные instance, допустимо несколько левых серий на одну правую. Для этого и существует group_left. Он разрешает связь many-to-one; уникальность правой стороны по выбранному ключу всё равно обязательна. Модификатор не выбирает случайную команду из двух возможных.
Когда допустима предварительная агрегация
Иногда справочная серия дублируется только из-за двух одинаковых источников. Если после проверки подтверждено, что cluster, service и team описывают один объект и каждое значение равно единице, дубли можно свернуть:
max by (cluster, service, team) (service_owner_info)
Но две разные команды останутся двумя строками. Это полезно: конфликт владельцев требует решения в источнике данных. Удаление team из агрегации может заставить запрос вычисляться, одновременно скрыв причину и потеряв label, ради которого затевалось соединение.
Есть другая ловушка: серия, не нашедшая пару, исчезает из арифметического результата. Поэтому после исправления ошибки сравните число сервисов до и после соединения. Если справочник не содержит новый сервис, общий график может молча показывать меньше трафика. Это отдельная проблема полноты, которую отсутствие many-to-many не решает.
Подтвердим смысл результата
Выберите один сервис и сравните значение до соединения и после него. При справочном множителе 1 числа должны совпасть, а team — появиться. Затем повторите на двух кластерах с одинаковым service. Такой пример проверяет и сохранность значения, и полноту ключа.
Рабочее соединение начинается с определения объекта: сервис в конкретном кластере, запрос определённого метода или экземпляр приложения. Когда этот объект выражен labels однозначно, выбор on, ignoring и группировки становится следствием модели данных, а не поиском комбинации, которая убирает сообщение об ошибке.
Ещё по теме
- P95 в Prometheus: как считать задержку по histogram и не усреднять процентили
- Scrape timeout в Prometheus: как различить медленный exporter и проблему сети
Продолжить изучение
Хотите построить мониторинг, который помогает находить причины сбоев? Метрики, дашборды и оповещения входят в программу «Prometheus и Grafana: мониторинг и observability».
Продолжить на практике
- Prometheus и Grafana: мониторинг и observability ↗
Замечайте сбои до жалоб пользователей. Соберите мониторинг приложения: метрики Prometheus, запросы PromQL, дашборды Grafana и алерты, по которым понятно, что делать. Итог — наблюдаемый сервис и разбор учебного инцидента.
