Module: MrMurano::Pretties

Defined in:
lib/MrMurano/makePretty.rb

Constant Summary collapse

PRETTIES_COLORSCHEME =
HighLine::ColorScheme.new do |cs|
  cs[:json] = [:magenta]
  cs[:record_type] = [:magenta]
  cs[:subject] = [:cyan]
  cs[:timestamp] = [:blue]
  cs[:tracking] = [:yellow]
end

Class Method Summary collapse

Class Method Details

.body_prefix(options) ⇒ Object



307
308
309
# File 'lib/MrMurano/makePretty.rb', line 307

def self.body_prefix(options)
  options.indent && '  ' || ''
end

.fmt_abbreviated_severity(severity, out, raw, options, min_width: 7) ⇒ Object



136
137
138
139
# File 'lib/MrMurano/makePretty.rb', line 136

def self.fmt_abbreviated_severity(severity, out, raw, options, min_width: 7)
  abbrev, _loquac, style = styled_severity(severity)
  fmt_text_padded(abbrev, style, out, raw, options, min_width: min_width)
end

.fmt_log_record_timestamp(line, options) ⇒ Object



181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
# File 'lib/MrMurano/makePretty.rb', line 181

def self.fmt_log_record_timestamp(line, options)
  if line.key?(:timestamp)
    if line[:timestamp].is_a? Numeric
      time_secs_epoch = Time.at(line[:timestamp] / 1000.0)
      if options.localtime
        curtime = time_secs_epoch.localtime
      else
        curtime = time_secs_epoch.gmtime
      end
      format = options.sprintf
      format = '%Y-%m-%d %H:%M:%S' if format.to_s.empty?
      curtime = curtime.strftime(format)
    else
      curtime = line[:timestamp]
    end
  else
    curtime = '<no timestamp>'
  end
  curtime
end

.fmt_loquacious_severity(severity, out, raw, options, min_width: 11) ⇒ Object



141
142
143
144
# File 'lib/MrMurano/makePretty.rb', line 141

def self.fmt_loquacious_severity(severity, out, raw, options, min_width: 11)
  _abbrev, loquac, style = styled_severity(severity)
  fmt_text_padded(loquac, style, out, raw, options, min_width: min_width)
end

.fmt_text_padded(text, style, out, raw, options, min_width: 0) ⇒ Object



93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
# File 'lib/MrMurano/makePretty.rb', line 93

def self.fmt_text_padded(text, style, out, raw, options, min_width: 0)
  inter_spaces = (min_width == 0) && 0 || options.one_line && 1 || 3
  min_width = text.length + inter_spaces unless options.align
  if !options.one_line && options.align && min_width == 0
    prefix = 0
    if TERM_WIDTH > (raw.length - text.length)
      prefix = TERM_WIDTH - raw.length - text.length
    end
    out += ' ' * prefix
    raw += ' ' * prefix
  end
  padding = min_width - text.length
  padding = ' ' * (padding > 0 && padding || 0)
  out += HighLine.color(text, style) + padding
  raw += text + padding
  [out, raw]
end

.log_pretty_assemble_body(line, options) ⇒ Object



226
227
228
229
230
231
232
233
234
# File 'lib/MrMurano/makePretty.rb', line 226

def self.log_pretty_assemble_body(line, options)
  out = ''
  return out if options.one_line
  out += log_pretty_assemble_message(line, options)
  return out if options.message_only
  out += log_pretty_assemble_data(line, options)
  out += log_pretty_assemble_remainder(line, options)
  out + log_pretty_assemble_tracking_id(line, options)
end

.log_pretty_assemble_data(line, options) ⇒ Object



241
242
243
244
245
246
247
248
249
250
251
252
# File 'lib/MrMurano/makePretty.rb', line 241

def self.log_pretty_assemble_data(line, options)
  return '' unless line.key?(:data)
  data = line[:data]
  if data.is_a?(Hash)
    out = ''
    out += log_pretty_emphasize_entry(:request, data, options)
    out += log_pretty_emphasize_entry(:response, data, options)
    out + log_pretty_data_remainder(data, options)
  else
    data.to_s
  end
end

.log_pretty_assemble_header(line, options) ⇒ Object



