arlequin 0.1.0 → 0.1.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/lib/arlequin/middleware.rb +74 -7
- data/lib/arlequin.rb +50 -1
- metadata +3 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: c730c5e938ae2adf97538d4d30c69118a6dc4a9f8c290ed476cb8ea7d9115975
|
4
|
+
data.tar.gz: c815726ab257c2c478f55783ca90e1e7a5f948b819099fc607ffad1114336cfb
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 726f9a8bb3f4c94aca726b43cdf3aa4bb09101122690ce78eab7ac90fa0ba34b4a2a222e39f6ebad1e9cb3f94f72f4b3fb9aa79ba2b8dcf889538f6db35af5e0
|
7
|
+
data.tar.gz: b87de6cdb5c012cb6471a5b6497f3f6cb765774fe4f87ab6837ed496f07b32b106971a0fe5d6b473041a592a0d42c220afc85602102987b783d10345d77daeb4
|
data/lib/arlequin/middleware.rb
CHANGED
@@ -1,40 +1,107 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
module Arlequin
|
4
|
+
##
|
5
|
+
# Middleware to detect and warn about N+1 queries in a Rails application.
|
4
6
|
class Middleware
|
7
|
+
##
|
8
|
+
# Initializes the middleware with the given app.
|
9
|
+
#
|
10
|
+
# @param app [Object] The Rack application this middleware wraps.
|
5
11
|
def initialize(app)
|
6
12
|
@app = app
|
7
13
|
end
|
8
14
|
|
15
|
+
##
|
16
|
+
# Processes the incoming request, detects N+1 queries, and injects a warning
|
17
|
+
# into the HTML response if necessary.
|
18
|
+
#
|
19
|
+
# @param env [Hash] The Rack environment.
|
20
|
+
# @return [Array] The status, headers, and response of the Rack application.
|
9
21
|
def call(env)
|
10
|
-
# Set up a query counter
|
11
22
|
@queries = Hash.new { |hash, key| hash[key] = 0 }
|
12
|
-
|
13
23
|
ActiveSupport::Notifications.subscribe("sql.active_record", &method(:on_sql))
|
14
24
|
|
15
25
|
status, headers, response = @app.call(env)
|
16
26
|
|
17
|
-
|
18
|
-
|
27
|
+
if n_plus_one_detected?
|
28
|
+
html_fragment = generate_html_warning
|
29
|
+
response = inject_html_fragment(response, html_fragment)
|
30
|
+
end
|
31
|
+
|
32
|
+
ActiveSupport::Notifications.unsubscribe("sql.active_record")
|
19
33
|
|
20
34
|
[ status, headers, response ]
|
21
35
|
end
|
22
36
|
|
23
37
|
private
|
24
38
|
|
39
|
+
##
|
40
|
+
# Callback for ActiveSupport notifications on SQL queries.
|
41
|
+
#
|
42
|
+
# @param _name [String] The event name.
|
43
|
+
# @param _start [Time] The start time of the event.
|
44
|
+
# @param _finish [Time] The finish time of the event.
|
45
|
+
# @param _id [String] The event ID.
|
46
|
+
# @param payload [Hash] The event payload containing SQL information.
|
25
47
|
def on_sql(_name, _start, _finish, _id, payload)
|
26
|
-
return if payload[:name] == "SCHEMA"
|
48
|
+
return if payload[:name] == "SCHEMA"
|
27
49
|
|
28
50
|
query = payload[:sql]
|
29
51
|
@queries[query] += 1
|
30
52
|
end
|
31
53
|
|
32
|
-
|
54
|
+
##
|
55
|
+
# Generates warnings for detected N+1 queries.
|
56
|
+
#
|
57
|
+
# @return [Array<String>] The list of N+1 query warnings.
|
58
|
+
def n_plus_one_warnings
|
59
|
+
warnings = []
|
60
|
+
|
33
61
|
@queries.each do |query, count|
|
34
62
|
if count > 1
|
35
|
-
|
63
|
+
warnings << "N+1 query detected: #{query}, executed #{count} times"
|
36
64
|
end
|
37
65
|
end
|
66
|
+
|
67
|
+
warnings
|
68
|
+
end
|
69
|
+
|
70
|
+
##
|
71
|
+
# Checks if any N+1 queries have been detected.
|
72
|
+
#
|
73
|
+
# @return [Boolean] True if N+1 queries are detected, otherwise false.
|
74
|
+
def n_plus_one_detected?
|
75
|
+
@queries.values.any? { |count| count > 1 }
|
76
|
+
end
|
77
|
+
|
78
|
+
##
|
79
|
+
# Generates an HTML warning for detected N+1 queries.
|
80
|
+
#
|
81
|
+
# @return [String] The HTML warning to be injected into the response.
|
82
|
+
def generate_html_warning
|
83
|
+
"<div style='z-index: 9999; position: fixed; bottom: 0; left: 0; width: 100%; background-color: blue; color: white; text-align: center; padding: 5px;'>" +
|
84
|
+
"N+1 query detected! Check your queries. " +
|
85
|
+
n_plus_one_warnings.join("<br>") +
|
86
|
+
"</div>"
|
87
|
+
end
|
88
|
+
|
89
|
+
##
|
90
|
+
# Injects an HTML fragment into the response body.
|
91
|
+
#
|
92
|
+
# @param response [Array<String>] The original response body.
|
93
|
+
# @param fragment [String] The HTML fragment to inject.
|
94
|
+
# @return [Array<String>] The modified response body.
|
95
|
+
def inject_html_fragment(response, fragment)
|
96
|
+
body = + ""
|
97
|
+
|
98
|
+
response.each do |part|
|
99
|
+
body << part
|
100
|
+
end
|
101
|
+
|
102
|
+
body.sub!("</body>", "#{fragment}</body>")
|
103
|
+
|
104
|
+
[ body ]
|
38
105
|
end
|
39
106
|
end
|
40
107
|
end
|
data/lib/arlequin.rb
CHANGED
@@ -1,7 +1,56 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
|
3
|
+
require "active_support/all"
|
4
|
+
require "arlequin/middleware"
|
5
|
+
|
6
|
+
module Arlequin
|
7
|
+
# The `Railtie` class integrates the Arlequin middleware into Rails applications.
|
8
|
+
#
|
9
|
+
# This Railtie automatically adds the Arlequin middleware to the Rails middleware stack,
|
10
|
+
# but it is intended to be used only in the development environment. It helps in monitoring
|
11
|
+
# and providing warnings about N+1 SQL queries during development.
|
12
|
+
#
|
13
|
+
# ## Configuration
|
14
|
+
#
|
15
|
+
# To use Arlequin in your Rails application, you should include it in the development group
|
16
|
+
# of your Gemfile and require it in the application configuration.
|
17
|
+
#
|
18
|
+
# Example Gemfile configuration:
|
19
|
+
#
|
20
|
+
# group :development do
|
21
|
+
# gem 'arlequin'
|
22
|
+
# end
|
23
|
+
#
|
24
|
+
# To ensure the middleware is used in development, require the Railtie in your application:
|
25
|
+
#
|
26
|
+
# # In `config/application.rb`
|
27
|
+
# require "arlequin/railtie"
|
28
|
+
#
|
29
|
+
# module YourApp
|
30
|
+
# class Application < Rails::Application
|
31
|
+
# # other configurations
|
32
|
+
# # Ensure that the Railtie is required
|
33
|
+
# end
|
34
|
+
# end
|
35
|
+
#
|
36
|
+
# This setup will automatically add the Arlequin middleware to the middleware stack
|
37
|
+
# when running in development mode. The middleware will then be used to detect and
|
38
|
+
# provide warnings for N+1 SQL queries.
|
39
|
+
#
|
40
|
+
# ## Usage
|
41
|
+
#
|
42
|
+
# Once configured, the Arlequin middleware will monitor SQL queries and inject a warning
|
43
|
+
# into the response HTML if N+1 queries are detected.
|
44
|
+
#
|
45
|
+
# The Railtie is part of the Arlequin gem and is designed to integrate seamlessly into
|
46
|
+
# Rails applications for development purposes, facilitating easier identification and
|
47
|
+
# resolution of N+1 query issues.
|
4
48
|
class Railtie < Rails::Railtie
|
49
|
+
# Initializes the Railtie and configures the Rails application to use the Arlequin middleware.
|
50
|
+
#
|
51
|
+
# This method is called during the initialization process of the Rails application.
|
52
|
+
# It adds the Arlequin middleware to the middleware stack in development environments,
|
53
|
+
# allowing it to intercept requests and monitor SQL queries.
|
5
54
|
initializer "arlequin.configure_rails_initialization" do |app|
|
6
55
|
app.middleware.use Arlequin::Middleware
|
7
56
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: arlequin
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Dominic Goulet
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2024-07-
|
11
|
+
date: 2024-07-25 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rails
|
@@ -32,7 +32,7 @@ extra_rdoc_files: []
|
|
32
32
|
files:
|
33
33
|
- lib/arlequin.rb
|
34
34
|
- lib/arlequin/middleware.rb
|
35
|
-
homepage: https://
|
35
|
+
homepage: https://github.com/dominicgoulet/arlequin
|
36
36
|
licenses:
|
37
37
|
- MIT
|
38
38
|
metadata: {}
|