active_record_query_counter 2.2.1 → 2.3.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +6 -0
- data/README.md +56 -32
- data/VERSION +1 -1
- data/active_record_query_counter.gemspec +7 -1
- data/lib/active_record_query_counter/counter.rb +2 -1
- data/lib/active_record_query_counter/transaction_manager_extension.rb +1 -0
- data/lib/active_record_query_counter.rb +22 -1
- metadata +9 -5
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 9b460515835154824cb80fec7db1e62dc4f4f983f8779fc1b80bec3c728646a4
|
4
|
+
data.tar.gz: 3d26302dd73d2ae010f4732ca4711a7dd1daa4ca0cca55e5ccd50349e89b282c
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: d1af45ed8c0659df4fcbf665621576b07380565a1289458e868b7cb33825c2d055e7b489eb1e490c31a566157a01f328eedd2771f9f3f5bffdece2b357445a01
|
7
|
+
data.tar.gz: ba21e07f668e1c3f97c61ce6f48fd10ef2d019afdd7d9d579e3487c710d58e8b44a9b1c5042572bc74be55a907c506d6385947dbe85a10b14b57e2b7b94037b7
|
data/CHANGELOG.md
CHANGED
@@ -4,6 +4,12 @@ All notable changes to this project will be documented in this file.
|
|
4
4
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
5
5
|
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
6
6
|
|
7
|
+
## 2.3.0
|
8
|
+
|
9
|
+
### Added
|
10
|
+
|
11
|
+
- Added count of rollbacks from transactions
|
12
|
+
|
7
13
|
## 2.2.1
|
8
14
|
|
9
15
|
### Changed
|
data/README.md
CHANGED
@@ -1,39 +1,47 @@
|
|
1
1
|
# ActiveRecordQueryCounter
|
2
2
|
|
3
3
|
[![Continuous Integration](https://github.com/bdurand/active_record_query_counter/actions/workflows/continuous_integration.yml/badge.svg)](https://github.com/bdurand/active_record_query_counter/actions/workflows/continuous_integration.yml)
|
4
|
-
[![Regression Test](https://github.com/bdurand/active_record_query_counter/actions/workflows/regression_test.yml/badge.svg)](https://github.com/bdurand/active_record_query_counter/actions/workflows/regression_test.yml)
|
5
4
|
[![Ruby Style Guide](https://img.shields.io/badge/code_style-standard-brightgreen.svg)](https://github.com/testdouble/standard)
|
6
5
|
[![Gem Version](https://badge.fury.io/rb/active_record_query_counter.svg)](https://badge.fury.io/rb/active_record_query_counter)
|
7
6
|
|
8
|
-
|
7
|
+
**ActiveRecordQueryCounter** is a ruby gem that provides detailed insights into how your code interacts with the database by hooking into ActiveRecord.
|
9
8
|
|
10
|
-
|
9
|
+
It measures database usage within a block of code, including:
|
11
10
|
|
12
|
-
-
|
13
|
-
-
|
14
|
-
-
|
15
|
-
-
|
16
|
-
-
|
11
|
+
- The number of queries executed
|
12
|
+
- The number of rows returned
|
13
|
+
- The total time spent on queries
|
14
|
+
- The number of transactions used
|
15
|
+
- The total time spent inside transactions
|
16
|
+
- The number of transactions that were rolled back
|
17
17
|
|
18
|
-
|
18
|
+
This gem is designed to help you:
|
19
|
+
|
20
|
+
- Identify "hot spots" in your code that generate excessive or slow queries.
|
21
|
+
- Spot queries returning unexpectedly large result sets.
|
22
|
+
- Detect areas where transactions are underutilized, especially when performing multiple database updates.
|
19
23
|
|
20
24
|
## Usage
|
21
25
|
|
22
|
-
|
26
|
+
### Enabling The Gem
|
27
|
+
|
28
|
+
To use **ActiveRecordQueryCounter**, you first need to enable it on your database connection adapter. Add the following to an initializer:
|
23
29
|
|
24
|
-
|
30
|
+
For **PostgreSQL**:
|
25
31
|
|
26
32
|
```ruby
|
27
33
|
ActiveRecordQueryCounter.enable!(ActiveRecord::ConnectionAdapters::PostgreSQLAdapter)
|
28
34
|
```
|
29
35
|
|
30
|
-
MySQL
|
36
|
+
For **MySQL**:
|
31
37
|
|
32
38
|
```ruby
|
33
39
|
ActiveRecordQueryCounter.enable!(ActiveRecord::ConnectionAdapters::Mysql2Adapter)
|
34
40
|
```
|
35
41
|
|
36
|
-
|
42
|
+
### Counting Queries
|
43
|
+
|
44
|
+
To measure database activity, wrap the code you want to monitor inside a `count_queries` block:
|
37
45
|
|
38
46
|
```ruby
|
39
47
|
ActiveRecordQueryCounter.count_queries do
|
@@ -43,18 +51,25 @@ ActiveRecordQueryCounter.count_queries do
|
|
43
51
|
puts "Query Time: #{ActiveRecordQueryCounter.query_time}"
|
44
52
|
puts "Transactions: #{ActiveRecordQueryCounter.transaction_count}"
|
45
53
|
puts "Transaction Time: #{ActiveRecordQueryCounter.transaction_time}"
|
54
|
+
puts "Rollbacks: #{ActiveRecordQueryCounter.rollback_count}"
|
46
55
|
end
|
47
56
|
```
|
48
57
|
|
49
|
-
|
58
|
+
### Middleware Integration
|
59
|
+
|
60
|
+
For **Rails** and **Sidekiq**, middleware is included to enable query counting in web requests and workers.
|
61
|
+
|
62
|
+
Add the following to an initializer:
|
50
63
|
|
51
64
|
```ruby
|
52
65
|
ActiveSupport.on_load(:active_record) do
|
53
66
|
ActiveRecordQueryCounter.enable!(ActiveRecord::ConnectionAdapters::PostgreSQLAdapter)
|
54
67
|
end
|
55
68
|
|
69
|
+
# Enable Rack Middleware
|
56
70
|
Rails.application.config.middleware.use(ActiveRecordQueryCounter::RackMiddleware)
|
57
71
|
|
72
|
+
# Enable Sidekiq Middleware
|
58
73
|
Sidekiq.configure_server do |config|
|
59
74
|
config.server_middleware do |chain|
|
60
75
|
chain.add ActiveRecordQueryCounter::SidekiqMiddleware
|
@@ -62,13 +77,15 @@ Sidekiq.configure_server do |config|
|
|
62
77
|
end
|
63
78
|
```
|
64
79
|
|
65
|
-
|
80
|
+
### Disabling Query Counting
|
81
|
+
|
82
|
+
You can temporarily disable query counting within a block using `disable`:
|
66
83
|
|
67
84
|
```ruby
|
68
85
|
ActiveRecordQueryCounter.count_queries do
|
69
86
|
do_something
|
70
87
|
ActiveRecordQueryCounter.disable do
|
71
|
-
# Queries will not be counted
|
88
|
+
# Queries in this block will not be counted.
|
72
89
|
do_something_else
|
73
90
|
end
|
74
91
|
end
|
@@ -76,43 +93,46 @@ end
|
|
76
93
|
|
77
94
|
### Notifications
|
78
95
|
|
79
|
-
|
96
|
+
**ActiveRecordQueryCounter** supports ActiveSupport notifications when certain query thresholds are exceeded.
|
97
|
+
|
98
|
+
#### Available Notifications
|
99
|
+
|
100
|
+
##### 1. active_record_query_counter.query_time notification
|
80
101
|
|
81
|
-
|
102
|
+
Triggered when a query exceeds the query_time threshold with the payload:
|
82
103
|
|
83
|
-
This notification is triggered when a query takes longer than the `query_time` threshold. The payload contains the following keys:
|
84
104
|
|
85
105
|
- `:sql` - The SQL statement that was executed.
|
86
106
|
- `:binds` - The bind parameters that were used.
|
87
107
|
- `:row_count` - The number of rows returned.
|
88
108
|
- `:trace` - The stack trace of where the query was executed.
|
89
109
|
|
90
|
-
|
110
|
+
##### 2. active_record_query_counter.row_count notification
|
91
111
|
|
92
|
-
|
112
|
+
Triggered when a query exceeds the row_count threshold with the payload:
|
93
113
|
|
94
114
|
- `:sql` - The SQL statement that was executed.
|
95
115
|
- `:binds` - The bind parameters that were used.
|
96
116
|
- `:row_count` - The number of rows returned.
|
97
117
|
- `:trace` - The stack trace of where the query was executed.
|
98
118
|
|
99
|
-
|
119
|
+
##### 3. active_record_query_counter.transaction_time notification
|
100
120
|
|
101
|
-
|
121
|
+
Triggered when a transaction exceeds the transaction_time threshold with the payload:
|
102
122
|
|
103
123
|
- `:trace` - The stack trace of where the transaction was completed.
|
104
124
|
|
105
|
-
|
125
|
+
##### 4. active_record_query_counter.transaction_count notification
|
106
126
|
|
107
|
-
|
127
|
+
Triggered when transactions exceed the transaction_count threshold with the payload:
|
108
128
|
|
109
129
|
- `:transactions` - An array of `ActiveRecordQueryCounter::TransactionInfo` objects.
|
110
130
|
|
111
131
|
The duration of the notification event is the time between when the first transaction was started and the last transaction was completed.
|
112
132
|
|
113
|
-
#### Thresholds
|
133
|
+
#### Setting Thresholds
|
114
134
|
|
115
|
-
|
135
|
+
Thresholds can be configured **globally** in an initializer:
|
116
136
|
|
117
137
|
```ruby
|
118
138
|
ActiveRecordQueryCounter.default_thresholds.set(
|
@@ -123,7 +143,7 @@ ActiveRecordQueryCounter.default_thresholds.set(
|
|
123
143
|
)
|
124
144
|
```
|
125
145
|
|
126
|
-
|
146
|
+
Or locally within a block:
|
127
147
|
|
128
148
|
```ruby
|
129
149
|
ActiveRecordQueryCounter.count_queries do
|
@@ -136,7 +156,8 @@ ActiveRecordQueryCounter.count_queries do
|
|
136
156
|
end
|
137
157
|
```
|
138
158
|
|
139
|
-
|
159
|
+
#### Sidekiq Worker Thresholds
|
160
|
+
Thresholds for individual Sidekiq workers can be set using `sidekiq_options`:
|
140
161
|
|
141
162
|
```ruby
|
142
163
|
class MyWorker
|
@@ -152,7 +173,6 @@ class MyWorker
|
|
152
173
|
}
|
153
174
|
}
|
154
175
|
)
|
155
|
-
# You can disable thresholds for the worker by setting `thresholds: false`.
|
156
176
|
|
157
177
|
def perform
|
158
178
|
do_something
|
@@ -160,7 +180,11 @@ class MyWorker
|
|
160
180
|
end
|
161
181
|
```
|
162
182
|
|
163
|
-
|
183
|
+
To disable thresholds for a worker, set `thresholds: false`.
|
184
|
+
|
185
|
+
#### Rack Middleware Thresholds
|
186
|
+
|
187
|
+
You can configure separate thresholds for the Rack middleware:
|
164
188
|
|
165
189
|
```ruby
|
166
190
|
Rails.application.config.middleware.use(ActiveRecordQueryCounter::RackMiddleware, thresholds: {
|
@@ -171,7 +195,7 @@ Rails.application.config.middleware.use(ActiveRecordQueryCounter::RackMiddleware
|
|
171
195
|
})
|
172
196
|
```
|
173
197
|
|
174
|
-
#### Example
|
198
|
+
#### Example: Subscribing to Notifications
|
175
199
|
|
176
200
|
```ruby
|
177
201
|
ActiveRecordQueryCounter.default_thresholds.query_time = 1.0
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
2.
|
1
|
+
2.3.0
|
@@ -4,10 +4,16 @@ Gem::Specification.new do |spec|
|
|
4
4
|
spec.authors = ["Brian Durand"]
|
5
5
|
spec.email = ["bbdurand@gmail.com"]
|
6
6
|
|
7
|
-
spec.summary = "
|
7
|
+
spec.summary = "Provides detailed insights into how your code interacts with the database by hooking into ActiveRecord."
|
8
8
|
spec.homepage = "https://github.com/bdurand/active_record_query_counter"
|
9
9
|
spec.license = "MIT"
|
10
10
|
|
11
|
+
spec.metadata = {
|
12
|
+
"homepage_uri" => spec.homepage,
|
13
|
+
"source_code_uri" => spec.homepage,
|
14
|
+
"changelog_uri" => "#{spec.homepage}/blob/main/CHANGELOG.md"
|
15
|
+
}
|
16
|
+
|
11
17
|
# Specify which files should be added to the gem when it is released.
|
12
18
|
# The `git ls-files -z` loads the files in the RubyGem that have been added into git.
|
13
19
|
ignore_files = %w[
|
@@ -3,7 +3,7 @@
|
|
3
3
|
module ActiveRecordQueryCounter
|
4
4
|
# Data structure for storing query information encountered within a block.
|
5
5
|
class Counter
|
6
|
-
attr_accessor :query_count, :row_count, :query_time, :cached_query_count
|
6
|
+
attr_accessor :query_count, :row_count, :query_time, :cached_query_count, :rollback_count
|
7
7
|
attr_reader :thresholds
|
8
8
|
|
9
9
|
def initialize
|
@@ -13,6 +13,7 @@ module ActiveRecordQueryCounter
|
|
13
13
|
@cached_query_count = 0
|
14
14
|
@transactions_hash = {}
|
15
15
|
@thresholds = ActiveRecordQueryCounter.default_thresholds.dup
|
16
|
+
@rollback_count = 0
|
16
17
|
end
|
17
18
|
|
18
19
|
# Return the percentage of queries that used the query cache instead of going to the database.
|
@@ -31,6 +31,7 @@ module ActiveRecordQueryCounter
|
|
31
31
|
if @active_record_query_counter_transaction_start_time && open_transactions == 1
|
32
32
|
end_time = Process.clock_gettime(Process::CLOCK_MONOTONIC)
|
33
33
|
ActiveRecordQueryCounter.add_transaction(@active_record_query_counter_transaction_start_time, end_time)
|
34
|
+
ActiveRecordQueryCounter.increment_rollbacks
|
34
35
|
@active_record_query_counter_transaction_start_time = nil
|
35
36
|
end
|
36
37
|
super
|
@@ -113,6 +113,17 @@ module ActiveRecordQueryCounter
|
|
113
113
|
end
|
114
114
|
end
|
115
115
|
|
116
|
+
# Return the number of rollbacks that have been counted within the current block.
|
117
|
+
# Returns nil if not inside a block where queries are being counted.
|
118
|
+
#
|
119
|
+
# @return [Integer, nil]
|
120
|
+
def increment_rollbacks
|
121
|
+
counter = current_counter
|
122
|
+
return unless counter.is_a?(Counter)
|
123
|
+
|
124
|
+
counter.rollback_count += 1
|
125
|
+
end
|
126
|
+
|
116
127
|
# Return the number of queries that have been counted within the current block.
|
117
128
|
# Returns nil if not inside a block where queries are being counted.
|
118
129
|
#
|
@@ -195,6 +206,15 @@ module ActiveRecordQueryCounter
|
|
195
206
|
counter.transactions if counter.is_a?(Counter)
|
196
207
|
end
|
197
208
|
|
209
|
+
# Return the number of transactions that have rolled back within the current block.
|
210
|
+
# Returns nil if not inside a block where queries are being counted.
|
211
|
+
#
|
212
|
+
# @return [Integer, nil]
|
213
|
+
def rollback_count
|
214
|
+
counter = current_counter
|
215
|
+
counter.rollback_count if counter.is_a?(Counter)
|
216
|
+
end
|
217
|
+
|
198
218
|
# Return the query info as a hash with keys :query_count, :row_count, :query_time
|
199
219
|
# :transaction_count, and :transaction_type or nil if not inside a block where queries
|
200
220
|
# are being counted.
|
@@ -210,7 +230,8 @@ module ActiveRecordQueryCounter
|
|
210
230
|
cached_query_count: counter.cached_query_count,
|
211
231
|
cache_hit_rate: counter.cache_hit_rate,
|
212
232
|
transaction_count: counter.transaction_count,
|
213
|
-
transaction_time: counter.transaction_time
|
233
|
+
transaction_time: counter.transaction_time,
|
234
|
+
rollback_count: counter.rollback_count
|
214
235
|
}
|
215
236
|
end
|
216
237
|
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: 2.
|
4
|
+
version: 2.3.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: 2024-
|
11
|
+
date: 2024-12-17 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: activerecord
|
@@ -62,7 +62,10 @@ files:
|
|
62
62
|
homepage: https://github.com/bdurand/active_record_query_counter
|
63
63
|
licenses:
|
64
64
|
- MIT
|
65
|
-
metadata:
|
65
|
+
metadata:
|
66
|
+
homepage_uri: https://github.com/bdurand/active_record_query_counter
|
67
|
+
source_code_uri: https://github.com/bdurand/active_record_query_counter
|
68
|
+
changelog_uri: https://github.com/bdurand/active_record_query_counter/blob/main/CHANGELOG.md
|
66
69
|
post_install_message:
|
67
70
|
rdoc_options: []
|
68
71
|
require_paths:
|
@@ -78,8 +81,9 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
78
81
|
- !ruby/object:Gem::Version
|
79
82
|
version: '0'
|
80
83
|
requirements: []
|
81
|
-
rubygems_version: 3.4.
|
84
|
+
rubygems_version: 3.4.10
|
82
85
|
signing_key:
|
83
86
|
specification_version: 4
|
84
|
-
summary:
|
87
|
+
summary: Provides detailed insights into how your code interacts with the database
|
88
|
+
by hooking into ActiveRecord.
|
85
89
|
test_files: []
|