From a36dc01a8130ed9320f8eb633a2344886f6f4228 Mon Sep 17 00:00:00 2001 From: Eugen Rochko Date: Sun, 10 Nov 2024 17:06:43 +0100 Subject: [PATCH] Fix performance of dashboard metrics by periodically warming cache --- .../mastodon/components/admin/Counter.jsx | 2 +- app/javascript/styles/mastodon/admin.scss | 6 ++ .../admin/metrics/dimension/base_dimension.rb | 4 ++ app/lib/admin/metrics/measure/base_measure.rb | 6 +- app/lib/admin/metrics/retention.rb | 6 +- app/views/admin/dashboard/index.html.haml | 4 +- .../admin/dashboard_cache_warmer_scheduler.rb | 55 +++++++++++++++++++ config/sidekiq.yml | 4 ++ 8 files changed, 82 insertions(+), 5 deletions(-) create mode 100644 app/workers/scheduler/admin/dashboard_cache_warmer_scheduler.rb diff --git a/app/javascript/mastodon/components/admin/Counter.jsx b/app/javascript/mastodon/components/admin/Counter.jsx index e4d21da627..c5bf7b1366 100644 --- a/app/javascript/mastodon/components/admin/Counter.jsx +++ b/app/javascript/mastodon/components/admin/Counter.jsx @@ -95,7 +95,7 @@ export default class Counter extends PureComponent {
{!loading && ( - x.value * 1)}> + x.value * 1)} margin={0}> )} diff --git a/app/javascript/styles/mastodon/admin.scss b/app/javascript/styles/mastodon/admin.scss index c7b32a9c9e..2570047534 100644 --- a/app/javascript/styles/mastodon/admin.scss +++ b/app/javascript/styles/mastodon/admin.scss @@ -1315,12 +1315,18 @@ a.sparkline { &__key { font-weight: 500; padding: 11px 10px; + white-space: nowrap; + text-overflow: ellipsis; + overflow: hidden; } &__value { text-align: end; color: $darker-text-color; padding: 11px 10px; + white-space: nowrap; + text-overflow: ellipsis; + overflow: hidden; } &__indicator { diff --git a/app/lib/admin/metrics/dimension/base_dimension.rb b/app/lib/admin/metrics/dimension/base_dimension.rb index bd2e4ececb..83b3b4c487 100644 --- a/app/lib/admin/metrics/dimension/base_dimension.rb +++ b/app/lib/admin/metrics/dimension/base_dimension.rb @@ -39,6 +39,10 @@ class Admin::Metrics::Dimension::BaseDimension send(key) if respond_to?(key) end + def perform_for_cache! + Rails.cache.write(cache_key, perform_query, expires_in: CACHE_TTL) + end + protected def load diff --git a/app/lib/admin/metrics/measure/base_measure.rb b/app/lib/admin/metrics/measure/base_measure.rb index 8b7fe39b55..fdbc87148a 100644 --- a/app/lib/admin/metrics/measure/base_measure.rb +++ b/app/lib/admin/metrics/measure/base_measure.rb @@ -1,7 +1,7 @@ # frozen_string_literal: true class Admin::Metrics::Measure::BaseMeasure - CACHE_TTL = 5.minutes.freeze + CACHE_TTL = 3.hours.freeze def self.with_params? false @@ -54,6 +54,10 @@ class Admin::Metrics::Measure::BaseMeasure send(key) if respond_to?(key) end + def perform_for_cache! + Rails.cache.write(cache_key, perform_queries, expires_in: CACHE_TTL) + end + protected def load diff --git a/app/lib/admin/metrics/retention.rb b/app/lib/admin/metrics/retention.rb index 9bd47c58e4..0a5891f661 100644 --- a/app/lib/admin/metrics/retention.rb +++ b/app/lib/admin/metrics/retention.rb @@ -1,7 +1,7 @@ # frozen_string_literal: true class Admin::Metrics::Retention - CACHE_TTL = 5.minutes.freeze + CACHE_TTL = 1.day.freeze class Cohort < ActiveModelSerializers::Model attributes :period, :frequency, :data @@ -30,6 +30,10 @@ class Admin::Metrics::Retention load end + def perform_for_cache! + Rails.cache.write(cache_key, perform_query, expires_in: CACHE_TTL) + end + protected def load diff --git a/app/views/admin/dashboard/index.html.haml b/app/views/admin/dashboard/index.html.haml index 2b4d02fa67..8b92f22877 100644 --- a/app/views/admin/dashboard/index.html.haml +++ b/app/views/admin/dashboard/index.html.haml @@ -107,7 +107,7 @@ dimension: 'software_versions', end_at: @time_period.last, label: t('admin.dashboard.software'), - limit: 4, + limit: 8, start_at: @time_period.first .dashboard__item @@ -115,5 +115,5 @@ dimension: 'space_usage', end_at: @time_period.last, label: t('admin.dashboard.space'), - limit: 3, + limit: 8, start_at: @time_period.first diff --git a/app/workers/scheduler/admin/dashboard_cache_warmer_scheduler.rb b/app/workers/scheduler/admin/dashboard_cache_warmer_scheduler.rb new file mode 100644 index 0000000000..12b11ad698 --- /dev/null +++ b/app/workers/scheduler/admin/dashboard_cache_warmer_scheduler.rb @@ -0,0 +1,55 @@ +# frozen_string_literal: true + +class Scheduler::Admin::DashboardCacheWarmerScheduler + include Sidekiq::Worker + + # The values in this file have to align with the values in app/views/admin/dashboard/index.html.haml + # so that the generated cache keys are the same, otherwise cache warming will have no benefit + + MEASURES = %w( + new_users + active_users + interactions + opened_reports + resolved_reports + ).freeze + + DIMENSIONS = %w( + sources + languages + servers + software_versions + space_usage + ).freeze + + DIMENSION_LIMIT = 8 + + TIME_PERIOD_DAYS = 29 + + RETENTION_TIME_PERIOD_MONTHS = 6 + + def perform + @start_at = TIME_PERIOD_DAYS.days.ago.to_date + @end_at = Time.now.utc.to_date + @retention_start_at = @end_at - RETENTION_TIME_PERIOD_MONTHS.months + @retention_end_at = @end_at + + warm_measures_cache! + warm_dimensions_cache! + warm_retention_cache! + end + + private + + def warm_measures_cache! + Admin::Metrics::Measure.retrieve(MEASURES, @start_at, @end_at, {}).each(&:perform_for_cache!) + end + + def warm_dimensions_cache! + Admin::Metrics::Dimension.retrieve(DIMENSIONS, @start_at, @end_at, DIMENSION_LIMIT, {}).each(&:perform_for_cache!) + end + + def warm_retention_cache! + Admin::Metrics::Retention.new(@retention_start_at, @retention_end_at, 'month').perform_for_cache! + end +end diff --git a/config/sidekiq.yml b/config/sidekiq.yml index 488c2f2ab3..62e30c281c 100644 --- a/config/sidekiq.yml +++ b/config/sidekiq.yml @@ -67,3 +67,7 @@ interval: 1 hour class: Scheduler::AutoCloseRegistrationsScheduler queue: scheduler + dashboard_cache_warmer_scheduler: + interval: 2 hours + class: Scheduler::Admin::DashboardCacheWarmerScheduler + queue: scheduler