rails_performance 1.0.5.3 → 1.2.0.alpha1

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: dffe7a004722639d7873e77a300ca3b62ea1c03d539975170e48a2491892093d
4
- data.tar.gz: ca03875ff577f34febab9fd8c091557790412fb6b5e36bc43c82941340390a68
3
+ metadata.gz: 7b526cdf667201a0ea200a83af542812f0be52724409ce9e2573ca878d2efd06
4
+ data.tar.gz: 26b5591a60b14647cdd713615e1d3e7163e840d1048466deba94241aab762544
5
5
  SHA512:
6
- metadata.gz: b907a6c5ace84663b4527744434c062673140d30d002b0b036542f72b67db1cfba1421b7261148fa0ae4f001491f0123243d21e3f547eef2e96abb67f512c6a3
7
- data.tar.gz: 85eb799be2eaadc0025768eb648db63f2a935dec20c097a2f37aca1b943ee07080adda2a27ee91652eff6cb2f3f317855185d2349c01389953127349217a9f9c
6
+ metadata.gz: 0acf1b56c93e1bfb3085fccf239839a96e92a4f92eb55633fbeaca3371a33427bbcbc97091124c864fb2ca8743a338c33fd77c95ece6d85982c9e276bb12bc5f
7
+ data.tar.gz: b2a8d5c8460c047f0614f6bae5124512e892e21d88f58c45578ce838dfefe16cd8aff3fce1c7838e5061d090e1df88047ea52ec6d8ce38f36346e1ce65d0b82b
data/README.md CHANGED
@@ -14,6 +14,7 @@ This is a **simple and free alternative** to the New Relic APM, Datadog or other
14
14
  It allows you to track:
15
15
 
16
16
  - real-time monitoring on the Recent tab
17
+ - monitor slow requests
17
18
  - throughput report (see amount of RPM (requests per minute))
18
19
  - an average response time
19
20
  - the slowest controllers & actions
@@ -59,7 +60,12 @@ RailsPerformance.setup do |config|
59
60
 
60
61
  # configure Recent tab (time window and limit of requests)
61
62
  # config.recent_requests_time_window = 60.minutes
62
- # config.recent_requests_limit = nil
63
+ # config.recent_requests_limit = nil # or 1000
64
+
65
+ # configure Slow Requests tab (time window, limit of requests and threshold)
66
+ # config.slow_requests_time_window = 4.hours # time window for slow requests
67
+ # config.slow_requests_limit = 500 # number of max rows
68
+ # config.slow_requests_threshold = 500 # number of ms
63
69
 
64
70
  # default path where to mount gem,
65
71
  # alternatively you can mount the RailsPerformance::Engine in your routes.rb
@@ -234,6 +240,9 @@ If "schema" how records are stored i Redis is changed, and this is a breacking c
234
240
  - https://github.com/D1ceWard
235
241
  - https://github.com/carl-printreleaf
236
242
 
