diff --git a/.rubocop.yml b/.rubocop.yml index 8b614a39..fad6db48 100644 --- a/.rubocop.yml +++ b/.rubocop.yml @@ -40,6 +40,7 @@ Metrics/BlockLength: - 'config/environments/production.rb' - 'config/initializers/devise.rb' - 'db/schema.rb' + - 'config/routes.rb' Metrics/ClassLength: Exclude: diff --git a/app/controllers/stats_controller.rb b/app/controllers/stats_controller.rb new file mode 100644 index 00000000..07baaf1a --- /dev/null +++ b/app/controllers/stats_controller.rb @@ -0,0 +1,18 @@ +# frozen_string_literal: true + +# Estadísticas del sitio +class StatsController < ApplicationController + include Pundit + before_action :authenticate_usuarie! + + def index + @site = find_site + authorize SiteStat.new(@site) + + # Solo queremos el promedio de tiempo de compilación, no de + # instalación de dependencias. + stats = @site.build_stats.jekyll + @build_avg = stats.average(:seconds).to_f.round(2) + @build_max = stats.maximum(:seconds).to_f.round(2) + end +end diff --git a/app/helpers/application_helper.rb b/app/helpers/application_helper.rb index 449f9c5c..8be0d41e 100644 --- a/app/helpers/application_helper.rb +++ b/app/helpers/application_helper.rb @@ -22,6 +22,14 @@ module ApplicationHelper "#{f.first}[#{f.last}]" end + def distance_of_time_in_words_if_more_than_a_minute(seconds) + if seconds > 60 + distance_of_time_in_words seconds + else + I18n.t('seconds', seconds: seconds) + end + end + def sanitize_markdown(text, options = {}) sanitize(CommonMarker.render_html(text), options) end diff --git a/app/models/build_stat.rb b/app/models/build_stat.rb index c99bf2c3..5a6a9365 100644 --- a/app/models/build_stat.rb +++ b/app/models/build_stat.rb @@ -3,4 +3,6 @@ # Recolecta estadísticas durante la generación del sitio class BuildStat < ApplicationRecord belongs_to :deploy + + scope :jekyll, -> { where(action: 'bundle_exec_jekyll_build') } end diff --git a/app/models/deploy.rb b/app/models/deploy.rb index e91a9d14..4d0ce450 100644 --- a/app/models/deploy.rb +++ b/app/models/deploy.rb @@ -42,7 +42,7 @@ class Deploy < ApplicationRecord # XXX: prestar atención a la concurrencia de sqlite3, se podría # enviar los datos directamente a una API para que se manejen desde # el proceso principal de rails y evitar problemas. - stat = build_stats.build action: cmd.split('-', 2).first.tr(' ', '_') + stat = build_stats.build action: cmd.split(' -', 2).first.tr(' ', '_') r = nil time_start diff --git a/app/models/site.rb b/app/models/site.rb index 354e376a..d566cd3d 100644 --- a/app/models/site.rb +++ b/app/models/site.rb @@ -18,6 +18,7 @@ class Site < ApplicationRecord belongs_to :licencia has_many :deploys + has_many :build_stats, through: :deploys has_many :roles has_many :usuaries, -> { where('roles.rol = ?', 'usuarie') }, through: :roles diff --git a/app/models/site_stat.rb b/app/models/site_stat.rb new file mode 100644 index 00000000..73503aca --- /dev/null +++ b/app/models/site_stat.rb @@ -0,0 +1,3 @@ +# frozen_string_literal: true + +SiteStat = Struct.new(:site) diff --git a/app/policies/site_stat_policy.rb b/app/policies/site_stat_policy.rb new file mode 100644 index 00000000..a797034c --- /dev/null +++ b/app/policies/site_stat_policy.rb @@ -0,0 +1,15 @@ +# frozen_string_literal: true + +# Política de acceso a las estadísticas +class SiteStatPolicy + attr_reader :site_stat, :usuarie + + def initialize(usuarie, site_stat) + @usuarie = usuarie + @site_stat = site_stat + end + + def index? + site_stat.site.usuarie? usuarie + end +end diff --git a/app/views/stats/index.haml b/app/views/stats/index.haml new file mode 100644 index 00000000..eb55c5d9 --- /dev/null +++ b/app/views/stats/index.haml @@ -0,0 +1,18 @@ +.row + .col + = render 'layouts/breadcrumb', + crumbs: [link_to(t('sites.index'), sites_path), + link_to(@site.name, site_path(@site)), t('.title')] +.row + .col + %h1= t('.title') + %p.lead= t('.help') + + %table.table.table-striped.table-condensed + %tbody + %tr + %td= t('.build.average') + %td= distance_of_time_in_words_if_more_than_a_minute @build_avg + %tr + %td= t('.build.maximum') + %td= distance_of_time_in_words_if_more_than_a_minute @build_max diff --git a/config/locales/en.yml b/config/locales/en.yml index 602ec0f2..6ad6eb9a 100644 --- a/config/locales/en.yml +++ b/config/locales/en.yml @@ -1,4 +1,5 @@ en: + seconds: '%{seconds} seconds' deploy_mailer: deployed: subject: "[Sutty] The site %{site} has been built" @@ -184,6 +185,15 @@ en: It also helps with site archival for historical purposes :) ejemplo: 'example' + stats: + index: + title: Statistics + help: | + Statistics show information about how your site is generated and + how many resources it uses. + build: + average: 'Average building time' + maximum: 'Maximum building time' sites: repository: config: 'Changes in config' diff --git a/config/locales/es.yml b/config/locales/es.yml index 7be2b4d4..0a65b29f 100644 --- a/config/locales/es.yml +++ b/config/locales/es.yml @@ -1,4 +1,5 @@ es: + seconds: '%{seconds} segundos' deploy_mailer: deployed: subject: "[Sutty] El sitio %{site} ha sido generado" @@ -195,6 +196,15 @@ es: También sirve para archivo histórico :) ejemplo: 'ejemplo' + stats: + index: + title: Estadísticas + help: | + Las estadísticas visibilizan información sobre cómo se genera y + cuántos recursos utiliza tu sitio. + build: + average: 'Tiempo promedio de generación' + maximum: 'Tiempo máximo de generación' sites: repository: config: 'Cambios en la configuración' diff --git a/config/routes.rb b/config/routes.rb index 7e66c766..a492ba90 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -42,5 +42,7 @@ Rails.application.routes.draw do # Compilar el sitio post 'enqueue', to: 'sites#enqueue' post 'reorder_posts', to: 'sites#reorder_posts' + + resources :stats, only: [:index] end end diff --git a/doc/crear_sitios.md b/doc/crear_sitios.md index 7f6bd8af..9155b002 100644 --- a/doc/crear_sitios.md +++ b/doc/crear_sitios.md @@ -217,6 +217,9 @@ tengamos tiempo de hacerlo realmente. # TODO * ver las estadisticas de compilación en lugar del log (el log también) + + agrupar los build stats para poder ver todos los pasos de una + compilación juntos * comitear en git los articulos (igual no es de esta rama...) * link a visitar sitio * editor de opciones