From eb16561f52c711318a9c04e1497faed3432e45c1 Mon Sep 17 00:00:00 2001 From: Adam Cooke Date: Fri, 1 Mar 2024 09:45:09 +0000 Subject: [PATCH] feat: tagged loggers --- .rubocop.yml | 2 +- README.md | 12 ++++++- lib/klogger.rb | 1 + lib/klogger/logger.rb | 20 ++++++++---- lib/klogger/tagged_logger.rb | 56 ++++++++++++++++++++++++++++++++ spec/specs/logger_spec.rb | 8 +++++ spec/specs/tagged_logger_spec.rb | 52 +++++++++++++++++++++++++++++ 7 files changed, 142 insertions(+), 9 deletions(-) create mode 100644 lib/klogger/tagged_logger.rb create mode 100644 spec/specs/tagged_logger_spec.rb diff --git a/.rubocop.yml b/.rubocop.yml index 0aefcf0..e58bfac 100644 --- a/.rubocop.yml +++ b/.rubocop.yml @@ -24,7 +24,7 @@ Metrics/MethodLength: Max: 14 Metrics/ClassLength: - Max: 120 + Max: 140 Style/SymbolArray: EnforcedStyle: brackets diff --git a/README.md b/README.md index c6f9fc2..05cc9db 100644 --- a/README.md +++ b/README.md @@ -135,7 +135,7 @@ Klogger.group(ip: '1.2.3.4') do end # If you can't use a block you can manually open and close a group but you'll need to be sure to close it -# when you're finished. +# when you're finished. group_id = Klogger.global_groups.add(ip: '1.2.3.4') # ... do anything that you want - everything will be tagged as appropriate Klogger.global_groups.pop @@ -149,6 +149,16 @@ logger.tagged(name: 'steve') do end ``` +## Tagged Loggers + +If you wish to apply tags to a series of log entries but you don't wish to use blocks, you can create a "sub" logger which will always include those tags for all messages sent to it. + +```ruby +logger = Klogger.new(:logger) +tagged_logger = logger.create_tagged_logger(tag: 'my-tag') +tagged_logger.info "Hello world!" # => will be tagged with tag=my-tag +``` + ### Silencing Sometimes you don't want to log for a little while. You can use the `silence` method to temporarily disable logging. diff --git a/lib/klogger.rb b/lib/klogger.rb index 80116de..7067b31 100644 --- a/lib/klogger.rb +++ b/lib/klogger.rb @@ -1,6 +1,7 @@ # frozen_string_literal: true require 'klogger/logger' +require 'klogger/tagged_logger' module Klogger diff --git a/lib/klogger/logger.rb b/lib/klogger/logger.rb index 879025d..953848d 100644 --- a/lib/klogger/logger.rb +++ b/lib/klogger/logger.rb @@ -25,7 +25,11 @@ class Logger < ::Logger go: Formatters::Go }.freeze - def initialize(name = nil, destination: $stdout, formatter: :go, highlight: false, include_group_ids: false, + def initialize(name = nil, + destination: $stdout, + formatter: :go, + highlight: false, + include_group_ids: false, tags: {}) @name = name @tags = tags @@ -39,12 +43,10 @@ def initialize(name = nil, destination: $stdout, formatter: :go, highlight: fals def exception(exception, message = nil, **tags) error( - **{ - message: message, - exception: exception.class.name, - exception_message: exception.message, - backtrace: exception.backtrace[0, 4].join("\n") - }.merge(tags) + message: message, + exception: exception.class.name, + exception_message: exception.message, + backtrace: exception.backtrace[0, 4].join("\n"), **tags ) end @@ -96,6 +98,10 @@ def remove_destination(destination) @destinations.delete(destination) end + def create_tagged_logger(**tags) + TaggedLogger.new(self, **tags) + end + private def add(severity, message = nil, progname = nil, **tags, &block) diff --git a/lib/klogger/tagged_logger.rb b/lib/klogger/tagged_logger.rb new file mode 100644 index 0000000..72ba5f9 --- /dev/null +++ b/lib/klogger/tagged_logger.rb @@ -0,0 +1,56 @@ +# frozen_string_literal: true + +require 'klogger/logger' + +module Klogger + class TaggedLogger + + def initialize(parent, **tags) + @parent = parent + @tags = tags + end + + Klogger::Logger::LEVELS.each do |level| + define_method(level) do |message = nil, progname = nil, **tags, &block| + @parent.public_send(level, message, progname, **@tags.merge(tags), &block) + end + end + + def exception(exception, message = nil, **tags) + @parent.exception(exception, message, **@tags.merge(tags)) + end + + def group(**tags, &block) + @parent.group(**@tags.merge(tags), &block) + end + + def add_group(**tags) + @parent.add_group(**@tags.merge(tags)) + end + + def pop_group + @parent.pop_group + end + + def tagged(**tags, &block) + @parent.tagged(**@tags.merge(tags), &block) + end + + def silence!(&block) + @parent.silence!(&block) + end + + def unsilence!(&block) + @parent.unsilence!(&block) + end + + def silenced? + @parent.silenced? + end + + def create_tagged_logger(**tags) + @parent.create_tagged_logger(**@tags.merge(tags)) + end + + end +end diff --git a/spec/specs/logger_spec.rb b/spec/specs/logger_spec.rb index 2deaea3..f8ae10b 100644 --- a/spec/specs/logger_spec.rb +++ b/spec/specs/logger_spec.rb @@ -366,6 +366,14 @@ module Klogger end end + describe '#create_tagged_logger' do + subject(:logger) { described_class.new('example', destination: output, formatter: :json) } + + it 'returns a new tagged logger' do + expect(logger.create_tagged_logger(tag: 'tag1')).to be_a Klogger::TaggedLogger + end + end + describe '#add_destination' do subject(:logger) { described_class.new('example', destination: output) } diff --git a/spec/specs/tagged_logger_spec.rb b/spec/specs/tagged_logger_spec.rb new file mode 100644 index 0000000..a009cd1 --- /dev/null +++ b/spec/specs/tagged_logger_spec.rb @@ -0,0 +1,52 @@ +# frozen_string_literal: true + +require 'spec_helper' +require 'klogger' +require 'klogger/tagged_logger' + +module Klogger + + RSpec.describe TaggedLogger do + before { Timecop.freeze } + after { Timecop.return } + + let!(:output) { StringIO.new } + let(:logger) { Logger.new('example', destination: output, formatter: :json) } + + subject(:tagged_logger) { described_class.new(logger, tag1: 'test') } + + Logger::LEVELS.each do |level| + describe "##{level}" do + it 'logs with the parent classes' do + tagged_logger.public_send(level, 'Hello', tag2: 'test') + expect(output.string).to eq({ time: Time.now.to_s, severity: level, + logger: 'example', message: 'Hello', + tag1: 'test', tag2: 'test' }.to_json + "\n") + end + end + end + + describe '#group' do + it 'logs appropriately' do + tagged_logger.group(grouptag: 'gt1') do + tagged_logger.info 'Hello', tag2: 'test' + end + expect(output.string).to eq({ time: Time.now.to_s, severity: 'info', + logger: 'example', message: 'Hello', + tag1: 'test', tag2: 'test', grouptag: 'gt1' }.to_json + "\n") + end + end + + describe '#tagged' do + it 'logs appropriately' do + tagged_logger.tagged(taggedtag: 'gt1') do + tagged_logger.info 'Hello', tag2: 'test' + end + expect(output.string).to eq({ time: Time.now.to_s, severity: 'info', + logger: 'example', message: 'Hello', + tag1: 'test', tag2: 'test', taggedtag: 'gt1' }.to_json + "\n") + end + end + end + +end