12FF5B8

hico_horiuchiの技術系な覚え書き.

SensuのアラートをHubotで通知

最近,研究室の20台弱のサーバをSensuで監視するようになった.
監視項目は,生存確認や,CPU・メモリ・ディスク使用率などだ.

研究室でチャットを使ってるので,そこにHubotを使ってアラートを流せるようにする.

SensuにHandlerを追加

Sensuでは,アラートが発生した際にスクリプト(handler)で通知する仕組みがある.
アラートはJSON形式でhandlerに渡されるので,それをHubotにHTTP POSTする.

  • /etc/sensu/handlers/http_post.rb
#!/usr/bin/env ruby

require 'uri'
require 'net/http'
require 'json'

uri = URI.parse ARGV.first
request = Net::HTTP::Post.new uri, initheader = { 'Content-Type' => 'application/json' }
request.body = STDIN.read

http = Net::HTTP.new uri.host, uri.port
http.start { |h| h.request request }
  • /etc/sensu/conf.d/handlers.json
{
  "handlers": {
    "default": {
      "type": "pipe",
      "command": "/etc/sensu/handlers/http_post.rb 'http://hubot.example.com/sensu?room=1234'"
    }
  }
}

Hubotの通知スクリプト

Sensuから投げられたアラートのJSONを,チャットに流せるようにする.
例えば/sensu?room=1234というURLに投げられた場合,1234というIDのルームに通知する.

# Description:
#   Notify Sensu alerts.
#
# URLS:
#   /sensu?room=<room>

url = require 'url'
querystring = require 'querystring'

module.exports = (robot) ->
  say = (room, message) ->
    envelope = room: room
    robot.send envelope, '[Sensu] ' + message

  robot.router.post '/sensu', (req, res) ->
    query = querystring.parse url.parse(req.url).query
    room = query.room
    payload = req.body
    res.send 400 unless room

    if payload.occurrences is 1 and payload.check.status > 0
      msg = "Alert of #{payload.check.name} occuerrd"
      msg += " in #{payload.client.name}.\n"
      msg += "```\n#{payload.check.output}\n```"
      say room, msg

    res.send 200

結果

Typetalkだと,こんな感じで通知される.
f:id:hico_horiuchi:20141001231812p:plain