SlideShare a Scribd company logo
Что в метриках тебе моих?Что в метриках тебе моих?
О чём могут поведать цифры и графики
в мониторинге и зачем вообще
заморачиваться.
Андрей Новиков
RubyRussia 2018
1
2
3
4
5
6
7
8
Чего мы хотим?Чего мы хотим?
Знать, как быстро растут и разгребаются очереди
Знать, какие задачи наиболее «проблемные»
Понимать, когда это началось и кто виноват
Понимать, помогли ли принятые нами меры
@Envek
9
Чего мы хотим?Чего мы хотим?
Больше метрик
Больше графиков
Ещё больше графиков
… и ещё два монитора
@Envek
10
Недостающие метрикиНедостающие метрики
Время обработки задач
Количество новых задач
@Envek
Недостающие графикиНедостающие графики
Динамика изменения размера очередей по отдельным очередям
Динамика изменения времени выполнения задач по классам
11
Мониторинг веб-приложенияМониторинг веб-приложения
Сервера: загрузка CPU, RAM, IO, LA, заполненность дисков, …
Веб: количество запросов, время их обработки, queueing time, …
Отложенные задачи: количество задач, время их обработки,
количество ошибок, …
Базы данных: количество запросов, время обработки, объём
данных, …
Внешние API: количество запросов, время обработки, ошибки…
Сеть: задержки, DNS lookup time, throughput, потери пакетов, …
Свои показатели: свой набор под каждую интеграцию
Бизнес-метрики: количество пользователей, заказов, , …
@Envek
12
13
А зачем?А зачем?
Чтобы понять, откуда вдруг запахло жареным:
Откуда — какой участок приложения горит.
Вдруг — когда загорелось. 5 минут назад, после
деплоя или медленно, но верно разгоралось по
мере роста сервиса?
Запах — в чём именно проблема? ЦП, память,
внешние сервисы?
@Envek
14
15
16
ТеорияТеория
17
МониторингМониторинг
Непрерывный процесс наблюдения и регистрации параметров системы
в сравнении с заданными критериями
 
«Вы не можете контролировать то, что не можете измерить»
— Том ДеМарко
@Envek
18
МетрикиМетрики
1. Параметры системы
2. Численные значения, полученные при измерении
этих параметров работающей системы
@Envek
19
Временные ряды (time series)Временные ряды (time series)
Значения какой либо величины в порядке времени измерения
Для хранения разработаны специальные базы данных:
InfluxDB, Graphite, …
@Envek
20
Ярлыки (labels)Ярлыки (labels)
Позволяют сегментировать значения и агрегировать их вновь
Для каждого уникального набора пишется свой временной ряд
Есть опасность комбинаторного взрыва (не стоит записывать в
них id пользователей)
 
