Class: Lens::Rails::LogExporter

Inherits:
Logger
  • Object
show all
Defined in:
lib/lens/rails/log_exporter.rb

Overview

Logger sink that buffers log records in a thread-safe Queue and ships them to POST /v1/logs via a single persistent HTTPS connection. A dedicated worker thread blocks on the queue and drains in batches, so there are no timer wakeups that can interfere with Puma response writes.

Constant Summary collapse

SEVERITY_TEXT =
{
  ::Logger::DEBUG => "DEBUG",
  ::Logger::INFO => "INFO",
  ::Logger::WARN => "WARN",
  ::Logger::ERROR => "ERROR",
  ::Logger::FATAL => "FATAL",
  ::Logger::UNKNOWN => "UNKNOWN"
}.freeze
BATCH_SIZE =
500

Instance Method Summary collapse

Constructor Details

#initialize(url:, token:, service_name:, max_buffer: 10_000, min_severity: ::Logger::INFO, open_timeout: 2, read_timeout: 2) ⇒ LogExporter

Returns a new instance of LogExporter.



25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
# File 'lib/lens/rails/log_exporter.rb', line 25

def initialize(url:, token:, service_name:,
  max_buffer: 10_000,
  min_severity: ::Logger::INFO,
  open_timeout: 2,
  read_timeout: 2)
  super(File::NULL)
  @token = token
  @service_name = service_name
  @uri = URI("#{url}/v1/logs")
  @open_timeout = open_timeout
  @read_timeout = read_timeout
  @min_severity = min_severity
  @max_buffer = max_buffer
  @queue = SizedQueue.new(max_buffer)
  @http = nil
  start_worker
  Lens::Rails.register_flushable(self)
end

Instance Method Details

#add(severity, message = nil, progname = nil, &block) ⇒ Object



44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
# File 'lib/lens/rails/log_exporter.rb', line 44

def add(severity, message = nil, progname = nil, &block)
  return true if Thread.current[:lens_in_export]

  severity ||= ::Logger::UNKNOWN
  return true if severity < @min_severity

  message = block ? block.call : progname if message.nil?
  return true if message.nil?

  record = {
    timestamp: Time.now.iso8601(3),
    severity: SEVERITY_TEXT[severity] || "UNKNOWN",
    body: message.to_s.gsub(/\e\[[0-9;]*m/, ""),
    controller: Thread.current[:lens_controller],
    action: Thread.current[:lens_action],
    request_id: Thread.current[:lens_request_id],
    job_id: Thread.current[:lens_job_id]
  }.compact

  @queue.push(record, true)
rescue ThreadError
  # Buffer full, drop record silently
end

#restart_flush_threadObject



74
75
76
77
78
79
80
81
82
83
# File 'lib/lens/rails/log_exporter.rb', line 74

def restart_flush_thread
  begin
    @worker&.kill
  rescue
    nil
  end
  close_http
  @queue = SizedQueue.new(@max_buffer)
  start_worker
end

#shutdown(timeout:) ⇒ Object



68
69
70
71
72
# File 'lib/lens/rails/log_exporter.rb', line 68

def shutdown(timeout:)
  @queue.close
  @worker&.join(timeout)
rescue
end