Выражение метрик

Материал из Документация Ключ-АСТРОМ
Версия от 13:28, 10 октября 2022; ENetrebin (обсуждение | вклад) (→‎Разрешение выражений)
(разн.) ← Предыдущая | Текущая версия (разн.) | Следующая → (разн.)

Выражения метрик позволяют использовать простые арифметические операции прямо в селекторе метрик.

Например, это выражение вычисляет соотношение (в процентах) двух показателей:

metric1 / metric2 * 100

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

  • Вам нужно использовать скобки, чтобы обеспечить порядок операций.
  • Все метрики с более чем 1 точкой данных, участвующей в выражении метрики, должны иметь одинаковое разрешение.
  • В качестве операнда можно использовать любую метрику, в том числе метрику, модифицированную любой цепочкой преобразования , и можно применять преобразования к результату выражения.

Ограничения

  • Селектор должен содержать хотя бы один ключ метрики.
  • Вы можете запрашивать точки данных до 10 метрик в одном запросе.

Для целей этого ограничения одно выражение (например, metric2 + metric2) считается одной метрикой.

Приоритет

Применяются стандартные правила математического приоритета:

  1. Скобки, метрические преобразования
  2. Отрицание
  3. Умножение, деление
  4. Сложение, вычитание

Агрегация

Если агрегация была применена в цепочке преобразования, используется эта агрегация. Если преобразование не применялось, используется агрегация по умолчанию. Ваши метрические операнды могут быть разных агрегатов. Например, metric:max - metric:min.

Разрешение выражений

Метрические выражения разрешаются следующим образом:

  1. Сформируйте пары записей для каждой пары метрик.
  2. Выровняйте точки данных в каждой записи.
  3. Примените арифметическую операцию к выровненным точкам данных.

Записи

В арифметических операциях используются точки данных записей (уникальные комбинации метрика-измерение-значение измерения) метрик. Идентичные кортежи каждой метрики объединяются в пары, а затем их точки данных выравниваются.

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

Непарные записей игнорируются выражением и не представлены в результате.

Точки данных

После формирования пар записей точки данных выравниваются, а затем к выровненным точкам данных применяется желаемая арифметическая операция.

  • Если какая-либо из выровненных точек данных равна null, выражение преобразуется в null.
  • Если в операции задействовано число, оно выравнивается с каждой точкой данных метрического операнда.
  • Если одна метрика представляет собой одну точку данных, а другая представляет собой ряд, одна точка данных выравнивается с каждой точкой данных ряда.
  • Если обе метрики представляют собой одну точку данных, точки данных выравниваются, и результирующий временной интервал охватывает обе точки данных.
  • Если обе метрики являются сериями, точки данных выравниваются по отметкам времени.

Для любых невыровненных точек данных выражение разрешается в null.

Лучшие практики

Используйте только при необходимости

Используйте метрическое выражение только в том случае, если вы не можете достичь своей цели без него. Допустим, вы хотите рассчитать среднее использование ЦП двумя хостами HOST-001и HOST-002. Вы можете сделать это с помощью метрического выражения:

(
    builtin:host.cpu.usage:filter(eq("dt.entity.host","HOST-001")):splitBy()
    +
    builtin:host.cpu.usage:filter(eq("dt.entity.host","HOST-002")):splitBy()
)
/2

При таком подходе есть две проблемы. Во-первых, выражение трудно читать и, следовательно, подвержено синтаксическим ошибкам. Во-вторых, если один из хостов находится в автономном режиме, результат выражения будет пустым. Несмотря на то, что вторая проблема может быть решена с помощью преобразования по умолчанию , использование средней агрегации более эффективно:

builtin:host.cpu.usage
:filter(
    or(
        eq("dt.entity.host","HOST-001"),
        eq("dt.entity.host","HOST-002")
    )
)
:splitBy()
:avg

Не конвертировать единицы

Не используйте метрическое выражение для преобразования единиц измерения данных. Вместо этого используйте преобразование toUnit . Единственным исключением из этого правила являются устройства, которые Ключ-АСТРОМ не поддерживает. Используйте запрос GET для всех единиц , чтобы получить список поддерживаемых единиц.

