tutorial

How to Monitor Kino (Elixir) with Vigilmon

Learn how to add uptime monitoring, heartbeat checks, and alerts to Livebook notebook infrastructure using Kino and Vigilmon.

How to Monitor Kino (Elixir) with Vigilmon

Kino is the Elixir library that powers rich interactive output in Livebook notebooks. It provides data tables, charts, frames, form controls, file uploads, and custom JavaScript widgets — turning a Livebook notebook into an interactive data exploration and operational dashboard tool. Teams use Kino-powered notebooks for data analysis, incident investigation, internal reporting pipelines, and runbook automation.

But Livebook is infrastructure. A Livebook server that goes down takes all active notebooks with it. A scheduled notebook that fails silently leaves operators without the report they depend on. A Kino widget backed by a live database connection can surface misleading results if that connection degrades. These are production reliability problems that require external monitoring.

This tutorial adds observability to your Livebook and Kino infrastructure:

  • HTTP uptime monitoring for the Livebook server with Vigilmon
  • Heartbeat monitoring from Kino-powered scheduled notebook runs
  • A Kino status widget that surfaces Vigilmon monitor state inside your notebooks
  • Alerts on Livebook downtime and missed notebook executions

Step 1: Add Kino to a Livebook notebook

Kino is used inside Livebook notebooks, not Mix projects, but you can also add it to a standalone Elixir application that embeds Livebook. For notebook-only use, install dependencies inside a notebook cell:

Mix.install([
  {:kino, "~> 0.14"},
  {:kino_vega_lite, "~> 0.1"},
  {:req, "~> 0.4"}
])

For a self-hosted Livebook server that hosts your Kino notebooks, install Livebook as a Mix release or use the official Docker image:

# Docker (recommended for production)
docker run -d \
  --name livebook \
  -p 8080:8080 \
  -e LIVEBOOK_PASSWORD=your-secure-password \
  -e LIVEBOOK_TOKEN_ENABLED=true \
  -v /data/livebook:/data \
  ghcr.io/livebook-dev/livebook:latest

Step 2: Verify Livebook is running

Livebook exposes a health endpoint at /public/health:

curl http://localhost:8080/public/health
# {"application":"livebook","version":"0.14.0","node":"livebook@hostname"}

This is the endpoint you will monitor with Vigilmon.


Step 3: Set up HTTP monitoring for your Livebook server in Vigilmon

Point Vigilmon at your Livebook health endpoint:

  1. Sign up at vigilmon.online
  2. Click New Monitor → HTTP
  3. Enter https://livebook.yourdomain.com/public/health
  4. Set check interval: 1 minute (paid) or 5 minutes (free)
  5. Under Advanced, add a keyword check for "livebook" to verify the response
  6. Save

Why external monitoring matters for Livebook:

Livebook servers are commonly deployed on a single node with no redundancy. An OOM kill, a disk-full event, or a container restart silently removes all active notebook sessions. Users trying to access notebooks see a failed connection with no explanation. External monitoring detects the outage and alerts your team before users start reporting problems.


Step 4: Send a heartbeat from scheduled notebook runs

Kino notebooks often automate scheduled tasks — generating reports, running data pipelines, sending summaries. Add a heartbeat ping at the end of each notebook to confirm successful completion:

# In your Livebook notebook — last cell of the notebook

defmodule NotebookHeartbeat do
  def ping(heartbeat_url) do
    case Req.get(heartbeat_url, receive_timeout: 15_000) do
      {:ok, %{status: 200}} ->
        Kino.Markdown.new("✅ Heartbeat sent to Vigilmon")
      {:ok, %{status: status}} ->
        Kino.Markdown.new("⚠️ Heartbeat returned HTTP #{status}")
      {:error, reason} ->
        Kino.Markdown.new("❌ Heartbeat failed: #{inspect(reason)}")
    end
  end
end

heartbeat_url = System.get_env("VIGILMON_NOTEBOOK_HEARTBEAT_URL")

if heartbeat_url do
  NotebookHeartbeat.ping(heartbeat_url)
else
  Kino.Markdown.new("ℹ️ No heartbeat URL configured (set VIGILMON_NOTEBOOK_HEARTBEAT_URL)")
end

The Kino.Markdown output makes heartbeat status visible directly in the notebook output. Set the environment variable in Livebook → Settings → Environment Variables.

In Vigilmon, create a Heartbeat monitor:

  1. New Monitor → Heartbeat
  2. Set interval to match your notebook schedule plus a grace window:
    • Hourly notebook → 70-minute interval
    • Daily notebook → 25-hour interval
    • Weekly notebook → 8-day interval
  3. Copy the ping URL → set as VIGILMON_NOTEBOOK_HEARTBEAT_URL in Livebook

Step 5: Build a Kino status dashboard that shows Vigilmon monitor state

