Skip to content

Instantly share code, notes, and snippets.

@jlecour
Last active May 22, 2022 17:43
Show Gist options
  • Star 48 You must be signed in to star a gist
  • Fork 12 You must be signed in to fork a gist
  • Save jlecour/9830941 to your computer and use it in GitHub Desktop.
Save jlecour/9830941 to your computer and use it in GitHub Desktop.
How to post alerts from Monit to Slack
# encoding: UTF-8
require 'optparse'
require 'net/http'
require 'json'
def parse_options(argv)
opts = {}
@parser = OptionParser.new do |o|
o.on '--channel CHANNEL', "name of the channel to post to" do |arg|
opts[:channel] = arg
end
o.on '--name NAME', "name of the bot" do |arg|
opts[:name] = arg
end
o.on '--emoji EMOJI', "emoji icon" do |arg|
opts[:emoji] = arg
end
o.on '--token TOKEN', "authentication token" do |arg|
opts[:token] = arg
end
o.on '--status [error,ok]', "kind of message" do |arg|
opts[:status] = arg
end
o.on '--color #HEX_COLOR', "color of the message" do |arg|
opts[:color] = arg
end
o.on '--slack-url URL', "URL to post to" do |arg|
opts[:slack_url] = arg
end
o.on '--monit-url URL', "URL of Monit" do |arg|
opts[:monit_url] = arg
end
o.on '--text TEXT', "text of the message" do |arg|
opts[:text] = arg
end
o.on '--service SERVICE', "Monit service affected" do |arg|
opts[:service] = arg
end
end
@parser.banner = "post_to_slack [options]"
# @parser.on_tail "-h", "--help", "Show help" do
# logger.info @parser
# die 1
# end
@parser.parse!(argv)
opts[:channel] ||= ENV.fetch('CHANNEL') { '#general' }
opts[:name] ||= ENV.fetch('NAME') { 'Monit' }
opts[:emoji] ||= ENV.fetch('EMOJI') { ':vertical_traffic_light:' }
opts[:token] ||= ENV.fetch('TOKEN') { '_your_token_' }
opts[:status] ||= ENV.fetch('STATUS') { 'unknown' }
opts[:slack_url] ||= ENV.fetch('SLACK_URL') { "https://_you_.slack.com/services/hooks/incoming-webhook" }
opts[:monit_url] ||= ENV.fetch('MONIT_URL') { "http://#{`hostname -f`.chomp}:2812/" }
opts[:color] ||= case opts[:status]
when 'ok'
'#59A452'
when 'error'
'#d00000'
else
'#cccccc'
end
opts
end
def format_payload(opts = {})
{
"channel" => opts[:channel],
"icon_emoji" => opts[:emoji],
"username" => opts[:name],
"text" => "Issue on #{`hostname`.chomp} : #{opts[:text]}",
"attachments" => [{
"fallback" => "#{opts[:text]}\n#{opts[:monit_url]}#{opts.fetch(:service){'#'}}",
"color" => opts[:color],
"fields" => [{
"title" => "Message",
"value" => opts[:text],
"short" => true
},{
"title" => "URL",
"value" => "<#{opts[:monit_url]}#{opts.fetch(:service){'#'}}|#{opts.fetch(:service){'?'}}>",
"short" => true
}]
}]
}
end
def post(url, payload)
uri = URI.parse(url)
http = Net::HTTP.new(uri.host, uri.port)
http.use_ssl = true
http.post("#{uri.path}?#{uri.query}", payload.to_json)
end
options = parse_options(ARGV)
payload = format_payload(options)
url = "#{options.fetch(:slack_url)}?token=#{options.fetch(:token)}"
post(url, payload)
check process _process_name_
with pidfile /path/to/pidfile.pid
start program = "/path/to/start" as uid _user_ and gid _group_ with timeout 30 seconds
stop program = "/path/to/stop" as uid _user_ and gid _group_ with timeout 30 seconds
if does not exist for 1 cycle
then exec "/path/to/ruby /path/to/post_to_slack.rb --service _process_name_ --status error --text 'Process X is down'"
else if succeeded for 1 cycle then exec "/path/to/ruby /path/to/post_to_slack.rb --service _process_name_ --status ok --text 'Process X is up'"
group _process_group_
@amit-naudiyal
Copy link

It seems it will only post an alert to Slack but will not start it.

@smalltown
Copy link

agree with @amit-naudiyal, need to add one more line "if does not exist then restart" to restart the process when encountering issue

check process _process_name_
  with pidfile /path/to/pidfile.pid
  start program = "/path/to/start" as uid _user_ and gid _group_ with timeout 30 seconds
  stop program = "/path/to/stop" as uid _user_ and gid _group_ with timeout 30 seconds
  if does not exist then restart
  if does not exist for 1 cycle
    then exec "/path/to/ruby /path/to/post_to_slack.rb --service _process_name_ --status error --text 'Process X is down'"
    else if succeeded for 1 cycle then exec "/path/to/ruby /path/to/post_to_slack.rb --service _process_name_ --status ok --text 'Process X is up'"
  group _process_group_

@neidiom
Copy link

neidiom commented Aug 19, 2018

@jlecour thanks for the inspiration, I had to automate monit to slack on several servers therefore I made a gem.

https://rubygems.org/gems/monit2slack

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment