From 39ab0d1db01e69e8abf69bbd63fc6d09fa2107dc Mon Sep 17 00:00:00 2001 From: Luke Horvat Date: Thu, 17 Mar 2016 21:06:09 +1100 Subject: [PATCH 1/6] Create logger class --- lib/rollbar/loggers.rb | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) create mode 100644 lib/rollbar/loggers.rb diff --git a/lib/rollbar/loggers.rb b/lib/rollbar/loggers.rb new file mode 100644 index 00000000..6fad1001 --- /dev/null +++ b/lib/rollbar/loggers.rb @@ -0,0 +1,17 @@ +require "logger" + +module Rollbar + class Logger < Logger + def initialize + @level = ERROR + end + + def add(severity, message = nil, progname = nil, &block) + return true if severity < @level + message ||= block_given? ? yield : progname + return true if message.blank? + rollbar_level = [:debug, :info, :warning, :error, :critical, :error][severity] || :error + Rollbar.log(rollbar_level, message) + end + end +end From 3edc7ca3f80e18c0e945cbe6ca4635448adbb77f Mon Sep 17 00:00:00 2001 From: Jon de Andres Date: Tue, 5 Apr 2016 18:18:12 +0200 Subject: [PATCH 2/6] Rewrite Rollbar::Logger in lib/rollbar/logger.rb Closes #404 Closes #359 --- lib/rollbar/logger.rb | 69 ++++++++++++++++++++++ lib/rollbar/loggers.rb | 17 ------ spec/rollbar/logger_spec.rb | 114 ++++++++++++++++++++++++++++++++++++ 3 files changed, 183 insertions(+), 17 deletions(-) create mode 100644 lib/rollbar/logger.rb delete mode 100644 lib/rollbar/loggers.rb create mode 100644 spec/rollbar/logger_spec.rb diff --git a/lib/rollbar/logger.rb b/lib/rollbar/logger.rb new file mode 100644 index 00000000..b34ad741 --- /dev/null +++ b/lib/rollbar/logger.rb @@ -0,0 +1,69 @@ +require "logger" +require 'rollbar' + +module Rollbar + class Logger < Logger + class Error < RuntimeError; end + class DatetimeFormatNotSupported < Error; end + class FormatterNotSupported < Error; end + + def initialize + @level = ERROR + end + + def add(severity, message = nil, progname = nil, &block) + return true if severity < @level + + message ||= block_given? ? yield : progname + + return true if message.blank? + + rollbar.log(rollbar_level(severity), message) + end + + def <<(message) + error(message) + end + + def formatter=(_) + fail(FormatterNotSupported) + end + + def formatter + fail(FormatterNotSupported) + end + + def datetime_format=(_) + fail(DatetimeFormatNotSupported) + end + + def datetime_format + fail(DatetimeFormatNotSupported) + end + + # Returns a Rollbar::Notifier instance with the current global scope and + # with a logger writing to /dev/null so we don't have a infinite loop + # when Rollbar.configuration.logger is Rails.logger. + def rollbar + notifier = Rollbar.scope + notifier.configuration.logger = ::Logger.new('/dev/null') + + notifier + end + + private + + # Find correct Rollbar level to use using the indexes in Logger::Severity + # DEBUG = 0 + # INFO = 1 + # WARN = 2 + # ERROR = 3 + # FATAL = 4 + # UNKNOWN = 5 + # + # If not found we'll use 'error' as the used level + def rollbar_level(severity) + [:debug, :info, :warning, :error, :critical, :error][severity] || :error + end + end +end diff --git a/lib/rollbar/loggers.rb b/lib/rollbar/loggers.rb deleted file mode 100644 index 6fad1001..00000000 --- a/lib/rollbar/loggers.rb +++ /dev/null @@ -1,17 +0,0 @@ -require "logger" - -module Rollbar - class Logger < Logger - def initialize - @level = ERROR - end - - def add(severity, message = nil, progname = nil, &block) - return true if severity < @level - message ||= block_given? ? yield : progname - return true if message.blank? - rollbar_level = [:debug, :info, :warning, :error, :critical, :error][severity] || :error - Rollbar.log(rollbar_level, message) - end - end -end diff --git a/spec/rollbar/logger_spec.rb b/spec/rollbar/logger_spec.rb new file mode 100644 index 00000000..2f7ac42d --- /dev/null +++ b/spec/rollbar/logger_spec.rb @@ -0,0 +1,114 @@ +require 'spec_helper' +require 'rollbar/logger' + +describe Rollbar::Logger do + describe '#add' do + context 'with severity under level' do + it 'returns true' do + result = subject.add(Logger::DEBUG, 'foo') + + expect(result).to be_truthy + end + end + + context 'with blank message' do + it 'returns true' do + result = subject.add(subject.level) + + expect(result).to be_truthy + end + end + + context 'with ERROR severity' do + let(:message) { 'foo' } + + it 'calls Rollbar to send the message' do + expect_any_instance_of(Rollbar::Notifier).to receive(:log).with(:error, message) + + subject.add(Logger::ERROR, message) + end + end + + context 'with FATAL severity' do + let(:message) { 'foo' } + + it 'calls Rollbar to send the message with critical level' do + expect_any_instance_of(Rollbar::Notifier).to receive(:log).with(:critical, message) + + subject.add(Logger::FATAL, message) + end + end + + context 'with UNKNOWN severity' do + let(:message) { 'foo' } + + it 'calls Rollbar to send the message with error level' do + expect_any_instance_of(Rollbar::Notifier).to receive(:log).with(:error, message) + + subject.add(Logger::UNKNOWN, message) + end + end + + context 'with out of range severity' do + let(:message) { 'foo' } + + it 'calls Rollbar to send the message with error level' do + expect_any_instance_of(Rollbar::Notifier).to receive(:log).with(:error, message) + + subject.add(10, message) + end + end + end + + describe '#<<' do + let(:message) { 'foo' } + + it 'calls #error' do + expect(subject).to receive(:error).with(message) + + subject << message + end + end + + describe '#formatter=' do + it 'fails with FormatterNotSupported' do + expect do + subject.formatter = double + end.to raise_error(Rollbar::Logger::FormatterNotSupported) + end + end + + describe '#formatter' do + it 'fails with FormatterNotSupported' do + expect do + subject.formatter + end.to raise_error(Rollbar::Logger::FormatterNotSupported) + end + end + + describe '#datetime_format=' do + it 'fails with DatetimeFormatNotSupported' do + expect do + subject.datetime_format = double + end.to raise_error(Rollbar::Logger::DatetimeFormatNotSupported) + end + end + + describe '#datetime_format' do + it 'fails with DatetimeFormatNotSupported' do + expect do + subject.datetime_format + end.to raise_error(Rollbar::Logger::DatetimeFormatNotSupported) + end + end + + describe '#rollbar' do + it 'returns a Rollbar notifier with a logger pointing to /dev/null' do + notifier = subject.rollbar + logger = notifier.configuration.logger + logdev = logger.instance_eval { @logdev } + + expect(logdev.filename).to be_eql('/dev/null') + end + end +end From af5439e38f438c559f3864de9ff22dbb6e27a955 Mon Sep 17 00:00:00 2001 From: Jon de Andres Date: Tue, 5 Apr 2016 18:32:01 +0200 Subject: [PATCH 3/6] Add documentation for Rollbar::Logger --- README.md | 21 ++++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 741d23bd..1a62959c 100644 --- a/README.md +++ b/README.md @@ -533,7 +533,7 @@ Rollbar.silenced { } ``` -# Sending backtrace without rescued exceptions +## Sending backtrace without rescued exceptions If you use the gem in this way: @@ -698,6 +698,25 @@ config.failover_handlers = [Rollbar::Delay::GirlFriday, Rollbar::Delay::Thread] With the configuration above Resque will be your primary asynchronous handler but if it fails queueing the job Rollbar will use GirlFriday at first, and just a thread in case that GirlFriday fails too. +## Logger interface + +The gem provides a class `Rollbar::Logger` that inherits from `Logger` so you can use Rollbar to log your application messages. The basic usage is: + +```ruby +require 'rollbar/logger' + +logger = Rollbar::Logger.new +logger.info('Purchase failed!') +``` + +If you are using Rails you can extend your `Rails.logger` so the log messages are sent to both outputs. You can use this snippet in one initializer: + +```ruby +require 'rollbar/logger' + +Rails.logger.extend(ActiveSupport::Logger.broadcast(Rollbar::Logger.new)) +``` + ## Using with rollbar-agent For even more asynchrony, you can configure the gem to write to a file instead of sending the payload to Rollbar servers directly. [rollbar-agent](https://github.com/rollbar/rollbar-agent) can then be hooked up to this file to actually send the payload across. To enable, add the following in ```config/initializers/rollbar.rb```: From f80cc5870ff4c6460e0a6f2280d586843ea4622b Mon Sep 17 00:00:00 2001 From: Jon de Andres Date: Tue, 5 Apr 2016 18:54:45 +0200 Subject: [PATCH 4/6] Add fixes to pass code climate --- lib/rollbar/logger.rb | 24 ++++++++++++++++++------ 1 file changed, 18 insertions(+), 6 deletions(-) diff --git a/lib/rollbar/logger.rb b/lib/rollbar/logger.rb index b34ad741..7958b8a8 100644 --- a/lib/rollbar/logger.rb +++ b/lib/rollbar/logger.rb @@ -1,7 +1,19 @@ -require "logger" +require 'logger' require 'rollbar' module Rollbar + # This class provides logger interface that can be used to replace + # the application logger and send all the log messages to Rollbar + # + # Usage: + # require 'rollbar/logger' + # logger = Rollbar::Logger.new + # logger.error('Error processing purchase') + # + # If using Rails, you can extend the Rails logger so messages are logged + # normally and also to Rollbar: + # + # Rails.logger.extend(ActiveSupport::Logger.broadcast(Rollbar::Logger.new)) class Logger < Logger class Error < RuntimeError; end class DatetimeFormatNotSupported < Error; end @@ -11,7 +23,7 @@ def initialize @level = ERROR end - def add(severity, message = nil, progname = nil, &block) + def add(severity, message = nil, progname = nil) return true if severity < @level message ||= block_given? ? yield : progname @@ -26,19 +38,19 @@ def <<(message) end def formatter=(_) - fail(FormatterNotSupported) + raise(FormatterNotSupported) end def formatter - fail(FormatterNotSupported) + raise(FormatterNotSupported) end def datetime_format=(_) - fail(DatetimeFormatNotSupported) + raise(DatetimeFormatNotSupported) end def datetime_format - fail(DatetimeFormatNotSupported) + raise(DatetimeFormatNotSupported) end # Returns a Rollbar::Notifier instance with the current global scope and From 7d51eeb2b87a5c4d11a885b63b8e28480dc9302b Mon Sep 17 00:00:00 2001 From: Jon de Andres Date: Wed, 6 Apr 2016 12:56:00 +0200 Subject: [PATCH 5/6] Avoid conflict between Rollbar::Logger and Logger constants --- lib/rollbar/configuration.rb | 2 +- lib/rollbar/logger.rb | 2 +- lib/rollbar/rake_tasks.rb | 1 + 3 files changed, 3 insertions(+), 2 deletions(-) diff --git a/lib/rollbar/configuration.rb b/lib/rollbar/configuration.rb index e775f643..93f8ed3d 100644 --- a/lib/rollbar/configuration.rb +++ b/lib/rollbar/configuration.rb @@ -63,7 +63,7 @@ def initialize @before_process = [] @code_version = nil @custom_data_method = nil - @default_logger = lambda { Logger.new(STDERR) } + @default_logger = lambda { ::Logger.new(STDERR) } @delayed_job_enabled = true @disable_monkey_patch = false @disable_core_monkey_patch = false diff --git a/lib/rollbar/logger.rb b/lib/rollbar/logger.rb index 7958b8a8..a11fbc7b 100644 --- a/lib/rollbar/logger.rb +++ b/lib/rollbar/logger.rb @@ -14,7 +14,7 @@ module Rollbar # normally and also to Rollbar: # # Rails.logger.extend(ActiveSupport::Logger.broadcast(Rollbar::Logger.new)) - class Logger < Logger + class Logger < ::Logger class Error < RuntimeError; end class DatetimeFormatNotSupported < Error; end class FormatterNotSupported < Error; end diff --git a/lib/rollbar/rake_tasks.rb b/lib/rollbar/rake_tasks.rb index c3d92244..58b00316 100644 --- a/lib/rollbar/rake_tasks.rb +++ b/lib/rollbar/rake_tasks.rb @@ -1,4 +1,5 @@ require 'rollbar' +require 'logger' namespace :rollbar do desc "Verify your gem installation by sending a test exception to Rollbar" From 2540019670532d0b38961e240cc9f4a2513a77dc Mon Sep 17 00:00:00 2001 From: Jon de Andres Date: Wed, 6 Apr 2016 13:21:01 +0200 Subject: [PATCH 6/6] Use mime-types < 3.0 for RUBY < 2.0 --- gemfiles/rails30.gemfile | 6 +++++- gemfiles/rails31.gemfile | 6 +++++- gemfiles/rails32.gemfile | 6 +++++- gemfiles/rails40.gemfile | 6 +++++- gemfiles/rails41.gemfile | 6 +++++- gemfiles/rails42.gemfile | 6 +++++- 6 files changed, 30 insertions(+), 6 deletions(-) diff --git a/gemfiles/rails30.gemfile b/gemfiles/rails30.gemfile index 6349d202..208a5aba 100644 --- a/gemfiles/rails30.gemfile +++ b/gemfiles/rails30.gemfile @@ -1,4 +1,4 @@ -# This file was generated by Appraisal +require 'rubygems/version' source 'https://rubygems.org' @@ -36,4 +36,8 @@ gem 'database_cleaner', '~> 1.0.0' gem 'genspec', '>= 0.2.8' gem 'girl_friday', '>= 0.11.1' +if Gem::Version.new(RUBY_VERSION) < Gem::Version.new('2.0') + gem 'mime-types', '< 3.0' +end + gemspec :path => '../' diff --git a/gemfiles/rails31.gemfile b/gemfiles/rails31.gemfile index 0cb0a766..23c14131 100644 --- a/gemfiles/rails31.gemfile +++ b/gemfiles/rails31.gemfile @@ -1,4 +1,4 @@ -# This file was generated by Appraisal +require 'rubygems/version' source "https://rubygems.org" @@ -34,4 +34,8 @@ gem 'database_cleaner' gem 'girl_friday' gem 'generator_spec' +if Gem::Version.new(RUBY_VERSION) < Gem::Version.new('2.0') + gem 'mime-types', '< 3.0' +end + gemspec :path => "../" diff --git a/gemfiles/rails32.gemfile b/gemfiles/rails32.gemfile index 0ebb7c51..7f7f735d 100644 --- a/gemfiles/rails32.gemfile +++ b/gemfiles/rails32.gemfile @@ -1,4 +1,4 @@ -# This file was generated by Appraisal +require 'rubygems/version' source "https://rubygems.org" @@ -36,4 +36,8 @@ gem 'database_cleaner', '~> 1.0.0' gem 'girl_friday', '>= 0.11.1' gem 'generator_spec' +if Gem::Version.new(RUBY_VERSION) < Gem::Version.new('2.0') + gem 'mime-types', '< 3.0' +end + gemspec :path => "../" diff --git a/gemfiles/rails40.gemfile b/gemfiles/rails40.gemfile index 14fc01f1..02631a9e 100644 --- a/gemfiles/rails40.gemfile +++ b/gemfiles/rails40.gemfile @@ -1,4 +1,4 @@ -# This file was generated by Appraisal +require 'rubygems/version' source "https://rubygems.org" @@ -36,4 +36,8 @@ gem 'database_cleaner', '~> 1.0.0' gem 'girl_friday', '>= 0.11.1' gem 'generator_spec' +if Gem::Version.new(RUBY_VERSION) < Gem::Version.new('2.0') + gem 'mime-types', '< 3.0' +end + gemspec :path => "../" diff --git a/gemfiles/rails41.gemfile b/gemfiles/rails41.gemfile index e322f99d..623ed2d5 100644 --- a/gemfiles/rails41.gemfile +++ b/gemfiles/rails41.gemfile @@ -1,4 +1,4 @@ -# This file was generated by Appraisal +require 'rubygems/version' source "https://rubygems.org" @@ -34,4 +34,8 @@ gem 'database_cleaner', '~> 1.0.0' gem 'girl_friday', '>= 0.11.1' gem 'generator_spec' +if Gem::Version.new(RUBY_VERSION) < Gem::Version.new('2.0') + gem 'mime-types', '< 3.0' +end + gemspec :path => "../" diff --git a/gemfiles/rails42.gemfile b/gemfiles/rails42.gemfile index 09ff3108..449a9bc4 100644 --- a/gemfiles/rails42.gemfile +++ b/gemfiles/rails42.gemfile @@ -1,4 +1,4 @@ -# This file was generated by Appraisal +require 'rubygems/version' source "https://rubygems.org" @@ -34,4 +34,8 @@ gem 'girl_friday', '>= 0.11.1' gem 'generator_spec' gem 'codeclimate-test-reporter', :group => :test, :require => nil +if Gem::Version.new(RUBY_VERSION) < Gem::Version.new('2.0') + gem 'mime-types', '< 3.0' +end + gemspec :path => "../"