How to Monitor Rollbax with Vigilmon
Rollbax is the Elixir client for Rollbar, the error tracking and exception monitoring platform. It captures uncaught exceptions, error logs, and custom telemetry events from your Elixir application and forwards them to the Rollbar dashboard with metadata: environment, host, request context, and custom user-defined attributes. It integrates with Phoenix and Plug to automatically capture HTTP request context alongside exceptions.
Rollbax solves the "what went wrong in the code" problem. But exception tracking alone has a blind spot: some failure modes produce no exceptions at all. A server that's unreachable from the internet fails silently — no request reaches the application, so no exception is captured. A health check endpoint that times out leaves no trace in Rollbar. A Kubernetes pod that's stuck in CrashLoopBackOff may restart before any exception is sent.
Vigilmon closes this gap with external uptime monitoring: probe your application from outside, detect when it's unreachable, and alert before users report issues — complementing the code-level visibility that Rollbax provides.
Why You Need Both Error Tracking and Uptime Monitoring
| Failure type | Visible in Rollbax | Visible in Vigilmon | |---|---|---| | Unhandled exception in request handler | Yes | No | | Memory leak causing OOM crash | Maybe (if Rollbax flushes before crash) | Yes | | Server unreachable (network/firewall issue) | No | Yes | | Database connection pool exhausted | Yes | Yes (500 responses) | | Deployment failure (app won't start) | No | Yes | | Silent background job failure | Yes (if logged) | Yes (via heartbeat) | | Certificate expiry | No | Yes | | Third-party API timeout | Yes | Only if it causes downstream 500s |
Running both gives you defense in depth: Rollbax catches application logic failures, Vigilmon catches infrastructure failures.
Key Metrics to Track
| Metric | Source | What it tells you | |--------|--------|-------------------| | Exception rate by class | Rollbax/Rollbar | Whether error frequency is rising or stable | | Error occurrences by environment | Rollbax | Whether prod is noisier than staging | | Uptime percentage | Vigilmon | Whether your app is reachable externally | | Health check response time | Vigilmon | Whether your app is slow before it goes down | | Heartbeat interval | Vigilmon | Whether background jobs are completing on schedule | | Error rate per deploy | Rollbax tags | Whether a release introduced new exceptions |
Step 1: Add Rollbax to Your Project
# mix.exs
defp deps do
[
{:rollbax, "~> 0.11"}
]
end
Configure in your application:
# config/runtime.exs
config :rollbax,
access_token: System.get_env("ROLLBAR_ACCESS_TOKEN"),
environment: System.get_env("ROLLBAR_ENVIRONMENT", "production"),
enabled: System.get_env("ROLLBAR_ACCESS_TOKEN") != nil
Start the Rollbax reporter in your supervision tree:
# lib/my_app/application.ex
children = [
Rollbax,
MyApp.Repo,
MyAppWeb.Endpoint
]
Step 2: Plug Integration for Phoenix
Capture request context alongside exceptions automatically:
# lib/my_app_web/endpoint.ex
defmodule MyAppWeb.Endpoint do
use Phoenix.Endpoint, otp_app: :my_app
plug Plug.RequestId
plug Plug.Logger
# ... other plugs
plug MyAppWeb.Router
end
Add the Rollbax Plug exception reporter:
# lib/my_app_web/router.ex
defmodule MyAppWeb.Router do
use MyAppWeb, :router
use Rollbax.PlugMiddleware # ← captures unhandled exceptions with request context
pipeline :api do
plug :accepts, ["json"]
end
# ... routes
end
The Rollbax.PlugMiddleware captures the exception, attaches Plug connection metadata (path, method, params, headers), and re-raises so Phoenix can render the error page normally.
Step 3: Custom Exception Reporting
For errors you catch and handle, report them explicitly with context:
# lib/my_app/payment_processor.ex
defmodule MyApp.PaymentProcessor do
require Logger
def charge(user_id, amount_cents, payment_method_id) do
case Stripe.Charge.create(%{
amount: amount_cents,
currency: "usd",
customer: payment_method_id
}) do
{:ok, charge} ->
{:ok, charge}
{:error, %Stripe.Error{code: code, message: message} = error} ->
Rollbax.report_message(:error, "Stripe charge failed", %{
user_id: user_id,
amount_cents: amount_cents,
payment_method_id: payment_method_id,
stripe_error_code: code,
stripe_message: message
})
Logger.error("Payment charge failed",
user_id: user_id,
stripe_code: code
)
{:error, error}
end
rescue
e ->
Rollbax.report(:error, e, __STACKTRACE__, %{
user_id: user_id,
amount_cents: amount_cents,
context: "payment_processor.charge"
})
reraise e, __STACKTRACE__
end
end
Step 4: Error-Level Routing and Custom Data
Differentiate warnings from critical errors and attach structured metadata:
# lib/my_app/error_reporter.ex
defmodule MyApp.ErrorReporter do
@moduledoc """
Centralized error reporting with consistent metadata.
Report to Rollbax with structured context for faster debugging.
"""
def report_exception(exception, stacktrace, context \\ %{}) do
base_context = %{
hostname: System.get_env("HOSTNAME", "unknown"),
release: Application.spec(:my_app, :vsn) |> to_string(),
node: node() |> to_string()
}
Rollbax.report(:error, exception, stacktrace, Map.merge(base_context, context))
end
def report_warning(message, custom_data \\ %{}) do
Rollbax.report_message(:warning, message, custom_data)
end
def report_critical(message, custom_data \\ %{}) do
Rollbax.report_message(:critical, message, custom_data)
end
end
Step 5: Health Check Endpoint
Add a health endpoint that Vigilmon can poll externally:
# lib/my_app_web/controllers/health_controller.ex
defmodule MyAppWeb.HealthController do
use MyAppWeb, :controller
def index(conn, _params) do
checks = %{
database: check_database(),
rollbax: check_rollbax()
}
all_ok = Enum.all?(checks, fn {_, v} -> v.status == "ok" end)
status = if all_ok, do: 200, else: 503
conn
|> put_status(status)
|> json(%{
status: if(all_ok, do: "ok", else: "degraded"),
checks: checks
})
end
defp check_database do
case Ecto.Adapters.SQL.query(MyApp.Repo, "SELECT 1", []) do
{:ok, _} -> %{status: "ok"}
{:error, reason} -> %{status: "error", reason: inspect(reason)}
end
rescue
e -> %{status: "error", reason: Exception.message(e)}
end
defp check_rollbax do
# Rollbax is healthy if it's running (its GenServer is alive)
case Process.whereis(Rollbax.Notifier) do
nil -> %{status: "error", reason: "Rollbax.Notifier not running"}
pid when is_pid(pid) -> %{status: "ok"}
end
end
end
Route it:
# lib/my_app_web/router.ex
scope "/", MyAppWeb do
get "/health", HealthController, :index
end
Step 6: Heartbeat Monitoring for Background Jobs
Report to both Rollbax (on failure) and Vigilmon (on success):
# lib/my_app/workers/report_generator.ex
defmodule MyApp.Workers.ReportGenerator do
use Oban.Worker, queue: :reports
require Logger
@impl Oban.Worker
def perform(%Oban.Job{args: args}) do
with {:ok, data} <- fetch_report_data(args),
{:ok, report} <- generate_report(data),
{:ok, _} <- deliver_report(report) do
ping_vigilmon_heartbeat()
:ok
else
{:error, reason} ->
MyApp.ErrorReporter.report_warning("ReportGenerator job failed", %{
args: args,
reason: inspect(reason)
})
Logger.error("Report generation failed", args: args, reason: inspect(reason))
{:error, reason}
end
rescue
e ->
MyApp.ErrorReporter.report_exception(e, __STACKTRACE__, %{
worker: "ReportGenerator",
args: args
})
reraise e, __STACKTRACE__
end
defp ping_vigilmon_heartbeat do
url = Application.get_env(:my_app, :vigilmon)[:report_heartbeat_url]
if url do
case :httpc.request(:get, {String.to_charlist(url), []}, [{:timeout, 5_000}], []) do
{:ok, _} -> :ok
{:error, reason} ->
Logger.warning("Vigilmon heartbeat ping failed", reason: inspect(reason))
end
end
end
defp fetch_report_data(_args), do: {:ok, %{}}
defp generate_report(_data), do: {:ok, %{}}
defp deliver_report(_report), do: {:ok, :delivered}
end
Step 7: Set Up Monitors in Vigilmon
HTTP uptime monitor:
- Sign in at vigilmon.online
- Click New Monitor → HTTP
- URL:
https://yourdomain.com/health - Interval: 1 minute (paid) or 5 minutes (free)
- Alert condition: non-200 response
Heartbeat monitor for Oban jobs:
- Click New Monitor → Heartbeat
- Set expected interval matching your job schedule (e.g., 25 hours for a daily job with grace period)
- Copy the ping URL
- Set as
VIGILMON_REPORT_HEARTBEAT_URLin your application config
SSL certificate monitor:
- Click New Monitor → SSL
- Enter your domain
- Alert 14 days before expiry — certificate failures produce no Rollbax exceptions
Step 8: Alerting
Slack notification for downtime:
In Vigilmon, go to Notifications → New Channel → Slack and configure your webhook. You'll receive:
🔴 DOWN: yourdomain.com/health
Status: 503 Service Unavailable
Duration: 4 minutes
Action: Check application logs and Rollbar dashboard for root cause
Link Vigilmon alerts to Rollbar:
In your Slack downtime notification, include a deep link to your Rollbar project's error stream filtered by time:
Vigilmon detected downtime at 14:32 UTC.
Check Rollbar: https://rollbar.com/my-org/my-app/items/?status=active&since=1420032000
This gives on-call engineers one-click access to the exceptions that caused the downtime.
Rollbax critical error → Vigilmon status:
Emit a Vigilmon manual check failure when Rollbax reports a critical error that you know will cause downtime:
defmodule MyApp.CriticalErrorHandler do
require Logger
def report_critical_and_degrade(exception, stacktrace, context) do
Rollbax.report(:critical, exception, stacktrace, context)
# Optionally notify a Vigilmon status page webhook to show degraded status
# while your team investigates, even before external monitoring detects it
Logger.error("Critical error reported to Rollbar",
exception: Exception.message(exception)
)
end
end
What You've Built
| What | How |
|------|-----|
| Exception tracking with request context | Rollbax + Rollbax.PlugMiddleware |
| Custom error reporting with metadata | Rollbax.report/4 and Rollbax.report_message/3 |
| External uptime monitoring | Vigilmon HTTP monitor on /health |
| Background job monitoring | Oban worker pinging Vigilmon heartbeat on success, Rollbax on failure |
| SSL certificate monitoring | Vigilmon SSL monitor |
| Linked Slack alerts | Vigilmon downtime alert with Rollbar deep link |
Rollbax tells you what your code did wrong. Vigilmon tells you when your infrastructure went dark. Together they give you full-stack observability: no failure mode is invisible.
Next Steps
- Add deploy tracking in Rollbar so errors are grouped by release version
- Use Rollbar's rate limiting rules to suppress expected errors (e.g., 404s) so your error stream stays actionable
- Set up Vigilmon response time history to catch latency regressions before they cause timeouts that Rollbax would report as exceptions
- Add a Vigilmon monitor for each external API your application depends on, and correlate those outages with spikes in Rollbar error counts
Get started free at vigilmon.online.