Ограничить использование преобразований

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

Рассмотрим следующий запрос, который пытается добавить 10 самых популярных периодов использования ЦП к 10 основным периодам простоя ЦП.

builtin:host.cpu.usage:sort(value(avg,descending)):limit(10)
+
builtin:host.cpu.idle:sort(value(avg,descending)):limit(10)

Если у вас большая среда с сотнями хостов, маловероятно, что 10 хостов с максимальной загрузкой ЦП входят в число 10 хостов с наибольшим временем простоя ЦП. У операндов не будет совпадающих записей, поэтому результат выражения будет пустым. Решение состоит в том, чтобы вместо этого применить ограничение к результату выражения:

(
    builtin:host.cpu.usage
    +
    builtin:host.cpu.idle
)
:sort(value(auto,descending))
:limit(10)

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

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

Рассмотрим этот пример выражения соотношения, где мы вычисляем коэффициент ошибок для ключевых действий пользователя:

builtin:apps.other.keyUserActions.reportedErrorCount.os
/
builtin:apps.other.keyUserActions.requestCount.os

Если запросов много, но ни одной ошибки на вашем таймфрейме, результат будет пустым, хотя коэффициент ошибок 0был бы более значимым. Вы можете добиться этого с помощью default(0)преобразования:

builtin:apps.other.keyUserActions.reportedErrorCount.os:default(0)
/
builtin:apps.other.keyUserActions.requestCount.os

Примеры

Пример 1. Построение метрики соотношения

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

  • builtin:service.errors.total.count показывает количество ошибок любого типа в службе
  • builtin:service.errors.server.successCount показывает количество вызовов без ошибок на стороне сервера

Из них мы можем построить метрику коэффициента ошибок:

builtin:service.errors.total.count:value:default(0)
/
(
    builtin:service.errors.total.successCount:value:default(0)
    +
    builtin:service.errors.total.count:value:default(0)
)

Преобразование по умолчанию используется для замены значений временных интервалов, имеющих значение null0.

Метрика 1:

{
  "totalCount": 3,
  "nextPageKey": null,
  "result": [
    {
      "metricId": "builtin:service.errors.total.count",
      "data": [
        {
          "dimensions": ["SERVICE-B82BFBCB4E264A98"],
          "dimensionMap": {
            "dt.entity.service": "SERVICE-B82BFBCB4E264A98"
          },
          "timestamps": [1619913600000, 1620086400000, 1620259200000],
          "values": [48763, 81283, 80798]
        },
        {
          "dimensions": ["SERVICE-BE8B6928C46204B5"],
          "dimensionMap": {
            "dt.entity.service": "SERVICE-BE8B6928C46204B5"
          },
          "timestamps": [1619913600000, 1620086400000, 1620259200000],
          "values": [1096, 1124, 1095]
        }
      ]
    }
  ]
}

Метрика 2:

{
  "totalCount": 3,
  "nextPageKey": null,
  "result": [
    {
      "metricId": "builtin:service.errors.total.successCount",
      "data": [
        {
          "dimensions": ["SERVICE-B82BFBCB4E264A98"],
          "dimensionMap": {
            "dt.entity.service": "SERVICE-B82BFBCB4E264A98"
          },
          "timestamps": [1619913600000, 1620086400000, 1620259200000],
          "values": [46182, 77110, 76736]
        },
        {
          "dimensions": ["SERVICE-BE8B6928C46204B5"],
          "dimensionMap": {
            "dt.entity.service": "SERVICE-BE8B6928C46204B5"
          },
          "timestamps": [1619913600000, 1620086400000, 1620259200000],
          "values": [0, 0, 0]
        }
      ]
    }
  ]
}

Результат:

{
  "totalCount": 3,
  "nextPageKey": null,
  "result": [
    {
      "metricId": "builtin:service.errors.total.count/(builtin:service.errors.total.count+builtin:service.errors.total.successCount)",
      "data": [
        {
          "dimensions": ["SERVICE-B82BFBCB4E264A98"],
          "dimensionMap": {
            "dt.entity.service": "SERVICE-B82BFBCB4E264A98"
          },
          "timestamps": [1619913600000, 1620086400000, 1620259200000],
          "values": [0.513592079625046, 0.513172930621934, 0.5128924549621035]
        },
        {
          "dimensions": ["SERVICE-BE8B6928C46204B5"],
          "dimensionMap": {
            "dt.entity.service": "SERVICE-BE8B6928C46204B5"
          },
          "timestamps": [1619913600000, 1620086400000, 1620259200000],
          "values": [1, 1, 1]
        }
      ]
    }
  ]
}

