mirror of
https://github.com/codeninjasllc/discourse.git
synced 2024-11-27 09:36:19 -05:00
refactor traffic report
split traffic report in 2, page view vs raw traffic hide raw traffic report by default improve flushing logic for application reqs
This commit is contained in:
parent
1d3f4f6935
commit
820ce8765e
12 changed files with 177 additions and 92 deletions
|
@ -53,6 +53,9 @@ export default Ember.Controller.extend({
|
|||
actions: {
|
||||
refreshProblems: function() {
|
||||
this.loadProblems();
|
||||
},
|
||||
showTrafficReport: function() {
|
||||
this.set("showTrafficReport", true);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -66,7 +66,7 @@
|
|||
<table class="table table-condensed table-hover">
|
||||
<thead>
|
||||
<tr>
|
||||
<th class="title" title="{{i18n 'admin.dashboard.traffic'}}">{{i18n 'admin.dashboard.traffic_short'}}</th>
|
||||
<th class="title" title="{{i18n 'admin.dashboard.page_views'}}">{{i18n 'admin.dashboard.page_views_short'}}</th>
|
||||
<th>{{i18n 'admin.dashboard.reports.today'}}</th>
|
||||
<th>{{i18n 'admin.dashboard.reports.yesterday'}}</th>
|
||||
<th>{{i18n 'admin.dashboard.reports.last_7_days'}}</th>
|
||||
|
@ -75,19 +75,15 @@
|
|||
</tr>
|
||||
</thead>
|
||||
{{#unless loading}}
|
||||
{{ render 'admin_report_counts' topic_anon_reqs }}
|
||||
{{ render 'admin_report_counts' topic_logged_in_reqs }}
|
||||
{{ render 'admin_report_counts' topic_crawler_reqs }}
|
||||
{{ render 'admin_report_counts' background_reqs }}
|
||||
{{ render 'admin_report_counts' success_reqs }}
|
||||
{{ render 'admin_report_counts' redirect_reqs }}
|
||||
{{ render 'admin_report_counts' server_error_reqs }}
|
||||
{{ render 'admin_report_counts' client_error_reqs }}
|
||||
{{ render 'admin_report_counts' total_reqs }}
|
||||
{{ render 'admin_report_counts' page_view_anon_reqs }}
|
||||
{{ render 'admin_report_counts' page_view_logged_in_reqs }}
|
||||
{{ render 'admin_report_counts' page_view_crawler_reqs }}
|
||||
{{ render 'admin_report_counts' page_view_total_reqs }}
|
||||
{{/unless}}
|
||||
</table>
|
||||
</div>
|
||||
|
||||
|
||||
<div class="dashboard-stats">
|
||||
<table class="table table-condensed table-hover">
|
||||
<thead>
|
||||
|
@ -148,6 +144,37 @@
|
|||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
{{#unless loading}}
|
||||
{{#if showTrafficReport}}
|
||||
<div class="dashboard-stats">
|
||||
<table class="table table-condensed table-hover">
|
||||
<thead>
|
||||
<tr>
|
||||
<th class="title" title="{{i18n 'admin.dashboard.traffic'}}">{{i18n 'admin.dashboard.traffic_short'}}</th>
|
||||
<th>{{i18n 'admin.dashboard.reports.today'}}</th>
|
||||
<th>{{i18n 'admin.dashboard.reports.yesterday'}}</th>
|
||||
<th>{{i18n 'admin.dashboard.reports.last_7_days'}}</th>
|
||||
<th>{{i18n 'admin.dashboard.reports.last_30_days'}}</th>
|
||||
<th>{{i18n 'admin.dashboard.reports.all'}}</th>
|
||||
</tr>
|
||||
</thead>
|
||||
{{#unless loading}}
|
||||
{{ render 'admin_report_counts' http_2xx_reqs }}
|
||||
{{ render 'admin_report_counts' http_3xx_reqs}}
|
||||
{{ render 'admin_report_counts' http_4xx_reqs}}
|
||||
{{ render 'admin_report_counts' http_5xx_reqs}}
|
||||
{{ render 'admin_report_counts' http_background_reqs }}
|
||||
{{ render 'admin_report_counts' http_total_reqs }}
|
||||
{{/unless}}
|
||||
</table>
|
||||
</div>
|
||||
{{else}}
|
||||
<div class="dashboard-stats">
|
||||
<a href {{action showTrafficReport}}>{{i18n 'admin.dashboard.show_traffic_report'}}</a>
|
||||
</div>
|
||||
{{/if}}
|
||||
{{/unless}}
|
||||
</div>
|
||||
|
||||
<div class="dashboard-right">
|
||||
|
|
|
@ -16,7 +16,8 @@ class AdminDashboardData
|
|||
'system_private_messages',
|
||||
'moderator_warning_private_messages',
|
||||
'notify_moderators_private_messages',
|
||||
'notify_user_private_messages'
|
||||
'notify_user_private_messages',
|
||||
'page_view_total_reqs'
|
||||
] + ApplicationRequest.req_types.keys.map{|r| r + "_reqs"}
|
||||
|
||||
def problems
|
||||
|
|
|
@ -1,9 +1,21 @@
|
|||
class ApplicationRequest < ActiveRecord::Base
|
||||
enum req_type: %i(total success background topic_anon topic_logged_in topic_crawler server_error client_error redirect)
|
||||
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)
|
||||
|
||||
cattr_accessor :autoflush
|
||||
cattr_accessor :autoflush, :autoflush_seconds, :last_flush
|
||||
# auto flush if backlog is larger than this
|
||||
self.autoflush = 200
|
||||
self.autoflush = 2000
|
||||
|
||||
# auto flush if older than this
|
||||
self.autoflush_seconds = 5.minutes
|
||||
self.last_flush = Time.now
|
||||
|
||||
def self.increment!(type, opts=nil)
|
||||
key = redis_key(type)
|
||||
|
@ -13,6 +25,11 @@ class ApplicationRequest < ActiveRecord::Base
|
|||
autoflush = (opts && opts[:autoflush]) || self.autoflush
|
||||
if autoflush > 0 && val >= autoflush
|
||||
write_cache!
|
||||
return
|
||||
end
|
||||
|
||||
if (Time.now - last_flush).to_i > autoflush_seconds
|
||||
write_cache!
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -23,6 +40,8 @@ class ApplicationRequest < ActiveRecord::Base
|
|||
return
|
||||
end
|
||||
|
||||
self.last_flush = Time.now
|
||||
|
||||
date = date.to_date
|
||||
|
||||
# this may seem a bit fancy but in so it allows
|
||||
|
|
|
@ -50,7 +50,14 @@ class Report
|
|||
end
|
||||
|
||||
def self.req_report(report, filter=nil)
|
||||
data = ApplicationRequest.where(req_type: ApplicationRequest.req_types[filter])
|
||||
data =
|
||||
if filter == :page_view_total
|
||||
ApplicationRequest.where(req_type: [
|
||||
ApplicationRequest.req_types.map{|k,v| v if k =~ /page_view/}.compact
|
||||
])
|
||||
else
|
||||
ApplicationRequest.where(req_type: ApplicationRequest.req_types[filter])
|
||||
end
|
||||
|
||||
filtered_results = data.where('date >= ? AND date <= ?', report.start_date.to_date, report.end_date.to_date)
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
# no reason to track this in development, that is 300+ redis calls saved per
|
||||
# page view (we serve all assets out of thin in development)
|
||||
if Rails.env != 'development'
|
||||
if Rails.env != 'development' || ENV['TRACK_REQUESTS']
|
||||
require 'middleware/request_tracker'
|
||||
Rails.configuration.middleware.unshift Middleware::RequestTracker
|
||||
end
|
||||
|
|
|
@ -1537,6 +1537,9 @@ en:
|
|||
backups: "backups"
|
||||
traffic_short: "Traffic"
|
||||
traffic: "Application web requests"
|
||||
page_views: "Page Views"
|
||||
page_views_short: "Page Views"
|
||||
show_traffic_report: "Show Detailed Traffic Report"
|
||||
|
||||
reports:
|
||||
today: "Today"
|
||||
|
|
|
@ -590,42 +590,46 @@ en:
|
|||
title: "Top Referred Topics"
|
||||
xaxis: "Topic"
|
||||
num_clicks: "Clicks"
|
||||
topic_anon_reqs:
|
||||
title: "Anonymous Topic Views"
|
||||
page_view_anon_reqs:
|
||||
title: "Anonymous"
|
||||
xaxis: "Day"
|
||||
yaxis: "Anonymous Topic Views"
|
||||
topic_logged_in_reqs:
|
||||
title: "Logged In Topic Views"
|
||||
yaxis: "Anonymous Page Views"
|
||||
page_view_logged_in_reqs:
|
||||
title: "Logged In"
|
||||
xaxis: "Day"
|
||||
yaxis: "Logged In Topic Views"
|
||||
topic_crawler_reqs:
|
||||
title: "Crawler Topic Views"
|
||||
yaxis: "Logged In Page Views"
|
||||
page_view_crawler_reqs:
|
||||
title: "Web Crawlers"
|
||||
xaxis: "Day"
|
||||
yaxis: "Crawler Topic Views"
|
||||
background_reqs:
|
||||
title: "Background requests"
|
||||
xaxis: "Day"
|
||||
yaxis: "Requests used for live update and tracking"
|
||||
success_reqs:
|
||||
title: "Successful requests"
|
||||
xaxis: "Day"
|
||||
yaxis: "Successful requests (Status 2xx)"
|
||||
redirect_reqs:
|
||||
title: "Redirect requests"
|
||||
xaxis: "Day"
|
||||
yaxis: "Redirect requests (Status 3xx)"
|
||||
server_error_reqs:
|
||||
title: "Server Errors"
|
||||
xaxis: "Day"
|
||||
yaxis: "Server Errors (Status 5xx)"
|
||||
client_error_reqs:
|
||||
title: "Bad requests"
|
||||
xaxis: "Day"
|
||||
yaxis: "Client Errors (Status 4xx)"
|
||||
total_reqs:
|
||||
yaxis: "Web Crawler Page Views"
|
||||
page_view_total_reqs:
|
||||
title: "Total"
|
||||
xaxis: "Day"
|
||||
yaxis: "Total application requests"
|
||||
yaxis: "Total Page Views"
|
||||
http_background_reqs:
|
||||
title: "Background"
|
||||
xaxis: "Day"
|
||||
yaxis: "Requests used for live update and tracking"
|
||||
http_2xx_reqs:
|
||||
title: "Status 2xx (OK)"
|
||||
xaxis: "Day"
|
||||
yaxis: "Successful requests (Status 2xx)"
|
||||
http_3xx_reqs:
|
||||
title: "HTTP 3xx (Redirect)"
|
||||
xaxis: "Day"
|
||||
yaxis: "Redirect requests (Status 3xx)"
|
||||
http_4xx_reqs:
|
||||
title: "HTTP 4xx (Client Error)"
|
||||
xaxis: "Day"
|
||||
yaxis: "Client Errors (Status 4xx)"
|
||||
http_5xx_reqs:
|
||||
title: "HTTP 5xx (Server Error)"
|
||||
xaxis: "Day"
|
||||
yaxis: "Server Errors (Status 5xx)"
|
||||
http_total_reqs:
|
||||
title: "Total"
|
||||
xaxis: "Day"
|
||||
yaxis: "Total requests"
|
||||
|
||||
dashboard:
|
||||
rails_env_warning: "Your server is running in %{env} mode."
|
||||
|
|
8
db/migrate/20150206004143_flush_application_requests.rb
Normal file
8
db/migrate/20150206004143_flush_application_requests.rb
Normal file
|
@ -0,0 +1,8 @@
|
|||
class FlushApplicationRequests < ActiveRecord::Migration
|
||||
def up
|
||||
# flush as enum changed
|
||||
execute "TRUNCATE TABLE application_requests"
|
||||
end
|
||||
def down
|
||||
end
|
||||
end
|
|
@ -14,44 +14,45 @@ class Middleware::RequestTracker
|
|||
end
|
||||
|
||||
PATH_PARAMS = "action_dispatch.request.path_parameters".freeze
|
||||
TRACK_VIEW = "HTTP_DISCOURSE_TRACK_VIEW".freeze
|
||||
|
||||
|
||||
def self.log_request(result,env,helper=nil)
|
||||
|
||||
helper ||= Middleware::AnonymousCache::Helper.new(env)
|
||||
params = env[PATH_PARAMS]
|
||||
request = Rack::Request.new(env)
|
||||
|
||||
ApplicationRequest.increment!(:total)
|
||||
|
||||
status,_ = result
|
||||
status,headers = result
|
||||
status = status.to_i
|
||||
|
||||
if status >= 500
|
||||
ApplicationRequest.increment!(:server_error)
|
||||
elsif status >= 400
|
||||
ApplicationRequest.increment!(:client_error)
|
||||
elsif status >= 300
|
||||
ApplicationRequest.increment!(:redirect)
|
||||
end
|
||||
|
||||
if request.path =~ /^\/message-bus\// || request.path == /\/topics\/timings/
|
||||
ApplicationRequest.increment!(:background)
|
||||
elsif status >= 200 && status < 300
|
||||
ApplicationRequest.increment!(:success)
|
||||
end
|
||||
|
||||
if params && params[:controller] == "topics" && params[:action] == "show"
|
||||
if (env[TRACK_VIEW] || (request.get? && !request.xhr? && headers["Content-Type"] =~ /text\/html/)) && status == 200
|
||||
if helper.is_crawler?
|
||||
ApplicationRequest.increment!(:topic_crawler)
|
||||
ApplicationRequest.increment!(:page_view_crawler)
|
||||
elsif helper.has_auth_cookie?
|
||||
ApplicationRequest.increment!(:topic_logged_in)
|
||||
ApplicationRequest.increment!(:page_view_logged_in)
|
||||
else
|
||||
ApplicationRequest.increment!(:topic_anon)
|
||||
ApplicationRequest.increment!(:page_view_anon)
|
||||
end
|
||||
end
|
||||
|
||||
rescue => ex
|
||||
Discourse.handle_exception(ex, {message: "Failed to log request"})
|
||||
ApplicationRequest.increment!(:http_total)
|
||||
|
||||
if status >= 500
|
||||
ApplicationRequest.increment!(:http_5xx)
|
||||
elsif status >= 400
|
||||
ApplicationRequest.increment!(:http_4xx)
|
||||
elsif status >= 300
|
||||
ApplicationRequest.increment!(:http_3xx)
|
||||
else
|
||||
if request.path =~ /^\/message-bus\// || request.path == /\/topics\/timings/
|
||||
ApplicationRequest.increment!(:http_background)
|
||||
elsif status >= 200 && status < 300
|
||||
ApplicationRequest.increment!(:http_2xx)
|
||||
end
|
||||
end
|
||||
|
||||
# rescue => ex
|
||||
# Discourse.handle_exception(ex, {message: "Failed to log request"})
|
||||
end
|
||||
|
||||
|
||||
|
|
|
@ -18,21 +18,20 @@ describe Middleware::RequestTracker do
|
|||
|
||||
ApplicationRequest.clear_cache!
|
||||
|
||||
Middleware::RequestTracker.log_request(["200"], env(
|
||||
"HTTP_USER_AGENT" => "AdsBot-Google (+http://www.google.com/adsbot.html)",
|
||||
"action_dispatch.request.path_parameters" => {controller: "topics", action: "show"}
|
||||
Middleware::RequestTracker.log_request(["200",{"Content-Type" => 'text/html'}], env(
|
||||
"HTTP_USER_AGENT" => "AdsBot-Google (+http://www.google.com/adsbot.html)"
|
||||
))
|
||||
Middleware::RequestTracker.log_request(["200"], env(
|
||||
"action_dispatch.request.path_parameters" => {controller: "topics", action: "show"}
|
||||
Middleware::RequestTracker.log_request(["200",{}], env(
|
||||
"HTTP_DISCOURSE_TRACK_VIEW" => "1"
|
||||
))
|
||||
|
||||
ApplicationRequest.write_cache!
|
||||
|
||||
ApplicationRequest.total.first.count.should == 2
|
||||
ApplicationRequest.success.first.count.should == 2
|
||||
ApplicationRequest.http_total.first.count.should == 2
|
||||
ApplicationRequest.http_2xx.first.count.should == 2
|
||||
|
||||
ApplicationRequest.topic_anon.first.count.should == 1
|
||||
ApplicationRequest.topic_crawler.first.count.should == 1
|
||||
ApplicationRequest.page_view_anon.first.count.should == 1
|
||||
ApplicationRequest.page_view_crawler.first.count.should == 1
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -18,19 +18,32 @@ describe ApplicationRequest do
|
|||
it 'can automatically flush' do
|
||||
t1 = Time.now.utc.at_midnight
|
||||
freeze_time(t1)
|
||||
inc(:total)
|
||||
inc(:total)
|
||||
inc(:total, autoflush: 3)
|
||||
inc(:http_total)
|
||||
inc(:http_total)
|
||||
inc(:http_total, autoflush: 3)
|
||||
|
||||
ApplicationRequest.first.count.should == 3
|
||||
ApplicationRequest.http_total.first.count.should == 3
|
||||
end
|
||||
|
||||
it 'can flush based on time' do
|
||||
t1 = Time.now.utc.at_midnight
|
||||
freeze_time(t1)
|
||||
ApplicationRequest.write_cache!
|
||||
inc(:http_total)
|
||||
ApplicationRequest.count.should == 0
|
||||
|
||||
freeze_time(t1 + ApplicationRequest.autoflush_seconds + 1)
|
||||
inc(:http_total)
|
||||
|
||||
ApplicationRequest.count.should == 1
|
||||
end
|
||||
|
||||
it 'flushes yesterdays results' do
|
||||
t1 = Time.now.utc.at_midnight
|
||||
freeze_time(t1)
|
||||
inc(:total)
|
||||
inc(:http_total)
|
||||
freeze_time(t1.tomorrow)
|
||||
inc(:total)
|
||||
inc(:http_total)
|
||||
|
||||
ApplicationRequest.write_cache!
|
||||
ApplicationRequest.count.should == 2
|
||||
|
@ -49,15 +62,15 @@ describe ApplicationRequest do
|
|||
time = Time.now.at_midnight
|
||||
freeze_time(time)
|
||||
|
||||
3.times { inc(:total) }
|
||||
2.times { inc(:success) }
|
||||
4.times { inc(:redirect) }
|
||||
3.times { inc(:http_total) }
|
||||
2.times { inc(:http_2xx) }
|
||||
4.times { inc(:http_3xx) }
|
||||
|
||||
ApplicationRequest.write_cache!
|
||||
|
||||
ApplicationRequest.total.first.count.should == 3
|
||||
ApplicationRequest.success.first.count.should == 2
|
||||
ApplicationRequest.redirect.first.count.should == 4
|
||||
ApplicationRequest.http_total.first.count.should == 3
|
||||
ApplicationRequest.http_2xx.first.count.should == 2
|
||||
ApplicationRequest.http_3xx.first.count.should == 4
|
||||
|
||||
end
|
||||
end
|
||||
|
|
Loading…
Reference in a new issue