forked from AkkomaGang/akkoma
allow users with admin:metrics to read app metrics
This commit is contained in:
parent
b8be8192fb
commit
c2054f82ab
14 changed files with 125 additions and 27 deletions
1
.gitignore
vendored
1
.gitignore
vendored
|
@ -76,3 +76,4 @@ docs/site
|
|||
|
||||
# docker stuff
|
||||
docker-db
|
||||
*.iml
|
||||
|
|
|
@ -3,9 +3,13 @@ defmodule Pleroma.Web.AkkomaAPI.MetricsController do
|
|||
|
||||
alias Pleroma.Web.Plugs.OAuthScopesPlug
|
||||
|
||||
@unauthenticated_access %{fallback: :proceed_unauthenticated, scopes: []}
|
||||
plug(:skip_auth)
|
||||
|
||||
plug(
|
||||
OAuthScopesPlug,
|
||||
%{scopes: ["admin:metrics"]}
|
||||
when action in [
|
||||
:show
|
||||
]
|
||||
)
|
||||
|
||||
def show(conn, _params) do
|
||||
stats = TelemetryMetricsPrometheus.Core.scrape()
|
||||
|
|
|
@ -197,7 +197,11 @@ defp incorporate_conn_info(action_settings, %{params: params} = conn) do
|
|||
})
|
||||
end
|
||||
|
||||
defp ip(%{remote_ip: remote_ip}) do
|
||||
defp ip(%{remote_ip: remote_ip}) when is_binary(remote_ip) do
|
||||
remote_ip
|
||||
end
|
||||
|
||||
defp ip(%{remote_ip: remote_ip}) when is_tuple(remote_ip) do
|
||||
remote_ip
|
||||
|> Tuple.to_list()
|
||||
|> Enum.join(".")
|
||||
|
|
|
@ -868,7 +868,11 @@ defmodule Pleroma.Web.Router do
|
|||
|
||||
scope "/" do
|
||||
pipe_through([:pleroma_html, :authenticate, :require_admin])
|
||||
live_dashboard("/phoenix/live_dashboard", metrics: {Pleroma.Web.Telemetry, :live_dashboard_metrics}, csp_nonce_assign_key: :csp_nonce)
|
||||
|
||||
live_dashboard("/phoenix/live_dashboard",
|
||||
metrics: {Pleroma.Web.Telemetry, :live_dashboard_metrics},
|
||||
csp_nonce_assign_key: :csp_nonce
|
||||
)
|
||||
end
|
||||
|
||||
# Test-only routes needed to test action dispatching and plug chain execution
|
||||
|
@ -907,6 +911,7 @@ defmodule Pleroma.Web.Router do
|
|||
scope "/", Pleroma.Web.Fallback do
|
||||
get("/registration/:token", RedirectController, :registration_page)
|
||||
get("/:maybe_nickname_or_id", RedirectController, :redirector_with_meta)
|
||||
get("/api/*path", RedirectController, :api_not_implemented)
|
||||
get("/*path", RedirectController, :redirector_with_preload)
|
||||
|
||||
options("/*path", RedirectController, :empty)
|
||||
|
|
|
@ -11,16 +11,13 @@ def start_link(arg) do
|
|||
def init(_arg) do
|
||||
children = [
|
||||
{:telemetry_poller, measurements: periodic_measurements(), period: 10_000},
|
||||
{TelemetryMetricsPrometheus, metrics: prometheus_metrics(), plug_cowboy_opts: [ip: {127, 0, 0, 1}]}
|
||||
{TelemetryMetricsPrometheus.Core, metrics: prometheus_metrics()}
|
||||
]
|
||||
|
||||
Supervisor.init(children, strategy: :one_for_one)
|
||||
end
|
||||
|
||||
@doc """
|
||||
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
|
||||
[
|
||||
distribution(
|
||||
|
@ -110,8 +107,6 @@ defp summary_metrics do
|
|||
summary("vm.total_run_queue_lengths.total"),
|
||||
summary("vm.total_run_queue_lengths.cpu"),
|
||||
summary("vm.total_run_queue_lengths.io"),
|
||||
|
||||
|
||||
last_value("pleroma.local_users.total"),
|
||||
last_value("pleroma.domains.total"),
|
||||
last_value("pleroma.local_statuses.total")
|
||||
|
|
|
@ -4,17 +4,33 @@
|
|||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width,initial-scale=1,minimal-ui">
|
||||
<title><%= Pleroma.Config.get([:instance, :name]) %></title>
|
||||
<link rel="stylesheet" href="/instance/static.css">
|
||||
<link rel="stylesheet" href="/static-fe/static-fe.css">
|
||||
<link rel="stylesheet" href="/static-fe/forms.css">
|
||||
</head>
|
||||
<body>
|
||||
<div class="instance-header">
|
||||
<a class="instance-header__content" href="/">
|
||||
<img class="instance-header__thumbnail" src="<%= Pleroma.Config.get([:instance, :instance_thumbnail]) %>">
|
||||
<h1 class="instance-header__title"><%= Pleroma.Config.get([:instance, :name]) %></h1>
|
||||
|
||||
<div class="background-image"></div>
|
||||
<nav>
|
||||
<div class="inner-nav">
|
||||
<a class="site-brand" href="/">
|
||||
<img class="favicon" src="/favicon.png" />
|
||||
<span><%= Pleroma.Config.get([:instance, :name]) %></span>
|
||||
</a>
|
||||
</div>
|
||||
</nav>
|
||||
<div class="container">
|
||||
<div class="underlay"></div>
|
||||
<div class="column main flex">
|
||||
<div class="panel oauth">
|
||||
<%= @inner_content %>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
|
||||
<style>
|
||||
:root {
|
||||
--background-image: url("<%= Pleroma.Config.get([:instance, :background_image]) %>");
|
||||
}
|
||||
</style>
|
||||
</html>
|
||||
|
|
|
@ -1,2 +1,8 @@
|
|||
<h1><%= Gettext.dpgettext("static_pages", "oauth authorized page title", "Successfully authorized") %></h1>
|
||||
<h2><%= raw Gettext.dpgettext("static_pages", "oauth token code message", "Token code is <br>%{token}", token: safe_to_string(html_escape(@auth.token))) %></h2>
|
||||
<div>
|
||||
<div class="panel-heading">
|
||||
<%= Gettext.dpgettext("static_pages", "oauth authorized page title", "Successfully authorized") %>
|
||||
</div>
|
||||
<div class="panel-content">
|
||||
<%= raw Gettext.dpgettext("static_pages", "oauth token code message", "Token code is <br>%{token}", token: safe_to_string(html_escape(@auth.token))) %>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -20,7 +20,9 @@
|
|||
|
||||
<div class="container__content">
|
||||
<%= if @app do %>
|
||||
<div class="panel-heading">
|
||||
<p><%= raw Gettext.dpgettext("static_pages", "oauth authorize message", "Application <strong>%{client_name}</strong> is requesting access to your account.", client_name: safe_to_string(html_escape(@app.client_name))) %></p>
|
||||
</div>
|
||||
<%= render @view_module, "_scopes.html", Map.merge(assigns, %{form: f}) %>
|
||||
<% end %>
|
||||
|
||||
|
|
2
mix.exs
2
mix.exs
|
@ -163,7 +163,7 @@ defp deps do
|
|||
{:telemetry, "~> 0.3"},
|
||||
{:telemetry_poller, "~> 0.4"},
|
||||
{:telemetry_metrics, "~> 0.4"},
|
||||
{:telemetry_metrics_prometheus, "~> 1.1.0"},
|
||||
{:telemetry_metrics_prometheus_core, "~> 1.1.0"},
|
||||
{:poolboy, "~> 1.5"},
|
||||
{:recon, "~> 2.5"},
|
||||
{:joken, "~> 2.0"},
|
||||
|
|
BIN
priv/static/static-fe/forms.css
Normal file
BIN
priv/static/static-fe/forms.css
Normal file
Binary file not shown.
Binary file not shown.
65
scripts/create_metrics_app.sh
Executable file
65
scripts/create_metrics_app.sh
Executable file
|
@ -0,0 +1,65 @@
|
|||
#!/bin/sh
|
||||
|
||||
read -p "Instance URL (e.g https://example.com): " INSTANCE_URL
|
||||
|
||||
echo "Creating oauth app..."
|
||||
|
||||
RESP=$(curl \
|
||||
-XPOST \
|
||||
$INSTANCE_URL/api/v1/apps \
|
||||
--silent \
|
||||
--data-urlencode 'client_name=fedibash' \
|
||||
--data-urlencode 'redirect_uris=urn:ietf:wg:oauth:2.0:oob' \
|
||||
--data-urlencode 'scopes=admin:metrics' \
|
||||
--header "Content-Type: application/x-www-form-urlencoded"
|
||||
)
|
||||
|
||||
client_id=$(echo $RESP | jq -r .client_id)
|
||||
client_secret=$(echo $RESP | jq -r .client_secret)
|
||||
|
||||
if [ -z "$client_id"]; then
|
||||
echo "Could not create an app"
|
||||
echo "$RESP"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "Please visit the following URL and input the code provided"
|
||||
AUTH_URL="$INSTANCE_URL/oauth/authorize?client_id=$client_id&redirect_uri=urn:ietf:wg:oauth:2.0:oob&scope=admin:metrics&response_type=code"
|
||||
if [ ! -z "$BROWSER" ]; then
|
||||
$BROWSER $AUTH_URL
|
||||
fi;
|
||||
|
||||
echo $AUTH_URL
|
||||
|
||||
read -p "Code: " CODE
|
||||
|
||||
echo "Requesting code..."
|
||||
|
||||
RESP=$(curl \
|
||||
-XPOST \
|
||||
$INSTANCE_URL/oauth/token \
|
||||
--silent \
|
||||
--header "Content-Type: application/x-www-form-urlencoded" \
|
||||
--data-urlencode "client_id=$client_id" \
|
||||
--data-urlencode "client_secret=$client_secret" \
|
||||
--data-urlencode "code=$CODE" \
|
||||
--data-urlencode "grant_type=authorization_code" \
|
||||
--data-urlencode 'redirect_uri=urn:ietf:wg:oauth:2.0:oob' \
|
||||
--data-urlencode "scope=admin:metrics"
|
||||
)
|
||||
|
||||
ACCESS_TOKEN="$(echo $RESP | jq -r .access_token)"
|
||||
|
||||
echo "Token is $ACCESS_TOKEN"
|
||||
DOMAIN=$(echo $INSTANCE_URL | sed -e 's/^https:\/\///')
|
||||
|
||||
echo "Use the following config in your prometheus.yml:
|
||||
- job_name: akkoma
|
||||
scheme: https
|
||||
authorization:
|
||||
credentials: $ACCESS_TOKEN
|
||||
metrics_path: /api/v1/akkoma/metrics
|
||||
static_configs:
|
||||
- targets:
|
||||
- $DOMAIN
|
||||
"
|
|
@ -554,7 +554,7 @@ def oauth_app_factory do
|
|||
%Pleroma.Web.OAuth.App{
|
||||
client_name: sequence(:client_name, &"Some client #{&1}"),
|
||||
redirect_uris: "https://example.com/callback",
|
||||
scopes: ["read", "write", "follow", "push", "admin"],
|
||||
scopes: ["read", "write", "follow", "push"],
|
||||
website: "https://example.com",
|
||||
client_id: Ecto.UUID.generate(),
|
||||
client_secret: "aaa;/&bbb"
|
||||
|
|
Loading…
Reference in a new issue