rails_performance 1.2.2 → 1.3.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 +11 -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 +95 -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/recent.html.erb +8 -6
- data/app/views/rails_performance/rails_performance/requests.html.erb +8 -1
- data/app/views/rails_performance/rails_performance/slow.html.erb +4 -1
- data/app/views/rails_performance/shared/_header.html.erb +0 -1
- data/app/views/rails_performance/stylesheets/style.css +6 -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 -38
- 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 -49
- 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 +123 -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/recent_requests_report.rb +24 -24
- data/lib/rails_performance/reports/requests_report.rb +27 -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 +53 -54
- data/lib/rails_performance/version.rb +2 -2
- data/lib/rails_performance.rb +38 -33
- metadata +20 -3
@@ -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>
|
@@ -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,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">Requests (path, total number, average response time)</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,7 +4,10 @@
|
|
4
4
|
<div class="card-content">
|
5
5
|
<div class="columns">
|
6
6
|
<div class="column">
|
7
|
-
<h2 class="subtitle">Slow Requests (last <%= RailsPerformance.slow_requests_time_window / 60 %> minutes + slower
|
7
|
+
<h2 class="subtitle">Slow Requests (last <%= RailsPerformance.slow_requests_time_window / 60 %> minutes + slower than <%= RailsPerformance.slow_requests_threshold %>ms)<h2>
|
8
|
+
</div>
|
9
|
+
<div class="column is-narrow">
|
10
|
+
<%= render "export" %>
|
8
11
|
</div>
|
9
12
|
</div>
|
10
13
|
|
@@ -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 %>
|
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
|
@@ -1,38 +1,56 @@
|
|
1
|
-
RailsPerformance
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
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
|
-
|
1
|
+
if defined?(RailsPerformance)
|
2
|
+
RailsPerformance.setup do |config|
|
3
|
+
# Redis configuration
|
4
|
+
config.redis = Redis::Namespace.new("#{Rails.env}-rails-performance", redis: Redis.new(url: ENV["REDIS_URL"].presence || "redis://127.0.0.1:6379/0"))
|
5
|
+
|
6
|
+
# All data we collect
|
7
|
+
config.duration = 4.hours
|
8
|
+
|
9
|
+
# Recent Requests configuration
|
10
|
+
config.recent_requests_time_window = 60.minutes
|
11
|
+
# confog.recent_requests_limit = nil # numnber of recent requests
|
12
|
+
|
13
|
+
# Slow Requests configuration
|
14
|
+
config.slow_requests_time_window = 4.hours
|
15
|
+
# config.slow_requests_limit = 500 # numnber of slow requests
|
16
|
+
config.slow_requests_threshold = 500 # ms
|
17
|
+
|
18
|
+
config.debug = false # currently not used>
|
19
|
+
config.enabled = true
|
20
|
+
|
21
|
+
# default path where to mount gem
|
22
|
+
config.mount_at = "/rails/performance"
|
23
|
+
|
24
|
+
# protect your Performance Dashboard with HTTP BASIC password
|
25
|
+
config.http_basic_authentication_enabled = false
|
26
|
+
config.http_basic_authentication_user_name = "rails_performance"
|
27
|
+
config.http_basic_authentication_password = "password12"
|
28
|
+
|
29
|
+
# if you need an additional rules to check user permissions
|
30
|
+
config.verify_access_proc = proc { |controller| true }
|
31
|
+
# for example when you have `current_user`
|
32
|
+
# config.verify_access_proc = proc { |controller| controller.current_user && controller.current_user.admin? }
|
33
|
+
|
34
|
+
# You can ignore endpoints with Rails standard notation controller#action
|
35
|
+
# config.ignored_endpoints = ['HomeController#contact']
|
36
|
+
|
37
|
+
# You can ignore request paths by specifying the beginning of the path.
|
38
|
+
# For example, all routes starting with '/admin' can be ignored:
|
39
|
+
config.ignored_paths = ['/rails/performance']
|
40
|
+
|
41
|
+
# store custom data for the request
|
42
|
+
# config.custom_data_proc = proc do |env|
|
43
|
+
# request = Rack::Request.new(env)
|
44
|
+
# {
|
45
|
+
# email: request.env['warden'].user&.email, # if you are using Devise for example
|
46
|
+
# user_agent: request.env['HTTP_USER_AGENT']
|
47
|
+
# }
|
48
|
+
# end
|
49
|
+
|
50
|
+
# config home button link
|
51
|
+
config.home_link = "/"
|
52
|
+
config.skipable_rake_tasks = ["webpacker:compile"]
|
53
|
+
config.include_rake_tasks = false
|
54
|
+
config.include_custom_events = true
|
55
|
+
end
|
56
|
+
end
|