rails_performance 0.0.1.19 → 0.9.0

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: 56c91669685f1dc4c4ee8830b921acde7a98642b7065c9ffbcb939fca355abcf
4
- data.tar.gz: 14d2bb35561e4af0a563791ae4efdae812e98235c7e692cf735346f4bd61e8f4
3
+ metadata.gz: fe073c7658af65303c6efc61dbaa973edba22d21c2991e715d523b6f4c96dc5f
4
+ data.tar.gz: bf7780ef55eab59d2974b990eba4e2afad26b78683f685fb8383b4df4d8ada30
5
5
  SHA512:
6
- metadata.gz: a9ab71a3a5140b1c1d403f08a6fe5c36a023b3c5839ed88b3976d0e35315364a7b335b5ec17b007b5fd2bf32067a1a7f687b6e8e356e44bd8ecd9d85af061162
7
- data.tar.gz: 7c956c17f1e3b4b24f715331c1df68afb8ea9f2a45876a6a8bf1bd097a17982035a2de528d18a7a7ca5becd63c06a0e6edd50aa7ee2f20e129c2c5a4acaee8fd
6
+ metadata.gz: b223eb60dc1dc48c64a577d39d2bf34073ff916d0b73ad5f507a74bedc0f9a2aa5af5cc33ec9bc063b12cc441a572f99d4e8c68362935f74f2f9084c6d8b6ca0
7
+ data.tar.gz: 7b030743ca075f02c38b4448ec0c1ad369a09d094dc381aba5c834c40ee245ccfe9511c939fa7d08e0e42d253c9b06817d4b6bc7d80c6b9d5f8bab7835472e7e
data/README.md CHANGED
@@ -6,11 +6,12 @@ This is **simple and free alternative** to New Relic, Datadog or other similar s
6
6
 
7
7
  It allows you to track:
8
8
 
9
- - throughput report (see amount of requests per minute)
9
+ - throughput report (see amount of RPM (requests per minute))
10
10
  - an average response time
11
11
  - the slowest controllers & actions
12
- - duration of total time spent per request, views rendering, DB execution
13
- - simple crash reports
12
+ - total duration of time spent per request, views rendering, DB
13
+ - SQL queries, rendering log in recent requests
14
+ - simple 500-crashes reports
14
15
 
15
16
  All data is stored in local Redis and not sent to 3rd party servers.
16
17
 
@@ -83,6 +84,8 @@ Like a regular web development.
83
84
 
84
85
  Please note that to simplify integration with other apps all CSS/JS are bundled inside, and delivered in body of the request. This is to avoid integration with assets pipeline or webpacker.
85
86
 