Use Kino to build a live status widget inside a notebook that fetches and renders your Vigilmon monitor states:

# Fetch monitor statuses from Vigilmon API
defmodule VigilmonStatus do
  @api_base "https://vigilmon.online/api/v1"

  def fetch_monitors(api_key) do
    case Req.get("#{@api_base}/monitors",
      headers: [{"authorization", "Bearer #{api_key}"}],
      receive_timeout: 10_000
    ) do
      {:ok, %{status: 200, body: body}} -> {:ok, body["monitors"]}
      {:ok, %{status: status}} -> {:error, "API returned #{status}"}
      {:error, reason} -> {:error, inspect(reason)}
    end
  end

  def status_emoji("up"), do: "🟢"
  def status_emoji("down"), do: "🔴"
  def status_emoji("degraded"), do: "🟡"
  def status_emoji(_), do: "⚪"
end

api_key = System.get_env("VIGILMON_API_KEY")

case VigilmonStatus.fetch_monitors(api_key) do
  {:ok, monitors} ->
    rows =
      Enum.map(monitors, fn m ->
        %{
          "Status" => VigilmonStatus.status_emoji(m["status"]),
          "Monitor" => m["name"],
          "Type" => m["type"],
          "Uptime (24h)" => "#{m["uptime_24h"] || "—"}%",
          "Last Check" => m["last_checked_at"] || "—"
        }
      end)

    Kino.DataTable.new(rows, name: "Vigilmon Monitor Status")

  {:error, reason} ->
    Kino.Markdown.new("❌ Could not fetch monitors: #{reason}")
end

Set VIGILMON_API_KEY in Livebook → Settings → Environment Variables. This notebook cell renders a live data table of all your monitors, making it a useful addition to an operations runbook notebook.


Step 6: Add a frame-based live status widget with auto-refresh

For a notebook that acts as a live dashboard, use Kino.Frame to refresh the monitor table on a timer:

frame = Kino.Frame.new()

Kino.listen(500, fn _ ->
  api_key = System.get_env("VIGILMON_API_KEY")

  content =
    case VigilmonStatus.fetch_monitors(api_key) do
      {:ok, monitors} ->
        rows = Enum.map(monitors, fn m ->
          %{
            "Status" => VigilmonStatus.status_emoji(m["status"]),
            "Monitor" => m["name"],
            "Uptime (7d)" => "#{m["uptime_7d"] || "—"}%"
          }
        end)
        Kino.DataTable.new(rows, name: "Live Monitor Status")

      {:error, _} ->
        Kino.Markdown.new("⚠️ Could not reach Vigilmon API")
    end

  Kino.Frame.render(frame, content)
end)

frame

This creates a refreshing status panel inside your Livebook notebook — useful for incident investigation notebooks where you want Vigilmon monitor states alongside your data analysis.


Step 7: Alerts via Slack

In Vigilmon, go to Notifications → New Channel → Slack and paste your incoming webhook URL.

Enable the channel on all monitors. Livebook-related incidents commonly appear as:

  • HTTP health check down (Livebook server crashed or OOM-killed)
  • Response time spike over 3 seconds (Livebook under heavy notebook load)
  • Notebook heartbeat missed (scheduled notebook failed or timed out)

Configure Vigilmon to alert your data/ops team on Livebook downtime and alert your notebook owners on missed heartbeats.


Step 8: Status page

  1. Status Pages → New Status Page in Vigilmon
  2. Add your Livebook HTTP health monitor and all notebook heartbeat monitors
  3. Share the URL with notebook users so they can check server availability before reporting a bug

README badge:

![Livebook Status](https://vigilmon.online/badge/your-monitor-slug)

What you've built

| What | How | |------|-----| | Livebook server uptime | Vigilmon HTTP monitor → /public/health | | Scheduled notebook heartbeat | Req.get ping in last notebook cell | | Heartbeat miss = failed run | Vigilmon heartbeat monitor with schedule-matched interval | | Kino status dashboard | Kino.DataTable rendering Vigilmon API response | | Live refreshing widget | Kino.Frame + Kino.listen auto-refresh | | Slack downtime alerts | Vigilmon Slack notification channel | | Status page | Vigilmon public status page |

Kino makes Livebook notebooks interactive and expressive. Vigilmon ensures the Livebook server stays up and the notebooks that drive your operations keep running on schedule.


Next steps

  • Add a Kino input form to your runbook notebooks that lets operators trigger ad-hoc Vigilmon monitor checks without leaving Livebook
  • Use Vigilmon response time history to detect when Livebook is running slow (a sign of notebook resource contention)
  • Create one heartbeat monitor per critical scheduled notebook so you get per-notebook failure attribution
  • Export Vigilmon uptime data to a Kino chart for a long-term notebook reliability report

Get started free at vigilmon.online.

Monitor your app with Vigilmon

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

Start free →