diff --git a/Gemfile.lock b/Gemfile.lock index 6b18067..75ad8fe 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -69,6 +69,3 @@ DEPENDENCIES rack (< 2.0) shoulda (~> 2.11.3) test-unit (~> 3.2.0) - -BUNDLED WITH - 1.14.6 diff --git a/lib/gelf/logger.rb b/lib/gelf/logger.rb index 6377cd6..4405d3c 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) @@ -28,9 +28,14 @@ def add(level, message = nil, progname = nil, &block) message_hash.merge!(self.class.extract_hash_from_exception(message)) end - if message_hash.key?('short_message') && !message_hash['short_message'].empty? - notify_with_level(level, message_hash) + return if !message_hash.key?('short_message') || message_hash['short_message'].empty? + + # Include tags in message hash + Array(log_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 # Redefines methods in +Notifier+. @@ -51,12 +56,37 @@ def add(level, message = nil, progname = nil, &block) 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 + 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 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.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 class Logger < Notifier include LoggerCompatibility end diff --git a/test/test_logger.rb b/test/test_logger.rb index 7498199..b78672c 100644 --- a/test/test_logger.rb +++ b/test/test_logger.rb @@ -237,6 +237,42 @@ class TestLogger < Test::Unit::TestCase @logger.formatter end + # 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 + @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.log_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 + end + context "close" do should "close socket" do @sender.expects(:close).once