87
+ For UI changes you need to use Bulma CSS (https://bulma.io/documentation).
88
+
86
89
  ## Why
87
90
 
88
91
  The idea of this gem grew from curriosity how many RPM my app receiving per day. Later it evolutionated to something more powerful.
@@ -91,27 +94,20 @@ The idea of this gem grew from curriosity how many RPM my app receiving per day.
91
94
 
92
95
  - documentation in Readme
93
96
  - generator for initial config
94
- - gif with demo
95
- - time/zone config?
96
97
  - CI for tests
97
- - connected charts
98
- - ability to zoom to see requests withing specific datime range
99
- - better hint
98
+ - time/zone config?
99
+ - connected charts on dashboard, when zoom, when hover?
100
+ - ability to zoom to see requests withing specific datetime range
101
+ - better hints?
100
102
  - export to csv
101
- - http basic auth config
102
- - current_user auth config
103
103
  - better stats tooltip, do not show if nothing to show
104
- - dark mode toggle? save to the cookies
105
- - integration with elastic search
104
+ - dark mode toggle? save to the cookies?
105
+ - integration with elastic search? or other?
106
106
  - monitor active job (sidekiq)?
107
- - logo?
107
+ - better logo?
108
108
  - number of requests last 24 hours, hour, etc.
109
- - integration with logger, to see the details of request?
110
- - no results if empty table (on crash page)
111
- - capture referal for 404 page?
112
- - SQL
113
- - Rendering
114
- - scroll to the top details
109
+ - collect deprecation.rails
110
+ - fix misspellings?
115
111
 
116
112
  ## Contributing
117
113
 
@@ -34,6 +34,7 @@ class RailsPerformanceController < BaseController
34
34
  end
35
35
 
36
36
  def trace
37
+ @record = RP::Models::Record.find_by(request_id: params[:id])
37
38
  @report = RP::Reports::TraceReport.new(request_id: params[:id])
38
39
  @data = @report.data
39
40
  respond_to do |format|
@@ -6,6 +6,29 @@ module RailsPerformanceHelper
6
6
  value.nan? ? nil : value.round(1)
7
7
  end
8
8
 
9
+ def duraction_alert_class(duration_str)
10
+ if duration_str.to_s =~ /(\d+.?\d+?)/
11
+ duration = $1.to_f
12
+ if duration >= 100
13
+ 'has-background-danger has-text-white-bis'
14
+ elsif duration >= 200
15
+ 'has-background-warning has-text-black-ter'
16
+ else
17
+ 'has-background-success has-text-white-bis'
18
+ end
19
+ else
20
+ 'has-background-light'
21
+ end
22
+ end
23
+
24
+ def extract_duration(str)
25
+ if (str =~ /Duration: (\d+.?\d+?ms)/i)
26
+ $1
27
+ else
28
+ '-'
29
+ end
30
+ end
31
+
9
32
  def ms(value)
10
33
  result = round_it(value)
11
34
  result && result != 0 ? "#{result} ms" : '-'
@@ -27,14 +50,16 @@ module RailsPerformanceHelper
27
50
 
28
51
  def report_name(h)
29
52
  h.except(:on).collect do |k, v|
53
+ next if v.blank?
54
+
30
55
  %Q{
31
56
  <div class="control">
32
57
  <span class="tags has-addons">
33
58
  <span class="tag">#{k}</span>
34
- <span class="tag is-success">#{v}</span>
59
+ <span class="tag is-info is-light">#{v}</span>
35
60
  </span>
36
61
  </div>}
37
- end.join.html_safe
62
+ end.compact.join.html_safe
38
63
  end
39
64
 
40
65
  def status_tag(status)
@@ -2,16 +2,17 @@
2
2
  <tbody>
3
3
  <% @data.each do |e| %>
4
4
  <tr>
5
- <td><%= e["group"] %></td>
6
5
  <% if e["group"] == 'db' %>
7
- <td class="nowrap">
6
+ <td class="nowrap has-text-right <%= duraction_alert_class(e['duration']) %>">
8
7
  <%= e["duration"] %> ms
9
8
  </td>
10
9
  <td>
11
10
  <%= e["sql"] %>
12
11
  </td>
13
12
  <% elsif e["group"] == 'view' %>
14
- <td>-</td>
13
+ <td class="nowrap has-text-right <%= duraction_alert_class(extract_duration(e['message'])) %>">
14
+ <%= extract_duration(e["message"]) %>
15
+ </td>
15
16
  <td>
16
17
  <%= e["message"] %>
17
18
  </td>
@@ -19,4 +20,6 @@
19
20
  </tr>
20
21
  <% end %>
21
22
  </tbody>
22
- </table>
23
+ </table>
24
+
25
+ <br/>
@@ -16,6 +16,12 @@
16
16
  </tr>
17
17
  </thead>
18
18
  <tbody>
19
+ <% if @data.empty? %>
20
+ <tr>
21
+ <td colspan="9">We are glad that this list is empty ;)</td>
22
+ </tr>
23
+ <% end %>
24
+
19
25
  <% @data.each do |e| %>
20
26
  <tr>
21
27
  <td><%= format_datetime e[:datetime] %></td>
@@ -1,7 +1,7 @@
1
1
  <div class="card">
2
2
  <div class="card-content">
3
3
 
4
- <h2 class="subtitle">Recent Requests (last <%= RailsPerformance::Reports::RecentRequestsReport::TIME_WINDOW %> minutes)<h2>
4
+ <h2 class="subtitle">Recent Requests (last <%= RailsPerformance::Reports::RecentRequestsReport::TIME_WINDOW / 60 %> minutes)<h2>
5
5
 
6
6
  <table class="table is-fullwidth is-hoverable is-narrow">
7
7
  <thead>
@@ -19,6 +19,11 @@
19
19
  </tr>
20
20
  </thead>
21
21
  <tbody>
22
+ <% if @data.empty? %>
23
+ <tr>
24
+ <td colspan="10">Nothing to show here. Try to make a few requests in main app.</td>
25
+ </tr>
26
+ <% end %>
22
27
  <% @data.each do |e| %>
23
28
  <tr>
24
29
  <td><%= format_datetime e[:datetime] %></td>
@@ -1,4 +1,9 @@
1
- window.panel.header.html(window.panel.close);
1
+ <% if @record %>
2
+ window.panel.header.html(window.panel.close + "<%= j report_name(@record.to_h) %>");
3
+ <% else %>
4
+ window.panel.header.html(window.panel.close);
5
+ <% end %>
6
+
2
7
  window.panel.content.html("<%= j render '/rails_performance/trace' %>");
3
8
 
4
9
  showPanel();
@@ -5,8 +5,10 @@ require_relative './instrument/metrics_collector.rb'
5
5
  module RailsPerformance
6
6
  class Engine < ::Rails::Engine
7
7
 
8
- if RailsPerformance.enabled
8
+ if RailsPerformance.try(:enabled) # for rails c
9
+
9
10
  config.app_middleware.insert_after ActionDispatch::Executor, RailsPerformance::Rails::Middleware
11
+
10
12
  initializer :configure_metrics, after: :initialize_logger do
