Skip to content

Commit 06e5805

Browse files
Add child logger with instance named tags support
1 parent 4b948bb commit 06e5805

File tree

6 files changed

+64
-2
lines changed

6 files changed

+64
-2
lines changed

CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@ This project adheres to [Semantic Versioning](http://semver.org/).
55

66
## [unreleased]
77

8+
- Add child logger with instance named tags support
9+
810
## [4.17.0]
911

1012
- Correct `source_code_uri` URL

docs/api.md

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -633,4 +633,18 @@ Or, when using a Gemfile:
633633
gem "semantic_logger", require: "semantic_logger/sync"
634634
~~~
635635

636+
### Child Logger
637+
638+
It is possible to create child loggers with pre-set instance tags.
639+
Any log message emitted by a logger with pre-set instance tags will include these tags along with the message data.
640+
641+
~~~ruby
642+
logger = SemanticLogger["MyClass"]
643+
child_logger1 = logger.child(tag1: "value1", tag2: "value2")
644+
child_logger2 = child_logger1.child(tag3: "value3")
645+
646+
# Will include tag1, tag2, tag3 and tag4 in the output
647+
child_logger2.info("Some message", tag4: "value4")
648+
~~~
649+
636650
### [Next: Testing ==>](testing.html)

lib/semantic_logger/base.rb

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
module SemanticLogger
88
class Base
99
# Class name to be logged
10-
attr_accessor :name, :filter
10+
attr_accessor :name, :filter, :child_named_tags
1111

1212
# Set the logging level for this logger
1313
#
@@ -250,6 +250,14 @@ def should_log?(log)
250250
meets_log_level?(log) && !filtered?(log)
251251
end
252252

253+
# Creates a new logger with the given instance named tags
254+
def child(**named_tags)
255+
new_named_tags = child_named_tags.merge(named_tags)
256+
new_logger = dup
257+
new_logger.child_named_tags = new_named_tags
258+
new_logger
259+
end
260+
253261
private
254262

255263
# Initializer for Abstract Class SemanticLogger::Base
@@ -290,6 +298,7 @@ def initialize(klass, level = nil, filter = nil)
290298
else
291299
self.level = level
292300
end
301+
@child_named_tags = {}
293302
end
294303

295304
# Return the level index for fast comparisons
@@ -349,6 +358,9 @@ def log_internal(level, index, message = nil, payload = nil, exception = nil)
349358
end
350359
end
351360

361+
# Add child named tags to the log
362+
log.payload = child_named_tags.merge(log.payload || {})
363+
352364
# Log level may change during assign due to :on_exception_level
353365
self.log(log) if should_log && should_log?(log)
354366
end
@@ -389,6 +401,9 @@ def measure_internal(level, index, message, params)
389401
# Extract options after block completes so that block can modify any of the options
390402
payload = params[:payload]
391403

404+
# Add child named tags
405+
payload = child_named_tags.merge(payload || {})
406+
392407
# May return false due to elastic logging
393408
should_log = log.assign(
394409
message: message,

lib/semantic_logger/loggable.rb

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ def self.included(base)
4242

4343
# Returns [SemanticLogger::Logger] class level logger
4444
def self.logger
45-
@semantic_logger ||= SemanticLogger[self]
45+
@semantic_logger ||= SemanticLogger[self].child(**@logger_child_named_tags)
4646
end
4747

4848
# Replace instance class level logger
@@ -114,6 +114,10 @@ def #{method_name}(*args, &block)
114114
true
115115
end
116116

117+
def logger_child(**named_tags)
118+
@logger_child_named_tags = named_tags
119+
end
120+
117121
private
118122

119123
# Dynamic Module to intercept method calls for measuring purposes.

test/loggable_test.rb

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,14 @@ class TestAttribute
2727
include SemanticLogger::Loggable
2828
end
2929

30+
class TestChildClassLogger
31+
include SemanticLogger::Loggable
32+
33+
TAG_DATA = {tag1: "value1", tag2: "value2"}.freeze
34+
35+
logger_child(**TAG_DATA)
36+
end
37+
3038
describe SemanticLogger::Loggable do
3139
describe "inheritance" do
3240
it "should give child classes their own logger" do
@@ -79,5 +87,11 @@ class TestAttribute
7987
TestAttribute.new.logger.is_a?(SemanticLogger::Logger)
8088
end
8189
end
90+
91+
describe "sample child class logger" do
92+
it "has child named tags set" do
93+
assert_equal TestChildClassLogger::TAG_DATA, TestChildClassLogger.logger.child_named_tags
94+
end
95+
end
8296
end
8397
end

test/logger_test.rb

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -153,5 +153,18 @@ def self.call(log)
153153
end
154154
end
155155
end
156+
157+
describe ".child" do
158+
it "creates a child logger" do
159+
tag_data = {tag1: "value1", tag2: "value2"}
160+
child_logger = logger.child(**tag_data)
161+
child_logger.info("hello world")
162+
163+
assert_equal tag_data, child_logger.child_named_tags
164+
assert log = child_logger.events.first
165+
assert_equal "hello world", log.message
166+
assert_equal tag_data, log.payload
167+
end
168+
end
156169
end
157170
end

0 commit comments

Comments
 (0)