pg-locks-monitor 0.1.2 → 0.2.1
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 +4 -4
- data/README.md +41 -3
- data/lib/pg-locks-monitor.rb +7 -7
- data/lib/pg_locks_monitor/configuration.rb +5 -0
- data/lib/pg_locks_monitor/version.rb +1 -1
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: c15914dcf0512070ba0f629249a9743c04aad078d6f7dcd23a96acda248284f4
|
4
|
+
data.tar.gz: bbf242ededb3f441489be230e5e013d362c85b0964f34667a89b9ffe12589aa0
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: c17edd2b3419837fd7e6f909ba8f7bf2878a28df97f0f80f0a2a12e5534188895d44f3897372445267ff8d524f1b1825d09c4a77b29ad8a991dedd4b71ba4dfb
|
7
|
+
data.tar.gz: a876c3894b680a8cc20bb29070d1e9dc8af6678cd09ed6293501ede52eecae134ddfb48b37d7441676f9a9f4499f8b0f2eba46108b963da19ebf8f6ef78992ee
|
data/README.md
CHANGED
@@ -36,6 +36,9 @@ PgLocksMonitor.configure do |config|
|
|
36
36
|
config.slack_channel = ""
|
37
37
|
|
38
38
|
config.notifier_class = PgLocksMonitor::DefaultNotifier
|
39
|
+
|
40
|
+
config.locks_filter_proc = ->(lock) { true }
|
41
|
+
config.blocking_filter_proc = ->(lock) { true }
|
39
42
|
end
|
40
43
|
```
|
41
44
|
|
@@ -49,7 +52,8 @@ end
|
|
49
52
|
- `slack_webhook_url` - webhook necessary for Slack notification to work
|
50
53
|
- `slack_channel` - the name of the target Slack channel
|
51
54
|
- `notifier_class` - customizable notifier class
|
52
|
-
|
55
|
+
- `locks_filter_proc` - configurable filter to exclude locks based on any custom logic
|
56
|
+
- `blocking_filter_proc` - configurable filter to exclude blocking locks based on any custom logic
|
53
57
|
|
54
58
|
## Testing the notification channels
|
55
59
|
|
@@ -129,14 +133,18 @@ Here's a sample lock notification:
|
|
129
133
|
"transactionid": null,
|
130
134
|
# bool indicating if the lock is already granted
|
131
135
|
"granted": true,
|
132
|
-
#
|
136
|
+
# mode of the acquired lock
|
133
137
|
"mode": "RowExclusiveLock",
|
134
138
|
# SQL query which acquired the lock
|
135
139
|
"query_snippet": "UPDATE \"users\" SET \"updated_at\" = $1 WHERE \"users\".\"id\" = $2 from/sidekiq_job:UserUpdater/",
|
136
140
|
# age of the lock
|
137
141
|
"age": "PT0.94945S",
|
138
142
|
# app that acquired the lock
|
139
|
-
"application": "bin/sidekiq"
|
143
|
+
"application": "bin/sidekiq",
|
144
|
+
# ID of the database where lock was acquired
|
145
|
+
"database": "84759327",
|
146
|
+
# type of the acquired lock
|
147
|
+
"locktype": "relation",
|
140
148
|
},
|
141
149
|
```
|
142
150
|
|
@@ -177,6 +185,36 @@ A background job that schedules itself is not the cleanest pattern. So alternati
|
|
177
185
|
|
178
186
|
A recommended frequency of invocation depends on your app's traffic. From my experience, even 1 minute apart snapshots can provide a lot of valuable data, but it all depends on how often the locks are occurring in your Rails application.
|
179
187
|
|
188
|
+
## Filter procs
|
189
|
+
|
190
|
+
You can modify `locks_filter_proc` and `blocking_filter_proc` to exclude locks from getting reported. For example, here's how you can report only locks that originated from the Puma server process:
|
191
|
+
|
192
|
+
`config/initializers/pg_locks_monitor.rb`
|
193
|
+
```ruby
|
194
|
+
PgLocksMonitor.configure do |config|
|
195
|
+
# ...
|
196
|
+
|
197
|
+
config.locks_filter_proc = -> (lock) {
|
198
|
+
lock.fetch("application").downcase.include?("puma")
|
199
|
+
}
|
200
|
+
end
|
201
|
+
```
|
202
|
+
|
203
|
+
or exclude blocking locks which are affecting only the Sidekiq process:
|
204
|
+
|
205
|
+
`config/initializers/pg_locks_monitor.rb`
|
206
|
+
```ruby
|
207
|
+
PgLocksMonitor.configure do |config|
|
208
|
+
# ...
|
209
|
+
|
210
|
+
config.blocking_filter_proc = -> (lock) {
|
211
|
+
!lock.fetch("blocked_sql_app").downcase.include?("sidekiq")
|
212
|
+
}
|
213
|
+
end
|
214
|
+
```
|
215
|
+
|
216
|
+
Please beware that configuring these procs does not overwrite the min duration settings, i.e., `locks_min_duration_ms` and `blocking_min_duration_ms`.
|
217
|
+
|
180
218
|
## Custom notifier class
|
181
219
|
|
182
220
|
`PgLocksMonitor::DefaultNotifier` supports sending lock notifications with `Rails.logger` or to a Slack channel. If you want to use different notification channels you can define your custom notifier like that:
|
data/lib/pg-locks-monitor.rb
CHANGED
@@ -5,23 +5,23 @@ require "pg"
|
|
5
5
|
|
6
6
|
module PgLocksMonitor
|
7
7
|
def self.snapshot!
|
8
|
-
locks =
|
9
|
-
in_format: :hash,
|
10
|
-
limit: configuration.locks_limit,
|
11
|
-
},
|
8
|
+
locks = RubyPgExtras.locks(
|
9
|
+
in_format: :hash,
|
12
10
|
).select do |lock|
|
13
11
|
if (age = lock.fetch("age"))
|
14
12
|
(ActiveSupport::Duration.parse(age).to_f * 1000) > configuration.locks_min_duration_ms
|
15
13
|
end
|
16
|
-
end
|
14
|
+
end.select(&configuration.locks_filter_proc)
|
15
|
+
.first(configuration.locks_limit)
|
17
16
|
|
18
17
|
if locks.present? && configuration.monitor_locks
|
19
18
|
configuration.notifier_class.call(locks)
|
20
19
|
end
|
21
20
|
|
22
|
-
blocking =
|
21
|
+
blocking = RubyPgExtras.blocking(in_format: :hash).select do |block|
|
23
22
|
(ActiveSupport::Duration.parse(block.fetch("blocking_duration")).to_f * 1000) > configuration.blocking_min_duration_ms
|
24
|
-
end
|
23
|
+
end.select(&configuration.blocking_filter_proc)
|
24
|
+
.first(configuration.locks_limit)
|
25
25
|
|
26
26
|
if blocking.present? && configuration.monitor_blocking
|
27
27
|
configuration.notifier_class.call(blocking)
|
@@ -13,6 +13,8 @@ module PgLocksMonitor
|
|
13
13
|
slack_webhook_url: nil,
|
14
14
|
slack_channel: nil,
|
15
15
|
notifier_class: PgLocksMonitor::DefaultNotifier,
|
16
|
+
locks_filter_proc: ->(lock) { true },
|
17
|
+
blocking_filter_proc: ->(lock) { true },
|
16
18
|
}
|
17
19
|
|
18
20
|
attr_accessor *DEFAULT.keys
|
@@ -43,6 +45,9 @@ PgLocksMonitor.configure do |config|
|
|
43
45
|
config.slack_channel = "#{DEFAULT[:slack_channel]}"
|
44
46
|
|
45
47
|
config.notifier_class = #{DEFAULT[:notifier_class]}
|
48
|
+
|
49
|
+
config.locks_filter_proc = ->(lock) { true }
|
50
|
+
config.blocking_filter_proc = ->(lock) { true }
|
46
51
|
end
|
47
52
|
CONFIG
|
48
53
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: pg-locks-monitor
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1
|
4
|
+
version: 0.2.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- pawurb
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2024-
|
11
|
+
date: 2024-10-02 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: ruby-pg-extras
|