When my production app processes change state on Heroku, I want to be notified in Slack:
Other examples:
17:38:52 clock.1 `bundle exec ruby schedule/clock.rb` up
17:39:03 web.1 `bundle exec puma -p $PORT -C ./config/puma.rb` up
17:39:05 web.2 `bundle exec puma -p $PORT -C ./config/puma.rb` up
Pager-notifying events:
17:38:52 queuenote.1 `bundle exec ruby queue/note.rb` crashed
Heroku has webhooks for these events but their payloads aren't in the format needed for Slack incoming webhooks.
AWS Lambda is the perfect glue to transform the Heroku webhook's JSON payload into a useful JSON payload for Slack's incoming webhook.
Slack config
Create an incoming webhook. Copy the URL.
Lambda config
Create a Lambda function. AWS' supported runtimes include Node, Python, Ruby, and Go. You can alternatively implement a custom runtime.
Here's an example in Ruby:
require "json"
require "net/http"
require "time"
require "uri"
def lambda_handler(event:, context:)
dyno = JSON.parse(event["body"])
name = dyno["data"]["name"] || ""
state = dyno["data"]["state"] || ""
ignored_states = ["starting", "down"].include?(state)
term_one_off = state == "crashed" && ["scheduler", "run"].any? { |p| name.include?(p) }
if ignored_states || term_one_off || name.include?("release")
return {
statusCode: 200,
headers: { "Content-Type": "application/json" },
body: "ok"
}
end
uri = URI.parse(ENV.fetch("SLACK_URL"))
http = Net::HTTP.new(uri.host, uri.port)
http.use_ssl = true
req = Net::HTTP::Post.new(uri.request_uri)
req["Content-Type"] = "application/json"
req.body = {
text: [
Time.parse(dyno["created_at"]).getlocal("-07:00").strftime('%H:%M:%S'),
name,
"`#{dyno["data"]["command"]}`",
state
].compact.join(" ")
}.to_json
res = http.request(req)
return {
statusCode: 200,
headers: { "Content-Type": "application/json" },
body: res.body
}
end
Paste the Slack incoming webhook URL as an environment variable, which is encrypted at rest.
Create an API Gateway to make the Lambda function accessible in the Heroku web UI.
Heroku config
Go to:
https://dashboard.heroku.com/apps/YOUR-APP-NAME/webhooks
Create a webhook with event type "dyno". Paste the API Gateway URL as the Payload URL.
Modify to taste
Edit and save the code in Lambda's web-based text editor. Trigger a webhook to test the function. View the auto-created CloudWatch logs for each function call.
Top comments (0)