Class: RSpecTelemetry::Analyzer

Inherits:
Object
  • Object
show all
Defined in:
lib/rspec_telemetry/analyzer.rb

Defined Under Namespace

Classes: Example, FileStat, QueryStat

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initializeAnalyzer

Returns a new instance of Analyzer.



50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
# File 'lib/rspec_telemetry/analyzer.rb', line 50

def initialize
  @examples = {}
  @factory_acc = FactoryAggregation::Accumulator.new
  @files = {}
  # Factory events arrive before example.finished, so merge them after loading.
  @example_fb = Hash.new { |h, k| h[k] = [0.0, 0] }
  @example_sql = Hash.new { |h, k| h[k] = [0.0, 0] }
  @queries = {}
  @example_count = 0
  @failure_count = 0
  @pending_count = 0
  @suite_duration_ms = 0.0
  @request_count = 0
  @total_request_ms = 0.0
  @total_db_ms = 0.0
  @total_view_ms = 0.0
  @sql_query_count = 0
  @total_sql_ms = 0.0
  @total_sql_in_factory_ms = 0.0
  @total_gc_ms = 0.0
  @total_allocated_objects = 0
end

Instance Attribute Details

#example_countObject (readonly)

Returns the value of attribute example_count.



32
33
34
# File 'lib/rspec_telemetry/analyzer.rb', line 32

def example_count
  @example_count
end

#examplesObject (readonly)

Returns the value of attribute examples.



32
33
34
# File 'lib/rspec_telemetry/analyzer.rb', line 32

def examples
  @examples
end

#failure_countObject (readonly)

Returns the value of attribute failure_count.



32
33
34
# File 'lib/rspec_telemetry/analyzer.rb', line 32

def failure_count
  @failure_count
end

#filesObject (readonly)

Returns the value of attribute files.



32
33
34
# File 'lib/rspec_telemetry/analyzer.rb', line 32

def files
  @files
end

#pending_countObject (readonly)

Returns the value of attribute pending_count.



32
33
34
# File 'lib/rspec_telemetry/analyzer.rb', line 32

def pending_count
  @pending_count
end

#request_countObject (readonly)

Returns the value of attribute request_count.



32
33
34
# File 'lib/rspec_telemetry/analyzer.rb', line 32

def request_count
  @request_count
end

#sql_query_countObject (readonly)

Returns the value of attribute sql_query_count.



32
33
34
# File 'lib/rspec_telemetry/analyzer.rb', line 32

def sql_query_count
  @sql_query_count
end

#suite_duration_msObject (readonly)

Returns the value of attribute suite_duration_ms.



32
33
34
# File 'lib/rspec_telemetry/analyzer.rb', line 32

def suite_duration_ms
  @suite_duration_ms
end

#total_allocated_objectsObject (readonly)

Returns the value of attribute total_allocated_objects.



32
33
34
# File 'lib/rspec_telemetry/analyzer.rb', line 32

def total_allocated_objects
  @total_allocated_objects
end

#total_db_msObject (readonly)

Returns the value of attribute total_db_ms.



32
33
34
# File 'lib/rspec_telemetry/analyzer.rb', line 32

def total_db_ms
  @total_db_ms
end

#total_gc_msObject (readonly)

Returns the value of attribute total_gc_ms.



32
33
34
# File 'lib/rspec_telemetry/analyzer.rb', line 32

def total_gc_ms
  @total_gc_ms
end

#total_request_msObject (readonly)

Returns the value of attribute total_request_ms.



32
33
34
# File 'lib/rspec_telemetry/analyzer.rb', line 32

def total_request_ms
  @total_request_ms
end

#total_sql_in_factory_msObject (readonly)

Returns the value of attribute total_sql_in_factory_ms.



32
33
34
# File 'lib/rspec_telemetry/analyzer.rb', line 32

def total_sql_in_factory_ms
  @total_sql_in_factory_ms
end

#total_sql_msObject (readonly)

Returns the value of attribute total_sql_ms.



