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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: d1cdcf1754671326b02e939ec99c90c2cd8d696bdcbdc82c6c84b378e0365f3b
4
- data.tar.gz: ad862bd65e1db50465ee1456ac18619abeb9f9f10dded487f335348f036b5d1c
3
+ metadata.gz: c15914dcf0512070ba0f629249a9743c04aad078d6f7dcd23a96acda248284f4
4
+ data.tar.gz: bbf242ededb3f441489be230e5e013d362c85b0964f34667a89b9ffe12589aa0
5
5
  SHA512:
6
- metadata.gz: f20cb497a1ba37843441cb244fb581ab26ad7181ea1310c4c8d1db75f243fdac3ea05c9ec0b460b1c9bfe23827cb46360885fb24fef8747879d57342d4ad28cd
7
- data.tar.gz: 9e9493e65efff88e07b33c08f8c7886b7b42b45939d07afe904600c7a9036896255756bcb7a7451754482f03bd150feb89db052a4766e8716e9f230832ed4b61
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
- # type of the acquired lock
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:
@@ -5,23 +5,23 @@ require "pg"
5
5
 
6
6
  module PgLocksMonitor
7
7
  def self.snapshot!
8
- locks = RailsPgExtras.locks(
9
- in_format: :hash, args: {
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 = RailsPgExtras.blocking(in_format: :hash).select do |block|
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
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module PgLocksMonitor
4
- VERSION = "0.1.2"
4
+ VERSION = "0.2.1"
5
5
  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.2
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-09-17 00:00:00.000000000 Z
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