rails_performance 0.9.0.1 → 0.9.1

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: f448780915ccb27d02015c9b9b4d011ae318175c5564ae33643fcf0c0a3ecd2f
4
- data.tar.gz: cd3f09c47e39ab49a35df35ff83f0f604e76758ebea92a424e5a817e6eef7294
3
+ metadata.gz: 662230b3b860d73ccb29daecb0c4c3da5c4f4cfe1e2c94204492d696f71b72a4
4
+ data.tar.gz: a131984d8579760ca2296834ef81aefbb9551a5b697777a407f2fa24b002165f
5
5
  SHA512:
6
- metadata.gz: '0891876b6e5aa7826da42d1a58800b574c5d0d987c286ae836c31a493adea505cd5d407f833b681f72e66526dbbfa6da05a16b7562002f328c150c1070beee4a'
7
- data.tar.gz: eab4c06078ef53261b90f7063c54859d39157e1999f27674db5f7f7dab3c30fe2fb87fa1013502f0910a0ea36e24e46ec2d22251e3c4707220d58fb5c61370c4
6
+ metadata.gz: 63f19b12ab23a87aa172a2e58552f4a0710406ade760c3922c1ff54b819edb21e948bed28a71cdee273cc9bb37b7a592dc78eda612060a61674f527468537f93
7
+ data.tar.gz: 819ed734ea3c433d3c9550748a877ab1883117eba7aa29da5e766f8c03f09d81a53c259c8a64fe860a5e27e952961bc03d615de9d9349e6ae0b1579de63ac908
data/README.md CHANGED
@@ -1,29 +1,44 @@
1
1
  # Rails Performance
2
2
 
3
- Self-hosted tool to monitor the performance of your Ruby on Rails application.
3
+ [![Build Status](https://travis-ci.org/igorkasyanchuk/rails_performance.svg?branch=master)](https://travis-ci.org/igorkasyanchuk/rails_performance)
4
+
5
+ A self-hosted tool to monitor the performance of your Ruby on Rails application.
4
6
 
5
7
  This is **simple and free alternative** to the New Relic APM, Datadog or other similar services.
6
8
 
9
+ ![Demo](docs/rails_performance.gif)
10
+
7
11
  It allows you to track:
8
12
 
9
13
  - throughput report (see amount of RPM (requests per minute))
10
14
  - an average response time
11
15
  - the slowest controllers & actions
12
16
  - total duration of time spent per request, views rendering, DB
13
- - SQL queries, rendering log in recent requests
17
+ - SQL queries, rendering logs in "Recent Requests" section
14
18
  - simple 500-crashes reports
19
+ - track Sidekiq jobs performance
15
20
 
16
21
  All data are stored in `local` Redis and not sent to any 3rd party servers.
17
22
 
18
23
  ## Production
19
24
 
20
- Gem is production-ready. At least on my 2 applications with ~800 unique users per day it works perfect.
25
+ Gem is production-ready. At least on my 2 applications with ~800 unique users per day it works perfectly.
26
+
27
+ Just don't forget to protect performance dashboard with http basic auth or check of current_user.
21
28
 
22
29
  ## Usage
23
30
 
31
+ ```
32
+ 1. Add gem to the Gemfile (in appropriate group if needed)
33
+ 2. Start rails server
34
+ 3. Make a few requests to your app
35
+ 4. open localhost:3000/rails/performance
36
+ 5. Tune the configuration and deploy to production
37
+ ```
38
+
24
39
  Default configulation is listed below. But you can overide it.
25
40
 
26
- Create `config/initializers/rails_performance.rb`
41
+ Create `config/initializers/rails_performance.rb` in your app:
27
42
 
28
43
  ```ruby
29
44
  RailsPerformance.setup do |config|
@@ -50,6 +65,12 @@ Add this line to your application's Gemfile:
50
65
 
51
66
  ```ruby
52
67
  gem 'rails_performance'
68
+
69
+ # or
70
+
71
+ group :development, :production do
72
+ gem 'rails_performance'
73
+ end
53
74
  ```
54
75
 
55
76
  And then execute:
@@ -61,6 +82,10 @@ You must also have installed Redis server, because this gem is storing data into
61
82
 
62
83
  After installation and configuration, start your Rails application, make a few requests, and open `https://localhost:3000/rails/performance` URL.
63
84
 
85
+ ## How it works
86
+
87
+ ![Schema](docs/rails_performance.png)
88
+
64
89
  ## Limitations
65
90
 
66
91
  - it doesn't track params of POST/PUT requests
@@ -70,6 +95,8 @@ After installation and configuration, start your Rails application, make a few r
70
95
 
71
96
  ## Redis
72
97
 
98
+ Gem is using Redis. This is the only one dependency.
99
+
73
100
  All information is stored into Redis. The default expiration time is set to `config.duration` from the configuration.
74
101
 
75
102
  ## Development & Testing
@@ -111,6 +138,8 @@ The idea of this gem grew from curriosity how many RPM my app receiving per day.
111
138
  - collect deprecation.rails
112
139
  - fix misspellings?
113
140
  - show "loading banner" until jquery is loaded?
141
+ - better UI on smaller screens? Recent requests when URL's are long? Truncate with CSS?
142
+ - rules for highlighting durations? how many ms to show warning, alert
114
143
 
115
144
  ## Contributing
116
145
 
@@ -4,7 +4,7 @@ class RailsPerformanceController < BaseController
4
4
 
5
5
  if RailsPerformance.enabled
6
6
  def index
7
- @datasource = RP::DataSource.new(prepare_query)
7
+ @datasource = RP::DataSource.new(**prepare_query, type: :requests, klass: RP::Models::Record)
8
8
  db = @datasource.db
9
9
 
10
10
  @throughput_report = RP::Reports::ThroughputReport.new(db)
@@ -15,7 +15,7 @@ class RailsPerformanceController < BaseController
15
15
  end
16
16
 
17
17
  def summary
18
- @datasource = RP::DataSource.new(prepare_query)
18
+ @datasource = RP::DataSource.new(**prepare_query, type: :requests, klass: RP::Models::Record)
19
19
  db = @datasource.db
20
20
 
21
21
  @throughput_report = RP::Reports::ThroughputReport.new(db)
@@ -44,26 +44,40 @@ class RailsPerformanceController < BaseController
44
44
  end
45
45
 
46
46
  def crashes
47
- @datasource = RP::DataSource.new(prepare_query({status_eq: 500}))
47
+ @datasource = RP::DataSource.new(**prepare_query({status_eq: 500}), type: :requests, klass: RP::Models::Record)
48
48
  db = @datasource.db
49
49
  @report = RP::Reports::CrashReport.new(db)
50
50
  @data = @report.data
51
51
  end
52
52
 
53
53
  def requests
54
- @datasource = RP::DataSource.new(prepare_query)
54
+ @datasource = RP::DataSource.new(**prepare_query, type: :requests, klass: RP::Models::Record)
55
55
  db = @datasource.db
56
56
  @report = RP::Reports::RequestsReport.new(db, group: :controller_action_format, sort: :count)
57
57
  @data = @report.data
58
58
  end
59
59
 
60
60
  def recent
61
- @datasource = RP::DataSource.new(prepare_query)
61
+ @datasource = RP::DataSource.new(**prepare_query, type: :requests, klass: RP::Models::Record)
62
62
  db = @datasource.db
63
63
  @report = RP::Reports::RecentRequestsReport.new(db)
64
64
  @data = @report.data
65
65
  end
66
66
 
67
+ def jobs
68
+ @datasource = RP::DataSource.new(**prepare_query, type: :jobs, klass: RP::Models::JobRecord)
69
+ db = @datasource.db
70
+
71
+ @throughput_report = RP::Reports::ThroughputReport.new(db)
72
+ @throughput_report_data = @throughput_report.data
73
+
74
+ @response_time_report = RP::Reports::ResponseTimeReport.new(db)
75
+ @response_time_report_data = @response_time_report.data
76
+
77
+ @recent_report = RP::Reports::RecentRequestsReport.new(db)
78
+ @recent_report_data = @recent_report.data(:jobs)
79
+ end
80
+
67
81
  private
68
82
 
69
83
  def prepare_query(query = params)
@@ -107,6 +107,8 @@ module RailsPerformanceHelper
107
107
  "is-active" if controller_name == "rails_performance" && action_name == "requests"
108
108
  when :recent
109
109
  "is-active" if controller_name == "rails_performance" && action_name == "recent"
110
+ when :jobs
111
+ "is-active" if controller_name == "rails_performance" && action_name == "jobs"
110
112
  end
111
113
  end
112
114
  end
@@ -25,7 +25,7 @@
25
25
  <% content_for :on_load do %>
26
26
  <script>
27
27
  var data1 = <%= raw @throughput_report_data.to_json %>;
28
- showTIRChart('throughput_report_chart', data1);
28
+ showTIRChart('throughput_report_chart', data1, ' rpm', 'RPM');
29
29
 
30
30
  var data2 = <%= raw @response_time_report_data.to_json %>;
31
31
  showRTChart('response_time_report_chart', data2);
@@ -1,4 +1,4 @@
1
- function showTIRChart(div, data) {
1
+ function showTIRChart(div, data, addon, name) {
2
2
  Highcharts.chart(div, {
3
3
  time: {
4
4
  timezone: 'Europe/Kiev'
@@ -24,7 +24,7 @@ function showTIRChart(div, data) {
24
24
  if (this.y == 0) {
25
25
  return '';
26
26
  }
27
- return this.y + ' rpm';
27
+ return this.y + addon;
28
28
  }
29
29
  },
30
30
  xAxis: {
@@ -69,7 +69,7 @@ function showTIRChart(div, data) {
69
69
  },
70
70
  series: [{
71
71
  type: 'area',
72
- name: 'RPM',
72
+ name: name,
73
73
  data: data,
74
74
  fillOpacity: 0.3,
75
75
  lineWidth: 1,
@@ -0,0 +1,73 @@
1
+ <title>Number of Requests to the Application</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">Sidekiq 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
+ <div class="card">
26
+ <div class="card-content">
27
+ <h2 class="subtitle">Recent Jobs (last <%= RailsPerformance::Reports::RecentRequestsReport::TIME_WINDOW / 60 %> minutes)<h2>
28
+
29
+ <table class="table is-fullwidth is-hoverable is-narrow">
30
+ <thead>
31
+ <tr>
32
+ <th data-sort="string">Datetime</th>
33
+ <th data-sort="string">Queue</th>
34
+ <th data-sort="string">Worker</th>
35
+ <th data-sort="string">Job ID</th>
36
+ <th data-sort="string">Status</th>
37
+ <th data-sort="float">Duration</th>
38
+ <th>Message</th>
39
+ <th></th>
40
+ </tr>
41
+ </thead>
42
+ <tbody>
43
+ <% if @recent_report_data.empty? %>
44
+ <tr>
45
+ <td colspan="10">Nothing to show here. Try to make a few requests in main app.</td>
46
+ </tr>
47
+ <% end %>
48
+ <% @recent_report_data.each do |e| %>
49
+ <tr>
50
+ <td><%= format_datetime e[:datetime] %></td>
51
+ <td><%= e[:queue] %></td>
52
+ <td><%= e[:worker] %></td>
53
+ <td><%= e[:jid] %></td>
54
+ <td><%= status_tag e[:status] %></td>
55
+ <td class="nowrap"><%= ms e[:duration] %></td>
56
+ <td><%= e[:message] %></td>
57
+ </tr>
58
+ <% end %>
59
+ </tbody>
60
+ </table>
61
+ </div>
62
+ </div>
63
+
64
+
65
+ <% content_for :on_load do %>
66
+ <script>
67
+ var data1 = <%= raw @throughput_report_data.to_json %>;
68
+ showTIRChart('throughput_report_chart', data1, ' jobs / minute', 'Jobs');
69
+
70
+ var data2 = <%= raw @response_time_report_data.to_json %>;
71
+ showRTChart('response_time_report_chart', data2);
72
+ </script>
73
+ <% end %>
@@ -1,6 +1,5 @@
1
1
  <div class="card">
2
2
  <div class="card-content">
3
-
4
3
  <h2 class="subtitle">Recent Requests (last <%= RailsPerformance::Reports::RecentRequestsReport::TIME_WINDOW / 60 %> minutes)<h2>
5
4
 
6
5
  <table class="table is-fullwidth is-hoverable is-narrow">
@@ -18,6 +18,9 @@
18
18
  <%= link_to 'Requests Analysis', rails_performance.rails_performance_requests_url, class: "navbar-item #{active?(:requests)}" %>
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
+ <% if defined?(Sidekiq) %>
22
+ <%= link_to 'Sidekiq', rails_performance.rails_performance_jobs_url, class: "navbar-item #{active?(:jobs)}" %>
23
+ <% end %>
21
24
  </div>
22
25
 
23
26
  <div class="navbar-end">
@@ -2,7 +2,7 @@ window.panel.header.html(window.panel.close + '<%= j report_name(@datasource.q)
2
2
  window.panel.content.html("<%= j render '/rails_performance/summary' %>");
3
3
 
4
4
  var data1 = <%= raw @throughput_report_data.to_json %>;
5
- showTIRChart('throughput_report_chart_mini', data1);
5
+ showTIRChart('throughput_report_chart_mini', data1, ' rpm', 'RPM');
6
6
 
7
7
  var data2 = <%= raw @response_time_report_data.to_json %>;
8
8
  showRTChart('response_time_report_chart_mini', data2);
@@ -7,6 +7,8 @@ RailsPerformance::Engine.routes.draw do
7
7
 
8
8
  get '/trace/:id' => 'rails_performance#trace', as: :rails_performance_trace
9
9
  get '/summary' => 'rails_performance#summary', as: :rails_performance_summary
10
+
11
+ get '/jobs' => 'rails_performance#jobs', as: :rails_performance_jobs
10
12
  end
11
13
 
12
14
  Rails.application.routes.draw do
@@ -4,7 +4,9 @@ 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
6
  require_relative "rails_performance/data_source.rb"
7
+ require_relative "rails_performance/models/base_record.rb"
7
8
  require_relative "rails_performance/models/record.rb"
9
+ require_relative "rails_performance/models/job_record.rb"
8
10
  require_relative "rails_performance/utils.rb"
9
11
  require_relative "rails_performance/reports/base_report.rb"
10
12
  require_relative "rails_performance/reports/requests_report.rb"
@@ -1,8 +1,10 @@
1
1
  module RailsPerformance
2
2
  class DataSource
3
- attr_reader :q
3
+ attr_reader :q, :klass, :type
4
4
 
5
- def initialize(q: {})
5
+ def initialize(q: {}, type:, klass:)
6
+ @klass = klass
7
+ @type = type
6
8
  q[:on] ||= Date.today
7
9
  @q = q
8
10
 
@@ -12,7 +14,7 @@ module RailsPerformance
12
14
  def db
13
15
  result = RP::Models::Collection.new
14
16
  (RP::Utils.days + 1).times do |e|
15
- RP::DataSource.new(q: self.q.merge({ on: e.days.ago.to_date })).add_to(result)
17
+ RP::DataSource.new(q: self.q.merge({ on: e.days.ago.to_date }), klass: klass, type: type).add_to(result)
16
18
  end
17
19
  result
18
20
  end
@@ -34,41 +36,46 @@ module RailsPerformance
34
36
  return [] if keys.blank?
35
37
 
36
38
  keys.each_with_index do |key, index|
37
- yield RP::Models::Record.new(key, values[index])
39
+ yield klass.new(key, values[index])
38
40
  end
39
41
  end
40
42
 
41
43
  private
42
44
 
43
- # key = performance|
44
- # controller|HomeController|
45
- # action|index|
46
- # format|html|
47
- # status|200|
48
- # datetime|20200124T0523|
49
- # datetimei|1579861423|
50
- # method|GET|
51
- # path|/|
52
- # END
53
-
54
- def compile_query
45
+ def query
46
+ case type
47
+ when :requests
48
+ "performance|*#{compile_requests_query}*|END"
49
+ when :jobs
50
+ "jobs|*#{compile_jobs_query}*|END"
51
+ else
52
+ raise "wrong type for datasource query builder"
53
+ end
54
+ end
55
+
56
+ def compile_requests_query
55
57
  str = []
56
58
 
57
59
  str << "controller|#{q[:controller]}|" if q[:controller].present?
58
60
  str << "action|#{q[:action]}|" if q[:action].present?
59
61
  str << "format|#{q[:format]}|" if q[:format].present?
60
62
  str << "status|#{q[:status]}|" if q[:status].present?
61
-
62
63
  str << "datetime|#{q[:on].strftime('%Y%m%d')}*|" if q[:on].present?
63
-
64
64
  str << "method|#{q[:method]}|" if q[:method].present?
65
65
  str << "path|#{q[:path]}|" if q[:path].present?
66
66
 
67
67
  str.join("*")
68
68
  end
69
69
 
70
- def query
71
- "performance|*#{compile_query}*|END"
70
+ def compile_jobs_query
71
+ str = []
72
+
73
+ str << "queue|#{q[:queue]}|" if q[:queue].present?
74
+ str << "worker|#{q[:worker]}|" if q[:worker].present?
75
+ str << "datetime|#{q[:on].strftime('%Y%m%d')}*|" if q[:on].present?
76
+ str << "status|#{q[:status]}|" if q[:status].present?
77
+
78
+ str.join("*")
72
79
  end
73
80
 
74
81
  end
@@ -19,7 +19,15 @@ module RailsPerformance
19
19
  ActionView::LogSubscriber.send :prepend, RailsPerformance::Extensions::View
20
20
  ActiveRecord::LogSubscriber.send :prepend, RailsPerformance::Extensions::Db
21
21
  end
22
+ end
22
23
 
24
+ if const_defined?("Sidekiq")
25
+ require_relative './gems/sidekiq.rb'
26
+ Sidekiq.configure_server do |config|
27
+ config.server_middleware do |chain|
28
+ chain.add RailsPerformance::Gems::Sidekiq
29
+ end
30
+ end
23
31
  end
24
32
 
25
33
  end
@@ -0,0 +1,35 @@
1
+ module RailsPerformance
2
+ module Gems
3
+ class Sidekiq
4
+
5
+ def initialize(options=nil)
6
+ end
7
+
8
+ def call(worker, msg, queue)
9
+ now = Time.now
10
+ data = {
11
+ enqueued_ati: msg['enqueued_at'].to_i,
12
+ created_ati: msg['created_at'].to_i,
13
+ jid: msg['jid'],
14
+ queue: queue,
15
+ start_timei: now.to_i,
16
+ datetime: now.strftime(RailsPerformance::FORMAT),
17
+ worker: msg['wrapped'.freeze] || worker.class.to_s
18
+ }
19
+ begin
20
+ yield
21
+ data[:status] = "success"
22
+ rescue Exception => ex
23
+ data[:status] = "exception"
24
+ data[:message] = ex.message
25
+ ensure
26
+ # store in ms instead of seconds
27
+ data[:duration] = (Time.now - now) * 1000
28
+ #puts data
29
+ RailsPerformance::Utils.log_job_in_redis(data)
30
+ end
31
+ end
32
+
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,24 @@
1
+ module RailsPerformance
2
+ module Models
3
+ class BaseRecord
4
+ def value
5
+ @value ||= JSON.parse(@json || "{}")
6
+ end
7
+
8
+ def duration
9
+ value['duration']
10
+ end
11
+
12
+ private
13
+
14
+ def ms(e)
15
+ if e
16
+ e.to_f.round(1).to_s + " ms"
17
+ else
18
+ nil
19
+ end
20
+ end
21
+
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,48 @@
1
+ module RailsPerformance
2
+ module Models
3
+ class JobRecord < BaseRecord
4
+ attr_reader :queue, :worker, :jid, :created_ati, :enqueued_ati, :datetime, :start_timei, :status
5
+
6
+ # key = job-performance
7
+ # |queue|default
8
+ # |worker|SimpleWorker
9
+ # |jid|7d48fbf20976c224510dbc60
10
+ # |datetime|20200124T0523
11
+ # |created_ati|1583146613
12
+ # |enqueued_ati|1583146613
13
+ # |start_timei|1583146614
14
+ # |status|success|END
15
+ # value = JSON
16
+ def initialize(key, value)
17
+ @json = value
18
+
19
+ items = key.split("|")
20
+
21
+ @queue = items[2]
22
+ @worker = items[4]
23
+ @jid = items[6]
24
+ @datetime = items[8]
25
+ @created_ati = items[10]
26
+ @enqueued_ati = items[12]
27
+ @start_timei = items[14]
28
+ @status = items[16]
29
+ end
30
+
31
+ def to_h
32
+ {
33
+ queue: queue,
34
+ worker: worker,
35
+ jid: jid,
36
+ datetime: datetime,
37
+ created_ati: created_ati,
38
+ enqueued_ati: enqueued_ati,
39
+ start_timei: start_timei,
40
+ duration: duration,
41
+ status: status,
42
+ message: value['message']
43
+ }
44
+ end
45
+
46
+ end
47
+ end
48
+ end
@@ -1,9 +1,8 @@
1
1
  module RailsPerformance
2
2
  module Models
3
- class Record
3
+ class Record < BaseRecord
4
4
  attr_reader :controller, :action, :format, :status, :datetime, :datetimei, :method, :path, :request_id
5
5
 
6
-
7
6
  def Record.find_by(request_id:)
8
7
  keys, values = RP::Utils.fetch_from_redis("performance|*|request_id|#{request_id}|*")
9
8
 
@@ -42,10 +41,6 @@ module RailsPerformance
42
41
  @request_id = items[18]
43
42
  end
44
43
 
45
- def value
46
- @value ||= JSON.parse(@json || "{}")
47
- end
48
-
49
44
  def controller_action
50
45
  "#{controller}##{action}"
51
46
  end
@@ -61,23 +56,13 @@ module RailsPerformance
61
56
  format: format,
62
57
  method: method,
63
58
  path: path,
64
- duration: ms(value['duration']),
59
+ duration: ms(duration),
65
60
  view_runtime: ms(value['view_runtime']),
66
61
  db_runtime: ms(value['db_runtime']),
67
62
  HTTP_REFERER: value['HTTP_REFERER']
68
63
  }
69
64
  end
70
65
 
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
-
81
66
  end
82
67
  end
83
68
  end
@@ -7,25 +7,48 @@ module RailsPerformance
7
7
  @sort ||= :datetime
8
8
  end
9
9
 
10
- def data
10
+ def data(type = :requests) # most popular type
11
11
  db.data.collect do |record|
12
- {
13
- controller: record.controller,
14
- action: record.action,
15
- format: record.format,
16
- status: record.status,
17
- method: record.method,
18
- path: record.path,
19
- request_id: record.request_id,
20
- datetime: Time.at(record.datetimei.to_i),
21
- duration: record.value['duration'],
22
- db_runtime: record.value['db_runtime'],
23
- view_runtime: record.value['view_runtime'],
24
- }
12
+ case type
13
+ when :requests
14
+ record_hash(record)
15
+ when :jobs
16
+ job_hash(record)
17
+ end
25
18
  end
26
19
  .select{|e| e if e[:datetime] >= TIME_WINDOW.ago}
27
20
  .sort{|a, b| b[sort] <=> a[sort]}
28
21
  end
22
+
23
+ private
24
+
25
+ def record_hash(record)
26
+ {
27
+ controller: record.controller,
28
+ action: record.action,
29
+ format: record.format,
30
+ status: record.status,
31
+ method: record.method,
32
+ path: record.path,
33
+ request_id: record.request_id,
34
+ datetime: Time.at(record.datetimei.to_i),
35
+ duration: record.value['duration'],
36
+ db_runtime: record.value['db_runtime'],
37
+ view_runtime: record.value['view_runtime'],
38
+ }
39
+ end
40
+
41
+ def job_hash(record)
42
+ {
43
+ worker: record.worker,
44
+ queue: record.queue,
45
+
46
+ jid: record.jid,
47
+ status: record.status,
48
+ datetime: Time.at(record.start_timei.to_i),
49
+ duration: record.value['duration'],
50
+ }
51
+ end
29
52
  end
30
53
 
31
54
 
@@ -12,28 +12,21 @@ module RailsPerformance
12
12
  now.strftime("%H:%M")
13
13
  end
14
14
 
15
+ def Utils.log_job_in_redis(e)
16
+ key = "jobs|queue|#{e[:queue]}|worker|#{e[:worker]}|jid|#{e[:jid]}|datetime|#{e[:datetime]}|created_ati|#{e[:created_ati]}|enqueued_ati|#{e[:enqueued_ati]}|start_timei|#{e[:start_timei]}|status|#{e[:status]}|END"
17
+ value = { message: e[:message], duration: e[:duration] }
18
+ Utils.save_to_redis(key, value)
19
+ end
20
+
15
21
  def Utils.log_request_in_redis(e)
16
22
  value = e.slice(:view_runtime, :db_runtime, :duration, :HTTP_REFERER)
17
23
  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
-
19
- # puts " [SAVE] key ---> #{key}\n"
20
- # puts " value ---> #{value.to_json}\n\n"
21
-
22
- RP.redis.set(key, value.to_json)
23
- RP.redis.expire(key, RP.duration.to_i)
24
-
25
- true
24
+ Utils.save_to_redis(key, value)
26
25
  end
27
26
 
28
27
  def Utils.log_trace_in_redis(request_id, value)
29
28
  key = "trace|#{request_id}"
30
-
31
- # puts " [SAVE] key ---> #{key}\n"
32
- # puts " value ---> #{value.to_json}\n\n"
33
- # pp value
34
-
35
- RP.redis.set(key, value.to_json)
36
- RP.redis.expire(key, RailsPerformance::Reports::RecentRequestsReport::TIME_WINDOW.to_i)
29
+ Utils.save_to_redis(key, value, RailsPerformance::Reports::RecentRequestsReport::TIME_WINDOW.to_i)
37
30
  end
38
31
 
39
32
  def Utils.fetch_from_redis(query)
@@ -64,5 +57,12 @@ module RailsPerformance
64
57
  end
65
58
  end
66
59
 
60
+ def Utils.save_to_redis(key, value, expire = RP.duration.to_i)
61
+ # puts " [SAVE] key ---> #{key}\n"
62
+ # puts " value ---> #{value.to_json}\n\n"
63
+ RP.redis.set(key, value.to_json)
64
+ RP.redis.expire(key, expire.to_i)
65
+ end
66
+
67
67
  end
68
68
  end
@@ -1,3 +1,3 @@
1
1
  module RailsPerformance
2
- VERSION = '0.9.0.1'
2
+ VERSION = '0.9.1'
3
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.9.0.1
4
+ version: 0.9.1
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 00:00:00.000000000 Z
11
+ date: 2020-03-04 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rails
@@ -80,6 +80,20 @@ dependencies:
80
80
  - - ">="
81
81
  - !ruby/object:Gem::Version
82
82
  version: '0'
83
+ - !ruby/object:Gem::Dependency
84
+ name: sidekiq
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - ">="
88
+ - !ruby/object:Gem::Version
89
+ version: '0'
90
+ type: :development
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - ">="
95
+ - !ruby/object:Gem::Version
96
+ version: '0'
83
97
  description: 3rd party dependency-free solution how to monitor performance of your
84
98
  Rails applications.
85
99
  email:
@@ -116,6 +130,7 @@ files:
116
130
  - app/views/rails_performance/javascripts/rails.js
117
131
  - app/views/rails_performance/javascripts/stupidtable.min.js
118
132
  - app/views/rails_performance/javascripts/table.js
133
+ - app/views/rails_performance/jobs.html.erb
119
134
  - app/views/rails_performance/layouts/rails_performance.html.erb
120
135
  - app/views/rails_performance/recent.html.erb
121
136
  - app/views/rails_performance/requests.html.erb
@@ -131,9 +146,12 @@ files:
131
146
  - lib/rails_performance/data_source.rb
132
147
  - lib/rails_performance/engine.rb
133
148
  - lib/rails_performance/extensions/capture_everything.rb
149
+ - lib/rails_performance/gems/sidekiq.rb
134
150
  - lib/rails_performance/instrument/metrics_collector.rb
151
+ - lib/rails_performance/models/base_record.rb
135
152
  - lib/rails_performance/models/collection.rb
136
153
  - lib/rails_performance/models/current_request.rb
154
+ - lib/rails_performance/models/job_record.rb
137
155
  - lib/rails_performance/models/record.rb
138
156
  - lib/rails_performance/rails/middleware.rb
139
157
  - lib/rails_performance/rails/query_builder.rb
@@ -166,7 +184,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
166
184
  - !ruby/object:Gem::Version
167
185
  version: '0'
168
186
  requirements: []
169
- rubygems_version: 3.0.6
187
+ rubyforge_project:
188
+ rubygems_version: 2.7.6.2
170
189
  signing_key:
171
190
  specification_version: 4
172
191
  summary: Simple Rails Performance tracker. Alternative to the NewRelic, Datadog or