32
33
34
# File 'lib/rspec_telemetry/analyzer.rb', line 32

def total_sql_ms
  @total_sql_ms
end

#total_view_msObject (readonly)

Returns the value of attribute total_view_ms.



32
33
34
# File 'lib/rspec_telemetry/analyzer.rb', line 32

def total_view_ms
  @total_view_ms
end

Class Method Details

.events_for_example(paths, example_id) ⇒ Object



145
146
147
148
149
150
151
152
153
154
155
156
157
# File 'lib/rspec_telemetry/analyzer.rb', line 145

def self.events_for_example(paths, example_id)
  events = []
  Array(paths).each do |path|
    File.foreach(path) do |line|
      event = Ndjson.parse(line)
      next unless event && event["example_id"] == example_id

      events << event
    end
  end

  events
end

.load(paths) ⇒ Object



73
74
75
76
77
78
79
80
81
82
# File 'lib/rspec_telemetry/analyzer.rb', line 73

def self.load(paths)
  new.tap do |analyzer|
    Array(paths).each do |path|
      File.foreach(path) do |line|
        event = Ndjson.parse(line)
        analyzer.add(event) if event
      end
    end
  end
end

Instance Method Details

#add(event) ⇒ Object



84
85
86
87
88
89
90
91
92
93
94
95
96
97
# File 'lib/rspec_telemetry/analyzer.rb', line 84

def add(event)
  case event["type"]
  when "example.finished"
    add_example(event)
  when "factory_bot.run_factory"
    add_factory(event)
  when "action_controller.process_action"
    add_request(event)
  when "sql.group"
    add_sql_group(event)
  when "suite.finished"
    add_suite(event)
  end
end

#factoriesObject



103
104
105
# File 'lib/rspec_telemetry/analyzer.rb', line 103

def factories
  @factory_acc.stats
end

#factory_time_ratioObject



111
112
113
114
# File 'lib/rspec_telemetry/analyzer.rb', line 111

def factory_time_ratio
  total = total_example_ms
  total.zero? ? 0.0 : total_factory_self_ms / total
end

#merged_examplesObject



120
121
122
123
124
125
126
127
128
129
130
131
# File 'lib/rspec_telemetry/analyzer.rb', line 120

def merged_examples
  # Mutate the report structs at the read boundary; raw aggregates stay separate.
  @examples.values.map do |ex|
    self_total, count = @example_fb[ex.example_id]
    ex.fb_self_total_ms = self_total
    ex.fb_count = count
    sql_total, sql_count = @example_sql[ex.example_id]
    ex.sql_total_ms = sql_total
    ex.sql_count = sql_count
    ex
  end
end

#slow_examples(limit = 20) ⇒ Object



116
117
118
# File 'lib/rspec_telemetry/analyzer.rb', line 116

def slow_examples(limit = 20)
  merged_examples.sort_by { |e| -e.duration_ms.to_f }.first(limit)
end

#slow_files(limit = 20) ⇒ Object



141
142
143
# File 'lib/rspec_telemetry/analyzer.rb', line 141

def slow_files(limit = 20)
  @files.values.sort_by { |f| -f.duration_ms.to_f }.first(limit)
end

#top_factories(limit = 20) ⇒ Object



133
134
135
# File 'lib/rspec_telemetry/analyzer.rb', line 133

def top_factories(limit = 20)
  @factory_acc.top(limit)
end

#top_queries(limit = 20) ⇒ Object



137
138
139
# File 'lib/rspec_telemetry/analyzer.rb', line 137

def top_queries(limit = 20)
  @queries.values.sort_by { |q| -q.total_ms }.first(limit)
end

#total_example_msObject



99
100
101
# File 'lib/rspec_telemetry/analyzer.rb', line 99

def total_example_ms
  @examples.values.sum { |e| e.duration_ms.to_f }
end

#total_factory_self_msObject



107
108
109
# File 'lib/rspec_telemetry/analyzer.rb', line 107

def total_factory_self_ms
  @factory_acc.stats.sum(&:self_total_ms)
end