Use a genserver to periodically fetch metrics #413
4 changed files with 71 additions and 5 deletions
49
lib/pleroma/prometheus_exporter.ex
Normal file
49
lib/pleroma/prometheus_exporter.ex
Normal file
|
@ -0,0 +1,49 @@
|
|||
defmodule Pleroma.PrometheusExporter do
|
||||
@moduledoc """
|
||||
Exports metrics in Prometheus format.
|
||||
Mostly exists because of https://github.com/beam-telemetry/telemetry_metrics_prometheus_core/issues/52
|
||||
Basically we need to fetch metrics every so often, or the lib will let them pile up and eventually crash the VM.
|
||||
It also sorta acts as a cache so there is that too.
|
||||
"""
|
||||
|
||||
use GenServer
|
||||
require Logger
|
||||
|
||||
def start_link(_opts) do
|
||||
GenServer.start_link(__MODULE__, :ok, name: __MODULE__)
|
||||
end
|
||||
|
||||
def init(_opts) do
|
||||
schedule_next()
|
||||
{:ok, ""}
|
||||
end
|
||||
|
||||
defp schedule_next do
|
||||
Process.send_after(self(), :gather, 60_000)
|
||||
end
|
||||
|
||||
# Scheduled function, gather metrics and schedule next run
|
||||
def handle_info(:gather, _state) do
|
||||
schedule_next()
|
||||
state = TelemetryMetricsPrometheus.Core.scrape()
|
||||
{:noreply, state}
|
||||
end
|
||||
|
||||
# Trigger the call dynamically, mostly for testing
|
||||
def handle_call(:gather, _from, _state) do
|
||||
state = TelemetryMetricsPrometheus.Core.scrape()
|
||||
{:reply, state, state}
|
||||
end
|
||||
|
||||
def handle_call(:show, _from, state) do
|
||||
{:reply, state, state}
|
||||
end
|
||||
|
||||
def show do
|
||||
GenServer.call(__MODULE__, :show)
|
||||
end
|
||||
|
||||
def gather do
|
||||
GenServer.call(__MODULE__, :gather)
|
||||
end
|
||||
end
|
|
@ -15,7 +15,7 @@ defmodule Pleroma.Web.AkkomaAPI.MetricsController do
|
|||
def show(conn, _params) do
|
||||
if Config.get([:instance, :export_prometheus_metrics], true) do
|
||||
conn
|
||||
|> text(TelemetryMetricsPrometheus.Core.scrape())
|
||||
|> text(Pleroma.PrometheusExporter.show())
|
||||
else
|
||||
conn
|
||||
|> send_resp(404, "Not Found")
|
||||
|
|
|
@ -2,6 +2,7 @@ defmodule Pleroma.Web.Telemetry do
|
|||
use Supervisor
|
||||
import Telemetry.Metrics
|
||||
alias Pleroma.Stats
|
||||
alias Pleroma.Config
|
||||
|
||||
def start_link(arg) do
|
||||
Supervisor.start_link(__MODULE__, arg, name: __MODULE__)
|
||||
|
@ -9,14 +10,28 @@ def start_link(arg) do
|
|||
|
||||
@impl true
|
||||
def init(_arg) do
|
||||
children = [
|
||||
{:telemetry_poller, measurements: periodic_measurements(), period: 10_000},
|
||||
{TelemetryMetricsPrometheus.Core, metrics: prometheus_metrics()}
|
||||
]
|
||||
children =
|
||||
[
|
||||
{:telemetry_poller, measurements: periodic_measurements(), period: 10_000}
|
||||
] ++
|
||||
prometheus_children()
|
||||
|
||||
Supervisor.init(children, strategy: :one_for_one)
|
||||
end
|
||||
|
||||
defp prometheus_children do
|
||||
config = Config.get([:instance, :export_prometheus_metrics], true)
|
||||
|
||||
if config do
|
||||
[
|
||||
{TelemetryMetricsPrometheus.Core, metrics: prometheus_metrics()},
|
||||
Pleroma.PrometheusExporter
|
||||
]
|
||||
else
|
||||
[]
|
||||
end
|
||||
end
|
||||
|
||||
# A seperate set of metrics for distributions because phoenix dashboard does NOT handle them well
|
||||
defp distribution_metrics do
|
||||
[
|
||||
|
|
|
@ -5,6 +5,8 @@ defmodule Pleroma.Web.AkkomaAPI.MetricsControllerTest do
|
|||
test "should return metrics when the user has admin:metrics" do
|
||||
%{conn: conn} = oauth_access(["admin:metrics"])
|
||||
|
||||
Pleroma.PrometheusExporter.gather()
|
||||
|
||||
resp =
|
||||
conn
|
||||
|> get("/api/v1/akkoma/metrics")
|
||||
|
|
Loading…
Reference in a new issue