rails_performance 0.0.1.19 → 0.9.0
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 +15 -19
- data/app/controllers/rails_performance_controller.rb +1 -0
- data/app/helpers/rails_performance_helper.rb +27 -2
- data/app/views/rails_performance/_trace.html.erb +7 -4
- data/app/views/rails_performance/crashes.html.erb +6 -0
- data/app/views/rails_performance/recent.html.erb +6 -1
- data/app/views/rails_performance/trace.js.erb +6 -1
- data/lib/rails_performance/engine.rb +5 -1
- data/lib/rails_performance/instrument/metrics_collector.rb +3 -1
- data/lib/rails_performance/models/current_request.rb +2 -0
- data/lib/rails_performance/models/record.rb +35 -0
- data/lib/rails_performance/rails/middleware.rb +14 -3
- data/lib/rails_performance/utils.rb +1 -1
- data/lib/rails_performance/version.rb +2 -2
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: fe073c7658af65303c6efc61dbaa973edba22d21c2991e715d523b6f4c96dc5f
|
4
|
+
data.tar.gz: bf7780ef55eab59d2974b990eba4e2afad26b78683f685fb8383b4df4d8ada30
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: b223eb60dc1dc48c64a577d39d2bf34073ff916d0b73ad5f507a74bedc0f9a2aa5af5cc33ec9bc063b12cc441a572f99d4e8c68362935f74f2f9084c6d8b6ca0
|
7
|
+
data.tar.gz: 7b030743ca075f02c38b4448ec0c1ad369a09d094dc381aba5c834c40ee245ccfe9511c939fa7d08e0e42d253c9b06817d4b6bc7d80c6b9d5f8bab7835472e7e
|
data/README.md
CHANGED
@@ -6,11 +6,12 @@ This is **simple and free alternative** to New Relic, Datadog or other similar s
|
|
6
6
|
|
7
7
|
It allows you to track:
|
8
8
|
|
9
|
-
- throughput report (see amount of requests per minute)
|
9
|
+
- throughput report (see amount of RPM (requests per minute))
|
10
10
|
- an average response time
|
11
11
|
- the slowest controllers & actions
|
12
|
-
- duration of
|
13
|
-
-
|
12
|
+
- total duration of time spent per request, views rendering, DB
|
13
|
+
- SQL queries, rendering log in recent requests
|
14
|
+
- simple 500-crashes reports
|
14
15
|
|
15
16
|
All data is stored in local Redis and not sent to 3rd party servers.
|
16
17
|
|
@@ -83,6 +84,8 @@ Like a regular web development.
|
|
83
84
|
|
84
85
|
Please note that to simplify integration with other apps all CSS/JS are bundled inside, and delivered in body of the request. This is to avoid integration with assets pipeline or webpacker.
|
85
86
|
|
87
|
+
For UI changes you need to use Bulma CSS (https://bulma.io/documentation).
|
88
|
+
|
86
89
|
## Why
|
87
90
|
|
88
91
|
The idea of this gem grew from curriosity how many RPM my app receiving per day. Later it evolutionated to something more powerful.
|
@@ -91,27 +94,20 @@ The idea of this gem grew from curriosity how many RPM my app receiving per day.
|
|
91
94
|
|
92
95
|
- documentation in Readme
|
93
96
|
- generator for initial config
|
94
|
-
- gif with demo
|
95
|
-
- time/zone config?
|
96
97
|
- CI for tests
|
97
|
-
-
|
98
|
-
-
|
99
|
-
-
|
98
|
+
- time/zone config?
|
99
|
+
- connected charts on dashboard, when zoom, when hover?
|
100
|
+
- ability to zoom to see requests withing specific datetime range
|
101
|
+
- better hints?
|
100
102
|
- export to csv
|
101
|
-
- http basic auth config
|
102
|
-
- current_user auth config
|
103
103
|
- better stats tooltip, do not show if nothing to show
|
104
|
-
- dark mode toggle? save to the cookies
|
105
|
-
- integration with elastic search
|
104
|
+
- dark mode toggle? save to the cookies?
|
105
|
+
- integration with elastic search? or other?
|
106
106
|
- monitor active job (sidekiq)?
|
107
|
-
- logo?
|
107
|
+
- better logo?
|
108
108
|
- number of requests last 24 hours, hour, etc.
|
109
|
-
-
|
110
|
-
-
|
111
|
-
- capture referal for 404 page?
|
112
|
-
- SQL
|
113
|
-
- Rendering
|
114
|
-
- scroll to the top details
|
109
|
+
- collect deprecation.rails
|
110
|
+
- fix misspellings?
|
115
111
|
|
116
112
|
## Contributing
|
117
113
|
|
@@ -6,6 +6,29 @@ module RailsPerformanceHelper
|
|
6
6
|
value.nan? ? nil : value.round(1)
|
7
7
|
end
|
8
8
|
|
9
|
+
def duraction_alert_class(duration_str)
|
10
|
+
if duration_str.to_s =~ /(\d+.?\d+?)/
|
11
|
+
duration = $1.to_f
|
12
|
+
if duration >= 100
|
13
|
+
'has-background-danger has-text-white-bis'
|
14
|
+
elsif duration >= 200
|
15
|
+
'has-background-warning has-text-black-ter'
|
16
|
+
else
|
17
|
+
'has-background-success has-text-white-bis'
|
18
|
+
end
|
19
|
+
else
|
20
|
+
'has-background-light'
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
def extract_duration(str)
|
25
|
+
if (str =~ /Duration: (\d+.?\d+?ms)/i)
|
26
|
+
$1
|
27
|
+
else
|
28
|
+
'-'
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
9
32
|
def ms(value)
|
10
33
|
result = round_it(value)
|
11
34
|
result && result != 0 ? "#{result} ms" : '-'
|
@@ -27,14 +50,16 @@ module RailsPerformanceHelper
|
|
27
50
|
|
28
51
|
def report_name(h)
|
29
52
|
h.except(:on).collect do |k, v|
|
53
|
+
next if v.blank?
|
54
|
+
|
30
55
|
%Q{
|
31
56
|
<div class="control">
|
32
57
|
<span class="tags has-addons">
|
33
58
|
<span class="tag">#{k}</span>
|
34
|
-
<span class="tag is-
|
59
|
+
<span class="tag is-info is-light">#{v}</span>
|
35
60
|
</span>
|
36
61
|
</div>}
|
37
|
-
end.join.html_safe
|
62
|
+
end.compact.join.html_safe
|
38
63
|
end
|
39
64
|
|
40
65
|
def status_tag(status)
|
@@ -2,16 +2,17 @@
|
|
2
2
|
<tbody>
|
3
3
|
<% @data.each do |e| %>
|
4
4
|
<tr>
|
5
|
-
<td><%= e["group"] %></td>
|
6
5
|
<% if e["group"] == 'db' %>
|
7
|
-
<td class="nowrap">
|
6
|
+
<td class="nowrap has-text-right <%= duraction_alert_class(e['duration']) %>">
|
8
7
|
<%= e["duration"] %> ms
|
9
8
|
</td>
|
10
9
|
<td>
|
11
10
|
<%= e["sql"] %>
|
12
11
|
</td>
|
13
12
|
<% elsif e["group"] == 'view' %>
|
14
|
-
<td
|
13
|
+
<td class="nowrap has-text-right <%= duraction_alert_class(extract_duration(e['message'])) %>">
|
14
|
+
<%= extract_duration(e["message"]) %>
|
15
|
+
</td>
|
15
16
|
<td>
|
16
17
|
<%= e["message"] %>
|
17
18
|
</td>
|
@@ -19,4 +20,6 @@
|
|
19
20
|
</tr>
|
20
21
|
<% end %>
|
21
22
|
</tbody>
|
22
|
-
</table>
|
23
|
+
</table>
|
24
|
+
|
25
|
+
<br/>
|
@@ -1,7 +1,7 @@
|
|
1
1
|
<div class="card">
|
2
2
|
<div class="card-content">
|
3
3
|
|
4
|
-
<h2 class="subtitle">Recent Requests (last <%= RailsPerformance::Reports::RecentRequestsReport::TIME_WINDOW %> minutes)<h2>
|
4
|
+
<h2 class="subtitle">Recent Requests (last <%= RailsPerformance::Reports::RecentRequestsReport::TIME_WINDOW / 60 %> minutes)<h2>
|
5
5
|
|
6
6
|
<table class="table is-fullwidth is-hoverable is-narrow">
|
7
7
|
<thead>
|
@@ -19,6 +19,11 @@
|
|
19
19
|
</tr>
|
20
20
|
</thead>
|
21
21
|
<tbody>
|
22
|
+
<% if @data.empty? %>
|
23
|
+
<tr>
|
24
|
+
<td colspan="10">Nothing to show here. Try to make a few requests in main app.</td>
|
25
|
+
</tr>
|
26
|
+
<% end %>
|
22
27
|
<% @data.each do |e| %>
|
23
28
|
<tr>
|
24
29
|
<td><%= format_datetime e[:datetime] %></td>
|
@@ -1,4 +1,9 @@
|
|
1
|
-
|
1
|
+
<% if @record %>
|
2
|
+
window.panel.header.html(window.panel.close + "<%= j report_name(@record.to_h) %>");
|
3
|
+
<% else %>
|
4
|
+
window.panel.header.html(window.panel.close);
|
5
|
+
<% end %>
|
6
|
+
|
2
7
|
window.panel.content.html("<%= j render '/rails_performance/trace' %>");
|
3
8
|
|
4
9
|
showPanel();
|
@@ -5,8 +5,10 @@ require_relative './instrument/metrics_collector.rb'
|
|
5
5
|
module RailsPerformance
|
6
6
|
class Engine < ::Rails::Engine
|
7
7
|
|
8
|
-
if RailsPerformance.enabled
|
8
|
+
if RailsPerformance.try(:enabled) # for rails c
|
9
|
+
|
9
10
|
config.app_middleware.insert_after ActionDispatch::Executor, RailsPerformance::Rails::Middleware
|
11
|
+
|
10
12
|
initializer :configure_metrics, after: :initialize_logger do
|
11
13
|
ActiveSupport::Notifications.subscribe(
|
12
14
|
"process_action.action_controller",
|
@@ -17,7 +19,9 @@ module RailsPerformance
|
|
17
19
|
ActionView::LogSubscriber.send :prepend, RailsPerformance::Extensions::View
|
18
20
|
ActiveRecord::LogSubscriber.send :prepend, RailsPerformance::Extensions::Db
|
19
21
|
end
|
22
|
+
|
20
23
|
end
|
24
|
+
|
21
25
|
end
|
22
26
|
|
23
27
|
end
|
@@ -18,6 +18,8 @@ module RailsPerformance
|
|
18
18
|
def call(event_name, started, finished, event_id, payload)
|
19
19
|
event = ActiveSupport::Notifications::Event.new(event_name, started, finished, event_id, payload)
|
20
20
|
|
21
|
+
return if event.payload[:path] =~ /^\/rails\/performance/
|
22
|
+
|
21
23
|
record = {
|
22
24
|
controller: event.payload[:controller],
|
23
25
|
action: event.payload[:action],
|
@@ -32,7 +34,7 @@ module RailsPerformance
|
|
32
34
|
duration: event.duration
|
33
35
|
}
|
34
36
|
|
35
|
-
|
37
|
+
CurrentRequest.current.record = record
|
36
38
|
end
|
37
39
|
end
|
38
40
|
end
|
@@ -1,6 +1,7 @@
|
|
1
1
|
module RailsPerformance
|
2
2
|
class CurrentRequest
|
3
3
|
attr_reader :request_id, :storage
|
4
|
+
attr_accessor :record
|
4
5
|
|
5
6
|
def CurrentRequest.init
|
6
7
|
Thread.current[:rp_current_request] ||= CurrentRequest.new(SecureRandom.hex(16))
|
@@ -17,6 +18,7 @@ module RailsPerformance
|
|
17
18
|
def initialize(request_id)
|
18
19
|
@request_id = request_id
|
19
20
|
@storage = []
|
21
|
+
@record = nil
|
20
22
|
end
|
21
23
|
|
22
24
|
def store(options = {})
|
@@ -3,6 +3,16 @@ module RailsPerformance
|
|
3
3
|
class Record
|
4
4
|
attr_reader :controller, :action, :format, :status, :datetime, :datetimei, :method, :path, :request_id
|
5
5
|
|
6
|
+
|
7
|
+
def Record.find_by(request_id:)
|
8
|
+
keys, values = RP::Utils.fetch_from_redis("performance|*|request_id|#{request_id}|*")
|
9
|
+
|
10
|
+
return nil if keys.blank?
|
11
|
+
return nil if values.blank?
|
12
|
+
|
13
|
+
RP::Models::Record.new(keys[0], values[0])
|
14
|
+
end
|
15
|
+
|
6
16
|
# key = performance|
|
7
17
|
# controller|HomeController|
|
8
18
|
# action|index|
|
@@ -43,6 +53,31 @@ module RailsPerformance
|
|
43
53
|
def controller_action_format
|
44
54
|
"#{controller}##{action}|#{format}"
|
45
55
|
end
|
56
|
+
|
57
|
+
def to_h
|
58
|
+
{
|
59
|
+
controller: controller,
|
60
|
+
action: action,
|
61
|
+
format: format,
|
62
|
+
method: method,
|
63
|
+
path: path,
|
64
|
+
duration: ms(value['duration']),
|
65
|
+
view_runtime: ms(value['view_runtime']),
|
66
|
+
db_runtime: ms(value['db_runtime']),
|
67
|
+
HTTP_REFERER: value['HTTP_REFERER']
|
68
|
+
}
|
69
|
+
end
|
70
|
+
|
71
|
+
private
|
72
|
+
|
73
|
+
def ms(e)
|
74
|
+
if e
|
75
|
+
e.to_f.round(1).to_s + " ms"
|
76
|
+
else
|
77
|
+
nil
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
46
81
|
end
|
47
82
|
end
|
48
83
|
end
|
@@ -8,17 +8,28 @@ module RailsPerformance
|
|
8
8
|
def call(env)
|
9
9
|
@status, @headers, @response = @app.call(env)
|
10
10
|
|
11
|
-
|
11
|
+
#t = Time.now
|
12
|
+
if record = CurrentRequest.current.record
|
12
13
|
begin
|
13
|
-
record[:status] ||= @status
|
14
|
+
record[:status] ||= @status # for 500 errors
|
14
15
|
record[:request_id] = CurrentRequest.current.request_id
|
16
|
+
|
17
|
+
# capture referer from where this page was opened
|
18
|
+
if record[:status] == 404
|
19
|
+
record[:HTTP_REFERER] = env["HTTP_REFERER"]
|
20
|
+
end
|
21
|
+
|
22
|
+
# store for section "recent requests"
|
15
23
|
RP::Utils.log_trace_in_redis(CurrentRequest.current.request_id, CurrentRequest.current.storage)
|
24
|
+
|
25
|
+
# store request information
|
16
26
|
RP::Utils.log_request_in_redis(record)
|
17
27
|
ensure
|
18
|
-
|
28
|
+
# we don't want to have a memory leak
|
19
29
|
CurrentRequest.cleanup
|
20
30
|
end
|
21
31
|
end
|
32
|
+
#puts "==> store performance data: #{(Time.now - t).round(3)}ms"
|
22
33
|
|
23
34
|
[@status, @headers, @response]
|
24
35
|
end
|
@@ -13,7 +13,7 @@ module RailsPerformance
|
|
13
13
|
end
|
14
14
|
|
15
15
|
def Utils.log_request_in_redis(e)
|
16
|
-
value = e.slice(:view_runtime, :db_runtime, :duration)
|
16
|
+
value = e.slice(:view_runtime, :db_runtime, :duration, :HTTP_REFERER)
|
17
17
|
key = "performance|controller|#{e[:controller]}|action|#{e[:action]}|format|#{e[:format]}|status|#{e[:status]}|datetime|#{e[:datetime]}|datetimei|#{e[:datetimei]}|method|#{e[:method]}|path|#{e[:path]}|request_id|#{e[:request_id]}|END"
|
18
18
|
|
19
19
|
# puts " [SAVE] key ---> #{key}\n"
|
@@ -1,3 +1,3 @@
|
|
1
1
|
module RailsPerformance
|
2
|
-
VERSION = '0.0
|
3
|
-
end
|
2
|
+
VERSION = '0.9.0'
|
3
|
+
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: rails_performance
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0
|
4
|
+
version: 0.9.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Igor Kasyanchuk
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2020-02-
|
11
|
+
date: 2020-02-11 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rails
|