Пример 2. Вклад одного сервиса в общее количество ошибок

Встроенная метрика :service.errors.total.count показывает количество ошибок в ваших службах. Список может быть длинным, и вас может заинтересовать вклад каждой службы в количество ошибок. Эту информацию может предоставить комбинация метрических преобразований и метрических выражений.

Вам нужны эти преобразования:

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

Затем используйте это выражение:

builtin:service.errors.total.count:filter(eq("dt.entity.service","SERVICE-B82BFBCB4E264A98")):value:default(0)
/
builtin:service.errors.total.count:splitBy():value:default(0) * 100

Преобразование по умолчанию используется для замены значений временных интервалов, имеющих значение null0.

Изолированный серсис:

{
  "totalCount": 1,
  "nextPageKey": null,
  "result": [
    {
      "metricId": "builtin:service.errors.total.count:filter(eq(\"dt.entity.service\",SERVICE-B82BFBCB4E264A98))",
      "data": [
        {
          "dimensions": ["SERVICE-B82BFBCB4E264A98"],
          "dimensionMap": {
            "dt.entity.service": "SERVICE-B82BFBCB4E264A98"
          },
          "timestamps": [1619913600000, 1620086400000, 1620259200000],
          "values": [48763, 81283, 80798]
        }
      ]
    }
  ]
}

Общее количество:

{
  "totalCount": 1,
  "nextPageKey": null,
  "result": [
    {
      "metricId": "builtin:service.errors.total.count:splitBy()",
      "data": [
        {
          "dimensions": [],
          "dimensionMap": {},
          "timestamps": [1619913600000, 1620086400000, 1620259200000],
          "values": [49882, 82425, 81911]
        }
      ]
    }
  ]
}

Процент:

{
  "totalCount": 1,
  "nextPageKey": null,
  "result": [
    {
      "metricId": "builtin:service.errors.total.count:filter(eq(\"dt.entity.service\",SERVICE-B82BFBCB4E264A98))/builtin:service.errors.total.count:splitBy()*100",
      "data": [
        {
          "dimensions": ["SERVICE-B82BFBCB4E264A98"],
          "dimensionMap": {
            "dt.entity.service": "SERVICE-B82BFBCB4E264A98"
          },
          "timestamps": [1619913600000, 1620086400000, 1620259200000],
          "values": [97.75670582574877, 98.61449802851077, 98.64120814054277]
        }
      ]
    }
  ]
}

Пример 3. Средняя продолжительность GC

Встроенная метрика : tech.jvm.memory.gc.collectionTime показывает общую продолжительность всех сборок мусора во временном интервале. Информация об отдельных сборках мусора недоступна, но мы можем использовать встроенную метрику: tech.jvm.memory.pool.collectionCount , показывающую количество сборок мусора за раз, чтобы получить среднюю продолжительность сборки мусора.

Прежде чем мы начнем расчет, нам нужно выровнять измерения обеих метрик. Для этого нам нужно применить разделение по преобразованию с dt.entity.process_group_instanceаргументом к встроенной метрике: tech.jvm.memory.pool.collectionCount .

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

(
builtin:tech.jvm.memory.gc.collectionTime
/
builtin:tech.jvm.memory.pool.collectionCount:splitBy("dt.entity.process_group_instance")
):sort(value(max,descending))

Общее время GS

