rails_performance 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 92b728bc962cef29c1e505e925bd149da93a27e97ae1663ee694bf08109d6681
4
+ data.tar.gz: 5188f58ab04ad5172fa4c18e320f938e829baf5e48bd4ce0eb6b6f9fe1862d60
5
+ SHA512:
6
+ metadata.gz: 8ea76771978cc52ba1411379c9d71d5abdb617d20718c7bcefa39a4ff9d6f27cfc91f5ca8fe335cf57b469458d00d460fc1034a7a1612876dce14b41ceb0c5e5
7
+ data.tar.gz: c27e7c74b92c6e91299f76dedbb5c7e776f7929c71695030a6b21216ca3d55acc39dd9e95bf51b02973a90704c853fa8a29f21b6ed52a4efa2e38e0bf3f2c8d2
data/MIT-LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright 2020 Igor Kasyanchuk
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,43 @@
1
+ # RailsPerformance
2
+
3
+ Short description and motivation.
4
+
5
+ ## Usage
6
+
7
+ Create `config/initializers/rails_performance.rb`
8
+
9
+ ```ruby
10
+ RailsPerformance.setup do |config|
11
+ config.redis = Redis.new
12
+ config.days = 3
13
+ end
14
+ ```
15
+
16
+ ## Installation
17
+ Add this line to your application's Gemfile:
18
+
19
+ ```ruby
20
+ gem 'rails_performance'
21
+ ```
22
+
23
+ And then execute:
24
+ ```bash
25
+ $ bundle
26
+ ```
27
+
28
+ ## TODO
29
+
30
+ - time/zone
31
+ - redis namespaces
32
+ - skip for tests ?
33
+ - documentation
34
+ - add 1 if 0 (it means one request was)
35
+ - better hint
36
+
37
+ ## Contributing
38
+
39
+ You are welcome to contribute.
40
+
41
+ ## License
42
+
43
+ The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
data/Rakefile ADDED
@@ -0,0 +1,32 @@
1
+ begin
2
+ require 'bundler/setup'
3
+ rescue LoadError
4
+ puts 'You must `gem install bundler` and `bundle install` to run rake tasks'
5
+ end
6
+
7
+ require 'rdoc/task'
8
+
9
+ RDoc::Task.new(:rdoc) do |rdoc|
10
+ rdoc.rdoc_dir = 'rdoc'
11
+ rdoc.title = 'RailsPerformance'
12
+ rdoc.options << '--line-numbers'
13
+ rdoc.rdoc_files.include('README.md')
14
+ rdoc.rdoc_files.include('lib/**/*.rb')
15
+ end
16
+
17
+ APP_RAKEFILE = File.expand_path("test/dummy/Rakefile", __dir__)
18
+ load 'rails/tasks/engine.rake'
19
+
20
+ load 'rails/tasks/statistics.rake'
21
+
22
+ require 'bundler/gem_tasks'
23
+
24
+ require 'rake/testtask'
25
+
26
+ Rake::TestTask.new(:test) do |t|
27
+ t.libs << 'test'
28
+ t.pattern = 'test/**/*_test.rb'
29
+ t.verbose = false
30
+ end
31
+
32
+ task default: :test
File without changes
@@ -0,0 +1,25 @@
1
+ class RailsPerformanceController < ActionController::Base
2
+
3
+ def index
4
+ @datasource = RailsPerformance::DataSource.new(
5
+ q: {
6
+ # controller: "HomeController",
7
+ # action: "about"
8
+ })
9
+
10
+ @data = RailsPerformance::ThroughputReport.new(@datasource.db).data
11
+ @global = RailsPerformance::RequestsReport.new(@datasource.db, group: :controller_action_format).data
12
+ #@full = RailsPerformance::FullReport.new.data(:controller_action).sort{|a, b| b[:count] <=> a[:count]}
13
+ end
14
+
15
+ # def RailsPerformanceController.x
16
+ # @datasource = RailsPerformance::DataSource.new(
17
+ # q: {
18
+ # controller: "HomeController",
19
+ # action: "about"
20
+ # })
21
+
22
+ # @data = RailsPerformance::ThroughputReport2.new(@datasource).data
23
+ # end
24
+
25
+ end
@@ -0,0 +1,106 @@
1
+ <link href="https://fonts.googleapis.com/css?family=Open+Sans&display=swap" rel="stylesheet">
2
+
3
+ <style>
4
+ body {
5
+ font-family: OpenSans, sans-serif;
6
+ margin: 0;
7
+ font-size: .8125rem;
8
+ font-weight: 400;
9
+ line-height: 1.5;
10
+ color: #a6b0cf;
11
+ text-align: left;
12
+ background-color: #282e38;
13
+ background: linear-gradient(45deg, #282e38, #382e38);
14
+ display: flex;
15
+ width: 100%;
16
+ flex-direction: column;
17
+ align-items: center;
18
+ }
19
+
20
+ #chart {
21
+ width: 100%;
22
+ min-height: 600px;
23
+ }
24
+
25
+ .card {
26
+ min-width: 90%;
27
+ padding: 1em 2em;
28
+ background-color: #323a46;
29
+ background-clip: border-box;
30
+ border: 0 solid #32394e;
31
+ border-radius: .25rem;
32
+ box-shadow: 0 0.75rem 6rem rgba(56,65,74,.03);
33
+ }
34
+
35
+ h1 {
36
+ text-align: center;
37
+ color: #f6f6f6;
38
+ font-size: 14px;
39
+ margin: 0 0 7px 0;
40
+ padding-top: 14px;
41
+ padding-bottom: 14px;
42
+ }
43
+
44
+ p.hint {
45
+ font-size: 10px;
46
+ text-align: center;
47
+ color: #aaa;
48
+ }
49
+
50
+ table {
51
+ border-collapse: collapse;
52
+ border-radius: 10px;
53
+ overflow: hidden;
54
+ width: 100%;
55
+ margin: 0 auto;
56
+ position: relative;
57
+ border-spacing: 1;
58
+ }
59
+ table * {
60
+ position: relative;
61
+ }
62
+ table td, table th {
63
+ padding-left: 8px;
64
+ }
65
+ table thead tr {
66
+ height: 60px;
67
+ }
68
+ table tbody tr {
69
+ height: 50px;
70
+ }
71
+ table tbody tr:last-child {
72
+ border: 0;
73
+ }
74
+ table td, table th {
75
+ text-align: left;
76
+ }
77
+ table td.l, table th.l {
78
+ text-align: right;
79
+ }
80
+ table td.c, table th.c {
81
+ text-align: center;
82
+ }
83
+ table td.r, table th.r {
84
+ text-align: center;
85
+ }
86
+
87
+ th {
88
+ font-size: 18px;
89
+ color: #f5f5f5;
90
+ line-height: 1.2;
91
+ font-weight: unset;
92
+ }
93
+
94
+ tbody tr {
95
+ font-size: 15px;
96
+ color: #f5f5f5;
97
+ line-height: 1.2;
98
+ font-weight: unset;
99
+ }
100
+
101
+ tbody tr:hover {
102
+ color: white;
103
+ background-color: #282e38;
104
+ }
105
+
106
+ </style>
@@ -0,0 +1,65 @@
1
+ <%= javascript_include_tag 'https://code.highcharts.com/highcharts.js' %>
2
+ <%= javascript_include_tag 'https://code.highcharts.com/modules/data.js' %>
3
+ <%= javascript_include_tag 'https://code.highcharts.com/modules/exporting.js' %>
4
+ <%= javascript_include_tag 'https://code.highcharts.com/modules/export-data.js' %>
5
+ <%= javascript_include_tag 'https://code.highcharts.com/modules/accessibility.js' %>
6
+
7
+ <script>
8
+ function showRequestsChart(div, data) {
9
+ Highcharts.chart(div, {
10
+ chart: {
11
+ type: 'column',
12
+ zoomType: 'x',
13
+ backgroundColor: '#323a46'
14
+ },
15
+ title: {
16
+ text: ''
17
+ },
18
+ xAxis: {
19
+ type: 'datetime',
20
+ labels: {
21
+ style: {
22
+ color: "#a6b0cf"
23
+ }
24
+ }
25
+ },
26
+ yAxis: {
27
+ min: 0,
28
+ title: {
29
+ text: 'RPM',
30
+ style: {
31
+ color: "#f6f6f6"
32
+ }
33
+ },
34
+ labels: {
35
+ style: {
36
+ color: "#a6b0cf"
37
+ }
38
+ }
39
+ },
40
+ legend: {
41
+ enabled: false
42
+ },
43
+ exporting: {
44
+ buttons: {
45
+ contextButton: {
46
+ theme: {
47
+ fill: "#a6b0cf"
48
+ }
49
+ }
50
+ }
51
+ },
52
+ plotOptions: {
53
+ column: {
54
+ color: '#ff5b5b',
55
+ borderColor: '#ff5b5b',
56
+ }
57
+ },
58
+ series: [{
59
+ type: 'column',
60
+ name: 'Requests per minute',
61
+ data: data
62
+ }]
63
+ });
64
+ };
65
+ </script>
@@ -0,0 +1,57 @@
1
+ <%= render '/rails_performance/css' %>
2
+
3
+ <title>Number of Requests to the Application</title>
4
+
5
+ <br/>
6
+ <br/>
7
+ <br/>
8
+
9
+ <div class="card">
10
+ <h1>Throughput Report<h1>
11
+ <div id="chart"></div>
12
+ <p class="hint">All requests (site visitors, search engines, bots, etc)</p>
13
+ </div>
14
+
15
+ <br/>
16
+ <br/>
17
+ <br/>
18
+
19
+ <div class="card">
20
+ <h1>Requests (path, total number, average response time)<h1>
21
+ <table>
22
+ <thead>
23
+ <tr>
24
+ <th></th>
25
+ <th>Format</th>
26
+ <th>Requests</th>
27
+ <th>Average (ms)</th>
28
+ <th>Slowest (ms)</th>
29
+ </tr>
30
+ </thead>
31
+ <tbody>
32
+ <% @global.each do |e| %>
33
+ <% groups = e[:group].split("|") %>
34
+ <tr>
35
+ <td><%= groups[0] %></td>
36
+ <td><%= groups[1]&.upcase %></td>
37
+ <td><%= e[:count] %></td>
38
+ <td><%= e[:average].round(2) %></td>
39
+ <td><%= e[:slowest].round(2) %></td>
40
+ </tr>
41
+ <% end %>
42
+ </tbody>
43
+ </table>
44
+ </div>
45
+
46
+ <br/>
47
+ <br/>
48
+ <br/>
49
+
50
+
51
+ <%= render '/rails_performance/js' %>
52
+
53
+ <script>
54
+ var data = <%= raw @data.to_json %>;
55
+ showRequestsChart('chart', data);
56
+ </script>
57
+
data/config/routes.rb ADDED
@@ -0,0 +1,12 @@
1
+ RailsPerformance::Engine.routes.draw do
2
+ get '/' => 'rails_performance#index', as: :rails_performance
3
+ end
4
+
5
+ Rails.application.routes.draw do
6
+ begin
7
+ mount RailsPerformance::Engine => '/rails/performance', as: 'rails_performance'
8
+ rescue ArgumentError
9
+ # already added
10
+ # this cod exist here because engine not includes routing automatically
11
+ end
12
+ end
@@ -0,0 +1,17 @@
1
+ module RailsPerformance
2
+ class BaseReport
3
+ attr_reader :db, :group
4
+
5
+ def initialize(db, group: nil)
6
+ @db = db
7
+ @group = group
8
+ end
9
+
10
+ def collect
11
+ db.group_by(group).values.inject([]) do |res, (k,v)|
12
+ res << yield(k, v)
13
+ res
14
+ end
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,36 @@
1
+ module RailsPerformance
2
+ class Collection
3
+ attr_reader :data
4
+
5
+ def initialize
6
+ @data = []
7
+ end
8
+
9
+ def add(record)
10
+ @data << record
11
+ end
12
+
13
+ def group_by(type)
14
+ @data = case type
15
+ when :controller_action, :controller_action_format, :datetime, :path
16
+ @data.group_by(&type)
17
+ else
18
+ []
19
+ end
20
+ self
21
+ end
22
+
23
+ def values
24
+ return [] if @data.empty?
25
+ result = {}
26
+ @data.each do |key, records|
27
+ result[key] ||= []
28
+ records.each do |record|
29
+ result[key] << record.value
30
+ end
31
+ end
32
+ result
33
+ end
34
+
35
+ end
36
+ end
@@ -0,0 +1,72 @@
1
+ module RailsPerformance
2
+ class DataSource
3
+ attr_reader :q
4
+
5
+ def initialize(q: {})
6
+ q[:on] ||= Date.current
7
+ @q = q
8
+ end
9
+
10
+ def DataSource.all
11
+ result = RP::Collection.new
12
+ RP::Utils.days.times do |e|
13
+ RP::DataSource.new(q: { on: e.days.ago.to_date }).add_to(result)
14
+ end
15
+ result
16
+ end
17
+
18
+ def db(storage = RP::Collection.new)
19
+ store do |record|
20
+ storage.add(record)
21
+ end
22
+ storage
23
+ end
24
+ alias :add_to :db
25
+
26
+ def store
27
+ #puts "REDIS: #{query}"
28
+
29
+ keys = RP.redis.keys(query)
30
+ return [] if keys.blank?
31
+ values = RP.redis.mget(keys)
32
+
33
+ keys.each_with_index do |key, index|
34
+ yield RP::Record.new(key, values[index])
35
+ end
36
+ end
37
+
38
+ private
39
+
40
+ # key = performance|
41
+ # controller|HomeController|
42
+ # action|index|
43
+ # format|html|
44
+ # status|200|
45
+ # datetime|20200124T0523|
46
+ # datetimei|1579861423|
47
+ # method|GET|
48
+ # path|/|
49
+ # END
50
+
51
+ def compile_query
52
+ str = []
53
+
54
+ str << "controller|#{q[:controller]}|" if q[:controller].present?
55
+ str << "action|#{q[:action]}|" if q[:action].present?
56
+ str << "format|#{q[:format]}|" if q[:format].present?
57
+ str << "status|#{q[:status]}|" if q[:status].present?
58
+
59
+ str << "datetime|#{q[:on].strftime('%Y%m%d')}*|" if q[:on].present?
60
+
61
+ str << "method|#{q[:method]}|" if q[:method].present?
62
+ str << "path|#{q[:path]}|" if q[:path].present?
63
+
64
+ str.join("*")
65
+ end
66
+
67
+ def query
68
+ "performance|*#{compile_query}*|END"
69
+ end
70
+
71
+ end
72
+ end
@@ -0,0 +1,19 @@
1
+ require_relative './middleware.rb'
2
+ require_relative './collection.rb'
3
+ require_relative './metrics_listener.rb'
4
+
5
+ module RailsPerformance
6
+ class Engine < ::Rails::Engine
7
+
8
+ #config.app_middleware.use RailsPerformance::Middleware
9
+ config.app_middleware.insert_after ActionDispatch::Executor, RailsPerformance::Middleware
10
+
11
+ initializer :configure_metrics, after: :initialize_logger do
12
+ ActiveSupport::Notifications.subscribe(
13
+ "process_action.action_controller",
14
+ RailsPerformance::MetricsListener.new
15
+ )
16
+ end
17
+
18
+ end
19
+ end
@@ -0,0 +1,40 @@
1
+ module RailsPerformance
2
+ class MetricsListener
3
+ FORMAT = "%Y%m%dT%H%M"
4
+
5
+ # payload
6
+ # {
7
+ # controller: "PostsController",
8
+ # action: "index",
9
+ # params: {"action" => "index", "controller" => "posts"},
10
+ # headers: #<ActionDispatch::Http::Headers:0x0055a67a519b88>,
11
+ # format: :html,
12
+ # method: "GET",
13
+ # path: "/posts",
14
+ # status: 200,
15
+ # view_runtime: 46.848,
16
+ # db_runtime: 0.157
17
+ # }
18
+
19
+ def call(event_name, started, finished, event_id, payload)
20
+ event = ActiveSupport::Notifications::Event.new(event_name, started, finished, event_id, payload)
21
+
22
+ record = {
23
+ controller: event.payload[:controller],
24
+ action: event.payload[:action],
25
+ format: event.payload[:format],
26
+ status: event.payload[:status],
27
+ datetime: finished.strftime(FORMAT),
28
+ datetimei: finished.to_i,
29
+ method: event.payload[:method],
30
+ path: event.payload[:path],
31
+ view_runtime: event.payload[:view_runtime],
32
+ db_runtime: event.payload[:db_runtime],
33
+ duration: event.duration
34
+ }
35
+
36
+ Thread.current["RP_request_info"] = record
37
+ end
38
+
39
+ end
40
+ end
@@ -0,0 +1,20 @@
1
+ module RailsPerformance
2
+ class Middleware
3
+ def initialize(app)
4
+ @app = app
5
+ end
6
+
7
+ def call(env)
8
+ @status, @headers, @response = @app.call(env)
9
+
10
+ record = Thread.current["RP_request_info"]
11
+
12
+ record[:status] ||= @status
13
+
14
+ RP::Utils.log_in_redis(record)
15
+
16
+ [@status, @headers, @response]
17
+ end
18
+
19
+ end
20
+ end
@@ -0,0 +1,45 @@
1
+ module RailsPerformance
2
+ class Record
3
+
4
+ attr_reader :controller, :action, :format, :status, :datetime, :datetimei, :method, :path
5
+
6
+ # key = performance|
7
+ # controller|HomeController|
8
+ # action|index|
9
+ # format|html|
10
+ # status|200|
11
+ # datetime|20200124T0523|
12
+ # datetimei|1579861423|
13
+ # method|GET|
14
+ # path|/|
15
+ # END
16
+ # = {"view_runtime":8.444603008683771,"db_runtime":0,"duration":9.216095000000001}
17
+ # value = JSON
18
+ def initialize(key, value)
19
+ @json = value
20
+
21
+ items = key.split("|")
22
+
23
+ @controller = items[2]
24
+ @action = items[4]
25
+ @format = items[6]
26
+ @status = items[8]
27
+ @datetime = items[10]
28
+ @datetimei = items[12]
29
+ @method = items[14]
30
+ @path = items[16]
31
+ end
32
+
33
+ def value
34
+ @value ||= JSON.parse(@json)
35
+ end
36
+
37
+ def controller_action
38
+ "#{controller}##{action}"
39
+ end
40
+
41
+ def controller_action_format
42
+ "#{controller}##{action}|#{format}"
43
+ end
44
+ end
45
+ end
@@ -0,0 +1,14 @@
1
+ module RailsPerformance
2
+ class RequestsReport < BaseReport
3
+ def data
4
+ collect do |k, v|
5
+ {
6
+ group: k,
7
+ average: v.sum{|e| e["duration"]}.to_f / v.size,
8
+ count: v.size,
9
+ slowest: v.max_by{|e| e["duration"]}.try(:[], "duration")
10
+ }
11
+ end.sort{|a, b| b[:count] <=> a[:count]}
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,31 @@
1
+ module RailsPerformance
2
+ class ThroughputReport < BaseReport
3
+
4
+ def initialize(ds)
5
+ super(ds, group: :datetime)
6
+ end
7
+
8
+ def data
9
+ all = {}
10
+ stop = Time.at(60 * (Time.now.to_i / 60))
11
+ current = stop - RailsPerformance.duration
12
+ @data = []
13
+
14
+ # read current values
15
+ db.group_by(group).values.each do |(k, v)|
16
+ all[k] = v.count
17
+ end
18
+
19
+ # add blank columns
20
+ while current <= stop
21
+ views = all[current.strftime(MetricsListener::FORMAT)] || 0
22
+ @data << [current.to_i * 1000, views.to_i]
23
+ current += 1.minute
24
+ end
25
+
26
+ # sort by time
27
+ @data.sort!
28
+ end
29
+
30
+ end
31
+ end
@@ -0,0 +1,53 @@
1
+ module RailsPerformance
2
+
3
+ class Utils
4
+ # date key in redis store
5
+ def Utils.cache_key(now = Date.current)
6
+ "date-#{now}"
7
+ end
8
+
9
+ # write to current slot
10
+ # time - date -minute
11
+ def Utils.field_key(now = Time.now)
12
+ now.strftime("%H:%M")
13
+ end
14
+
15
+ def Utils.log_in_redis(e)
16
+ value = e.slice(:view_runtime, :db_runtime, :duration)
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]}|END"
18
+
19
+ #puts " [SAVE] ---> #{key} = #{value.to_json}\n\n"
20
+
21
+ RP.redis.set(key, value.to_json)
22
+ RP.redis.expire(key, RP.duration.to_i)
23
+ true
24
+ end
25
+
26
+ def Utils.days
27
+ (RP.duration % 24.days).parts[:days] + 1
28
+ end
29
+
30
+ def Utils.median(array)
31
+ sorted = array.sort
32
+ size = sorted.size
33
+ center = size / 2
34
+
35
+ if size == 0
36
+ nil
37
+ elsif size.even?
38
+ (sorted[center - 1] + sorted[center]) / 2.0
39
+ else
40
+ sorted[center]
41
+ end
42
+ end
43
+
44
+ # populate test data
45
+ # run in rails c
46
+ def Utils.populate_test_data(seed = 20, limit = 10000, days = 7)
47
+ limit.times do
48
+ t = rand(86400*days).seconds.ago # within last 7 days
49
+ RP.redis.hincrby(cache_key(t.to_date), field_key(t), rand(seed))
50
+ end
51
+ end
52
+ end
53
+ end
@@ -0,0 +1,3 @@
1
+ module RailsPerformance
2
+ VERSION = '0.0.1'
3
+ end
@@ -0,0 +1,29 @@
1
+ require "redis"
2
+ require "redis-namespace"
3
+ require_relative "rails_performance/middleware.rb"
4
+ require_relative "rails_performance/data_source.rb"
5
+ require_relative "rails_performance/record.rb"
6
+ require_relative "rails_performance/utils.rb"
7
+ require_relative "rails_performance/base_report.rb"
8
+ require_relative "rails_performance/requests_report.rb"
9
+ require_relative "rails_performance/throughput_report.rb"
10
+
11
+ require "rails_performance/engine"
12
+
13
+ module RailsPerformance
14
+ mattr_accessor :redis
15
+ @@redis = Redis::Namespace.new("#{Rails.env}-rails-performance", redis: Redis.new)
16
+
17
+ mattr_accessor :duration
18
+ @@duration = 24.hours
19
+
20
+ mattr_accessor :debug
21
+ @@debug = false
22
+
23
+ def self.setup
24
+ yield(self)
25
+ end
26
+
27
+ end
28
+
29
+ RP = RailsPerformance
metadata ADDED
@@ -0,0 +1,134 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: rails_performance
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Igor Kasyanchuk
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2020-01-24 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: rails
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: '0'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: '0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: redis
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: redis-namespace
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :runtime
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: sqlite3
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ">="
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
69
+ - !ruby/object:Gem::Dependency
70
+ name: simplecov
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - ">="
74
+ - !ruby/object:Gem::Version
75
+ version: '0'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - ">="
81
+ - !ruby/object:Gem::Version
82
+ version: '0'
83
+ description: Track number of requests to your app
84
+ email:
85
+ - igorkasyanchuk@gmail.com
86
+ executables: []
87
+ extensions: []
88
+ extra_rdoc_files: []
89
+ files:
90
+ - MIT-LICENSE
91
+ - README.md
92
+ - Rakefile
93
+ - app/assets/config/rails_performance_manifest.js
94
+ - app/controllers/rails_performance_controller.rb
95
+ - app/views/rails_performance/_css.html.erb
96
+ - app/views/rails_performance/_js.html.erb
97
+ - app/views/rails_performance/index.html.erb
98
+ - config/routes.rb
99
+ - lib/rails_performance.rb
100
+ - lib/rails_performance/base_report.rb
101
+ - lib/rails_performance/collection.rb
102
+ - lib/rails_performance/data_source.rb
103
+ - lib/rails_performance/engine.rb
104
+ - lib/rails_performance/metrics_listener.rb
105
+ - lib/rails_performance/middleware.rb
106
+ - lib/rails_performance/record.rb
107
+ - lib/rails_performance/requests_report.rb
108
+ - lib/rails_performance/throughput_report.rb
109
+ - lib/rails_performance/utils.rb
110
+ - lib/rails_performance/version.rb
111
+ homepage: https://github.com/igorkasyanchuk/rails_performance
112
+ licenses:
113
+ - MIT
114
+ metadata: {}
115
+ post_install_message:
116
+ rdoc_options: []
117
+ require_paths:
118
+ - lib
119
+ required_ruby_version: !ruby/object:Gem::Requirement
120
+ requirements:
121
+ - - ">="
122
+ - !ruby/object:Gem::Version
123
+ version: '0'
124
+ required_rubygems_version: !ruby/object:Gem::Requirement
125
+ requirements:
126
+ - - ">="
127
+ - !ruby/object:Gem::Version
128
+ version: '0'
129
+ requirements: []
130
+ rubygems_version: 3.0.6
131
+ signing_key:
132
+ specification_version: 4
133
+ summary: Track number of requests to your app
134
+ test_files: []