@@ -17,16 +17,21 @@ class ActiveRecordSubscriber < AbstractSubscriber
1717 class_attribute :backtrace_cleaner , default : ( ActiveSupport ::BacktraceCleaner . new . tap do |cleaner |
1818 cleaner . add_silencer { |line | line . include? ( "sentry-ruby/lib" ) || line . include? ( "sentry-rails/lib" ) }
1919 end )
20+
21+ CLEAN_FRAME_CACHE_SIZE = 1000
22+
23+ @clean_frame_cache = { }
24+ @backtrace_cache = { }
2025 end
2126
2227 class << self
2328 def subscribe!
24- record_query_source = SUPPORT_SOURCE_LOCATION && Sentry . configuration . rails . enable_db_query_source
25- query_source_threshold = Sentry . configuration . rails . db_query_source_threshold_ms
26-
2729 subscribe_to_event ( EVENT_NAMES ) do |event_name , duration , payload |
2830 next if EXCLUDED_EVENTS . include? payload [ :name ]
2931
32+ record_query_source = SUPPORT_SOURCE_LOCATION && Sentry . configuration . rails . enable_db_query_source
33+ query_source_threshold = Sentry . configuration . rails . db_query_source_threshold_ms
34+
3035 record_on_current_span (
3136 op : SPAN_PREFIX + event_name ,
3237 origin : SPAN_ORIGIN ,
@@ -62,21 +67,17 @@ def subscribe!
6267 span . set_data ( Span ::DataConventions ::SERVER_PORT , db_config [ :port ] ) if db_config [ :port ]
6368 span . set_data ( Span ::DataConventions ::SERVER_SOCKET_ADDRESS , db_config [ :socket ] ) if db_config [ :socket ]
6469
65- next unless record_query_source
66-
6770 # both duration and query_source_threshold are in ms
68- next unless duration >= query_source_threshold
69-
70- source_location = query_source_location
71-
72- if source_location
73- backtrace_line = Sentry ::Backtrace ::Line . parse ( source_location )
74-
75- span . set_data ( Span ::DataConventions ::FILEPATH , backtrace_line . file ) if backtrace_line . file
76- span . set_data ( Span ::DataConventions ::LINENO , backtrace_line . number ) if backtrace_line . number
77- span . set_data ( Span ::DataConventions ::FUNCTION , backtrace_line . method ) if backtrace_line . method
78- # Only JRuby has namespace in the backtrace
79- span . set_data ( Span ::DataConventions ::NAMESPACE , backtrace_line . module_name ) if backtrace_line . module_name
71+ if record_query_source && duration >= query_source_threshold
72+ backtrace_line = query_source_location
73+
74+ if backtrace_line
75+ span . set_data ( Span ::DataConventions ::FILEPATH , backtrace_line . file ) if backtrace_line . file
76+ span . set_data ( Span ::DataConventions ::LINENO , backtrace_line . number ) if backtrace_line . number
77+ span . set_data ( Span ::DataConventions ::FUNCTION , backtrace_line . method ) if backtrace_line . method
78+ # Only JRuby has namespace in the backtrace
79+ span . set_data ( Span ::DataConventions ::NAMESPACE , backtrace_line . module_name ) if backtrace_line . module_name
80+ end
8081 end
8182 end
8283 end
@@ -87,11 +88,35 @@ def subscribe!
8788 if SUPPORT_SOURCE_LOCATION && Thread . respond_to? ( :each_caller_location )
8889 def query_source_location
8990 Thread . each_caller_location do |location |
90- frame = backtrace_cleaner . clean_frame ( location )
91- return frame if frame
91+ if should_include_location? ( location )
92+ return cached_backtrace_line ( location )
93+ end
9294 end
9395 nil
9496 end
97+
98+ def should_include_location? ( location )
99+ cache_key = [ location . absolute_path , location . lineno ]
100+
101+ cached_result = @clean_frame_cache [ cache_key ]
102+ return cached_result unless cached_result . nil?
103+
104+ # Check if backtrace_cleaner would include this frame
105+ frame = backtrace_cleaner . clean_frame ( location )
106+ should_include = !frame . nil?
107+
108+ if @clean_frame_cache . size < CLEAN_FRAME_CACHE_SIZE
109+ @clean_frame_cache [ cache_key ] = should_include
110+ end
111+
112+ should_include
113+ end
114+
115+ def cached_backtrace_line ( location )
116+ cache_key = [ location . absolute_path , location . lineno ]
117+
118+ @backtrace_cache [ cache_key ] ||= Sentry ::Backtrace ::Line . from_source_location ( location )
119+ end
95120 else
96121 # Since Sentry is mostly used in production, we don't want to fallback to the slower implementation
97122 # and adds potentially big overhead to the application.
0 commit comments