pg_reports 0.6.1 → 0.6.2

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: 77275298b8ef6a1dba986e9b47849d1685e2d09cacdd64e3b086b20ab403574c
4
- data.tar.gz: 893da425321112adf5d4f9944fb72028898c77119ec95ad92d27c21681a80a0e
3
+ metadata.gz: a61a108ff2ba498edaa622cfc11f3f746d56a54f1b964ced3e941516c2eaaec4
4
+ data.tar.gz: 9e0d3da7d606309d51c64e5daf96e66875a6645f23649433d98001209be175d7
5
5
  SHA512:
6
- metadata.gz: c99a83908899a5896734b7025b4b593dad0c0d4045b9578e1912ccb332aa9f29dcb0c1e79fe69a403f4a248e99a540fc1b0627af44d7ddc1c1c889c738c1ffa7
7
- data.tar.gz: 4ff3fe8ae5a907dee4a6eb9186adb1e9819d49e62c84c7447c49999dd2c4f09d01cd962711461437f18f1853ba1c3ea9b226af5a822a373034f61f93521ef1f5
6
+ metadata.gz: f25452a5db23c9288b02334d4c900b838d063e8d754695d0047f931b24d1ec7c2b6a98fbfea3898277df0c124a3cbc52ed40f22e325adc85af503a6d9db43351
7
+ data.tar.gz: 046aca0f21ec77c649f3a5a0658aac92ba4c44bedbd15ec979838b183574b16fe67fcaebf8e7b6b3727de9f082712b7f67ed321c0f8c89723cffbc59cd93e845
data/CHANGELOG.md CHANGED
@@ -7,6 +7,22 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
7
7
 
8
8
  ## [Unreleased]
9
9
 
10
+ ## [0.6.2] - 2026-04-25
11
+
12
+ ### Added
13
+
14
+ - **Native Rails QueryLogs source_location support** — `AnnotationParser` now recognizes the `source_location` tag emitted by `ActiveRecord::QueryLogs` and splits it into separate `:file` / `:line` fields for the dashboard's source column. Values are URL-decoded first, since Rails CGI-escapes tag values (so `%2F.../%3A19` becomes `/.../foo.rb:19`).
15
+
16
+ ### Fixed
17
+
18
+ - **`counter_cache_issues` crashed/misreported on Rails 7.1+ Hash form.** `belongs_to :user, counter_cache: :col` is internally normalized to `{active: true, column: :col}` on Rails 7.1+, but the helper only handled `true` / Symbol / String — so the column came out as `Hash#inspect` (`{active: true, column: "usage_count"}`) and the suggested migration was malformed. `counter_cache_column_name` now handles all four forms (Boolean, Symbol, String, Hash with `:column` key, Hash without `:column`).
19
+ - **`polymorphic_without_index` crashed with `NoMethodError: undefined method '&' for an instance of String`** when a table had an expression index (e.g. `CREATE INDEX ON x (LOWER(email))`). PostgreSQL returns `IndexDefinition#columns` as a String for expression indexes, not an Array. Both the polymorphic check and `coverage_label` now filter out non-array indexes.
20
+
21
+ ### Changed
22
+
23
+ - **README simplified** — full reports listing moved to [docs/reports.md](docs/reports.md), long sections (EXPLAIN ANALYZE, SQL Query Monitor, Connection pool analytics, IDE integration, Telegram delivery, raw query execution, source tracking) collapsed into `<details>` blocks. From 582 lines to ~340.
24
+ - **Query source tracking** documentation now leads with native `ActiveRecord::QueryLogs` (Rails 7.0+) including a `source_location` lambda example. Marginalia mentioned only as the option for Rails < 7.0.
25
+
10
26
  ## [0.6.1] - 2026-04-24
11
27
 
12
28
  ### Added
data/README.md CHANGED
@@ -131,25 +131,40 @@ end
131
131
  </details>
132
132
 
133
133
  <details>
134
- <summary><strong>Query source tracking (Marginalia / Rails query logs)</strong></summary>
134
+ <summary><strong>Query source tracking (Rails query logs)</strong></summary>
135
135
 
