Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
BufferedJSONLogger with some helpers for Rails 2.x. More to follow..
- Loading branch information
Showing
9 changed files
with
258 additions
and
25 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Original file line | Diff line number | Diff line change |
---|---|---|---|
@@ -1,4 +1,5 @@ | |||
.bundle | .bundle | ||
.rvmrc | .rvmrc | ||
Gemfile.lock | Gemfile.lock | ||
*.gem | *.gem | ||
.DS_Store |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Original file line | Diff line number | Diff line change |
---|---|---|---|
@@ -1,6 +1,3 @@ | |||
source :rubygems | source :rubygems | ||
|
|
||
gem "mocha" | gemspec | ||
gem "activesupport" | |||
gem "redgreen" | |||
gem "bunny" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Original file line | Diff line number | Diff line change |
---|---|---|---|
@@ -0,0 +1,71 @@ | |||
require 'json' | |||
|
|||
|
|||
# in der rails app | |||
module AMQPLogging | |||
module SimpleFormatter | |||
def self.call(severity, time, progname, msg) | |||
msg | |||
end | |||
end | |||
|
|||
class BufferedJSONLogger < Logger | |||
attr_reader :buffer | |||
attr_reader :fields | |||
|
|||
def initialize(logdev, *args) | |||
super | |||
@default_formatter = SimpleFormatter | |||
@default_fields = { | |||
:host => Socket.gethostname.split('.').first, | |||
:process => Process.pid | |||
} | |||
@fields = {} | |||
@buffer = [] | |||
end | |||
|
|||
def add_field(name, value) | |||
@fields[name] = value | |||
end | |||
|
|||
def add_fields(extra_fields) | |||
@fields.merge!(extra_fields) | |||
end | |||
|
|||
def add(severity, message = nil, progname = nil, &block) | |||
severity ||= UNKNOWN | |||
if severity < @level | |||
return true | |||
end | |||
progname ||= @progname | |||
if message.nil? | |||
if block_given? | |||
message = yield | |||
else | |||
message = progname | |||
progname = @progname | |||
end | |||
end | |||
t = Time.now | |||
formatted_message = format_message(format_severity(severity), t, progname, message).strip | |||
@buffer << [severity, t.strftime("%d.%m.%YT%H:%M:%S.#{t.usec}"), formatted_message] | |||
true | |||
end | |||
|
|||
def flush | |||
@logdev.write(format_json) | |||
@buffer = [] | |||
@fields = {} | |||
true | |||
end | |||
|
|||
private | |||
def format_json | |||
@default_fields.merge({ | |||
:lines => @buffer.reverse, | |||
:severity => @buffer.map {|l| l[0]}.max | |||
}).merge(@fields).to_json + "\n" | |||
end | |||
|
|||
end | |||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Original file line | Diff line number | Diff line change |
---|---|---|---|
@@ -0,0 +1,15 @@ | |||
require 'amqp_logging' | |||
require 'amqp_logging/buffered_json_logger/rails/after_dispatch_callback_handler' | |||
|
|||
|
|||
ActionController::Dispatcher.after_dispatch do |dispatcher| | |||
AMQPLogging::Rails::AfterDispatchCallbackHandler.run(dispatcher) | |||
end | |||
|
|||
class ActionController::Base | |||
def log_processing_for_request_id_with_json_logger_preparation | |||
logger.add_field :page, "#{self.class.name}\##{action_name}" | |||
log_processing_for_request_id_without_json_logger_preparation | |||
end | |||
alias_method_chain :log_processing_for_request_id, :json_logger_preparation | |||
end |
27 changes: 27 additions & 0 deletions
27
lib/amqp_logging/buffered_json_logger/rails/after_dispatch_callback_handler.rb
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Original file line | Diff line number | Diff line change |
---|---|---|---|
@@ -0,0 +1,27 @@ | |||
module AMQPLogging | |||
module Rails | |||
class AfterDispatchCallbackHandler | |||
def self.run(dispatcher) | |||
env = dispatcher.instance_variable_get(:@env) | |||
response = env["action_controller.rescue.response"] | |||
request = env["action_controller.rescue.request"] | |||
request_headers = request.headers.dup | |||
request_headers.each do |k, v| | |||
case v | |||
when String, Fixnum, Numeric | |||
else | |||
request_headers[k] = "#<#{v.class.name}>" | |||
end | |||
end | |||
|
|||
ActionController::Base.logger.add_fields({ | |||
:env => RAILS_ENV, | |||
:response_code => response.status, | |||
:request_params => request.request_parameters, | |||
:request_headers => request_headers, | |||
:response_headers => response.headers | |||
}) | |||
end | |||
end | |||
end | |||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Original file line | Diff line number | Diff line change |
---|---|---|---|
@@ -0,0 +1,73 @@ | |||
require File.dirname(__FILE__) + '/test_helper.rb' | |||
|
|||
module AMQPLogging | |||
class TheBufferedJSONLoggerTest < Test::Unit::TestCase | |||
def setup | |||
@output = StringIO.new | |||
@logger = BufferedJSONLogger.new(@output) | |||
end | |||
|
|||
test "should have all the convenience log methods of a regular logger" do | |||
::Logger::Severity.constants.map(&:downcase).each do |logmethod| | |||
assert_nothing_raised do | |||
@logger.send(logmethod, "foo") | |||
end | |||
end | |||
end | |||
|
|||
test "should not write the logs immediately" do | |||
assert_equal "", @output.string | |||
@logger.debug "foo" | |||
assert_equal "", @output.string | |||
end | |||
|
|||
test "should write to the log when flush is called eventually" do | |||
assert_equal "", @output.string | |||
@logger.debug "foo" | |||
@logger.flush | |||
assert_match /foo/, @output.string | |||
end | |||
|
|||
test "should empty the buffer when flush is called" do | |||
@logger.debug "foo" | |||
@logger.flush | |||
assert_equal [], @logger.buffer | |||
end | |||
end | |||
|
|||
class BufferedLoggerJSONOutputTest < Test::Unit::TestCase | |||
def setup | |||
@output = StringIO.new | |||
@logger = BufferedJSONLogger.new(@output) | |||
@logger.debug "foo" | |||
@logger.warn "bar" | |||
@logger.info "baz" | |||
@logger.flush | |||
@json = JSON.parse(@output.string) | |||
end | |||
|
|||
test "should have the loglines in a array called lines" do | |||
assert @json["lines"].instance_of?(Array) | |||
assert_equal 3, @json["lines"].size | |||
end | |||
|
|||
test "should have each logline with severity, a timestamp and the message" do | |||
severity, timestamp, message = @json["lines"][2] | |||
assert_equal Logger::DEBUG, severity | |||
assert_nothing_raised { Time.parse(timestamp) } | |||
assert_equal "foo", message | |||
end | |||
|
|||
test "should have a field with the highest severity" do | |||
assert_equal Logger::WARN, @json["severity"] | |||
end | |||
|
|||
test "should have a field with the process id" do | |||
assert_equal Process.pid, @json["process"] | |||
end | |||
|
|||
test "should have a field with the hostname" do | |||
assert_equal Socket.gethostname.split('.').first, @json["host"] | |||
end | |||
end | |||
end |