Рубрики
Uncategorized

Публикация метрик приложений в CloudWatch с использованием микрометра

Наблюдение является важным качественным атрибутом. Реестр Micrometer Cloudwatch Exports Meters Meter в виде метрик CloudWatch. Tagged с AWS, DevOps, Kotlin, Cloud.

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

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

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

Микрометр является фасадом метриков применения, нейтрального, для JVM, который можно использовать для сбора специфических метрик применения. Это немного похоже на SLF4J Но для метрик.

В этом сообщении мы рассмотрим, как публиковать метрики приложений в AWS CloudWatch с использованием Micrometer. Остальная часть поста структурирована следующим образом. Сначала мы представим несколько ключевых концепций микрометра. В следующем разделе перечислены все счетчики, которые доступны из коробки. После этого мы собираемся подробно объяснить, как публиковать метрики в CloudWatch, используя реестр метров CloudWatch. Мы закрываем пост, суммируя основные выводы и обсуждаем некоторые проблемы, с которыми мы сталкивались.

Все примеры кода написаны в Котлине.

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

В зависимости от реализации реестра значения счетчика экспортируются на внешнюю метрическую систему, такую как Permotheus ( PROMOTHEUSETERREGISTION ) или Графит ( graphitemeterregistry ). Самый базовый реестр измерителей — это Simplemeterregistry который имеет последнее значение каждого метра в памяти.

Хотя в микрометре есть более продвинутые концепции, счетчики и реестры — все, что вам нужно знать, чтобы начать. Затем давайте посмотрим на счетчики, которые доступны из коробки в микрометре.

Основные счетчики

Прилавок

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

val counter = Metrics.counter("api.errors")
counter.increment()

Таймер

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

val timer = Metrics.timer("api.request")
timer.record(Duration.ofMillis(1234))

Timer API также имеет методы, которые принимают аргумент функции. Затем микрометр выполнит функцию и измеряет время, наконец, вернет результат. Если вы хотите измерить время самостоятельно, вы можете просто записать вычисленную продолжительность в конце, как это сделано в коде выше.

Измерять

Датчики используются для сообщения о числовом состоянии в определенное время. В отличие от счетчика, который вы можете увеличить, датчик наблюдает за состоянием объекта и сообщает о текущем состоянии всякий раз, когда метрика экспортируется. Общим примером является количество сообщений в очереди или количество соединений в вашем пуле соединений. Следующий фрагмент кода создает датчик, который контролирует размер очереди.

val queue = Metrics.gauge(
    "queue.size",
    ArrayBlockingQueue(10),
    { it.size.toDouble() }
)

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

Резюме распределения

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

val summary = Metrics.summary("request.payload.size")
summary.record(120.0)

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

Продвинутые метры

Длинный таймер задачи

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

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

Длинные таймеры задач построены в качестве обычных таймеров:

val timer = Metrics.more().longTaskTimer("job.duration")

Функциональный счетчик

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

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

val cache: LoadingCache = TODO()
Metrics.more().counter(
    "cache.evictions", // name
    emptyList(),       // tags
    cache,             // object
    { it.stats().evictionCount().toDouble() } // count function
)

Функциональный таймер

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

val cache: LoadingCache = TODO()
Metrics.more().timer(
    "cache.get.latency", // name
    emptyList(),         // tags
    cache,               // object
    { it.stats().loadCount() },                // count function
    { it.stats().totalLoadTime().toDouble() }, // time function
    TimeUnit.NANOSECONDS // time unit
)

Время

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

val value = Metrics.more().timeGauge(
    "custom.timeGauge",
    emptyList(),
    AtomicInteger(5),
    TimeUnit.SECONDS,
    { it.toDouble() }
)

После того, как вы выяснили, какие показатели приложений вас интересуют, и знаете, как выразить их с точки зрения счетчиков, вы можете зарегистрировать эти счетчики в реестрах, которые вы хотите использовать. В этом разделе объясняется, как использовать реестр CloudWatch Microtometry, чтобы экспортировать ваши метрики в AWS CloudWatch.

Сейчас мы не будем подробно рассказывать о терминологии CloudWatch Metrics. Не стесняйтесь проверить мои другие посты мониторинга AWS Lambda с CloudWatch для получения дополнительной информации о концепциях метрик CloudWatch.

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

