diff --git a/config/unicorn.conf.rb b/config/unicorn.conf.rb index f90911a1bb4..9704fd38609 100644 --- a/config/unicorn.conf.rb +++ b/config/unicorn.conf.rb @@ -1,5 +1,12 @@ # See http://unicorn.bogomips.org/Unicorn/Configurator.html +if ENV["UNICORN_JSON_LOG_FORMAT"] + unicorn_logger = Logger.new($stderr) + require_relative '../lib/unicorn/unicorn_json_log_formatter' + unicorn_logger.formatter = UnicornJSONLogFormatter.new + logger unicorn_logger +end + # enable out of band gc out of the box, it is low risk and improves perf a lot ENV['UNICORN_ENABLE_OOBGC'] ||= "1" diff --git a/lib/unicorn/unicorn_json_log_formatter.rb b/lib/unicorn/unicorn_json_log_formatter.rb new file mode 100644 index 00000000000..4410c467bdc --- /dev/null +++ b/lib/unicorn/unicorn_json_log_formatter.rb @@ -0,0 +1,21 @@ +require 'json' + +class UnicornJSONLogFormatter < Logger::Formatter + def call(severity, datetime, progname, message) + default = { + severity: severity, + datetime: datetime, + progname: progname, + pid: $$, + } + + default[:message] = + if message.is_a?(Exception) + "#{message.message}: #{message.backtrace.join("\n")}" + else + message + end + + "#{default.to_json}\n" + end +end diff --git a/spec/components/unicorn/unicorn_json_log_formatter_spec.rb b/spec/components/unicorn/unicorn_json_log_formatter_spec.rb new file mode 100644 index 00000000000..78505770c00 --- /dev/null +++ b/spec/components/unicorn/unicorn_json_log_formatter_spec.rb @@ -0,0 +1,31 @@ +require 'rails_helper' +require 'unicorn/unicorn_json_log_formatter' + +RSpec.describe UnicornJSONLogFormatter do + context 'when message is an exception' do + it 'should include the backtrace' do + freeze_time do + begin + raise 'boom' + rescue => e + error = e + + output = described_class.new.call( + 'INFO', + Time.zone.now, + '', + e + ) + end + + output = JSON.parse(output) + + expect(output["severity"]).to eq('INFO') + expect(output["datetime"]).to be_present + expect(output["progname"]).to eq('') + expect(output["pid"]).to be_present + expect(output["message"]).to match(/boom:.*/) + end + end + end +end