Module: Kettle::Ndjson

Defined in:
lib/kettle/ndjson.rb,
lib/kettle/ndjson/version.rb,
sig/kettle/ndjson.rbs

Defined Under Namespace

Modules: Version Classes: Error, EventRecorder, EventStream, UnknownEventTypeError

Constant Summary collapse

EVENT_TYPES =

Returns:

  • (Array[String])
%w[
  run_start
  phase_start
  phase_finish
  command_step
  diagnostic
  summary
].freeze
DEFAULT_EVENT_TYPES =

Returns:

  • (Array[String])
EVENT_TYPES.freeze
EVENT_TYPE_ALIASES =

Returns:

  • (Hash[String, Array[String]])
{
  "all" => EVENT_TYPES,
  "default" => DEFAULT_EVENT_TYPES,
  "progress" => %w[run_start phase_start phase_finish command_step summary]
}.freeze
VERSION =

Traditional Constant Location

Returns:

  • (String)
Version::VERSION

Class Method Summary collapse

Class Method Details

.compact_payload(payload) ⇒ Hash[Symbol, untyped]

Parameters:

  • payload (Hash[Symbol, untyped])

Returns:

  • (Hash[Symbol, untyped])


126
127
128
# File 'lib/kettle/ndjson.rb', line 126

def compact_payload(payload)
  payload.to_h.compact
end

.emit_diagnostic_event(events, diagnostic, index: nil, total: nil) ⇒ void

This method returns an undefined value.

Parameters:

  • events (Object)
  • diagnostic (Object)
  • index: (Integer? index) (defaults to: nil)
  • total: (Integer? total) (defaults to: nil)


94
95
96
97
98
99
100
101
102
103
104
105
106
107
# File 'lib/kettle/ndjson.rb', line 94

def emit_diagnostic_event(events, diagnostic, index: nil, total: nil)
  payload = diagnostic.respond_to?(:to_h) ? diagnostic.to_h : {message: diagnostic.to_s}
  emit_event(
    events,
    "diagnostic",
    index: index,
    total: total,
    kind: payload[:kind] || payload["kind"] || payload[:key] || payload["key"],
    severity: payload[:severity] || payload["severity"],
    path: payload[:path] || payload["path"],
    message: payload[:message] || payload["message"] || diagnostic.to_s,
    blocking: payload[:blocking] || payload["blocking"]
  )
end

.emit_event(events, type, payload = {}) ⇒ void

This method returns an undefined value.

Parameters:

  • events (Object)
  • type (String)
  • payload (Hash[Symbol, untyped]) (defaults to: {})


51
52
53
54
55
# File 'lib/kettle/ndjson.rb', line 51

def emit_event(events, type, payload = {})
  return unless events

  events.emit(payload.merge(type: type, event_version: 1))
end

.emit_phase_event(events, phase, status:, **payload) ⇒ void

This method returns an undefined value.

Parameters:

  • events (Object)
  • phase (String, Symbol)
  • status: (String status)
  • payload (Object)


57
58
59
60
# File 'lib/kettle/ndjson.rb', line 57

def emit_phase_event(events, phase, status:, **payload)
  event_type = (status.to_s == "started") ? "phase_start" : "phase_finish"
  emit_event(events, event_type, payload.merge(phase: phase.to_s, status: status))
end

.emit_step_event(events, event_type, step, phase:, index: nil, total: nil) ⇒ void

This method returns an undefined value.

Parameters:

  • events (Object)
  • event_type (String)
  • step (Hash[Symbol | String, untyped])
  • phase: (String phase)
  • index: (Integer? index) (defaults to: nil)
  • total: (Integer? total) (defaults to: nil)


76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
# File 'lib/kettle/ndjson.rb', line 76

def emit_step_event(events, event_type, step, phase:, index: nil, total: nil)
  emit_event(
    events,
    event_type,
    phase: phase.to_s,
    index: index,
    total: total,
    name: payload_value(step, :name),
    status: payload_value(step, :status),
    reason: payload_value(step, :reason),
    command: payload_value(step, :command),
    path: payload_value(step, :path),
    changed_files: Array(payload_value(step, :changed_files) || []),
    changed_count: Array(payload_value(step, :changed_files) || []).length,
    mark: step_event_mark(step)
  )
end

.emit_summary_event(events, payload) ⇒ void

This method returns an undefined value.