Во -первых, вам необходимо добавить реестр в качестве зависимости вашего проекта. Доступны два модуля: Micrometer-Rude-Cloudwatch и Micrometer-Registry-Cloudwatch2 Анкет Единственное отличие состоит в том, что первый использует AWS Java SDK версии 1, а последняя использует версию 2. Рекомендуется использовать версию 2.

Чтобы создать новый реестр, вам сначала нужно создать CloudWatchConfig Анкет Поскольку реестр Cloudwatch является Оттехойрегистика , CloudWatchConfig Унаследованы от Stepconfig интерфейс. Реестр шаг -метра публикует метрики в предварительно определенных интервалах (шаги) и нормализует значения метрики для каждого шага, например Складывая индивидуальные счетчики.

В дополнение к параметрам конфигурации, доступных для каждого реестра шагов, конфигурация CloudWatch требует указания пространства имен для публикации метрик. Следующий фрагмент создает новую конфигурацию CloudWatch, которая публикует все метрики для Компания/приложение Пространство имен каждую минуту.

val config = object : CloudWatchConfig {
    private val configuration = mapOf(
        "cloudwatch.namespace" to "Company/App",
        "cloudwatch.step" to Duration.ofMinutes(1).toString()
    )

    override fun get(key: String): String? =
        configuration[key]
}

Затем мы создаем реестр счетчиков, предоставив конфигурацию, часы и асинхронное клиент CloudWatch.

val registry = CloudWatchMeterRegistry(
  config,
  Clock.SYSTEM,
  CloudWatchAsyncClient.create()
)

Затем мы можем либо добавить реестр в синглтон микрометра, используя Metrics.addregistry (реестр) , или зарегистрировать новые счетчики напрямую.

Регистрация счетчиков

Зарегистрировать новые счетчики легко. Вы можете использовать заводские методы, предоставленные Global Метрики Singleton (если вы добавили реестр Cloudwatch ранее) или те, которые предоставляются непосредственно в реестре. Примеры измерителя предыдущего раздела были созданы таким образом. Для большей гибкости вы можете использовать сборщики счетчиков и позвонить в регистр Метод в конце.

На каждом этапе реестр CloudWatch будет собирать данные для всех зарегистрированных счетчиков и соответствующим образом публикует метрики CloudWatch. Эти показатели будут опубликованы в пространстве имен, указанном в конфигурации реестра. Измерения метрики напрямую получены из метра.

Количество показателей, опубликованных на метр, и их имена зависят от типа метра. Название каждой метрики создается путем объединения префикса и суффикса имени. Префикс всегда установлен на имя счетчика. Суффикс зависит от значения, которое представлено этой метрикой.

Например, счетчик излучает только одну метрику, которая представляет счет, но длинный таймер задачи излучает продолжительность задачи, а также количество активных задач. Следующая таблица иллюстрирует различные показатели (представленные их суффиксами), которые испускаются для соответствующего метра.

Прилавок считать
Таймер сумма, граф, AVG, макс.
Измерять ценность
Резюме распределения сумма, граф, AVG, макс.
Длинный таймер задачи ActiveTasks, продолжительность
Функциональный счетчик считать
Функциональный таймер граф, Avg
Время ценность

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

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

Благодаря реестру метров CloudWatch мы можем экспортировать значения счетчика в качестве метрик CloudWatch. Конфигурация проста, но мы также столкнулись с двумя проблемами. Сначала у нас была проблема, что через некоторое время мы получили много Java.io. IoException с Оказывается, есть Известная проблема где CloudWatch просит клиента закрыть соединение, и по какой -то причине Java SDK игнорирует этот запрос и пытается продолжать его повторно использовать.

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

Однако проблема в том, что время, после чего TimeWindowMax Забывает, что значение не синхронизируется с временем шага реестра. Если вы настраиваете время шага в 100 секунд, но ваши максимальные распады через 10 секунд вы по сути теряете 90% ваших данных. Это также означает, что если у вас очень мало продолжительности, максимум может показать даже 0, хотя были записаны продолжительность.

Это особенно странно, потому что другие показатели, такие как средняя продолжительность, рассчитываются на основе всех зарегистрированных продолжительности между двумя шагами. Может быть, мы не используем API правильно, но это выглядит как недостаток дизайна для нас. Если у кого -то есть предложение, как решить эту проблему, сообщите нам об этом в комментариях ниже!

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

Оригинал: «https://dev.to/frosnerd/publishing-application-metrics-to-cloudwatch-using-micrometer-343f»