Gem Version Build Status Code Climate

Kurchatov

Перед вами гем для мониторинга с помощью riemann. Я люблю chef и ohai, поэтому здесь есть немного первого и немного второго.

Юзкейз таков:

  • Kurchatov попадает в среду (окружение, приложения) которую не знает, и изучает ее с помощью ohai
  • Решает какие плагины запускать
  • Отсылает сообщения на riemann-хост со присвоеными статусами

DSL

Решено использовать dsl для написания плагинов, плагин выглядит так:

name "человеко читаемое имя" # по дефолту basename файла
interval 60 # с какой переодичностью будет запускаться плагин
always_start true # плагину не нужны дополнительные настройки

default[:nginx][:file] = "/etc/nginx/nginx.conf"
default[:nginx][:cmd] = "nginx -t" # дефолтные значение для Mashie: 'plugin'
default[:nginx][:url] = "http://127.0.0.1:133233/status" # данные значения смержаться со значениями
                                                         # полученными из конфига

run_if :os => 'linux' do # по умолчанию разрешено запускать все и везде
  File.exists? plugin.file # plugin - не что иное как проставленые значения из default
                           # доступно обращение plugin[:file], plugin["file"], plugin.file
end

collect :web_some_platform => true, :os => 'linux' do # значение полученные через ohai, 
                                                    # collect включиться ohai[:web_some_platform] == true и
                                                    # для ohai[:os] == 'linux'
  metric = rest_get(default[:nginx][:url]).split("\n").first.split("Active connections:").last.to_i
  event(
    :service => "nginx active connections",          # по дефолту name, если редиректим в graphite
    :metric => metric,                               # то service будет ключем для url
    :warning => 10,
    :critical => 20,
    :diff => true, # говорим что запоминать предыдущие значения и если разница между новым и старым
                   # меньше warning - получим статус 'ok', больше critical - 'critical' и так далее
                   # без :diff мы будем считать честные значения
                   # для того чтобы посчитать RPS мы просто делим метрику на interval
    :description => "Что-то для человека-монитора" # допустимо сокращения :desc
  )

  event(
    :service => "nginx test config #{plugin.file}",  # сервис должен быть человекочитаемым но уникальным!
    :state => shell_out("#{ohai[:nginx][:cmd]}").exitstatus == 0  # если :state == true стейт "ok", иначе - "critical"
                                              # shell_out! - сгенерит exception и riemann уйдет сообщение об ошибке
                                              # в плагине, также доступен просто shell() - он вернет только stdout и
                                              # действует как shell_out!
    :desc => "Ой, конфиг не валидный, наверно nginx -t его испортил :("
  )

end

Если плагин отправил event, это не означает что он попадает на riemann-server:

  • Эвенты группируются и отсылаются асинхронно пачками (все что накопилось за Kurchatov::Responders::Riemann::FLUSH_INTERVAL по дефолту 0.5 секунд)
  • При отсутвии метрики второй и последующий раз :state == "ok" не будет отсылаться

Helpers

  • stop! - останавливает запущенный плагин
  • rest_get("http://user:password@host/uri") - body
  • rest_get("/tmp/file") - body
  • http_get("http://ya.ru") - body и http_code. если http_code == 0 - возвращает на SocketError
  • runit_service_stat("service_name") - service status. unknown если неизвестный сервис
  • runit_service_running?("service_name") - true если сервис запущен
  • runit_service_uptime("service_name") - аптайм сервиса, -1 в случае ошибки

Больше примеров вы найдете тут.

Ohai

И в африке ohai. Минимальный пример:

provides "postgres"
postgres Mash.new
cmd = "psql -U postgres -tqc 'select version()'"
status, stdout, stderr = run_command(:command => cmd)
postgres[:version] = stdout.strip

Config

Это обычный yml-файл с настройками плагинов, eго удобно генерить chef'ом :)

plugin name:
  settings name:
  - 'bla-bla'

Есть небольшая магия, для того чтобы использовать плагин как провайдер (например следить за определенными портами):

web watcher:
  - url: http://localhost/ # создастся plugin с name == 'web watcher_0'
    status: 302
  - url: https://localhost/login # новый плагин name == 'web watcher_1'
    status: 200
    ua: Mozilla
robots txt watcher: # новый плагин name == 'robots txt watcher'
  parent: web watcher
  url: https://localhost/robots.txt
  status: 404
  ua: ^Yandex

Почему велосипед

Удобно писать плагины, использовать 1 процесс, 1 коннект, и проч.

Посмотрите официальную реализацию riemann-client, По сравнению с ней вы тут не найдете search и udp.