discourse/app/models/application_request.rb
David Taylor 2f2da72747
FEATURE: Add experimental tracking of 'real browser' pageviews (#26647)
Our 'page_view_crawler' / 'page_view_anon' metrics are based purely on the User Agent sent by clients. This means that 'badly behaved' bots which are imitating real user agents are counted towards 'anon' page views.

This commit introduces a new method of tracking visitors. When an initial HTML request is made, we assume it is a 'non-browser' request (i.e. a bot). Then, once the JS application has booted, we notify the server to count it as a 'browser' request. This reliance on a JavaScript-capable browser matches up more closely to dedicated analytics systems like Google Analytics.

Existing data collection and graphs are unchanged. Data collected via the new technique is available in a new 'experimental' report.
2024-04-25 11:00:01 +01:00

76 lines
1.8 KiB
Ruby

# frozen_string_literal: true
class ApplicationRequest < ActiveRecord::Base
enum req_type: %i[
http_total
http_2xx
http_background
http_3xx
http_4xx
http_5xx
page_view_crawler
page_view_logged_in
page_view_anon
page_view_logged_in_mobile
page_view_anon_mobile
api
user_api
page_view_anon_browser
page_view_anon_browser_mobile
page_view_logged_in_browser
page_view_logged_in_browser_mobile
]
include CachedCounting
def self.disable
@disabled = true
end
def self.enable
@disabled = false
end
def self.increment!(req_type)
return if @disabled
perform_increment!(req_type)
end
def self.write_cache!(req_type, count, date)
req_type_id = req_types[req_type]
DB.exec(<<~SQL, date: date, req_type_id: req_type_id, count: count)
INSERT INTO application_requests (date, req_type, count)
VALUES (:date, :req_type_id, :count)
ON CONFLICT (date, req_type)
DO UPDATE SET count = application_requests.count + excluded.count
SQL
end
def self.stats
s = HashWithIndifferentAccess.new({})
self.req_types.each do |key, i|
query = self.where(req_type: i)
s["#{key}_total"] = query.sum(:count)
s["#{key}_30_days"] = query.where("date > ?", 30.days.ago).sum(:count)
s["#{key}_7_days"] = query.where("date > ?", 7.days.ago).sum(:count)
end
s
end
end
# == Schema Information
#
# Table name: application_requests
#
# id :integer not null, primary key
# date :date not null
# req_type :integer not null
# count :integer default(0), not null
#
# Indexes
#
# index_application_requests_on_date_and_req_type (date,req_type) UNIQUE
#