DropWizard Metrics Счетчики и таймеры

Я изучаю библиотеку метрик DropWizard (ранее метрики Coda Hale), и я сбит с толку когда я должен использовать Meters против Timers. Согласно документам:

Счетчик. Счетчик измеряет скорость, с которой происходит набор событий.

а также:

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

Основываясь на этих определениях, я не могу увидеть разницу между ними. Что меня смущает, так это то, что Timer используется не так, как я ожидал. Для меня Timer — это просто таймер; он должен измерять разницу во времени между start() и stop(). Но похоже, что Timers также фиксирует скорость, с которой происходят события, что похоже на то, что они наступают Meters на пальцы ног.

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


person smeeb    schedule 22.06.2015    source источник


Ответы (1)


Вы частично сбиты с толку, потому что таймер DW Metrics ЯВЛЯЕТСЯ, среди прочего, счетчиком DW Metrics.

Измеритель касается исключительно скоростей, измеряемых в Гц (событий в секунду). Каждый измеритель приводит к публикации 4 (?) различных показателей:

  • средняя (средняя) ставка с момента запуска Метрики
  • 1-, 5- и 15-минутные скорости скользящего среднего

Вы используете измеритель, записывая значение в разных точках вашего кода — DW Metrics автоматически записывает время каждого звонка вместе с заданным вами значением и использует их для расчета скорости, с которой это значение увеличивается:

Meter getRequests = registry.meter("some-operation.operations")
getRequests.mark() //resets the value, e.g. sets it to 0
int numberOfOps = doSomeNumberOfOperations() //takes 10 seconds, returns 333
getRequests.mark(numberOfOps) //sets the value to number of ops.

Мы ожидаем, что наши частоты будут 33,3 Гц, так как было выполнено 333 операции, а время между двумя вызовами mark() составляло 10 секунд.

Timer вычисляет эти 4 метрики (считая каждый Timer.Context одним событием) и добавляет к ним ряд дополнительных метрик:

  • подсчет количества событий
  • минимальная, средняя и максимальная продолжительность с момента запуска метрик
  • среднеквадратичное отклонение
  • гистограмма, фиксирующая продолжительность, распределенную по 50-му, 97-му, 98-му, 99-му и 99,95 процентилю

Для каждого таймера сообщается около 15 общих показателей.

Короче говоря: таймеры сообщают о МНОЖЕСТВЕ метрик, и их может быть сложно понять, но как только вы это сделаете, они станут довольно мощным способом обнаружения скачкообразного поведения.


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

Timer timer = registry.timer("costly-operation.service-time")
Timer.Context context = timer.time()
costlyOperation() //service time 10 ms
context.stop()

Предположим, что costlyOperation() имеет постоянную стоимость, постоянную нагрузку и работает в одном потоке. В течение 1-минутного отчетного периода мы должны рассчитывать время этой операции 6000 раз. Очевидно, что мы не будем сообщать о фактическом времени обслуживания по сети 6000x — вместо этого нам нужен какой-то способ суммировать все эти операции, чтобы соответствовать нашему желаемому окну отчетности. Таймер DW Metrics делает это за нас автоматически раз в минуту (наш отчетный период). Через 5 минут наш реестр показателей будет сообщать:

  • скорость 100 (событий в секунду)
  • 1-минутная средняя скорость 100
  • 5-минутная средняя скорость 100
  • количество 30000 (всего просмотренных событий)
  • максимум 10 (мс)
  • мин 10
  • в среднем 10
  • значение 50-го процентиля (p50) равное 10
  • 99,9-й процентиль (p999) значение 10

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

Timer timer = registry.timer("costly-operation.service-time")
Timer.Context context = timer.time()
costlyOperation() //takes 10 ms usually, but once every 1000 times spikes to 1000 ms
context.stop()

Теперь за 1-минутный период сбора мы увидим менее 6000 выполнений, так как каждое 1000-е выполнение занимает больше времени. Получается около 5505. После первой минуты (всего 6 минут системного времени) мы увидим:

  • средняя скорость 98 (событий в секунду)
  • средняя скорость за 1 минуту 91,75
  • 5-минутная средняя скорость 98,35
  • количество 35505 (всего просмотренных событий)
  • максимальная продолжительность 1000 (мс)
  • мин продолжительность 10
  • средняя продолжительность 10,13
  • значение 50-го процентиля (p50) равное 10
  • 99,9-й процентиль (p999) значение 1000

Если вы посмотрите на график, вы увидите, что большинство запросов (p50, p75, p99 и т. д.) выполнялись за 10 мс, но один запрос из 1000 (p99) выполнялся за 1 с. Это также будет рассматриваться как небольшое снижение средней скорости (около 2%) и значительное снижение среднего значения за 1 минуту (почти 9%).

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

person Matthew Mark Miller    schedule 24.06.2015
comment
Хорошая дополнительная информация содержится здесь. Таймеры по умолчанию используют экспоненциально затухающий резервуар. Это означает, что вы видите данные примерно за последние 5 минут с уклоном в сторону более новых данных для ваших значений гистограммы. - person markdsievers; 09.02.2016
comment
Есть ли способ получить время выполнения каждый раз, когда запускается блок кода? Мне это нужно помимо средних ставок, средних ставок и прочего. Это возможно? - person AnOldSoul; 26.08.2016
comment
Если вы просто хотите измерять и сообщать о времени обслуживания для каждого выполнения блока кода, это не совсем то, для чего предназначена библиотека агрегации метрик. Резервуар, в котором хранятся метрики по мере их возникновения, скорее всего, не сохраняет достаточно контекста для ваших нужд. К счастью, это проблема, которую вы можете легко решить с помощью простого ведения журнала или инструментального инструментария для виртуальных машин, такого как YourKit. - person Matthew Mark Miller; 07.09.2016
comment
Таким образом, это по существу означает, что если я аннотирую свой метод с помощью @Timed , аннотирование его также с помощью @Metered является избыточным, потому что @Timed все равно будет делать то, что @Metered делает? - person Chirag; 22.03.2018
comment
@MatthewMarkMiller Но как я могу получить время выполнения AVG в мс, измеренное таймером, например, за последние 1/5/15 минут, поскольку я вижу, что таймер является единственным хранилищем «Среднего» значения, которое собирает статистику для всего жизненного цикла приложения и также он хранит скорости 1/5/15 минут, но они показывают некоторую частоту (скорость выполнения в секунду), а не время AVG. Допустим, за последние 5 минут у меня было 3 вставки БД с продолжительностью выполнения 1 мс/2 мс/3 мс. Таким образом, AVG будет 2 мс. Как я могу получить эту статистику с помощью таймера? - person MeetJoeBlack; 11.07.2018
comment
К сожалению, нет встроенного счетчика для того, что вы просите. Метрики p_XX (которые представляют собой скользящую медиану, взвешенную по самым последним значениям) — ваш лучший вариант. В вашем примере p_50 сообщит о 2 мс, а p_75,95,99 и т. д. сообщит о 3 мс, а std_dev — 1 мс. Этого было бы достаточно, чтобы понять, что большинство вызовов были менее 2 мс и ни один вызов не превышал 3 мс. - person Matthew Mark Miller; 11.07.2018
comment
Я не уверен, дают ли 1 мин и 5 мин скользящую среднюю скорость. В их документации указано Returns the five-minute exponentially-weighted moving average rate at which events have occurred since the meter was created. - person L. Dai; 25.03.2019