Class: Errorgap::LogDelivery

Inherits:
Object
  • Object
show all
Defined in:
lib/errorgap/log_delivery.rb

Overview

Delivers structured log lines to the ingestion API. Levels are ranked so a configurable minimum threshold can drop low-severity logs before any request is made.

Constant Summary collapse

LEVELS =
%w[trace debug info warn error fatal].freeze
LEVEL_ALIASES =
{ "warning" => "warn", "err" => "error", "critical" => "fatal", "panic" => "fatal" }.freeze

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(configuration) ⇒ LogDelivery

Returns a new instance of LogDelivery.



16
17
18
# File 'lib/errorgap/log_delivery.rb', line 16

def initialize(configuration)
  configure(configuration)
end

Class Method Details

.normalize_level(level) ⇒ Object



65
66
67
68
69
# File 'lib/errorgap/log_delivery.rb', line 65

def self.normalize_level(level)
  value = level.to_s.strip.downcase
  value = LEVEL_ALIASES.fetch(value, value)
  LEVELS.include?(value) ? value : "info"
end

.rank(level) ⇒ Object



71
72
73
# File 'lib/errorgap/log_delivery.rb', line 71

def self.rank(level)
  LEVELS.index(level) || LEVELS.index("info")
end

Instance Method Details

#configure(configuration) ⇒ Object



20
21
22
# File 'lib/errorgap/log_delivery.rb', line 20

def configure(configuration)
  @configuration = configuration
end

#deliver(payload) ⇒ Object



47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
# File 'lib/errorgap/log_delivery.rb', line 47

def deliver(payload)
  uri = URI.join(
    @configuration.endpoint.end_with?("/") ? @configuration.endpoint : "#{@configuration.endpoint}/",
    "api/projects/#{@configuration.project_slug}/logs"
  )
  request = Net::HTTP::Post.new(uri)
  request["Content-Type"] = "application/json"
  request["User-Agent"] = "errorgap-ruby/#{Errorgap::VERSION}"
  request["X-Errorgap-Project-Key"] = @configuration.api_key if present?(@configuration.api_key)
  request.body = JSON.generate(payload)

  Net::HTTP.start(uri.hostname, uri.port, use_ssl: uri.scheme == "https") do |http|
    http.request(request)
  end
rescue StandardError => exception
  @configuration.logger&.warn("[errorgap] log delivery error: #{exception.class}: #{exception.message}")
end

#log(message, level: "info", source: nil, environment: nil, occurred_at: nil, sync: false) ⇒ Object



24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
# File 'lib/errorgap/log_delivery.rb', line 24

def log(message, level: "info", source: nil, environment: nil, occurred_at: nil, sync: false)
  return unless @configuration.logs_enabled
  return if @configuration.ignored_environment?

  normalized = self.class.normalize_level(level)
  return if self.class.rank(normalized) < self.class.rank(self.class.normalize_level(@configuration.minimum_log_level))

  payload = {
    message: message.to_s,
    level: normalized,
    environment: environment || @configuration.environment,
    occurred_at: (occurred_at || Time.now).utc.iso8601(3)
  }
  payload[:source] = source.to_s if source

  if sync || !@configuration.async
    deliver(payload)
  else
    Errorgap.register_thread(Thread.new { deliver(payload) })
    nil
  end
end