Skip to content

Commit 76a555d

Browse files
committed
Enhance performance monitoring and reporting features
- Added `detection_window` property to `CQL::Performance::Config` for configurable query detection window. - Introduced `stats_trackers` abstract method in `CQL::Performance::Interfaces` for retrieving statistics. - Removed `CacheStats` struct from `CQL::Performance::Monitor` and adjusted related methods. - Updated `CQL::Performance::NPlusOneDetector` to utilize `detection_window` and added thread safety with mutex. - Enhanced `CQL::Performance::PerformanceMetrics` to return metrics in a more consistent format. - Improved `CQL::Performance::QueryProfiler` to manage slow queries with mutex for thread safety. - Refactored `CQL::Performance::Utilities` to ensure thread-safe operations on performance metrics. - Updated `CQL::Performance::UnifiedReportGenerator` to format reports more cleanly and added JSON serialization methods. - Enhanced console output formatting for performance reports to improve readability.
1 parent ae93b6f commit 76a555d

15 files changed

Lines changed: 3726 additions & 227 deletions

spec/performance/config_spec.cr

Lines changed: 448 additions & 0 deletions
Large diffs are not rendered by default.

spec/performance/monitor_spec.cr

Lines changed: 454 additions & 0 deletions
Large diffs are not rendered by default.

spec/performance/n_plus_one_detector_spec.cr

Lines changed: 522 additions & 0 deletions
Large diffs are not rendered by default.

spec/performance/query_profiler_spec.cr

