Add support for setting a logger

Adds support for setting `Stripe.logger` to a logger that's compatible
with `Logger` from Ruby's standard library. In set, the library will no
longer log to stdout, and instead emit straight to the logger and defer
decision on what log level to print to it.

Addresses a request in #566.
This commit is contained in:
Brandur 2017-08-11 11:16:29 -07:00
parent 20ec883e8b
commit cb111a8e74
3 changed files with 85 additions and 9 deletions

View File

@ -84,6 +84,7 @@ module Stripe
@uploads_base = 'https://uploads.stripe.com'
@log_level = nil
@logger = nil
@max_network_retries = 0
@max_network_retry_delay = 2
@ -151,6 +152,9 @@ module Stripe
# what it's doing. For example, it'll produce information about requests,
# responses, and errors that are received. Valid log levels are `debug` and
# `info`, with `debug` being a little more verbose in places.
#
# Use of this configuration is only useful when `.logger` is _not_ set. When
# it is, the decision what levels to print is entirely deferred to the logger.
def self.log_level
@log_level
end
@ -162,6 +166,21 @@ module Stripe
@log_level = val
end
# Sets a logger to which logging output will be sent. The logger should
# support the same interface as the `Logger` class that's part of Ruby's
# standard library (hint, anything in `Rails.logger` will likely be
# suitable).
#
# If `.logger` is set, the value of `.log_level` is ignored. The decision on
# what levels to print is entirely deferred to the logger.
def self.logger
@logger
end
def self.logger=(val)
@logger = val
end
def self.max_network_retries
@max_network_retries
end

View File

@ -90,16 +90,19 @@ module Stripe
end
def self.log_info(message, data = {})
if Stripe.log_level == Stripe::LEVEL_DEBUG ||Stripe.log_level == Stripe::LEVEL_INFO
if !Stripe.logger.nil? ||
Stripe.log_level == Stripe::LEVEL_DEBUG ||
Stripe.log_level == Stripe::LEVEL_INFO
log_internal(message, data, color: :cyan,
level: Stripe::LEVEL_INFO, out: $stdout)
level: Stripe::LEVEL_INFO, logger: Stripe.logger, out: $stdout)
end
end
def self.log_debug(message, data = {})
if Stripe.log_level == Stripe::LEVEL_DEBUG
if !Stripe.logger.nil? ||
Stripe.log_level == Stripe::LEVEL_DEBUG
log_internal(message, data, color: :blue,
level: Stripe::LEVEL_DEBUG, out: $stdout)
level: Stripe::LEVEL_DEBUG, logger: Stripe.logger, out: $stdout)
end
end
@ -340,16 +343,24 @@ module Stripe
# TODO: Make these named required arguments when we drop support for Ruby
# 2.0.
def self.log_internal(message, data = {}, color: nil, level: nil, out: nil)
def self.log_internal(message, data = {}, color: nil, level: nil, logger: nil, out: nil)
data_str = data.select { |k,v| !v.nil? }.
map { |(k,v)|
"%s=%s" % [
colorize(k, color, out.isatty),
colorize(k, color, !out.nil? && out.isatty),
wrap_logfmt_value(v)
]
}.join(" ")
if out.isatty
if !logger.nil?
str = "message=%s %s" % [wrap_logfmt_value(message), data_str]
case level
when Stripe::LEVEL_DEBUG
logger.debug(str)
else # Stripe::LEVEL_INFO (there should be no other values)
logger.info(str)
end
elsif out.isatty
out.puts "%s %s %s" %
[colorize(level[0, 4].upcase, color, out.isatty), message, data_str]
else

View File

@ -1,3 +1,4 @@
require "logger"
require File.expand_path('../../test_helper', __FILE__)
module Stripe
@ -216,6 +217,35 @@ module Stripe
end
end
context ".log_* with a logger" do
setup do
@out = StringIO.new
logger = ::Logger.new(@out)
# Set a really simple formatter to make matching output as easy as
# possible.
logger.formatter = proc { |_severity, _datetime, _progname, message|
message
}
Stripe.logger = logger
end
context ".log_debug" do
should "log to the logger" do
Util.log_debug("foo")
assert_equal "message=foo ", @out.string
end
end
context ".log_info" do
should "log to the logger" do
Util.log_info("foo")
assert_equal "message=foo ", @out.string
end
end
end
context ".normalize_headers" do
should "normalize the format of a header key" do
assert_equal({ "Request-Id" => nil },
@ -267,7 +297,7 @@ module Stripe
end
Util.send(:log_internal, "message", { foo: "bar" },
color: :green, level: Stripe::LEVEL_DEBUG, out: out)
color: :green, level: Stripe::LEVEL_DEBUG, logger: nil, out: out)
assert_equal "\e[0;32;49mDEBU\e[0m message \e[0;32;49mfoo\e[0m=bar\n",
out.string
end
@ -275,10 +305,26 @@ module Stripe
should "log in a data friendly way" do
out = StringIO.new
Util.send(:log_internal, "message", { foo: "bar" },
color: :green, level: Stripe::LEVEL_DEBUG, out: out)
color: :green, level: Stripe::LEVEL_DEBUG, logger: nil, out: out)
assert_equal "message=message level=debug foo=bar\n",
out.string
end
should "log to a logger if set" do
out = StringIO.new
logger = ::Logger.new(out)
# Set a really simple formatter to make matching output as easy as
# possible.
logger.formatter = proc { |_severity, _datetime, _progname, message|
message
}
Util.send(:log_internal, "message", { foo: "bar" },
color: :green, level: Stripe::LEVEL_DEBUG, logger: logger, out: nil)
assert_equal "message=message foo=bar",
out.string
end
end
context ".wrap_logfmt_value" do