Skip to content

Commit

Permalink
Wrap appender
Browse files Browse the repository at this point in the history
  • Loading branch information
shalvah committed Feb 26, 2023
1 parent 3551891 commit f08e8c4
Show file tree
Hide file tree
Showing 3 changed files with 40 additions and 25 deletions.
3 changes: 1 addition & 2 deletions lib/honeybadger/backend/server.rb
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,7 @@ module Backend
class Server < Base
ENDPOINTS = {
notices: '/v1/notices'.freeze,
deploys: '/v1/deploys'.freeze,
logs: '/v1/events'.freeze,
deploys: '/v1/deploys'.freeze
}.freeze

CHECK_IN_ENDPOINT = '/v1/check_in'.freeze
Expand Down
34 changes: 25 additions & 9 deletions lib/honeybadger/logger.rb
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,7 @@ def self.create(**args)
# and call #batch when the batch is ready to be sent
class HttpAppender < SemanticLogger::Subscriber
MAX_RETRY_BACKLOG = 200.freeze
LOGS_HOST = "localhost:4567"

def initialize(*)
super
Expand All @@ -85,32 +86,47 @@ def default_formatter

def batch(logs)
payload = logs.map { |log| formatter.call(log, self) }.join("\n")
def payload.to_json; self; end # The Server backend calls to_json
response = Honeybadger.config.backend.notify(:logs, payload)

if response.success?
succeeded = send_payload(payload)
if succeeded
retry_previous_failed_requests
else
@retry_queue << payload
@retry_queue.shift if @retry_queue.size > MAX_RETRY_BACKLOG
retry_later(payload)
end
rescue => e
retry_later(payload)
Honeybadger::Logger.log_internal_error(e, action: :send)
end

private

def send_payload(payload)
semantic_logger_http.__send__(:post, payload)
end

def retry_later(payload)
@retry_queue << payload
@retry_queue.shift if @retry_queue.size > MAX_RETRY_BACKLOG
end

def semantic_logger_http
@semantic_logger_http ||= ::SemanticLogger::Appender.factory(
appender: :http,
url: "http://honeybadger:#{Honeybadger.config[:api_key]}@#{LOGS_HOST}/v1/events",
compress: true,
)
end

def retry_previous_failed_requests
can_send = true
until @retry_queue.empty? || !can_send
payload = @retry_queue.shift
response = Honeybadger.config.backend.notify(:logs, payload)
if !response.success?
succeeded = send_payload(payload)
if !succeeded
@retry_queue.unshift(payload)
can_send = false
end
end
end
end
end
end
end
28 changes: 14 additions & 14 deletions spec/unit/honeybadger/logger_spec.rb
Original file line number Diff line number Diff line change
@@ -1,20 +1,22 @@
require 'honeybadger/logger'

RSpec.describe Honeybadger::Logger do
let(:mock_http) { double(SemanticLogger::Appender::Http) }
let(:received_batches) { [] }

before do
Honeybadger.logger.instance_variable_set(:@appender, nil)
Honeybadger::Backend::Test.notifications[:logs] = []
Honeybadger.config[:backend] = :test
allow(SemanticLogger::Appender::Http).to receive(:new).and_return(mock_http)
allow(mock_http).to receive(:post) do |payload|
received_batches << payload
true
end
end

after do
Honeybadger.logger.instance_variable_get(:@appender).shutdown!
end

def received_batches
Honeybadger::Backend::Test.notifications[:logs]
end

def wait_for_other_thread(wait = 0.05)
yield
sleep wait
Expand Down Expand Up @@ -54,12 +56,7 @@ def wait_for_other_thread(wait = 0.05)
Honeybadger.config[:"features.logger.batch_size"] = 200
Honeybadger.config[:"features.logger.batch_interval"] = 0.001

backend = Honeybadger::Backend::Test.new(Honeybadger.config)
Honeybadger.config[:backend] = backend

expect(backend).to receive(:notify).twice do
Honeybadger::Backend::Null::StubbedResponse.new(successful: false)
end
expect(mock_http).to receive(:post).twice { false }
# Four messages across three batches, with the first two batches failing
wait_for_other_thread do
Honeybadger.logger.debug("First - fails")
Expand All @@ -69,7 +66,10 @@ def wait_for_other_thread(wait = 0.05)

expect(received_batches.size).to eq(0)

expect(backend).to receive(:notify).exactly(3).times.and_call_original
expect(mock_http).to receive(:post).exactly(3).times do |payload|
received_batches << payload
true
end
wait_for_other_thread { Honeybadger.logger.error("Fourth - succeeds") }

expect(received_batches.size).to eq(3)
Expand All @@ -80,4 +80,4 @@ def wait_for_other_thread(wait = 0.05)
["Fourth - succeeds", "First - fails", "Second - fails", "Third - fails"]
)
end
end
end

0 comments on commit f08e8c4

Please sign in to comment.