Class: Sentiero::Analytics::VitalsCollector

Inherits:
Object
  • Object
show all
Includes:
Events, Stats
Defined in:
lib/sentiero/analytics/collectors/vitals_collector.rb

Overview

Per-segment web-vitals accumulator. The recorder emits one "__perf" custom event per metric report, with data.payload value, rating.

Within a single segment, multiple reports for the same metric collapse to the LAST (the web-vitals library re-reports as the page evolves; only the final report is authoritative). Samples accumulate across all segments.

#summarize's worst carries :value too; PageReportAnalyzer strips it afterward.

Constant Summary collapse

PERF_TAG =

Recorder tag for a web-vitals report.

"__perf"

Constants included from Events

Events::CUSTOM, Events::INCREMENTAL, Events::META, Events::SOURCE_INPUT, Events::SOURCE_MOUSE_INTERACTION, Events::SOURCE_SCROLL

Instance Attribute Summary collapse

Instance Method Summary collapse

Methods included from Stats

#mean, #offset_ms, #percentile, #top_counts

Constructor Details

#initialize(max_samples: nil) ⇒ VitalsCollector

max_samples: nil unbounded; an Integer caps each metric's values, flipping #capped.



26
27
28
29
30
# File 'lib/sentiero/analytics/collectors/vitals_collector.rb', line 26

def initialize(max_samples: nil)
  @max_samples = max_samples
  @metrics = {} # metric => {values:, ratings:, worst:}
  @capped = false
end

Instance Attribute Details

#cappedObject (readonly)

Returns the value of attribute capped.



23
24
25
# File 'lib/sentiero/analytics/collectors/vitals_collector.rb', line 23

def capped
  @capped
end

Instance Method Details

#collect(segment, session_id:, window_id:, anchor:) ⇒ Object

session_id/window_id/anchor attribute the worst (highest-value) sample. anchor is the window's first-event timestamp; offset_ms is relative to it so replay deep-links target the window start, not the segment.



35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
# File 'lib/sentiero/analytics/collectors/vitals_collector.rb', line 35

def collect(segment, session_id:, window_id:, anchor:)
  samples = {}
  segment.each do |event|
    sample = parse_sample(event)
    samples[sample[:metric]] = sample if sample
  end

  samples.each_value do |sample|
    entry = @metrics[sample[:metric]] ||= {values: [], ratings: Hash.new(0), worst: nil}
    if @max_samples && entry[:values].size >= @max_samples
      @capped = true
      next
    end

    entry[:values] << sample[:value]

    rating = sample[:rating]
    entry[:ratings][rating] += 1 if rating.is_a?(String) && !rating.empty?

    if entry[:worst].nil? || sample[:value] > entry[:worst][:value]
      entry[:worst] = {
        session_id: session_id,
        window_id: window_id,
        offset_ms: offset_ms(anchor, sample[:timestamp]),
        value: sample[:value]
      }
    end
  end
end

#summarizeObject



65
66
67
68
69
70
71
# File 'lib/sentiero/analytics/collectors/vitals_collector.rb', line 65

def summarize
  summarized = @metrics.transform_values { |entry| summarize_metric(entry) }
  {
    sample_count: summarized.values.sum { |m| m[:samples] },
    metrics: summarized
  }
end