Class: Libhoney::ExperimentalTransmissionClient Private

Inherits:
TransmissionClient show all
Defined in:
lib/libhoney/experimental_transmission.rb

Overview

This class is part of a private API. You should avoid using this class if possible, as it may be removed or be changed in the future.

An experimental variant of the standard TransmissionClient that uses a custom implementation of a sized queue whose pop/push methods support a timeout internally.

Examples:

Use this transmission with the Ruby Beeline

require 'libhoney/experimental_transmission'

Honeycomb.configure do |config|
  config.client = Libhoney::Client.new(
    writekey: ENV["HONEYCOMB_WRITE_KEY"],
    dataset: ENV.fetch("HONEYCOMB_DATASET", "awesome_sauce"),
    transmission: Libhoney::ExperimentalTransmissionClient
  )
  ...
end

Constant Summary

Constants included from Cleaner

Cleaner::ENCODING_OPTIONS, Cleaner::RAISED, Cleaner::RECURSION

Instance Method Summary collapse

Methods inherited from TransmissionClient

#close, #initialize, #send_loop

Methods included from Cleaner

#clean_data, #clean_string

Constructor Details

This class inherits a constructor from Libhoney::TransmissionClient

Instance Method Details

#add(event) ⇒ Object

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.


25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
# File 'lib/libhoney/experimental_transmission.rb', line 25

def add(event)
  return unless event_valid(event)

  begin
    # if block_on_send is true, never timeout the wait to enqueue an event
    # otherwise, timeout the wait immediately and if the queue is full, we'll
    # have a ThreadError raised because we could not add to the queue.
    timeout = @block_on_send ? :never : 0
    @batch_queue.enq(event, timeout)
  rescue Libhoney::Queueing::SizedQueueWithTimeout::PushTimedOut
    # happens if the queue was full and block_on_send = false.
    warn "#{self.class.name}: batch queue full, dropping event." if %w[debug trace].include?(ENV['LOG_LEVEL'])
  end

  ensure_threads_running
end

#batch_loopObject

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.


42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
# File 'lib/libhoney/experimental_transmission.rb', line 42

def batch_loop
  next_send_time = Time.now + @send_frequency
  batched_events = Hash.new do |h, key|
    h[key] = []
  end

  loop do
    begin
      # an event on the batch_queue
      #   1. pops out and is truthy
      #   2. gets included in the current batch
      #   3. while waits for another event
      while (event = @batch_queue.pop(@send_frequency))
        key = [event.api_host, event.writekey, event.dataset]
        batched_events[key] << event
      end

      # a nil on the batch_queue
      #   1. pops out and is falsy
      #   2. ends the event-popping while do..end
      #   3. breaks the loop
      #   4. flushes the current batch
      #   5. ends the batch_loop
      break

    # a timeout expiration waiting for an event
    #   1. skips the break and is rescued
    #   2. triggers the ensure to flush the current batch
    #   3. begins the loop again with an updated next_send_time
    rescue Libhoney::Queueing::SizedQueueWithTimeout::PopTimedOut => e
      warn "#{self.class.name}: ⏱ " + e.message if %w[trace].include?(ENV['LOG_LEVEL'])

    # any exception occurring in this loop should not take down the actual
    # instrumented Ruby process, so handle here and log that there is trouble
    rescue Exception => e
      warn "#{self.class.name}: 💥 " + e.message if %w[debug trace].include?(ENV['LOG_LEVEL'])
      warn e.backtrace.join("\n").to_s if ['trace'].include?(ENV['LOG_LEVEL'])

    # regardless of the exception, figure out whether enough time has passed to
    # send the current batched events, if so, send them and figure out the next send time
    # before going back to the top of the loop
    ensure
      next_send_time = flush_batched_events(batched_events) if Time.now > next_send_time
    end
  end

  # don't need to capture the next_send_time here because the batch_loop is exiting
  # for some reason (probably transmission.close)
  flush_batched_events(batched_events)
end