tutorial

How to Monitor Ratatouille with Vigilmon

Ratatouille is a declarative TUI framework for Elixir built on ExTermbox. Learn how to monitor your terminal applications for process health, rendering loops, and background job reliability using Vigilmon.

Ratatouille is a React-inspired TUI framework for Elixir that runs on top of ExTermbox, letting you build interactive terminal applications with a declarative component model — views, event loops, and state management in pure Elixir. Whether you're building CLI dashboards, admin tools, or interactive DevOps utilities, Ratatouille applications run as long-lived BEAM processes that depend on external services, background tasks, and system resources. Vigilmon gives you the uptime monitoring, heartbeat checks, and alerting to catch failures in those dependencies before your users hit broken interfaces.

What You'll Set Up

  • HTTP health endpoint exposing the application's readiness and external dependency status
  • Cron heartbeat to confirm background data-fetching workers are running
  • Latency alerts for slow upstream services that feed the TUI's display data
  • SSL certificate monitoring for any HTTPS endpoints the application polls

Prerequisites

  • Elixir 1.14+ with ratatouille and ex_termbox in your mix.exs
  • A Plug- or Bandit-based HTTP server (even minimal) for the health endpoint
  • A free Vigilmon account

Step 1: Add a Health Endpoint Alongside Your TUI Process

Ratatouille applications are typically supervised OTP applications. Add a minimal Plug-based health endpoint as a sibling process under your supervisor so Vigilmon can reach it independently of the terminal UI:

# mix.exs
defp deps do
  [
    {:ratatouille, "~> 0.5"},
    {:bandit, "~> 1.0"},
    {:plug, "~> 1.15"},
    # ... other deps
  ]
end
# lib/my_app/health_router.ex
defmodule MyApp.HealthRouter do
  use Plug.Router

  plug :match
  plug :dispatch

  get "/health" do
    checks = %{
      data_worker: check_data_worker(),
      upstream_api: check_upstream_api()
    }

    status = if Enum.all?(checks, fn {_, v} -> v == :ok end), do: 200, else: 503

    conn
    |> put_resp_content_type("application/json")
    |> send_resp(status, Jason.encode!(%{status: if(status == 200, do: "ok", else: "degraded"), checks: checks}))
  end

  defp check_data_worker do
    case Process.whereis(MyApp.DataWorker) do
      nil -> :error
      pid -> if Process.alive?(pid), do: :ok, else: :error
    end
  end

  defp check_upstream_api do
    case :httpc.request(:head, {'https://api.example.com/ping', []}, [{:timeout, 3000}], []) do
      {:ok, {{_, 200, _}, _, _}} -> :ok
      _ -> :error
    end
  end
end

Register it in your supervision tree:

# lib/my_app/application.ex
defmodule MyApp.Application do
  use Application

  def start(_type, _args) do
    children = [
      {Bandit, plug: MyApp.HealthRouter, port: 4001},
      MyApp.DataWorker,
      {Ratatouille.Runtime.Supervisor, runtime: [app: MyApp.TuiApp]}
    ]

    opts = [strategy: :one_for_one, name: MyApp.Supervisor]
    Supervisor.start_link(children, opts)
  end
end

Verify the health endpoint independently of the terminal UI:

curl http://localhost:4001/health
# {"status":"ok","checks":{"data_worker":"ok","upstream_api":"ok"}}

Step 2: Add the Monitor in Vigilmon

  1. Log in to vigilmon.online and click Add Monitor.
  2. Set Type to HTTP / HTTPS.
  3. Enter http://your-server:4001/health (or your public health URL).
  4. Set Check interval to 1 minute.
  5. Set Expected HTTP status to 200.
  6. Under Response body, enable Contains keyword and enter "ok".
  7. Click Save.

The keyword check detects the case where the health route returns 200 but reports a degraded downstream service — common when an upstream API becomes unreachable while the TUI process itself stays alive.


Step 3: Heartbeat Monitoring for the Data Fetching Worker

Ratatouille TUIs display live data — metrics dashboards, log tails, API monitors. The background workers that fetch and push updates to the runtime state can fail silently: the BEAM supervisor restarts them, but if the restart fails or the upstream is permanently unavailable, your TUI just shows stale data with no alert.