111
112
113
114
115
116
117
# File 'lib/MrMurano/makePretty.rb', line 111

def self.log_pretty_assemble_header(line, options)
  out = ''
  raw = ''
  out, raw = log_pretty_assemble_header_meta(line, out, raw, options)
  out, _raw = log_pretty_header_add_message(line, out, raw, options)
  out.empty? && out || out + "\n"
end

.log_pretty_assemble_header_meta(line, out, raw, options) ⇒ Object



119
120
121
122
123
124
125
126
# File 'lib/MrMurano/makePretty.rb', line 119

def self.log_pretty_assemble_header_meta(line, out, raw, options)
  return [out, raw] if options.omit_headers
  out, raw = log_pretty_header_add_event_timestamp(line, out, raw, options)
  out, raw = log_pretty_header_add_murano_tracking(line, out, raw, options)
  out, raw = log_pretty_header_add_log_record_type(line, out, raw, options)
  out, raw = log_pretty_header_add_abbreviated_sev(line, out, raw, options)
  log_pretty_header_add_a_service_event(line, out, raw, options)
end

.log_pretty_assemble_message(line, options) ⇒ Object



236
237
238
239
# File 'lib/MrMurano/makePretty.rb', line 236

def self.log_pretty_assemble_message(line, options)
  return '' unless line.key?(:message) && !line[:message].to_s.empty?
  body_prefix(options) + line[:message] + "\n"
end

.log_pretty_assemble_remainder(line, options) ⇒ Object



277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
# File 'lib/MrMurano/makePretty.rb', line 277

def self.log_pretty_assemble_remainder(line, options)
  known_keys = i[
    severity
    type
    timestamp
    service
    event
    message
    tracking_id
    data
  ]
  line = line.reject { |key, _val| known_keys.include?(key) }
  return '' if line.empty?
  body_prefix(options) + log_pretty_json(line, options) + "\n"
end

.log_pretty_assemble_tracking_id(line, options) ⇒ Object



293
294
295
296
# File 'lib/MrMurano/makePretty.rb', line 293

def self.log_pretty_assemble_tracking_id(line, options)
  return '' unless options.tracking
  log_pretty_entry_value(:tracking_id, line, options)
end

.log_pretty_data_remainder(data, options) ⇒ Object



266
267
268
269
270
271
272
273
274
275
# File 'lib/MrMurano/makePretty.rb', line 266

def self.log_pretty_data_remainder(data, options)
  known_keys = i[
    request
    response
  ]
  data = data.reject { |key, _val| known_keys.include?(key) }
  return '' if data.empty?
  out = options.separators && (body_prefix(options) + "---------\n") || ''
  out + body_prefix(options) + 'data: ' + log_pretty_json(data, options) + "\n"
end

.log_pretty_emphasize_entry(entry, hash, options) ⇒ Object



254
255
256
257
258
# File 'lib/MrMurano/makePretty.rb', line 254

def self.log_pretty_emphasize_entry(entry, hash, options)
  return '' unless hash.key?(entry) && !hash[entry].empty?
  out = body_prefix(options) + "---------\n" && options.separators || ''
  out + log_pretty_entry_value(entry, hash, options)
end

.log_pretty_entry_value(entry, hash, options) ⇒ Object



260
261
262
263
264
# File 'lib/MrMurano/makePretty.rb', line 260

def self.log_pretty_entry_value(entry, hash, options)
  out = body_prefix(options) + "#{entry}: "
  out += log_pretty_json(hash[entry], options)
  out + "\n"
end

.log_pretty_header_add_a_service_event(line, out, raw, options) ⇒ Object



208
209
210
211
212
213
214
215
216
217
# File 'lib/MrMurano/makePretty.rb', line 208

def self.log_pretty_header_add_a_service_event(line, out, raw, options)
  pad = options.align && '    ' || ''
  out += pad
  raw += pad
  svc_evt = []
  svc_evt += [line[:service]] unless line[:service].to_s.empty?
  svc_evt += [line[:event]] unless line[:event].to_s.empty?
  svc_evt = "[#{svc_evt.join(' ').upcase}]"
  fmt_text_padded(svc_evt, :subject, out, raw, options, min_width: 0)
end

.log_pretty_header_add_abbreviated_sev(line, out, raw, options) ⇒ Object



