active-record-query-count 0.1.4 → 0.1.6

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 61cf944e309b8f269e891b003e767b657f9c89bf78934337199e6189d7f7599b
4
- data.tar.gz: a0b055c5fc44099ad356d366d6ffc259c9c783eaad05ce7585df3034826972a3
3
+ metadata.gz: d095bdca093b9cc7bf7f2e765855daa33c256a6eb6a23f7e7efb70001675f881
4
+ data.tar.gz: 50cf40d3cd40b1ee75096a5518e83289739fcbe381afa484d9db6c4395370a83
5
5
  SHA512:
6
- metadata.gz: e1c83e3b6ecde6b6e1a5eed1e17c844be5ad83430c8ba21d21c24961a4ab2d9dd79c6c1b33e7950e357976bd14e5b7040aed1d77606257ae29ad5d254412c19a
7
- data.tar.gz: c5d0981a4a35f9189fe5aa0e722a326ca1ed83df442d118556898daf63290463d37b385b5fdc5d39d5924066429bcb2e53f04eaa76da0c8472d9316bb486b8ba
6
+ metadata.gz: c13044996330b7784b78afef3a0243d9199c9f694ce5998d9349db9e2fc930d33f22e5425dc235c653c3d1c2283bf811dd484c7ffa7363c606ac0a191d7cfddb
7
+ data.tar.gz: c8f60440c96860f2dff53cd739718a1c28815de9113a7a323def118dbcb63b72442368ef1f90a24ed026c9c5d74c223a14e083ed57c0ae2a3f3988abebe20a8c
data/README.md CHANGED
@@ -1,14 +1,14 @@
1
1
  # ActiveRecordQueryCount
2
2
 
3
- `ActiveRecordQueryCount` is a Ruby gem designed to help you visualize and track SQL queries executed by your ActiveRecord models on a block of code.
3
+ `ActiveRecordQueryCount` is a Ruby gem designed to help you visualize and track the SQL queries executed by your ActiveRecord models within a block of code.
4
4
 
5
- By subscribing to ActiveSupport notifications, it provides detailed insights into the quantity of queries being run, including the tables involved and the locations in your code where the queries are generated.
5
+ By subscribing to ActiveSupport notifications, it provides detailed insights into the number of queries being run, the time taken by the code at specific locations (by adding the time each query took in that place), the tables involved, and the locations in your code where the queries were generated.
6
6
 
7
- There are three things this gem allows you to do:
7
+ This gem offers three key features:
8
8
 
9
- 1. See an overview of all the queries that a code block executes and their origin locations in a graph, a table, or in the console.
10
- 2. Benchmark two blocks of code to view the difference in SQL counts at different locations, with a graph or a table.
11
- 3. See an overview of the current request on a controller action with a button on the top left corner of the screen.
9
+ 1. View an overview of all queries executed by a block of code, including the time taken and their origin locations, presented in a graph, an HTML table, or directly in the console.
10
+ 2. Benchmark two blocks of code to compare SQL query counts at different locations, with results displayed in a graph or table.
11
+ 3. Get an overview of SQL queries for the current request in a controller action, accessible via a button in the top-left corner of the screen.
12
12
 
13
13
  ## Installation
14
14
 
data/assets/style.css CHANGED
@@ -4,10 +4,9 @@
4
4
  width: 100%;
5
5
  border-collapse: collapse;
6
6
  margin-top: 20px;
7
-
8
7
  height: 100%;
9
- overflow:auto;
10
- display: block; /* Ensure the table behaves as a block element */
8
+ overflow: auto;
9
+ display: block;
11
10
  box-sizing: border-box;
12
11
  }
