rails_performance 1.4.1 → 1.4.3
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 +20 -11
- data/app/assets/images/details.svg +3 -0
- data/app/assets/images/external.svg +1 -0
- data/app/controllers/rails_performance/base_controller.rb +9 -0
- data/app/helpers/rails_performance/rails_performance_helper.rb +4 -0
- data/app/views/rails_performance/javascripts/app.js +1 -0
- data/app/views/rails_performance/rails_performance/_recent_row.html.erb +14 -2
- data/app/views/rails_performance/rails_performance/_summary.html.erb +9 -2
- data/app/views/rails_performance/rails_performance/crashes.html.erb +16 -2
- data/app/views/rails_performance/rails_performance/requests.html.erb +8 -1
- data/app/views/rails_performance/rails_performance/resources.html.erb +16 -43
- data/app/views/rails_performance/stylesheets/panel.css +14 -2
- data/app/views/rails_performance/stylesheets/style.css +40 -1
- data/lib/generators/rails_performance/install/templates/initializer.rb +5 -2
- data/lib/rails_performance/engine.rb +3 -3
- data/lib/rails_performance/models/resource_record.rb +3 -6
- data/lib/rails_performance/reports/resources_report.rb +22 -20
- data/lib/rails_performance/reports/slow_requests_report.rb +1 -1
- data/lib/rails_performance/system_monitor/resource_chart.rb +105 -0
- data/lib/rails_performance/{extensions → system_monitor}/resources_monitor.rb +14 -35
- data/lib/rails_performance/version.rb +1 -1
- data/lib/rails_performance.rb +10 -0
- metadata +7 -7
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 60fc2568e878c07db112623ef55985422852996f3eea18fd972c9ccc0288fd1a
|
4
|
+
data.tar.gz: 3ff0036deb507e91fd9ac1ab63cafac95e98aeb59646ca566dff403a2bcdc1d6
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 28a6b7d3918eaabb97a4cabcdbc95e66cca45dba61c416f90ed083e6508df79333a0e2c209fb3d1d1654a1516587dda5387eb88a42518a4b602cb77b4c83922e
|
7
|
+
data.tar.gz: '0179ca0fdece9492e9053820aa025d0210391957d9eee2cac714bc0e8611003b467ff8d06bf91cb27d0eb8024bc4a8d77a56410aa7879a701be0d9df59ed8ee1'
|
data/README.md
CHANGED
@@ -2,7 +2,9 @@
|
|
2
2
|
|
3
3
|
[](https://github.com/igorkasyanchuk/rails_performance/actions/workflows/ruby.yml)
|
4
4
|
[](https://www.railsjazz.com)
|
5
|
-
[
|
5
|
+
[My Cheatsheets](https://cheatsheetshero.com/user/igor-kasyanchuk)
|
6
|
+
|
7
|
+
[](https://buymeacoffee.com/igorkasyanchuk)
|
6
8
|
|
7
9
|
A self-hosted tool to monitor the performance of your Ruby on Rails application.
|
8
10
|
|
@@ -43,7 +45,7 @@ All data are stored in `local` Redis and not sent to any 3rd party servers.
|
|
43
45
|
|
44
46
|
## Production
|
45
47
|
|
46
|
-
Gem is production-ready. At least
|
48
|
+
Gem is production-ready. At least in my 2 applications with ~800 unique users per day it works perfectly.
|
47
49
|
|
48
50
|
Just don't forget to protect performance dashboard with http basic auth or check of current_user.
|
49
51
|
|
@@ -66,7 +68,7 @@ RailsPerformance.setup do |config|
|
|
66
68
|
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
|
67
69
|
config.duration = 4.hours
|
68
70
|
|
69
|
-
config.debug = false # currently not used
|
71
|
+
config.debug = false # currently not used
|
70
72
|
config.enabled = true
|
71
73
|
|
72
74
|
# configure Recent tab (time window and limit of requests)
|
@@ -170,6 +172,7 @@ After installation and configuration, start your Rails application, make a few r
|
|
170
172
|
|
171
173
|
If you, for whatever reason (company policy, devise, ...) need to mount RailsPerformance yourself, feel free to do so by using the following snippet as inspiration.
|
172
174
|
You can skip the `mount_at` and `http_basic_authentication_*` configurations then, if you like.
|
175
|
+
Under certain constraints (i.e. subdomains) it may be necessary to set `url_options` in the config so that RailsPeformance can generate links correctly.
|
173
176
|
|
174
177
|
```ruby
|
175
178
|
# config/routes.rb
|
@@ -221,10 +224,10 @@ env:
|
|
221
224
|
RAILS_PERFORMANCE_SERVER_ID: "server"
|
222
225
|
```
|
223
226
|
|
224
|
-
You can also
|
227
|
+
You can also specify custom "context" and "role" for monitoring, by changing the env variables:
|
225
228
|
|
226
229
|
```ruby
|
227
|
-
RailsPerformance::
|
230
|
+
RailsPerformance::SystemMonitor::ResourcesMonitor.new(
|
228
231
|
ENV["RAILS_PERFORMANCE_SERVER_CONTEXT"].presence || "rails",
|
229
232
|
ENV["RAILS_PERFORMANCE_SERVER_ROLE"].presence || "web"
|
230
233
|
)
|
@@ -242,7 +245,7 @@ RailsPerformance.measure("some label", "some namespace") do
|
|
242
245
|
end
|
243
246
|
```
|
244
247
|
|
245
|
-
## Using with
|
248
|
+
## Using with Redis Namespace
|
246
249
|
|
247
250
|
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:
|
248
251
|
|
@@ -321,6 +324,15 @@ The idea of this gem grew from curiosity how many RPM my app receiving per day.
|
|
321
324
|
- sinatra?
|
322
325
|
- tests to check what is actually stored in redis db after request
|
323
326
|
- upgrade bulma
|
327
|
+
- optimize svg icons, remove inline svg (switch to base64 or assets)
|
328
|
+
|
329
|
+
## Development
|
330
|
+
|
331
|
+
1. Clone the repo
|
332
|
+
2. Run `bundle install`
|
333
|
+
3. Setup dummy app `cd test/dummy && bundle install && rails db:create && rails db:migrate`
|
334
|
+
4. Run `rails s` in the root folder
|
335
|
+
5. Run `rails test` to run tests
|
324
336
|
|
325
337
|
## Contributing
|
326
338
|
|
@@ -332,14 +344,11 @@ If "schema" how records are stored i Redis is changed, and this is a breaking ch
|
|
332
344
|
|
333
345
|
https://github.com/igorkasyanchuk/rails_performance/graphs/contributors
|
334
346
|
|
335
|
-
## Other
|
336
|
-
|
337
|
-
[<img src="https://opensource-heroes.com/svg/embed/igorkasyanchuk/rails_performance"
|
338
|
-
/>](https://opensource-heroes.com/r/igorkasyanchuk/rails_performance)
|
339
|
-
|
340
347
|
## License
|
341
348
|
|
342
349
|
The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
|
343
350
|
|
344
351
|
[<img src="https://github.com/igorkasyanchuk/rails_time_travel/blob/main/docs/more_gems.png?raw=true"
|
345
352
|
/>](https://www.railsjazz.com/?utm_source=github&utm_medium=bottom&utm_campaign=rails_performance)
|
353
|
+
|
354
|
+
[](https://buymeacoffee.com/igorkasyanchuk)
|
@@ -0,0 +1,3 @@
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="size-6">
|
2
|
+
<path stroke-linecap="round" stroke-linejoin="round" d="m21 21-5.197-5.197m0 0A7.5 7.5 0 1 0 5.196 5.196a7.5 7.5 0 0 0 10.607 10.607ZM10.5 7.5v6m3-3h-6" />
|
3
|
+
</svg>
|
@@ -0,0 +1 @@
|
|
1
|
+
<?xml version="1.0"?><svg viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><g><path d="M0 0h24v24H0z" fill="none"/><path d="M10 6v2H5v11h11v-5h2v6a1 1 0 0 1-1 1H4a1 1 0 0 1-1-1V7a1 1 0 0 1 1-1h6zm11-3v8h-2V6.413l-7.793 7.794-1.414-1.414L17.585 5H13V3h8z"/></g></svg>
|
@@ -4,6 +4,7 @@ module RailsPerformance
|
|
4
4
|
layout "rails_performance/layouts/rails_performance"
|
5
5
|
|
6
6
|
before_action :verify_access
|
7
|
+
after_action :set_permissive_csp
|
7
8
|
|
8
9
|
if RailsPerformance.http_basic_authentication_enabled
|
9
10
|
http_basic_authenticate_with \
|
@@ -11,11 +12,19 @@ module RailsPerformance
|
|
11
12
|
password: RailsPerformance.http_basic_authentication_password
|
12
13
|
end
|
13
14
|
|
15
|
+
def url_options
|
16
|
+
RailsPerformance.url_options.nil? ? super : RailsPerformance.url_options
|
17
|
+
end
|
18
|
+
|
14
19
|
private
|
15
20
|
|
16
21
|
def verify_access
|
17
22
|
result = RailsPerformance.verify_access_proc.call(self)
|
18
23
|
redirect_to("/", error: "Access Denied", status: 401) unless result
|
19
24
|
end
|
25
|
+
|
26
|
+
def set_permissive_csp
|
27
|
+
response.headers["Content-Security-Policy"] = "default-src 'self' https:; script-src 'self' 'unsafe-inline' 'unsafe-eval' https:; style-src 'self' 'unsafe-inline' https:"
|
28
|
+
end
|
20
29
|
end
|
21
30
|
end
|
@@ -9,12 +9,24 @@
|
|
9
9
|
<td><%= format_datetime e[:datetime] %></td>
|
10
10
|
<td>
|
11
11
|
<% controller_action_info = e[:controller] + '#' + e[:action]%>
|
12
|
-
<%= link_to
|
12
|
+
<%= link_to rails_performance.rails_performance_summary_path({controller_eq: e[:controller], action_eq: e[:action]}), remote: true, title: controller_action_info do %>
|
13
|
+
<span class="details_icon">
|
14
|
+
<%= icon 'details' %>
|
15
|
+
</span>
|
16
|
+
<%= truncate(controller_action_info, length: 40) %>
|
17
|
+
<% end %>
|
13
18
|
</td>
|
14
19
|
<td><%= e[:method] %></td>
|
15
20
|
<td><%= e[:format] %></td>
|
16
21
|
<td><%= bot_icon e["user_agent"] %></td>
|
17
|
-
<td
|
22
|
+
<td>
|
23
|
+
<span class="with_external_icon">
|
24
|
+
<%= link_to_path(e) %>
|
25
|
+
<span class="icon external_icon">
|
26
|
+
<%= icon('external') %>
|
27
|
+
</span>
|
28
|
+
</span>
|
29
|
+
</td>
|
18
30
|
<td><%= status_tag e[:status] %></td>
|
19
31
|
<td class="nowrap"><%= ms e[:duration] %></td>
|
20
32
|
<td class="nowrap"><%= ms e[:view_runtime] %></td>
|
@@ -5,7 +5,7 @@
|
|
5
5
|
<div id="response_time_report_chart_mini" class="chart_mini"></div>
|
6
6
|
|
7
7
|
<h2 class="subtitle"><%= title %></h2>
|
8
|
-
<table class="table is-fullwidth is-hoverable is-narrow is-size-
|
8
|
+
<table class="table is-fullwidth is-hoverable is-narrow is-size-8">
|
9
9
|
<thead>
|
10
10
|
<tr>
|
11
11
|
<th data-sort="string">Datetime</th>
|
@@ -25,7 +25,14 @@
|
|
25
25
|
<td><%= format_datetime e[:datetime] %></td>
|
26
26
|
<td><%= e[:method] %></td>
|
27
27
|
<td><%= bot_icon e["user_agent"] %></td>
|
28
|
-
<td
|
28
|
+
<td>
|
29
|
+
<span class="with_external_icon">
|
30
|
+
<%= link_to_path(e) %>
|
31
|
+
<span class="icon external_icon">
|
32
|
+
<%= icon('external') %>
|
33
|
+
</span>
|
34
|
+
</span>
|
35
|
+
</td>
|
29
36
|
<td><%= e[:format] %></td>
|
30
37
|
<td><%= status_tag e[:status] %></td>
|
31
38
|
<td class="nowrap"><%= ms e[:duration] %></td>
|
@@ -35,11 +35,25 @@
|
|
35
35
|
<% @data.each do |e| %>
|
36
36
|
<tr>
|
37
37
|
<td><%= format_datetime e[:datetime] %></td>
|
38
|
-
<td
|
38
|
+
<td>
|
39
|
+
<%= link_to rails_performance.rails_performance_summary_path({controller_eq: e[:controller], action_eq: e[:action]}), remote: true do %>
|
40
|
+
<span class="details_icon">
|
41
|
+
<%= icon 'details' %>
|
42
|
+
</span>
|
43
|
+
<%= e[:controller] + '#' + e[:action] %>
|
44
|
+
<% end %>
|
45
|
+
</td>
|
39
46
|
<td><%= e[:method] %></td>
|
40
47
|
<td><%= e[:format] %></td>
|
41
48
|
<td><%= bot_icon e["user_agent"] %></td>
|
42
|
-
<td
|
49
|
+
<td>
|
50
|
+
<span class="with_external_icon">
|
51
|
+
<%= link_to_path(e) %>
|
52
|
+
<span class="icon external_icon">
|
53
|
+
<%= icon('external') %>
|
54
|
+
</span>
|
55
|
+
</span>
|
56
|
+
</td>
|
43
57
|
<td><%= e[:exception] %></td>
|
44
58
|
<td class="very-small-text">
|
45
59
|
<%= raw e[:backtrace]&.join("<br/>") %>
|
@@ -36,7 +36,14 @@
|
|
36
36
|
<% groups = e[:group].split("|") %>
|
37
37
|
<% c, a = groups[0].split("#") %>
|
38
38
|
<tr>
|
39
|
-
<td
|
39
|
+
<td>
|
40
|
+
<%= link_to rails_performance.rails_performance_summary_path({controller_eq: c, action_eq: a}), remote: true do %>
|
41
|
+
<span class="details_icon">
|
42
|
+
<%= icon 'details' %>
|
43
|
+
</span>
|
44
|
+
<%= groups[0] %>
|
45
|
+
<% end %>
|
46
|
+
</td>
|
40
47
|
<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>
|
41
48
|
<td><%= e[:count] %></td>
|
42
49
|
<td class="nowrap attention"><%= ms e[:p50_duration] %></td>
|
@@ -1,50 +1,23 @@
|
|
1
1
|
<title>System Resources</title>
|
2
2
|
|
3
|
-
<% @resources_report.
|
4
|
-
<h1 class="title mt-8 pt-8"><%=
|
5
|
-
|
6
|
-
|
7
|
-
<div class="card
|
8
|
-
<
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
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">Storage</h2>
|
29
|
-
<div id="disk_report_<%= server_key.parameterize %>" class="chart"></div>
|
30
|
-
<p class="content is-small">Available storage size (local disk size)</p>
|
3
|
+
<% @resources_report.servers.each do |server| %>
|
4
|
+
<h1 class="title mt-8 pt-8"><%= server.name %></h1>
|
5
|
+
|
6
|
+
<% server.charts.each.with_index do |chart, index| %>
|
7
|
+
<div class="card">
|
8
|
+
<div class="card-content">
|
9
|
+
<h2 class="subtitle"><%= chart.subtitle %></h2>
|
10
|
+
<div class="chart" id="<%= chart.id %>"></div>
|
11
|
+
<p class="content is-small"><%= chart.description %></p>
|
12
|
+
</div>
|
31
13
|
</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, 'CPU');
|
42
14
|
|
43
|
-
|
44
|
-
showUsageChart('memory_report_<%= server_key.parameterize %>', data2, 'Usage', 2);
|
15
|
+
<br/>
|
45
16
|
|
46
|
-
|
47
|
-
|
17
|
+
<% content_for :on_load do %>
|
18
|
+
<script>
|
19
|
+
show<%= chart.type %>Chart('<%= chart.id %>', <%= raw chart.data.to_json %>, '<%= chart.legend %>', <%= index %>);
|
20
|
+
</script>
|
48
21
|
<% end %>
|
49
|
-
|
22
|
+
<% end %>
|
50
23
|
<% end %>
|
@@ -32,13 +32,25 @@
|
|
32
32
|
.cd-panel__container {
|
33
33
|
z-index: 100;
|
34
34
|
position: fixed;
|
35
|
-
width:
|
35
|
+
width: 1200px;
|
36
36
|
height: 100%;
|
37
37
|
top: 0;
|
38
38
|
transition: transform 0.3s 0s;
|
39
39
|
overflow: scroll;
|
40
40
|
}
|
41
41
|
|
42
|
+
@media (max-width: 1200px) {
|
43
|
+
.cd-panel__container {
|
44
|
+
width: 800px;
|
45
|
+
}
|
46
|
+
}
|
47
|
+
|
48
|
+
@media (max-width: 768px) {
|
49
|
+
.cd-panel__container {
|
50
|
+
width: 500px;
|
51
|
+
}
|
52
|
+
}
|
53
|
+
|
42
54
|
.cd-panel--from-right .cd-panel__container {
|
43
55
|
right: 0;
|
44
56
|
transform: translate3d(100%, 0, 0);
|
@@ -57,4 +69,4 @@
|
|
57
69
|
.cd-panel__container .panel {
|
58
70
|
background: white;
|
59
71
|
min-height: 100vh;
|
60
|
-
}
|
72
|
+
}
|
@@ -62,6 +62,33 @@
|
|
62
62
|
color: red;
|
63
63
|
}
|
64
64
|
|
65
|
+
.external_icon svg {
|
66
|
+
width: 12px;
|
67
|
+
height: 12px;
|
68
|
+
color: #eee;
|
69
|
+
margin-left: -4px;
|
70
|
+
opacity: 0;
|
71
|
+
}
|
72
|
+
|
73
|
+
.details_icon {
|
74
|
+
position: relative;
|
75
|
+
width: 14px;
|
76
|
+
height: 14px;
|
77
|
+
}
|
78
|
+
|
79
|
+
.details_icon svg {
|
80
|
+
position: relative;
|
81
|
+
top: 2px;
|
82
|
+
width: 14px;
|
83
|
+
height: 14px;
|
84
|
+
}
|
85
|
+
|
86
|
+
.with_external_icon:hover {
|
87
|
+
.external_icon svg {
|
88
|
+
opacity: 1;
|
89
|
+
}
|
90
|
+
}
|
91
|
+
|
65
92
|
.user-agent-icon svg {
|
66
93
|
width: 12px;
|
67
94
|
height: 12px;
|
@@ -77,7 +104,19 @@
|
|
77
104
|
|
78
105
|
.chart_mini {
|
79
106
|
height: 200px;
|
80
|
-
width:
|
107
|
+
width: 1160px;
|
108
|
+
}
|
109
|
+
|
110
|
+
@media (max-width: 1200px) {
|
111
|
+
.chart_mini {
|
112
|
+
width: 770px;
|
113
|
+
}
|
114
|
+
}
|
115
|
+
|
116
|
+
@media (max-width: 768px) {
|
117
|
+
.chart_mini {
|
118
|
+
width: 400px;
|
119
|
+
}
|
81
120
|
}
|
82
121
|
|
83
122
|
.red {
|
@@ -8,11 +8,11 @@ if defined?(RailsPerformance)
|
|
8
8
|
|
9
9
|
# Recent Requests configuration
|
10
10
|
config.recent_requests_time_window = 60.minutes
|
11
|
-
#
|
11
|
+
# config.recent_requests_limit = nil # number of recent requests
|
12
12
|
|
13
13
|
# Slow Requests configuration
|
14
14
|
config.slow_requests_time_window = 4.hours
|
15
|
-
# config.slow_requests_limit = 500 #
|
15
|
+
# config.slow_requests_limit = 500 # number of slow requests
|
16
16
|
config.slow_requests_threshold = 500 # ms
|
17
17
|
|
18
18
|
config.debug = false # currently not used>
|
@@ -31,6 +31,9 @@ if defined?(RailsPerformance)
|
|
31
31
|
# for example when you have `current_user`
|
32
32
|
# config.verify_access_proc = proc { |controller| controller.current_user && controller.current_user.admin? }
|
33
33
|
|
34
|
+
# Override engine url options, necessary if hosting under a unique domain
|
35
|
+
# config.url_options = {host: "sub.example.com"}
|
36
|
+
|
34
37
|
# You can ignore endpoints with Rails standard notation controller#action
|
35
38
|
# config.ignored_endpoints = ['HomeController#contact']
|
36
39
|
|
@@ -2,7 +2,7 @@ require "action_view/log_subscriber"
|
|
2
2
|
require_relative "rails/middleware"
|
3
3
|
require_relative "models/collection"
|
4
4
|
require_relative "instrument/metrics_collector"
|
5
|
-
require_relative "
|
5
|
+
require_relative "system_monitor/resources_monitor"
|
6
6
|
|
7
7
|
module RailsPerformance
|
8
8
|
class Engine < ::Rails::Engine
|
@@ -16,7 +16,7 @@ module RailsPerformance
|
|
16
16
|
next if $rails_performance_running_mode == :console # rubocop:disable Style/GlobalVars
|
17
17
|
|
18
18
|
# start monitoring
|
19
|
-
RailsPerformance._resource_monitor = RailsPerformance::
|
19
|
+
RailsPerformance._resource_monitor = RailsPerformance::SystemMonitor::ResourcesMonitor.new(
|
20
20
|
ENV["RAILS_PERFORMANCE_SERVER_CONTEXT"].presence || "rails",
|
21
21
|
ENV["RAILS_PERFORMANCE_SERVER_ROLE"].presence || "web"
|
22
22
|
)
|
@@ -44,7 +44,7 @@ module RailsPerformance
|
|
44
44
|
RailsPerformance._resource_monitor.stop_monitoring
|
45
45
|
RailsPerformance._resource_monitor = nil
|
46
46
|
# start background monitoring
|
47
|
-
RailsPerformance._resource_monitor = RailsPerformance::
|
47
|
+
RailsPerformance._resource_monitor = RailsPerformance::SystemMonitor::ResourcesMonitor.new(
|
48
48
|
ENV["RAILS_PERFORMANCE_SERVER_CONTEXT"].presence || "sidekiq",
|
49
49
|
ENV["RAILS_PERFORMANCE_SERVER_ROLE"].presence || "background"
|
50
50
|
)
|
@@ -26,16 +26,13 @@ module RailsPerformance
|
|
26
26
|
end
|
27
27
|
|
28
28
|
def record_hash
|
29
|
-
{
|
29
|
+
value.symbolize_keys.merge({
|
30
30
|
server: server,
|
31
31
|
role: role,
|
32
32
|
context: context,
|
33
33
|
datetime: datetime,
|
34
|
-
datetimei: RailsPerformance::Utils.from_datetimei(datetimei.to_i)
|
35
|
-
|
36
|
-
memory: value["memory"],
|
37
|
-
disk: value["disk"]
|
38
|
-
}
|
34
|
+
datetimei: RailsPerformance::Utils.from_datetimei(datetimei.to_i)
|
35
|
+
})
|
39
36
|
end
|
40
37
|
|
41
38
|
def save
|
@@ -1,40 +1,42 @@
|
|
1
1
|
module RailsPerformance
|
2
2
|
module Reports
|
3
3
|
class ResourcesReport < BaseReport
|
4
|
-
|
5
|
-
|
6
|
-
.
|
7
|
-
|
8
|
-
# .transform_values { |v| v.sort { |a, b| b[sort] <=> a[sort] } }
|
9
|
-
.transform_values { |v| v.map { |e| e.merge({datetimei: e[:datetimei].to_i}) } }
|
10
|
-
end
|
4
|
+
Server = Struct.new(:report, :key) do
|
5
|
+
def name
|
6
|
+
key.split("///").join(", ")
|
7
|
+
end
|
11
8
|
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
end)
|
9
|
+
def charts
|
10
|
+
RailsPerformance.system_monitors.map do |class_name|
|
11
|
+
SystemMonitor.const_get(class_name).new(self)
|
12
|
+
end
|
17
13
|
end
|
18
14
|
end
|
19
15
|
|
20
|
-
def
|
21
|
-
|
22
|
-
|
23
|
-
res[e[:datetimei] * 1000] = e[:memory].to_f.round(2)
|
24
|
-
end)
|
16
|
+
def servers
|
17
|
+
data.keys.map do |key|
|
18
|
+
Server.new(self, key)
|
25
19
|
end
|
26
20
|
end
|
27
21
|
|
28
|
-
def
|
29
|
-
|
22
|
+
def extract_signal &block
|
23
|
+
data.transform_values do |v|
|
30
24
|
prepare_report(v.each_with_object({}) do |e, res|
|
31
|
-
res[e[:datetimei] * 1000] =
|
25
|
+
res[e[:datetimei] * 1000] = block.call(e)
|
32
26
|
end)
|
33
27
|
end
|
34
28
|
end
|
35
29
|
|
36
30
|
private
|
37
31
|
|
32
|
+
def data
|
33
|
+
@data ||= db.data
|
34
|
+
.collect { |e| e.record_hash }
|
35
|
+
.group_by { |e| e[:server] + "///" + e[:context] + "///" + e[:role] }
|
36
|
+
# .transform_values { |v| v.sort { |a, b| b[sort] <=> a[sort] } }
|
37
|
+
.transform_values { |v| v.map { |e| e.merge({datetimei: e[:datetimei].to_i}) } }
|
38
|
+
end
|
39
|
+
|
38
40
|
def prepare_report(input)
|
39
41
|
nullify_data(input, RailsPerformance.system_monitor_duration)
|
40
42
|
end
|
@@ -10,7 +10,7 @@ module RailsPerformance
|
|
10
10
|
.collect { |e| e.record_hash }
|
11
11
|
.select { |e| e if e[sort] > RailsPerformance.slow_requests_time_window.ago.to_i }
|
12
12
|
.sort { |a, b| b[sort] <=> a[sort] }
|
13
|
-
.filter { |e| e[:duration] > RailsPerformance.slow_requests_threshold.to_i }
|
13
|
+
.filter { |e| e[:duration].to_f > RailsPerformance.slow_requests_threshold.to_i }
|
14
14
|
.first(limit)
|
15
15
|
end
|
16
16
|
|
@@ -0,0 +1,105 @@
|
|
1
|
+
module RailsPerformance
|
2
|
+
module SystemMonitor
|
3
|
+
ResourceChart = Struct.new(:server, :key, :type, :subtitle, :description, :legend, keyword_init: true) do
|
4
|
+
def id
|
5
|
+
[key, "report", server.key.parameterize].join("_")
|
6
|
+
end
|
7
|
+
|
8
|
+
def data
|
9
|
+
all_data = server.report.extract_signal { |e| signal(e) }
|
10
|
+
all_data[server.key]
|
11
|
+
end
|
12
|
+
|
13
|
+
def signal e
|
14
|
+
format(e[key])
|
15
|
+
end
|
16
|
+
|
17
|
+
def format measurement
|
18
|
+
measurement
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
class CPULoad < ResourceChart
|
23
|
+
def initialize server
|
24
|
+
super(
|
25
|
+
server:,
|
26
|
+
key: :cpu,
|
27
|
+
type: "Percentage",
|
28
|
+
subtitle: "CPU",
|
29
|
+
description: "CPU load average (1 min), average per 1 minute",
|
30
|
+
legend: "CPU",
|
31
|
+
)
|
32
|
+
end
|
33
|
+
|
34
|
+
def format measurement
|
35
|
+
measurement["one_min"].to_f.round(2)
|
36
|
+
end
|
37
|
+
|
38
|
+
def measure
|
39
|
+
load_averages = Sys::CPU.load_avg
|
40
|
+
{
|
41
|
+
one_min: load_averages[0],
|
42
|
+
five_min: load_averages[1],
|
43
|
+
fifteen_min: load_averages[2]
|
44
|
+
}
|
45
|
+
rescue => e
|
46
|
+
::Rails.logger.error "Error fetching CPU usage: #{e.message}"
|
47
|
+
{one_min: 0.0, five_min: 0.0, fifteen_min: 0.0}
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
class MemoryUsage < ResourceChart
|
52
|
+
def initialize server
|
53
|
+
super(
|
54
|
+
server:,
|
55
|
+
key: :memory,
|
56
|
+
type: "Usage",
|
57
|
+
subtitle: "Memory",
|
58
|
+
description: "App memory usage",
|
59
|
+
legend: "Usage",
|
60
|
+
)
|
61
|
+
end
|
62
|
+
|
63
|
+
def format measurement
|
64
|
+
measurement.to_f.round(2)
|
65
|
+
end
|
66
|
+
|
67
|
+
def measure
|
68
|
+
GetProcessMem.new.bytes
|
69
|
+
rescue => e
|
70
|
+
::Rails.logger.error "Error fetching memory usage: #{e.message}"
|
71
|
+
0
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
class DiskUsage < ResourceChart
|
76
|
+
def initialize server
|
77
|
+
super(
|
78
|
+
server:,
|
79
|
+
key: :disk,
|
80
|
+
type: "Usage",
|
81
|
+
subtitle: "Storage",
|
82
|
+
description: "Available storage size (local disk size)",
|
83
|
+
legend: "Usage",
|
84
|
+
)
|
85
|
+
end
|
86
|
+
|
87
|
+
def signal measurement
|
88
|
+
measurement["available"].to_f.round(2)
|
89
|
+
end
|
90
|
+
|
91
|
+
def measure
|
92
|
+
path = "/"
|
93
|
+
stat = Sys::Filesystem.stat(path)
|
94
|
+
{
|
95
|
+
available: stat.blocks_available * stat.block_size,
|
96
|
+
total: stat.blocks * stat.block_size,
|
97
|
+
used: (stat.blocks - stat.blocks_available) * stat.block_size
|
98
|
+
}
|
99
|
+
rescue => e
|
100
|
+
::Rails.logger.error "Error fetching disk space: #{e.message}"
|
101
|
+
{available: 0, total: 0, used: 0}
|
102
|
+
end
|
103
|
+
end
|
104
|
+
end
|
105
|
+
end
|
@@ -1,6 +1,8 @@
|
|
1
|
+
require "rails_performance/system_monitor/resource_chart"
|
2
|
+
|
1
3
|
module RailsPerformance
|
2
|
-
module
|
3
|
-
class
|
4
|
+
module SystemMonitor
|
5
|
+
class ResourcesMonitor
|
4
6
|
attr_reader :context, :role
|
5
7
|
|
6
8
|
def initialize(context, role)
|
@@ -39,43 +41,20 @@ module RailsPerformance
|
|
39
41
|
end
|
40
42
|
end
|
41
43
|
|
42
|
-
def
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
store_data({cpu:, memory:, disk:})
|
48
|
-
end
|
49
|
-
|
50
|
-
def fetch_process_cpu_usage
|
51
|
-
load_averages = Sys::CPU.load_avg
|
52
|
-
{
|
53
|
-
one_min: load_averages[0],
|
54
|
-
five_min: load_averages[1],
|
55
|
-
fifteen_min: load_averages[2]
|
56
|
-
}
|
57
|
-
rescue => e
|
58
|
-
::Rails.logger.error "Error fetching CPU usage: #{e.message}"
|
59
|
-
{one_min: 0.0, five_min: 0.0, fifteen_min: 0.0}
|
44
|
+
def payload
|
45
|
+
monitors.reduce({}) do |data, monitor|
|
46
|
+
data.merge(monitor.key => monitor.measure)
|
47
|
+
end
|
60
48
|
end
|
61
49
|
|
62
|
-
def
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
0
|
50
|
+
def monitors
|
51
|
+
@monitors ||= RailsPerformance.system_monitors.map do |class_name|
|
52
|
+
RailsPerformance::SystemMonitor.const_get(class_name).new(nil)
|
53
|
+
end
|
67
54
|
end
|
68
55
|
|
69
|
-
def
|
70
|
-
|
71
|
-
{
|
72
|
-
available: stat.blocks_available * stat.block_size,
|
73
|
-
total: stat.blocks * stat.block_size,
|
74
|
-
used: (stat.blocks - stat.blocks_available) * stat.block_size
|
75
|
-
}
|
76
|
-
rescue => e
|
77
|
-
::Rails.logger.error "Error fetching disk space: #{e.message}"
|
78
|
-
{available: 0, total: 0, used: 0}
|
56
|
+
def run
|
57
|
+
store_data(payload)
|
79
58
|
end
|
80
59
|
|
81
60
|
def store_data(data)
|
data/lib/rails_performance.rb
CHANGED
@@ -119,10 +119,20 @@ module RailsPerformance
|
|
119
119
|
mattr_accessor :ignore_trace_headers
|
120
120
|
@@ignore_trace_headers = ["datetimei"]
|
121
121
|
|
122
|
+
mattr_accessor :url_options
|
123
|
+
@@url_options = nil
|
124
|
+
|
122
125
|
# System monitor duration (expiration time)
|
123
126
|
mattr_accessor :system_monitor_duration
|
124
127
|
@@system_monitor_duration = 24.hours
|
125
128
|
|
129
|
+
mattr_accessor :system_monitors
|
130
|
+
@@system_monitors = [
|
131
|
+
"CPULoad",
|
132
|
+
"MemoryUsage",
|
133
|
+
"DiskUsage"
|
134
|
+
]
|
135
|
+
|
126
136
|
# -- internal usage --
|
127
137
|
#
|
128
138
|
#
|
metadata
CHANGED
@@ -1,14 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: rails_performance
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.4.
|
4
|
+
version: 1.4.3
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Igor Kasyanchuk
|
8
|
-
autorequire:
|
9
8
|
bindir: bin
|
10
9
|
cert_chain: []
|
11
|
-
date:
|
10
|
+
date: 1980-01-02 00:00:00.000000000 Z
|
12
11
|
dependencies:
|
13
12
|
- !ruby/object:Gem::Dependency
|
14
13
|
name: railties
|
@@ -291,8 +290,10 @@ files:
|
|
291
290
|
- app/assets/images/activity.svg
|
292
291
|
- app/assets/images/bot.svg
|
293
292
|
- app/assets/images/close.svg
|
293
|
+
- app/assets/images/details.svg
|
294
294
|
- app/assets/images/download.svg
|
295
295
|
- app/assets/images/export.svg
|
296
|
+
- app/assets/images/external.svg
|
296
297
|
- app/assets/images/git.svg
|
297
298
|
- app/assets/images/github.svg
|
298
299
|
- app/assets/images/home.svg
|
@@ -346,7 +347,6 @@ files:
|
|
346
347
|
- lib/rails_performance.rb
|
347
348
|
- lib/rails_performance/data_source.rb
|
348
349
|
- lib/rails_performance/engine.rb
|
349
|
-
- lib/rails_performance/extensions/resources_monitor.rb
|
350
350
|
- lib/rails_performance/extensions/trace.rb
|
351
351
|
- lib/rails_performance/gems/custom_ext.rb
|
352
352
|
- lib/rails_performance/gems/delayed_job_ext.rb
|
@@ -377,6 +377,8 @@ files:
|
|
377
377
|
- lib/rails_performance/reports/slow_requests_report.rb
|
378
378
|
- lib/rails_performance/reports/throughput_report.rb
|
379
379
|
- lib/rails_performance/reports/trace_report.rb
|
380
|
+
- lib/rails_performance/system_monitor/resource_chart.rb
|
381
|
+
- lib/rails_performance/system_monitor/resources_monitor.rb
|
380
382
|
- lib/rails_performance/thread/current_request.rb
|
381
383
|
- lib/rails_performance/utils.rb
|
382
384
|
- lib/rails_performance/version.rb
|
@@ -384,7 +386,6 @@ homepage: https://github.com/igorkasyanchuk/rails_performance
|
|
384
386
|
licenses:
|
385
387
|
- MIT
|
386
388
|
metadata: {}
|
387
|
-
post_install_message:
|
388
389
|
rdoc_options: []
|
389
390
|
require_paths:
|
390
391
|
- lib
|
@@ -399,8 +400,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
399
400
|
- !ruby/object:Gem::Version
|
400
401
|
version: '0'
|
401
402
|
requirements: []
|
402
|
-
rubygems_version: 3.
|
403
|
-
signing_key:
|
403
|
+
rubygems_version: 3.6.9
|
404
404
|
specification_version: 4
|
405
405
|
summary: Simple Rails Performance tracker. Alternative to the NewRelic, Datadog or
|
406
406
|
other services.
|