From 3c50c8a1b8864c66b98875e8a5f4814ee2a691c8 Mon Sep 17 00:00:00 2001 From: Mark Glenn Date: Thu, 7 May 2015 14:49:15 -0500 Subject: [PATCH 1/2] Add tagged logging support Implement tagged logging similar to ActiveSupport::TaggedLogging. --- lib/gelf/logger.rb | 27 +++++++++++++++++++++++++++ test/test_logger.rb | 32 ++++++++++++++++++++++++++++++++ 2 files changed, 59 insertions(+) diff --git a/lib/gelf/logger.rb b/lib/gelf/logger.rb index 7025dc2..be62afa 100644 --- a/lib/gelf/logger.rb +++ b/lib/gelf/logger.rb @@ -32,6 +32,11 @@ def add(level, message = nil, progname = nil, &block) message_hash.merge!(self.class.extract_hash_from_exception(message)) end + # Include tags in message hash + Array(default_options['tags']).each_with_index do |tag_name, index| + message_hash.merge!("_#{tag_name}" => current_tags[index]) if current_tags[index] + end + notify_with_level(level, message_hash) end @@ -51,12 +56,34 @@ def #{const.downcase}? # def debug? def <<(message) notify_with_level(GELF::UNKNOWN, 'short_message' => message) end + + def tagged(*tags) + new_tags = push_tags(*tags) + yield self + ensure + current_tags.pop(new_tags.size) + end + + def push_tags(*tags) + tags.flatten.reject{ |t| t.respond_to?(:empty?) ? !!t.empty? : !t }.tap do |new_tags| + current_tags.concat new_tags + end + end + + def current_tags + Thread.current[:gelf_tagged_logging_tags] ||= [] + end end # Graylog2 notifier, compatible with Ruby Logger. # You can use it with Rails like this: # config.logger = GELF::Logger.new("localhost", 12201, "WAN", { :facility => "appname" }) # config.colorize_logging = false + # + # Tagged logging (with tags from rack middleware) (order of tags is important) + # Adds custom gelf messages: { '_uuid_name' => , '_remote_ip_name' => } + # config.log_tags = [:uuid, :remote_ip] + # config.logger = GELF::Logger.new("localhost", 12201, "LAN", { :facility => "appname", :tags => config.log_tags }) class Logger < Notifier include LoggerCompatibility end diff --git a/test/test_logger.rb b/test/test_logger.rb index b4b793e..f0fc449 100644 --- a/test/test_logger.rb +++ b/test/test_logger.rb @@ -210,6 +210,38 @@ class TestLogger < Test::Unit::TestCase @logger.formatter end + context "#tagged" do + # logger.tagged("TAG") { logger.info "Message" } + should "support tagged method" do + @logger.expects(:notify_with_level!).with do |level, hash| + level == GELF::INFO && + hash['short_message'] == 'Message' && + hash['facility'] == 'gelf-rb' + end + + str = "TAG" + str.stubs(:blank?).returns(true) + + @logger.tagged(str) { @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.default_options.merge!('tags' => ['test_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 + end + + str = "TAG" + str.stubs(:blank?).returns(false) + + @logger.tagged(str) { @logger.info "Message" } + end + end context "close" do should "close socket" do From 43f3d4e8ebd4ae12e4a8f3b40923187a8565365d Mon Sep 17 00:00:00 2001 From: Mark Glenn Date: Thu, 7 May 2015 15:43:57 -0500 Subject: [PATCH 2/2] Use log_tags attribute on logger Don't use the default_options to pass the tags into the logger. This causes the tags field to be sent over to graylog as an array. Instead pass the tag names into an attribute called log_tags that matches with the Rails standard of config.log_tags. --- lib/gelf/logger.rb | 7 ++++--- test/test_logger.rb | 2 +- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/lib/gelf/logger.rb b/lib/gelf/logger.rb index be62afa..02e8801 100644 --- a/lib/gelf/logger.rb +++ b/lib/gelf/logger.rb @@ -2,7 +2,7 @@ module GELF # Methods for compatibility with Ruby Logger. module LoggerCompatibility - attr_accessor :formatter + attr_accessor :formatter, :log_tags # Use it like Logger#add... or better not to use at all. def add(level, message = nil, progname = nil, &block) @@ -33,7 +33,7 @@ def add(level, message = nil, progname = nil, &block) end # Include tags in message hash - Array(default_options['tags']).each_with_index do |tag_name, index| + Array(log_tags).each_with_index do |tag_name, index| message_hash.merge!("_#{tag_name}" => current_tags[index]) if current_tags[index] end @@ -82,8 +82,9 @@ def current_tags # # Tagged logging (with tags from rack middleware) (order of tags is important) # Adds custom gelf messages: { '_uuid_name' => , '_remote_ip_name' => } + # config.logger = GELF::Logger.new("localhost", 12201, "LAN", { :facility => "appname" }) # config.log_tags = [:uuid, :remote_ip] - # config.logger = GELF::Logger.new("localhost", 12201, "LAN", { :facility => "appname", :tags => config.log_tags }) + # config.logger.log_tags = [:uuid_name, :remote_ip_name] # Same order as config.log_tags class Logger < Notifier include LoggerCompatibility end diff --git a/test/test_logger.rb b/test/test_logger.rb index f0fc449..cd703b1 100644 --- a/test/test_logger.rb +++ b/test/test_logger.rb @@ -227,7 +227,7 @@ class TestLogger < Test::Unit::TestCase should "set custom gelf message with tag name and tag content" do # I want the first tag with name 'test_tag' - @logger.default_options.merge!('tags' => ['test_tag']) + @logger.log_tags = [:test_tag] @logger.expects(:notify_with_level!).with do |level, hash| level == GELF::INFO &&