commit: 9fcf918e1ca9f01b8fbe2af15bd8065627b61d25
parent c945a8a467a98306512d82fd1b226f3cff9c1183
Author: lain <lain@soykaf.club>
Date: Sun, 11 Jan 2026 05:40:47 +0000
Merge branch 'phnt/oban-web' into 'develop'
Add Oban Web and upgrade LiveView, plug
See merge request pleroma/pleroma!4422
Diffstat:
9 files changed, 73 insertions(+), 5 deletions(-)
diff --git a/changelog.d/oban-web.add b/changelog.d/oban-web.add
@@ -0,0 +1 @@
+Added Oban Web dashboard located at /pleroma/oban
diff --git a/changelog.d/phoenix-livedashboard-move.change b/changelog.d/phoenix-livedashboard-move.change
@@ -0,0 +1 @@
+Moved Phoenix LiveDashboard to /pleroma/live_dashboard
diff --git a/docs/administration/dashboards.md b/docs/administration/dashboards.md
@@ -0,0 +1,47 @@
+# Dashboards
+
+Pleroma comes with two types of backend dashboards viewable to instance administrators:
+
+* [Phoenix LiveDashboard](https://hexdocs.pm/phoenix_live_dashboard/Phoenix.LiveDashboard.html) - A general system oriented dashboard for viewing statistics about Pleroma resource consumption, Pleroma's database and Pleroma's job processor (Oban).
+* [Oban Web](https://hexdocs.pm/oban_web/overview.html) - A dashboard specific to Oban for viewing Oban statistics, managing jobs and job queues.
+
+!!! note
+ Both dashboards require working Websockets.
+ If your browser or web server don't support Websockets, both dashboards either won't update or will not display all information.
+
+## Phoenix LiveDashboard
+
+Instance administrators can access this dashboard at `/pleroma/live_dashboard`, giving a simple overview of software versions including Erlang and Elixir versions, instance uptime and resource consumption.
+
+This dashboard gives insights into the current state of the BEAM VM running Pleroma code and database statistics including basic diagnostics.
+It can be useful for troubleshooting of some issues namely regarding database performance.
+
+### Relevant dashboard tabs
+
+* Home - A general overview of system information including software versions, uptime and memory BEAM memory consumption.
+* OS Data - Information about the OS and system such as CPU load, memory usage and disk usage.
+* Ecto Stats - Information about the Pleroma database.
+ - Diagnose - Basic database diagnostics, including a `bloat` warning when an index or a table have excessive bloat, which can lead to bad database performance.
+ - Bloat - A table showing size of "bloat" (unused wasted space) in database tables and indexes. Very high bloat size in the `activities` and `objects` tables can lead to bad performance especially on slower disks such as on most VPS providers.
+ - Db settings - A small list of PostgreSQL settings mostly relevant to database performance.
+ - Total table size - Shows sizes of all database tables including indexes sorted by size, useful for quickly checking overall database size.
+ - Long running queries - A list of of slow database queries and their duration. Multiple entries with duration in multiple seconds indicate a slowly performing database.
+* Oban - Shows a list of all Oban jobs.
+
+!!! note
+ The DB bloat warning for `index 'oban_jobs::oban_jobs_args_index'` in Ecto Stats can be safely ignored.
+
+## Oban Web
+
+An advanced dashboard and management console viewable to instance administrators specifically for Oban, Pleroma's job processor.
+It allows managing jobs, including force retrying failed jobs and job deletion.
+It can be accessed at `/pleroma/oban`.
+
+!!! danger
+ This dashboard is very powerful! If you are unsure what a certain feature does, don't use it.
+ Changing individual queue state/settings in the "Queues" view is heavily discouraged.
+
+* Shows a real time chart of either a number of executed jobs, or job execution/wait time per a given time frame and the state/queue/worker.
+* Shows a list of jobs in each state, their argument, number of attempts and execution/scheduled time.
+* Selecting one or multiple jobs in the list allows performing actions like canceling/deleting and retrying.
+* Clicking on a job shows a detailed view including the full argument, when it was inserted, information about its attempts, and performing actions on it.
diff --git a/lib/pleroma/web/fallback/redirect_controller.ex b/lib/pleroma/web/fallback/redirect_controller.ex
@@ -29,6 +29,11 @@ defmodule Pleroma.Web.Fallback.RedirectController do
)
end
+ def live_dashboard(conn, _params) do
+ conn
+ |> redirect(to: "/pleroma/live_dashboard")
+ end
+
def redirector(conn, _params, code \\ 200) do
{:ok, index_content} = File.read(index_file_path(conn))
diff --git a/lib/pleroma/web/router.ex b/lib/pleroma/web/router.ex
@@ -5,6 +5,7 @@
defmodule Pleroma.Web.Router do
use Pleroma.Web, :router
import Phoenix.LiveDashboard.Router
+ import Oban.Web.Router
pipeline :accepts_html do
plug(:accepts, ["html"])
@@ -1043,7 +1044,8 @@ defmodule Pleroma.Web.Router do
scope "/" do
pipe_through([:pleroma_html, :authenticate, :require_admin])
- live_dashboard("/phoenix/live_dashboard", additional_pages: [oban: Oban.LiveDashboard])
+ live_dashboard("/pleroma/live_dashboard", additional_pages: [oban: Oban.LiveDashboard])
+ oban_dashboard("/pleroma/oban")
end
# Test-only routes needed to test action dispatching and plug chain execution
@@ -1084,14 +1086,20 @@ defmodule Pleroma.Web.Router do
get("/:maybe_nickname_or_id", RedirectController, :redirector_with_meta)
match(:*, "/api/pleroma/*path", LegacyPleromaApiRerouterPlug, [])
get("/api/*path", RedirectController, :api_not_implemented)
+ get("/phoenix/live_dashboard", RedirectController, :live_dashboard)
get("/*path", RedirectController, :redirector_with_preload)
options("/*path", RedirectController, :empty)
end
+ # /pleroma/{phoenix,oban}/* need to get filtered out from api routes for frontend configuration
+ # to not drop admin overrides for /pleroma/admin.
+ @non_api_routes ["/pleroma/live_dashboard", "/pleroma/oban"]
+
def get_api_routes do
Phoenix.Router.routes(__MODULE__)
|> Enum.reject(fn r -> r.plug == Pleroma.Web.Fallback.RedirectController end)
+ |> Enum.reject(fn r -> String.starts_with?(r.path, @non_api_routes) end)
|> Enum.map(fn r ->
r.path
|> String.split("/", trim: true)
diff --git a/mix.exs b/mix.exs
@@ -130,7 +130,7 @@ defmodule Pleroma.Mixfile do
{:ecto_enum, "~> 1.4"},
{:postgrex, ">= 0.20.0"},
{:phoenix_html, "~> 3.3"},
- {:phoenix_live_view, "~> 0.19.0"},
+ {:phoenix_live_view, "~> 1.1.0"},
{:phoenix_live_dashboard, "~> 0.8.0"},
{:telemetry_metrics, "~> 0.6"},
{:telemetry_poller, "~> 1.0"},
@@ -140,6 +140,7 @@ defmodule Pleroma.Mixfile do
{:oban_plugins_lazarus,
git: "https://git.pleroma.social/pleroma/elixir-libraries/oban_plugins_lazarus.git",
ref: "e49fc355baaf0e435208bf5f534d31e26e897711"},
+ {:oban_web, "~> 2.11"},
{:gettext, "~> 0.20"},
{:bcrypt_elixir, "~> 2.2"},
{:trailing_format_plug, "~> 0.0.7"},
diff --git a/mix.lock b/mix.lock
@@ -95,7 +95,9 @@
"nodex": {:git, "https://git.pleroma.social/pleroma/nodex", "cb6730f943cfc6aad674c92161be23a8411f15d1", [ref: "cb6730f943cfc6aad674c92161be23a8411f15d1"]},
"oban": {:hex, :oban, "2.19.4", "045adb10db1161dceb75c254782f97cdc6596e7044af456a59decb6d06da73c1", [:mix], [{:ecto_sql, "~> 3.10", [hex: :ecto_sql, repo: "hexpm", optional: false]}, {:ecto_sqlite3, "~> 0.9", [hex: :ecto_sqlite3, repo: "hexpm", optional: true]}, {:igniter, "~> 0.5", [hex: :igniter, repo: "hexpm", optional: true]}, {:jason, "~> 1.1", [hex: :jason, repo: "hexpm", optional: true]}, {:myxql, "~> 0.7", [hex: :myxql, repo: "hexpm", optional: true]}, {:postgrex, "~> 0.16", [hex: :postgrex, repo: "hexpm", optional: true]}, {:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "5fcc6219e6464525b808d97add17896e724131f498444a292071bf8991c99f97"},
"oban_live_dashboard": {:hex, :oban_live_dashboard, "0.1.1", "8aa4ceaf381c818f7d5c8185cc59942b8ac82ef0cf559881aacf8d3f8ac7bdd3", [:mix], [{:oban, "~> 2.15", [hex: :oban, repo: "hexpm", optional: false]}, {:phoenix_live_dashboard, "~> 0.7", [hex: :phoenix_live_dashboard, repo: "hexpm", optional: false]}], "hexpm", "16dc4ce9c9a95aa2e655e35ed4e675652994a8def61731a18af85e230e1caa63"},
+ "oban_met": {:hex, :oban_met, "1.0.5", "bb633ab06448dab2ef9194f6688d33b3d07fc3f2ad793a1a08f4dfbb2cc9fe50", [:mix], [{:oban, "~> 2.19", [hex: :oban, repo: "hexpm", optional: false]}], "hexpm", "64664d50805bbfd3903aeada1f3c39634652a87844797ee400b0bcc95a28f5ea"},
"oban_plugins_lazarus": {:git, "https://git.pleroma.social/pleroma/elixir-libraries/oban_plugins_lazarus.git", "e49fc355baaf0e435208bf5f534d31e26e897711", [ref: "e49fc355baaf0e435208bf5f534d31e26e897711"]},
+ "oban_web": {:hex, :oban_web, "2.11.6", "53933cb4253c4d9f1098ee311c06f07935259f0e564dcf2d66bae4cc98e317fe", [:mix], [{:jason, "~> 1.2", [hex: :jason, repo: "hexpm", optional: false]}, {:oban, "~> 2.19", [hex: :oban, repo: "hexpm", optional: false]}, {:oban_met, "~> 1.0", [hex: :oban_met, repo: "hexpm", optional: false]}, {:phoenix, "~> 1.7", [hex: :phoenix, repo: "hexpm", optional: false]}, {:phoenix_html, "~> 3.3 or ~> 4.0", [hex: :phoenix_html, repo: "hexpm", optional: false]}, {:phoenix_live_view, "~> 1.0", [hex: :phoenix_live_view, repo: "hexpm", optional: false]}, {:phoenix_pubsub, "~> 2.1", [hex: :phoenix_pubsub, repo: "hexpm", optional: false]}], "hexpm", "576d94b705688c313694c2c114ca21aa0f8f2ad1b9ca45c052c5ba316d3e8d10"},
"octo_fetch": {:hex, :octo_fetch, "0.4.0", "074b5ecbc08be10b05b27e9db08bc20a3060142769436242702931c418695b19", [:mix], [{:castore, "~> 0.1 or ~> 1.0", [hex: :castore, repo: "hexpm", optional: false]}, {:ssl_verify_fun, "~> 1.1", [hex: :ssl_verify_fun, repo: "hexpm", optional: false]}], "hexpm", "cf8be6f40cd519d7000bb4e84adcf661c32e59369ca2827c4e20042eda7a7fc6"},
"open_api_spex": {:hex, :open_api_spex, "3.22.0", "fbf90dc82681dc042a4ee79853c8e989efbba73d9e87439085daf849bbf8bc20", [:mix], [{:decimal, "~> 1.0 or ~> 2.0", [hex: :decimal, repo: "hexpm", optional: true]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}, {:plug, "~> 1.7", [hex: :plug, repo: "hexpm", optional: false]}, {:poison, "~> 3.0 or ~> 4.0 or ~> 5.0 or ~> 6.0", [hex: :poison, repo: "hexpm", optional: true]}, {:ymlr, "~> 2.0 or ~> 3.0 or ~> 4.0 or ~> 5.0", [hex: :ymlr, repo: "hexpm", optional: true]}], "hexpm", "dd751ddbdd709bb4a5313e9a24530da6e66594773c7242a0c2592cbd9f589063"},
"parse_trans": {:hex, :parse_trans, "3.4.1", "6e6aa8167cb44cc8f39441d05193be6e6f4e7c2946cb2759f015f8c56b76e5ff", [:rebar3], [], "hexpm", "620a406ce75dada827b82e453c19cf06776be266f5a67cff34e1ef2cbb60e49a"},
@@ -105,12 +107,12 @@
"phoenix_html": {:hex, :phoenix_html, "3.3.4", "42a09fc443bbc1da37e372a5c8e6755d046f22b9b11343bf885067357da21cb3", [:mix], [{:plug, "~> 1.5", [hex: :plug, repo: "hexpm", optional: true]}], "hexpm", "0249d3abec3714aff3415e7ee3d9786cb325be3151e6c4b3021502c585bf53fb"},
"phoenix_live_dashboard": {:hex, :phoenix_live_dashboard, "0.8.7", "405880012cb4b706f26dd1c6349125bfc903fb9e44d1ea668adaf4e04d4884b7", [:mix], [{:ecto, "~> 3.6.2 or ~> 3.7", [hex: :ecto, repo: "hexpm", optional: true]}, {:ecto_mysql_extras, "~> 0.5", [hex: :ecto_mysql_extras, repo: "hexpm", optional: true]}, {:ecto_psql_extras, "~> 0.7", [hex: :ecto_psql_extras, repo: "hexpm", optional: true]}, {:ecto_sqlite3_extras, "~> 1.1.7 or ~> 1.2.0", [hex: :ecto_sqlite3_extras, repo: "hexpm", optional: true]}, {:mime, "~> 1.6 or ~> 2.0", [hex: :mime, repo: "hexpm", optional: false]}, {:phoenix_live_view, "~> 0.19 or ~> 1.0", [hex: :phoenix_live_view, repo: "hexpm", optional: false]}, {:telemetry_metrics, "~> 0.6 or ~> 1.0", [hex: :telemetry_metrics, repo: "hexpm", optional: false]}], "hexpm", "3a8625cab39ec261d48a13b7468dc619c0ede099601b084e343968309bd4d7d7"},
"phoenix_live_reload": {:hex, :phoenix_live_reload, "1.3.3", "3a53772a6118d5679bf50fc1670505a290e32a1d195df9e069d8c53ab040c054", [:mix], [{:file_system, "~> 0.2.1 or ~> 0.3", [hex: :file_system, repo: "hexpm", optional: false]}, {:phoenix, "~> 1.4", [hex: :phoenix, repo: "hexpm", optional: false]}], "hexpm", "766796676e5f558dbae5d1bdb066849673e956005e3730dfd5affd7a6da4abac"},
- "phoenix_live_view": {:hex, :phoenix_live_view, "0.19.5", "6e730595e8e9b8c5da230a814e557768828fd8dfeeb90377d2d8dbb52d4ec00a", [:mix], [{:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}, {:phoenix, "~> 1.6.15 or ~> 1.7.0", [hex: :phoenix, repo: "hexpm", optional: false]}, {:phoenix_html, "~> 3.3", [hex: :phoenix_html, repo: "hexpm", optional: false]}, {:phoenix_template, "~> 1.0", [hex: :phoenix_template, repo: "hexpm", optional: false]}, {:phoenix_view, "~> 2.0", [hex: :phoenix_view, repo: "hexpm", optional: true]}, {:telemetry, "~> 0.4.2 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "b2eaa0dd3cfb9bd7fb949b88217df9f25aed915e986a28ad5c8a0d054e7ca9d3"},
+ "phoenix_live_view": {:hex, :phoenix_live_view, "1.1.19", "c95e9acbc374fb796ee3e24bfecc8213123c74d9f9e45667ca40bb0a4d242953", [:mix], [{:igniter, ">= 0.6.16 and < 1.0.0-0", [hex: :igniter, repo: "hexpm", optional: true]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}, {:lazy_html, "~> 0.1.0", [hex: :lazy_html, repo: "hexpm", optional: true]}, {:phoenix, "~> 1.6.15 or ~> 1.7.0 or ~> 1.8.0-rc", [hex: :phoenix, repo: "hexpm", optional: false]}, {:phoenix_html, "~> 3.3 or ~> 4.0", [hex: :phoenix_html, repo: "hexpm", optional: false]}, {:phoenix_template, "~> 1.0", [hex: :phoenix_template, repo: "hexpm", optional: false]}, {:phoenix_view, "~> 2.0", [hex: :phoenix_view, repo: "hexpm", optional: true]}, {:plug, "~> 1.15", [hex: :plug, repo: "hexpm", optional: false]}, {:telemetry, "~> 0.4.2 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "d5ad357d6b21562a5b431f0ad09dfe76db9ce5648c6949f1aac334c8c4455d32"},
"phoenix_pubsub": {:hex, :phoenix_pubsub, "2.1.3", "3168d78ba41835aecad272d5e8cd51aa87a7ac9eb836eabc42f6e57538e3731d", [:mix], [], "hexpm", "bba06bc1dcfd8cb086759f0edc94a8ba2bc8896d5331a1e2c2902bf8e36ee502"},
"phoenix_swoosh": {:hex, :phoenix_swoosh, "1.2.1", "b74ccaa8046fbc388a62134360ee7d9742d5a8ae74063f34eb050279de7a99e1", [:mix], [{:finch, "~> 0.8", [hex: :finch, repo: "hexpm", optional: true]}, {:hackney, "~> 1.10", [hex: :hackney, repo: "hexpm", optional: true]}, {:phoenix, "~> 1.6", [hex: :phoenix, repo: "hexpm", optional: true]}, {:phoenix_html, "~> 3.0 or ~> 4.0", [hex: :phoenix_html, repo: "hexpm", optional: true]}, {:phoenix_view, "~> 1.0 or ~> 2.0", [hex: :phoenix_view, repo: "hexpm", optional: false]}, {:swoosh, "~> 1.5", [hex: :swoosh, repo: "hexpm", optional: false]}], "hexpm", "4000eeba3f9d7d1a6bf56d2bd56733d5cadf41a7f0d8ffe5bb67e7d667e204a2"},
"phoenix_template": {:hex, :phoenix_template, "1.0.4", "e2092c132f3b5e5b2d49c96695342eb36d0ed514c5b252a77048d5969330d639", [:mix], [{:phoenix_html, "~> 2.14.2 or ~> 3.0 or ~> 4.0", [hex: :phoenix_html, repo: "hexpm", optional: true]}], "hexpm", "2c0c81f0e5c6753faf5cca2f229c9709919aba34fab866d3bc05060c9c444206"},
"phoenix_view": {:hex, :phoenix_view, "2.0.4", "b45c9d9cf15b3a1af5fb555c674b525391b6a1fe975f040fb4d913397b31abf4", [:mix], [{:phoenix_html, "~> 2.14.2 or ~> 3.0 or ~> 4.0", [hex: :phoenix_html, repo: "hexpm", optional: true]}, {:phoenix_template, "~> 1.0", [hex: :phoenix_template, repo: "hexpm", optional: false]}], "hexpm", "4e992022ce14f31fe57335db27a28154afcc94e9983266835bb3040243eb620b"},
- "plug": {:hex, :plug, "1.18.1", "5067f26f7745b7e31bc3368bc1a2b818b9779faa959b49c934c17730efc911cf", [:mix], [{:mime, "~> 1.0 or ~> 2.0", [hex: :mime, repo: "hexpm", optional: false]}, {:plug_crypto, "~> 1.1.1 or ~> 1.2 or ~> 2.0", [hex: :plug_crypto, repo: "hexpm", optional: false]}, {:telemetry, "~> 0.4.3 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "57a57db70df2b422b564437d2d33cf8d33cd16339c1edb190cd11b1a3a546cc2"},
+ "plug": {:hex, :plug, "1.19.1", "09bac17ae7a001a68ae393658aa23c7e38782be5c5c00c80be82901262c394c0", [:mix], [{:mime, "~> 1.0 or ~> 2.0", [hex: :mime, repo: "hexpm", optional: false]}, {:plug_crypto, "~> 1.1.1 or ~> 1.2 or ~> 2.0", [hex: :plug_crypto, repo: "hexpm", optional: false]}, {:telemetry, "~> 0.4.3 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "560a0017a8f6d5d30146916862aaf9300b7280063651dd7e532b8be168511e62"},
"plug_cowboy": {:hex, :plug_cowboy, "2.7.4", "729c752d17cf364e2b8da5bdb34fb5804f56251e88bb602aff48ae0bd8673d11", [:mix], [{:cowboy, "~> 2.7", [hex: :cowboy, repo: "hexpm", optional: false]}, {:cowboy_telemetry, "~> 0.3", [hex: :cowboy_telemetry, repo: "hexpm", optional: false]}, {:plug, "~> 1.14", [hex: :plug, repo: "hexpm", optional: false]}], "hexpm", "9b85632bd7012615bae0a5d70084deb1b25d2bcbb32cab82d1e9a1e023168aa3"},
"plug_crypto": {:hex, :plug_crypto, "2.1.1", "19bda8184399cb24afa10be734f84a16ea0a2bc65054e23a62bb10f06bc89491", [:mix], [], "hexpm", "6470bce6ffe41c8bd497612ffde1a7e4af67f36a15eea5f921af71cf3e11247c"},
"plug_static_index_html": {:hex, :plug_static_index_html, "1.0.0", "840123d4d3975585133485ea86af73cb2600afd7f2a976f9f5fd8b3808e636a0", [:mix], [{:plug, "~> 1.0", [hex: :plug, repo: "hexpm", optional: false]}], "hexpm", "79fd4fcf34d110605c26560cbae8f23c603ec4158c08298bd4360fdea90bb5cf"},
diff --git a/test/pleroma/web/fallback_test.exs b/test/pleroma/web/fallback_test.exs
@@ -77,6 +77,10 @@ defmodule Pleroma.Web.FallbackTest do
assert redirected_to(get(conn, "/pleroma/admin")) =~ "/pleroma/admin/"
end
+ test "GET /phoenix/live_dashboard -> /pleroma/live_dashboard", %{conn: conn} do
+ assert redirected_to(get(conn, "/phoenix/live_dashboard")) =~ "/pleroma/live_dashboard"
+ end
+
test "OPTIONS /*path", %{conn: conn} do
assert conn
|> options("/foo")
diff --git a/test/pleroma/web/plugs/frontend_static_plug_test.exs b/test/pleroma/web/plugs/frontend_static_plug_test.exs
@@ -106,7 +106,6 @@ defmodule Pleroma.Web.Plugs.FrontendStaticPlugTest do
"manifest.json",
"auth",
"proxy",
- "phoenix",
"test",
"user_exists",
"check_password"