13
12
  th, td {
@@ -17,11 +16,12 @@
17
16
  th {
18
17
  background-color: #f2f2f2;
19
18
  }
20
- tr:nth-child(even) {
21
- background-color: #f9f9f9;
19
+ tr.main-row.even, tr.sub-row.even {
20
+ background-color: #f2f2f2;
22
21
  }
23
- .sub-row {
24
- background-color: #f9f9f9;
22
+
23
+ tr.main-row.odd, tr.sub-row.odd {
24
+ background-color: #ffffff;
25
25
  }
26
26
 
27
27
  .center-container {
@@ -39,4 +39,4 @@
39
39
  #queryTable {
40
40
  display: table;
41
41
  }
42
- }
42
+ }
@@ -3,9 +3,10 @@
3
3
  </style>
4
4
  <div id='query_counter_report_gem'>
5
5
  <h2>Query Count Report</h2>
6
- <p>Total query count on process: <%= total_query_count %></p>
7
- <p>The table will show only tables with more than <%= ::ActiveRecordQueryCount::Configuration.ignore_table_count %> queries</p>
8
- <p>Only the top <%= ::ActiveRecordQueryCount::Configuration.max_locations_per_table %> locations with the most occurrences will be shown.</p>
6
+ <p>Total number of queries in this process: <%= total_query_count %></p>
7
+ <p>Total time spent on queries in this process (ms): <%= total_duration_time %></p>
8
+ <p>Only tables with <%= ::ActiveRecordQueryCount::Configuration.ignore_table_count %> or more queries will be displayed.</p>
9
+ <p>The top <%= ::ActiveRecordQueryCount::Configuration.max_locations_per_table %> locations with the highest occurrences will be shown for each table.</p>
9
10
  <button id="toggleButton" onclick="toggleView()">Show Chart View</button>
10
11
  <button id="toggleColumnButton" onclick="toggleColumnContent()">Show SQL</button>
11
12
 
@@ -19,14 +20,15 @@
19
20
  <th id="columnHeader">File Path</th>
20
21
  <th>Method</th>
21
22
  <th>Location Count</th>
23
+ <th>Total Duration(ms)</th>
22
24
  </tr>
23
- <% filter_data(data).each do |table, info| %>
24
- <tr>
25
+ <% filter_data(data).each_with_index do |(table, info), index| %>
26
+ <tr class="main-row <%= index.even? ? 'even' : 'odd' %>">
25
27
  <td rowspan="<%= info[:location].size + 1 %>"><%= table %></td>
26
28
  <td rowspan="<%= info[:location].size + 1 %>"><%= info[:count] %></td>
27
29
  </tr>
28
30
  <% info[:location].each do |loc, detail| %>
29
- <tr class="sub-row">
31
+ <tr class="sub-row <%= index.even? ? 'even' : 'odd' %>">
30
32
  <% match = loc&.match(/^(?<file_path>.*):in.*`(?<method>.*)'$/) %>
31
33
  <% file_path = match ? match[:file_path] : loc %>
32
34
  <% method = match ? match[:method] : nil %>
@@ -36,6 +38,7 @@
36
38
  </td>
37
39
  <td class="method-column"><%= method %></td>
38
40
  <td><%= detail[:count] %></td>
41
+ <td><%= detail[:duration] %></td>
39
42
  </tr>
40
43
  <% end %>
41
44
  <% end %>
@@ -1,17 +1,26 @@
1
- require 'active_support/notifications'
2
- require_relative 'active_record_query_count/version'
3
- require_relative 'active_record_query_count/configuration'
4
- require_relative 'active_record_query_count/printer/base'
5
- require_relative 'active_record_query_count/printer/console'
6
- require_relative 'active_record_query_count/printer/html'
7
- require_relative 'active_record_query_count/recording/base'
8
- require_relative 'active_record_query_count/recording/tracker'
9
- require_relative 'active_record_query_count/compare/comparator'
10
- require_relative 'active_record_query_count/middleware'
11
- require_relative 'active_record_query_count/printer/html_compare'
12
-
13
1
  module ActiveRecordQueryCount
2
+ autoload :VERSION, 'active_record_query_count/version'
3
+ autoload :Configuration, 'active_record_query_count/configuration'
4
+ autoload :Middleware, 'active_record_query_count/middleware'
5
+
6
+ module Printer
7
+ autoload :Base, 'active_record_query_count/printer/base'
8
+ autoload :Console, 'active_record_query_count/printer/console'
9
+ autoload :Html, 'active_record_query_count/printer/html'
10
+ autoload :HtmlCompare, 'active_record_query_count/printer/html_compare'
11
+ end
12
+
13
+ module Recording
14
+ autoload :Base, 'active_record_query_count/recording/base'
15
+ autoload :Tracker, 'active_record_query_count/recording/tracker'
16
+ end
17
+
18
+ module Compare
19
+ autoload :Comparator, 'active_record_query_count/compare/comparator'
20
+ end
21
+
14
22
  extend Recording::Base
23
+
15
24
  if defined?(Rails::Railtie)
16
25
  class QueryCountRailtie < Rails::Railtie
17
26
  initializer 'active_record_query_count.configure_rails_initialization' do |app|
@@ -26,7 +35,7 @@ module ActiveRecordQueryCount
26
35
  end
27
36
 
28
37
  def tracker
29
- Thread.current[:query_counter_data] ||= Tracker.new
38
+ Thread.current[:query_counter_data] ||= Recording::Tracker.new
30
39
  end
31
40
 
32
41
  def compare
@@ -1,4 +1,3 @@
1
- require 'active_support'
2
1
  require 'active_support/core_ext/module/attribute_accessors'
3
2
 
4
3
  module ActiveRecordQueryCount
@@ -1,3 +1,4 @@
1
+ require 'json'
1
2
  module ActiveRecordQueryCount
2
3
  module Printer
3
4
  class Base
@@ -11,6 +12,11 @@ module ActiveRecordQueryCount
11
12
  INJECT_TEMPLATE_PATH = File.join(parent_dir, 'assets', 'template_for_inject.html.erb')
12
13
 
13
14
  def filter_data data
15
+ data.each_value do |info|
16
+ info[:location].each_value do |detail|
17
+ detail[:duration] = detail[:duration].truncate(2)
18
+ end
19
+ end
14
20
  data = data.select { |_, v| v[:count] >= Configuration.ignore_table_count }
15
21
  data = data.sort_by { |_, v| -v[:count] }.each do |_category, info|
16
22
  info[:location] = info[:location].sort_by do |_, detail|
@@ -30,6 +36,7 @@ module ActiveRecordQueryCount
30
36
  end
31
37
 
32
38
  def open_file html_dest
39
+ require 'launchy'
33
40
  if ENV['WSL_DISTRIBUTION']
34
41
  Launchy.open("file://wsl%24/#{ENV['WSL_DISTRIBUTION']}#{html_dest}")
35
42
  else
@@ -1,5 +1,3 @@
1
- require 'colorize'
2
-
3
1
  module ActiveRecordQueryCount
4
2
  module Printer
5
3
  class Console < Base
@@ -9,6 +7,7 @@ module ActiveRecordQueryCount
9
7
  end
10
8
 
11
9
  def print
10
+ require 'colorize'
12
11
  data = filter_data(@data)
13
12
  puts '[ActiveRecordQueryCount] Query count per table:'.colorize(:blue)
14
13
  puts "Total query count: #{data.values.sum { |v| v[:count] }}\n\n"
@@ -21,6 +20,7 @@ module ActiveRecordQueryCount
21
20
  info[:location].each do |loc, details|
22
21
  puts " - File location: #{loc}"
23
22
  puts " Query count: #{details[:count].to_s.colorize(:blue)}"
23
+ puts " Total Duration(ms): #{details[:duration]}"
24
24
  end
25
25
  puts
26
26
  end
@@ -1,8 +1,4 @@
1
1
  require 'erb'
2
- require 'tempfile'
3
- require 'launchy'
4
- require 'pry-byebug'
5
- require 'json'
6
2
 
7
3
  module ActiveRecordQueryCount
8
4
  module Printer
@@ -14,13 +10,21 @@ module ActiveRecordQueryCount
14
10
  end
15
11
 
16
12
  def chart_data
17
- @chart_data ||= generate_chart_data(data)
13
+ @chart_data ||= generate_chart_js_data(data)
18
14
  end
19
15
 
20
16
  def total_query_count
21
17
  @total_query_count ||= data.values.sum { |v| v[:count] }
22
18
  end
23
19
 
20
+ def total_duration_time
21
+ @total_duration_time ||= data.sum do |_, info|
22
+ info[:location].sum do |_, detail|
23
+ detail[:duration]
24
+ end
25
+ end.truncate(2)
26
+ end
27
+
24
28
  def inject_in_html
25
29
  ERB.new(inject_template_content).result(binding)
26
30
  end
@@ -36,13 +40,13 @@ module ActiveRecordQueryCount
36
40
 
37
41
  private
38
42
 
39
- def generate_chart_data(data)
43
+ def generate_chart_js_data(data)
40
44
  chart_data = { labels: [], data: [], locations: {} }
41
45
  data.each do |table, info|
42
46
  chart_data[:labels] << table
43
47
  chart_data[:data] << info[:count]
44
48
  chart_data[:locations][table] = info[:location].map do |loc, detail|
45
- { location: loc, count: detail[:count] }
49
+ { location: loc, count: detail[:count], duration: detail[:duration] }
46
50
  end
47
51
  end
48
52
  chart_data
@@ -1,8 +1,4 @@
1
1
  require 'erb'
2
- require 'tempfile'
3
- require 'launchy'
4
- require 'pry-byebug'
5
- require 'json'
6
2
 
7
3
  module ActiveRecordQueryCount
8
4
  module Printer
@@ -25,7 +21,7 @@ module ActiveRecordQueryCount
25
21
  tables = data_1.keys | data_2.keys
26
22
  total_query_count_1 = data_1.values.sum { |v| v[:count] }
27
23
  total_query_count_2 = data_2.values.sum { |v| v[:count] }
28
- chart_data = generate_chart_data_compare(data_1, data_2)
24
+ chart_data = generate_chart_js_data_compare(data_1, data_2)
29
25
  # end
30
26
  html_dest = generate_html(binding)
31
27
  open_file(html_dest)
@@ -33,7 +29,7 @@ module ActiveRecordQueryCount
33
29
 
34
30
  private
35
31
 
36
- def generate_chart_data_compare(data_1, data_2)
32
+ def generate_chart_js_data_compare(data_1, data_2)
37
33
  labels = (data_1.keys | data_2.keys).sort
38
34
  chart_data = { labels: [], data_1: {}, data_2: {}, locations: {} }
39
35
  chart_data[:data_1][:name] = @script_1_name
@@ -1,40 +1,46 @@
1
+ require 'active_support/notifications'
2
+
1
3
  module ActiveRecordQueryCount
2
- class Tracker
3
- REGEX_TABLE_SQL = /FROM\s+"(?<table>[^"]+)"/
4
- attr_accessor :active_record_query_tracker, :subscription
4
+ module Recording
5
+ class Tracker
6
+ REGEX_TABLE_SQL = /FROM\s+"(?<table>[^"]+)"/
7
+ attr_accessor :active_record_query_tracker, :subscription
5
8
 
6
- def initialize
7
- reset_query_count
8
- end
9
+ def initialize
10
+ reset_query_count
11
+ end
9
12
 
10
- # This assums that in the same location of the code it will always be the same sql query
11
- def reset_query_count
12
- @active_record_query_tracker = Hash.new do |hash, key|
13
- hash[key] = { count: 0, location: Hash.new do |loc_hash, loc_key|
14
- loc_hash[loc_key] = { count: 0, sql: nil }
15
- end }
13
+ # This assums that in the same location of the code it will always be the same sql query
14
+ def reset_query_count
15
+ @active_record_query_tracker = Hash.new do |hash, key|
16
+ hash[key] = { count: 0, location: Hash.new do |loc_hash, loc_key|
17
+ loc_hash[loc_key] = { count: 0, sql: nil }
18
+ end }
19
+ end
16
20
  end
17
- end
18
21
 
19
- def subscribe
20
- return unless subscription.nil?
22
+ def subscribe
23
+ return unless subscription.nil?
21
24
 
22
- @subscription = ActiveSupport::Notifications.subscribe('sql.active_record') do |_a, _b, _c, _d, payload|
23
- caller_from_sql = caller
24
- sql = payload[:sql]
25
- match = sql.match(REGEX_TABLE_SQL)
26
- if match.present? && match[:table]
27
- actual_location = Rails.backtrace_cleaner.clean(caller_from_sql).first
28
- active_record_query_tracker[match[:table]][:count] += 1
29
- active_record_query_tracker[match[:table]][:location][actual_location][:count] += 1
30
- active_record_query_tracker[match[:table]][:location][actual_location][:sql] = sql
25
+ @subscription = ActiveSupport::Notifications.subscribe('sql.active_record') do |_a, start, finish, _d, payload|
26
+ caller_from_sql = caller
27
+ sql = payload[:sql]
28
+ match = sql.match(REGEX_TABLE_SQL)
29
+ if match.present? && match[:table]
30
+ actual_location = Rails.backtrace_cleaner.clean(caller_from_sql).first
31
+ active_record_query_tracker[match[:table]][:count] += 1
32
+ active_record_query_tracker[match[:table]][:location][actual_location][:duration] ||= 0
33
+ active_record_query_tracker[match[:table]][:location][actual_location][:duration] += (finish - start) * 1000
34
+ active_record_query_tracker[match[:table]][:location][actual_location][:count] += 1
35
+ active_record_query_tracker[match[:table]][:location][actual_location][:sql] = sql
36
+ end
31
37
  end
32
38
  end
33
- end
34
39
 
35
- def unsubscribe
36
- ActiveSupport::Notifications.unsubscribe(@subscription)
37
- @subscription = nil
40
+ def unsubscribe
41
+ ActiveSupport::Notifications.unsubscribe(@subscription)
42
+ @subscription = nil
43
+ end
38
44
  end
39
45
  end
40
46
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module ActiveRecordQueryCount
4
- VERSION = '0.1.4'
4
+ VERSION = '0.1.6'
5
5
  end
@@ -1,4 +1,4 @@
1
- require_relative '../lib/active-record-query-count'
1
+ require 'active-record-query-count'
2
2
  require 'pry-byebug'
3
3
 
4
4
  data_1 = File.read('scripts_for_testing/example_script_unoptimize.yaml')
@@ -1,5 +1,5 @@
1
- require_relative '../lib/active-record-query-count'
2
1
  require 'pry-byebug'
2
+ require 'active-record-query-count'
3
3
 
4
4
  data = File.read('scripts_for_testing/example_script_unoptimize.yaml')
5
5
  data = YAML.safe_load(data, permitted_classes: [Proc, Symbol])
@@ -1,5 +1,5 @@
1
- require_relative '../lib/active-record-query-count'
2
1
  require 'pry-byebug'
2
+ require 'active-record-query-count'
3
3
 
4
4
  data = File.read('scripts_for_testing/example_script_unoptimize.yaml')
5
5
  data = YAML.safe_load(data, permitted_classes: [Proc, Symbol])
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: active-record-query-count
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.4
4
+ version: 0.1.6
5
5
  platform: ruby
6
6
  authors:
7
7
  - Jose Lara
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2024-07-16 00:00:00.000000000 Z
11
+ date: 2025-02-06 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activesupport
@@ -265,7 +265,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
265
265
  requirements:
266
266
  - - ">="
267
267
  - !ruby/object:Gem::Version
268
- version: '2.7'
268
+ version: '3.0'
269
269
  - - "<"
270
270
  - !ruby/object:Gem::Version
271
271
  version: '4.0'
@@ -275,7 +275,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
275
275
  - !ruby/object:Gem::Version
276
276
  version: '0'
277
277
  requirements: []
278
- rubygems_version: 3.4.10
278
+ rubygems_version: 3.5.15
279
279
  signing_key:
280
280
  specification_version: 4
281
281
  summary: Display an overview of the quantity of queries being made and their origins