11
13
  ActiveSupport::Notifications.subscribe(
12
14
  "process_action.action_controller",
@@ -17,7 +19,9 @@ module RailsPerformance
17
19
  ActionView::LogSubscriber.send :prepend, RailsPerformance::Extensions::View
18
20
  ActiveRecord::LogSubscriber.send :prepend, RailsPerformance::Extensions::Db
19
21
  end
22
+
20
23
  end
24
+
21
25
  end
22
26
 
23
27
  end
@@ -18,6 +18,8 @@ module RailsPerformance
18
18
  def call(event_name, started, finished, event_id, payload)
19
19
  event = ActiveSupport::Notifications::Event.new(event_name, started, finished, event_id, payload)
20
20
 
21
+ return if event.payload[:path] =~ /^\/rails\/performance/
22
+
21
23
  record = {
22
24
  controller: event.payload[:controller],
23
25
  action: event.payload[:action],
@@ -32,7 +34,7 @@ module RailsPerformance
32
34
  duration: event.duration
33
35
  }
34
36
 
35
- Thread.current["RP_request_info"] = record
37
+ CurrentRequest.current.record = record
36
38
  end
37
39
  end
38
40
  end
@@ -1,6 +1,7 @@
1
1
  module RailsPerformance
2
2
  class CurrentRequest
3
3
  attr_reader :request_id, :storage
4
+ attr_accessor :record
4
5
 
5
6
  def CurrentRequest.init
6
7
  Thread.current[:rp_current_request] ||= CurrentRequest.new(SecureRandom.hex(16))
@@ -17,6 +18,7 @@ module RailsPerformance
17
18
  def initialize(request_id)
18
19
  @request_id = request_id
19
20
  @storage = []
21
+ @record = nil
20
22
  end
21
23
 
22
24
  def store(options = {})
@@ -3,6 +3,16 @@ module RailsPerformance
3
3
  class Record
4
4
  attr_reader :controller, :action, :format, :status, :datetime, :datetimei, :method, :path, :request_id
5
5
 
6
+
7
+ def Record.find_by(request_id:)
8
+ keys, values = RP::Utils.fetch_from_redis("performance|*|request_id|#{request_id}|*")
9
+
10
+ return nil if keys.blank?
11
+ return nil if values.blank?
12
+
13
+ RP::Models::Record.new(keys[0], values[0])
14
+ end
15
+
6
16
  # key = performance|
7
17
  # controller|HomeController|
8
18
  # action|index|
@@ -43,6 +53,31 @@ module RailsPerformance
43
53
  def controller_action_format
44
54
  "#{controller}##{action}|#{format}"
45
55
  end
56
+
57
+ def to_h
58
+ {
59
+ controller: controller,
60
+ action: action,
61
+ format: format,
62
+ method: method,
63
+ path: path,
64
+ duration: ms(value['duration']),
65
+ view_runtime: ms(value['view_runtime']),
66
+ db_runtime: ms(value['db_runtime']),
67
+ HTTP_REFERER: value['HTTP_REFERER']
68
+ }
69
+ end
70
+
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
+
46
81
  end
47
82
  end
48
83
  end
@@ -8,17 +8,28 @@ module RailsPerformance
8
8
  def call(env)
9
9
  @status, @headers, @response = @app.call(env)
10
10
 
11
- if record = Thread.current["RP_request_info"]
11
+ #t = Time.now
12
+ if record = CurrentRequest.current.record
12
13
  begin
13
- record[:status] ||= @status
14
+ record[:status] ||= @status # for 500 errors
14
15
  record[:request_id] = CurrentRequest.current.request_id
16
+
17
+ # capture referer from where this page was opened
18
+ if record[:status] == 404
19
+ record[:HTTP_REFERER] = env["HTTP_REFERER"]
20
+ end
21
+
22
+ # store for section "recent requests"
15
23
  RP::Utils.log_trace_in_redis(CurrentRequest.current.request_id, CurrentRequest.current.storage)
24
+
25
+ # store request information
16
26
  RP::Utils.log_request_in_redis(record)
17
27
  ensure
18
- Thread.current["RP_request_info"] = nil
28
+ # we don't want to have a memory leak
19
29
  CurrentRequest.cleanup
20
30
  end
21
31
  end
32
+ #puts "==> store performance data: #{(Time.now - t).round(3)}ms"
22
33
 
23
34
  [@status, @headers, @response]
24
35
  end
@@ -13,7 +13,7 @@ module RailsPerformance
13
13
  end
14
14
 
15
15
  def Utils.log_request_in_redis(e)
16
- value = e.slice(:view_runtime, :db_runtime, :duration)
16
+ value = e.slice(:view_runtime, :db_runtime, :duration, :HTTP_REFERER)
17
17
  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
18
 
19
19
  # puts " [SAVE] key ---> #{key}\n"
@@ -1,3 +1,3 @@
1
1
  module RailsPerformance
2
- VERSION = '0.0.1.19'
3
- end
2
+ VERSION = '0.9.0'
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.0.1.19
4
+ version: 0.9.0
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-10 00:00:00.000000000 Z
11
+ date: 2020-02-11 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rails