Fix: Invalid JSON on gc-stats (#1801)#4
Conversation
* Fix: Invalid JSON on gc-stats Credits of this patch should be for @jdsundberg, who reported the issue but never sent a patch. Link to his bug report is below. Closes puma#1687. * Update tests so JSON response is correctly parsed JSON without a whitespace between key and values wasn't being correctly parsed (for example: `key: 'value'` was processed ok, but `key:'value'` wasn't).
📝 WalkthroughWalkthroughThis change refactors GC statistics serialization in Puma's status endpoint and corresponding tests. The codebase replaces manual JSON string construction with standard Changes
Estimated code review effort🎯 2 (Simple) | ⏱️ ~8 minutes Poem
🚥 Pre-merge checks | ✅ 1 | ❌ 2❌ Failed checks (2 warnings)
✅ Passed checks (1 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing touches
🧪 Generate unit tests (beta)
Warning There were issues while running some tools. Please review the errors and either fix the tool's configuration or disable the tool if it's a critical failure. 🔧 RuboCop (1.84.0)lib/puma/app/status.rbError: The test/test_cli.rbError: The Comment |
There was a problem hiding this comment.
Actionable comments posted: 0
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
test/test_cli.rb (1)
177-185:⚠️ Potential issue | 🟠 MajorIncomplete fix: First gc-stats parsing still uses manual regex extraction.
The PR objective is to fix JSON parsing issues, but only the second gc-stats call (line 199) was updated to use
JSON.parse. The first gc-stats parsing (lines 177-185) still uses the fragile manual regex approach that was the source of the original bug.This inconsistency means:
- The first gc-stats call may still fail with certain JSON formats
- The test logic is unnecessarily complex and harder to maintain
🐛 Proposed fix to use JSON.parse consistently
lines = body.split("\r\n") json_line = lines.detect { |l| l[0] == "{" } - pairs = json_line.scan(/\"[^\"]+\": [^,]+/) - gc_stats = {} - pairs.each do |p| - p =~ /\"([^\"]+)\": ([^,]+)/ || raise("Can't parse #{p.inspect}!") - gc_stats[$1] = $2 - end - gc_count_before = gc_stats["count"].to_i + gc_stats = JSON.parse(json_line) + gc_count_before = gc_stats["count"] s = yield s << "GET /gc HTTP/1.0\r\n\r\n"
🧹 Nitpick comments (1)
test/test_cli.rb (1)
96-97: Redundantrequire 'json'statement.This
require 'json'insidetest_control_clusteredis now redundant sincejsonis already required at the top of the file (line 4).🧹 Suggested cleanup
sleep 2 s = UNIXSocket.new `@tmp_path` s << "GET /stats HTTP/1.0\r\n\r\n" body = s.read - require 'json' status = JSON.parse(body.split("\n").last)
📜 Review details
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (2)
lib/puma/app/status.rbtest/test_cli.rb
🔇 Additional comments (4)
lib/puma/app/status.rb (2)
1-2: LGTM!Adding
require 'json'at the top level is the correct approach to enable JSON serialization forGC.stat.
64-65: Clean fix for the JSON serialization issue.Using
GC.stat.to_jsoninstead of manual string construction correctly addresses the whitespace-sensitive JSON parsing issue. The standard library handles all edge cases in key-value formatting.test/test_cli.rb (2)
4-4: LGTM!Adding
require "json"at the top level is appropriate for the test file.
199-200: Good use ofJSON.parsefor the second gc-stats call.This correctly parses the JSON response. Note that with
JSON.parse,gc_stats["count"]will already be an integer, so the.to_icall on line 200 is technically redundant but harmless.
✏️ Tip: You can disable this entire section by setting review_details to false in your review settings.
PR_054
Summary by CodeRabbit
✏️ Tip: You can customize this high-level summary in your review settings.