File size: 3,357 Bytes
8da2481 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 | defmodule PlausibleWeb.Api.SystemController do
use Plausible
use PlausibleWeb, :controller
require Logger
def info(conn, _params) do
build =
:plausible
|> Application.get_env(:runtime_metadata)
|> Keyword.take([:version, :commit, :created, :tags])
|> Map.new()
geo_database = Plausible.Geo.database_type() || "(not configured)"
json(conn, %{
geo_database: geo_database,
build: build
})
end
def liveness(conn, _params) do
json(conn, %{ok: true})
end
def api_docs(conn, _params) do
json(conn, %{
endpoints: [
%{
method: "GET",
path: "/health",
purpose: "Returns HTTP 200 when the app is ready for Hugging Face Space transition from starting to running."
},
%{
method: "GET",
path: "/api-docs",
purpose: "Exposes documentation of all available API endpoints."
},
%{
method: "POST",
path: "/api/event",
purpose: "Send analytical events directly via the API."
},
%{
method: "GET",
path: "/api/v1/stats/realtime/visitors",
purpose: "Get current number of active visitors on a site."
},
%{
method: "GET",
path: "/api/v1/stats/aggregate",
purpose: "Retrieve aggregate metrics over a given period."
},
%{
method: "GET",
path: "/api/v1/stats/breakdown",
purpose: "Break down stats by metrics like browser, country, etc."
},
%{
method: "GET",
path: "/api/v1/stats/timeseries",
purpose: "Get metrics over time at regular intervals."
}
]
})
end
@task_timeout 15_000
@critical_caches [
Plausible.Site.Cache,
Plausible.Shield.IPRuleCache,
on_ee do
Plausible.Site.TrackerScriptIdCache
else
Plausible.Site.TrackerScriptCache
end
]
def readiness(conn, _params) do
postgres_health_task =
Task.async(fn ->
Ecto.Adapters.SQL.query(Plausible.Repo, "SELECT 1", [])
end)
clickhouse_health_task =
Task.async(fn ->
Ecto.Adapters.SQL.query(Plausible.ClickhouseRepo, "SELECT 1", [])
end)
postgres_health =
case Task.await(postgres_health_task, @task_timeout) do
{:ok, _} ->
"ok"
e ->
Logger.error("Postgres health check failure: #{inspect(e)}")
"error"
end
clickhouse_health =
case Task.await(clickhouse_health_task, @task_timeout) do
{:ok, _} ->
"ok"
e ->
Logger.error("Clickhouse health check failure: #{inspect(e)}")
"error"
end
cache_health =
if postgres_health == "ok" and Enum.all?(@critical_caches, & &1.ready?()) do
"ok"
end
sessions_health =
if Plausible.Session.Transfer.attempted?() do
"ok"
else
"waiting"
end
status =
case {postgres_health, clickhouse_health, cache_health, sessions_health} do
{"ok", "ok", "ok", "ok"} -> 200
_ -> 500
end
put_status(conn, status)
|> json(%{
postgres: postgres_health,
clickhouse: clickhouse_health,
sites_cache: cache_health,
sessions: sessions_health
})
end
end
|