rails_performance 1.2.3 → 1.3.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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 +96 -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/index.html.erb +29 -0
- data/app/views/rails_performance/rails_performance/recent.html.erb +8 -6
- data/app/views/rails_performance/rails_performance/requests.html.erb +15 -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 +10 -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 +128 -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/percentile_report.rb +14 -0
- data/lib/rails_performance/reports/recent_requests_report.rb +24 -24
- data/lib/rails_performance/reports/requests_report.rb +30 -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 +64 -54
- data/lib/rails_performance/version.rb +2 -2
- data/lib/rails_performance.rb +35 -36
- metadata +21 -17
@@ -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>
|
@@ -4,6 +4,35 @@
|
|
4
4
|
<%#= link_to raw("← Back"), rails_performance_path, class: "back_link" %>
|
5
5
|
<% end %>
|
6
6
|
|
7
|
+
<div class="columns">
|
8
|
+
<div class="column">
|
9
|
+
<div class="card">
|
10
|
+
<div class="card-content">
|
11
|
+
<h2 class="subtitle is-size-1"><%= ms @percentile_report_data[:p50] %></h2>
|
12
|
+
<p class="content is-size-4">p50</p>
|
13
|
+
</div>
|
14
|
+
</div>
|
15
|
+
</div>
|
16
|
+
|
17
|
+
<div class="column">
|
18
|
+
<div class="card">
|
19
|
+
<div class="card-content">
|
20
|
+
<h2 class="subtitle is-size-1"><%= ms @percentile_report_data[:p95] %></h2>
|
21
|
+
<p class="content is-size-4">p95</p>
|
22
|
+
</div>
|
23
|
+
</div>
|
24
|
+
</div>
|
25
|
+
|
26
|
+
<div class="column">
|
27
|
+
<div class="card">
|
28
|
+
<div class="card-content">
|
29
|
+
<h2 class="subtitle is-size-1"><%= ms @percentile_report_data[:p99] %></h2>
|
30
|
+
<p class="content is-size-4">p99</p>
|
31
|
+
</div>
|
32
|
+
</div>
|
33
|
+
</div>
|
34
|
+
</div>
|
35
|
+
|
7
36
|
<div class="card">
|
8
37
|
<div class="card-content">
|
9
38
|
<h2 class="subtitle">Throughput Report</h2>
|
@@ -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,10 +1,18 @@
|
|
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 Analysis</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>
|
7
14
|
<th colspan='3'>Name</th>
|
15
|
+
<th colspan='3' class="attention">Percentile</th>
|
8
16
|
<th colspan='3'>Average</th>
|
9
17
|
<th colspan='3'>Slowest</th>
|
10
18
|
</tr>
|
@@ -12,6 +20,9 @@
|
|
12
20
|
<th data-sort="string">Controller#action</th>
|
13
21
|
<th data-sort="string">Format</th>
|
14
22
|
<th data-sort="int">Requests</th>
|
23
|
+
<th data-sort="float" class="attention">P50</th>
|
24
|
+
<th data-sort="float" class="attention">P95</th>
|
25
|
+
<th data-sort="float" class="attention">P99</th>
|
15
26
|
<th data-sort="float">Duration</th>
|
16
27
|
<th data-sort="float">Views</th>
|
17
28
|
<th data-sort="float">DB</th>
|
@@ -28,6 +39,9 @@
|
|
28
39
|
<td><%= link_to groups[0], rails_performance.rails_performance_summary_path({controller_eq: c, action_eq: a}), remote: true %></td>
|
29
40
|
<td><%= link_to groups[1].try(:upcase), rails_performance.rails_performance_summary_path({controller_eq: c, action_eq: a, format_eq: groups[1]}), remote: true %></td>
|
30
41
|
<td><%= e[:count] %></td>
|
42
|
+
<td class="nowrap attention"><%= ms e[:p50_duration] %></td>
|
43
|
+
<td class="nowrap attention"><%= ms e[:p95_duration] %></td>
|
44
|
+
<td class="nowrap attention"><%= ms e[:p99_duration] %></td>
|
31
45
|
<td class="nowrap"><%= ms e[:duration_average] %></td>
|
32
46
|
<td class="nowrap"><%= ms e[:view_runtime_average] %></td>
|
33
47
|
<td class="nowrap"><%= ms e[:db_runtime_average] %></td>
|
@@ -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 %>
|
@@ -56,6 +56,12 @@
|
|
56
56
|
height: 24px;
|
57
57
|
}
|
58
58
|
|
59
|
+
.download_icon svg {
|
60
|
+
width: 24px;
|
61
|
+
height: 24px;
|
62
|
+
color: red;
|
63
|
+
}
|
64
|
+
|
59
65
|
.user-agent-icon svg {
|
60
66
|
width: 12px;
|
61
67
|
height: 12px;
|
@@ -115,3 +121,7 @@ table th[data-sort] {
|
|
115
121
|
font-size: 7px !important;
|
116
122
|
line-height: 20px !important;
|
117
123
|
}
|
124
|
+
|
125
|
+
.attention {
|
126
|
+
background-color: #f6f5f5;
|
127
|
+
}
|
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
|