@@ -42,15 +42,19 @@ def initialize_watcher(data)
4242 cursor_position = data [ "cursor_position" ] || 0
4343 filter = data [ "filter" ] . presence
4444 mode = data [ "mode" ] || "live"
45+ search_type = data [ "search_type" ]
4546 regexp_mode = data [ "regexp_mode" ] == true || data [ "regexp_mode" ] == "true"
4647 start_position = data [ "start_position" ] &.to_i || 0
4748 end_position = data [ "end_position" ] &.to_i
4849
49- if mode == "search"
50- # For search mode , read the entire file with filter and send all matching lines
50+ if mode == "search" && search_type != "byteoffset"
51+ # For filter-based search , read the entire file with filter and send all matching lines
5152 read_entire_file_with_filter ( file_path , filter , regexp_mode , start_position , end_position )
53+ elsif search_type == "byteoffset"
54+ # For byteoffset search, read a fixed range
55+ start_log_watcher ( file_path , cursor_position , filter , regexp_mode , end_position )
5256 else
53- # For live mode, start the watcher
57+ # For live mode, stream indefinitely without end position
5458 start_log_watcher ( file_path , cursor_position , filter , regexp_mode )
5559 end
5660 end
@@ -75,12 +79,13 @@ def cleanup_existing_operations
7579 stop_log_watcher
7680 end
7781
78- def start_log_watcher ( file_path , cursor_position , filter = nil , regexp_mode = false )
82+ def start_log_watcher ( file_path , cursor_position , filter = nil , regexp_mode = false , end_position = nil )
7983 return if @log_watcher_running
8084
8185 @log_watcher_running = true
8286 @filter = filter
8387 @regexp_mode = regexp_mode
88+ @end_position = end_position
8489
8590 transmit ( { action : "message" , content : "Reading file. Please wait..." } )
8691
@@ -90,19 +95,27 @@ def start_log_watcher(file_path, cursor_position, filter = nil, regexp_mode = fa
9095
9196 @log_watcher_thread = Thread . new do
9297 Rails . logger . silence ( Logger ::ERROR ) do
98+ current_byte_offset = cursor_position
9399 @log_file . watch do |new_lines |
94100 break unless @log_watcher_running
95101
96102 # Collect all filtered lines from this batch
97103 lines_to_send = [ ]
98104
99105 new_lines . each do |log_line |
106+ # Stop if we've reached the end position (only when expanding context)
107+ if @end_position && @end_position > 0 && current_byte_offset >= @end_position
108+ @log_watcher_running = false
109+ break
110+ end
111+
100112 # Filters in live mode are not yet implemented
101113 # if @filter.present? && !Onlylogs::Grep.match_line?(log_line.text, @filter, regexp_mode: @regexp_mode)
102114 # next
103115 # end
104116
105- lines_to_send << render_log_line ( log_line )
117+ lines_to_send << render_log_line ( log_line , byte_offset : current_byte_offset )
118+ current_byte_offset += log_line . bytesize
106119 end
107120
108121 if lines_to_send . any?
@@ -118,6 +131,8 @@ def start_log_watcher(file_path, cursor_position, filter = nil, regexp_mode = fa
118131 Rails . logger . error e . backtrace . join ( "\n " )
119132 ensure
120133 @log_watcher_running = false
134+ # Send finish message if we had an end position (byteoffset mode)
135+ transmit ( { action : "finish" , content : "Context loaded." } ) if @end_position . present?
121136 end
122137 end
123138
@@ -156,11 +171,15 @@ def read_entire_file_with_filter(file_path, filter = nil, regexp_mode = false, s
156171
157172 begin
158173 Rails . logger . silence ( Logger ::ERROR ) do
159- @log_file . grep ( filter , regexp_mode : regexp_mode , start_position : start_position , end_position : end_position ) do |log_line |
174+ @log_file . grep ( filter , regexp_mode : regexp_mode , start_position : start_position , end_position : end_position ) do |result |
160175 break if @batch_sender . nil?
161176
177+ # Result is now a hash with {byte_offset, content}
178+ byte_offset = result [ :byte_offset ]
179+ log_line = result [ :content ]
180+
162181 # Add to batch buffer (sender thread will handle sending)
163- @batch_sender . add_line ( render_log_line ( log_line ) )
182+ @batch_sender . add_line ( render_log_line ( log_line , byte_offset : byte_offset , show_expand_button : true ) )
164183
165184 line_count += 1
166185 end
@@ -184,8 +203,14 @@ def read_entire_file_with_filter(file_path, filter = nil, regexp_mode = false, s
184203 end
185204 end
186205
187- def render_log_line ( log_line )
188- "<pre>#{ FilePathParser . parse ( AnsiColorParser . parse ( ERB ::Util . html_escape ( log_line ) ) ) } </pre>"
206+ def render_log_line ( log_line , byte_offset : nil , show_expand_button : false )
207+ parsed = FilePathParser . parse ( AnsiColorParser . parse ( ERB ::Util . html_escape ( log_line ) ) )
208+
209+ {
210+ content : parsed ,
211+ byte_offset : byte_offset ,
212+ show_expand_button : show_expand_button
213+ }
189214 end
190215 end
191216end
0 commit comments