Lines changed: 781 additions & 0 deletions
Large diffs are not rendered by default.
Lines changed: 200 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,200 @@
1+
require "../spec_helper"
2+
require "../../src/performance/sql_formatter"
3+
4+
describe CQL::Performance::SQLFormatter do
5+
# Disable colorization for predictable test output
6+
before_each do
7+
Colorize.enabled = false
8+
end
9+
10+
after_each do
11+
Colorize.enabled = true
12+
end
13+
14+
describe "#format" do
15+
it "formats SQL with params" do
16+
formatter = CQL::Performance::SQLFormatter.new(colorize_enabled: false, pretty_format: false)
17+
result = formatter.format("SELECT * FROM users WHERE id = ?", [1] of DB::Any)
18+
result.should contain("SQL")
19+
result.should contain("SELECT * FROM users WHERE id = ?")
20+
result.should contain("Parameters:")
21+
result.should contain("[1]")
22+
end
23+
24+
it "formats SQL without params" do
25+
formatter = CQL::Performance::SQLFormatter.new(colorize_enabled: false, pretty_format: false)
26+
result = formatter.format("SELECT * FROM users")
27+
result.should contain("SQL")
28+
result.should contain("SELECT * FROM users")
29+
result.should_not contain("Parameters:")
30+
end
31+
32+
it "includes execution time when provided" do
33+
formatter = CQL::Performance::SQLFormatter.new(colorize_enabled: false, pretty_format: false)
34+
result = formatter.format("SELECT 1", execution_time: 50.milliseconds)
35+
result.should contain("SQL")
36+
end
37+
38+
it "includes rows affected when provided" do
39+
formatter = CQL::Performance::SQLFormatter.new(colorize_enabled: false, pretty_format: false)
40+
result = formatter.format("UPDATE users SET name = ?", ["test"] of DB::Any, rows_affected: 5_i64)
41+
result.should contain("5 rows")
42+
end
43+
44+
it "includes context when provided" do
45+
formatter = CQL::Performance::SQLFormatter.new(colorize_enabled: false, pretty_format: false)
46+
result = formatter.format("SELECT 1", context: "test-context")
47+
result.should contain("test-context")
48+
end
49+
end
50+
51+
describe "#format_sql_only" do
52+
it "formats just the SQL without metadata" do
53+
formatter = CQL::Performance::SQLFormatter.new(colorize_enabled: false, pretty_format: false)
54+
result = formatter.format_sql_only("SELECT * FROM users WHERE id = ?")
55+
result.should eq("SELECT * FROM users WHERE id = ?")
56+
end
57+
58+
it "applies pretty formatting when enabled" do
59+
formatter = CQL::Performance::SQLFormatter.new(colorize_enabled: false, pretty_format: true)
60+
result = formatter.format_sql_only("SELECT * FROM users WHERE id = 1")
61+
result.should contain("SELECT")
62+
result.should contain("FROM")
63+
result.should contain("WHERE")
64+
end
65+
66+
it "does not apply pretty formatting when disabled" do
67+
formatter = CQL::Performance::SQLFormatter.new(colorize_enabled: false, pretty_format: false)
68+
sql = "SELECT * FROM users"
69+
result = formatter.format_sql_only(sql)
70+
result.should eq(sql)
71+
end
72+
end
73+
74+
describe "#format_params" do
75+
it "formats a parameter array" do
76+
formatter = CQL::Performance::SQLFormatter.new(colorize_enabled: false)
77+
params = [1, "hello"] of DB::Any
78+
result = formatter.format_params(params)
79+
result.should eq("[1, hello]")
80+
end
81+
82+
it "returns empty brackets for empty params" do
83+
formatter = CQL::Performance::SQLFormatter.new(colorize_enabled: false)
84+
result = formatter.format_params([] of DB::Any)
85+
result.should eq("[]")
86+
end
87+
88+
it "truncates long parameter values at max_param_length" do
89+
formatter = CQL::Performance::SQLFormatter.new(colorize_enabled: false, max_param_length: 10)
90+
long_string = "a" * 50
91+
params = [long_string] of DB::Any
92+
result = formatter.format_params(params)
93+
result.should contain("aaaaaaaaaa...")
94+
result.should_not contain(long_string)
95+
end
96+
97+
it "does not truncate short parameter values" do
98+
formatter = CQL::Performance::SQLFormatter.new(colorize_enabled: false, max_param_length: 50)
99+
params = ["short"] of DB::Any
100+
result = formatter.format_params(params)
101+
result.should eq("[short]")
102+
end
103+
104+
it "formats multiple parameters separated by commas" do
105+
formatter = CQL::Performance::SQLFormatter.new(colorize_enabled: false)
106+
params = [1, "two", 3] of DB::Any
107+
result = formatter.format_params(params)
108+
result.should eq("[1, two, 3]")
109+
end
110+
end
111+
112+
describe "#configure" do
113+
it "updates colorize setting" do
114+
formatter = CQL::Performance::SQLFormatter.new(colorize_enabled: false, pretty_format: false)
115+
formatter.configure(colorize: false)
116+
result = formatter.format_sql_only("SELECT 1")
117+
result.should eq("SELECT 1")
118+
end
119+
120+
it "updates pretty format setting" do
121+
formatter = CQL::Performance::SQLFormatter.new(colorize_enabled: false, pretty_format: false)
122+
formatter.configure(pretty: true)
123+
result = formatter.format_sql_only("SELECT * FROM users WHERE id = 1")
124+
result.should contain("\n")
125+
end
126+
127+
it "updates max_sql_length setting" do
128+
formatter = CQL::Performance::SQLFormatter.new(colorize_enabled: false, pretty_format: false)
129+
formatter.configure(max_sql: 20)
130+
result = formatter.format("SELECT * FROM users WHERE id = 1 AND name = 'test'")
131+
result.should contain("...")
132+
end
133+
134+
it "updates max_param_length setting" do
135+
formatter = CQL::Performance::SQLFormatter.new(colorize_enabled: false)
136+
formatter.configure(max_param: 5)
137+
params = ["longvalue"] of DB::Any
138+
result = formatter.format_params(params)
139+
result.should contain("longv...")
140+
end
141+
end
142+
143+
describe "SQL truncation" do
144+
it "truncates SQL at max_sql_length" do
145+
formatter = CQL::Performance::SQLFormatter.new(colorize_enabled: false, pretty_format: false, max_sql_length: 30)
146+
long_sql = "SELECT * FROM users WHERE id = 1 AND name = 'test' AND email = 'foo@bar.com'"
147+
result = formatter.format(long_sql)
148+
result.should contain("...")
149+
end
150+
151+
it "does not truncate SQL shorter than max_sql_length" do
152+
formatter = CQL::Performance::SQLFormatter.new(colorize_enabled: false, pretty_format: false, max_sql_length: 500)
153+
short_sql = "SELECT * FROM users"
154+
result = formatter.format(short_sql)
155+
result.should contain("SELECT * FROM users")
156+
result.should_not contain("...")
157+
end
158+
end
159+
160+
describe "pretty formatting" do
161+
it "adds line breaks at SQL keywords" do
162+
formatter = CQL::Performance::SQLFormatter.new(colorize_enabled: false, pretty_format: true)
163+
sql = "SELECT id, name FROM users WHERE active = 1 ORDER BY name"
164+
result = formatter.format_sql_only(sql)
165+
result.should contain("\n")
166+
result.should contain("SELECT")
167+
result.should contain("FROM")
168+
result.should contain("WHERE")
169+
result.should contain("ORDER BY")
170+
end
171+
172+
it "adds line breaks for JOIN clauses" do
173+
formatter = CQL::Performance::SQLFormatter.new(colorize_enabled: false, pretty_format: true)
174+
sql = "SELECT * FROM users INNER JOIN orders ON users.id = orders.user_id"
175+
result = formatter.format_sql_only(sql)
176+
result.should contain("INNER JOIN")
177+
end
178+
179+
it "normalizes whitespace in SQL" do
180+
formatter = CQL::Performance::SQLFormatter.new(colorize_enabled: false, pretty_format: true)
181+
sql = "SELECT * FROM users WHERE id = 1"
182+
result = formatter.format_sql_only(sql)
183+
result.should_not contain(" ")
184+
end
185+
end
186+
187+
describe "empty params handling" do
188+
it "does not include parameters section when params are empty" do
189+
formatter = CQL::Performance::SQLFormatter.new(colorize_enabled: false, pretty_format: false)
190+
result = formatter.format("SELECT * FROM users", [] of DB::Any)
191+
result.should_not contain("Parameters:")
192+
end
193+
194+
it "format_params returns empty brackets for empty array" do
195+
formatter = CQL::Performance::SQLFormatter.new(colorize_enabled: false)
196+
result = formatter.format_params([] of DB::Any)
197+
result.should eq("[]")
198+
end
199+
end
200+
end

0 commit comments

Comments
 (0)