DEV: Ability to collect stats without exposing them via API (#23933)

This adds the ability to collect stats without exposing them 
among other stats via API.

The most important thing I wanted to achieve is to provide 
an API where stats are not exposed by default, and a developer 
has to explicitly specify that they should be 
exposed (`expose_via_api: true`). Implementing an opposite 
solution would be simpler, but that's less safe in terms of 
potential security issues. 

When working on this, I had to refactor the current solution. 
I would go even further with the refactoring, but the next steps 
seem to be going too far in changing the solution we have, 
and that would also take more time. Two things that can be 
improved in the future:
1. Data structures for holding stats can be further improved
2. Core stats are hard-coded in the About template (it's hard 
to fix it without correcting data structures first, see point 1):
    63a0700d45/app/views/about/index.html.erb (L61-L101)

The most significant refactorings are:
1. Introducing the `Stat` model
2. Aligning the way the core and the plugin stats' are registered
This commit is contained in:
Andrei Prigorshnev
2023-11-10 00:44:05 +04:00
committed by GitHub
parent bdb81b5346
commit d91456fd53
15 changed files with 228 additions and 119 deletions

View File

@ -1110,7 +1110,7 @@ class Plugin::Instance
# but all stats will be shown on the /about.json route. For example take
# this usage:
#
# register_about_stat_group("chat_messages") do
# register_stat("chat_messages") do
# { last_day: 1, "7_days" => 10, "30_days" => 100, count: 1000, previous_30_days: 150 }
# end
#
@ -1132,18 +1132,12 @@ class Plugin::Instance
# group of stats is shown on the site About page in the Site Statistics
# table. Some stats may be needed purely for reporting purposes and thus
# do not need to be shown in the UI to admins/users.
def register_about_stat_group(plugin_stat_group_name, show_in_ui: false, &block)
def register_stat(name, show_in_ui: false, expose_via_api: false, &block)
# We do not want to register and display the same group multiple times.
if DiscoursePluginRegistry.about_stat_groups.any? { |stat_group|
stat_group[:name] == plugin_stat_group_name
}
return
end
return if DiscoursePluginRegistry.stats.any? { |stat| stat.name == name }
DiscoursePluginRegistry.register_about_stat_group(
{ name: plugin_stat_group_name, show_in_ui: show_in_ui, block: block },
self,
)
stat = Stat.new(name, show_in_ui: show_in_ui, expose_via_api: expose_via_api, &block)
DiscoursePluginRegistry.register_stat(stat, self)
end
##