Add basic metrics

This commit is contained in:
Shadowfacts 2021-04-10 15:37:13 -04:00
parent e7211d2042
commit 757c2b696a
Signed by: shadowfacts
GPG Key ID: 94A5AB95422746E5
7 changed files with 114 additions and 3 deletions

View File

@ -14,9 +14,11 @@ defmodule Wiki.Application do
# Start the PubSub system
{Phoenix.PubSub, name: Wiki.PubSub},
# Start the Endpoint (http/https)
WikiWeb.Endpoint
WikiWeb.Endpoint,
# Start a worker by calling: Wiki.Worker.start_link(arg)
# {Wiki.Worker, arg}
{Wiki.MetricStorage, WikiWeb.Telemetry.metrics()},
Wiki.MetricGenerator
]
# See https://hexdocs.pm/elixir/Supervisor.html

View File

@ -0,0 +1,34 @@
defmodule Wiki.MetricGenerator do
use GenServer
alias Wiki.Repo
alias Wiki.Content.{Page, PageLink, Upload}
def start_link(state) do
GenServer.start_link(__MODULE__, state, name: __MODULE__)
end
@impl true
def init(state) do
update_metrics()
# 5 minutes
Process.send_after(self(), :update, 5 * 60 * 1000)
{:ok, state}
end
@impl true
def handle_info(:update, state) do
update_metrics()
{:noreply, state}
end
def update_metrics do
pages = Repo.aggregate(Page, :count)
uploads = Repo.aggregate(Upload, :count)
links = Repo.aggregate(PageLink, :count)
:telemetry.execute([:wiki, :pages], %{count: pages})
:telemetry.execute([:wiki, :uploads], %{count: uploads})
:telemetry.execute([:wiki, :links], %{count: links})
end
end

View File

@ -0,0 +1,66 @@
defmodule Wiki.MetricStorage do
use GenServer
@history_buffer_size 50
def metrics_history(metric) do
GenServer.call(__MODULE__, {:data, metric})
end
def start_link(args) do
GenServer.start_link(__MODULE__, args, name: __MODULE__)
end
@impl true
def init(metrics) do
Process.flag(:trap_exit, true)
metric_histories_map =
metrics
|> Enum.map(fn metric ->
attach_handler(metric)
{metric, CircularBuffer.new(@history_buffer_size)}
end)
|> Map.new()
{:ok, metric_histories_map}
end
@impl true
def terminate(_, metrics) do
for metric <- metrics do
:telemetry.detach({__MODULE__, metric, self()})
end
:ok
end
defp attach_handler(%{event_name: name_list} = metric) do
:telemetry.attach(
{__MODULE__, metric, self()},
name_list,
&__MODULE__.handle_event/4,
metric
)
end
def handle_event(_event_name, data, metadata, metric) do
if data = Phoenix.LiveDashboard.extract_datapoint_for_metric(metric, data, metadata) do
GenServer.cast(__MODULE__, {:telemetry_metric, data, metric})
end
end
@impl true
def handle_cast({:telemetry_metric, data, metric}, state) do
{:noreply, update_in(state[metric], &CircularBuffer.insert(&1, data))}
end
@impl true
def handle_call({:data, metric}, _from, state) do
if history = state[metric] do
{:reply, CircularBuffer.to_list(history), state}
else
{:reply, [], state}
end
end
end

View File

@ -56,7 +56,9 @@ defmodule WikiWeb.Router do
scope "/", WikiWeb do
pipe_through [:browser, :require_authenticated_user, :require_admin_user]
live_dashboard "/dashboard", metrics: WikiWeb.Telemetry
live_dashboard "/dashboard",
metrics: WikiWeb.Telemetry,
metrics_history: {Wiki.MetricStorage, :metrics_history, []}
end
scope "/", WikiWeb do

View File

@ -21,6 +21,11 @@ defmodule WikiWeb.Telemetry do
def metrics do
[
# Wiki Metrics
last_value("wiki.pages.count"),
last_value("wiki.uploads.count"),
last_value("wiki.links.count"),
# Phoenix Metrics
summary("phoenix.endpoint.stop.duration",
unit: {:native, :millisecond}

View File

@ -47,7 +47,8 @@ defmodule Wiki.MixProject do
{:jason, "~> 1.0"},
{:plug_cowboy, "~> 2.0"},
{:phx_gen_auth, "~> 0.4.0", only: :dev, runtime: false},
{:earmark, "~> 1.4.10"}
{:earmark, "~> 1.4.10"},
{:circular_buffer, "~> 0.3.0"}
]
end

View File

@ -1,6 +1,7 @@
%{
"argon2_elixir": {:hex, :argon2_elixir, "2.3.0", "e251bdafd69308e8c1263e111600e6d68bd44f23d2cccbe43fcb1a417a76bc8e", [:make, :mix], [{:comeonin, "~> 5.3", [hex: :comeonin, repo: "hexpm", optional: false]}, {:elixir_make, "~> 0.6", [hex: :elixir_make, repo: "hexpm", optional: false]}], "hexpm", "28ccb63bff213aecec1f7f3dde9648418b031f822499973281d8f494b9d5a3b3"},
"bcrypt_elixir": {:hex, :bcrypt_elixir, "2.2.0", "3df902b81ce7fa8867a2ae30d20a1da6877a2c056bfb116fd0bc8a5f0190cea4", [:make, :mix], [{:comeonin, "~> 5.3", [hex: :comeonin, repo: "hexpm", optional: false]}, {:elixir_make, "~> 0.6", [hex: :elixir_make, repo: "hexpm", optional: false]}], "hexpm", "762be3fcb779f08207531bc6612cca480a338e4b4357abb49f5ce00240a77d1e"},
"circular_buffer": {:hex, :circular_buffer, "0.3.0", "3eaa7e349ab07cff53dd1c25eb179ac14913fe1e407762260402a291dac4af96", [:mix], [], "hexpm", "f582b2ce394f8965cadf43c5b140f399b83dc8404aef701cb41c928c4bac1943"},
"comeonin": {:hex, :comeonin, "5.3.1", "7fe612b739c78c9c1a75186ef2d322ce4d25032d119823269d0aa1e2f1e20025", [:mix], [], "hexpm", "d6222483060c17f0977fad1b7401ef0c5863c985a64352755f366aee3799c245"},
"connection": {:hex, :connection, "1.0.4", "a1cae72211f0eef17705aaededacac3eb30e6625b04a6117c1b2db6ace7d5976", [:mix], [], "hexpm", "4a0850c9be22a43af9920a71ab17c051f5f7d45c209e40269a1938832510e4d9"},
"cowboy": {:hex, :cowboy, "2.8.0", "f3dc62e35797ecd9ac1b50db74611193c29815401e53bac9a5c0577bd7bc667d", [:rebar3], [{:cowlib, "~> 2.9.1", [hex: :cowlib, repo: "hexpm", optional: false]}, {:ranch, "~> 1.7.1", [hex: :ranch, repo: "hexpm", optional: false]}], "hexpm", "4643e4fba74ac96d4d152c75803de6fad0b3fa5df354c71afdd6cbeeb15fac8a"},