Skip to content

Commit a4298f6

Browse files
p-ddsignclaude
andcommitted
DI: normalize Windows backslashes in CodeTracker suffix-stripping loops
The DEBUG-5111 Windows path fix was incomplete: Utils.path_matches_suffix? normalizes backslashes internally, but CodeTracker#iseqs_for_path_suffix and #resolve_path_suffix have their own suffix-shortening loops that check working_suffix.include?('/') and strip via %r{.*/+}. When the probe path contains only backslashes (e.g. shared\rails\app\foo.rb sent by IDE tooling on Windows), the loop's '/' check is false, so the stripping never fires. With no stripping, only the full suffix is tested against registry paths; the typical Linux deployment doesn't have the source-repo prefix (shared/rails/) in its filesystem paths, so the match fails and the probe stays at RECEIVED instead of progressing to INSTALLED. Surfaced via the system test test_probe_status_log_line_with_windows_path in DataDog/system-tests, which sends sourceFile with backslashes against a Rails weblog whose runtime paths lack the shared/rails/ prefix. Fix: normalize backslashes upfront in both functions before the stripping loop, mirroring the pattern Utils.path_can_match_spec? already uses. Spec coverage in spec/datadog/di/code_tracker_spec.rb covers: - Windows-style probe path with prefix stripping required (the failing case) - Windows-style + uppercase, exercising both backslash normalization and the case-insensitive fallback - Absolute Windows-style path Verified: 3 new specs pass; full code_tracker_spec/utils_spec/instrumenter_spec/ probe_spec suite (203 examples) passes; standardrb clean; steep clean. Co-Authored-By: Claude <[email protected]>
1 parent 36584cf commit a4298f6

2 files changed

Lines changed: 48 additions & 0 deletions

File tree

lib/datadog/di/code_tracker.rb

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -249,6 +249,11 @@ def iseqs_for_path_suffix(suffix)
249249
exact = registry[suffix]
250250
return [suffix, exact] if exact
251251

252+
# Normalize Windows-style backslash separators (DEBUG-5111) upfront
253+
# so the suffix-shortening loop's "/+" regex can strip leading
254+
# components on probes whose sourceFile uses backslashes.
255+
suffix = Utils.normalize_windows_separators(suffix)
256+
252257
# Per the design comment in utils.rb, attempt case-sensitive
253258
# matching first (steps 5-6) and only fall back to case-insensitive
254259
# matching (steps 7-8) when no case-sensitive match is found.
@@ -371,6 +376,11 @@ def resolve_path_suffix(suffix, paths)
371376
# Exact match.
372377
return suffix if paths.include?(suffix)
373378

379+
# Normalize Windows-style backslash separators (DEBUG-5111) upfront
380+
# so the suffix-shortening loop's "/+" regex can strip leading
381+
# components on probes whose sourceFile uses backslashes.
382+
suffix = Utils.normalize_windows_separators(suffix)
383+
374384
# Suffix match. Per the design comment in utils.rb, attempt
375385
# case-sensitive matching first (steps 5-6) and only fall back to
376386
# case-insensitive (steps 7-8) when no case-sensitive match is found.

spec/datadog/di/code_tracker_spec.rb

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -652,6 +652,44 @@
652652
end
653653
end
654654

655+
describe "#iseqs_for_path_suffix with Windows backslash suffix" do
656+
# Verifies that backslash separators (DEBUG-5111) are normalized upfront so
657+
# the suffix-shortening loop can strip leading components. Probe paths from
658+
# IDE tooling on Windows arrive with backslashes; the runtime registry path
659+
# has forward slashes and typically lacks the leading directory components
660+
# of the source repository path.
661+
around do |example|
662+
tracker.define_singleton_method(:backfill_registry) {}
663+
tracker.start
664+
665+
registry = tracker.send(:registry)
666+
# Runtime path on the deployed weblog — no shared/rails/ prefix.
667+
registry["/app/controllers/debugger_controller.rb"] = "/app/controllers/debugger_controller.rb"
668+
669+
example.run
670+
671+
tracker.stop
672+
end
673+
674+
it "matches when the probe path uses backslashes and needs prefix stripping" do
675+
expect(
676+
tracker.iseqs_for_path_suffix('shared\rails\app\controllers\debugger_controller.rb'),
677+
).to eq(["/app/controllers/debugger_controller.rb", "/app/controllers/debugger_controller.rb"])
678+
end
679+
680+
it "matches when the probe path uses backslashes and uppercase, needing both fallbacks" do
681+
expect(
682+
tracker.iseqs_for_path_suffix('SHARED\RAILS\APP\CONTROLLERS\DEBUGGER_CONTROLLER.RB'),
683+
).to eq(["/app/controllers/debugger_controller.rb", "/app/controllers/debugger_controller.rb"])
684+
end
685+
686+
it "matches when the probe path is an absolute Windows-style path" do
687+
expect(
688+
tracker.iseqs_for_path_suffix('\app\controllers\debugger_controller.rb'),
689+
).to eq(["/app/controllers/debugger_controller.rb", "/app/controllers/debugger_controller.rb"])
690+
end
691+
end
692+
655693
describe '#iseq_for_line' do
656694
before do
657695
allow(Datadog::DI).to receive(:respond_to?).and_call_original

0 commit comments

Comments
 (0)