Skip to content
Open
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 Gemfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -577,6 +577,7 @@ PLATFORMS
arm64-darwin-22
arm64-darwin-23
arm64-darwin-24
arm64-darwin-25
x86_64-darwin-21
x86_64-darwin-22
x86_64-darwin-23
Expand Down
8 changes: 4 additions & 4 deletions app/assets/stylesheets/app/metrics-card.scss
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
.metrics-card-body {
height: 450px;
height: 275px;

.metrics-chart {
height: 100%;
}

.metrics-table {
height: 100%;
}
// .metrics-table {
// height: 100%;
// }
}
47 changes: 47 additions & 0 deletions app/controllers/concerns/metrics_queries.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
require "active_support/concern"

module MetricsQueries
extend ActiveSupport::Concern

def alltime_downloads(model, select_override = nil)
model_id, column = model_attrs(model)
selection = select_override || column

Rollups::HourlyDownload
.where("#{column}": model_id)
.select(selection, "SUM(count) AS count")
.group(selection)
.final
.load_async
end

def daterange_downloads(model, date_start = Date.utc_today - 28.days, date_end = Time.now, interval = "DAY")
model_id, column = model_attrs(model)

Rollups::HourlyDownload
.where("#{column}": model_id, hour: (date_start..date_end))
.select(column, "DATE_TRUNC('#{interval}', hour) AS hour", "SUM(count) AS count")
.group(column, "DATE_TRUNC('#{interval}', hour) AS hour")
.order(Arel.sql("DATE_TRUNC('#{interval}', hour) ASC"))
.final
.load_async
end

def model_attrs(model)
model_id = if model.is_a?(Enumerable)
model.pluck(:guid)
elsif model.is_a?(Podcast)
model[:id]
elsif model.is_a?(Episode)
model[:guid]
end

column = if model.is_a?(Enumerable)
"#{model.first.class.to_s.downcase}_id"
else
"#{model.class.to_s.downcase}_id"
end

[model_id, column]
end
end
28 changes: 21 additions & 7 deletions app/controllers/concerns/metrics_utils.rb
Original file line number Diff line number Diff line change
Expand Up @@ -55,25 +55,39 @@ def primary_blue
"#0072a3"
end

def light_pink
"#e7d4ff"
end

def light_blue
"#aafff5"
end

def orange
"#ff9601"
end

def single_rollups(downloads, label = I18n.t(".helpers.label.metrics.chart.all_episodes"))
{
rollups: downloads,
color: primary_blue,
color: light_blue,
label: label
}
end

def multiple_episode_rollups(episodes, rollups, totals)
episodes.to_enum(:each_with_index).map do |episode, i|
def multiple_episode_rollups(episodes, rollups)
episodes.map.with_index do |episode, i|
color = if i == 0
orange
else
light_blue
end
{
episode: episode,
rollups: rollups.select do |r|
r["episode_id"] == episode.guid
end,
totals: totals.select do |r|
r["episode_id"] == episode.guid
end,
color: colors[i]
color: color
}
end
end
Expand Down
216 changes: 129 additions & 87 deletions app/controllers/podcast_metrics_controller.rb
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
class PodcastMetricsController < ApplicationController
include MetricsUtils
include MetricsQueries

before_action :set_podcast
# before_action :check_clickhouse, except: %i[show]
Expand Down Expand Up @@ -29,60 +30,87 @@ def episode_sparkline
}
end

def downloads
@downloads_within_date_range =
Rollups::HourlyDownload
.where(podcast_id: @podcast.id, hour: (@date_start..@date_end))
.select("DATE_TRUNC('#{@interval}', hour) AS hour", "SUM(count) AS count")
.group("DATE_TRUNC('#{@interval}', hour) AS hour")
.order(Arel.sql("DATE_TRUNC('#{@interval}', hour) ASC"))
.load_async
def monthly_downloads
@date_start = (Date.utc_today - 11.months).beginning_of_month
@date_end = Date.utc_today
@date_range = generate_date_range(@date_start, @date_end.beginning_of_month, "MONTH")
@downloads_within_date_range = daterange_downloads(@podcast, @date_start, @date_end, "MONTH")

@downloads = single_rollups(@downloads_within_date_range)
@downloads = single_rollups(@downloads_within_date_range, "Downloads")

