Use a genserver to periodically fetch metrics
Ref https://github.com/beam-telemetry/telemetry_metrics_prometheus_core/issues/52
This commit is contained in:
parent
6be3383a09
commit
6e646c4cbc
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
|
def show(conn, _params) do
|
||||||
if Config.get([:instance, :export_prometheus_metrics], true) do
|
if Config.get([:instance, :export_prometheus_metrics], true) do
|
||||||
conn
|
conn
|
||||||
|> text(TelemetryMetricsPrometheus.Core.scrape())
|
|> text(Pleroma.PrometheusExporter.show())
|
||||||
else
|
else
|
||||||
conn
|
conn
|
||||||
|> send_resp(404, "Not Found")
|
|> send_resp(404, "Not Found")
|
||||||
|
|
|
@ -2,6 +2,7 @@ defmodule Pleroma.Web.Telemetry do
|
||||||
use Supervisor
|
use Supervisor
|
||||||
import Telemetry.Metrics
|
import Telemetry.Metrics
|
||||||
alias Pleroma.Stats
|
alias Pleroma.Stats
|
||||||
|
alias Pleroma.Config
|
||||||
|
|
||||||
def start_link(arg) do
|
def start_link(arg) do
|
||||||
Supervisor.start_link(__MODULE__, arg, name: __MODULE__)
|
Supervisor.start_link(__MODULE__, arg, name: __MODULE__)
|
||||||
|
@ -9,14 +10,28 @@ def start_link(arg) do
|
||||||
|
|
||||||
@impl true
|
@impl true
|
||||||
def init(_arg) do
|
def init(_arg) do
|
||||||
children = [
|
children =
|
||||||
{:telemetry_poller, measurements: periodic_measurements(), period: 10_000},
|
[
|
||||||
{TelemetryMetricsPrometheus.Core, metrics: prometheus_metrics()}
|
{:telemetry_poller, measurements: periodic_measurements(), period: 10_000}
|
||||||
]
|
] ++
|
||||||
|
prometheus_children()
|
||||||
|
|
||||||
Supervisor.init(children, strategy: :one_for_one)
|
Supervisor.init(children, strategy: :one_for_one)
|
||||||
end
|
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
|
# A seperate set of metrics for distributions because phoenix dashboard does NOT handle them well
|
||||||
defp distribution_metrics do
|
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
|
test "should return metrics when the user has admin:metrics" do
|
||||||
%{conn: conn} = oauth_access(["admin:metrics"])
|
%{conn: conn} = oauth_access(["admin:metrics"])
|
||||||
|
|
||||||
|
Pleroma.PrometheusExporter.gather()
|
||||||
|
|
||||||
resp =
|
resp =
|
||||||
conn
|
conn
|
||||||
|> get("/api/v1/akkoma/metrics")
|
|> get("/api/v1/akkoma/metrics")
|
||||||
|
|
Loading…
Reference in a new issue