mirror of
https://0xacab.org/sutty/sutty
synced 2024-11-16 12:21:43 +00:00
refactorizar rollups recursivos
This commit is contained in:
parent
6b191d2d91
commit
aad5c82cb7
3 changed files with 102 additions and 42 deletions
38
app/jobs/concerns/recursive_rollup.rb
Normal file
38
app/jobs/concerns/recursive_rollup.rb
Normal file
|
@ -0,0 +1,38 @@
|
||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
module RecursiveRollup
|
||||||
|
extend ActiveSupport::Concern
|
||||||
|
|
||||||
|
included do
|
||||||
|
private
|
||||||
|
|
||||||
|
# Genera un rollup recursivo en base al período anterior y aplica una
|
||||||
|
# operación.
|
||||||
|
#
|
||||||
|
# @param :name [String]
|
||||||
|
# @param :interval_previous [String]
|
||||||
|
# @param :interval [String]
|
||||||
|
# @param :operation [Symbol]
|
||||||
|
# @param :dimensions [Hash]
|
||||||
|
# @param :new_name [String]
|
||||||
|
# @param :beginning [Time]
|
||||||
|
# @return [Rollup]
|
||||||
|
def recursive_rollup(name:, interval_previous:, interval:, dimensions:, beginning:, operation: :sum, new_name: nil)
|
||||||
|
Rollup.where(name: name, interval: interval_previous)
|
||||||
|
.where('time >= ?', beginning.try(:"beginning_of_#{interval}"))
|
||||||
|
.where_dimensions(**dimensions)
|
||||||
|
.group(*dimensions_to_jsonb_query(dimensions))
|
||||||
|
.rollup(new_name || name, interval: interval, update: true) do |rollup|
|
||||||
|
rollup.try(operation, :value)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
# @param :dimensions [Hash]
|
||||||
|
# @return [Array]
|
||||||
|
def dimensions_to_jsonb_query(dimensions)
|
||||||
|
dimensions.keys.map do |key|
|
||||||
|
"dimensions->'#{key}'"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
|
@ -3,6 +3,8 @@
|
||||||
# Genera resúmenes de información para poder mostrar estadísticas y se
|
# Genera resúmenes de información para poder mostrar estadísticas y se
|
||||||
# corre regularmente a sí misma.
|
# corre regularmente a sí misma.
|
||||||
class StatCollectionJob < PeriodicJob
|
class StatCollectionJob < PeriodicJob
|
||||||
|
include RecursiveRollup
|
||||||
|
|
||||||
STAT_NAME = 'stat_collection_job'
|
STAT_NAME = 'stat_collection_job'
|
||||||
|
|
||||||
def perform(site_id:, once: true)
|
def perform(site_id:, once: true)
|
||||||
|
@ -20,9 +22,11 @@ class StatCollectionJob < PeriodicJob
|
||||||
|
|
||||||
# XXX: Es correcto promediar promedios?
|
# XXX: Es correcto promediar promedios?
|
||||||
Stat::INTERVALS.reduce do |previous, current|
|
Stat::INTERVALS.reduce do |previous, current|
|
||||||
rollup(name: 'builds', interval_previous: previous, interval: current)
|
opts = { interval_previous: previous, interval: current, dimensions: { site_id: site.id } }
|
||||||
rollup(name: 'space_used', interval_previous: previous, interval: current, operation: :average)
|
|
||||||
rollup(name: 'build_time', interval_previous: previous, interval: current, operation: :average)
|
recursive_rollup(name: 'builds', **opts)
|
||||||
|
recursive_rollup(name: 'space_used', operation: :average, **opts)
|
||||||
|
recursive_rollup(name: 'build_time', operation: :average, **opts)
|
||||||
|
|
||||||
current
|
current
|
||||||
end
|
end
|
||||||
|
@ -35,20 +39,6 @@ class StatCollectionJob < PeriodicJob
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|
||||||
# Genera un rollup recursivo en base al período anterior y aplica una
|
|
||||||
# operación.
|
|
||||||
#
|
|
||||||
# @return [NilClass]
|
|
||||||
def rollup(name:, interval_previous:, interval:, operation: :sum)
|
|
||||||
Rollup.where(name: name, interval: interval_previous)
|
|
||||||
.where('time >= ?', beginning_of_interval.try(:"beginning_of_#{interval}"))
|
|
||||||
.where_dimensions(site_id: site.id)
|
|
||||||
.group("dimensions->'site_id'")
|
|
||||||
.rollup(name, interval: interval, update: true) do |rollup|
|
|
||||||
rollup.try(operation, :value)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
# Los registros a procesar
|
# Los registros a procesar
|
||||||
#
|
#
|
||||||
# @return [ActiveRecord::Relation]
|
# @return [ActiveRecord::Relation]
|
||||||
|
|
|
@ -11,6 +11,8 @@
|
||||||
# Los hostnames de un sitio van a poder obtenerse a partir de
|
# Los hostnames de un sitio van a poder obtenerse a partir de
|
||||||
# Site#hostnames con la garantía de que son únicos.
|
# Site#hostnames con la garantía de que son únicos.
|
||||||
class UriCollectionJob < PeriodicJob
|
class UriCollectionJob < PeriodicJob
|
||||||
|
include RecursiveRollup
|
||||||
|
|
||||||
# Ignoramos imágenes porque suelen ser demasiadas y no aportan a las
|
# Ignoramos imágenes porque suelen ser demasiadas y no aportan a las
|
||||||
# estadísticas.
|
# estadísticas.
|
||||||
IMAGES = %w[.png .jpg .jpeg .gif .webp .jfif].freeze
|
IMAGES = %w[.png .jpg .jpeg .gif .webp .jfif].freeze
|
||||||
|
@ -21,35 +23,19 @@ class UriCollectionJob < PeriodicJob
|
||||||
|
|
||||||
# Recordar la última vez que se corrió la tarea
|
# Recordar la última vez que se corrió la tarea
|
||||||
stat = site.stats.create! name: STAT_NAME
|
stat = site.stats.create! name: STAT_NAME
|
||||||
|
name = 'host|uri'
|
||||||
|
beginning = beginning_of_interval
|
||||||
|
|
||||||
|
hostnames.each do |host|
|
||||||
|
break if stop?
|
||||||
|
|
||||||
hostnames.each do |hostname|
|
|
||||||
uris.each do |uri|
|
uris.each do |uri|
|
||||||
next if stop?
|
break if stop?
|
||||||
|
|
||||||
AccessLog.where(host: hostname, uri: uri)
|
rollup_uri(uri, host, name, beginning)
|
||||||
.where('created_at >= ?', beginning_of_interval)
|
|
||||||
.completed_requests
|
|
||||||
.non_robots
|
|
||||||
.group(:host, :uri)
|
|
||||||
.rollup('host|uri', interval: starting_interval, update: true)
|
|
||||||
|
|
||||||
# Reducir las estadísticas calculadas aplicando un rollup sobre el
|
|
||||||
# intervalo más amplio.
|
|
||||||
Stat::INTERVALS.reduce do |previous, current|
|
|
||||||
beginning_of_this_interval = beginning_of_interval.try(:"beginning_of_#{current}")
|
|
||||||
|
|
||||||
Rollup.where(name: 'host|uri', interval: previous)
|
|
||||||
.where('time >= ?', beginning_of_this_interval)
|
|
||||||
.where_dimensions(host: hostname, uri: uri)
|
|
||||||
.group("dimensions->'host'", "dimensions->'uri'")
|
|
||||||
.rollup('host|uri', interval: current, update: true) do |rollup|
|
|
||||||
rollup.sum(:value)
|
|
||||||
end
|
end
|
||||||
|
|
||||||
# Devolver el intervalo actual
|
rollup_host(host, name, beginning)
|
||||||
current
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
stat.touch
|
stat.touch
|
||||||
|
@ -59,6 +45,52 @@ class UriCollectionJob < PeriodicJob
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|
||||||
|
def rollup_uri(uri, host, name, beginning)
|
||||||
|
dimensions = { host: host, uri: uri }
|
||||||
|
|
||||||
|
AccessLog.where(**dimensions)
|
||||||
|
.where('created_at >= ?', beginning)
|
||||||
|
.completed_requests
|
||||||
|
.non_robots
|
||||||
|
.group(*dimensions.keys)
|
||||||
|
.rollup(name, interval: starting_interval, update: true)
|
||||||
|
|
||||||
|
# Reducir las estadísticas calculadas aplicando un rollup sobre el
|
||||||
|
# intervalo más amplio.
|
||||||
|
Stat::INTERVALS.reduce do |previous, current|
|
||||||
|
recursive_rollup(name: name,
|
||||||
|
interval_previous: previous,
|
||||||
|
interval: current,
|
||||||
|
dimensions: dimensions,
|
||||||
|
beginning: beginning)
|
||||||
|
|
||||||
|
# Devolver el intervalo actual
|
||||||
|
current
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def rollup_host(host, name, beginning)
|
||||||
|
dimensions = { host: host }
|
||||||
|
new_name = 'host'
|
||||||
|
|
||||||
|
recursive_rollup(name: name,
|
||||||
|
new_name: new_name,
|
||||||
|
interval_previous: starting_interval,
|
||||||
|
interval: starting_interval,
|
||||||
|
dimensions: dimensions,
|
||||||
|
beginning: beginning)
|
||||||
|
|
||||||
|
Stat::INTERVALS.reduce do |previous, current|
|
||||||
|
recursive_rollup(name: new_name,
|
||||||
|
interval_previous: previous,
|
||||||
|
interval: current,
|
||||||
|
dimensions: dimensions,
|
||||||
|
beginning: beginning)
|
||||||
|
|
||||||
|
current
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
def stat_name
|
def stat_name
|
||||||
STAT_NAME
|
STAT_NAME
|
||||||
end
|
end
|
||||||
|
|
Loading…
Reference in a new issue