SQLert.Alert behaviour (sqlert v0.0.2)

View Source

Defines an SQL-based alert (Behaviour).

SQLert alerts are modules that specify SQL queries to be executed on schedule, checking for specific conditions in your database. When these conditions are met, alerts can trigger notifications through various channels.

Alert Lifecycle

Each alert runs in its own process and follows this lifecycle:

  1. At the configured schedule, the alert's query/0 callback is executed
  2. The query result is passed to handle_result/1
  3. If handle_result/1 returns {:alert, message, metadata}, notifications are sent
  4. The process waits for the next scheduled

Defining Alerts

To define an alert, create a module that uses SQLert.Alert and implement the required callbacks:

defmodule MyApp.Alerts.HighErrorRate do
  use SQLert.Alert,
    schedule: "10 * * * *"
    enabled: true

  @impl true
  def query do
    "SELECT COUNT(*) FROM errors WHERE created_at > NOW() - INTERVAL '1 hour'"
  end

  @impl true
  def handle_result([[count]]}) when count > 100 do
    {:alert, "High error rate detected", %{count: count}}
  end
  def handle_result(_) do
    {:skip, %{count: 0}}
  end

  @impl true
  def notifiers do
    [MyApp.Alerts.Notifiers.Slack]
  end
end

Configuration Options

  • :schedule - (String) Cron notation with the alert schedule. REQUIRED
  • :enabled - (Boolean) Whether this alert should run. Defaults to Mix.env() == :prod

Query Types

The query/0 callback can return either a string SQL query or an Ecto query:

# Raw SQL
def query do
  "SELECT COUNT(*) FROM users WHERE last_login < NOW() - INTERVAL '30 days'"
end

# Ecto query
def query do
  from u in User,
    where: u.last_login < ago(30, "day"),
    select: count(u.id)
end

Handling Results

The handle_result/1 callback receives the query result and must return one of:

  • {:alert, message, metadata} - Trigger notifications with the given message
  • {:skip, metadata} - Condition not met, skip notifications

For SQL queries, results come in the format %{rows: [[value]]}. For Ecto queries, you receive the direct query result.

Notifications

Alerts can have multiple notifiers that implement the SQLert.Notifier behaviour. Define them in the notifiers/0 callback:

def notifiers do
  [
    MyApp.Alerts.Notifiers.Slack,
    MyApp.Alerts.Notifiers.Email
  ]
end

See SQLert.Notifier for details on implementing notifiers.

Summary

Types

alert_result()

@type alert_result() :: {:alert, String.t(), map()} | {:skip, map()}

query()

@type query() :: String.t() | Ecto.Query.t()

t()

@type t() :: %SQLert.Alert{message: String.t(), metadata: map()}

Callbacks

handle_result(any)

@callback handle_result(any()) :: alert_result()

notifiers()

@callback notifiers() :: [module()]

query()

@callback query() :: query()