243
+ [<img src="https://opensource-heroes.com/svg/embed/igorkasyanchuk/rails_performance"
244
+ />](https://opensource-heroes.com/r/igorkasyanchuk/rails_performance)
245
+
237
246
  ## License
238
247
 
239
248
  The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
@@ -61,6 +61,12 @@ module RailsPerformance
61
61
  end
62
62
  end
63
63
 
64
+ def slow
65
+ @datasource = RailsPerformance::DataSource.new(**prepare_query, type: :requests)
66
+ db = @datasource.db
67
+ @data = RailsPerformance::Reports::SlowRequestsReport.new(db).data
68
+ end
69
+
64
70
  def sidekiq
65
71
  @datasource = RailsPerformance::DataSource.new(**prepare_query, type: :sidekiq)
66
72
  db = @datasource.db
@@ -107,4 +113,4 @@ module RailsPerformance
107
113
  end
108
114
 
109
115
  end
110
- end
116
+ end
@@ -1,5 +1,7 @@
1
1
  module RailsPerformance
2
2
  module ApplicationHelper
3
+ include LocalTimeHelper
4
+
3
5
  def round_it(value, limit = 1)
4
6
  return nil unless value
5
7
  return value if value.is_a?(Integer)
@@ -49,7 +51,7 @@ module RailsPerformance
49
51
 
50
52
  def link_to_path(e)
51
53
  if e[:method] == 'GET'
52
- link_to(short_path(e[:path]), e[:path], target: '_blank')
54
+ link_to(short_path(e[:path]), e[:path], target: '_blank', title: short_path(e[:path]))
53
55
  else
54
56
  short_path(e[:path])
55
57
  end
@@ -105,7 +107,9 @@ module RailsPerformance
105
107
  end
106
108
 
107
109
  def format_datetime(e)
108
- e.strftime("%Y-%m-%d %H:%M:%S")
110
+ #e.strftime("%Y-%m-%d %H:%M:%S")
111
+ # I18n.l(e, format: "%Y-%m-%d %H:%M:%S")
112
+ local_time(e, "%Y-%m-%d %H:%M:%S")
109
113
  end
110
114
 
111
115
  def active?(section)
@@ -118,6 +122,8 @@ module RailsPerformance
118
122
  "is-active" if controller_name == "rails_performance" && action_name == "requests"
119
123
  when :recent
120
124
  "is-active" if controller_name == "rails_performance" && action_name == "recent"
125
+ when :slow
126
+ "is-active" if controller_name == "rails_performance" && action_name == "slow"
121
127
  when :sidekiq
122
128
  "is-active" if controller_name == "rails_performance" && action_name == "sidekiq"
123
129
  when :delayed_job
@@ -1,6 +1,7 @@
1
1
  <%= insert_js_file 'jquery-3.4.1.min.js' %>
2
2
  <%= insert_js_file 'rails.js' %>
3
3
  <%= insert_js_file 'stupidtable.min.js' %>
4
+ <%= insert_js_file 'local-time.es2017-umd.js' %>
4
5
 
5
6
  <%= javascript_include_tag 'https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.12.1/js/all.min.js' %>
6
7
  <%= javascript_include_tag 'https://code.highcharts.com/highcharts.js' %>
@@ -170,6 +170,17 @@ function showRTChart(div, data) {
170
170
  const recent = document.getElementById("recent")
171
171
  const autoupdate = document.getElementById("autoupdate")
172
172
 
173
+ if(autoupdate) {
174
+ // set autoupdate checked from localStorage is missing
175
+ if (localStorage.getItem("autoupdate") === null) {
176
+ localStorage.setItem("autoupdate", "true");
177
+ }
178
+ autoupdate.checked = localStorage.getItem("autoupdate") === "true";
179
+ autoupdate.addEventListener('change', () => {
180
+ localStorage.setItem("autoupdate", autoupdate.checked);
181
+ });
182
+ }
183
+
173
184
  if(recent) {
174
185
  const tbody = recent.querySelector("tbody")
175
186
 
@@ -192,3 +203,5 @@ if(recent) {
192
203
  })
193
204
  }, 3000);
194
205
  }