128
129
130
# File 'lib/MrMurano/makePretty.rb', line 128

def self.log_pretty_header_add_abbreviated_sev(line, out, raw, options)
  fmt_abbreviated_severity(line[:severity], out, raw, options)
end

.log_pretty_header_add_event_timestamp(line, out, raw, options) ⇒ Object



174
175
176
177
178
179
# File 'lib/MrMurano/makePretty.rb', line 174

def self.log_pretty_header_add_event_timestamp(line, out, raw, options)
  curtime = fmt_log_record_timestamp(line, options)
  inter_spaces = options.one_line && 1 || 3
  min_width = curtime.length + inter_spaces
  fmt_text_padded(curtime, :timestamp, out, raw, options, min_width: min_width)
end

.log_pretty_header_add_log_record_type(line, out, raw, options) ⇒ Object



169
170
171
172
# File 'lib/MrMurano/makePretty.rb', line 169

def self.log_pretty_header_add_log_record_type(line, out, raw, options)
  log_type = line[:type].to_s.empty? && '--' || line[:type]
  fmt_text_padded(log_type.upcase, :record_type, out, raw, options, min_width: 10)
end

.log_pretty_header_add_loquacious_sev(line, out, raw, options) ⇒ Object



132
133
134
# File 'lib/MrMurano/makePretty.rb', line 132

def self.log_pretty_header_add_loquacious_sev(line, out, raw, options)
  fmt_loquacious_severity(line[:severity], out, raw, options)
end

.log_pretty_header_add_message(line, out, raw, options) ⇒ Object



219
220
221
222
223
224
# File 'lib/MrMurano/makePretty.rb', line 219

def self.log_pretty_header_add_message(line, out, raw, options)
  return [out, raw] unless options.one_line
  return [out, raw] unless line.key?(:message) && !line[:message].to_s.empty?
  msg = ' ' + line[:message]
  [out + msg, raw + msg]
end

.log_pretty_header_add_murano_tracking(line, out, raw, options) ⇒ Object



202
203
204
205
206
# File 'lib/MrMurano/makePretty.rb', line 202

def self.log_pretty_header_add_murano_tracking(line, out, raw, options)
  return [out, raw] unless options.tracking
  tid = line[:tracking_id].to_s.empty? && '--------' || line[:tracking_id].slice(0, 8)
  fmt_text_padded(tid, :tracking, out, raw, options, min_width: 11)
end

.log_pretty_json(hash, options) ⇒ Object



298
299
300
301
302
303
304
305
# File 'lib/MrMurano/makePretty.rb', line 298

def self.log_pretty_json(hash, options)
  return '' if hash.empty?
  prefix = body_prefix(options)
  prefix = prefix.to_s.empty? && '  ' || prefix
  makeJsonPretty(
    hash, options, indent: prefix, object_nl: "\n" + prefix
  )
end

.makeJsonPretty(data, options, indent: nil, object_nl: nil) ⇒ Object

rubocop:disable Style/MethodName: “Use snake_case for method names.”



28
29
30
31
32
33
34
35
36
37
# File 'lib/MrMurano/makePretty.rb', line 28

def self.makeJsonPretty(data, options, indent: nil, object_nl: nil)
  if options.pretty
    ret = JSON.pretty_generate(data, indent: indent, object_nl: object_nl).to_s
    ret[0] = HighLine.color(ret[0], :json)
    ret[-1] = HighLine.color(ret[-1], :json)
    ret
  else
    data.to_json
  end
end

.MakePrettyLogsV1(line, options) ⇒ Object

FIXME: (landonb): MUR-3081: Remove old http code for v3.1.0. Search: LOGS_USE_HTTP.



40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
# File 'lib/MrMurano/makePretty.rb', line 40

