rails_performance 1.3.2 → 1.4.0.alpha1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: ce8db107a23bdd7c902fa8edcc2ebe260998e1cf7712f0a710131983b28c3fa9
4
- data.tar.gz: 82e818c24db06fb74d6d477aba06f0841174894c23f45fab785dd6dd0f808aa8
3
+ metadata.gz: 524031a11cbbe218cd746b2469a34b05e0867fa33f2f87dc06377a9a6ee983da
4
+ data.tar.gz: 69ea547a8574ed29550d28057d6d7369f8598509104fdcad002408be71533af6
5
5
  SHA512:
6
- metadata.gz: 49d48df321943a17cd226f68ace96bbebca96ab6b47dde70e6cc95fd21276338562d3e0dbe365d1133aa6cd93981d2dd0980790cac8f52512ac2fbdb3558263d
7
- data.tar.gz: 6c3ec9d24045abc760cba57d2f3d12fe6c3ea0e35a49a138bad3bfec06ae9c8a0ebc11721c5a3c92a9f3dcad6dc80ac98d1b0d6e3fd0a2a8063b11a715dfb5e8
6
+ metadata.gz: '0122738b6f1fde35c2bca00783e26e1c0f65b84896b4e22130e79dfffd2e59d211d7aec34f9b9b7718c239a713993e8d05656bc87294e253d7695462b9f477ea'
7
+ data.tar.gz: 5170e8f7e24ce9a9904bf7d9163dbf34eca2063da745fb9824f808793a12e9940b618b5b64ebe8f2fe39e6e12bebcc98f560c9fdd3fd51fb6fc973f880417a8e
data/README.md CHANGED
@@ -10,9 +10,19 @@ This is a **simple and free alternative** to the New Relic APM, Datadog or other
10
10
 
11
11
  ![Demo](docs/rails_performance.gif)
12
12
 
13
+ A new version with P50, P90, P99, throughput, and more is available.
14
+
15
+ ![Home](docs/rails_performance_updated_home.png)
16
+
17
+ Detailed p50, p90, p99 response time information.
18
+
19
+ ![Home](docs/rails_performance_recent_requests.png)
20
+
13
21
  It allows you to track:
14
22
 
15
23
  - real-time monitoring on the Recent tab
24
+ - see your p50, p90, p99 response time
25
+ - monitor system resources (CPU, memory, disk)
16
26
  - monitor slow requests
17
27
  - throughput report (see amount of RPM (requests per minute))
18
28
  - an average response time
@@ -51,7 +61,7 @@ Create `config/initializers/rails_performance.rb` in your app:
51
61
 
52
62
  ```ruby
53
63
  RailsPerformance.setup do |config|
54
- config.redis = Redis::Namespace.new("#{Rails.env}-rails-performance", redis: Redis.new(url: ENV["REDIS_URL"].presence || "redis://127.0.0.1:6379/0"))
64
+ config.redis = Redis.new(url: ENV["REDIS_URL"].presence || "redis://127.0.0.1:6379/0") # or Redis::Namespace.new("rails-performance", redis: Redis.new), see below in README
55
65
  config.duration = 4.hours
56
66
 
57
67
  config.debug = false # currently not used>
@@ -165,6 +175,16 @@ You need to configure `config.custom_data_proc`. And you can capture current_use
165
175
  ![Custom Data](docs/custom_data.png)
166
176
 
167
177
 
178
+ ### System Monitoring
179
+
180
+ You can monitor system resources (CPU, memory, disk) by adding a gem to your Gemfile:
181
+
182
+ ```ruby
183
+ gem "sys-filesystem"
184
+ gem "sys-cpu"
185
+ gem "get_process_mem"
186
+ ```
187
+
168
188
  ### Custom events
169
189
 
170
190
  ```ruby
@@ -173,6 +193,20 @@ RailsPerformance.measure("some label", "some namespace") do
173
193
  end