{
  "totalCount": 3,
  "nextPageKey": null,
  "result": [
    {
      "metricId": "builtin:tech.jvm.memory.gc.collectionTime",
      "data": [
        {
          "dimensions": ["PROCESS_GROUP_INSTANCE-18A5241823ABC769"],
          "dimensionMap": {
            "dt.entity.process_group_instance": "PROCESS_GROUP_INSTANCE-18A5241823ABC769"
          },
          "timestamps": [1619913600000, 1620086400000, 1620259200000],
          "values": [164670, 171630, 163044]
        },
        {
          "dimensions": ["PROCESS_GROUP_INSTANCE-92605BB8AE962F1C"],
          "dimensionMap": {
            "dt.entity.process_group_instance": "PROCESS_GROUP_INSTANCE-92605BB8AE962F1C"
          },
          "timestamps": [1619913600000, 1620086400000, 1620259200000],
          "values": [6883411, 5977311, 6356225]
        },
        {
          "dimensions": ["PROCESS_GROUP_INSTANCE-4285F2EF6B79E8A9"],
          "dimensionMap": {
            "dt.entity.process_group_instance": "PROCESS_GROUP_INSTANCE-4285F2EF6B79E8A9"
          },
          "timestamps": [1619913600000, 1620086400000, 1620259200000],
          "values": [163368, 162924, 170502]
        }
      ]
    }
  ]
}

Номер GS:

{
  "totalCount": 3,
  "nextPageKey": null,
  "result": [
    {
      "metricId": "builtin:tech.jvm.memory.pool.collectionCount:splitBy(\"dt.entity.process_group_instance\")",
      "data": [
        {
          "dimensions": ["PROCESS_GROUP_INSTANCE-18A5241823ABC769"],
          "dimensionMap": {
            "dt.entity.process_group_instance": "PROCESS_GROUP_INSTANCE-18A5241823ABC769"
          },
          "timestamps": [1619913600000, 1620086400000, 1620259200000],
          "values": [1727814, 1720686, 1691604]
        },
        {
          "dimensions": ["PROCESS_GROUP_INSTANCE-92605BB8AE962F1C"],
          "dimensionMap": {
            "dt.entity.process_group_instance": "PROCESS_GROUP_INSTANCE-92605BB8AE962F1C"
          },
          "timestamps": [1619913600000, 1620086400000, 1620259200000],
          "values": [31363, 30588, 31419.5]
        },
        {
          "dimensions": ["PROCESS_GROUP_INSTANCE-4285F2EF6B79E8A9"],
          "dimensionMap": {
            "dt.entity.process_group_instance": "PROCESS_GROUP_INSTANCE-4285F2EF6B79E8A9"
          },
          "timestamps": [1619913600000, 1620086400000, 1620259200000],
          "values": [1697262, 1703742, 1722612]
        }
      ]
    }
  ]
}

Средняя продолжительность GC:

{
  "totalCount": 3,
  "nextPageKey": null,
  "result": [
    {
      "metricId": "(builtin:tech.jvm.memory.gc.collectionTime/builtin:tech.jvm.memory.pool.collectionCount:splitBy(\"dt.entity.process_group_instance\")):sort(value(max,descending))",
      "data": [
        {
          "dimensions": ["PROCESS_GROUP_INSTANCE-92605BB8AE962F1C"],
          "dimensionMap": {
            "dt.entity.process_group_instance": "PROCESS_GROUP_INSTANCE-92605BB8AE962F1C"
          },
          "timestamps": [1619913600000, 1620086400000, 1620259200000],
          "values": [219.47552848898383, 195.41359356610437, 202.3019144162065]
        },
        {
          "dimensions": ["PROCESS_GROUP_INSTANCE-18A5241823ABC769"],
          "dimensionMap": {
            "dt.entity.process_group_instance": "PROCESS_GROUP_INSTANCE-18A5241823ABC769"
          },
          "timestamps": [1619913600000, 1620086400000, 1620259200000],
          "values": [0.09530539745597616, 0.09974510166294141, 0.09638426014599162]
        },
        {
          "dimensions": ["PROCESS_GROUP_INSTANCE-4285F2EF6B79E8A9"],
          "dimensionMap": {
            "dt.entity.process_group_instance": "PROCESS_GROUP_INSTANCE-4285F2EF6B79E8A9"
          },
          "timestamps": [1619913600000, 1620086400000, 1620259200000],
          "values": [0.09625384884596486, 0.09562715481569392, 0.09897876016189368]
        }
      ]
    }
  ]
}