Class: Quonfig::Telemetry::ExampleContextsAggregator

Inherits:
Object
  • Object
show all
Defined in:
lib/quonfig/telemetry/example_contexts_aggregator.rb

Overview

Samples example contexts seen during evaluation. Dedupes by the concatenation of each named context’s “key” property and rate-limits each grouped key to once per hour.

Emits api-telemetry’s ‘exampleContexts` event — JSON wire format, matching sdk-node and sdk-go. This is NOT the old Prefab protobuf.

Constant Summary collapse

ONE_HOUR_SECONDS =
60 * 60

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(max_contexts:, rate_limit_seconds: ONE_HOUR_SECONDS) ⇒ ExampleContextsAggregator

Returns a new instance of ExampleContextsAggregator.



16
17
18
19
20
# File 'lib/quonfig/telemetry/example_contexts_aggregator.rb', line 16

def initialize(max_contexts:, rate_limit_seconds: ONE_HOUR_SECONDS)
  @max_contexts = max_contexts
  @data = Concurrent::Array.new
  @cache = Quonfig::RateLimitCache.new(rate_limit_seconds)
end

Instance Attribute Details

#cacheObject (readonly)

Returns the value of attribute cache.



14
15
16
# File 'lib/quonfig/telemetry/example_contexts_aggregator.rb', line 14

def cache
  @cache
end

#dataObject (readonly)

Returns the value of attribute data.



14
15
16
# File 'lib/quonfig/telemetry/example_contexts_aggregator.rb', line 14

def data
  @data
end

Instance Method Details

#drain_eventObject

Drain accumulated examples into a single telemetry event payload matching api-telemetry’s ExampleContextsSchema, or nil if empty.



47
48
49
50
51
52
53
54
55
56
57
58
# File 'lib/quonfig/telemetry/example_contexts_aggregator.rb', line 47

def drain_event
  return nil if @data.size.zero?

  to_ship = prepare_data

  examples = to_ship.map do |timestamp_ms, context|
    contexts_list = contexts_to_list(context)
    { 'timestamp' => timestamp_ms, 'contextSet' => { 'contexts' => contexts_list } }
  end

  { 'exampleContexts' => { 'examples' => examples } }
end

#prepare_dataObject



38
39
40
41
42
43
# File 'lib/quonfig/telemetry/example_contexts_aggregator.rb', line 38

def prepare_data
  to_ship = @data.dup
  @data.clear
  @cache.prune
  to_ship
end

#record(context) ⇒ Object

Record a context for possible emission. Expects a Quonfig::Context. Contexts with no grouped_key (nothing to dedupe on) are dropped to avoid shipping empty/anonymous samples.



25
26
27
28
29
30
31
32
33
34
35
36
# File 'lib/quonfig/telemetry/example_contexts_aggregator.rb', line 25

def record(context)
  return if @max_contexts <= 0
  return if context.nil?

  key = grouped_key_for(context)
  return if key.nil? || key.empty?

  return unless @data.size < @max_contexts && !@cache.fresh?(key)

  @cache.set(key)
  @data.push([Quonfig::TimeHelpers.now_in_ms, context])
end