diff --git a/app/lib/admin/metrics/measure/instance_accounts_measure.rb b/app/lib/admin/metrics/measure/instance_accounts_measure.rb index 889a5e6f05f..04de2b9b1c0 100644 --- a/app/lib/admin/metrics/measure/instance_accounts_measure.rb +++ b/app/lib/admin/metrics/measure/instance_accounts_measure.rb @@ -27,25 +27,11 @@ class Admin::Metrics::Measure::InstanceAccountsMeasure < Admin::Metrics::Measure nil end - def sql_array - [sql_query_string, { start_at: @start_at, end_at: @end_at, domain: params[:domain] }] - end - - def sql_query_string - <<~SQL.squish - SELECT axis.*, ( - WITH new_accounts AS ( - SELECT accounts.id - FROM accounts - WHERE date_trunc('day', accounts.created_at)::date = axis.period - AND #{account_domain_sql(params[:include_subdomains])} - ) - SELECT count(*) FROM new_accounts - ) AS value - FROM ( - #{generated_series_days} - ) AS axis - SQL + def data_source + Account + .select(:id) + .where(account_domain_sql, domain: params[:domain]) + .where(daily_period(:accounts)) end def params diff --git a/app/lib/admin/metrics/measure/instance_followers_measure.rb b/app/lib/admin/metrics/measure/instance_followers_measure.rb index fa934c6b96c..726d6d8f037 100644 --- a/app/lib/admin/metrics/measure/instance_followers_measure.rb +++ b/app/lib/admin/metrics/measure/instance_followers_measure.rb @@ -27,26 +27,12 @@ class Admin::Metrics::Measure::InstanceFollowersMeasure < Admin::Metrics::Measur nil end - def sql_array - [sql_query_string, { start_at: @start_at, end_at: @end_at, domain: params[:domain] }] - end - - def sql_query_string - <<~SQL.squish - SELECT axis.*, ( - WITH new_followers AS ( - SELECT follows.id - FROM follows - INNER JOIN accounts ON follows.account_id = accounts.id - WHERE date_trunc('day', follows.created_at)::date = axis.period - AND #{account_domain_sql(params[:include_subdomains])} - ) - SELECT count(*) FROM new_followers - ) AS value - FROM ( - #{generated_series_days} - ) AS axis - SQL + def data_source + Follow + .select(:id) + .joins(:account) + .where(account_domain_sql, domain: params[:domain]) + .where(daily_period(:follows)) end def params diff --git a/app/lib/admin/metrics/measure/instance_follows_measure.rb b/app/lib/admin/metrics/measure/instance_follows_measure.rb index 3f3ab73fc90..24e8a32945f 100644 --- a/app/lib/admin/metrics/measure/instance_follows_measure.rb +++ b/app/lib/admin/metrics/measure/instance_follows_measure.rb @@ -27,26 +27,12 @@ class Admin::Metrics::Measure::InstanceFollowsMeasure < Admin::Metrics::Measure: nil end - def sql_array - [sql_query_string, { start_at: @start_at, end_at: @end_at, domain: params[:domain] }] - end - - def sql_query_string - <<~SQL.squish - SELECT axis.*, ( - WITH new_follows AS ( - SELECT follows.id - FROM follows - INNER JOIN accounts ON follows.target_account_id = accounts.id - WHERE date_trunc('day', follows.created_at)::date = axis.period - AND #{account_domain_sql(params[:include_subdomains])} - ) - SELECT count(*) FROM new_follows - ) AS value - FROM ( - #{generated_series_days} - ) AS axis - SQL + def data_source + Follow + .select(:id) + .joins(:target_account) + .where(account_domain_sql, domain: params[:domain]) + .where(daily_period(:follows)) end def params diff --git a/app/lib/admin/metrics/measure/instance_media_attachments_measure.rb b/app/lib/admin/metrics/measure/instance_media_attachments_measure.rb index 996ca52e0bb..1e1089f2173 100644 --- a/app/lib/admin/metrics/measure/instance_media_attachments_measure.rb +++ b/app/lib/admin/metrics/measure/instance_media_attachments_measure.rb @@ -36,25 +36,23 @@ class Admin::Metrics::Measure::InstanceMediaAttachmentsMeasure < Admin::Metrics: nil end - def sql_array - [sql_query_string, { start_at: @start_at, end_at: @end_at, domain: params[:domain] }] + def data_source + MediaAttachment + .select(media_size_total) + .joins(:account) + .where(account_domain_sql, domain: params[:domain]) + .where(daily_period(:media_attachments)) end - def sql_query_string + def select_target <<~SQL.squish - SELECT axis.*, ( - WITH new_media_attachments AS ( - SELECT COALESCE(media_attachments.file_file_size, 0) + COALESCE(media_attachments.thumbnail_file_size, 0) AS size - FROM media_attachments - INNER JOIN accounts ON accounts.id = media_attachments.account_id - WHERE date_trunc('day', media_attachments.created_at)::date = axis.period - AND #{account_domain_sql(params[:include_subdomains])} - ) - SELECT COALESCE(SUM(size), 0) FROM new_media_attachments - ) AS value - FROM ( - #{generated_series_days} - ) AS axis + COALESCE(SUM(size), 0) + SQL + end + + def media_size_total + <<~SQL.squish + COALESCE(media_attachments.file_file_size, 0) + COALESCE(media_attachments.thumbnail_file_size, 0) AS size SQL end diff --git a/app/lib/admin/metrics/measure/instance_reports_measure.rb b/app/lib/admin/metrics/measure/instance_reports_measure.rb index ae1bb6e68de..2b760c4e843 100644 --- a/app/lib/admin/metrics/measure/instance_reports_measure.rb +++ b/app/lib/admin/metrics/measure/instance_reports_measure.rb @@ -27,26 +27,12 @@ class Admin::Metrics::Measure::InstanceReportsMeasure < Admin::Metrics::Measure: nil end - def sql_array - [sql_query_string, { start_at: @start_at, end_at: @end_at, domain: params[:domain] }] - end - - def sql_query_string - <<~SQL.squish - SELECT axis.*, ( - WITH new_reports AS ( - SELECT reports.id - FROM reports - INNER JOIN accounts ON accounts.id = reports.target_account_id - WHERE date_trunc('day', reports.created_at)::date = axis.period - AND #{account_domain_sql(params[:include_subdomains])} - ) - SELECT count(*) FROM new_reports - ) AS value - FROM ( - #{generated_series_days} - ) AS axis - SQL + def data_source + Report + .select(:id) + .joins(:target_account) + .where(account_domain_sql, domain: params[:domain]) + .where(daily_period(:reports)) end def params diff --git a/app/lib/admin/metrics/measure/instance_statuses_measure.rb b/app/lib/admin/metrics/measure/instance_statuses_measure.rb index 324d427b18b..3a3304b97c3 100644 --- a/app/lib/admin/metrics/measure/instance_statuses_measure.rb +++ b/app/lib/admin/metrics/measure/instance_statuses_measure.rb @@ -27,27 +27,13 @@ class Admin::Metrics::Measure::InstanceStatusesMeasure < Admin::Metrics::Measure nil end - def sql_array - [sql_query_string, { start_at: @start_at, end_at: @end_at, domain: params[:domain], earliest_status_id: earliest_status_id, latest_status_id: latest_status_id }] - end - - def sql_query_string - <<~SQL.squish - SELECT axis.*, ( - WITH new_statuses AS ( - SELECT statuses.id - FROM statuses - INNER JOIN accounts ON accounts.id = statuses.account_id - WHERE statuses.id BETWEEN :earliest_status_id AND :latest_status_id - AND #{account_domain_sql(params[:include_subdomains])} - AND date_trunc('day', statuses.created_at)::date = axis.period - ) - SELECT count(*) FROM new_statuses - ) AS value - FROM ( - #{generated_series_days} - ) AS axis - SQL + def data_source + Status + .select(:id) + .joins(:account) + .where(account_domain_sql, domain: params[:domain]) + .where(status_range_sql, earliest_status_id: earliest_status_id, latest_status_id: latest_status_id) + .where(daily_period(:statuses)) end def earliest_status_id diff --git a/app/lib/admin/metrics/measure/new_users_measure.rb b/app/lib/admin/metrics/measure/new_users_measure.rb index 32057154d6b..d70f86086ee 100644 --- a/app/lib/admin/metrics/measure/new_users_measure.rb +++ b/app/lib/admin/metrics/measure/new_users_measure.rb @@ -17,23 +17,9 @@ class Admin::Metrics::Measure::NewUsersMeasure < Admin::Metrics::Measure::BaseMe User.where(created_at: previous_time_period).count end - def sql_array - [sql_query_string, { start_at: @start_at, end_at: @end_at }] - end - - def sql_query_string - <<~SQL.squish - SELECT axis.*, ( - WITH new_users AS ( - SELECT users.id - FROM users - WHERE date_trunc('day', users.created_at)::date = axis.period - ) - SELECT count(*) FROM new_users - ) AS value - FROM ( - #{generated_series_days} - ) AS axis - SQL + def data_source + User + .select(:id) + .where(daily_period(:users)) end end diff --git a/app/lib/admin/metrics/measure/opened_reports_measure.rb b/app/lib/admin/metrics/measure/opened_reports_measure.rb index 47de38bbe64..8d901dfd169 100644 --- a/app/lib/admin/metrics/measure/opened_reports_measure.rb +++ b/app/lib/admin/metrics/measure/opened_reports_measure.rb @@ -17,23 +17,9 @@ class Admin::Metrics::Measure::OpenedReportsMeasure < Admin::Metrics::Measure::B Report.where(created_at: previous_time_period).count end - def sql_array - [sql_query_string, { start_at: @start_at, end_at: @end_at }] - end - - def sql_query_string - <<~SQL.squish - SELECT axis.*, ( - WITH new_reports AS ( - SELECT reports.id - FROM reports - WHERE date_trunc('day', reports.created_at)::date = axis.period - ) - SELECT count(*) FROM new_reports - ) AS value - FROM ( - #{generated_series_days} - ) AS axis - SQL + def data_source + Report + .select(:id) + .where(daily_period(:reports)) end end diff --git a/app/lib/admin/metrics/measure/query_helper.rb b/app/lib/admin/metrics/measure/query_helper.rb index 47cfc63e5c5..864673239dd 100644 --- a/app/lib/admin/metrics/measure/query_helper.rb +++ b/app/lib/admin/metrics/measure/query_helper.rb @@ -15,19 +15,49 @@ module Admin::Metrics::Measure::QueryHelper ActiveRecord::Base.sanitize_sql_array(sql_array) end - def generated_series_days - Arel.sql( - <<~SQL.squish - SELECT generate_series(:start_at::timestamp, :end_at::timestamp, '1 day')::date AS period - SQL - ) + def sql_array + [sql_query_string, { start_at: @start_at, end_at: @end_at }] end - def account_domain_sql(include_subdomains) - if include_subdomains - "accounts.domain IN (SELECT domain FROM instances WHERE reverse('.' || domain) LIKE reverse('.' || :domain::text))" + def sql_query_string + <<~SQL.squish + SELECT axis.*, ( + WITH data_source AS (#{data_source.to_sql}) + SELECT #{select_target} FROM data_source + ) AS value + FROM ( + SELECT generate_series(:start_at::timestamp, :end_at::timestamp, '1 day')::date AS period + ) AS axis + SQL + end + + def select_target + <<~SQL.squish + COUNT(*) + SQL + end + + def daily_period(table, column = :created_at) + <<~SQL.squish + DATE_TRUNC('day', #{table}.#{column})::date = axis.period + SQL + end + + def status_range_sql + <<~SQL.squish + statuses.id BETWEEN :earliest_status_id AND :latest_status_id + SQL + end + + def account_domain_sql + if params[:include_subdomains] + <<~SQL.squish + accounts.domain IN (SELECT domain FROM instances WHERE reverse('.' || domain) LIKE reverse('.' || :domain::text)) + SQL else - 'accounts.domain = :domain::text' + <<~SQL.squish + accounts.domain = :domain::text + SQL end end end diff --git a/app/lib/admin/metrics/measure/resolved_reports_measure.rb b/app/lib/admin/metrics/measure/resolved_reports_measure.rb index ecfd779c86a..d9d5c71f4b6 100644 --- a/app/lib/admin/metrics/measure/resolved_reports_measure.rb +++ b/app/lib/admin/metrics/measure/resolved_reports_measure.rb @@ -17,23 +17,9 @@ class Admin::Metrics::Measure::ResolvedReportsMeasure < Admin::Metrics::Measure: Report.resolved.where(action_taken_at: previous_time_period).count end - def sql_array - [sql_query_string, { start_at: @start_at, end_at: @end_at }] - end - - def sql_query_string - <<~SQL.squish - SELECT axis.*, ( - WITH resolved_reports AS ( - SELECT reports.id - FROM reports - WHERE date_trunc('day', reports.action_taken_at)::date = axis.period - ) - SELECT count(*) FROM resolved_reports - ) AS value - FROM ( - #{generated_series_days} - ) AS axis - SQL + def data_source + Report + .select(:id) + .where(daily_period(:reports, :action_taken_at)) end end diff --git a/app/lib/admin/metrics/measure/tag_servers_measure.rb b/app/lib/admin/metrics/measure/tag_servers_measure.rb index 5db1076062b..6b4f56fdbb8 100644 --- a/app/lib/admin/metrics/measure/tag_servers_measure.rb +++ b/app/lib/admin/metrics/measure/tag_servers_measure.rb @@ -21,28 +21,15 @@ class Admin::Metrics::Measure::TagServersMeasure < Admin::Metrics::Measure::Base tag.statuses.where('statuses.id BETWEEN ? AND ?', Mastodon::Snowflake.id_at(@start_at - length_of_period, with_random: false), Mastodon::Snowflake.id_at(@end_at - length_of_period, with_random: false)).joins(:account).count('distinct accounts.domain') end - def sql_array - [sql_query_string, { start_at: @start_at, end_at: @end_at, tag_id: tag.id, earliest_status_id: earliest_status_id, latest_status_id: latest_status_id }] - end - - def sql_query_string - <<~SQL.squish - SELECT axis.*, ( - WITH tag_servers AS ( - SELECT DISTINCT accounts.domain - FROM statuses - INNER JOIN statuses_tags ON statuses.id = statuses_tags.status_id - INNER JOIN accounts ON statuses.account_id = accounts.id - WHERE statuses_tags.tag_id = :tag_id - AND statuses.id BETWEEN :earliest_status_id AND :latest_status_id - AND date_trunc('day', statuses.created_at)::date = axis.period - ) - SELECT COUNT(*) FROM tag_servers - ) AS value - FROM ( - #{generated_series_days} - ) as axis - SQL + def data_source + Status + .select('accounts.domain') + .distinct + .reorder(nil) + .joins(:tags, :account) + .where(statuses_tags: { tag_id: tag.id }) + .where(status_range_sql, earliest_status_id: earliest_status_id, latest_status_id: latest_status_id) + .where(daily_period(:statuses)) end def earliest_status_id