rails_performance 0.9.9 → 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 (47) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +32 -3
  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/rails_performance/_summary.html.erb +1 -1
  7. data/app/views/rails_performance/rails_performance/custom.html.erb +83 -0
  8. data/app/views/rails_performance/rails_performance/delayed_job.html.erb +74 -0
  9. data/app/views/rails_performance/rails_performance/grape.html.erb +64 -0
  10. data/app/views/rails_performance/rails_performance/rake.html.erb +55 -0
  11. data/app/views/rails_performance/rails_performance/recent.html.erb +3 -1
  12. data/app/views/rails_performance/rails_performance/{jobs.html.erb → sidekiq.html.erb} +5 -4
  13. data/app/views/rails_performance/rails_performance/summary.js.erb +1 -1
  14. data/app/views/rails_performance/rails_performance/trace.js.erb +1 -1
  15. data/app/views/rails_performance/shared/_header.html.erb +9 -1
  16. data/app/views/rails_performance/stylesheets/style.css +5 -0
  17. data/config/routes.rb +5 -1
  18. data/lib/rails_performance.rb +29 -6
  19. data/lib/rails_performance/data_source.rb +52 -13
  20. data/lib/rails_performance/engine.rb +20 -3
  21. data/lib/rails_performance/extensions/{capture_everything.rb → trace.rb} +2 -2
  22. data/lib/rails_performance/gems/custom_ext.rb +33 -0
  23. data/lib/rails_performance/gems/delayed_job_ext.rb +54 -0
  24. data/lib/rails_performance/gems/grape_ext.rb +35 -0
  25. data/lib/rails_performance/gems/rake_ext.rb +40 -0
  26. data/lib/rails_performance/gems/{sidekiq.rb → sidekiq_ext.rb} +13 -12
  27. data/lib/rails_performance/instrument/metrics_collector.rb +3 -2
  28. data/lib/rails_performance/models/base_record.rb +12 -0
  29. data/lib/rails_performance/models/custom_record.rb +48 -0
  30. data/lib/rails_performance/models/delayed_job_record.rb +62 -0
  31. data/lib/rails_performance/models/grape_record.rb +61 -0
  32. data/lib/rails_performance/models/rake_record.rb +49 -0
  33. data/lib/rails_performance/models/request_record.rb +98 -0
  34. data/lib/rails_performance/models/sidekiq_record.rb +66 -0
  35. data/lib/rails_performance/models/trace_record.rb +19 -0
  36. data/lib/rails_performance/rails/middleware.rb +42 -16
  37. data/lib/rails_performance/rails/query_builder.rb +1 -1
  38. data/lib/rails_performance/reports/breakdown_report.rb +4 -16
  39. data/lib/rails_performance/reports/crash_report.rb +4 -15
  40. data/lib/rails_performance/reports/recent_requests_report.rb +7 -44
  41. data/lib/rails_performance/reports/trace_report.rb +1 -1
  42. data/lib/rails_performance/{models → thread}/current_request.rb +9 -4
  43. data/lib/rails_performance/utils.rb +15 -28
  44. data/lib/rails_performance/version.rb +1 -1
  45. metadata +79 -10
  46. data/lib/rails_performance/models/job_record.rb +0 -48
  47. data/lib/rails_performance/models/record.rb +0 -68
@@ -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| %>
@@ -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,7 +8,11 @@ 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
@@ -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
@@ -60,12 +65,30 @@ module RailsPerformance
60
65
  end
61
66
  @@ignored_endpoints = []
62
67
 
68
+ # skip requests if it's inside Rails Performance view
69
+ mattr_accessor :skip
70
+ @@skip = false
71
+
63
72
  def self.setup
64
73
  yield(self)
65
74
  end
66
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
+
67
87
  end
68
88
 
69
89
  RP = RailsPerformance
70
90
 
71
91
  require "rails_performance/engine"
92
+
93
+ require_relative './rails_performance/gems/custom_ext.rb'
94
+ RailsPerformance.send :extend, RailsPerformance::Gems::CustomExtension
@@ -1,20 +1,27 @@
1
1
  module RailsPerformance
2
2
  class DataSource
3
+ KLASSES = {
4
+ requests: RailsPerformance::Models::RequestRecord,
5
+ sidekiq: RailsPerformance::Models::SidekiqRecord,
6
+ delayed_job: RailsPerformance::Models::DelayedJobRecord,
7
+ grape: RailsPerformance::Models::GrapeRecord,
8
+ rake: RailsPerformance::Models::RakeRecord,
9
+ custom: RailsPerformance::Models::CustomRecord,
10
+ }
11
+
3
12
  attr_reader :q, :klass, :type
4
13
 
5
- def initialize(q: {}, type:, klass:)
6
- @klass = klass
14
+ def initialize(q: {}, type:)
7
15
  @type = type
16
+ @klass = KLASSES[type]
8
17
  q[:on] ||= Date.today
9
18
  @q = q
10
-
11
- #puts " [DataSource Q] --> #{@q.inspect}\n\n"
12
19
  end
13
20
 
14
21
  def db
15
22
  result = RP::Models::Collection.new
16
23
  (RP::Utils.days + 1).times do |e|
17
- RP::DataSource.new(q: self.q.merge({ on: e.days.ago.to_date }), klass: klass, type: type).add_to(result)
24
+ RP::DataSource.new(q: self.q.merge({ on: e.days.ago.to_date }), type: type).add_to(result)
18
25
  end
19
26
  result
20
27
  end
@@ -36,7 +43,7 @@ module RailsPerformance
36
43
  return [] if keys.blank?
37
44
 
