rails_performance 1.2.3 → 1.3.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +5 -13
- data/Rakefile +14 -14
- data/app/assets/images/download.svg +3 -0
- data/app/controllers/rails_performance/base_controller.rb +21 -21
- data/app/controllers/rails_performance/concerns/csv_exportable.rb +29 -0
- data/app/controllers/rails_performance/rails_performance_controller.rb +95 -49
- data/app/helpers/rails_performance/rails_performance_helper.rb +152 -156
- data/app/views/rails_performance/javascripts/app.js +2 -2
- data/app/views/rails_performance/rails_performance/_export.html.erb +3 -0
- data/app/views/rails_performance/rails_performance/crashes.html.erb +8 -1
- data/app/views/rails_performance/rails_performance/recent.html.erb +8 -6
- data/app/views/rails_performance/rails_performance/requests.html.erb +8 -1
- data/app/views/rails_performance/rails_performance/slow.html.erb +3 -0
- data/app/views/rails_performance/shared/_header.html.erb +0 -1
- data/app/views/rails_performance/stylesheets/style.css +6 -0
- data/config/routes.rb +16 -18
- data/lib/generators/rails_performance/install/install_generator.rb +1 -1
- data/lib/generators/rails_performance/install/templates/initializer.rb +56 -42
- data/lib/rails_performance/data_source.rb +120 -121
- data/lib/rails_performance/engine.rb +8 -8
- data/lib/rails_performance/extensions/trace.rb +32 -33
- data/lib/rails_performance/gems/custom_ext.rb +31 -34
- data/lib/rails_performance/gems/delayed_job_ext.rb +50 -54
- data/lib/rails_performance/gems/grape_ext.rb +33 -35
- data/lib/rails_performance/gems/rake_ext.rb +41 -44
- data/lib/rails_performance/gems/sidekiq_ext.rb +34 -37
- data/lib/rails_performance/instrument/metrics_collector.rb +50 -50
- data/lib/rails_performance/models/base_record.rb +33 -36
- data/lib/rails_performance/models/collection.rb +35 -36
- data/lib/rails_performance/models/custom_record.rb +47 -48
- data/lib/rails_performance/models/delayed_job_record.rb +61 -62
- data/lib/rails_performance/models/grape_record.rb +60 -61
- data/lib/rails_performance/models/rake_record.rb +48 -49
- data/lib/rails_performance/models/request_record.rb +123 -120
- data/lib/rails_performance/models/sidekiq_record.rb +65 -66
- data/lib/rails_performance/models/trace_record.rb +18 -19
- data/lib/rails_performance/rails/middleware.rb +75 -76
- data/lib/rails_performance/rails/query_builder.rb +18 -20
- data/lib/rails_performance/reports/base_report.rb +60 -60
- data/lib/rails_performance/reports/breakdown_report.rb +15 -18
- data/lib/rails_performance/reports/crash_report.rb +15 -17
- data/lib/rails_performance/reports/recent_requests_report.rb +24 -24
- data/lib/rails_performance/reports/requests_report.rb +27 -27
- data/lib/rails_performance/reports/response_time_report.rb +17 -17
- data/lib/rails_performance/reports/slow_requests_report.rb +4 -4
- data/lib/rails_performance/reports/throughput_report.rb +15 -17
- data/lib/rails_performance/reports/trace_report.rb +16 -18
- data/lib/rails_performance/thread/current_request.rb +33 -34
- data/lib/rails_performance/utils.rb +53 -54
- data/lib/rails_performance/version.rb +2 -2
- data/lib/rails_performance.rb +33 -34
- metadata +20 -3
@@ -1,156 +1,152 @@
|
|
1
|
-
module RailsPerformance
|
2
|
-
module RailsPerformanceHelper
|
3
|
-
|
4
|
-
|
5
|
-
return
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
duration
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
<span class="tag">#{
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
end
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
@icons ||= {}
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
end
|
117
|
-
|
118
|
-
def
|
119
|
-
raw "<
|
120
|
-
end
|
121
|
-
|
122
|
-
def
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
when :
|
134
|
-
"is-active" if controller_name == "rails_performance" && action_name == "
|
135
|
-
when :
|
136
|
-
"is-active" if controller_name == "rails_performance" && action_name == "
|
137
|
-
when :
|
138
|
-
"is-active" if controller_name == "rails_performance" && action_name == "
|
139
|
-
when :
|
140
|
-
"is-active" if controller_name == "rails_performance" && action_name == "
|
141
|
-
when :
|
142
|
-
"is-active" if controller_name == "rails_performance" && action_name == "
|
143
|
-
when :
|
144
|
-
"is-active" if controller_name == "rails_performance" && action_name == "
|
145
|
-
when :
|
146
|
-
"is-active" if controller_name == "rails_performance" && action_name == "
|
147
|
-
when :
|
148
|
-
"is-active" if controller_name == "rails_performance" && action_name == "
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
end
|
154
|
-
end
|
155
|
-
end
|
156
|
-
end
|
1
|
+
module RailsPerformance
|
2
|
+
module RailsPerformanceHelper
|
3
|
+
def round_it(value, limit = 1)
|
4
|
+
return nil unless value
|
5
|
+
return value if value.is_a?(Integer)
|
6
|
+
|
7
|
+
value.nan? ? nil : value.round(limit)
|
8
|
+
end
|
9
|
+
|
10
|
+
def duraction_alert_class(duration_str)
|
11
|
+
if duration_str.to_s =~ /(\d+.?\d+?)/
|
12
|
+
duration = $1.to_f
|
13
|
+
if duration >= 500
|
14
|
+
"has-background-danger has-text-white-bis"
|
15
|
+
elsif duration >= 200
|
16
|
+
"has-background-warning has-text-black-ter"
|
17
|
+
else
|
18
|
+
"has-background-success has-text-white-bis"
|
19
|
+
end
|
20
|
+
else
|
21
|
+
"has-background-light"
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
def extract_duration(str)
|
26
|
+
if str =~ /Duration: (\d+.?\d+?ms)/i
|
27
|
+
$1
|
28
|
+
else
|
29
|
+
"-"
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
def mss(value, limit = 1)
|
34
|
+
ms(value.to_f * 1000, limit)
|
35
|
+
end
|
36
|
+
|
37
|
+
def ms(value, limit = 1)
|
38
|
+
result = round_it(value, limit)
|
39
|
+
return "-" if result.nil?
|
40
|
+
|
41
|
+
(result && result != 0) ? "#{result} ms" : "< 0 ms"
|
42
|
+
end
|
43
|
+
|
44
|
+
def short_path(path, length: 55)
|
45
|
+
content_tag :span, title: path do
|
46
|
+
truncate(path, length: length)
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
def link_to_path(e)
|
51
|
+
if e[:method] == "GET"
|
52
|
+
link_to(short_path(e[:path]), e[:path], target: "_blank", title: short_path(e[:path]))
|
53
|
+
else
|
54
|
+
short_path(e[:path])
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
def report_name(h)
|
59
|
+
h.except(:on).collect do |k, v|
|
60
|
+
next if v.blank?
|
61
|
+
|
62
|
+
%(
|
63
|
+
<div class="control">
|
64
|
+
<span class="tags has-addons">
|
65
|
+
<span class="tag">#{k}</span>
|
66
|
+
<span class="tag is-info is-light">#{v}</span>
|
67
|
+
</span>
|
68
|
+
</div>)
|
69
|
+
end.compact.join.html_safe
|
70
|
+
end
|
71
|
+
|
72
|
+
def status_tag(status)
|
73
|
+
klass = case status.to_s
|
74
|
+
when /error/
|
75
|
+
"tag is-danger"
|
76
|
+
when /^5/
|
77
|
+
"tag is-danger"
|
78
|
+
when /^4/
|
79
|
+
"tag is-warning"
|
80
|
+
when /^3/
|
81
|
+
"tag is-info"
|
82
|
+
when /^2/
|
83
|
+
"tag is-success"
|
84
|
+
when /success/
|
85
|
+
"tag is-success"
|
86
|
+
end
|
87
|
+
content_tag(:span, class: klass) do
|
88
|
+
status
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
92
|
+
def bot_icon(user_agent)
|
93
|
+
return nil if user_agent.blank?
|
94
|
+
|
95
|
+
browser = Browser.new(user_agent)
|
96
|
+
if browser.bot?
|
97
|
+
content_tag(:span, class: "user-agent-icon", title: browser.bot&.name) do
|
98
|
+
icon("bot")
|
99
|
+
end
|
100
|
+
else
|
101
|
+
content_tag(:span, class: "user-agent-icon user-agent-icon-user", title: "Real User") do
|
102
|
+
icon("user")
|
103
|
+
end
|
104
|
+
end
|
105
|
+
end
|
106
|
+
|
107
|
+
def icon(name)
|
108
|
+
@icons ||= {}
|
109
|
+
|
110
|
+
# https://www.iconfinder.com/iconsets/vivid
|
111
|
+
@icons[name] ||= raw File.read(File.expand_path(File.dirname(__FILE__) + "/../../assets/images/#{name}.svg"))
|
112
|
+
end
|
113
|
+
|
114
|
+
def insert_css_file(file)
|
115
|
+
raw "<style>#{raw File.read File.expand_path(File.dirname(__FILE__) + "/../../views/rails_performance/stylesheets/#{file}")}</style>"
|
116
|
+
end
|
117
|
+
|
118
|
+
def insert_js_file(file)
|
119
|
+
raw "<script>#{raw File.read File.expand_path(File.dirname(__FILE__) + "/../../views/rails_performance/javascripts/#{file}")}</script>"
|
120
|
+
end
|
121
|
+
|
122
|
+
def format_datetime(e)
|
123
|
+
dt = RailsPerformance::Reports::BaseReport.time_in_app_time_zone(e)
|
124
|
+
I18n.l(dt, format: "%Y-%m-%d %H:%M:%S")
|
125
|
+
end
|
126
|
+
|
127
|
+
def active?(section)
|
128
|
+
case section
|
129
|
+
when :dashboard
|
130
|
+
"is-active" if controller_name == "rails_performance" && action_name == "index"
|
131
|
+
when :crashes
|
132
|
+
"is-active" if controller_name == "rails_performance" && action_name == "crashes"
|
133
|
+
when :requests
|
134
|
+
"is-active" if controller_name == "rails_performance" && action_name == "requests"
|
135
|
+
when :recent
|
136
|
+
"is-active" if controller_name == "rails_performance" && action_name == "recent"
|
137
|
+
when :slow
|
138
|
+
"is-active" if controller_name == "rails_performance" && action_name == "slow"
|
139
|
+
when :sidekiq
|
140
|
+
"is-active" if controller_name == "rails_performance" && action_name == "sidekiq"
|
141
|
+
when :delayed_job
|
142
|
+
"is-active" if controller_name == "rails_performance" && action_name == "delayed_job"
|
143
|
+
when :grape
|
144
|
+
"is-active" if controller_name == "rails_performance" && action_name == "grape"
|
145
|
+
when :rake
|
146
|
+
"is-active" if controller_name == "rails_performance" && action_name == "rake"
|
147
|
+
when :custom
|
148
|
+
"is-active" if controller_name == "rails_performance" && action_name == "custom"
|
149
|
+
end
|
150
|
+
end
|
151
|
+
end
|
152
|
+
end
|
@@ -22,7 +22,7 @@ function showTIRChart(div, data, addon, name) {
|
|
22
22
|
},
|
23
23
|
formatter: function() {
|
24
24
|
if (this.y == 0) {
|
25
|
-
return
|
25
|
+
return false;
|
26
26
|
}
|
27
27
|
return this.y + addon;
|
28
28
|
}
|
@@ -107,7 +107,7 @@ function showRTChart(div, data) {
|
|
107
107
|
},
|
108
108
|
formatter: function() {
|
109
109
|
if (this.y == 0) {
|
110
|
-
return
|
110
|
+
return false;
|
111
111
|
}
|
112
112
|
return this.y + ' ms';
|
113
113
|
}
|
@@ -1,6 +1,13 @@
|
|
1
1
|
<div class="card">
|
2
2
|
<div class="card-content">
|
3
|
-
<
|
3
|
+
<div class="columns is-vcentered">
|
4
|
+
<div class="column">
|
5
|
+
<h2 class="subtitle">Crash Report</h2>
|
6
|
+
</div>
|
7
|
+
<div class="column is-narrow">
|
8
|
+
<%= render "export" %>
|
9
|
+
</div>
|
10
|
+
</div>
|
4
11
|
<table class="table is-fullwidth is-hoverable is-narrow">
|
5
12
|
<thead>
|
6
13
|
<tr>
|
@@ -6,14 +6,16 @@
|
|
6
6
|
<div class="column">
|
7
7
|
<h2 class="subtitle">Recent Requests (last <%= RailsPerformance.recent_requests_time_window / 60 %> minutes)<h2>
|
8
8
|
</div>
|
9
|
-
<div class="column
|
10
|
-
|
11
|
-
<input id="autoupdate" type="checkbox"/>
|
12
|
-
Auto-update
|
13
|
-
</label>
|
9
|
+
<div class="column is-narrow">
|
10
|
+
<%= render "export" %>
|
14
11
|
</div>
|
15
12
|
</div>
|
16
|
-
|
13
|
+
<div class="has-text-right">
|
14
|
+
<label id="autoupdate_label">
|
15
|
+
<input id="autoupdate" type="checkbox" />
|
16
|
+
Auto-update
|
17
|
+
</label>
|
18
|
+
</div>
|
17
19
|
<table id="recent" class="table is-fullwidth is-hoverable is-narrow">
|
18
20
|
<thead>
|
19
21
|
<tr>
|
@@ -1,6 +1,13 @@
|
|
1
1
|
<div class="card">
|
2
2
|
<div class="card-content">
|
3
|
-
<
|
3
|
+
<div class="columns is-vcentered">
|
4
|
+
<div class="column">
|
5
|
+
<h2 class="subtitle">Requests (path, total number, average response time)</h2>
|
6
|
+
</div>
|
7
|
+
<div class="column is-narrow">
|
8
|
+
<%= render "export" %>
|
9
|
+
</div>
|
10
|
+
</div>
|
4
11
|
<table class="table is-fullwidth is-hoverable is-narrow">
|
5
12
|
<thead>
|
6
13
|
<tr>
|
@@ -6,6 +6,9 @@
|
|
6
6
|
<div class="column">
|
7
7
|
<h2 class="subtitle">Slow Requests (last <%= RailsPerformance.slow_requests_time_window / 60 %> minutes + slower than <%= RailsPerformance.slow_requests_threshold %>ms)<h2>
|
8
8
|
</div>
|
9
|
+
<div class="column is-narrow">
|
10
|
+
<%= render "export" %>
|
11
|
+
</div>
|
9
12
|
</div>
|
10
13
|
|
11
14
|
<table id="recent" class="table is-fullwidth is-hoverable is-narrow">
|
@@ -39,7 +39,6 @@
|
|
39
39
|
<div class="navbar-end">
|
40
40
|
<div class="navbar-item">
|
41
41
|
<div class="buttons">
|
42
|
-
<%#= link_to 'Export to CSV', '#', target: '_blank', class: "button is-primary" %>
|
43
42
|
<%= link_to RailsPerformance.home_link, class: "button is-light home_icon" do %>
|
44
43
|
<%= icon('home') %>
|
45
44
|
<% end %>
|
data/config/routes.rb
CHANGED
@@ -1,26 +1,24 @@
|
|
1
1
|
RailsPerformance::Engine.routes.draw do
|
2
|
-
get
|
2
|
+
get "/" => "rails_performance#index", :as => :rails_performance
|
3
3
|
|
4
|
-
get
|
5
|
-
get
|
6
|
-
get
|
7
|
-
get
|
4
|
+
get "/requests" => "rails_performance#requests", :as => :rails_performance_requests
|
5
|
+
get "/crashes" => "rails_performance#crashes", :as => :rails_performance_crashes
|
6
|
+
get "/recent" => "rails_performance#recent", :as => :rails_performance_recent
|
7
|
+
get "/slow" => "rails_performance#slow", :as => :rails_performance_slow
|
8
8
|
|
9
|
-
get
|
10
|
-
get
|
9
|
+
get "/trace/:id" => "rails_performance#trace", :as => :rails_performance_trace
|
10
|
+
get "/summary" => "rails_performance#summary", :as => :rails_performance_summary
|
11
11
|
|
12
|
-
get
|
13
|
-
get
|
14
|
-
get
|
15
|
-
get
|
16
|
-
get
|
12
|
+
get "/sidekiq" => "rails_performance#sidekiq", :as => :rails_performance_sidekiq
|
13
|
+
get "/delayed_job" => "rails_performance#delayed_job", :as => :rails_performance_delayed_job
|
14
|
+
get "/grape" => "rails_performance#grape", :as => :rails_performance_grape
|
15
|
+
get "/rake" => "rails_performance#rake", :as => :rails_performance_rake
|
16
|
+
get "/custom" => "rails_performance#custom", :as => :rails_performance_custom
|
17
17
|
end
|
18
18
|
|
19
19
|
Rails.application.routes.draw do
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
# this code exist here because engine not includes routing automatically
|
25
|
-
end
|
20
|
+
mount RailsPerformance::Engine => RailsPerformance.mount_at, :as => "rails_performance"
|
21
|
+
rescue ArgumentError
|
22
|
+
# already added
|
23
|
+
# this code exist here because engine not includes routing automatically
|
26
24
|
end
|
@@ -1,42 +1,56 @@
|
|
1
|
-
RailsPerformance
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
1
|
+
if defined?(RailsPerformance)
|
2
|
+
RailsPerformance.setup do |config|
|
3
|
+
# Redis configuration
|
4
|
+
config.redis = Redis::Namespace.new("#{Rails.env}-rails-performance", redis: Redis.new(url: ENV["REDIS_URL"].presence || "redis://127.0.0.1:6379/0"))
|
5
|
+
|
6
|
+
# All data we collect
|
7
|
+
config.duration = 4.hours
|
8
|
+
|
9
|
+
# Recent Requests configuration
|
10
|
+
config.recent_requests_time_window = 60.minutes
|
11
|
+
# confog.recent_requests_limit = nil # numnber of recent requests
|
12
|
+
|
13
|
+
# Slow Requests configuration
|
14
|
+
config.slow_requests_time_window = 4.hours
|
15
|
+
# config.slow_requests_limit = 500 # numnber of slow requests
|
16
|
+
config.slow_requests_threshold = 500 # ms
|
17
|
+
|
18
|
+
config.debug = false # currently not used>
|
19
|
+
config.enabled = true
|
20
|
+
|
21
|
+
# default path where to mount gem
|
22
|
+
config.mount_at = "/rails/performance"
|
23
|
+
|
24
|
+
# protect your Performance Dashboard with HTTP BASIC password
|
25
|
+
config.http_basic_authentication_enabled = false
|
26
|
+
config.http_basic_authentication_user_name = "rails_performance"
|
27
|
+
config.http_basic_authentication_password = "password12"
|
28
|
+
|
29
|
+
# if you need an additional rules to check user permissions
|
30
|
+
config.verify_access_proc = proc { |controller| true }
|
31
|
+
# for example when you have `current_user`
|
32
|
+
# config.verify_access_proc = proc { |controller| controller.current_user && controller.current_user.admin? }
|
33
|
+
|
34
|
+
# You can ignore endpoints with Rails standard notation controller#action
|
35
|
+
# config.ignored_endpoints = ['HomeController#contact']
|
36
|
+
|
37
|
+
# You can ignore request paths by specifying the beginning of the path.
|
38
|
+
# For example, all routes starting with '/admin' can be ignored:
|
39
|
+
config.ignored_paths = ['/rails/performance']
|
40
|
+
|
41
|
+
# store custom data for the request
|
42
|
+
# config.custom_data_proc = proc do |env|
|
43
|
+
# request = Rack::Request.new(env)
|
44
|
+
# {
|
45
|
+
# email: request.env['warden'].user&.email, # if you are using Devise for example
|
46
|
+
# user_agent: request.env['HTTP_USER_AGENT']
|
47
|
+
# }
|
48
|
+
# end
|
49
|
+
|
50
|
+
# config home button link
|
51
|
+
config.home_link = "/"
|
52
|
+
config.skipable_rake_tasks = ["webpacker:compile"]
|
53
|
+
config.include_rake_tasks = false
|
54
|
+
config.include_custom_events = true
|
55
|
+
end
|
56
|
+
end
|