perchfall-notify
perchfall-notify delivers Perchfall synthetic check reports to Slack and other notification channels, with fail-open delivery across channels.
Features
- Fail-open delivery – every channel is attempted; one channel failing does not skip the others.
- Slack channel built in – Block Kit messages with status, URL, HTTP code, duration, and the full list of network and console errors.
-
Pluggable channels – subclass
Perchfall::Notify::Channel, implement#deliver, plug in webhooks, PagerDuty, SMS, email. - No framework required – runs in Sidekiq jobs, Rake tasks, plain Ruby scripts.
Requirements
| Dependency | Version |
|---|---|
| Ruby | >= 3.2 |
| perchfall | >= 0.3.0 |
Installation
Add to your Gemfile:
gem "perchfall-notify"Or install directly:
bundle add perchfall-notifyQuick start
require "perchfall/notify"
slack = Perchfall::Notify::Channels::Slack.new(
webhook_url: ENV.fetch("SLACK_WEBHOOK_URL")
)
report = Perchfall.run(url: "https://example.com")
Perchfall::Notify.deliver(report, channels: [slack])
# => nil # raises Perchfall::Notify::DeliveryError if any channel failsThe Slack message includes any network and console errors recorded on the report.
Slack channel
Create a Slack incoming webhook and pass the URL:
slack = Perchfall::Notify::Channels::Slack.new(
webhook_url: "https://hooks.slack.com/services/..."
)The default Block Kit message includes:
- Pass/fail header with optional scenario name
- URL, HTTP status, and duration
- Network errors with method, URL, and failure reason
- Console errors with type and message
Custom message format
Inject a formatter to control message shape:
class MyFormatter
def format(report)
{
text: report.ok? ? "#{report.url} OK" : "#{report.url} FAILED"
}
end
end
slack = Perchfall::Notify::Channels::Slack.new(
webhook_url: ENV.fetch("SLACK_WEBHOOK_URL"),
formatter: MyFormatter.new
)Delivering to multiple channels
Pass any number of channels. All are attempted; a failure in one does not skip the others.
Perchfall::Notify.deliver(report, channels: [slack, pagerduty, sms])If any channels fail, a single Perchfall::Notify::DeliveryError is raised after all channels have been attempted, with a summary of every failure.
Building a custom channel
Subclass Perchfall::Notify::Channel and implement #deliver:
require "net/http"
require "json"
class WebhookChannel < Perchfall::Notify::Channel
def initialize(url:)
@url = URI(url)
end
def deliver(report)
response = Net::HTTP.post(@url, report.to_json, "Content-Type" => "application/json")
raise Perchfall::Notify::DeliveryError, "Webhook failed: #{response.code}" unless response.is_a?(Net::HTTPSuccess)
end
endRaise DeliveryError on failure so Notifier can accumulate it alongside other channel failures.
Use in a background job
class SyntheticCheckJob
include Sidekiq::Job
def perform(url)
channels = [
Perchfall::Notify::Channels::Slack.new(webhook_url: ENV.fetch("SLACK_WEBHOOK_URL"))
]
report = Perchfall.run(url: url)
Perchfall::Notify.deliver(report, channels: channels)
rescue Perchfall::Errors::PageLoadError => e
Perchfall::Notify.deliver(e.report, channels: channels)
end
endPageLoadError#report carries the partial Perchfall report so the failed run is still delivered.
Errors
| Exception | When |
|---|---|
Perchfall::Notify::ConfigurationError |
A channel was constructed with invalid configuration (e.g. missing webhook URL) |
Perchfall::Notify::DeliveryError |
One or more channels failed to deliver |
Perchfall::Notify::Error |
Base class; rescue this to catch any perchfall-notify error |
Supported Ruby versions
perchfall-notify supports Ruby 3.2+. CI runs against Ruby 4.0. See .github/workflows/ci.yml for the current matrix.
Documentation
Development
bundle install
bundle exec rspec
bin/consoleContributing
Bug reports and pull requests are welcome on GitHub. See CONTRIBUTING.md for the workflow.
Code of Conduct
Everyone interacting in the perchfall-notify project's codebases and issue trackers is expected to follow the Contributor Covenant code of conduct.
License
Released under the MIT License.