active_record_query_counter 1.0.0 → 1.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.github/dependabot.yml +12 -0
- data/.github/workflows/continuous_integration.yml +51 -0
- data/.standard.yml +11 -0
- data/CHANGE_LOG.md +4 -0
- data/README.md +6 -3
- data/VERSION +1 -1
- data/active_record_query_counter.gemspec +11 -12
- data/lib/active_record_query_counter.rb +77 -29
- metadata +12 -23
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 7600a3d02b1c366ac42c06a7d4e781a4b622d84bca14d26e46b4e8aa34a09b32
|
4
|
+
data.tar.gz: f2922c6db0478569029f1d869b2544dcbd0b1535ca95b0188691c5da9cddb561
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 15370172634b6ebbf4a1bcf783e5ff0f0132f01e2a013c1ef457dac95d80369718fad4acf8408ea5e51bf5ffbd6adf96303ad64c1c4e67b2c6817776183b99ab
|
7
|
+
data.tar.gz: b48d6016e2fd9feb9bbb30705e92484dd1b0376658e9c55267a526c17199e19e7d4d104863b1910d2d6a05a009d75ef2332a6bf606090640b055a3b550e852eb
|
@@ -0,0 +1,12 @@
|
|
1
|
+
# Dependabot update strategy
|
2
|
+
version: 2
|
3
|
+
updates:
|
4
|
+
- package-ecosystem: bundler
|
5
|
+
directory: "/"
|
6
|
+
schedule:
|
7
|
+
interval: daily
|
8
|
+
allow:
|
9
|
+
# Automatically keep all runtime dependencies updated
|
10
|
+
- dependency-name: "*"
|
11
|
+
dependency-type: "production"
|
12
|
+
versioning-strategy: lockfile-only
|
@@ -0,0 +1,51 @@
|
|
1
|
+
name: Continuous Integration
|
2
|
+
on:
|
3
|
+
push:
|
4
|
+
branches:
|
5
|
+
- master
|
6
|
+
- actions-*
|
7
|
+
tags:
|
8
|
+
- v*
|
9
|
+
pull_request:
|
10
|
+
env:
|
11
|
+
BUNDLE_CLEAN: "true"
|
12
|
+
BUNDLE_PATH: vendor/bundle
|
13
|
+
BUNDLE_JOBS: 3
|
14
|
+
BUNDLE_RETRY: 3
|
15
|
+
jobs:
|
16
|
+
specs:
|
17
|
+
name: ${{ matrix.job }} ruby-${{ matrix.ruby }} ${{ matrix.activerecord && format('activerecord-{0}', matrix.activerecord) }}
|
18
|
+
runs-on: ubuntu-latest
|
19
|
+
strategy:
|
20
|
+
fail-fast: false
|
21
|
+
matrix:
|
22
|
+
ruby: ["2.6"]
|
23
|
+
activerecord: ["4.2", "5.0", "5.1", "5.2", "6.0"]
|
24
|
+
job: [ rspec ]
|
25
|
+
include:
|
26
|
+
- ruby: "2.7"
|
27
|
+
activerecord: original
|
28
|
+
job: rspec
|
29
|
+
- ruby: "2.7"
|
30
|
+
job: standardrb
|
31
|
+
steps:
|
32
|
+
- name: checkout
|
33
|
+
uses: actions/checkout@v2
|
34
|
+
- name: set up Ruby
|
35
|
+
uses: ruby/setup-ruby@v1
|
36
|
+
with:
|
37
|
+
ruby-version: ${{ matrix.ruby }}
|
38
|
+
- name: inject activerecord ${{ matrix.activerecord }}
|
39
|
+
if: matrix.activerecord != 'original' && matrix.activerecord != null
|
40
|
+
run: | # inject a specific version of activerecord into the Gemfile
|
41
|
+
bundle update
|
42
|
+
bundle exec appraisal generate
|
43
|
+
bundle config set gemfile "gemfiles/activerecord_${{ matrix.activerecord }}.gemfile"
|
44
|
+
- name: install dependencies
|
45
|
+
run: bundle install
|
46
|
+
- name: specs
|
47
|
+
if: matrix.job == 'rspec'
|
48
|
+
run: bundle exec rake spec
|
49
|
+
- name: standardrb
|
50
|
+
if: matrix.job == 'standardrb'
|
51
|
+
run: bundle exec rake standard
|
data/.standard.yml
ADDED
data/CHANGE_LOG.md
CHANGED
data/README.md
CHANGED
@@ -1,9 +1,10 @@
|
|
1
1
|
# ActiveRecordQueryCounter
|
2
2
|
|
3
|
-
|
3
|
+
![Continuous Integration](https://github.com/bdurand/active_record_query_counter/workflows/Continuous%20Integration/badge.svg)
|
4
4
|
[![Maintainability](https://api.codeclimate.com/v1/badges/21094ecec0c151983bb1/maintainability)](https://codeclimate.com/github/bdurand/active_record_query_counter/maintainability)
|
5
|
+
[![Ruby Style Guide](https://img.shields.io/badge/code_style-standard-brightgreen.svg)](https://github.com/testdouble/standard)
|
5
6
|
|
6
|
-
This gem injects itself into ActiveRecord to count the number of queries, the number of rows returned,
|
7
|
+
This gem injects itself into ActiveRecord to count the number of queries, the number of rows returned, the amount of time spent on queries, the number of transactions, and the amount of time spent inside transactions within a block.
|
7
8
|
|
8
9
|
The intended use is to gather instrumentation stats for finding hot spots in your code.
|
9
10
|
|
@@ -30,7 +31,9 @@ ActiveRecordQueryCounter.count_queries do
|
|
30
31
|
do_something
|
31
32
|
puts "Queries: #{ActiveRecordQueryCounter.query_count}"
|
32
33
|
puts "Rows: #{ActiveRecordQueryCounter.row_count}"
|
33
|
-
puts "Time: #{ActiveRecordQueryCounter.query_time}"
|
34
|
+
puts "Query Time: #{ActiveRecordQueryCounter.query_time}"
|
35
|
+
puts "Transactions: #{ActiveRecordQueryCounter.transaction_count}"
|
36
|
+
puts "Transaction Time: #{ActiveRecordQueryCounter.transaction_time}"
|
34
37
|
end
|
35
38
|
```
|
36
39
|
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
1.
|
1
|
+
1.1.0
|
@@ -1,16 +1,16 @@
|
|
1
1
|
Gem::Specification.new do |spec|
|
2
|
-
spec.name =
|
2
|
+
spec.name = "active_record_query_counter"
|
3
3
|
spec.version = File.read(File.expand_path("../VERSION", __FILE__)).strip
|
4
|
-
spec.authors = [
|
5
|
-
spec.email = [
|
4
|
+
spec.authors = ["Brian Durand"]
|
5
|
+
spec.email = ["bbdurand@gmail.com"]
|
6
6
|
|
7
7
|
spec.summary = "Count total number of ActiveRecord queries and row counts inside a block"
|
8
|
-
spec.homepage = "https://github.com/bdurand/
|
8
|
+
spec.homepage = "https://github.com/bdurand/active_record_query_counter"
|
9
9
|
spec.license = "MIT"
|
10
10
|
|
11
11
|
# Specify which files should be added to the gem when it is released.
|
12
12
|
# The `git ls-files -z` loads the files in the RubyGem that have been added into git.
|
13
|
-
ignore_files = %w
|
13
|
+
ignore_files = %w[
|
14
14
|
.gitignore
|
15
15
|
.travis.yml
|
16
16
|
Appraisals
|
@@ -19,17 +19,16 @@ Gem::Specification.new do |spec|
|
|
19
19
|
Rakefile
|
20
20
|
gemfiles/
|
21
21
|
spec/
|
22
|
-
|
23
|
-
spec.files = Dir.chdir(File.expand_path(
|
24
|
-
`git ls-files -z`.split("\x0").reject{ |f| ignore_files.any?{ |path| f.start_with?(path) } }
|
22
|
+
]
|
23
|
+
spec.files = Dir.chdir(File.expand_path("..", __FILE__)) do
|
24
|
+
`git ls-files -z`.split("\x0").reject { |f| ignore_files.any? { |path| f.start_with?(path) } }
|
25
25
|
end
|
26
26
|
|
27
|
-
spec.require_paths = [
|
27
|
+
spec.require_paths = ["lib"]
|
28
28
|
|
29
29
|
spec.add_dependency "activerecord", ">= 4.2"
|
30
30
|
|
31
|
+
spec.add_development_dependency "bundler", "~>2.0"
|
32
|
+
spec.add_development_dependency "rspec", ["~> 3.0"]
|
31
33
|
spec.add_development_dependency "sqlite3"
|
32
|
-
spec.add_development_dependency("rspec", ["~> 3.0"])
|
33
|
-
spec.add_development_dependency "rake"
|
34
|
-
spec.add_development_dependency "appraisal"
|
35
34
|
end
|
@@ -10,14 +10,23 @@
|
|
10
10
|
# puts ActiveRecordQueryCounter.row_count
|
11
11
|
# end
|
12
12
|
module ActiveRecordQueryCounter
|
13
|
+
class Counter
|
14
|
+
attr_accessor :query_count, :row_count, :query_time, :transaction_count, :transaction_time
|
15
|
+
def initialize
|
16
|
+
@query_count = 0
|
17
|
+
@row_count = 0
|
18
|
+
@query_time = 0.0
|
19
|
+
@transaction_count = 0
|
20
|
+
@transaction_time = 0.0
|
21
|
+
end
|
22
|
+
end
|
13
23
|
|
14
24
|
class << self
|
15
|
-
|
16
25
|
# Enable query counting within a block.
|
17
26
|
def count_queries
|
18
27
|
current = Thread.current[:database_query_counter]
|
19
28
|
begin
|
20
|
-
Thread.current[:database_query_counter] =
|
29
|
+
Thread.current[:database_query_counter] = Counter.new
|
21
30
|
yield
|
22
31
|
ensure
|
23
32
|
Thread.current[:database_query_counter] = current
|
@@ -26,41 +35,60 @@ module ActiveRecordQueryCounter
|
|
26
35
|
|
27
36
|
# Increment the query counters
|
28
37
|
def increment(row_count, elapsed_time)
|
29
|
-
|
30
|
-
if
|
31
|
-
|
32
|
-
|
33
|
-
|
38
|
+
counter = Thread.current[:database_query_counter]
|
39
|
+
if counter.is_a?(Counter)
|
40
|
+
counter.query_count += 1
|
41
|
+
counter.row_count += row_count
|
42
|
+
counter.query_time += elapsed_time
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
def increment_transaction(elapsed_time)
|
47
|
+
counter = Thread.current[:database_query_counter]
|
48
|
+
if counter.is_a?(Counter)
|
49
|
+
counter.transaction_count += 1
|
50
|
+
counter.transaction_time += elapsed_time
|
34
51
|
end
|
35
52
|
end
|
36
53
|
|
37
54
|
def query_count
|
38
|
-
|
39
|
-
|
55
|
+
counter = Thread.current[:database_query_counter]
|
56
|
+
counter.query_count if counter.is_a?(Counter)
|
40
57
|
end
|
41
58
|
|
42
59
|
def row_count
|
43
|
-
|
44
|
-
|
60
|
+
counter = Thread.current[:database_query_counter]
|
61
|
+
counter.row_count if counter.is_a?(Counter)
|
45
62
|
end
|
46
63
|
|
47
64
|
def query_time
|
48
|
-
|
49
|
-
|
65
|
+
counter = Thread.current[:database_query_counter]
|
66
|
+
counter.query_time if counter.is_a?(Counter)
|
67
|
+
end
|
68
|
+
|
69
|
+
def transaction_count
|
70
|
+
counter = Thread.current[:database_query_counter]
|
71
|
+
counter.transaction_count if counter.is_a?(Counter)
|
50
72
|
end
|
51
73
|
|
52
|
-
|
53
|
-
|
74
|
+
def transaction_time
|
75
|
+
counter = Thread.current[:database_query_counter]
|
76
|
+
counter.transaction_time if counter.is_a?(Counter)
|
77
|
+
end
|
78
|
+
|
79
|
+
# Return the query info as a hash with keys :query_count, :row_count, :query_time
|
80
|
+
# :transaction_count, and :transaction_type or nil if not inside a block where queries
|
81
|
+
# are being counted.
|
54
82
|
def info
|
55
|
-
|
56
|
-
if
|
83
|
+
counter = Thread.current[:database_query_counter]
|
84
|
+
if counter.is_a?(Counter)
|
57
85
|
{
|
58
|
-
:query_count
|
59
|
-
:row_count
|
60
|
-
:query_time
|
86
|
+
query_count: counter.query_count,
|
87
|
+
row_count: counter.row_count,
|
88
|
+
query_time: counter.query_time,
|
89
|
+
transaction_count: counter.transaction_count,
|
90
|
+
transaction_time: counter.transaction_time
|
61
91
|
}
|
62
|
-
else
|
63
|
-
nil
|
64
92
|
end
|
65
93
|
end
|
66
94
|
|
@@ -69,13 +97,14 @@ module ActiveRecordQueryCounter
|
|
69
97
|
unless connection_class.include?(ConnectionAdapterExtension)
|
70
98
|
connection_class.prepend(ConnectionAdapterExtension)
|
71
99
|
end
|
100
|
+
unless ActiveRecord::ConnectionAdapters::TransactionManager.include?(TransactionManagerExtension)
|
101
|
+
ActiveRecord::ConnectionAdapters::TransactionManager.prepend(TransactionManagerExtension)
|
102
|
+
end
|
72
103
|
end
|
73
|
-
|
74
104
|
end
|
75
105
|
|
76
106
|
# Module to prepend to the connection adapter to inject the counting behavior.
|
77
107
|
module ConnectionAdapterExtension
|
78
|
-
|
79
108
|
def exec_query(*args)
|
80
109
|
start_time = Time.now
|
81
110
|
result = super
|
@@ -84,12 +113,35 @@ module ActiveRecordQueryCounter
|
|
84
113
|
end
|
85
114
|
result
|
86
115
|
end
|
116
|
+
end
|
117
|
+
|
118
|
+
module TransactionManagerExtension
|
119
|
+
def begin_transaction(*args)
|
120
|
+
if open_transactions == 0
|
121
|
+
@active_record_query_counter_transaction_start_time = Time.current
|
122
|
+
end
|
123
|
+
super
|
124
|
+
end
|
125
|
+
|
126
|
+
def commit_transaction(*args)
|
127
|
+
if @active_record_query_counter_transaction_start_time && open_transactions == 1
|
128
|
+
ActiveRecordQueryCounter.increment_transaction(Time.current - @active_record_query_counter_transaction_start_time)
|
129
|
+
@active_record_query_counter_transaction_start_time = nil
|
130
|
+
end
|
131
|
+
super
|
132
|
+
end
|
87
133
|
|
134
|
+
def rollback_transaction(*args)
|
135
|
+
if @active_record_query_counter_transaction_start_time && open_transactions == 1
|
136
|
+
ActiveRecordQueryCounter.increment_transaction(Time.current - @active_record_query_counter_transaction_start_time)
|
137
|
+
@active_record_query_counter_transaction_start_time = nil
|
138
|
+
end
|
139
|
+
super
|
140
|
+
end
|
88
141
|
end
|
89
142
|
|
90
143
|
# Rack middleware to count queries on a request.
|
91
144
|
class RackMiddleware
|
92
|
-
|
93
145
|
def initialize(app)
|
94
146
|
@app = app
|
95
147
|
end
|
@@ -97,16 +149,12 @@ module ActiveRecordQueryCounter
|
|
97
149
|
def call(env)
|
98
150
|
ActiveRecordQueryCounter.count_queries { @app.call(env) }
|
99
151
|
end
|
100
|
-
|
101
152
|
end
|
102
153
|
|
103
154
|
# Sidekiq middleware to count queries on a job.
|
104
155
|
class SidekiqMiddleware
|
105
|
-
|
106
156
|
def call(worker, job, queue, &block)
|
107
157
|
ActiveRecordQueryCounter.count_queries(&block)
|
108
158
|
end
|
109
|
-
|
110
159
|
end
|
111
|
-
|
112
160
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: active_record_query_counter
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.1.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Brian Durand
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2020-
|
11
|
+
date: 2020-10-30 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: activerecord
|
@@ -25,19 +25,19 @@ dependencies:
|
|
25
25
|
- !ruby/object:Gem::Version
|
26
26
|
version: '4.2'
|
27
27
|
- !ruby/object:Gem::Dependency
|
28
|
-
name:
|
28
|
+
name: bundler
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
30
30
|
requirements:
|
31
|
-
- - "
|
31
|
+
- - "~>"
|
32
32
|
- !ruby/object:Gem::Version
|
33
|
-
version: '0'
|
33
|
+
version: '2.0'
|
34
34
|
type: :development
|
35
35
|
prerelease: false
|
36
36
|
version_requirements: !ruby/object:Gem::Requirement
|
37
37
|
requirements:
|
38
|
-
- - "
|
38
|
+
- - "~>"
|
39
39
|
- !ruby/object:Gem::Version
|
40
|
-
version: '0'
|
40
|
+
version: '2.0'
|
41
41
|
- !ruby/object:Gem::Dependency
|
42
42
|
name: rspec
|
43
43
|
requirement: !ruby/object:Gem::Requirement
|
@@ -53,21 +53,7 @@ dependencies:
|
|
53
53
|
- !ruby/object:Gem::Version
|
54
54
|
version: '3.0'
|
55
55
|
- !ruby/object:Gem::Dependency
|
56
|
-
name:
|
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: appraisal
|
56
|
+
name: sqlite3
|
71
57
|
requirement: !ruby/object:Gem::Requirement
|
72
58
|
requirements:
|
73
59
|
- - ">="
|
@@ -87,13 +73,16 @@ executables: []
|
|
87
73
|
extensions: []
|
88
74
|
extra_rdoc_files: []
|
89
75
|
files:
|
76
|
+
- ".github/dependabot.yml"
|
77
|
+
- ".github/workflows/continuous_integration.yml"
|
78
|
+
- ".standard.yml"
|
90
79
|
- CHANGE_LOG.md
|
91
80
|
- MIT_LICENSE
|
92
81
|
- README.md
|
93
82
|
- VERSION
|
94
83
|
- active_record_query_counter.gemspec
|
95
84
|
- lib/active_record_query_counter.rb
|
96
|
-
homepage: https://github.com/bdurand/
|
85
|
+
homepage: https://github.com/bdurand/active_record_query_counter
|
97
86
|
licenses:
|
98
87
|
- MIT
|
99
88
|
metadata: {}
|