206
+
207
+ LocalTime.start()
@@ -0,0 +1 @@
1
+ !function(t,e){"object"==typeof exports&&"undefined"!=typeof module?module.exports=e():"function"==typeof define&&define.amd?define(e):(t="undefined"!=typeof globalThis?globalThis:t||self).LocalTime=e()}(this,(function(){"use strict";var t;t={config:{},run:function(){return this.getController().processElements()},process:function(...t){var e,r,a;for(r=0,a=t.length;r<a;r++)e=t[r],this.getController().processElement(e);return t.length},getController:function(){return null!=this.controller?this.controller:this.controller=new t.Controller}};var e,r,a,n,s,i,o,u,l,c,d,m,h,f,g,y,p,v,b,S,M,T,D,E,w,A,N,O,$,C=t;return C.config.i18n={en:{date:{dayNames:["Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"],abbrDayNames:["Sun","Mon","Tue","Wed","Thu","Fri","Sat"],monthNames:["January","February","March","April","May","June","July","August","September","October","November","December"],abbrMonthNames:["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"],yesterday:"yesterday",today:"today",tomorrow:"tomorrow",on:"on {date}",formats:{default:"%b %e, %Y",thisYear:"%b %e"}},time:{am:"am",pm:"pm",singular:"a {time}",singularAn:"an {time}",elapsed:"{time} ago",second:"second",seconds:"seconds",minute:"minute",minutes:"minutes",hour:"hour",hours:"hours",formats:{default:"%l:%M%P"}},datetime:{at:"{date} at {time}",formats:{default:"%B %e, %Y at %l:%M%P %Z"}}}},C.config.locale="en",C.config.defaultLocale="en",C.config.timerInterval=6e4,a=!isNaN(Date.parse("2011-01-01T12:00:00-05:00")),C.parseDate=function(t){return t=t.toString(),a||(t=r(t)),new Date(Date.parse(t))},e=/^(\d{4})-(\d{2})-(\d{2})T(\d{2}):(\d{2}):(\d{2})(Z|[-+]?[\d:]+)$/,r=function(t){var r,a,n,s,i,o,u,l,c,d;if(s=t.match(e))return[r,c,o,a,n,i,l,d]=s,"Z"!==d&&(u=d.replace(":","")),`${c}/${o}/${a} ${n}:${i}:${l} GMT${[u]}`},C.elementMatchesSelector=(n=document.documentElement,s=null!=(i=null!=(o=null!=(u=null!=(l=n.matches)?l:n.matchesSelector)?u:n.webkitMatchesSelector)?o:n.mozMatchesSelector)?i:n.msMatchesSelector,function(t,e){if((null!=t?t.nodeType:void 0)===Node.ELEMENT_NODE)return s.call(t,e)}),({config:c}=C),({i18n:m}=c),C.getI18nValue=function(t="",{locale:e}={locale:c.locale}){var r;return null!=(r=d(m[e],t))?r:e!==c.defaultLocale?C.getI18nValue(t,{locale:c.defaultLocale}):void 0},C.translate=function(t,e={},r){var a,n,s;for(a in s=C.getI18nValue(t,r),e)n=e[a],s=s.replace(`{${a}}`,n);return s},d=function(t,e){var r,a,n,s,i;for(i=t,r=0,n=(s=e.split(".")).length;r<n;r++){if(null==i[a=s[r]])return null;i=i[a]}return i},({getI18nValue:h,translate:p}=C),C.strftime=y=function(t,e){var r,a,n,s,i,o,u;return a=t.getDay(),r=t.getDate(),i=t.getMonth(),u=t.getFullYear(),n=t.getHours(),s=t.getMinutes(),o=t.getSeconds(),e.replace(/%(-?)([%aAbBcdeHIlmMpPSwyYZ])/g,(function(e,l,c){switch(c){case"%":return"%";case"a":return h("date.abbrDayNames")[a];case"A":return h("date.dayNames")[a];case"b":return h("date.abbrMonthNames")[i];case"B":return h("date.monthNames")[i];case"c":return t.toString();case"d":return f(r,l);case"e":return r;case"H":return f(n,l);case"I":return f(y(t,"%l"),l);case"l":return 0===n||12===n?12:(n+12)%12;case"m":return f(i+1,l);case"M":return f(s,l);case"p":return p("time."+(n>11?"pm":"am")).toUpperCase();case"P":return p("time."+(n>11?"pm":"am"));case"S":return f(o,l);case"w":return a;case"y":return f(u%100,l);case"Y":return u;case"Z":return g(t)}}))},f=function(t,e){return"-"===e?t:`0${t}`.slice(-2)},g=function(t){var e,r,a,n,s;return(e=null!=(r=(s=t.toString()).match(/\(([\w\s]+)\)$/))?r[1]:void 0)?/\s/.test(e)?e.match(/\b(\w)/g).join(""):e:(e=null!=(a=s.match(/(\w{3,4})\s\d{4}$/))?a[1]:void 0)||(e=null!=(n=s.match(/(UTC[\+\-]\d+)/))?n[1]:void 0)?e:""},C.CalendarDate=class{static fromDate(t){return new this(t.getFullYear(),t.getMonth()+1,t.getDate())}static today(){return this.fromDate(new Date)}constructor(t,e,r){this.date=new Date(Date.UTC(t,e-1)),this.date.setUTCDate(r),this.year=this.date.getUTCFullYear(),this.month=this.date.getUTCMonth()+1,this.day=this.date.getUTCDate(),this.value=this.date.getTime()}equals(t){return(null!=t?t.value:void 0)===this.value}is(t){return this.equals(t)}isToday(){return this.is(this.constructor.today())}occursOnSameYearAs(t){return this.year===(null!=t?t.year:void 0)}occursThisYear(){return this.occursOnSameYearAs(this.constructor.today())}daysSince(t){if(t)return(this.date-t.date)/864e5}daysPassed(){return this.constructor.today().daysSince(this)}},({strftime:b,translate:S,getI18nValue:v}=C),C.RelativeTime=class{constructor(t){this.date=t,this.calendarDate=C.CalendarDate.fromDate(this.date)}toString(){var t,e;return(e=this.toTimeElapsedString())?S("time.elapsed",{time:e}):(t=this.toWeekdayString())?(e=this.toTimeString(),S("datetime.at",{date:t,time:e})):S("date.on",{date:this.toDateString()})}toTimeOrDateString(){return this.calendarDate.isToday()?this.toTimeString():this.toDateString()}toTimeElapsedString(){var t,e,r,a,n;return r=(new Date).getTime()-this.date.getTime(),a=Math.round(r/1e3),e=Math.round(a/60),t=Math.round(e/60),r<0?null:a<10?(n=S("time.second"),S("time.singular",{time:n})):a<45?`${a} ${S("time.seconds")}`:a<90?(n=S("time.minute"),S("time.singular",{time:n})):e<45?`${e} ${S("time.minutes")}`:e<90?(n=S("time.hour"),S("time.singularAn",{time:n})):t<24?`${t} ${S("time.hours")}`:""}toWeekdayString(){switch(this.calendarDate.daysPassed()){case 0:return S("date.today");case 1:return S("date.yesterday");case-1:return S("date.tomorrow");case 2:case 3:case 4:case 5:case 6:return b(this.date,"%A");default:return""}}toDateString(){var t;return t=this.calendarDate.occursThisYear()?v("date.formats.thisYear"):v("date.formats.default"),b(this.date,t)}toTimeString(){return b(this.date,v("time.formats.default"))}},({elementMatchesSelector:M}=C),C.PageObserver=class{constructor(t,e){this.processMutations=this.processMutations.bind(this),this.processInsertion=this.processInsertion.bind(this),this.selector=t,this.callback=e}start(){if(!this.started)return this.observeWithMutationObserver()||this.observeWithMutationEvent(),this.started=!0}observeWithMutationObserver(){if("undefined"!=typeof MutationObserver&&null!==MutationObserver)return new MutationObserver(this.processMutations).observe(document.documentElement,{childList:!0,subtree:!0}),!0}observeWithMutationEvent(){return addEventListener("DOMNodeInserted",this.processInsertion,!1),!0}findSignificantElements(t){var e;return e=[],(null!=t?t.nodeType:void 0)===Node.ELEMENT_NODE&&(M(t,this.selector)&&e.push(t),e.push(...t.querySelectorAll(this.selector))),e}processMutations(t){var e,r,a,n,s,i,o,u;for(e=[],r=0,n=t.length;r<n;r++)if("childList"===(i=t[r]).type)for(a=0,s=(u=i.addedNodes).length;a<s;a++)o=u[a],e.push(...this.findSignificantElements(o));return this.notify(e)}processInsertion(t){var e;return e=this.findSignificantElements(t.target),this.notify(e)}notify(t){if(null!=t?t.length:void 0)return"function"==typeof this.callback?this.callback(t):void 0}},({parseDate:E,strftime:w,getI18nValue:D,config:T}=C),C.Controller=function(){var t,e,r;return t="time[data-local]:not([data-localized])",e=function(t){return t.setAttribute("data-localized","")},r=function(t){return new C.RelativeTime(t)},class{constructor(){this.processElements=this.processElements.bind(this),this.pageObserver=new C.PageObserver(t,this.processElements)}start(){if(!this.started)return this.processElements(),this.startTimer(),this.pageObserver.start(),this.started=!0}startTimer(){var t;if(t=T.timerInterval)return null!=this.timer?this.timer:this.timer=setInterval(this.processElements,t)}processElements(e=document.querySelectorAll(t)){var r,a,n;for(a=0,n=e.length;a<n;a++)r=e[a],this.processElement(r);return e.length}processElement(t){var a,n,s,i,o,u;if(n=t.getAttribute("datetime"),s=t.getAttribute("data-format"),i=t.getAttribute("data-local"),o=E(n),!isNaN(o))return t.hasAttribute("title")||(u=w(o,D("datetime.formats.default")),t.setAttribute("title",u)),t.textContent=a=function(){switch(i){case"time":return e(t),w(o,s);case"date":return e(t),r(o).toDateString();case"time-ago":return r(o).toString();case"time-or-date":return r(o).toTimeOrDateString();case"weekday":return r(o).toWeekdayString();case"weekday-or-date":return r(o).toWeekdayString()||r(o).toDateString()}}(),t.hasAttribute("aria-label")?void 0:t.setAttribute("aria-label",a)}}}.call(window),$=!1,A=function(){return document.attachEvent?"complete"===document.readyState:"loading"!==document.readyState},N=function(t){var e;return null!=(e="function"==typeof requestAnimationFrame?requestAnimationFrame(t):void 0)?e:setTimeout(t,17)},O=function(){return C.getController().start()},C.start=function(){if(!$)return $=!0,"undefined"!=typeof MutationObserver&&null!==MutationObserver||A()?O():N(O)},window.LocalTime===C&&C.start(),C}));
@@ -7,7 +7,10 @@
7
7
  <% end %>
