Class: Gitlab::Ci::Trace::Stream

Inherits:
Object
  • Object
show all
Defined in:
lib/gitlab/ci/trace/stream.rb

Constant Summary collapse

BUFFER_SIZE =
4096
LIMIT_SIZE =
500.kilobytes
TIMESTAMP_HEADER_DATETIME =
'\d{4}-[01][0-9]-[0-3][0-9]T[0-2][0-9]:[0-5][0-9]:[0-5][0-9]\.[0-9]{6}Z'
TIMESTAMP_HEADER_DATETIME_LENGTH =
27
TIMESTAMP_HEADER_REGEX =
/(#{TIMESTAMP_HEADER_DATETIME}) [0-9a-f]{2}[EO][+ ]/
TIMESTAMP_HEADER_LENGTH =
32

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(metrics = Trace::Metrics.new) ⇒ Stream

Returns a new instance of Stream.



19
20
21
22
23
24
# File 'lib/gitlab/ci/trace/stream.rb', line 19

def initialize(metrics = Trace::Metrics.new)
  @stream = yield
  @stream&.binmode
  @metrics = metrics
  @timestamped = nil
end

Instance Attribute Details

#metricsObject (readonly)

Returns the value of attribute metrics.



15
16
17
# File 'lib/gitlab/ci/trace/stream.rb', line 15

def metrics
  @metrics
end

#streamObject (readonly)

Returns the value of attribute stream.



15
16
17
# File 'lib/gitlab/ci/trace/stream.rb', line 15

def stream
  @stream
end

Instance Method Details

#append(data, offset) ⇒ Object



46
47
48
49
50
51
52
53
54
55
56
# File 'lib/gitlab/ci/trace/stream.rb', line 46

def append(data, offset)
  data = data.force_encoding(Encoding::BINARY)

  metrics.increment_trace_operation(operation: :streamed)
  metrics.increment_trace_bytes(data.bytesize)

  stream.seek(offset, IO::SEEK_SET)
  stream.write(data)
  stream.truncate(offset + data.bytesize)
  stream.flush
end

#extract_coverage(regex) ⇒ Object



80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
# File 'lib/gitlab/ci/trace/stream.rb', line 80

def extract_coverage(regex)
  return unless valid?
  return unless regex.present?

  regex = Gitlab::UntrustedRegexp.new(regex)

  match = ""
  strip_timestamp = has_timestamps?

  reverse_line do |line|
    line.chomp!

    # strip timestamp from line
    line.slice!(0, TIMESTAMP_HEADER_LENGTH) if strip_timestamp

    matches = regex.scan(line)
    next unless matches.is_a?(Array)
    next if matches.empty?

    match = matches.flatten.last
    coverage = match.gsub(/\d+(\.\d+)?/).first
    return coverage if coverage.present? # rubocop:disable Cop/AvoidReturnFromBlocks
  end

  nil
rescue StandardError
  # if bad regex or something goes wrong we dont want to interrupt transition
  # so we just silently ignore error for now
end

#extract_sectionsObject



110
111
112
113
114
115
116
117
118
# File 'lib/gitlab/ci/trace/stream.rb', line 110

def extract_sections
  return [] unless valid?

  lines = to_enum(:each_line_with_pos)
  parser = SectionParser.new(lines)

  parser.parse!
  parser.sections
end

#file?Boolean

Returns:

  • (Boolean)


31
32
33
# File 'lib/gitlab/ci/trace/stream.rb', line 31

def file?
  self.path.present?
end

#html(last_lines: nil, max_size: nil) ⇒ Object



74
75
76
77
78
# File 'lib/gitlab/ci/trace/stream.rb', line 74

def html(last_lines: nil, max_size: nil)
  text = raw(last_lines: last_lines, max_size: max_size)
  buffer = StringIO.new(text)
  ::Gitlab::Ci::Ansi2html.convert(buffer).html
end

#limit(last_bytes = LIMIT_SIZE) ⇒ Object



39
40
41
42
43
44
# File 'lib/gitlab/ci/trace/stream.rb', line 39

def limit(last_bytes = LIMIT_SIZE)
  if last_bytes < size
    stream.seek(-last_bytes, IO::SEEK_END)
    stream.readline
  end
end

#pathObject



35
36
37
# File 'lib/gitlab/ci/trace/stream.rb', line 35

def path
  self.stream.path if self.stream.respond_to?(:path)
end

#raw(last_lines: nil, max_size: nil) ⇒ Object



62
63
64
65
66
67
68
69
70
71
72
# File 'lib/gitlab/ci/trace/stream.rb', line 62

def raw(last_lines: nil, max_size: nil)
  return unless valid?

  if max_size.to_i > 0
    read_last_lines_with_max_size(last_lines, max_size)
  elsif last_lines.to_i > 0
    read_last_lines(last_lines)
  else
    stream.read
  end.force_encoding(Encoding.default_external)
end

#set(data) ⇒ Object



58
59
60
# File 'lib/gitlab/ci/trace/stream.rb', line 58

def set(data)
  append(data, 0)
end

#valid?Boolean Also known as: present?

Returns:

  • (Boolean)


26
27
28
# File 'lib/gitlab/ci/trace/stream.rb', line 26

def valid?
  self.stream.present?
end