Parameters:

  • events (Object)
  • payload (Hash[Symbol, untyped])


109
110
111
# File 'lib/kettle/ndjson.rb', line 109

def emit_summary_event(events, payload)
  emit_event(events, "summary", payload.merge(mark: payload.fetch(:mark, ".")))
end

.event_recorder(stream = nil, phase_timings: []) ⇒ EventRecorder

Parameters:

  • stream (Object) (defaults to: nil)
  • phase_timings: (Array[Hash[Symbol, untyped]] phase_timings) (defaults to: [])

Returns:



34
35
36
# File 'lib/kettle/ndjson.rb', line 34

def event_recorder(stream = nil, phase_timings: [])
  EventRecorder.new(stream, phase_timings)
end

.event_stream(io, types: nil, event_types: EVENT_TYPES, aliases: EVENT_TYPE_ALIASES) ⇒ EventStream

Parameters:

  • io (Object)
  • types: (String? types) (defaults to: nil)
  • event_types: (Array[String] event_types) (defaults to: EVENT_TYPES)
  • aliases: (Hash[String, Array[String]] aliases) (defaults to: EVENT_TYPE_ALIASES)

Returns:



30
31
32
# File 'lib/kettle/ndjson.rb', line 30

def event_stream(io, types: nil, event_types: EVENT_TYPES, aliases: EVENT_TYPE_ALIASES)
  EventStream.new(io, types: normalize_event_types(types, event_types: event_types, aliases: aliases))
end

.normalize_event_types(types, event_types: EVENT_TYPES, aliases: EVENT_TYPE_ALIASES) ⇒ Array[String]

Parameters:

  • types (String, nil)
  • event_types: (Array[String] event_types) (defaults to: EVENT_TYPES)
  • aliases: (Hash[String, Array[String]] aliases) (defaults to: EVENT_TYPE_ALIASES)

Returns:

  • (Array[String])

Raises:



38
39
40
41
42
43
44
45
46
47
48
49
# File 'lib/kettle/ndjson.rb', line 38

def normalize_event_types(types, event_types: EVENT_TYPES, aliases: EVENT_TYPE_ALIASES)
  requested = types.to_s.strip
  tokens = requested.empty? ? ["default"] : requested.split(",").map { |token| token.strip }.reject(&:empty?)
  normalized = tokens.flat_map do |token|
    normalized_token = token.tr("-", "_")
    aliases.fetch(normalized_token) { normalized_token }
  end.map(&:to_s).uniq
  unknown = normalized - event_types.map(&:to_s)
  raise UnknownEventTypeError, "Unknown event type(s): #{unknown.join(", ")}" unless unknown.empty?

  normalized
end

.payload_value(payload, key) ⇒ Object

Parameters:

  • payload (Hash[Symbol | String, untyped])
  • key (Symbol)

Returns:

  • (Object)


120
121
122
123
124
# File 'lib/kettle/ndjson.rb', line 120

def payload_value(payload, key)
  return payload.public_send(key) if payload.respond_to?(key)

  payload.fetch(key, payload.fetch(key.to_s, nil))
end

.record_phase_timing(events, phase, status:, duration_ms:, payload: {}) ⇒ void

This method returns an undefined value.

Parameters:

  • events (Object)
  • phase (String, Symbol)
  • status: (String status)
  • duration_ms: (Float duration_ms)
  • payload: (Hash[Symbol, untyped] payload) (defaults to: {})


62
63
64
65
66
67
68
69
70
71
72
73
74
# File 'lib/kettle/ndjson.rb', line 62

def record_phase_timing(events, phase, status:, duration_ms:, payload: {})
  return unless events.respond_to?(:record_phase_timing)

  events.record_phase_timing(
    compact_payload(
      payload.merge(
        phase: phase.to_s,
        status: status,
        duration_ms: duration_ms
      )
    )
  )
end

.step_event_mark(step) ⇒ String

Parameters:

  • step (Hash[Symbol | String, untyped])

Returns:

  • (String)


113
114
115
116
117
118
# File 'lib/kettle/ndjson.rb', line 113

def step_event_mark(step)
  return ">" if payload_value(step, :status).to_s == "started"
  return "F" if %w[failed blocked].include?(payload_value(step, :status).to_s)

  Array(payload_value(step, :changed_files) || []).empty? ? "." : "*"
end