8
8
  </td>
9
9
  <td><%= format_datetime e[:datetime] %></td>
10
- <td><%= link_to e[:controller] + '#' + e[:action], rails_performance.rails_performance_summary_path({controller_eq: e[:controller], action_eq: e[:action]}), remote: true %></td>
10
+ <td>
11
+ <% controller_action_info = e[:controller] + '#' + e[:action]%>
12
+ <%= link_to truncate(controller_action_info, length: 40), rails_performance.rails_performance_summary_path({controller_eq: e[:controller], action_eq: e[:action]}), remote: true, title: controller_action_info %>
13
+ </td>
11
14
  <td><%= e[:method] %></td>
12
15
  <td><%= e[:format] %></td>
13
16
  <td><%= link_to_path(e) %></td>
@@ -22,4 +25,4 @@
22
25
  <% end %>
23
26
  <% end %>
24
27
  </td>
25
- </tr>
28
+ </tr>
@@ -19,5 +19,11 @@
19
19
  <% end %>
20
20
  </tr>
21
21
  <% end %>
22
+
23
+ <% if @data.empty? %>
24
+ <tr>
25
+ <td>Nothing to show here. Perphaps details about the requests already expired. Setting "slow_requests_time_window" should be equal to "duration".</td>
26
+ </td>
27
+ <% end %>
22
28
  </tbody>
