Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down
8 changes: 7 additions & 1 deletion lib/plausible_web/controllers/helpers.ex
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand All @@ -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
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
defmodule PlausibleWeb.Api.ExternalController.DebugMetadataTest do
alias Plausible.{IngestRepo, ClickhouseRepo}
use PlausibleWeb.ConnCase

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
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
defmodule PlausibleWeb.Api.StatsController.DebugMetadataTest do
alias Plausible.{IngestRepo, ClickhouseRepo}
use PlausibleWeb.ConnCase

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
Loading