rails_performance 0.9.0.1 → 0.9.1

Sign up to get free protection for your applications and to get access to all the features.
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