23
29
  </table>
@@ -8,7 +8,7 @@
8
8
  </div>
9
9
  <div class="column right-text is-size-5 has-text-right">
10
10
  <label id="autoupdate_label">
11
- <input id="autoupdate" type="checkbox" checked/>
11
+ <input id="autoupdate" type="checkbox"/>
12
12
  Auto-update
13
13
  </label>
14
14
  </div>
@@ -0,0 +1,39 @@
1
+ <title>Slow Requests</title>
2
+
3
+ <div class="card">
4
+ <div class="card-content">
5
+ <div class="columns">
6
+ <div class="column">
7
+ <h2 class="subtitle">Slow Requests (last <%= RailsPerformance.slow_requests_time_window / 60 %> minutes + slower then <%= RailsPerformance.slow_requests_threshold %>ms)<h2>
8
+ </div>
9
+ </div>
10
+
11
+ <table id="recent" class="table is-fullwidth is-hoverable is-narrow">
12
+ <thead>
13
+ <tr>
14
+ <th data-sort="string"></th>
15
+ <th data-sort="string">Datetime</th>
16
+ <th data-sort="string">Controller#action</th>
17
+ <th data-sort="string">Method</th>
18
+ <th data-sort="string">Format</th>
19
+ <th data-sort="string">Path</th>
20
+ <th data-sort="string">Status</th>
21
+ <th data-sort="float">Duration</th>
22
+ <th data-sort="float">Views</th>
23
+ <th data-sort="float">DB</th>
24
+ <th></th>
25
+ </tr>
26
+ </thead>
27
+ <tbody>
28
+ <% if @data.empty? %>
29
+ <tr>
30
+ <td colspan="10">Nothing to show here. Try to make a few requests in the main app.</td>
31
+ </tr>
32
+ <% end %>
33
+ <% @data.each do |e| %>
34
+ <%= render 'recent_row', e: e %>
35
+ <% end %>
36
+ </tbody>
37
+ </table>
38
+ </div>
39
+ </div>
@@ -18,6 +18,7 @@
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
+ <%= link_to 'Slow Requests', rails_performance.rails_performance_slow_url, class: "navbar-item #{active?(:slow)}" %>
21
22
  <% if defined?(Sidekiq) %>