Add a Vigilmon cron heartbeat:

  1. In Vigilmon, click Add MonitorCron Heartbeat.
  2. Set Expected ping interval to match your worker's poll cycle (e.g. 60 seconds for a 1-minute refresh).
  3. Copy the heartbeat URL (e.g. https://vigilmon.online/heartbeat/abc123).

Ping Vigilmon at the end of each successful data fetch:

# lib/my_app/data_worker.ex
defmodule MyApp.DataWorker do
  use GenServer

  require Logger

  @interval 60_000

  def start_link(_), do: GenServer.start_link(__MODULE__, %{}, name: __MODULE__)

  @impl true
  def init(state) do
    schedule_fetch()
    {:ok, state}
  end

  @impl true
  def handle_info(:fetch, state) do
    case fetch_data() do
      {:ok, data} ->
        Ratatouille.Runtime.subscribe(MyApp.TuiApp, {:data_updated, data})
        ping_heartbeat()
      {:error, reason} ->
        Logger.error("DataWorker fetch failed: #{inspect(reason)}")
        # No ping → Vigilmon alerts after the window expires
    end

    schedule_fetch()
    {:noreply, state}
  end

  defp schedule_fetch, do: Process.send_after(self(), :fetch, @interval)

  defp ping_heartbeat do
    heartbeat_url = System.get_env("VIGILMON_HEARTBEAT_URL")
    if heartbeat_url do
      :httpc.request(:get, {String.to_charlist(heartbeat_url), []}, [{:timeout, 5000}], [])
    end
  end

  defp fetch_data do
    # Your data fetching logic here
    {:ok, %{}}
  end
end

If the worker crashes and the supervisor's restart budget is exhausted, Vigilmon alerts you within one missed interval — no more silent stale dashboards.


Step 4: Alert on Slow Upstream API Responses

TUI dashboards are only as fast as their data sources. Add a dedicated Vigilmon HTTP monitor for each upstream API your Ratatouille app polls:

  1. Click Add MonitorHTTP / HTTPS.
  2. Enter the upstream API URL (e.g. https://api.example.com/data).
  3. Set Check interval to 1 minute.
  4. Under Advanced, set Response time threshold to your SLA (e.g. 2000 ms).
  5. Click Save.

This catches upstream slowdowns before they cascade into unresponsive TUI updates. If the API starts responding in 4 seconds instead of 200 ms, Vigilmon alerts you while users are still seeing a sluggish — not yet broken — interface.

You can also use Telemetry in your data worker to emit latency measurements:

defp fetch_data_with_telemetry do
  start = System.monotonic_time()
  result = fetch_data()
  duration = System.monotonic_time() - start

  :telemetry.execute(
    [:my_app, :data_worker, :fetch],
    %{duration: duration},
    %{result: elem(result, 0)}
  )

  result
end

Step 5: Monitor SSL Certificates for Upstream HTTPS Endpoints

If your Ratatouille app polls HTTPS APIs, add certificate expiry monitoring:

  1. Open the upstream API monitor from Step 4.
  2. Enable Monitor SSL certificate.
  3. Set Alert when certificate expires in less than 21 days.
  4. Click Save.

Expired upstream certificates cause your data worker to receive TLS errors rather than data — which means your TUI shows stale values with no obvious reason why.


Step 6: Configure Alert Channels

  1. Go to Alert Channels in Vigilmon and add Slack, email, or PagerDuty.
  2. Set Consecutive failures before alert to 2 to filter transient blips.
  3. Use Maintenance windows when you're deliberately restarting the Ratatouille process for a new release:
curl -X POST https://vigilmon.online/api/maintenance \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -d '{"monitor_id": "abc123", "duration_minutes": 10}'

Consider routing data-worker heartbeat failures to a high-priority channel (PagerDuty) while routing upstream latency warnings to a lower-priority Slack channel — the severity differs significantly.


Summary

| Monitor | Target | What It Catches | |---|---|---| | HTTP health check | /health on port 4001 | DataWorker crash, upstream API unreachable | | Cron heartbeat | Heartbeat URL | Silent data-fetch failure, stale TUI state | | Upstream HTTP monitor | External API URL | Slow or unavailable data source | | SSL certificate | Upstream HTTPS endpoint | TLS expiry causing fetch errors |

Ratatouille's declarative model makes it easy to build rich terminal applications — Vigilmon makes sure the processes and services behind those applications stay alive and responsive. With a health endpoint, heartbeat monitoring, and upstream latency alerts, you'll know about failures before your dashboard shows stale data.

Monitor your app with Vigilmon

Free plan — 5 monitors, no credit card required. Up and running in 60 seconds.

Start free →