174
194
  ```
175
195
 
196
+ ## Using with Rails Namespace
197
+
198
+ If you want to use Redis namespace (for example when you have multiple apps running on the same server), you can configure it like this:
199
+
200
+ ```ruby
201
+ config.redis = Redis::Namespace.new("#{Rails.env}-rails-performance", redis: Redis.new(url: ENV["REDIS_URL"].presence || "redis://127.0.0.1:6379/0"))
202
+ ```
203
+
204
+ and add a gem dependency to the Gemfile:
205
+
206
+ ```ruby
207
+ gem 'redis-namespace'
208
+ ```
209
+
176
210
  ## How it works
177
211
 
178
212
  ![Schema](docs/rails_performance.png)
@@ -6,9 +6,7 @@ module RailsPerformance
6
6
 
7
7
  if RailsPerformance.enabled
8
8
  def index
9
- @datasource = RailsPerformance::DataSource.new(
10
- **prepare_query, type: :requests
11
- )
9
+ @datasource = RailsPerformance::DataSource.new(**prepare_query(params), type: :requests)
12
10
  db = @datasource.db
13
11
 
14
12
  @throughput_report_data = RailsPerformance::Reports::ThroughputReport.new(db).data
@@ -16,17 +14,20 @@ module RailsPerformance
16
14
  @percentile_report_data = RailsPerformance::Reports::PercentileReport.new(db).data
17
15
  end
18
16
 
17
+ def resources
18
+ @datasource = RailsPerformance::DataSource.new(**prepare_query(params), type: :resources)
19
+ db = @datasource.db
20
+
21
+ @resources_report = RailsPerformance::Reports::ResourcesReport.new(db)
22
+ end
23
+
19
24
  def summary
20
- @datasource = RailsPerformance::DataSource.new(
21
- **prepare_query, type: :requests
22
- )
25
+ @datasource = RailsPerformance::DataSource.new(**prepare_query(params), type: :requests)
23
26
  db = @datasource.db
24
27
 
25
28
  @throughput_report_data = RailsPerformance::Reports::ThroughputReport.new(db).data
26
29
  @response_time_report_data = RailsPerformance::Reports::ResponseTimeReport.new(db).data
27
- @data = RailsPerformance::Reports::BreakdownReport.new(
28
- db, title: "Requests"
29
- ).data
30
+ @data = RailsPerformance::Reports::BreakdownReport.new(db, title: "Requests").data
30
31
  respond_to do |format|
31
32
  format.js {}
32
33
  format.any do
@@ -47,9 +48,7 @@ module RailsPerformance
47
48
  end
48
49
 
49
50
  def crashes
50
- @datasource = RailsPerformance::DataSource.new(
51
- **prepare_query({status_eq: 500}), type: :requests
52
- )
51
+ @datasource = RailsPerformance::DataSource.new(**prepare_query({status_eq: 500}), type: :requests)
53
52
  db = @datasource.db
54
53
  @data = RailsPerformance::Reports::CrashReport.new(db).data
55
54
 
@@ -62,11 +61,9 @@ module RailsPerformance
62
61
  end
63
62
 
64
63
  def requests
65
- @datasource = RailsPerformance::DataSource.new(**prepare_query,
66
- type: :requests)
64
+ @datasource = RailsPerformance::DataSource.new(**prepare_query(params), type: :requests)
67
65
  db = @datasource.db
68
- @data = RailsPerformance::Reports::RequestsReport.new(db,
69
- group: :controller_action_format, sort: :count).data
66
+ @data = RailsPerformance::Reports::RequestsReport.new(db, group: :controller_action_format, sort: :count).data
70
67
  respond_to do |format|
71
68
  format.html
72
69
  format.csv do
@@ -76,8 +73,7 @@ type: :requests)
76
73
  end
77
74
 
78
75
  def recent
79
- @datasource = RailsPerformance::DataSource.new(**prepare_query,
80
- type: :requests)
76
+ @datasource = RailsPerformance::DataSource.new(**prepare_query(params), type: :requests)
81
77
  db = @datasource.db
82
78
  @data = RailsPerformance::Reports::RecentRequestsReport.new(db).data(params[:from_timei])
83
79
 
@@ -110,8 +106,7 @@ type: :requests)
110
106
  end
111
107
 
112
108
  def slow
113
- @datasource = RailsPerformance::DataSource.new(**prepare_query,
114
- type: :requests)
109
+ @datasource = RailsPerformance::DataSource.new(**prepare_query(params), type: :requests)
115
110
  db = @datasource.db
116
111
  @data = RailsPerformance::Reports::SlowRequestsReport.new(db).data
117
112
 
@@ -124,9 +119,7 @@ type: :requests)
124
119
  end
125
120
 
126
121
  def sidekiq
127
- @datasource = RailsPerformance::DataSource.new(
128
- **prepare_query, type: :sidekiq
129
- )
122
+ @datasource = RailsPerformance::DataSource.new(**prepare_query(params), type: :sidekiq)
130
123
  db = @datasource.db
131
124
  @throughput_report_data = RailsPerformance::Reports::ThroughputReport.new(db).data
132
125
  @response_time_report_data = RailsPerformance::Reports::ResponseTimeReport.new(db).data
@@ -134,9 +127,7 @@ type: :requests)
134
127
  end
135
128
 
136
129
  def delayed_job
137
- @datasource = RailsPerformance::DataSource.new(
138
- **prepare_query, type: :delayed_job
139
- )
130
+ @datasource = RailsPerformance::DataSource.new(**prepare_query(params), type: :delayed_job)
140
131
  db = @datasource.db
141
132
  @throughput_report_data = RailsPerformance::Reports::ThroughputReport.new(db).data
142
133
  @response_time_report_data = RailsPerformance::Reports::ResponseTimeReport.new(db).data
@@ -144,9 +135,7 @@ type: :requests)
144
135
  end
145
136
 
146
137
  def custom
147
- @datasource = RailsPerformance::DataSource.new(
148
- **prepare_query, type: :custom
149
- )
138
+ @datasource = RailsPerformance::DataSource.new(**prepare_query(params), type: :custom)
150
139
  db = @datasource.db
151
140
  @throughput_report_data = RailsPerformance::Reports::ThroughputReport.new(db).data
152
141
  @response_time_report_data = RailsPerformance::Reports::ResponseTimeReport.new(db).data
@@ -154,18 +143,14 @@ type: :requests)
154
143
  end
155
144
 
156
145
  def grape
157
- @datasource = RailsPerformance::DataSource.new(
158
- **prepare_query, type: :grape
159
- )
146
+ @datasource = RailsPerformance::DataSource.new(**prepare_query(params), type: :grape)
160
147
  db = @datasource.db
161
148
  @throughput_report_data = RailsPerformance::Reports::ThroughputReport.new(db).data
162
149
  @recent_report_data = RailsPerformance::Reports::RecentRequestsReport.new(db).data
163
150
  end
164
151
 
165
152
  def rake
166
- @datasource = RailsPerformance::DataSource.new(
167
- **prepare_query, type: :rake
168
- )
153
+ @datasource = RailsPerformance::DataSource.new(**prepare_query(params), type: :rake)
169
154
  db = @datasource.db
170
155
  @throughput_report_data = RailsPerformance::Reports::ThroughputReport.new(db).data
171
156
  @recent_report_data = RailsPerformance::Reports::RecentRequestsReport.new(db).data
@@ -173,7 +158,7 @@ type: :requests)
173
158
 
174
159
  private
175
160
 
176
- def prepare_query(query = params)
161
+ def prepare_query(query = {})
177
162
  RailsPerformance::Rails::QueryBuilder.compose_from(query)
178
163
  end
179
164
  end
@@ -132,6 +132,8 @@ module RailsPerformance
132
132
  "is-active" if controller_name == "rails_performance" && action_name == "crashes"
133
133
  when :requests
134
134
  "is-active" if controller_name == "rails_performance" && action_name == "requests"
135
+ when :resources
136
+ "is-active" if controller_name == "rails_performance" && action_name == "resources"
135
137
  when :recent
136
138
  "is-active" if controller_name == "rails_performance" && action_name == "recent"
137
139
  when :slow
@@ -1,8 +1,5 @@
1
1
  function showTIRChart(div, data, addon, name) {
2
2
  Highcharts.chart(div, {
3
- // time: {
4
- // timezone: 'Europe/Kiev'
5
- // },
6
3
  chart: {
7
4
  type: 'area',
8
5
  zoomType: 'x',
@@ -22,7 +19,7 @@ function showTIRChart(div, data, addon, name) {
22
19
  },
23
20
  formatter: function() {
24
21
  if (this.y == 0) {
25
- return false;
22
+ return false;
26
23
  }
27
24
  return this.y + addon;
28
25
  }
@@ -84,9 +81,6 @@ function showTIRChart(div, data, addon, name) {
84
81
 
85
82
  function showRTChart(div, data) {
86
83
  Highcharts.chart(div, {
87
- // time: {
88
- // timezone: 'Europe/Kiev'
89
- // },
90
84
  chart: {
91
85
  type: 'area',
92
86
  zoomType: 'x',
@@ -167,6 +161,179 @@ function showRTChart(div, data) {
167
161
  });
168
162
  };
169
163
 
164
+ function showPercentageChart(div, data, addon, name) {
165
+ Highcharts.chart(div, {
166
+ chart: {
167
+ type: 'line',
168
+ zoomType: 'x',
169
+ },
170
+ title: {
171
+ text: ''
172
+ },
173
+ tooltip: {
174
+ borderWidth: 0,
175
+ backgroundColor: 'yellow',
176
+ pointFormat: '{point.y}',
177
+ //headerFormat: '',
178
+ shadow: false,
179
+ style: {
180
+ fontSize: '16px',
181
+ color: '#000',
182
+ },
183
+ formatter: function() {
184
+ if (this.y == 0) {
185
+ return false;
186
+ }
187
+ return this.y + ' %';
188
+ }
189
+ },
190
+ xAxis: {
191
+ crosshair: true,
192
+ type: 'datetime',
193
+ labels: {
194
+ style: {
195
+ color: "#a6b0cf"
196
+ }
197
+ }
198
+ },
199
+ yAxis: {
200
+ min: 0,
201
+ title: {
202
+ text: '%',
203
+ style: {
204
+ color: "#f6f6f6"
205
+ }
206
+ },
207
+ labels: {
208
+ style: {
209
+ color: "#a6b0cf"
210
+ }
211
+ }
212
+ },
213
+ legend: {
214
+ enabled: false
215
+ },
216
+ exporting: {
217
+ buttons: {
218
+ contextButton: {
219
+ theme: {
220
+ fill: "#eee"
221
+ }
222
+ }
223
+ }
224
+ },
225
+ plotOptions: {
226
+ area: {
227
+ color: '#ff5b5b',
228
+ }
229
+ },
230
+ series: [{
231
+ type: 'line',
232
+ name: name,
233
+ data: data,
234
+ fillOpacity: 0.3,
235
+ lineWidth: 1,
236
+ states: {
237
+ hover: {
238
+ lineWidth: 2
239
+ }
240
+ }
241
+ }]
242
+ });
243
+ };
244
+
245
+
246
+ function showUsageChart(div, data, addon, name) {
247
+ Highcharts.chart(div, {
248
+ chart: {
249
+ type: 'line',
250
+ zoomType: 'x',
251
+ },
252
+ title: {
253
+ text: ''
254
+ },
255
+ tooltip: {
256
+ borderWidth: 0,
257
+ backgroundColor: 'yellow',
258
+ pointFormat: '{point.y}',
259
+ //headerFormat: '',
260
+ shadow: false,
261
+ style: {
262
+ fontSize: '16px',
263
+ color: '#000',
264
+ },
265
+ formatter: function() {
266
+ if (this.y == 0) {
267
+ return false;
268
+ }
269
+ return bytes(this.y, true);
270
+ }
271
+ },
272
+ xAxis: {
273
+ crosshair: true,
274
+ type: 'datetime',
275
+ labels: {
276
+ style: {
277
+ color: "#a6b0cf"
278
+ }
279
+ }
280
+ },
281
+ yAxis: {
282
+ min: 0,
283
+ title: {
284
+ text: '',
285
+ style: {
286
+ color: "#f6f6f6"
287
+ }
288
+ },
289
+ labels: {
290
+ style: {
291
+ color: "#a6b0cf"
292
+ }
293
+ }
294
+ },
295
+ legend: {
296
+ enabled: false
297
+ },
298
+ exporting: {
299
+ buttons: {
300
+ contextButton: {
301
+ theme: {
302
+ fill: "#eee"
303
+ }
304
+ }
305
+ }
306
+ },
307
+ plotOptions: {
308
+ area: {
309
+ color: '#ff5b5b',
310
+ }
311
+ },
312
+ series: [{
313
+ type: 'line',
314
+ name: name,
315
+ data: data,
316
+ fillOpacity: 0.3,
317
+ lineWidth: 1,
318
+ states: {
319
+ hover: {
320
+ lineWidth: 2
321
+ }
322
+ }
323
+ }]
324
+ });
325
+ };
326
+
327
+ function bytes(bytes, label) {
328
+ if (bytes == 0) return '';
329
+ var s = ['bytes', 'KB', 'MB', 'GB', 'TB', 'PB'];
330
+ var e = Math.floor(Math.log(bytes)/Math.log(1024));
331
+ var value = ((bytes/Math.pow(1024, Math.floor(e))).toFixed(2));
332
+ e = (e<0) ? (-e) : e;
333
+ if (label) value += ' ' + s[e];
334
+ return value;
335
+ }
336
+
170
337
  const recent = document.getElementById("recent")
171
338
  const autoupdate = document.getElementById("autoupdate")
172
339
 
@@ -1,5 +1,5 @@
1
1
  <!DOCTYPE html>
2
- <html>
2
+ <html class="theme-light">
3
3
  <head>
4
4
  <meta charset="utf-8">
5
5
  <meta name="viewport" content="width=device-width, initial-scale=1">
@@ -0,0 +1,50 @@
1
+ <title>System Resources</title>
2
+
3
+ <% @resources_report.data.keys.each do |server_key| %>
4
+ <h1 class="title mt-8 pt-8"><%= server_key.split("///"). join(", ") %></h1>
5
+
6
+ <div class="card">
7
+ <div class="card-content">
8
+ <h2 class="subtitle">CPU</h2>
9
+ <div id="cpu_report_<%= server_key.parameterize %>" class="chart"></div>
10
+ <p class="content is-small">CPU usage %, average per 1 minute</p>
11
+ </div>
12
+ </div>
13
+
14
+ <br/>
15
+
16
+ <div class="card">
17
+ <div class="card-content">
18
+ <h2 class="subtitle">Memory</h2>
19
+ <div id="memory_report_<%= server_key.parameterize %>" class="chart"></div>
20
+ <p class="content is-small">App memory usage</p>
21
+ </div>
22
+ </div>
23
+
24
+ <br/>
25
+
26
+ <div class="card">
27
+ <div class="card-content">
28
+ <h2 class="subtitle">Disk</h2>
29
+ <div id="disk_report_<%= server_key.parameterize %>" class="chart"></div>
30
+ <p class="content is-small">Available disk size</p>
31
+ </div>
32
+ </div>
33
+
34
+ <br>
35
+ <% end %>
36
+
37
+ <% content_for :on_load do %>
38
+ <script>
39
+ <% @resources_report.data.keys.each do |server_key| %>
40
+ var data1 = <%= raw @resources_report.cpu[server_key].to_json %>;
41
+ showPercentageChart('cpu_report_<%= server_key.parameterize %>', data1, ' %', '%');
42
+
43
+ var data2 = <%= raw @resources_report.memory[server_key].to_json %>;
44
+ showUsageChart('memory_report_<%= server_key.parameterize %>', data2, ' Mb', 'Mb');
45
+
46
+ var data3 = <%= raw @resources_report.disk[server_key].to_json %>;
47
+ showUsageChart('disk_report_<%= server_key.parameterize %>', data3, ' Gb', 'Gb');
48
+ <% end %>
49
+ </script>
50
+ <% end %>
@@ -17,6 +17,9 @@
17
17
  <%= link_to 'Dashboard', rails_performance.rails_performance_url, class: "navbar-item #{active?(:dashboard)}" %>
18
18
  <%= link_to 'Requests Analysis', rails_performance.rails_performance_requests_url, class: "navbar-item #{active?(:requests)}" %>
19
19
  <%= link_to 'Recent Requests', rails_performance.rails_performance_recent_url, class: "navbar-item #{active?(:recent)}" %>
20
+ <% if RailsPerformance._resource_monitor_enabled %>
21
+ <%= link_to 'System', rails_performance.rails_performance_resources_url, class: "navbar-item #{active?(:resources)}" %>
22
+ <% end %>
20
23
  <%= link_to 'Slow Requests', rails_performance.rails_performance_slow_url, class: "navbar-item #{active?(:slow)}" %>
21
24
  <%= link_to '500 Errors', rails_performance.rails_performance_crashes_url, class: "navbar-item #{active?(:crashes)}" %>
22
25
  <% if defined?(Sidekiq) %>