22
23
  <%= link_to 'Sidekiq', rails_performance.rails_performance_sidekiq_url, class: "navbar-item #{active?(:sidekiq)}" %>
23
24
  <% end %>
data/config/routes.rb CHANGED
@@ -4,6 +4,7 @@ RailsPerformance::Engine.routes.draw do
4
4
  get '/requests' => 'rails_performance#requests', as: :rails_performance_requests
5
5
  get '/crashes' => 'rails_performance#crashes', as: :rails_performance_crashes
6
6
  get '/recent' => 'rails_performance#recent', as: :rails_performance_recent
7
+ get '/slow' => 'rails_performance#slow', as: :rails_performance_slow
7
8
 
8
9
  get '/trace/:id' => 'rails_performance#trace', as: :rails_performance_trace
9
10
  get '/summary' => 'rails_performance#summary', as: :rails_performance_summary
@@ -20,8 +20,8 @@ module RailsPerformance
20
20
 
21
21
  def db
22
22
  result = RailsPerformance::Models::Collection.new
23
- (RailsPerformance::Utils.days + 1).times do |e|
24
- RailsPerformance::DataSource.new(q: self.q.merge({ on: e.days.ago.to_date }), type: type).add_to(result)
23
+ (0..(RailsPerformance::Utils.days + 1)).to_a.reverse.each do |e|
24
+ RailsPerformance::DataSource.new(q: self.q.merge({ on: (Time.now - e.days).to_date }), type: type).add_to(result)
25
25
  end
