From ac6fe90a8cce7257e0e9941a3db31430f9f99a70 Mon Sep 17 00:00:00 2001 From: Adam Cooke Date: Mon, 16 Sep 2024 11:08:01 +0100 Subject: [PATCH] feat: adds Logger#with_destination to log blocks to custom destinations --- README.md | 7 ++++++- lib/klogger/logger.rb | 10 +++++++++- spec/helpers/fake_destination.rb | 15 +++++++++++++++ spec/specs/logger_spec.rb | 19 +++++++++++++++++++ 4 files changed, 49 insertions(+), 2 deletions(-) create mode 100644 spec/helpers/fake_destination.rb diff --git a/README.md b/README.md index 6b9873e..cb83819 100644 --- a/README.md +++ b/README.md @@ -78,7 +78,7 @@ logger.info { "Hello world!" } logger.info('Result of 1 + 1') { 1 + 1 } # Logs with a message of "Result: 2" ``` -### Loggging exceptions +### Logging exceptions Exceptions happen and when they do, you want to know about them. Klogger provides a helper method to log exceptions. These will automatically be logged with the `error` severity. @@ -197,4 +197,9 @@ end # Create a logger and add the destination logger = Klogger.new(name) logger.add_destination(GraylogDestination.new('graylog.example.com', 12201)) + +# If you only want to send certain data to another block, you can do so +logger.with_destination(other_destination) do + # ... +end ``` diff --git a/lib/klogger/logger.rb b/lib/klogger/logger.rb index 953848d..a1dd4a0 100644 --- a/lib/klogger/logger.rb +++ b/lib/klogger/logger.rb @@ -36,6 +36,7 @@ def initialize(name = nil, @destinations = [] @group_set = GroupSet.new @silenced = Concurrent::ThreadLocalVar.new { false } + @block_destinations = Concurrent::ThreadLocalVar.new { [] } @include_group_ids = include_group_ids super(destination) self.formatter = FORMATTERS[formatter].new(highlight: highlight) @@ -98,6 +99,13 @@ def remove_destination(destination) @destinations.delete(destination) end + def with_destination(destination) + @block_destinations.value << destination + yield + ensure + @block_destinations.value.delete(destination) + end + def create_tagged_logger(**tags) TaggedLogger.new(self, **tags) end @@ -142,7 +150,7 @@ def create_payload(severity, message, tags) end def call_destinations(payload, group_ids) - @destinations.each do |destination| + (@destinations + @block_destinations.value).each do |destination| destination.call(self, payload.dup, group_ids) rescue StandardError => e # If something goes wrong in here, we don't want to break the application diff --git a/spec/helpers/fake_destination.rb b/spec/helpers/fake_destination.rb new file mode 100644 index 0000000..f38f87f --- /dev/null +++ b/spec/helpers/fake_destination.rb @@ -0,0 +1,15 @@ +# frozen_string_literal: true + +class FakeDestination + + attr_reader :lines + + def initialize + @lines = [] + end + + def call(logger, payload, group_ids) + @lines << [logger, payload, group_ids] + end + +end diff --git a/spec/specs/logger_spec.rb b/spec/specs/logger_spec.rb index f8ae10b..a7b29fd 100644 --- a/spec/specs/logger_spec.rb +++ b/spec/specs/logger_spec.rb @@ -3,6 +3,7 @@ require 'spec_helper' require 'klogger' require 'klogger/logger' +require_relative '../helpers/fake_destination' module Klogger @@ -394,6 +395,24 @@ module Klogger expect(logger.destinations).to_not include destination end end + + describe '#with_destination' do + subject(:logger) { described_class.new('example', destination: output) } + let(:fake_destination) { FakeDestination.new } + + it 'sends log output to the given destination for the duration of the block' do + logger.info 'line1' + logger.with_destination(fake_destination) do + logger.info 'line2' + logger.info 'line3' + end + logger.info 'line4' + expect(fake_destination.lines).to match [ + [logger, hash_including(message: 'line2'), []], + [logger, hash_including(message: 'line3'), []] + ] + end + end end end