Class: Necropsy::Diagnostics

Inherits:
Object
  • Object
show all
Defined in:
lib/necropsy/diagnostics.rb

Constant Summary collapse

FORMATS =
%i[human json].freeze

Instance Method Summary collapse

Constructor Details

#initialize(report) ⇒ Diagnostics

Returns a new instance of Diagnostics.

Raises:



10
11
12
13
14
# File 'lib/necropsy/diagnostics.rb', line 10

def initialize(report)
  raise Error, 'Reachability witnesses are unavailable for this report' unless report.reachability

  @report = report
end

Instance Method Details

#explain(node_id) ⇒ Object



39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
# File 'lib/necropsy/diagnostics.rb', line 39

def explain(node_id)
  lookup = graph.nodes.lookup(node_id)
  return with_source_incompleteness(ambiguous_payload(lookup)) if lookup.ambiguous?
  return with_source_incompleteness(missing_payload(node_id)) if lookup.missing?

  node = lookup.node

  finding = finding_for(node.graph_id)
  return with_source_incompleteness({ 'status' => 'alive', 'node' => node.to_h }) unless finding

  payload = {
    'status' => 'finding',
    'node' => node.to_h,
    'classification' => finding.classification.to_s,
    'confidence' => finding.confidence.to_s,
    'score' => finding.score,
    'components' => finding.score_components.map(&:to_h),
    'reasons' => finding.reasons,
    'blockers' => finding.blockers.map(&:to_h)
  }
  with_source_incompleteness(payload)
end

#render(payload, format: :human) ⇒ Object

Raises:



70
71
72
73
74
75
76
77
# File 'lib/necropsy/diagnostics.rb', line 70

def render(payload, format: :human)
  normalized = format.to_sym
  raise Error, "Diagnostics support only human or json output, not #{format}" unless FORMATS.include?(normalized)

  return JSON.pretty_generate(payload) if normalized == :json

  render_human(payload)
end

#why(node_id) ⇒ Object



16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
# File 'lib/necropsy/diagnostics.rb', line 16

def why(node_id)
  lookup = graph.nodes.lookup(node_id)
  return with_source_incompleteness(ambiguous_payload(lookup)) if lookup.ambiguous?
  return with_source_incompleteness(missing_payload(node_id)) if lookup.missing?

  node = lookup.node

  graph_id = node.graph_id
  runtime_path = reachability.witness(graph_id)
  return with_source_incompleteness(alive_payload(node, runtime_path, :runtime)) if runtime_path

  external_path = reachability.witness(graph_id, kind: :external)
  return with_source_incompleteness(alive_payload(node, external_path, :external)) if external_path

  finding = finding_for(graph_id)
  return with_source_incompleteness(dead_payload(node, finding)) if finding&.classification == :blocked

  test_path = reachability.witness(graph_id, kind: :test)
  return with_source_incompleteness(alive_payload(node, test_path, :test)) if test_path

  with_source_incompleteness(dead_payload(node, finding))
end

#why_not(node_id) ⇒ Object



62
63
64
65
66
67
68
# File 'lib/necropsy/diagnostics.rb', line 62

def why_not(node_id)
  lookup = graph.nodes.lookup(node_id)
  return with_source_incompleteness(ambiguous_payload(lookup)) if lookup.ambiguous?
  return with_source_incompleteness(missing_payload(node_id)) if lookup.missing?

  WhyNotExplanation.new(report).call(lookup.node)
end