From 09326ffa56cae01f80d0125f4b8770d077e02967 Mon Sep 17 00:00:00 2001 From: floatingghost Date: Wed, 7 Dec 2022 11:12:34 +0000 Subject: [PATCH] Diagnostics tasks (#348) a bunch of ways to get query plans to help with debugging Co-authored-by: FloatingGhost Reviewed-on: https://akkoma.dev/AkkomaGang/akkoma/pulls/348 --- .../administration/CLI_tasks/diagnostics.md | 30 ++++++++ lib/mix/tasks/pleroma/diagnostics.ex | 77 +++++++++++++++++++ lib/pleroma/web/activity_pub/activity_pub.ex | 4 +- 3 files changed, 109 insertions(+), 2 deletions(-) create mode 100644 docs/docs/administration/CLI_tasks/diagnostics.md create mode 100644 lib/mix/tasks/pleroma/diagnostics.ex diff --git a/docs/docs/administration/CLI_tasks/diagnostics.md b/docs/docs/administration/CLI_tasks/diagnostics.md new file mode 100644 index 000000000..25572da8a --- /dev/null +++ b/docs/docs/administration/CLI_tasks/diagnostics.md @@ -0,0 +1,30 @@ +# Diagnostics + +A few tasks to help with debugging, troubleshooting, and diagnosing problems. + +They mostly relate to common postgres queries. + +## Home timeline query plan + +This task will print a query plan for the home timeline of a given user. + +=== "OTP" + + `./bin/pleroma_ctl diagnostics home_timeline ` + +=== "From Source" + + `mix pleroma.diagnostics home_timeline ` + +## User timeline query plan + +This task will print a query plan for the user timeline of a given user, +from the perspective of another given user. + +=== "OTP" + + `./bin/pleroma_ctl diagnostics user_timeline ` + +=== "From Source" + + `mix pleroma.diagnostics user_timeline ` \ No newline at end of file diff --git a/lib/mix/tasks/pleroma/diagnostics.ex b/lib/mix/tasks/pleroma/diagnostics.ex new file mode 100644 index 000000000..6e83bf6f0 --- /dev/null +++ b/lib/mix/tasks/pleroma/diagnostics.ex @@ -0,0 +1,77 @@ +defmodule Mix.Tasks.Pleroma.Diagnostics do + alias Pleroma.Repo + alias Pleroma.User + + require Logger + require Pleroma.Constants + + import Mix.Pleroma + import Ecto.Query + use Mix.Task + + def run(["home_timeline", nickname]) do + start_pleroma() + user = Repo.get_by!(User, nickname: nickname) + Logger.info("Home timeline query #{user.nickname}") + + followed_hashtags = + user + |> User.followed_hashtags() + |> Enum.map(& &1.id) + + params = + %{limit: 20} + |> Map.put(:type, ["Create", "Announce"]) + |> Map.put(:blocking_user, user) + |> Map.put(:muting_user, user) + |> Map.put(:reply_filtering_user, user) + |> Map.put(:announce_filtering_user, user) + |> Map.put(:user, user) + |> Map.put(:followed_hashtags, followed_hashtags) + |> Map.delete(:local) + + list_memberships = Pleroma.List.memberships(user) + recipients = [user.ap_id | User.following(user)] + + query = + Pleroma.Web.ActivityPub.ActivityPub.fetch_activities_query( + recipients ++ list_memberships, + params + ) + |> limit(20) + + Ecto.Adapters.SQL.explain(Repo, :all, query, analyze: true, timeout: :infinity) + |> IO.puts() + end + + def run(["user_timeline", nickname, reading_nickname]) do + start_pleroma() + user = Repo.get_by!(User, nickname: nickname) + reading_user = Repo.get_by!(User, nickname: reading_nickname) + Logger.info("User timeline query #{user.nickname}") + + params = + %{limit: 20} + |> Map.put(:type, ["Create", "Announce"]) + |> Map.put(:user, reading_user) + |> Map.put(:actor_id, user.ap_id) + |> Map.put(:pinned_object_ids, Map.keys(user.pinned_objects)) + + list_memberships = Pleroma.List.memberships(user) + + recipients = + %{ + godmode: params[:godmode], + reading_user: reading_user + } + |> Pleroma.Web.ActivityPub.ActivityPub.user_activities_recipients() + + query = + (recipients ++ list_memberships) + |> Pleroma.Web.ActivityPub.ActivityPub.fetch_activities_query(params) + |> limit(20) + + Ecto.Adapters.SQL.explain(Repo, :all, query, analyze: true, timeout: :infinity) + |> IO.puts() + end +end diff --git a/lib/pleroma/web/activity_pub/activity_pub.ex b/lib/pleroma/web/activity_pub/activity_pub.ex index 3f46a8ecb..d700128c0 100644 --- a/lib/pleroma/web/activity_pub/activity_pub.ex +++ b/lib/pleroma/web/activity_pub/activity_pub.ex @@ -739,9 +739,9 @@ defp fetch_activities_for_reading_user(reading_user, params) do |> fetch_activities(params, :offset) end - defp user_activities_recipients(%{godmode: true}), do: [] + def user_activities_recipients(%{godmode: true}), do: [] - defp user_activities_recipients(%{reading_user: reading_user}) do + def user_activities_recipients(%{reading_user: reading_user}) do if not is_nil(reading_user) and reading_user.local do [ Constants.as_public(),