Skip to content

Add support for custom notifiers - #500

Closed
gabrieltaylor wants to merge 3 commits into
ankane:masterfrom
ritual:add-support-for-custom-notifiers
Closed

gabrieltaylor wants to merge 3 commits into
ankane:masterfrom
ritual:add-support-for-custom-notifiers

Conversation

@gabrieltaylor

Copy link
Copy Markdown

Description

Adds support for sending failing checks to a custom notifier.

Happy to adjust the code however you recommend if this change has value for other users. Happy to close the PR if it doesn't :)

Motivation

In our application we find value in triggering alerts from failing Blazer checks. In order to create alerts in a third party system we need to send a specific payload to that service via an HTTP POST request.

To enable this function we've defined a module that implements:

  • state_change
  • failing_checks

following the pattern defined by the Blazer::EmailNotifier and Blazer::SlackNotifier.

The interface implemented by the module is

  module Interface
    def self.state_change(check:, state:, state_was:, result:, message:, check_type:)
    end

    def self.failing_checks(checks)
    end
  end

The implementation might look something like this

module BlazerService
  module CheckFailureHttpNotifier
    extend T::Sig

    sig { params(check: Blazer::Check, state: String, state_was: String, result: Blazer::Result, message: T.nilable(String), check_type: String).returns(Net::HTTPResponse) }
    def self.state_change(check:, state:, state_was:, result:, message:, check_type:)
      payload = build_payload(check:, state:, state_was:, result:, message:, check_type:)
      make_request(payload)
    end

    sig { params(checks: T::Array[Blazer::Check]).void }
    def self.failing_checks(checks)
      # noop
    end

    sig { params(payload: T::Hash[Symbol, T.untyped]).returns(Net::HTTPResponse) }
    def self.make_request(payload)
      http = Net::HTTP.new(uri.host, uri.port)
      http.use_ssl = (uri.scheme == "https")

      request = Net::HTTP::Post.new(uri.request_uri, {"Content-Type" => "application/json", "Accept" => "application/json"})
      request.body = payload.to_json

      http.request(request)
    end

    sig { params(check: Blazer::Check, state: String, state_was: String, result: Blazer::Result, message: T.nilable(String), check_type: String).returns(T::Hash[Symbol, T.untyped]) }
    def self.build_payload(check:, state:, state_was:, result:, message:, check_type:)
      {
        check_id: check.id,
        query_name: check.query&.name,
        query_description: check.query&.description,
        query_statement: check.query&.statement,
        row_count: result.rows.size,
        state:,
        state_was:,
        message:,
        check_type:
      }
    end

    sig { returns(URI::HTTP) }
    def self.uri
      T.cast(URI.parse(url), URI::HTTP)
    end

    sig { returns(String) }
    def self.url
      ENV.fetch("BLAZER_HTTP_NOTIFICATION_URL")
    end
  end
end

We're adding the custom notifier in the initializer like this.

Rails.application.config.to_prepare do
  notifier = BlazerService::CheckFailureHttpNotifier
  unless Blazer.custom_notifiers.include?(notifier)
    Blazer.custom_notifiers << notifier
  end
end

Gabriel Taylor Russ added 3 commits March 26, 2025 16:44
@ankane ankane closed this in 610f914 May 20, 2026
@ankane

ankane commented May 20, 2026

Copy link
Copy Markdown
Owner

Hi @gabrieltaylor, thanks for the suggestion and PR. Added an experimental API for notifiers in the commit above.

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants