rails_performance 0.9.5 → 1.0.0.beta1

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.
Files changed (52) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +59 -9
  3. data/app/controllers/rails_performance/rails_performance_controller.rb +47 -35
  4. data/app/helpers/rails_performance/application_helper.rb +25 -7
  5. data/app/views/rails_performance/javascripts/app.js +2 -2
  6. data/app/views/rails_performance/layouts/rails_performance.html.erb +2 -2
  7. data/app/views/rails_performance/rails_performance/_summary.html.erb +1 -1
  8. data/app/views/rails_performance/rails_performance/custom.html.erb +83 -0
  9. data/app/views/rails_performance/rails_performance/delayed_job.html.erb +74 -0
  10. data/app/views/rails_performance/rails_performance/grape.html.erb +64 -0
  11. data/app/views/rails_performance/rails_performance/rake.html.erb +55 -0
  12. data/app/views/rails_performance/rails_performance/recent.html.erb +3 -1
  13. data/app/views/rails_performance/rails_performance/requests.html.erb +1 -1
  14. data/app/views/rails_performance/rails_performance/{jobs.html.erb → sidekiq.html.erb} +5 -4
  15. data/app/views/rails_performance/rails_performance/summary.js.erb +1 -1
  16. data/app/views/rails_performance/rails_performance/trace.js.erb +1 -1
  17. data/app/views/rails_performance/shared/_header.html.erb +9 -1
  18. data/app/views/rails_performance/stylesheets/style.css +5 -0
  19. data/config/routes.rb +7 -3
  20. data/lib/generators/rails_performance/install/USAGE +8 -0
  21. data/lib/generators/rails_performance/install/install_generator.rb +8 -0
  22. data/lib/generators/rails_performance/install/templates/initializer.rb +23 -0
  23. data/lib/rails_performance.rb +40 -7
  24. data/lib/rails_performance/data_source.rb +52 -13
  25. data/lib/rails_performance/engine.rb +39 -18
  26. data/lib/rails_performance/extensions/{capture_everything.rb → trace.rb} +2 -2
  27. data/lib/rails_performance/gems/custom_ext.rb +33 -0
  28. data/lib/rails_performance/gems/delayed_job_ext.rb +54 -0
  29. data/lib/rails_performance/gems/grape_ext.rb +35 -0
  30. data/lib/rails_performance/gems/rake_ext.rb +40 -0
  31. data/lib/rails_performance/gems/{sidekiq.rb → sidekiq_ext.rb} +14 -12
  32. data/lib/rails_performance/instrument/metrics_collector.rb +5 -3
  33. data/lib/rails_performance/models/base_record.rb +12 -0
  34. data/lib/rails_performance/models/custom_record.rb +48 -0
  35. data/lib/rails_performance/models/delayed_job_record.rb +62 -0
  36. data/lib/rails_performance/models/grape_record.rb +61 -0
  37. data/lib/rails_performance/models/rake_record.rb +49 -0
  38. data/lib/rails_performance/models/request_record.rb +98 -0
  39. data/lib/rails_performance/models/sidekiq_record.rb +66 -0
  40. data/lib/rails_performance/models/trace_record.rb +19 -0
  41. data/lib/rails_performance/rails/middleware.rb +42 -16
  42. data/lib/rails_performance/rails/query_builder.rb +1 -1
  43. data/lib/rails_performance/reports/breakdown_report.rb +4 -16
  44. data/lib/rails_performance/reports/crash_report.rb +4 -15
  45. data/lib/rails_performance/reports/recent_requests_report.rb +7 -44
  46. data/lib/rails_performance/reports/trace_report.rb +1 -1
  47. data/lib/rails_performance/{models → thread}/current_request.rb +9 -4
  48. data/lib/rails_performance/utils.rb +15 -29
  49. data/lib/rails_performance/version.rb +1 -1
  50. metadata +96 -10
  51. data/lib/rails_performance/models/job_record.rb +0 -48
  52. data/lib/rails_performance/models/record.rb +0 -68
@@ -0,0 +1,74 @@
1
+ <title>Delayed::Job</title>
2
+
3
+ <% unless @datasource.default? %>
4
+ <%#= link_to raw("&larr; Back"), rails_performance_path, class: "back_link" %>
5
+ <% end %>
6
+
7
+ <div class="card">
8
+ <div class="card-content">
9
+ <h2 class="subtitle">Delayed::Job Workers Throughput Report</h2>
10
+ <div id="throughput_report_chart" class="chart"></div>
11
+ <p class="content is-small">All workers in the application</p>
12
+ </div>
13
+ </div>
14
+
15
+ <br/>
16
+
17
+ <div class="card">
18
+ <div class="card-content">
19
+ <h2 class="subtitle">Average Execution Time</h2>
20
+ <div id="response_time_report_chart" class="chart"></div>
21
+ <p class="content is-small">All workers in the application</p>
22
+ </div>
23
+ </div>
24
+
25
+ <br/>
26
+
27
+ <div class="card">
28
+ <div class="card-content">
29
+ <h2 class="subtitle">Recent Jobs (last <%= RailsPerformance::Reports::RecentRequestsReport::TIME_WINDOW / 60 %> minutes)<h2>
30
+
31
+ <table class="table is-fullwidth is-hoverable is-narrow">
32
+ <thead>
33
+ <tr>
34
+ <th data-sort="string">Datetime</th>
35
+ <th data-sort="string">Job ID</th>
36
+ <th data-sort="string">Type</th>
37
+ <th data-sort="string">Class</th>
38
+ <th data-sort="string">Method</th>
39
+ <th data-sort="string">Status</th>
40
+ <th data-sort="float">Duration</th>
41
+ </tr>
42
+ </thead>
43
+ <tbody>
44
+ <% if @recent_report_data.empty? %>
45
+ <tr>
46
+ <td colspan="10">Nothing to show here. Try to make a few requests in the main app.</td>
47
+ </tr>
48
+ <% end %>
49
+ <% @recent_report_data.each do |e| %>
50
+ <tr>
51
+ <td><%= format_datetime e[:datetime] %></td>
52
+ <td><%= e[:jid] %></td>
53
+ <td><%= e[:source_type] %></td>
54
+ <td><%= e[:class_name] %></td>
55
+ <td><%= e[:method_name] %></td>
56
+ <td><%= status_tag e[:status] %></td>
57
+ <td class="nowrap"><%= ms e[:duration], 1 %></td>
58
+ </tr>
59
+ <% end %>
60
+ </tbody>
61
+ </table>
62
+ </div>
63
+ </div>
64
+
65
+
66
+ <% content_for :on_load do %>
67
+ <script>
68
+ var data1 = <%= raw @throughput_report_data.to_json %>;
69
+ showTIRChart('throughput_report_chart', data1, ' jobs / minute', 'Jobs');
70
+
71
+ var data2 = <%= raw @response_time_report_data.to_json %>;
72
+ showRTChart('response_time_report_chart', data2);
73
+ </script>
74
+ <% end %>
@@ -0,0 +1,64 @@
1
+ <title>Grape</title>
2
+
3
+ <% unless @datasource.default? %>
4
+ <%#= link_to raw("&larr; Back"), rails_performance_path, class: "back_link" %>
5
+ <% end %>
6
+
7
+ <div class="card">
8
+ <div class="card-content">
9
+ <h2 class="subtitle">Grape Throughput Report</h2>
10
+ <div id="throughput_report_chart" class="chart"></div>
11
+ <p class="content is-small"></p>
12
+ </div>
13
+ </div>
14
+
15
+ <br/>
16
+
17
+ <div class="card">
18
+ <div class="card-content">
19
+ <h2 class="subtitle">Recent Requests (last <%= RailsPerformance::Reports::RecentRequestsReport::TIME_WINDOW / 60 %> minutes)<h2>
20
+
21
+ <table class="table is-fullwidth is-hoverable is-narrow">
22
+ <thead>
23
+ <tr>
24
+ <th data-sort="string">Datetime</th>
25
+ <th data-sort="string">Method</th>
26
+ <th data-sort="string">Path</th>
27
+ <th data-sort="string">Status</th>
28
+ <th data-sort="float">endpoint_render.grape</th>
29
+ <th data-sort="float">format_response.grape</th>
30
+ <th data-sort="float">endpoint_run.grape</th>
31
+ <th></th>
32
+ </tr>
33
+ </thead>
34
+ <tbody>
35
+ <% if @recent_report_data.empty? %>
36
+ <tr>
37
+ <td colspan="10">Nothing to show here. Try to make a few requests in the main app.</td>
38
+ </tr>
39
+ <% end %>
40
+ <% @recent_report_data.each do |e| %>
41
+ <tr>
42
+ <td><%= format_datetime e[:datetime] %></td>
43
+ <td><%= e[:method] %></td>
44
+ <td><%= e[:path] %></td>
45
+ <td><%= status_tag e[:status] %></td>
46
+ <td class="nowrap"><%= ms e["endpoint_render.grape"] %></td>
47
+ <td class="nowrap"><%= ms e["format_response.grape"] %></td>
48
+ <td class="nowrap">
49
+ <%= ms e["endpoint_run.grape"] %>
50
+ </td>
51
+ </tr>
52
+ <% end %>
53
+ </tbody>
54
+ </table>
55
+ </div>
56
+ </div>
57
+
58
+
59
+ <% content_for :on_load do %>
60
+ <script>
61
+ var data1 = <%= raw @throughput_report_data.to_json %>;
62
+ showTIRChart('throughput_report_chart', data1, ' requests / minute', 'Requests');
63
+ </script>
64
+ <% end %>
@@ -0,0 +1,55 @@
1
+ <title>Rake</title>
2
+
3
+ <% unless @datasource.default? %>
4
+ <%#= link_to raw("&larr; Back"), rails_performance_path, class: "back_link" %>
5
+ <% end %>
6
+
7
+ <div class="card">
8
+ <div class="card-content">
9
+ <h2 class="subtitle">Recent Rake tasks (last <%= RailsPerformance::Reports::RecentRequestsReport::TIME_WINDOW / 60 %> minutes)<h2>
10
+
11
+ <table class="table is-fullwidth is-hoverable is-narrow">
12
+ <thead>
13
+ <tr>
14
+ <th data-sort="string">Datetime</th>
15
+ <th data-sort="string">Details</th>
16
+ <th data-sort="float">Duration</th>
17
+ <th data-sort="string">Status</th>
18
+ </tr>
19
+ </thead>
20
+ <tbody>
21
+ <% if @recent_report_data.empty? %>
22
+ <tr>
23
+ <td colspan="10">Nothing to show here. Try to make a few requests in the main app.</td>
24
+ </tr>
25
+ <% end %>
26
+ <% @recent_report_data.each do |e| %>
27
+ <tr>
28
+ <td><%= format_datetime e[:datetime] %></td>
29
+ <td>[<%= e[:task].join(" ") %>]</td>
30
+ <td class="nowrap"><%= ms e[:duration] %></td>
31
+ <td><%= status_tag e[:status] %></td>
32
+ </tr>
33
+ <% end %>
34
+ </tbody>
35
+ </table>
36
+ </div>
37
+ </div>
38
+
39
+ <br/>
40
+
41
+ <div class="card">
42
+ <div class="card-content">
43
+ <h2 class="subtitle">Rake Throughput Report</h2>
44
+ <div id="throughput_report_chart" class="chart"></div>
45
+ <p class="content is-small">All rake tasks in the application</p>
46
+ </div>
47
+ </div>
48
+
49
+
50
+ <% content_for :on_load do %>
51
+ <script>
52
+ var data1 = <%= raw @throughput_report_data.to_json %>;
53
+ showTIRChart('throughput_report_chart', data1, ' tasks / minute', 'Tasks');
54
+ </script>
55
+ <% end %>
@@ -1,3 +1,5 @@
1
+ <title>Recent Requests</title>
2
+
1
3
  <div class="card">
2
4
  <div class="card-content">
3
5
  <h2 class="subtitle">Recent Requests (last <%= RailsPerformance::Reports::RecentRequestsReport::TIME_WINDOW / 60 %> minutes)<h2>
@@ -21,7 +23,7 @@
21
23
  <tbody>
22
24
  <% if @data.empty? %>
23
25
  <tr>
24
- <td colspan="10">Nothing to show here. Try to make a few requests in main app.</td>
26
+ <td colspan="10">Nothing to show here. Try to make a few requests in the main app.</td>
25
27
  </tr>
26
28
  <% end %>
27
29
  <% @data.each do |e| %>
@@ -26,7 +26,7 @@
26
26
  <% c, a = groups[0].split("#") %>
27
27
  <tr>
28
28
  <td><%= link_to groups[0], rails_performance.rails_performance_summary_path({controller_eq: c, action_eq: a}), remote: true %></td>
29
- <td><%= link_to groups[1]&.upcase, rails_performance.rails_performance_summary_path({controller_eq: c, action_eq: a, format_eq: groups[1]}), remote: true %></td>
29
+ <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>
30
30
  <td><%= e[:count] %></td>
31
31
  <td class="nowrap"><%= ms e[:duration_average] %></td>
32
32
  <td class="nowrap"><%= ms e[:view_runtime_average] %></td>
@@ -1,4 +1,4 @@
1
- <title>Number of Requests to the Application</title>
1
+ <title>Sidekiq</title>
2
2
 
3
3
  <% unless @datasource.default? %>
4
4
  <%#= link_to raw("&larr; Back"), rails_performance_path, class: "back_link" %>
@@ -22,6 +22,8 @@
22
22
  </div>
23
23
  </div>
24
24
 
25
+ <br/>
26
+
25
27
  <div class="card">
26
28
  <div class="card-content">
27
29
  <h2 class="subtitle">Recent Jobs (last <%= RailsPerformance::Reports::RecentRequestsReport::TIME_WINDOW / 60 %> minutes)<h2>
@@ -36,13 +38,12 @@
36
38
  <th data-sort="string">Status</th>
37
39
  <th data-sort="float">Duration</th>
38
40
  <th>Message</th>
39
- <th></th>
40
41
  </tr>
41
42
  </thead>
42
43
  <tbody>
43
44
  <% if @recent_report_data.empty? %>
44
45
  <tr>
45
- <td colspan="10">Nothing to show here. Try to make a few requests in main app.</td>
46
+ <td colspan="10">Nothing to show here. Try to make a few requests in the main app.</td>
46
47
  </tr>
47
48
  <% end %>
48
49
  <% @recent_report_data.each do |e| %>
@@ -53,7 +54,7 @@
53
54
  <td><%= e[:jid] %></td>
54
55
  <td><%= status_tag e[:status] %></td>
55
56
  <td class="nowrap"><%= ms e[:duration] %></td>
56
- <td><%= e[:message] %></td>
57
+ <td><%= e[:message].presence || '-' %></td>
57
58
  </tr>
58
59
  <% end %>
59
60
  </tbody>
@@ -1,5 +1,5 @@
1
1
  window.panel.header.html(window.panel.close + '<%= j report_name(@datasource.q) %>');
2
- window.panel.content.html("<%= j render '/rails_performance/rails_performance/summary' %>");
2
+ window.panel.content.html("<%= j render '/rails_performance/rails_performance/summary', title: "Requests" %>");
3
3
 
4
4
  var data1 = <%= raw @throughput_report_data.to_json %>;
5
5
  showTIRChart('throughput_report_chart_mini', data1, ' rpm', 'RPM');
@@ -1,5 +1,5 @@
1
1
  <% if @record %>
2
- window.panel.header.html(window.panel.close + "<%= j report_name(@record.to_h) %>");
2
+ window.panel.header.html(window.panel.close + "<%= j report_name(@record.record_hash) %>");
3
3
  <% else %>
4
4
  window.panel.header.html(window.panel.close);
5
5
  <% end %>
@@ -19,8 +19,16 @@
19
19
  <%= link_to '500 Errors', rails_performance.rails_performance_crashes_url, class: "navbar-item #{active?(:crashes)}" %>
20
20
  <%= link_to 'Recent Requests', rails_performance.rails_performance_recent_url, class: "navbar-item #{active?(:recent)}" %>
21
21
  <% if defined?(Sidekiq) %>
22
- <%= link_to 'Sidekiq', rails_performance.rails_performance_jobs_url, class: "navbar-item #{active?(:jobs)}" %>
22
+ <%= link_to 'Sidekiq', rails_performance.rails_performance_sidekiq_url, class: "navbar-item #{active?(:sidekiq)}" %>
23
23
  <% end %>
24
+ <% if defined?(Delayed::Job) %>
25
+ <%= link_to 'Delayed::Job', rails_performance.rails_performance_delayed_job_url, class: "navbar-item #{active?(:delayed_job)}" %>
26
+ <% end %>
27
+ <% if defined?(Grape) %>
28
+ <%= link_to 'Grape', rails_performance.rails_performance_grape_url, class: "navbar-item #{active?(:grape)}" %>
29
+ <% end %>
30
+ <%= link_to 'Rake', rails_performance.rails_performance_rake_url, class: "navbar-item #{active?(:rake)}" %>
31
+ <%= link_to 'Custom Events', rails_performance.rails_performance_custom_url, class: "navbar-item #{active?(:custom)}" %>
24
32
  </div>
25
33
 
26
34
  <div class="navbar-end">
@@ -36,6 +36,11 @@
36
36
  opacity: 0.7;
37
37
  }
38
38
 
39
+ .footer-box a {
40
+ color: #4a4a4a;
41
+ text-decoration: underline;
42
+ }
43
+
39
44
  .stats_icon svg {
40
45
  width: 16px;
41
46
  height: 16px;
data/config/routes.rb CHANGED
@@ -8,14 +8,18 @@ RailsPerformance::Engine.routes.draw do
8
8
  get '/trace/:id' => 'rails_performance#trace', as: :rails_performance_trace
9
9
  get '/summary' => 'rails_performance#summary', as: :rails_performance_summary
10
10
 
11
- get '/jobs' => 'rails_performance#jobs', as: :rails_performance_jobs
11
+ get '/sidekiq' => 'rails_performance#sidekiq', as: :rails_performance_sidekiq
12
+ get '/delayed_job'=> 'rails_performance#delayed_job', as: :rails_performance_delayed_job
13
+ get '/grape' => 'rails_performance#grape', as: :rails_performance_grape
14
+ get '/rake' => 'rails_performance#rake', as: :rails_performance_rake
15
+ get '/custom' => 'rails_performance#custom', as: :rails_performance_custom
12
16
  end
13
17
 
14
18
  Rails.application.routes.draw do
15
19
  begin
16
- mount RailsPerformance::Engine => '/rails/performance', as: 'rails_performance'
20
+ mount RailsPerformance::Engine => RailsPerformance.mount_at, as: 'rails_performance'
17
21
  rescue ArgumentError
18
22
  # already added
19
- # this cod exist here because engine not includes routing automatically
23
+ # this code exist here because engine not includes routing automatically
20
24
  end
21
25
  end
@@ -0,0 +1,8 @@
1
+ Description:
2
+ Generates initial config for rails_performance gem
3
+
4
+ Example:
5
+ bin/rails generate rails_performance:install
6
+
7
+ This will create:
8
+ config/initializers/rails_performance.rb
@@ -0,0 +1,8 @@
1
+ class RailsPerformance::InstallGenerator < Rails::Generators::Base
2
+ source_root File.expand_path('templates', __dir__)
3
+ desc "Generates initial config for rails_performance gem"
4
+
5
+ def copy_initializer_file
6
+ copy_file "initializer.rb", "config/initializers/rails_performance.rb"
7
+ end
8
+ end
@@ -0,0 +1,23 @@
1
+ RailsPerformance.setup do |config|
2
+ config.redis = Redis::Namespace.new("#{Rails.env}-rails-performance", redis: Redis.new)
3
+ config.duration = 4.hours
4
+
5
+ config.debug = false # currently not used>
6
+ config.enabled = true
7
+
8
+ # default path where to mount gem
9
+ config.mount_at = '/rails/performance'
10
+
11
+ # protect your Performance Dashboard with HTTP BASIC password
12
+ config.http_basic_authentication_enabled = false
13
+ config.http_basic_authentication_user_name = 'rails_performance'
14
+ config.http_basic_authentication_password = 'password12'
15
+
16
+ # if you need an additional rules to check user permissions
17
+ config.verify_access_proc = proc { |controller| true }
18
+ # for example when you have `current_user`
19
+ # config.verify_access_proc = proc { |controller| controller.current_user && controller.current_user.admin? }
20
+
21
+ # You can ignore endpoints with Rails standard notation controller#action
22
+ # config.ignored_endpoints = ['HomeController#contact']
23
+ end if defined?(RailsPerformance)
@@ -3,10 +3,15 @@ require "redis-namespace"
3
3
  require_relative "./rails_performance/version.rb"
4
4
  require_relative "rails_performance/rails/query_builder.rb"
5
5
  require_relative "rails_performance/rails/middleware.rb"
6
- require_relative "rails_performance/data_source.rb"
7
6
  require_relative "rails_performance/models/base_record.rb"
8
- require_relative "rails_performance/models/record.rb"
9
- require_relative "rails_performance/models/job_record.rb"
7
+ require_relative "rails_performance/models/request_record.rb"
8
+ require_relative "rails_performance/models/sidekiq_record.rb"
9
+ require_relative "rails_performance/models/delayed_job_record.rb"
10
+ require_relative "rails_performance/models/grape_record.rb"
11
+ require_relative "rails_performance/models/trace_record.rb"
12
+ require_relative "rails_performance/models/rake_record.rb"
13
+ require_relative "rails_performance/models/custom_record.rb"
14
+ require_relative "rails_performance/data_source.rb"
10
15
  require_relative "rails_performance/utils.rb"
11
16
  require_relative "rails_performance/reports/base_report.rb"
12
17
  require_relative "rails_performance/reports/requests_report.rb"
@@ -16,14 +21,14 @@ require_relative "rails_performance/reports/throughput_report.rb"
16
21
  require_relative "rails_performance/reports/recent_requests_report.rb"
17
22
  require_relative "rails_performance/reports/breakdown_report.rb"
18
23
  require_relative "rails_performance/reports/trace_report.rb"
19
- require_relative "rails_performance/extensions/capture_everything.rb"
20
- require_relative "rails_performance/models/current_request.rb"
24
+ require_relative "rails_performance/extensions/trace.rb"
25
+ require_relative "rails_performance/thread/current_request.rb"
21
26
 
22
27
  module RailsPerformance
23
28
  FORMAT = "%Y%m%dT%H%M"
24
29
 
25
30
  mattr_accessor :redis
26
- @@redis = Redis::Namespace.new("#{::Rails.env}-rails-performance", redis: Redis.new)
31
+ @@redis = Redis::Namespace.new("{#{::Rails.env}-rails-performance}", redis: Redis.new)
27
32
 
28
33
  mattr_accessor :duration
29
34
  @@duration = 4.hours
@@ -34,6 +39,10 @@ module RailsPerformance
34
39
  mattr_accessor :enabled
35
40
  @@enabled = true
36
41
 
42
+ # default path where to mount gem
43
+ mattr_accessor :mount_at
44
+ @@mount_at = "/rails/performance"
45
+
37
46
  # Enable http basic authentication
38
47
  mattr_accessor :http_basic_authentication_enabled
39
48
  @@http_basic_authentication_enabled = false
@@ -50,12 +59,36 @@ module RailsPerformance
50
59
  mattr_accessor :verify_access_proc
51
60
  @@verify_access_proc = proc { |controller| true }
52
61
 
62
+ mattr_reader :ignored_endpoints
63
+ def RailsPerformance.ignored_endpoints=(endpoints)
64
+ @@ignored_endpoints = Set.new(endpoints)
65
+ end
66
+ @@ignored_endpoints = []
67
+
68
+ # skip requests if it's inside Rails Performance view
69
+ mattr_accessor :skip
70
+ @@skip = false
71
+
53
72
  def self.setup
54
73
  yield(self)
55
74
  end
56
75
 
76
+ def self.log(message)
77
+ return
78
+
79
+ if ::Rails.logger
80
+ # puts(message)
81
+ ::Rails.logger.debug(message)
82
+ else
83
+ puts(message)
84
+ end
85
+ end
86
+
57
87
  end
58
88
 
59
89
  RP = RailsPerformance
60
90
 
61
- require "rails_performance/engine"
91
+ require "rails_performance/engine"
92
+
93
+ require_relative './rails_performance/gems/custom_ext.rb'
94
+ RailsPerformance.send :extend, RailsPerformance::Gems::CustomExtension