Skip to content
This repository was archived by the owner on Jan 29, 2025. It is now read-only.

tagged logging support key-value tags with backward compatibility #3

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,4 @@ tmp/

.DS_Store
*.gem

.bundle
64 changes: 60 additions & 4 deletions lib/gelf/logger.rb
Original file line number Diff line number Diff line change
Expand Up @@ -58,23 +58,72 @@ def <<(message)
end

def tagged(*tags)
new_tags = push_tags(*tags)
new_keys, new_values = push_tags(*tags)
yield self
ensure
current_tags.pop(new_tags.size)
log_tags.pop(new_keys.size)
current_tags.pop(new_values.size)
end

# be aware direct call of #push_tags will overwrite defined log_tags - current_tags values
# if log_tags is defined globally better use #tagged
def push_tags(*tags)
tags.flatten.reject{ |t| t.respond_to?(:empty?) ? !!t.empty? : !t }.tap do |new_tags|
current_tags.concat new_tags
new_keys, new_values = to_new_keys_and_values(*tags)
self.log_tags = Array(log_tags).concat(new_keys)
current_tags.concat(new_values)

return new_keys, new_values
end

def to_new_keys_and_values(*tags)
new_tags = tags.flatten
values_to_fill = (log_tags && log_tags.size - current_tags.size) || 0
new_values = []
new_keys = []

if tags.first.is_a?(Hash)
new_tags.first.reject! { |k, v| k.respond_to?(:empty?) ? !!k.empty? : !k || v.respond_to?(:empty?) ? !!v.empty? : !v }
new_keys = new_tags.first.keys
new_values = Array.new(values_to_fill, '').concat(new_tags.first.values)

return new_keys, new_values
end

if values_to_fill > 0
new_values = new_tags.shift(values_to_fill)
end

unless new_tags.empty?
new_tags.reject{ |t| t.respond_to?(:empty?) ? !!t.empty? : !t }.each.with_index(1) do |tag, index|
new_keys << "tag_#{(log_tags&.size || 0) + index}"
new_values << tag
end
end

return new_keys, new_values
end

def current_tags
val = Thread.current.thread_variable_get(:gelf_tagged_logging_tags)
return val unless val.nil?
Thread.current.thread_variable_set(:gelf_tagged_logging_tags, [])
end

def clear_tags!
self.log_tags.clear
current_tags.clear
end

def pop_tags(size = 1)
log_tags.pop(size)
current_tags.pop(size)
end

def pop_tag_by_key(key)
index = log_tags.index { |log_tag_key| log_tag_key.to_s == key.to_s }
log_tags.delete_at(index)
current_tags.delete_at(index)
end
end

# Graylog2 notifier, compatible with Ruby Logger.
Expand All @@ -87,6 +136,13 @@ def current_tags
# config.logger = GELF::Logger.new("localhost", 12201, "LAN", { :facility => "appname" })
# config.log_tags = [:uuid, :remote_ip]
# config.logger.log_tags = [:uuid_name, :remote_ip_name] # Same order as config.log_tags
#
# To add constants log_tags values - be aware it will overwrite config.log_tags:
# logger.push_tags({environment: 'production', stage: 'production'})
# To add additional log_tags in block:
# logger.tagged({tag_name: 'tag_value'}) { logger.info('...') }


class Logger < Notifier
include LoggerCompatibility
end
Expand Down
81 changes: 68 additions & 13 deletions test/test_logger.rb
Original file line number Diff line number Diff line change
Expand Up @@ -240,36 +240,91 @@ class TestLogger < Test::Unit::TestCase
# Supports only Ruby 2.0 or higher
if RUBY_VERSION[0, 1].to_i >= 2
context "#tagged" do
# logger.tagged("TAG") { logger.info "Message" }
should "support tagged method" do
context 'backward compatibility' do
#logger.tagged("TAG") { logger.info "Message" }
should "support tagged method with undefined log_tags" do
@logger.expects(:notify_with_level!).with do |level, hash|
level == GELF::INFO &&
hash['short_message'] == 'Message' &&
hash['facility'] == 'gelf-rb' &&
hash['_tag_1'] == 'TAG_1' &&
hash['_tag_2'] == 'TAG_2'
end

@logger.tagged('TAG_1', 'TAG_2') { @logger.info "Message" }
end

should "support tagged method with defined log_tags" do
# I want the first tag with name 'test_tag'
@logger.log_tags = [:test_tag1]

@logger.expects(:notify_with_level!).with do |level, hash|
level == GELF::INFO &&
hash['short_message'] == 'Message' &&
hash['facility'] == 'gelf-rb' &&
hash['_test_tag1'] == 'TAG_1' &&
hash['_tag_2'] == 'TAG_2'
end

@logger.tagged('TAG_1', 'TAG_2') { @logger.info "Message" }
end
end

#logger.tagged(TAG_NAME: "TAG") { logger.info "Message" }
should "support tagged method with undefined log_tags" do
@logger.expects(:notify_with_level!).with do |level, hash|
level == GELF::INFO &&
hash['short_message'] == 'Message' &&
hash['facility'] == 'gelf-rb'
hash['facility'] == 'gelf-rb' &&
hash['_test_tag1'] == 'TAG_1' &&
hash['_test_tag2'] == 'TAG_2'
end

str = "TAG"
str.stubs(:blank?).returns(true)
@logger.tagged({test_tag1: 'TAG_1', test_tag2: 'TAG_2'}) { @logger.info "Message" }
end

should "support tagged method with defined log_tags" do
@logger.log_tags = [:test_tag1]
@logger.expects(:notify_with_level!).with do |level, hash|
level == GELF::INFO &&
hash['short_message'] == 'Message' &&
hash['facility'] == 'gelf-rb' &&
hash['_test_tag2'] == 'TAG_2'
end

@logger.tagged(str) { @logger.info "Message" }
@logger.tagged(test_tag2: 'TAG_2') { @logger.info "Message" }
end

should "set custom gelf message with tag name and tag content" do
# I want the first tag with name 'test_tag'
@logger.log_tags = [:test_tag]
should "support push_tags method with undefined log_tags" do
@logger.push_tags(test_tag: 'TAG')

@logger.expects(:notify_with_level!).with do |level, hash|
level == GELF::INFO &&
hash['short_message'] == 'Message' &&
hash['facility'] == 'gelf-rb' &&
hash['_test_tag'] == 'TAG' # TAG should be in the hash
hash['_test_tag'] == 'TAG'
end

str = "TAG"
str.stubs(:blank?).returns(false)
@logger.info('Message')
@logger.clear_tags!
end

should "support push_tags method with defined log_tags" do
@logger.log_tags = [:test_tag1]
@logger.push_tags(test_tag2: 'TAG_2')

@logger.expects(:notify_with_level!).with do |level, hash|
level == GELF::INFO &&
hash['short_message'] == 'Message' &&
hash['facility'] == 'gelf-rb' &&
hash['_test_tag1'] == '' &&
hash['_test_tag2'] == 'TAG_2'
end

@logger.tagged(str) { @logger.info "Message" }
@logger.info('Message')
@logger.clear_tags!
end

end
end

Expand Down