21
СчётчикСчётчик
CRDT: G-Counter — монотонно возрастающий счётчик
Базовый тип для более сложных метрик: histogram, …
Позволяет уверенно детектировать рестарты и суммировать
значения хоть с тысячи воркеров.
@Envek
22
GaugeGauge
Произвольное значение, без ограничений.
Используется для мониторинга состояния «внешнего мира»:
Загрузка CPU, потребление памяти, количество процессов.
@Envek
23
Histogram и SummaryHistogram и Summary
Сложные типы для сбора статистики по времени выполнения
или потребления ресурсов: перцентили, среднее, медиана, …
Histogram: набор счётчиков по «корзинам».
Summary: Предпросчёт требуемой статистики клиентом на ходу.
@Envek
Prometheus Librato NewRelic
Типы метрик:
( — настраивается)
histogram
summary
summary
(перцентили)
summary (min, max,
сумма квадратов, …)
24
DYI: PrometheusDYI: Prometheus
Регистрация метрикРегистрация метрик
prometheus = Prometheus::Client.registry
prometheus.counter :sidekiq_jobs_executed_total, "A counter of the total number of jobs sidekiq executed."
prometheus.counter :sidekiq_jobs_success_total, "A counter of the total number of jobs successfully processe
prometheus.counter :sidekiq_jobs_failed_total, "A counter of the total number of jobs failed in sidekiq."
prometheus.histogram :sidekiq_job_runtime_seconds, "A histogram of the job execution time."
prometheus.gauge :sidekiq_jobs_waiting_count, "The number of jobs waiting to process in sidekiq."
prometheus.gauge :sidekiq_active_workers_count, "The number of currently running machines with sidekiq worke
prometheus.gauge :sidekiq_jobs_scheduled_count, "The number of jobs scheduled for later execution."
prometheus.gauge :sidekiq_jobs_retry_count, "The number of failed jobs waiting to be retried"
prometheus.gauge :sidekiq_jobs_dead_count, "The number of jobs exceeded their retry count."
prometheus.gauge :sidekiq_active_processes, "The number of active Sidekiq worker processes."
@Envek
evilmartians.com/chronicles/embracing-metrics-as-new-tests 25
DYI: PrometheusDYI: Prometheus
Обновление метрикОбновление метрик
class SidekiqWorkerPrometheusMiddleware
def call(worker, job, queue)
prometheus = Prometheus::Client.registry
labels = { queue: queue, worker: worker.class }
start = Time.now
begin
yield
prometheus.get(:sidekiq_jobs_success_total).increment(labels)
rescue Exception # rubocop: disable Lint/RescueException
prometheus.get(:sidekiq_jobs_failed_total).increment(labels)
raise
ensure
prometheus.get(:sidekiq_job_runtime_seconds).observe(labels, (Time.now - start).round(3))
prometheus.get(:sidekiq_jobs_executed_total).increment(labels)
end
end
end
@Envek
evilmartians.com/chronicles/embracing-metrics-as-new-tests 26
DYI: PrometheusDYI: Prometheus
Обновление метрикОбновление метрик
class SidekiqExporter < ::Prometheus::Middleware::Exporter
def call(env)
refresh_sidekiq_stats if env["REQUEST_PATH"].start_with?(path)
super
end
def refresh_sidekiq_stats
r = Prometheus.registry
stats = ::Sidekiq::Stats.new
stats.queues.each do |k, v|
r.get(:sidekiq_jobs_waiting_count).set({ queue: k }, v)
end
r.get(:sidekiq_active_workers_count).set({}, stats.workers_size)
r.get(:sidekiq_jobs_scheduled_count).set({}, stats.scheduled_size)
r.get(:sidekiq_jobs_dead_count).set({}, stats.dead_size)
r.get(:sidekiq_active_processes).set({}, stats.processes_size)
end
end
@Envek
evilmartians.com/chronicles/embracing-metrics-as-new-tests 27
DYI: PrometheusDYI: Prometheus
Вывод метрикВывод метрик
Sidekiq.configure_server do |config|
config.redis = redis_credentials
config.server_middleware do |chain|
chain.add SidekiqWorkerPrometheusMiddleware
end
# Start server to expose metrics for Prometheus collector
Thread.new do
Rack::Handler::WEBrick.run(
Rack::Builder.new do
use Rack::CommonLogger, ::Sidekiq.logger
use SidekiqExporter, registry: Prometheus.registry
run ->(_env) { [404, {"Content-Type" => "text/plain"}, ["Not Foundn"]] }
end,
Host: ENV["PROMETHEUS_EXPORTER_BIND"] || "0.0.0.0",
Port: ENV.fetch("PROMETHEUS_EXPORTER_PORT", 9310),
AccessLog: []
)
end
end
@Envek
28
DYI: PrometheusDYI: Prometheus
Успех!Успех!
@Envek
curl http://localhost:9091/metrics
# TYPE sidekiq_jobs_executed_total counter
# HELP sidekiq_jobs_executed_total A counter of the total number of jobs sidekiq executed.
sidekiq_jobs_executed_total{queue="utils",worker="EmptyJob"} 16
sidekiq_jobs_executed_total{queue="default",worker="WaitingJob"} 160
# TYPE sidekiq_jobs_waiting_count gauge
# HELP sidekiq_jobs_waiting_count The number of jobs waiting to process in sidekiq.
sidekiq_jobs_waiting_count{queue="utils"} 2190
sidekiq_jobs_waiting_count{queue="default"} 1490
# TYPE sidekiq_job_runtime_seconds histogram
# HELP sidekiq_job_runtime_seconds A histogram of the job execution time.
sidekiq_job_runtime_seconds_bucket{queue="utils",worker="EmptyJob",le="0.5"} 9.0
sidekiq_job_runtime_seconds_bucket{queue="utils",worker="EmptyJob",le="1"} 16.0
sidekiq_job_runtime_seconds_bucket{queue="utils",worker="EmptyJob",le="5"} 16.0
sidekiq_job_runtime_seconds_bucket{queue="utils",worker="EmptyJob",le="10"} 16.0
sidekiq_job_runtime_seconds_bucket{queue="utils",worker="EmptyJob",le="60"} 16.0
sidekiq_job_runtime_seconds_bucket{queue="utils",worker="EmptyJob",le="300"} 16.0
sidekiq_job_runtime_seconds_bucket{queue="utils",worker="EmptyJob",le="+Inf"} 16.0
sidekiq_job_runtime_seconds_sum{queue="utils",worker="EmptyJob"} 7.963
sidekiq_job_runtime_seconds_count{queue="utils",worker="EmptyJob"} 16.0
29
30
А теперь рисуемА теперь рисуем
31
32
33
34
35
36
37
38
Алерты!Алерты!
Пусть роботы анализируют метрики
39
yabedayabeda
Набор библиотек для удобной работы с метрикамиНабор библиотек для удобной работы с метриками
# Gemfile
gem "yabeda-rails"
# Yay! Standard RoR metrics already tracked!
gem "yabeda-sidekiq"
# Yay! Sidekiq metrics are registered and tracked!
gem "yabeda-prometheus"
# Now you can export metrics to Prometheus
# But some configuration is still needed
gem "yabeda-newrelic"
# And to NewRelic at the same time (not yet released though)
@Envek
Пока WIP :-)
40
yabedayabeda
DSL для описания метрикDSL для описания метрик
Yabeda.configure do
group :sidekiq
counter(:jobs_total_count, comment: "Total number of jobs sidekiq executed.")
counter(:jobs_success_count, comment: "Total number of jobs successfully processed by sidekiq."
counter(:jobs_failed_count, comment: "Total number of jobs failed in sidekiq.")
histogram(:job_runtime, unit: :seconds, comment: "Job execution time.")
gauge(:jobs_waiting_count, comment: "The number of jobs waiting to process in sidekiq.")
end
@Envek
41
yabedayabeda
DSL для сбора метрикDSL для сбора метрик
# Явно в коде
Yabeda.things_duration.measure({type: :foo}, 10)
Yabeda.things_happened_total.increment({type: :foo})
Yabeda.configure do
# Подписываемся на события в системе
ActiveSupport::Notifications.subscribe 'occurence.custom_things' do |*args|
things_duration.measure({type: :foo}, 10)
things_happened_total.increment({type: :foo})
end
# Получаем текущие значения когда приходит время отдать накопленные метрики
collect do
things_alive_total.set({}, Thing.alive.count)
end
end
@Envek
42
yabedayabeda
Хуки для сбора собственных метрикХуки для сбора собственных метрик
Yabeda::Rails.after_controller_action do |event|
tags = {}
external_service_requests_total.increment(tags)
external_service_latency_seconds.measure(tags, event.duration)
end
@Envek
43
Различия систем мониторингаРазличия систем мониторинга
Prometheus Librato NewRelic
Метод сбора: Опрос сервером
клиентов
1. Отправка с
клиента на сервер
2. Периодический
вывод в лог
Отправка с клиента
на сервер
Типы метрик: counter
gauge
histogram
summary
counter
gauge
summary
counter
gauge
histogram
@Envek
44
yabedayabeda
Набор библиотек для удобной работы с метрикамиНабор библиотек для удобной работы с метриками
github.com/yabeda-rb
@Envek
Попробовать в деле:
github.com/yabeda-rb/example-prometheus-sidekiq 45
И это всё?И это всё?
Наличие подробных метрик приложения и его окружения драматично
упрощает отладку (если озаботиться заранее).
Продакшен по прежнему падает, но время восстановления меньше
Изменения и оптимизации больше не делаются в слепую.
С одного взгляда можно ответить на вопрос «Ну чо, как?»
Можно бесконечно смотреть на три вещи: огонь, воду и графики.
@Envek
46
Кажись, всёКажись, всё
✅ Метрики в сайдкике разобрал
✅ Теорию про мониторинг рассказал
✅ Ruby-код показал
✅ Гемы пропиарил
47
Вопросы?Вопросы?
GitHub, Twitter, Telegram: @Envek
envek@envek.name
Нам нужныНам нужны
твои мозги!твои мозги!
GitHub, Twitter, Telegram: @evilmartians
evilmartians.com/chronicles
dev.to/evilmartians
github.com/yabeda-rb
Скоро опубликуем
продолжение!
48

More Related Content

PDF
SECON'2014 - Павел Щеваев - Метаданные и автогенерация кода
PPTX
Метапрограммирование с примерами на JavaScript
PDF
Использование юнит-тестов для повышения качества разработки
PDF
Parallel STL
PDF
Pinboard + pinba / Как организовать мониторинг сотни PHP-проектов (Devconf 2014)
PDF
20130429 dynamic c_c++_program_analysis-alexey_samsonov
PDF
Андрей Субботин "Локализация приложений для iOS: как не прострелить себе ногу"
PDF
Профилирование кода на C/C++ в *nix системах
SECON'2014 - Павел Щеваев - Метаданные и автогенерация кода
Метапрограммирование с примерами на JavaScript
Использование юнит-тестов для повышения качества разработки
Parallel STL
Pinboard + pinba / Как организовать мониторинг сотни PHP-проектов (Devconf 2014)
20130429 dynamic c_c++_program_analysis-alexey_samsonov
Андрей Субботин "Локализация приложений для iOS: как не прострелить себе ногу"
Профилирование кода на C/C++ в *nix системах

What's hot (20)

PDF
Практика применения Pinba в Badoo / Денис Карасик (Badoo)
PDF
Сага о кластере. Все что вы хотели знать про горизонтальное масштабирование в...
PDF
Hacking PostgreSQL. Обзор исходного кода
PDF
Михаил Давыдов - JavaScript. Асинхронность
PPTX
Оптимизация работы с данными в мобильных приложениях / Святослав Иванов, Артё...
PPT
Основы индексирования и расширенные возможности EXPLAIN в MySQL / Василий Лук...
PDF
Подводные камни System.Security.Cryptography
PDF
Михаил Давыдов — JavaScript: Асинхронность
PPTX
Прикладная теория Application Security
PPTX
мониторинг производительности приложения на PINBA
PDF
Component Inspector
PDF
Модульность и управляемая многопоточность встраиваемых С++ приложений - трудн...
PPTX
Взломать сайт на ASP.NET
PDF
Avito Stachka 2012
PDF
Борис Каплуновский, Aviasales.ru
PDF
Семь тысяч Rps, один go
PDF
Очередной скучный доклад про логгирование
PDF
Для чего мы делали свой акторный фреймворк и что из этого вышло?
PDF
Шишки, набитые за 15 лет использования акторов в C++
PDF
Reform: путь к лучшему ORM
Практика применения Pinba в Badoo / Денис Карасик (Badoo)
Сага о кластере. Все что вы хотели знать про горизонтальное масштабирование в...
Hacking PostgreSQL. Обзор исходного кода
Михаил Давыдов - JavaScript. Асинхронность
Оптимизация работы с данными в мобильных приложениях / Святослав Иванов, Артё...
Основы индексирования и расширенные возможности EXPLAIN в MySQL / Василий Лук...
Подводные камни System.Security.Cryptography
Михаил Давыдов — JavaScript: Асинхронность
Прикладная теория Application Security
мониторинг производительности приложения на PINBA
Component Inspector
Модульность и управляемая многопоточность встраиваемых С++ приложений - трудн...
Взломать сайт на ASP.NET
Avito Stachka 2012
Борис Каплуновский, Aviasales.ru
Семь тысяч Rps, один go
Очередной скучный доклад про логгирование
Для чего мы делали свой акторный фреймворк и что из этого вышло?
Шишки, набитые за 15 лет использования акторов в C++
Reform: путь к лучшему ORM
Ad

Similar to What's in a metrics? Ruby Russia 2018 (20)

PDF
JavaDay'14
PPTX
Вячеслав Смирнов - Инструменты нагрузочного тестирования
PDF
Инструментируй это
PPTX
Примеры быстрой разработки API на масштабируемом сервере приложений Impress д...
PPTX
мониторинг производительности Web приложений на python
PPTX
Хорошо поддерживаемое в продакшне приложение / Николай Сивко (okmeter.io)
PPTX
20090720 hpc exercise1
PPT
Как оценивать состояние проекта по разработке с помощью формальных метрик и о...
PPT
C# 5.0. Взгляд в будущее
PPTX
Опыт разработки статического анализатора кода
PPTX
PPTX
Эволюция к Behavior Driven Development на примере популярного фреймворка JBehave
PPTX
Основы и применение статического анализа кода при разработке лекция 1
PDF
Как выглядит современный фронтенд
PDF
Load testing with Tsung
PDF
Руслан Гроховецкий "Как Python стал делать погоду в Яндексе"
PDF
Erlang tasty & useful stuff
ODP
Scorex framework
PPTX
Современный статический анализ кода: что умеет он, чего не умели линтеры
PDF
Как мы строили аналитическую платформу на несколько миллиардов событии в месяц
JavaDay'14
Вячеслав Смирнов - Инструменты нагрузочного тестирования
Инструментируй это
Примеры быстрой разработки API на масштабируемом сервере приложений Impress д...
мониторинг производительности Web приложений на python
Хорошо поддерживаемое в продакшне приложение / Николай Сивко (okmeter.io)
20090720 hpc exercise1
Как оценивать состояние проекта по разработке с помощью формальных метрик и о...
C# 5.0. Взгляд в будущее
Опыт разработки статического анализатора кода
Эволюция к Behavior Driven Development на примере популярного фреймворка JBehave
Основы и применение статического анализа кода при разработке лекция 1
Как выглядит современный фронтенд
Load testing with Tsung
Руслан Гроховецкий "Как Python стал делать погоду в Яндексе"
Erlang tasty & useful stuff
Scorex framework
Современный статический анализ кода: что умеет он, чего не умели линтеры
Как мы строили аналитическую платформу на несколько миллиардов событии в месяц
Ad

More from Андрей Новиков (6)

PDF
imgproxy is amazing
PDF
PostgreSQL as seen by Rubyists (Kaigi on Rails 2022)
PDF
Нюансы запуска приложений в Kubernetes
PDF
Индексируем базу: как делать хорошо и не делать плохо Winter saint p 2021 m...
ODP
Spb RubyConf 2017 — надёжные вебсокеты
ODP
Правильная работа с часовыми поясами в Rails приложении — DevConf 2015
imgproxy is amazing
PostgreSQL as seen by Rubyists (Kaigi on Rails 2022)
Нюансы запуска приложений в Kubernetes
Индексируем базу: как делать хорошо и не делать плохо Winter saint p 2021 m...
Spb RubyConf 2017 — надёжные вебсокеты
Правильная работа с часовыми поясами в Rails приложении — DevConf 2015

What's in a metrics? Ruby Russia 2018

  • 1. Что в метриках тебе моих?Что в метриках тебе моих? О чём могут поведать цифры и графики в мониторинге и зачем вообще заморачиваться. Андрей Новиков RubyRussia 2018 1
  • 2. 2
  • 3. 3
  • 4. 4
  • 5. 5
  • 6. 6
  • 7. 7
  • 8. 8
  • 9. Чего мы хотим?Чего мы хотим? Знать, как быстро растут и разгребаются очереди Знать, какие задачи наиболее «проблемные» Понимать, когда это началось и кто виноват Понимать, помогли ли принятые нами меры @Envek 9
  • 10. Чего мы хотим?Чего мы хотим? Больше метрик Больше графиков Ещё больше графиков … и ещё два монитора @Envek 10
  • 11. Недостающие метрикиНедостающие метрики Время обработки задач Количество новых задач @Envek Недостающие графикиНедостающие графики Динамика изменения размера очередей по отдельным очередям Динамика изменения времени выполнения задач по классам 11
  • 12. Мониторинг веб-приложенияМониторинг веб-приложения Сервера: загрузка CPU, RAM, IO, LA, заполненность дисков, … Веб: количество запросов, время их обработки, queueing time, … Отложенные задачи: количество задач, время их обработки, количество ошибок, … Базы данных: количество запросов, время обработки, объём данных, … Внешние API: количество запросов, время обработки, ошибки… Сеть: задержки, DNS lookup time, throughput, потери пакетов, … Свои показатели: свой набор под каждую интеграцию Бизнес-метрики: количество пользователей, заказов, , … @Envek 12
  • 13. 13
  • 14. А зачем?А зачем? Чтобы понять, откуда вдруг запахло жареным: Откуда — какой участок приложения горит. Вдруг — когда загорелось. 5 минут назад, после деплоя или медленно, но верно разгоралось по мере роста сервиса? Запах — в чём именно проблема? ЦП, память, внешние сервисы? @Envek 14
  • 15. 15
  • 16. 16
  • 18. МониторингМониторинг Непрерывный процесс наблюдения и регистрации параметров системы в сравнении с заданными критериями   «Вы не можете контролировать то, что не можете измерить» — Том ДеМарко @Envek 18
  • 19. МетрикиМетрики 1. Параметры системы 2. Численные значения, полученные при измерении этих параметров работающей системы @Envek 19
  • 20. Временные ряды (time series)Временные ряды (time series) Значения какой либо величины в порядке времени измерения Для хранения разработаны специальные базы данных: InfluxDB, Graphite, … @Envek 20
  • 21. Ярлыки (labels)Ярлыки (labels) Позволяют сегментировать значения и агрегировать их вновь Для каждого уникального набора пишется свой временной ряд Есть опасность комбинаторного взрыва (не стоит записывать в них id пользователей)   21
  • 22. СчётчикСчётчик CRDT: G-Counter — монотонно возрастающий счётчик Базовый тип для более сложных метрик: histogram, … Позволяет уверенно детектировать рестарты и суммировать значения хоть с тысячи воркеров. @Envek 22
  • 23. GaugeGauge Произвольное значение, без ограничений. Используется для мониторинга состояния «внешнего мира»: Загрузка CPU, потребление памяти, количество процессов. @Envek 23
  • 24. Histogram и SummaryHistogram и Summary Сложные типы для сбора статистики по времени выполнения или потребления ресурсов: перцентили, среднее, медиана, … Histogram: набор счётчиков по «корзинам». Summary: Предпросчёт требуемой статистики клиентом на ходу. @Envek Prometheus Librato NewRelic Типы метрик: ( — настраивается) histogram summary summary (перцентили) summary (min, max, сумма квадратов, …) 24
  • 25. DYI: PrometheusDYI: Prometheus Регистрация метрикРегистрация метрик prometheus = Prometheus::Client.registry prometheus.counter :sidekiq_jobs_executed_total, "A counter of the total number of jobs sidekiq executed." prometheus.counter :sidekiq_jobs_success_total, "A counter of the total number of jobs successfully processe prometheus.counter :sidekiq_jobs_failed_total, "A counter of the total number of jobs failed in sidekiq." prometheus.histogram :sidekiq_job_runtime_seconds, "A histogram of the job execution time." prometheus.gauge :sidekiq_jobs_waiting_count, "The number of jobs waiting to process in sidekiq." prometheus.gauge :sidekiq_active_workers_count, "The number of currently running machines with sidekiq worke prometheus.gauge :sidekiq_jobs_scheduled_count, "The number of jobs scheduled for later execution." prometheus.gauge :sidekiq_jobs_retry_count, "The number of failed jobs waiting to be retried" prometheus.gauge :sidekiq_jobs_dead_count, "The number of jobs exceeded their retry count." prometheus.gauge :sidekiq_active_processes, "The number of active Sidekiq worker processes." @Envek evilmartians.com/chronicles/embracing-metrics-as-new-tests 25
  • 26. DYI: PrometheusDYI: Prometheus Обновление метрикОбновление метрик class SidekiqWorkerPrometheusMiddleware def call(worker, job, queue) prometheus = Prometheus::Client.registry labels = { queue: queue, worker: worker.class } start = Time.now begin yield prometheus.get(:sidekiq_jobs_success_total).increment(labels) rescue Exception # rubocop: disable Lint/RescueException prometheus.get(:sidekiq_jobs_failed_total).increment(labels) raise ensure prometheus.get(:sidekiq_job_runtime_seconds).observe(labels, (Time.now - start).round(3)) prometheus.get(:sidekiq_jobs_executed_total).increment(labels) end end end @Envek evilmartians.com/chronicles/embracing-metrics-as-new-tests 26
  • 27. DYI: PrometheusDYI: Prometheus Обновление метрикОбновление метрик class SidekiqExporter < ::Prometheus::Middleware::Exporter def call(env) refresh_sidekiq_stats if env["REQUEST_PATH"].start_with?(path) super end def refresh_sidekiq_stats r = Prometheus.registry stats = ::Sidekiq::Stats.new stats.queues.each do |k, v| r.get(:sidekiq_jobs_waiting_count).set({ queue: k }, v) end r.get(:sidekiq_active_workers_count).set({}, stats.workers_size) r.get(:sidekiq_jobs_scheduled_count).set({}, stats.scheduled_size) r.get(:sidekiq_jobs_dead_count).set({}, stats.dead_size) r.get(:sidekiq_active_processes).set({}, stats.processes_size) end end @Envek evilmartians.com/chronicles/embracing-metrics-as-new-tests 27
  • 28. DYI: PrometheusDYI: Prometheus Вывод метрикВывод метрик Sidekiq.configure_server do |config| config.redis = redis_credentials config.server_middleware do |chain| chain.add SidekiqWorkerPrometheusMiddleware end # Start server to expose metrics for Prometheus collector Thread.new do Rack::Handler::WEBrick.run( Rack::Builder.new do use Rack::CommonLogger, ::Sidekiq.logger use SidekiqExporter, registry: Prometheus.registry run ->(_env) { [404, {"Content-Type" => "text/plain"}, ["Not Foundn"]] } end, Host: ENV["PROMETHEUS_EXPORTER_BIND"] || "0.0.0.0", Port: ENV.fetch("PROMETHEUS_EXPORTER_PORT", 9310), AccessLog: [] ) end end @Envek 28
  • 29. DYI: PrometheusDYI: Prometheus Успех!Успех! @Envek curl http://localhost:9091/metrics # TYPE sidekiq_jobs_executed_total counter # HELP sidekiq_jobs_executed_total A counter of the total number of jobs sidekiq executed. sidekiq_jobs_executed_total{queue="utils",worker="EmptyJob"} 16 sidekiq_jobs_executed_total{queue="default",worker="WaitingJob"} 160 # TYPE sidekiq_jobs_waiting_count gauge # HELP sidekiq_jobs_waiting_count The number of jobs waiting to process in sidekiq. sidekiq_jobs_waiting_count{queue="utils"} 2190 sidekiq_jobs_waiting_count{queue="default"} 1490 # TYPE sidekiq_job_runtime_seconds histogram # HELP sidekiq_job_runtime_seconds A histogram of the job execution time. sidekiq_job_runtime_seconds_bucket{queue="utils",worker="EmptyJob",le="0.5"} 9.0 sidekiq_job_runtime_seconds_bucket{queue="utils",worker="EmptyJob",le="1"} 16.0 sidekiq_job_runtime_seconds_bucket{queue="utils",worker="EmptyJob",le="5"} 16.0 sidekiq_job_runtime_seconds_bucket{queue="utils",worker="EmptyJob",le="10"} 16.0 sidekiq_job_runtime_seconds_bucket{queue="utils",worker="EmptyJob",le="60"} 16.0 sidekiq_job_runtime_seconds_bucket{queue="utils",worker="EmptyJob",le="300"} 16.0 sidekiq_job_runtime_seconds_bucket{queue="utils",worker="EmptyJob",le="+Inf"} 16.0 sidekiq_job_runtime_seconds_sum{queue="utils",worker="EmptyJob"} 7.963 sidekiq_job_runtime_seconds_count{queue="utils",worker="EmptyJob"} 16.0 29
  • 30. 30
  • 31. А теперь рисуемА теперь рисуем 31
  • 32. 32
  • 33. 33
  • 34. 34
  • 35. 35
  • 36. 36
  • 37. 37
  • 38. 38
  • 40. yabedayabeda Набор библиотек для удобной работы с метрикамиНабор библиотек для удобной работы с метриками # Gemfile gem "yabeda-rails" # Yay! Standard RoR metrics already tracked! gem "yabeda-sidekiq" # Yay! Sidekiq metrics are registered and tracked! gem "yabeda-prometheus" # Now you can export metrics to Prometheus # But some configuration is still needed gem "yabeda-newrelic" # And to NewRelic at the same time (not yet released though) @Envek Пока WIP :-) 40
  • 41. yabedayabeda DSL для описания метрикDSL для описания метрик Yabeda.configure do group :sidekiq counter(:jobs_total_count, comment: "Total number of jobs sidekiq executed.") counter(:jobs_success_count, comment: "Total number of jobs successfully processed by sidekiq." counter(:jobs_failed_count, comment: "Total number of jobs failed in sidekiq.") histogram(:job_runtime, unit: :seconds, comment: "Job execution time.") gauge(:jobs_waiting_count, comment: "The number of jobs waiting to process in sidekiq.") end @Envek 41
  • 42. yabedayabeda DSL для сбора метрикDSL для сбора метрик # Явно в коде Yabeda.things_duration.measure({type: :foo}, 10) Yabeda.things_happened_total.increment({type: :foo}) Yabeda.configure do # Подписываемся на события в системе ActiveSupport::Notifications.subscribe 'occurence.custom_things' do |*args| things_duration.measure({type: :foo}, 10) things_happened_total.increment({type: :foo}) end # Получаем текущие значения когда приходит время отдать накопленные метрики collect do things_alive_total.set({}, Thing.alive.count) end end @Envek 42
  • 43. yabedayabeda Хуки для сбора собственных метрикХуки для сбора собственных метрик Yabeda::Rails.after_controller_action do |event| tags = {} external_service_requests_total.increment(tags) external_service_latency_seconds.measure(tags, event.duration) end @Envek 43
  • 44. Различия систем мониторингаРазличия систем мониторинга Prometheus Librato NewRelic Метод сбора: Опрос сервером клиентов 1. Отправка с клиента на сервер 2. Периодический вывод в лог Отправка с клиента на сервер Типы метрик: counter gauge histogram summary counter gauge summary counter gauge histogram @Envek 44
  • 45. yabedayabeda Набор библиотек для удобной работы с метрикамиНабор библиотек для удобной работы с метриками github.com/yabeda-rb @Envek Попробовать в деле: github.com/yabeda-rb/example-prometheus-sidekiq 45
  • 46. И это всё?И это всё? Наличие подробных метрик приложения и его окружения драматично упрощает отладку (если озаботиться заранее). Продакшен по прежнему падает, но время восстановления меньше Изменения и оптимизации больше не делаются в слепую. С одного взгляда можно ответить на вопрос «Ну чо, как?» Можно бесконечно смотреть на три вещи: огонь, воду и графики. @Envek 46
  • 47. Кажись, всёКажись, всё ✅ Метрики в сайдкике разобрал ✅ Теорию про мониторинг рассказал ✅ Ruby-код показал ✅ Гемы пропиарил 47
  • 48. Вопросы?Вопросы? GitHub, Twitter, Telegram: @Envek envek@envek.name Нам нужныНам нужны твои мозги!твои мозги! GitHub, Twitter, Telegram: @evilmartians evilmartians.com/chronicles dev.to/evilmartians github.com/yabeda-rb Скоро опубликуем продолжение! 48