def self.MakePrettyLogsV1(line, options)
  # 2017-07-02: Changing shovel operator << to +=
  # to support Ruby 3.0 frozen string literals.
  out = ''
  out += HighLine.color("#{line[:type] || '--'} ".upcase, :subject)
  out += HighLine.color("[#{line[:subject] || ''}]", :subject)
  out += ' '
  if line.key?(:timestamp)
    if line[:timestamp].is_a? Numeric
      if options.localtime
        curtime = Time.at(line[:timestamp]).localtime.strftime('%Y-%m-%d %H:%M:%S')
      else
        curtime = Time.at(line[:timestamp]).gmtime.strftime('%Y-%m-%d %H:%M:%S')
      end
    else
      curtime = line[:timestamp]
    end
  else
    curtime = '<no timestamp>'
  end
  out += HighLine.color(curtime, :timestamp)
  out += ":\n"
  if line.key?(:data)
    data = line[:data]

    if data.is_a?(Hash)
      if data.key?(:request) && data.key?(:response)
        out += "---------\nrequest:"
        out += makeJsonPretty(data[:request], options)

        out += "\n---------\nresponse:"
        out += makeJsonPretty(data[:response], options)
      else
        out += makeJsonPretty(data, options)
      end
    else
      out += data.to_s
    end

  else
    line.delete :type
    line.delete :timestamp
    line.delete :subject
    out += makeJsonPretty(line, options)
  end
  out
end

.MakePrettyLogsV2(line, options) ⇒ Object



88
89
90
91
# File 'lib/MrMurano/makePretty.rb', line 88

def self.MakePrettyLogsV2(line, options)
  out = log_pretty_assemble_header(line, options)
  out + log_pretty_assemble_body(line, options)
end

.split_text_on_whitespace(full, width_avail) ⇒ Object



334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
# File 'lib/MrMurano/makePretty.rb', line 334

def self.split_text_on_whitespace(full, width_avail)
  # The easiest method is to split at the width, and not on closest whitespace:
  #   elem.meta[key].scan(/.{1,#{width_avail}}/).join("\n")
  # We'll instead split on whitespace.
  parts = []
  split_posit = width_avail - 1
  until full.empty?
    # Split the description on a space before the max width.
    part = full[0..split_posit]
    full = full[(split_posit + 1)..-1] || ''
    leftover = ''
    part, _space, leftover = part.rpartition(' ') unless full.empty?
    if part.empty?
      part = leftover.to_s
      leftover = ''
    else
      full = leftover.to_s + full
      full = full
    end
    parts.push(part.strip)
  end
  parts.join("\n")
end

.styled_severity(severity) ⇒ Object



146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
# File 'lib/MrMurano/makePretty.rb', line 146

def self.styled_severity(severity)
  case severity
  when 0 # Emergency: system is unusable
    ['EMERG', 'EMERGENCY', i[red bold on_white]]
  when 1 # Alert: action must be taken immediately
    ['ALERT', 'ALERT', i[red bold]]
  when 2 # Critical: critical conditions
    ['CRIT', 'CRITICAL', i[red bold]]
  when 3 # Error: error conditions
    ['ERROR', 'ERROR', i[red]]
  when 4 # Warning: warning conditions
    ['WARN', 'WARNING', i[yellow]]
  when 5 # Notice: normal but significant condition
    ['NOTE', 'NOTICE', i[white]]
  when 6 # Informational: informational messages
    ['INFO', 'INFO', i[blue]]
  when 7 # Debug: debug-level messages ]
    ['DEBUG', 'DEBUG', i[green]]
  else
    ["????#{severity}", "????#{severity}", i[red]]
  end
end

.width_last_column(headers, elems) ⇒ Object



311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
# File 'lib/MrMurano/makePretty.rb', line 311

def self.width_last_column(headers, elems)
  return nil unless $stdout.tty?
  # Calculate how much room (how many characters) are left for the
  # description column.
  width_taken = 0
  # rubocop:disable Performance/FixedSize
  #   "Do not compute the size of statically sized objects."
  width_taken += '| '.length
  # Calculate the width of each column except the last (:description).
  headers[0..-2].each do |key|
    elem_with_max = elems.max { |a, b| a.send(key).length <=> b.send(key).length }
    width_taken += elem_with_max.send(key).length unless elem_with_max.nil?
    width_taken += ' | '.length
  end
  width_taken += ' | '.length
  term_width, _rows = HighLine::SystemExtensions.terminal_size
  width_avail = term_width - width_taken
  # MAGIC_NUMBER: Tweak/change this if you want. 20 char min feels
  # about right: don't wrap if column would be narrow or negative.
  return nil if width_avail < 20
  width_avail
end