rails_request_stats 0.1.0 → 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/Gemfile +2 -0
- data/README.md +13 -6
- data/lib/rails_request_stats/notification_subscribers.rb +28 -4
- data/lib/rails_request_stats/report.rb +4 -2
- data/lib/rails_request_stats/request_stats.rb +5 -2
- data/lib/rails_request_stats/version.rb +1 -1
- metadata +3 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 67a34ab4f6878674fdf3cf11c2b9129bd25d61fb
|
4
|
+
data.tar.gz: 1bd610a86b78aa721061c875d517057e9c43bfc5
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 46500b124a71c42c4ab0aa609eb004b090528be062ab12999c8db9e4141586dd2cdd6abc502c6fe5a399c2ca65f6e8c0ced702daf5fc4b2a4080232271b0304f
|
7
|
+
data.tar.gz: bb43c7e65b32142a7823acdf71999aef0d2e2d5aec8efeafbd3465bc201c5cb5bf3e5b59f3f473106f4ef35d10eec19b5f5d38df6a7954aef8ab1c3fece36c74
|
data/Gemfile
CHANGED
data/README.md
CHANGED
@@ -1,5 +1,10 @@
|
|
1
1
|
# RailsRequestStats
|
2
2
|
|
3
|
+
[![Gem Version](https://badge.fury.io/rb/rails_request_stats.svg)](https://badge.fury.io/rb/rails_request_stats)
|
4
|
+
[![Build Status](https://travis-ci.org/kevinjalbert/rails_request_stats.svg?branch=master)](https://travis-ci.org/kevinjalbert/rails_request_stats)
|
5
|
+
[![Code Climate](https://codeclimate.com/github/kevinjalbert/rails_request_stats/badges/gpa.svg)](https://codeclimate.com/github/kevinjalbert/rails_request_stats)
|
6
|
+
[![Test Coverage](https://codeclimate.com/github/kevinjalbert/rails_request_stats/badges/coverage.svg)](https://codeclimate.com/github/kevinjalbert/rails_request_stats/coverage)
|
7
|
+
|
3
8
|
During development have you ever:
|
4
9
|
|
5
10
|
* Wondered how many SQL queries occurred during a request?
|
@@ -11,9 +16,11 @@ During development have you ever:
|
|
11
16
|
|
12
17
|
## How this Works
|
13
18
|
|
14
|
-
`RailsRequestStats::NotificationSubscribers` when required will subscribe to the `sql.active_record`, and `process_action.action_controller` `ActionSupport::Notifications`.
|
19
|
+
`RailsRequestStats::NotificationSubscribers` when required will subscribe to the `sql.active_record`, `start_processing.action_controller`, and `process_action.action_controller` `ActionSupport::Notifications`.
|
15
20
|
|
16
|
-
The `sql.active_record` event allow us to count each SQL query that passes though ActiveRecord, which we count internally.
|
21
|
+
* The `sql.active_record` event allow us to count each SQL query that passes though ActiveRecord, which we count internally.
|
22
|
+
* The `start_processing.action_controller` event allows us to clear iternal counts, as well as perform a `GC.start` and capturing the total number of objects residing in the `ObjectSpace`.
|
23
|
+
* The `process_action.action_controller` event provides us runtime information along with identifying controller action details, we even determine the number of generated objects since the start of processing the action. At this point we are able to synthesis the query information and runtime information and store them internally in running collection of `RailsRequestStats::RequestStats` objects.
|
17
24
|
|
18
25
|
**Note** the data collection is tracked and stored in class-level instance variables. Thus this is not threadsafe, as no concurrency mechanisms are used (i.e., mutex). For non-threaded and forking application servers this should be fine.
|
19
26
|
|
@@ -30,15 +37,15 @@ gem 'rails_request_stats', group: :development
|
|
30
37
|
Within the console ./log/development.log you should start seeing the following statement appearing at the end of processing a request:
|
31
38
|
|
32
39
|
```
|
33
|
-
[RailsRequestStats] (AVG view_runtime: 163.655ms | AVG db_runtime: 15.465ms | query_count: 9 | cached_query_count: 0)
|
40
|
+
[RailsRequestStats] (AVG view_runtime: 163.655ms | AVG db_runtime: 15.465ms | AVG generated_object_count: 14523 | query_count: 9 | cached_query_count: 0)
|
34
41
|
```
|
35
42
|
|
36
43
|
Finally when you exit the application's server, you should see a report of all the data captured:
|
37
44
|
|
38
45
|
```
|
39
|
-
[RailsRequestStats] INDEX:html "/users" (AVG view_runtime: 128.492ms | AVG db_runtime: 9.186ms | MIN query_count: 8 | MAX query_count: 9)
|
40
|
-
[RailsRequestStats] SHOW:html "/users/2" (AVG view_runtime: 13.0429ms | AVG db_runtime: 1.69033ms | MIN query_count: 2 | MAX query_count: 2)
|
41
|
-
[RailsRequestStats] SHOW:html "/users/2?test=1&blah=2" (AVG view_runtime: 17.8252ms | AVG db_runtime: 1.621ms | MIN query_count: 2 | MAX query_count: 2)
|
46
|
+
[RailsRequestStats] INDEX:html "/users" (AVG view_runtime: 128.492ms | AVG db_runtime: 9.186ms | AVG generated_object_count: 25529 | MIN query_count: 8 | MAX query_count: 9) from 4 requests
|
47
|
+
[RailsRequestStats] SHOW:html "/users/2" (AVG view_runtime: 13.0429ms | AVG db_runtime: 1.69033ms | AVG generated_object_count: 14523 | MIN query_count: 2 | MAX query_count: 2) from 3 requests
|
48
|
+
[RailsRequestStats] SHOW:html "/users/2?test=1&blah=2" (AVG view_runtime: 17.8252ms | AVG db_runtime: 1.621ms | AVG generated_object_count: 18511 | MIN query_count: 2 | MAX query_count: 2) from 1 requests
|
42
49
|
```
|
43
50
|
|
44
51
|
## Customizing Outputs
|
@@ -5,13 +5,17 @@ module RailsRequestStats
|
|
5
5
|
|
6
6
|
attr_reader :query_count,
|
7
7
|
:cached_query_count,
|
8
|
+
:before_action_object_count,
|
9
|
+
:generated_object_count,
|
8
10
|
:requests
|
9
11
|
|
10
|
-
def self.
|
12
|
+
def self.reset_counts
|
11
13
|
@query_count = 0
|
12
14
|
@cached_query_count = 0
|
15
|
+
@before_action_object_count = 0
|
16
|
+
@generated_object_count = 0
|
13
17
|
end
|
14
|
-
|
18
|
+
reset_counts
|
15
19
|
|
16
20
|
def self.reset_requests
|
17
21
|
@requests = {}
|
@@ -26,6 +30,10 @@ module RailsRequestStats
|
|
26
30
|
handle_sql_event(args.extract_options!)
|
27
31
|
end
|
28
32
|
|
33
|
+
ActiveSupport::Notifications.subscribe('start_processing.action_controller') do |*args|
|
34
|
+
handle_start_processing_event(args.extract_options!)
|
35
|
+
end
|
36
|
+
|
29
37
|
ActiveSupport::Notifications.subscribe('process_action.action_controller') do |*args|
|
30
38
|
handle_process_action_event(args.extract_options!)
|
31
39
|
end
|
@@ -43,16 +51,32 @@ module RailsRequestStats
|
|
43
51
|
@query_count += 1
|
44
52
|
end
|
45
53
|
|
54
|
+
def self.handle_start_processing_event(event)
|
55
|
+
reset_counts
|
56
|
+
|
57
|
+
GC.start
|
58
|
+
@before_action_object_count = total_object_count
|
59
|
+
end
|
60
|
+
|
46
61
|
def self.handle_process_action_event(event)
|
62
|
+
@generated_object_count = total_object_count - @before_action_object_count
|
63
|
+
|
47
64
|
request_key = { action: event[:action], format: event[:format], method: event[:method], path: event[:path] }
|
48
65
|
|
49
66
|
request_stats = @requests[request_key] || RequestStats.new(request_key)
|
50
|
-
request_stats.add_stats(event[:view_runtime], event[:db_runtime], @query_count, @cached_query_count)
|
67
|
+
request_stats.add_stats(event[:view_runtime], event[:db_runtime], @query_count, @cached_query_count, @generated_object_count)
|
51
68
|
|
52
69
|
@requests[request_key] = request_stats
|
53
|
-
reset_query_counts
|
54
70
|
|
55
71
|
Rails.logger.info { Report.new(request_stats).report_text }
|
56
72
|
end
|
73
|
+
|
74
|
+
class << self
|
75
|
+
private
|
76
|
+
|
77
|
+
def total_object_count
|
78
|
+
ObjectSpace.count_objects.select { |k, v| k.to_s.start_with?('T_') }.values.reduce(:+)
|
79
|
+
end
|
80
|
+
end
|
57
81
|
end
|
58
82
|
end
|
@@ -11,21 +11,23 @@ module RailsRequestStats
|
|
11
11
|
def report_text
|
12
12
|
avg_view_runtime = "AVG view_runtime: #{format_number(avg_stat(:view_runtime))}ms"
|
13
13
|
avg_db_runtime = "AVG db_runtime: #{format_number(avg_stat(:db_runtime))}ms"
|
14
|
+
avg_generated_object_count = "AVG generated_object_count: #{format_number(avg_stat(:generated_object_count))}"
|
14
15
|
query_count = "query_count: #{format_number(last_stat(:query_count))}"
|
15
16
|
cached_query_count = "cached_query_count: #{format_number(last_stat(:cached_query_count))}"
|
16
17
|
|
17
|
-
"[RailsRequestStats] (#{[avg_view_runtime, avg_db_runtime, query_count, cached_query_count].join(' | ')})"
|
18
|
+
"[RailsRequestStats] (#{[avg_view_runtime, avg_db_runtime, avg_generated_object_count, query_count, cached_query_count].join(' | ')})"
|
18
19
|
end
|
19
20
|
|
20
21
|
def exit_report_text
|
21
22
|
controller_information = "[RailsRequestStats] #{@request_stats.action.upcase}:#{@request_stats.format} \"#{@request_stats.path}\""
|
22
23
|
avg_view_runtime = "AVG view_runtime: #{format_number(avg_stat(:view_runtime))}ms"
|
23
24
|
avg_db_runtime = "AVG db_runtime: #{format_number(avg_stat(:db_runtime))}ms"
|
25
|
+
avg_generated_object_count = "AVG generated_object_count: #{format_number(avg_stat(:generated_object_count))}"
|
24
26
|
min_query_count = "MIN query_count: #{format_number(min_stat(:query_count))}"
|
25
27
|
max_query_count = "MAX query_count: #{format_number(max_stat(:query_count))}"
|
26
28
|
request_count = "from #{format_number(count_stat(:view_runtime))} requests"
|
27
29
|
|
28
|
-
"#{controller_information} (#{[avg_view_runtime, avg_db_runtime, min_query_count, max_query_count].join(' | ')}) #{request_count}"
|
30
|
+
"#{controller_information} (#{[avg_view_runtime, avg_db_runtime, avg_generated_object_count, min_query_count, max_query_count].join(' | ')}) #{request_count}"
|
29
31
|
end
|
30
32
|
|
31
33
|
def min_stat(category)
|
@@ -8,7 +8,8 @@ module RailsRequestStats
|
|
8
8
|
:view_runtime_collection,
|
9
9
|
:db_runtime_collection,
|
10
10
|
:query_count_collection,
|
11
|
-
:cached_query_count_collection
|
11
|
+
:cached_query_count_collection,
|
12
|
+
:generated_object_count_collection
|
12
13
|
|
13
14
|
def initialize(key)
|
14
15
|
@action = key[:action]
|
@@ -20,13 +21,15 @@ module RailsRequestStats
|
|
20
21
|
@db_runtime_collection = []
|
21
22
|
@query_count_collection = []
|
22
23
|
@cached_query_count_collection = []
|
24
|
+
@generated_object_count_collection = []
|
23
25
|
end
|
24
26
|
|
25
|
-
def add_stats(view_runtime, db_runtime, query_count, cached_query_count)
|
27
|
+
def add_stats(view_runtime, db_runtime, query_count, cached_query_count, generated_object_count)
|
26
28
|
@view_runtime_collection << view_runtime.to_f
|
27
29
|
@db_runtime_collection << db_runtime.to_f
|
28
30
|
@query_count_collection << query_count
|
29
31
|
@cached_query_count_collection << cached_query_count
|
32
|
+
@generated_object_count_collection << generated_object_count
|
30
33
|
end
|
31
34
|
end
|
32
35
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: rails_request_stats
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.2.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Kevin Jalbert
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2016-01-05 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -121,7 +121,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
121
121
|
version: '0'
|
122
122
|
requirements: []
|
123
123
|
rubyforge_project:
|
124
|
-
rubygems_version: 2.4.
|
124
|
+
rubygems_version: 2.4.5.1
|
125
125
|
signing_key:
|
126
126
|
specification_version: 4
|
127
127
|
summary: Provides additional development statistics on Rails requests in logfile
|