gitlab-org--gitlab-foss/lib/gitlab/ci/trace/section_parser.rb

100 lines
2.7 KiB
Ruby

# frozen_string_literal: true
module Gitlab
module Ci
class Trace
class SectionParser
def initialize(lines)
@lines = lines
end
def parse!
@markers = {}
@lines.each do |line, pos|
parse_line(line, pos)
end
end
def sections
sanitize_markers.map do |name, markers|
start_, end_ = markers
{
name: name,
byte_start: start_[:marker],
byte_end: end_[:marker],
date_start: start_[:timestamp],
date_end: end_[:timestamp]
}
end
end
private
def parse_line(line, line_start_position)
s = StringScanner.new(line)
until s.eos?
find_next_marker(s) do |scanner|
marker_begins_at = line_start_position + scanner.pointer
if scanner.scan(Gitlab::Regex.build_trace_section_regex)
marker_ends_at = line_start_position + scanner.pointer
handle_line(scanner[1], scanner[2].to_i, scanner[3], marker_begins_at, marker_ends_at)
true
else
false
end
end
end
end
def sanitize_markers
@markers.select do |_, markers|
markers.size == 2 && markers[0][:action] == :start && markers[1][:action] == :end
end
end
def handle_line(action, time, name, marker_start, marker_end)
action = action.to_sym
timestamp = Time.at(time).utc
marker = if action == :start
marker_end
else
marker_start
end
@markers[name] ||= []
@markers[name] << {
name: name,
action: action,
timestamp: timestamp,
marker: marker
}
end
def beginning_of_section_regex
@beginning_of_section_regex ||= /section_/.freeze
end
def find_next_marker(scanner)
beginning_of_section_len = 8
maybe_marker = scanner.exist?(beginning_of_section_regex)
if maybe_marker.nil?
scanner.terminate
else
# repositioning at the beginning of the match
scanner.pos += maybe_marker - beginning_of_section_len
if block_given?
good_marker = yield(scanner)
# if not a good marker: Consuming the matched beginning_of_section_regex
scanner.pos += beginning_of_section_len unless good_marker
end
end
end
end
end
end
end