Class: Onlylogs::HttpDevice

Inherits:
Object
  • Object
show all
Defined in:
lib/onlylogs/http_device.rb

Constant Summary collapse

DEFAULT_BATCH_SIZE =
100
DEFAULT_FLUSH_INTERVAL =
0.5
DEFAULT_MAX_QUEUE_SIZE =
10_000
DEFAULT_OPEN_TIMEOUT =

Keep timeouts short: a single slow/dead drain must never stall the app for long.

0.5
DEFAULT_READ_TIMEOUT =
0.5
DEFAULT_KEEP_ALIVE_TIMEOUT =

How long Net::HTTP may keep an idle connection around for reuse. Comfortably longer than the default flush interval so normal traffic reuses one connection across many batches.

30
CIRCUIT_FAILURE_THRESHOLD =

Open the circuit after this many consecutive failed sends

3
CIRCUIT_COOLDOWN =

...and keep it open for this long once it is open.

30

Instance Method Summary collapse

Constructor Details

#initialize(drain_url: ENV["ONLYLOGS_DRAIN_URL"], batch_size: ENV.fetch("ONLYLOGS_BATCH_SIZE", DEFAULT_BATCH_SIZE).to_i, flush_interval: ENV.fetch("ONLYLOGS_FLUSH_INTERVAL", DEFAULT_FLUSH_INTERVAL).to_f, max_queue_size: ENV.fetch("ONLYLOGS_MAX_QUEUE_SIZE", DEFAULT_MAX_QUEUE_SIZE).to_i, open_timeout: ENV.fetch("ONLYLOGS_OPEN_TIMEOUT", DEFAULT_OPEN_TIMEOUT).to_f, read_timeout: ENV.fetch("ONLYLOGS_READ_TIMEOUT", DEFAULT_READ_TIMEOUT).to_f, circuit_cooldown: ENV.fetch("ONLYLOGS_CIRCUIT_COOLDOWN", CIRCUIT_COOLDOWN).to_f, keep_alive_timeout: ENV.fetch("ONLYLOGS_KEEP_ALIVE_TIMEOUT", DEFAULT_KEEP_ALIVE_TIMEOUT).to_f, spool_dir: ENV.fetch("ONLYLOGS_SPOOL_DIR", default_spool_dir), spool_max_bytes: ENV.fetch("ONLYLOGS_SPOOL_MAX_BYTES", Spool::DEFAULT_MAX_BYTES).to_i) ⇒ HttpDevice

Returns a new instance of HttpDevice.



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
64
65
66
67
68
69
70
71
72
73
74
75
# File 'lib/onlylogs/http_device.rb', line 38

def initialize(
  drain_url: ENV["ONLYLOGS_DRAIN_URL"],
  batch_size: ENV.fetch("ONLYLOGS_BATCH_SIZE", DEFAULT_BATCH_SIZE).to_i,
  flush_interval: ENV.fetch("ONLYLOGS_FLUSH_INTERVAL", DEFAULT_FLUSH_INTERVAL).to_f,
  max_queue_size: ENV.fetch("ONLYLOGS_MAX_QUEUE_SIZE", DEFAULT_MAX_QUEUE_SIZE).to_i,
  open_timeout: ENV.fetch("ONLYLOGS_OPEN_TIMEOUT", DEFAULT_OPEN_TIMEOUT).to_f,
  read_timeout: ENV.fetch("ONLYLOGS_READ_TIMEOUT", DEFAULT_READ_TIMEOUT).to_f,
  circuit_cooldown: ENV.fetch("ONLYLOGS_CIRCUIT_COOLDOWN", CIRCUIT_COOLDOWN).to_f,
  keep_alive_timeout: ENV.fetch("ONLYLOGS_KEEP_ALIVE_TIMEOUT", DEFAULT_KEEP_ALIVE_TIMEOUT).to_f,
  spool_dir: ENV.fetch("ONLYLOGS_SPOOL_DIR", default_spool_dir),
  spool_max_bytes: ENV.fetch("ONLYLOGS_SPOOL_MAX_BYTES", Spool::DEFAULT_MAX_BYTES).to_i
)
  @drain_url = drain_url
  @uri = URI.parse(drain_url) if drain_url
  @batch_size = batch_size
  @flush_interval = flush_interval
  @max_queue_size = max_queue_size
  @open_timeout = open_timeout
  @read_timeout = read_timeout
  @circuit_cooldown = circuit_cooldown
  @keep_alive_timeout = keep_alive_timeout
  @queue = Queue.new
  @mutex = Mutex.new
  @http_mutex = Mutex.new
  @http = nil
  @spool = nil

  @consecutive_failures = 0
  @circuit_open_until = nil
  @dropped = 0

  if @drain_url
    @spool = build_spool(spool_dir, spool_max_bytes)
    start_sender
  else
    $stderr.puts "Onlylogs::HttpDevice: ONLYLOGS_DRAIN_URL is not set; logging locally only." # rubocop:disable Style/StderrPuts
  end
end

Instance Method Details

#closeObject



86
87
88
89
90
91
# File 'lib/onlylogs/http_device.rb', line 86

def close
  flush
  @running = false
  @sender_thread&.join(2)
  close_connection
end

#flushObject



93
94
95
# File 'lib/onlylogs/http_device.rb', line 93

def flush
  send_batch(drain_queue)
end

#write(message) ⇒ Object

Receives the already-formatted, already-level-filtered line from Logger#add.



78
79
80
81
82
83
84
# File 'lib/onlylogs/http_device.rb', line 78

def write(message)
  return if message.nil? || message.empty?
  # No drain configured: nothing to ship. The local fallback (see MultiDevice) still logs it.
  return unless @drain_url

  enqueue(message.chomp)
end