26
26
  result
27
27
  end
@@ -118,4 +118,4 @@ module RailsPerformance
118
118
  end
119
119
 
120
120
  end
121
- end
121
+ end
@@ -55,7 +55,7 @@ module RailsPerformance
55
55
  next unless RailsPerformance.enabled
56
56
 
57
57
  ActionView::LogSubscriber.send :prepend, RailsPerformance::Extensions::View
58
- ActiveRecord::LogSubscriber.send :prepend, RailsPerformance::Extensions::Db
58
+ ActiveRecord::LogSubscriber.send :prepend, RailsPerformance::Extensions::Db if defined?(ActiveRecord)
59
59
 
60
60
  if defined?(::Rake::Task)
61
61
  require_relative './gems/rake_ext.rb'
@@ -30,4 +30,4 @@ module RailsPerformance
30
30
 
31
31
  end
32
32
  end
33
- end
33
+ end
@@ -10,7 +10,7 @@ module RailsPerformance
10
10
  stop = Time.at(60 * (Time.now.to_i / 60))
11
11
  current = stop - RailsPerformance.duration
12
12
  @data = []
13
- offset = Time.current.utc_offset
13
+ offset = Time.now.utc_offset
14
14
 
15
15
  # puts "current: #{current}"
16
16
  # puts "stop: #{stop}"
@@ -34,4 +34,4 @@ module RailsPerformance
34
34
  end
35
35
  end
36
36
  end
37
- end
37
+ end
@@ -0,0 +1,24 @@
1
+ module RailsPerformance
2
+ module Reports
3
+ class SlowRequestsReport < BaseReport
4
+ def set_defaults
5
+ @sort ||= :datetimei
6
+ end
7
+
8
+ def data
9
+ db.data
10
+ .collect{|e| e.record_hash}
11
+ .select{|e| e if e[sort] > RailsPerformance.slow_requests_time_window.ago.to_i}
12
+ .sort{|a, b| b[sort] <=> a[sort]}
13
+ .filter{|e| e[:duration] > RailsPerformance.slow_requests_threshold.to_i}
14
+ .first(limit)
15
+ end
16
+
17
+ private
18
+
19
+ def limit
20
+ RailsPerformance.slow_requests_limit ? RailsPerformance.slow_requests_limit.to_i : 100_000
21
+ end
22
+ end
23
+ end
24
+ end
@@ -11,7 +11,7 @@ module RailsPerformance
11
11
  stop = Time.at(60 * (Time.now.to_i / 60))
12
12
  current = stop - RailsPerformance.duration
13
13
  @data = []
14
- offset = Time.current.utc_offset
14
+ offset = Time.now.utc_offset
15
15
 
16
16
  # puts "current: #{current}"
17
17
  # puts "stop: #{stop}"
@@ -34,4 +34,4 @@ module RailsPerformance
34
34
 
35
35
  end
36
36
  end
37
- end
37
+ end
@@ -31,4 +31,4 @@ module RailsPerformance
31
31
  end
32
32
 
33
33
  end
34
- end
34
+ end
@@ -1,4 +1,4 @@
1
1
  module RailsPerformance
2
- VERSION = '1.0.5.3'
2
+ VERSION = '1.2.0.alpha1'
3
3
  SCHEMA = '1.0.1'
4
4
  end
@@ -1,5 +1,6 @@
1
1
  require "redis"
2
2
  require "redis-namespace"
3
+ require "local_time"
3
4
  require_relative "./rails_performance/version.rb"
4
5
  require_relative "rails_performance/rails/query_builder.rb"
5
6
  require_relative "rails_performance/rails/middleware.rb"
@@ -19,6 +20,7 @@ require_relative "rails_performance/reports/crash_report.rb"
19
20
  require_relative "rails_performance/reports/response_time_report.rb"
20
21
  require_relative "rails_performance/reports/throughput_report.rb"