38
45
  keys.each_with_index do |key, index|
39
- yield klass.new(key, values[index])
46
+ yield klass.from_db(key, values[index])
40
47
  end
41
48
  end
42
49
 
@@ -45,9 +52,17 @@ module RailsPerformance
45
52
  def query
46
53
  case type
47
54
  when :requests
48
- "performance|*#{compile_requests_query}*|END"
49
- when :jobs
50
- "jobs|*#{compile_jobs_query}*|END"
55
+ "performance|*#{compile_requests_query}*|END|#{RailsPerformance::VERSION}"
56
+ when :sidekiq
57
+ "sidekiq|*#{compile_sidekiq_query}*|END|#{RailsPerformance::VERSION}"
58
+ when :delayed_job
59
+ "delayed_job|*#{compile_delayed_job_query}*|END|#{RailsPerformance::VERSION}"
60
+ when :grape
61
+ "grape|*#{compile_grape_query}*|END|#{RailsPerformance::VERSION}"
62
+ when :rake
63
+ "rake|*#{compile_rake_query}*|END|#{RailsPerformance::VERSION}"
64
+ when :custom
65
+ "custom|*#{compile_custom_query}*|END|#{RailsPerformance::VERSION}"
51
66
  else
52
67
  raise "wrong type for datasource query builder"
53
68
  end
@@ -55,7 +70,6 @@ module RailsPerformance
55
70
 
56
71
  def compile_requests_query
57
72
  str = []
58
-
59
73
  str << "controller|#{q[:controller]}|" if q[:controller].present?
60
74
  str << "action|#{q[:action]}|" if q[:action].present?
61
75
  str << "format|#{q[:format]}|" if q[:format].present?
@@ -63,18 +77,43 @@ module RailsPerformance
63
77
  str << "datetime|#{q[:on].strftime('%Y%m%d')}*|" if q[:on].present?
64
78
  str << "method|#{q[:method]}|" if q[:method].present?
65
79
  str << "path|#{q[:path]}|" if q[:path].present?
66
-
67
80
  str.join("*")
68
81
  end
69
82
 
70
- def compile_jobs_query
83
+ def compile_sidekiq_query
71
84
  str = []
72
-
73
85
  str << "queue|#{q[:queue]}|" if q[:queue].present?
74
86
  str << "worker|#{q[:worker]}|" if q[:worker].present?
75
87
  str << "datetime|#{q[:on].strftime('%Y%m%d')}*|" if q[:on].present?
76
88
  str << "status|#{q[:status]}|" if q[:status].present?
89
+ str.join("*")
90
+ end
91
+
92
+ def compile_delayed_job_query
93
+ str = []
94
+ str << "datetime|#{q[:on].strftime('%Y%m%d')}*|" if q[:on].present?
95
+ str << "status|#{q[:status]}|" if q[:status].present?
96
+ str.join("*")
97
+ end
98
+
99
+ def compile_rake_query
100
+ str = []
101
+ str << "datetime|#{q[:on].strftime('%Y%m%d')}*|" if q[:on].present?
102
+ str << "status|#{q[:status]}|" if q[:status].present?
103
+ str.join("*")
104
+ end
105
+
106
+ def compile_custom_query
107
+ str = []
108
+ str << "datetime|#{q[:on].strftime('%Y%m%d')}*|" if q[:on].present?
109
+ str << "status|#{q[:status]}|" if q[:status].present?
110
+ str.join("*")
111
+ end
77
112
 
113
+ def compile_grape_query
114
+ str = []
115
+ str << "datetime|#{q[:on].strftime('%Y%m%d')}*|" if q[:on].present?
116
+ str << "status|#{q[:status]}|" if q[:status].present?
78
117
  str.join("*")
79
118
  end
80
119
 
@@ -15,15 +15,27 @@ module RailsPerformance
15
15
  else
16
16
  app.middleware.insert_after ActionDispatch::Static, RailsPerformance::Rails::Middleware
17
17
  end
18
+ # look like it works in reverse order?
19
+ app.middleware.insert_before RailsPerformance::Rails::Middleware, RailsPerformance::Rails::MiddlewareTraceStorerAndCleanup
18
20
 
19
- if defined?(Sidekiq)
20
- require_relative './gems/sidekiq.rb'
21
+ if defined?(::Sidekiq)
22
+ require_relative './gems/sidekiq_ext.rb'
21
23
  Sidekiq.configure_server do |config|
22
24
  config.server_middleware do |chain|
23
- chain.add RailsPerformance::Gems::Sidekiq
25
+ chain.add RailsPerformance::Gems::SidekiqExt
24
26
  end
25
27
  end
26
28
  end
29
+
30
+ if defined?(::Grape)
31
+ require_relative './gems/grape_ext.rb'
32
+ RailsPerformance::Gems::GrapeExt.init
33
+ end
34
+
35
+ if defined?(::Delayed::Job)
36
+ require_relative './gems/delayed_job_ext.rb'
37
+ RailsPerformance::Gems::DelayedJobExt.init
38
+ end
27
39
  end
28
40
 
29
41
  initializer :configure_metrics, after: :initialize_logger do
@@ -41,5 +53,10 @@ module RailsPerformance
41
53
  ActionView::LogSubscriber.send :prepend, RailsPerformance::Extensions::View
42
54
  ActiveRecord::LogSubscriber.send :prepend, RailsPerformance::Extensions::Db
43
55
  end
56
+
57
+ if defined?(::Rake::Task)
58
+ require_relative './gems/rake_ext.rb'
59
+ RailsPerformance::Gems::RakeExt.init
60
+ end
44
61
  end
45
62
  end