136
- PgReports parses query annotations to show **where queries originated**.
136
+ PgReports parses query annotations to show **where queries originated**. On Rails 7.0+ use the built-in `ActiveRecord::QueryLogs` (no extra gem needed). On older Rails, install [Marginalia](https://github.com/basecamp/marginalia) — PgReports auto-detects both formats.
137
137
 
138
- [Marginalia](https://github.com/basecamp/marginalia):
138
+ Minimal setup — adds controller/action:
139
139
 
140
140
  ```ruby
141
- gem "marginalia"
141
+ # config/application.rb
142
+ config.active_record.query_log_tags_enabled = true
143
+ config.active_record.query_log_tags = [:controller, :action]
142
144
  ```
143
145
 
144
- Rails 7+ query logs:
146
+ To also surface **file path and line number** (so source links jump to the actual call site, not just the controller), add a custom `source_location` lambda that walks `caller_locations` and skips gem/framework frames:
145
147
 
146
148
  ```ruby
147
149
  # config/application.rb
148
150
  config.active_record.query_log_tags_enabled = true
149
- config.active_record.query_log_tags = [:controller, :action]
151
+ config.active_record.query_log_tags = [
152
+ :controller,
153
+ :action,
154
+ :job,
155
+ {
156
+ source_location: -> {
157
+ ignore = %r{/(gems|active_record|active_support|active_model|railties|
158
+ action_controller|action_view|action_pack|action_dispatch|
159
+ rack|core_ext|relation|associations|scoping|connection_adapters)/}x
160
+ loc = caller_locations.find { |l| !l.path.match?(ignore) }
161
+ "#{loc.path}:#{loc.lineno}" if loc
162
+ }
163
+ }
164
+ ]
150
165
  ```
151
166
 
152
- Either form is auto-detected; controller/action and file:line appear in the **source** column on report rows.
167
+ PgReports recognizes the `source_location` tag and splits it into file and line for the **source** column.
153
168
 
154
169
  </details>
155
170
 
@@ -284,7 +299,10 @@ The Export dropdown includes **Copy Prompt** (visible on actionable reports). It
284
299
 
285
300
  </details>
286
301
 
287
- ## Telegram
302
+ <details>
303
+ <summary><strong>Telegram delivery</strong></summary>
304
+
305
+ Get a bot token from [@BotFather](https://t.me/BotFather) and your chat ID from [@userinfobot](https://t.me/userinfobot), then:
288
306
 
289
307
  ```ruby
290
308
  PgReports.configure do |config|
@@ -296,7 +314,9 @@ PgReports.slow_queries.send_to_telegram
296
314
  PgReports.health_report.send_to_telegram_as_file
297
315
  ```
298
316
 
299
- Get a bot token from [@BotFather](https://t.me/BotFather) and your chat ID from [@userinfobot](https://t.me/userinfobot).
317
+ Reports under ~50 rows go as a message; larger ones are sent as a file attachment.
318
+
319
+ </details>
300
320
 
301
321
  ## Development
302
322
 
@@ -1,10 +1,12 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require "cgi"
4
+
3
5
  module PgReports
4
6
  # Parses SQL query comments to extract source location and metadata
5
7
  # Supports:
6
8
  # - Marginalia format: /*application:myapp,controller:users,action:index*/
7
- # - Rails QueryLogs: /*action='index',controller='users'*/
9
+ # - Rails QueryLogs: /*action='index',controller='users',source_location='app/foo.rb:42'*/
8
10
  #
9
11
  module AnnotationParser
10
12
  class << self
@@ -32,6 +34,16 @@ module PgReports
32
34
  end
33
35
  end
34
36
 
37
+ # Rails QueryLogs custom tag — Rails URL-encodes tag values (CGI.escape) to keep
38
+ # SQL comments safe, so "/" → "%2F" and ":" → "%3A". Decode then split into :file/:line.
39
+ if result[:source_location] && !result[:file]
40
+ decoded = CGI.unescape(result[:source_location].to_s)
41
+ if (match = decoded.match(%r{^(.+):(\d+)$}))
42
+ result[:file] = match[1]
43
+ result[:line] = match[2]
44
+ end
45
+ end
46
+
35
47
  result
36
48
  end
37
49
 
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module PgReports
4
- VERSION = "0.6.1"
4
+ VERSION = "0.6.2"
5
5
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: pg_reports
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.6.1
4
+ version: 0.6.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Eldar Avatov