render partial: "metrics/downloads_card", locals: {
url: request.fullpath,
form_id: "podcast_downloads_metrics",
date_start: @date_start,
date_end: @date_end,
interval: @interval,
render partial: "metrics/monthly_card", locals: {
date_range: @date_range,
downloads: @downloads
}
end

def episodes
@episodes =
@podcast.episodes
.published
.order(first_rss_published_at: :desc)
.paginate(params[:episodes], params[:per])
@episodes = @podcast.episodes.published.dropdate_desc.limit(10)
@date_range = generate_date_range(Date.utc_today - 28.days, Date.utc_today, "DAY")

@episodes_recent =
Rollups::HourlyDownload
.where(podcast_id: @podcast.id, episode_id: @episodes.pluck(:guid), hour: (@date_start..@date_end))
.select(:episode_id, "DATE_TRUNC('#{@interval}', hour) AS hour", "SUM(count) AS count")
.group(:episode_id, "DATE_TRUNC('#{@interval}', hour) AS hour")
.order(Arel.sql("DATE_TRUNC('#{@interval}', hour) ASC"))
.load_async
@episodes_alltime =
@episodes_downloads = daterange_downloads(@episodes)

@episode_rollups = multiple_episode_rollups(@episodes, @episodes_downloads)

render partial: "metrics/episodes_card", locals: {
episode_rollups: @episode_rollups,
date_range: @date_range
}
end

def feeds
feed_slugs = @podcast.feeds.pluck(:slug).map { |slug| slug.nil? ? "" : slug }
date_start = (Date.utc_today - 28.days)

@downloads_by_feed =
Rollups::HourlyDownload
.where(podcast_id: @podcast.id, episode_id: @episodes.pluck(:guid))
.select(:episode_id, "SUM(count) AS count")
.group(:episode_id)
.where(podcast_id: @podcast.id, feed_slug: feed_slugs, hour: (date_start..))
.select(:feed_slug, "SUM(count) AS count")
.group(:feed_slug)
.order(Arel.sql("SUM(count) AS count DESC"))
.final
.load_async

@episode_rollups = multiple_episode_rollups(@episodes, @episodes_recent, @episodes_alltime)
feeds_with_downloads = []

render partial: "metrics/episodes_card", locals: {
url: request.fullpath,
form_id: "podcast_episodes_metrics",
date_start: @date_start,
date_end: @date_end,
interval: @interval,
date_range: @date_range,
episodes: @episodes,
episode_rollups: @episode_rollups
@feeds = @downloads_by_feed.map do |rollup|
feed = if rollup[:feed_slug].blank?
@podcast.default_feed
else
@podcast.feeds.where(slug: rollup[:feed_slug]).first
end

feeds_with_downloads << feed

{
feed: feed,
downloads: rollup
}
end

@podcast.feeds.each { |feed| @feeds << {feed: feed} if feeds_with_downloads.exclude?(feed) }

render partial: "metrics/feeds_card", locals: {
podcast: @podcast,
feeds: @feeds
}
end

def seasons
published_seasons = @podcast.episodes.published.pluck(:season_number).uniq

@season_rollups = published_seasons.map do |season|
episodes = @podcast.episodes.published.where(season_number: season)
rollup = alltime_downloads(episodes, "podcast_id")

{
season_number: season,
downloads: rollup.first
}
end

render partial: "metrics/seasons_card", locals: {
seasons: @season_rollups
}
end

Expand Down Expand Up @@ -154,55 +182,69 @@ def dropdays
}
end

def geos
# @top_subdivs =
# Rollups::DailyGeo
# .where(podcast_id: @podcast.id)
# .select(:country_code, :subdiv_code, "DATE_TRUNC('WEEK', day) AS day", "SUM(count) AS count")
# .group(:country_code, :subdiv_code, "DATE_TRUNC('WEEK', day) AS day")
# .order(Arel.sql("SUM(count) AS count DESC"))
# .limit(10)
# @top_countries =
# Rollups::DailyGeo
# .where(podcast_id: @podcast.id)
# .select(:country_code, "SUM(count) AS count")
# .group(:country_code)
# .order(Arel.sql("SUM(count) AS count DESC"))
# .limit(10)
def countries
date_start = (Date.utc_today - 28.days).to_s
date_end = Date.utc_today.to_s

top_countries =
Rollups::DailyGeo
.where(podcast_id: @podcast.id, day: date_start..date_end)
.select(:country_code, "SUM(count) AS count")
.group(:country_code)
.order(Arel.sql("SUM(count) AS count DESC"))
.final
.limit(10)
.load_async

top_country_codes = top_countries.pluck(:country_code)

other_countries =
Rollups::DailyGeo
.where(podcast_id: @podcast.id, day: date_start..date_end)
.where.not(country_code: top_country_codes)
.select("'Other' AS country_code", "SUM(count) AS count")
.final
.load_async

@country_rollups = []
@country_rollups << top_countries
@country_rollups << other_countries

render partial: "metrics/countries_card", locals: {
countries: @country_rollups.flatten
}
end

def agents
# @agent_apps_query =
# Rollups::DailyAgent
# .where(podcast_id: @podcast.id)
# .select("agent_name_id AS code", "SUM(count) AS count")
# .group("agent_name_id AS code")
# .order(Arel.sql("SUM(count) AS count DESC"))
# .load_async
# @agent_types_query =
# Rollups::DailyAgent
# .where(podcast_id: @podcast.id)
# .select("agent_type_id AS code", "SUM(count) AS count")
# .group("agent_type_id AS code")
# .order(Arel.sql("SUM(count) AS count DESC"))
# .load_async
# @agent_os_query =
# Rollups::DailyAgent
# .where(podcast_id: @podcast.id)
# .select("agent_os_id AS code", "SUM(count) AS count")
# .group("agent_os_id AS code")
# .order(Arel.sql("SUM(count) AS count DESC"))
# .load_async

# @agent_apps = Kaminari.paginate_array(@agent_apps_query).page(params[:agent_apps]).per(10)
# @agent_types = Kaminari.paginate_array(@agent_types_query).page(params[:agent_types]).per(10)
# @agent_os = Kaminari.paginate_array(@agent_os_query).page(params[:agent_os]).per(10)

# render partial: "agents", locals: {
# agent_apps: @agent_apps,
# agent_types: @agent_types,
# agent_os: @agent_os
# }
date_start = (Date.utc_today - 28.days).to_s
date_end = Date.utc_today.to_s

agent_apps =
Rollups::DailyAgent
.where(podcast_id: @podcast.id, day: date_start..date_end)
.select("agent_name_id AS code", "SUM(count) AS count")
.group("agent_name_id AS code")
.order(Arel.sql("SUM(count) AS count DESC"))
.final
.limit(10)
.load_async

top_apps_ids = agent_apps.pluck(:code)
other_apps =
Rollups::DailyAgent
.where(podcast_id: @podcast.id, day: date_start..date_end)
.where.not(agent_name_id: top_apps_ids)
.select("'Other' AS code", "SUM(count) AS count")
.final
.load_async

@agent_rollups = []
@agent_rollups << agent_apps
@agent_rollups << other_apps

render partial: "metrics/agent_apps_card", locals: {
agents: @agent_rollups.flatten
}
end

private
Expand Down
8 changes: 7 additions & 1 deletion app/controllers/podcasts_controller.rb
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
class PodcastsController < ApplicationController
include Prx::Api
include SlackHelper
include MetricsQueries

before_action :set_podcast, only: %i[show edit update destroy]

Expand All @@ -19,7 +20,12 @@ def show

@recently_published_episodes = @podcast.episodes.published.dropdate_desc.limit(4)
@trend_episodes = @podcast.default_feed.episodes.published.dropdate_desc.where.not(first_rss_published_at: nil).offset(1).limit(4)
@episode_trend_pairs = episode_trend_pairs(@recently_published_episodes, @trend_episodes)
if Rails.env.development?
@episode_trend_pairs = episode_trend_pairs(@recently_published_episodes, @trend_episodes)
@alltime_downloads = alltime_downloads(@podcast).sum(&:count)
@daterange_downloads = daterange_downloads(@podcast).sum(&:count)
end
@episode_count = @podcast.episodes.published.length

# @recently_published is used for the prod branch
@recently_published = @recently_published_episodes[0..2]
Expand Down
Loading