1
0
mirror of https://github.com/meineerde/rackstash.git synced 2026-01-31 17:27:13 +00:00

Set rack.errors in the Rack::Middlware

This ensures that other middlewares whi want to log to the default
rack.errors stream will log to a sensible location instead of the usual
default of raw STDOUT or STDERR.
This commit is contained in:
Holger Just 2017-12-05 18:55:04 +01:00
parent 3b8e76329c
commit 26597680af
4 changed files with 137 additions and 0 deletions

View File

@ -0,0 +1,66 @@
# frozen_string_literal: true
# Copyright 2016 Holger Just
#
# This software may be modified and distributed under the terms
# of the MIT license. See the LICENSE.txt file for details.
module Rackstash
module Rack
# Provide an error stream to Rack applications which logs to a
# {Rackstash::Logger} instance.
#
# According to the [Rack SPEC](http://www.rubydoc.info/github/rack/rack/file/SPEC#The_Error_Stream),
# the error stream in `env['rack.errors']` must coform to the following
# interface:
#
# > The error stream must respond to `puts`, `write` and `flush`.
# >
# > * `puts` must be called with a single argument that responds to `to_s`.
# > * `write` must be called with a single argument that is a `String`.
# > * `flush` must be called without arguments and must be called in order
# > to make the error appear for sure.
# > * `close` must never be called on the error stream.
class Errors
# @return [Rackstash::Logger]
attr_reader :logger
# @param logger [Rackstash::Logger] a {Logger} instance to write error
# logs to
def initialize(logger)
@logger = logger
end
# Log a formatted error message to the current buffer of the `logger`. We
# will format the given message and log it with an `UNKNOWN` severity to
# the current buffer. Usually, the logger's formatter adds a trailing
# newline to the message.
#
# @param msg [#to_s] a message to write to the error stream
# @return [String] the given `msg` as a String
def puts(msg)
msg = msg.to_s
@logger.unknown(msg)
msg
end
# Log a raw and unformatted error message to the current buffer of the
# `logger`. It will be logged as an unformatted {Message} without any
# aded newline characters.
#
# @param msg [String] a raw message to write to the error stream
# @return [String] the given `msg`
def write(msg)
@logger << msg
msg
end
# This method does nothing. It is only provided to satisfy the
# requirements of the error stream interface. The {Logger} (resp. its
# adapters) are responsible to flush their buffers on their own as
# suitable or required.
def flush
# no-op
end
end
end
end

View File

@ -7,6 +7,7 @@
require 'rack'
require 'rackstash/helpers/time'
require 'rackstash/rack/errors'
module Rackstash
module Rack
@ -199,6 +200,7 @@ module Rackstash
began_at = clock_time
env['rackstash.logger'.freeze] = @logger
env['rack.logger'.freeze] = @logger
env['rack.errors'.freeze] = Rackstash::Rack::Errors.new(@logger)
@logger.push_buffer(buffering: @buffering, allow_silent: true)
begin

View File

@ -0,0 +1,56 @@
# frozen_string_literal: true
#
# Copyright 2017 Holger Just
#
# This software may be modified and distributed under the terms
# of the MIT license. See the LICENSE.txt file for details.
require 'spec_helper'
require 'rackstash/rack/errors'
describe Rackstash::Rack::Errors do
let(:logger) { instance_double(Rackstash::Logger) }
let(:errors) { described_class.new(logger) }
describe '#initialize' do
it 'takes a logger' do
errors = described_class.new(logger)
expect(errors.logger).to equal logger
end
end
describe '#puts' do
it 'logs a formatted message' do
expect(logger).to receive(:unknown).with('an error')
errors.puts('an error')
end
it 'returns the stringified message' do
allow(logger).to receive(:unknown)
expect(errors.puts('error')).to eql 'error'
expect(errors.puts(123)).to eql '123'
end
end
describe '#write' do
it 'logs an unformatted message' do
expect(logger).to receive(:<<).with('an error')
errors.write('an error')
end
it 'returns the raw message' do
allow(logger).to receive(:<<)
expect(errors.write('error')).to eql 'error'
expect(errors.write(123)).to eql 123
end
end
describe '#flush' do
it 'does nothing' do
errors.flush
end
end
end

View File

@ -92,6 +92,19 @@ describe Rackstash::Rack::Middleware do
expect(called).to be true
end
it 'sets rack.errors environment variable' do
called = false
app = lambda do |env|
called = true
expect(env['rack.errors']).to be_instance_of Rackstash::Rack::Errors
expect(env['rack.errors'].logger).to equal logger
[200, { 'Content-Type' => 'text/plain' }, ['Hello, World!']]
end
::Rack::MockRequest.new(described_class.new(app, logger)).get('/')
expect(called).to be true
end
it 'logs basic request data' do
get('/demo')