21
22
  require_relative "rails_performance/reports/recent_requests_report.rb"
23
+ require_relative "rails_performance/reports/slow_requests_report.rb"
22
24
  require_relative "rails_performance/reports/breakdown_report.rb"
23
25
  require_relative "rails_performance/reports/trace_report.rb"
24
26
  require_relative "rails_performance/extensions/trace.rb"
@@ -39,6 +41,15 @@ module RailsPerformance
39
41
  mattr_accessor :recent_requests_limit
40
42
  @@recent_requests_limit = nil
41
43
 
44
+ mattr_accessor :slow_requests_time_window
45
+ @@slow_requests_time_window = 4.hours
46
+
47
+ mattr_accessor :slow_requests_limit
48
+ @@recent_requests_limit = 500
49
+
50
+ mattr_accessor :slow_requests_threshold
51
+ @@slow_requests_threshold = 500
52
+
42
53
  mattr_accessor :debug
43
54
  @@debug = false
44
55
 
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: 1.0.5.3
4
+ version: 1.2.0.alpha1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Igor Kasyanchuk
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2023-06-11 00:00:00.000000000 Z
11
+ date: 2023-06-24 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rails
@@ -52,6 +52,20 @@ dependencies:
52
52
  - - ">="
53
53
  - !ruby/object:Gem::Version
54
54
  version: '0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: local_time
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ type: :runtime
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ">="
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
55
69
  - !ruby/object:Gem::Dependency
56
70
  name: sqlite3
57
71
  requirement: !ruby/object:Gem::Requirement
@@ -234,6 +248,7 @@ files:
234
248
  - app/views/rails_performance/javascripts/_javascripts.html.erb
235
249
  - app/views/rails_performance/javascripts/app.js
236
250
  - app/views/rails_performance/javascripts/jquery-3.4.1.min.js
251
+ - app/views/rails_performance/javascripts/local-time.es2017-umd.js
237
252
  - app/views/rails_performance/javascripts/navbar.js
238
253
  - app/views/rails_performance/javascripts/panel.js
239
254
  - app/views/rails_performance/javascripts/rails.js
@@ -253,6 +268,7 @@ files:
253
268
  - app/views/rails_performance/rails_performance/recent.js.erb
254
269
  - app/views/rails_performance/rails_performance/requests.html.erb
255
270
  - app/views/rails_performance/rails_performance/sidekiq.html.erb
271
+ - app/views/rails_performance/rails_performance/slow.html.erb
256
272
  - app/views/rails_performance/rails_performance/summary.js.erb
257
273
  - app/views/rails_performance/rails_performance/trace.js.erb
258
274
  - app/views/rails_performance/shared/_header.html.erb
@@ -292,6 +308,7 @@ files:
292
308
  - lib/rails_performance/reports/recent_requests_report.rb
293
309
  - lib/rails_performance/reports/requests_report.rb
294
310
  - lib/rails_performance/reports/response_time_report.rb
311
+ - lib/rails_performance/reports/slow_requests_report.rb
295
312
  - lib/rails_performance/reports/throughput_report.rb
296
313
  - lib/rails_performance/reports/trace_report.rb
297
314
  - lib/rails_performance/thread/current_request.rb
@@ -312,11 +329,11 @@ required_ruby_version: !ruby/object:Gem::Requirement
312
329
  version: '0'
313
330
  required_rubygems_version: !ruby/object:Gem::Requirement
314
331
  requirements:
315
- - - ">="
332
+ - - ">"
316
333
  - !ruby/object:Gem::Version
317
- version: '0'
334
+ version: 1.3.1
318
335
  requirements: []
319
- rubygems_version: 3.4.10
336
+ rubygems_version: 3.4.13
320
337
  signing_key:
321
338
  specification_version: 4
322
339
  summary: Simple Rails Performance tracker. Alternative to the NewRelic, Datadog or