DEV: Consolidate Unicorn error backtraces when logstash is enabled.

DEV: Consolidate Unicorn error backtraces when logstash is enabled.

diff --git a/config/unicorn.conf.rb b/config/unicorn.conf.rb
index 3a6cf23..7eb335f 100644
--- a/config/unicorn.conf.rb
+++ b/config/unicorn.conf.rb
@@ -4,6 +4,7 @@
 
 if (ENV["LOGSTASH_UNICORN_URI"] || "").length > 0
   require_relative '../lib/discourse_logstash_logger'
+  require_relative '../lib/unicorn_logstash_patch'
   logger DiscourseLogstashLogger.logger(uri: ENV['LOGSTASH_UNICORN_URI'], type: :unicorn)
 end
 
diff --git a/lib/unicorn_logstash_patch.rb b/lib/unicorn_logstash_patch.rb
new file mode 100644
index 0000000..e6f931a
--- /dev/null
+++ b/lib/unicorn_logstash_patch.rb
@@ -0,0 +1,12 @@
+# See https://github.com/defunkt/unicorn/commit/5f478f5a9a58f72c0a844258b8ee614bf24ea9f7
+# Unicorn originally logs backtrace line by line with `exc.backtrace.each { |line| logger.error(line) }`.
+# However, that means we get a separate logstash message for each backtrace which isn't what we want. The
+# monkey patch here overrides Unicorn's logging of error so that we log the error and backtrace in a
+# single message.
+module Unicorn
+  def self.log_error(logger, prefix, exc)
+    message = exc.message
+    message = message.dump if /[[:cntrl:]]/ =~ message
+    logger.error "#{prefix}: #{message} (#{exc.class})\n#{exc.backtrace.join("\n")}"
+  end
+end

GitHub sha: bb8f1ce8