rails_performance 1.3.2 → 1.4.0.alpha1

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 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) %>