Commit 287fe603 authored by Doug Barrett's avatar Doug Barrett 🔴
Browse files

perf: combine regex patterns for efficient path matching

Combine IGNORE_PATHS and wrapper_patterns into a single Regexp.union
for efficient matching. Cache is invalidated when patterns change.

Relates-to: #60
parent cb5f4827
Loading
Loading
Loading
Loading
+8 −2
Original line number Diff line number Diff line
@@ -18,6 +18,7 @@ module Labkit
        class << self
          def register_wrapper_pattern(pattern)
            wrapper_patterns << pattern
            @combined_ignore_pattern = nil
          end

          def wrapper_patterns
@@ -26,6 +27,11 @@ module Labkit

          def reset_wrapper_patterns!
            @wrapper_patterns = nil
            @combined_ignore_pattern = nil
          end

          def combined_ignore_pattern
            @combined_ignore_pattern ||= Regexp.union(IGNORE_PATHS + wrapper_patterns)
          end
        end

@@ -66,13 +72,13 @@ module Labkit
        def determine_callsite
          locations = caller_locations(INTERNAL_FRAMES_TO_SKIP, MAX_FRAMES_TO_INSPECT) || []
          locations = caller_locations(1, MAX_FRAMES_TO_INSPECT) || [] if locations.empty?
          ignore_pattern = LogInterceptor.combined_ignore_pattern

          locations.find do |loc|
            path = loc.path

            next if path == __FILE__
            next if IGNORE_PATHS.any? { |pattern| pattern.match?(path) }
            next if LogInterceptor.wrapper_patterns.any? { |pattern| pattern.match?(path) }
            next if ignore_pattern.match?(path)

            true
          end
+39 −0
Original line number Diff line number Diff line
@@ -175,6 +175,13 @@ RSpec.describe Labkit::Logging::FieldValidator::LogInterceptor do

        expect(described_class.wrapper_patterns).to include(%r{/custom_logger\.rb$})
      end

      it 'invalidates the combined_ignore_pattern cache' do
        initial_pattern = described_class.combined_ignore_pattern
        described_class.register_wrapper_pattern(%r{/custom_logger\.rb$})

        expect(described_class.combined_ignore_pattern).not_to eq(initial_pattern)
      end
    end

    describe '.wrapper_patterns' do
@@ -193,6 +200,38 @@ RSpec.describe Labkit::Logging::FieldValidator::LogInterceptor do

        expect(described_class.wrapper_patterns).not_to include(%r{/custom\.rb$})
      end

      it 'invalidates the combined_ignore_pattern cache' do
        described_class.register_wrapper_pattern(%r{/custom\.rb$})
        pattern_with_custom = described_class.combined_ignore_pattern

        described_class.reset_wrapper_patterns!

        expect(described_class.combined_ignore_pattern).not_to eq(pattern_with_custom)
      end
    end

    describe '.combined_ignore_pattern' do
      after do
        described_class.reset_wrapper_patterns!
      end

      it 'returns a Regexp that combines IGNORE_PATHS and wrapper_patterns' do
        pattern = described_class.combined_ignore_pattern

        expect(pattern).to be_a(Regexp)
        expect(pattern).to match('/gems/logger-1.0.0/lib/logger.rb')
        expect(pattern).to match('/lib/labkit/logging/json_logger.rb')
        expect(pattern).to match('/app/lib/my_logger.rb')
        expect(pattern).not_to match('/app/models/user.rb')
      end

      it 'is cached for performance' do
        pattern1 = described_class.combined_ignore_pattern
        pattern2 = described_class.combined_ignore_pattern

        expect(pattern1).to be(pattern2)
      end
    end
  end
end