From 6c329a1ec06f09b91078942bc9a1d894bda61962 Mon Sep 17 00:00:00 2001 From: Artur Pata Date: Wed, 7 Jan 2026 19:53:50 +0200 Subject: [PATCH 1/2] Add team ID to debug metadata --- CHANGELOG.md | 1 + lib/plausible_web/controllers/helpers.ex | 8 +- .../debug_metadata_test.exs | 52 +++++++++ .../stats_controller/debug_metadata_test.exs | 102 ++++++++++++++++++ 4 files changed, 162 insertions(+), 1 deletion(-) create mode 100644 test/plausible_web/controllers/api/external_stats_controller/debug_metadata_test.exs create mode 100644 test/plausible_web/controllers/api/stats_controller/debug_metadata_test.exs diff --git a/CHANGELOG.md b/CHANGELOG.md index f52001d57b62..899ad0bf7822 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,7 @@ All notable changes to this project will be documented in this file. ### Added +- Adds team_id to query debug metadata (saved in system.query_log log_comment column) - A visitor percentage breakdown is now shown on all reports, both on the dashboard and in the detailed breakdown - Shared links can now be limited to a particular segment of the data diff --git a/lib/plausible_web/controllers/helpers.ex b/lib/plausible_web/controllers/helpers.ex index 022fd75a4a74..e66e91c5545e 100644 --- a/lib/plausible_web/controllers/helpers.ex +++ b/lib/plausible_web/controllers/helpers.ex @@ -28,7 +28,8 @@ defmodule PlausibleWeb.ControllerHelpers do phoenix_action: conn.private.phoenix_action |> to_string(), site_id: conn.assigns.site.id, site_domain: conn.assigns.site.domain, - user_id: get_user_id(conn, conn.assigns) + user_id: get_user_id(conn, conn.assigns), + team_id: get_team_id(conn, conn.assigns) } end @@ -40,4 +41,9 @@ defmodule PlausibleWeb.ControllerHelpers do _ -> nil end end + + defp get_team_id(_conn, %{current_team: %Plausible.Teams.Team{id: id}}), do: id + defp get_team_id(_conn, %{site_team: %Plausible.Teams.Team{id: id}}), do: id + defp get_team_id(_conn, %{api_context: :site, site: %Plausible.Site{team_id: id}}), do: id + defp get_team_id(_conn, _assigns), do: nil end diff --git a/test/plausible_web/controllers/api/external_stats_controller/debug_metadata_test.exs b/test/plausible_web/controllers/api/external_stats_controller/debug_metadata_test.exs new file mode 100644 index 000000000000..e25e53d9dc29 --- /dev/null +++ b/test/plausible_web/controllers/api/external_stats_controller/debug_metadata_test.exs @@ -0,0 +1,52 @@ +defmodule PlausibleWeb.Api.ExternalController.DebugMetadataTest do + alias Plausible.{IngestRepo, ClickhouseRepo} + use PlausibleWeb.ConnCase, async: true + + describe "Debug metadata" do + setup [:create_user, :create_api_key, :use_api_key] + + test "is saved correctly", %{conn: conn, user: user} do + domain = :rand.bytes(20) |> Base.url_encode64() + site = new_site(domain: domain, owner: user) + + query = %{ + "site_id" => site.domain, + "date_range" => "all", + "metrics" => ["visitors"] + } + + conn = + post(conn, "api/v2/query", query) + + assert json_response(conn, 200) + + IngestRepo.query!("SYSTEM FLUSH LOGS") + + %{rows: [r1, r2]} = + ClickhouseRepo.query!( + "FROM system.query_log SELECT log_comment WHERE JSONExtractString(log_comment, 'site_domain') = {$0:String}", + [site.domain] + ) + + for [unparsed_log_comment] <- [r1, r2] do + decoded = Jason.decode!(unparsed_log_comment) + + assert_matches ^strict_map(%{ + # params are asserted below + "params" => %{}, + "phoenix_action" => "query", + "phoenix_controller" => + "Elixir.PlausibleWeb.Api.ExternalQueryApiController", + "request_method" => "POST", + "request_path" => "api/v2/query", + "site_domain" => ^site.domain, + "site_id" => ^site.id, + "team_id" => ^team_of(user).id, + "user_id" => ^user.id + }) = decoded + + assert decoded["params"] == query + end + end + end +end diff --git a/test/plausible_web/controllers/api/stats_controller/debug_metadata_test.exs b/test/plausible_web/controllers/api/stats_controller/debug_metadata_test.exs new file mode 100644 index 000000000000..7cb7cf2b74bf --- /dev/null +++ b/test/plausible_web/controllers/api/stats_controller/debug_metadata_test.exs @@ -0,0 +1,102 @@ +defmodule PlausibleWeb.Api.StatsController.DebugMetadataTest do + alias Plausible.{IngestRepo, ClickhouseRepo} + use PlausibleWeb.ConnCase, async: true + + describe "Debug metadata for logged in requests" do + setup [:create_user, :log_in] + + test "for main-graph", %{conn: conn, user: user} do + domain = :rand.bytes(20) |> Base.url_encode64() + site = new_site(domain: domain, owner: user) + conn = get(conn, "/api/stats/#{site.domain}/main-graph") + + assert json_response(conn, 200) + + IngestRepo.query!("SYSTEM FLUSH LOGS") + + %{rows: [r1, r2]} = + ClickhouseRepo.query!( + "FROM system.query_log SELECT log_comment WHERE JSONExtractString(log_comment, 'site_domain') = {$0:String}", + [site.domain] + ) + + for [unparsed_log_comment] <- [r1, r2] do + decoded = Jason.decode!(unparsed_log_comment) + + assert_matches ^strict_map(%{ + "params" => ^strict_map(%{"domain" => ^site.domain}), + "phoenix_action" => "main_graph", + "phoenix_controller" => "Elixir.PlausibleWeb.Api.StatsController", + "request_method" => "GET", + "request_path" => ^"/api/stats/#{site.domain}/main-graph", + "site_domain" => ^site.domain, + "site_id" => ^site.id, + "team_id" => ^team_of(user).id, + "user_id" => ^user.id + }) = decoded + end + end + end + + defp setup_dashboard_case(domain, type) do + site_owner = new_user() + + case type do + "public" -> + site = new_site(domain: domain, owner: site_owner, public: true) + {site, "", %{"domain" => domain}} + + "shared" -> + site = new_site(domain: domain, owner: site_owner) + link = insert(:shared_link, site: site) + + {site, "?auth=#{link.slug}", %{"domain" => domain, "auth" => link.slug}} + end + end + + describe "Debug metadata for non-private dashboard requests" do + setup [:create_user, :log_in] + + for type <- ["public", "shared"] do + test "for /pages request (#{type})", %{ + conn: conn, + user: user + } do + domain = :rand.bytes(20) |> Base.url_encode64() + {site, query_string, expected_params} = setup_dashboard_case(domain, unquote(type)) + conn = get(conn, "/api/stats/#{site.domain}/pages#{query_string}") + + assert json_response(conn, 200) + + IngestRepo.query!("SYSTEM FLUSH LOGS") + + %{rows: [r1, r2]} = + ClickhouseRepo.query!( + "FROM system.query_log SELECT log_comment WHERE JSONExtractString(log_comment, 'site_domain') = {$0:String}", + [site.domain] + ) + + for [unparsed_log_comment] <- [r1, r2] do + decoded = Jason.decode!(unparsed_log_comment) + + assert_matches ^strict_map(%{ + # params are asserted below + "params" => %{}, + "phoenix_action" => "pages", + "phoenix_controller" => "Elixir.PlausibleWeb.Api.StatsController", + "request_method" => "GET", + "request_path" => ^"/api/stats/#{site.domain}/pages", + "site_domain" => ^site.domain, + "site_id" => ^site.id, + # nil team_id because viewing a public/shared dashboard + "team_id" => nil, + # the logged in user ID is included even when viewing a random public dashboard + "user_id" => ^user.id + }) = decoded + + assert decoded["params"] == expected_params + end + end + end + end +end From cc640fb3603273e14736ff348a53366380457f90 Mon Sep 17 00:00:00 2001 From: Artur Pata Date: Mon, 12 Jan 2026 09:00:41 +0200 Subject: [PATCH 2/2] Remove async tag from tests --- .../api/external_stats_controller/debug_metadata_test.exs | 2 +- .../controllers/api/stats_controller/debug_metadata_test.exs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/test/plausible_web/controllers/api/external_stats_controller/debug_metadata_test.exs b/test/plausible_web/controllers/api/external_stats_controller/debug_metadata_test.exs index e25e53d9dc29..cb22646835cc 100644 --- a/test/plausible_web/controllers/api/external_stats_controller/debug_metadata_test.exs +++ b/test/plausible_web/controllers/api/external_stats_controller/debug_metadata_test.exs @@ -1,6 +1,6 @@ defmodule PlausibleWeb.Api.ExternalController.DebugMetadataTest do alias Plausible.{IngestRepo, ClickhouseRepo} - use PlausibleWeb.ConnCase, async: true + use PlausibleWeb.ConnCase describe "Debug metadata" do setup [:create_user, :create_api_key, :use_api_key] diff --git a/test/plausible_web/controllers/api/stats_controller/debug_metadata_test.exs b/test/plausible_web/controllers/api/stats_controller/debug_metadata_test.exs index 7cb7cf2b74bf..abe2af055a5c 100644 --- a/test/plausible_web/controllers/api/stats_controller/debug_metadata_test.exs +++ b/test/plausible_web/controllers/api/stats_controller/debug_metadata_test.exs @@ -1,6 +1,6 @@ defmodule PlausibleWeb.Api.StatsController.DebugMetadataTest do alias Plausible.{IngestRepo, ClickhouseRepo} - use PlausibleWeb.ConnCase, async: true + use PlausibleWeb.ConnCase describe "Debug metadata for logged in requests" do setup [:create_user, :log_in]