Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added basic logger/log-device and tests #375

Closed
wants to merge 19 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion Gemfile
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,9 @@ source "https://rubygems.org"
group :test, optional: true do
gem 'rake', RUBY_VERSION <= '1.9.3' ? '~> 11.3.0' : '~> 12.3.0'
gem 'rspec'
gem 'rspec-mocks'
gem 'logging'
gem 'rdoc', '~> 5.1.0'
gem 'rspec-mocks'
gem 'pry'
gem 'addressable', '~> 2.3.8'
gem 'delayed_job' if RUBY_VERSION >= '2.2.2'
Expand Down
6 changes: 6 additions & 0 deletions example/rails-42/app/controllers/application_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -56,4 +56,10 @@ def severity
end
@text = msg
end

def crash_after_log
@test_model = TestModel.new :foo => "Foo"
@test_model.save
raise "Crash"
end
end
2 changes: 2 additions & 0 deletions example/rails-42/app/models/test_model.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
class TestModel < ActiveRecord::Base
end
1 change: 1 addition & 0 deletions example/rails-42/config/routes.rb
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
Rails.application.routes.draw do
root :to => 'application#index'
get "log" => 'application#crash_after_log'

get 'crash' => 'application#crash'
get 'crash_with_callback' => 'application#callback'
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
class CreateTestModels < ActiveRecord::Migration
def change
create_table :test_models do |t|
t.string :foo

t.timestamps null: false
end
end
end
2 changes: 1 addition & 1 deletion lib/bugsnag.rb
Original file line number Diff line number Diff line change
Expand Up @@ -124,7 +124,7 @@ def notify(exception, auto_notify=false, &block)

##
# Records a breadcrumb to give context to notifications
def leave_breadcrumb(name, type=nil, metadata={})
def leave_breadcrumb(name, metadata={}, type=Bugsnag::Breadcrumbs::MANUAL_TYPE)
configuration.recorder.add_breadcrumb(Bugsnag::Breadcrumbs::Breadcrumb.new(name, type, metadata))
end

Expand Down
29 changes: 29 additions & 0 deletions lib/bugsnag/breadcrumbs/appender.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
require_relative "logger"
require "logging"

module Bugsnag::Breadcrumbs
class Appender < Logging::Appender
def initialize(level = Logger::INFO)
super "Bugsnag", { :level => level }
end

def <<(message)
return if closed?
Bugsnag::Breadcrumbs::Logger.log_breadcrumb(message)
end

def append(event)
return if closed? || !allow(event)

message = event.data.to_s
metadata = {
:method => event.method.to_s,
:file => event.file.to_s,
:line => event.line.to_s
}.delete_if { |_k, v| v == "" }

severity = Bugsnag::Breadcrumbs::Logger.get_severity_name(event.level)
Bugsnag::Breadcrumbs::Logger.log_breadcrumb(message, metadata, severity)
end
end
end
76 changes: 76 additions & 0 deletions lib/bugsnag/breadcrumbs/logger.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
require "logger"
require "bugsnag"

module Bugsnag::Breadcrumbs
class Logger < Logger
SEVERITIES = [
"debug",
"info",
"warn",
"error",
"fatal",
"unknown"
]

def self.get_severity_name(severity)
if (0..5).cover? severity
SEVERITIES[severity]
else
severity
end
end

def self.log_breadcrumb(message, data = nil, severity = "unknown")
metadata = {
:severity => severity,
:message => message
}
if data.is_a? Hash
metadata.merge!(data)
elsif !data.nil?
metadata[:data] = data.to_s
end

Bugsnag.leave_breadcrumb("Log output", metadata, Bugsnag::Breadcrumbs::LOG_TYPE)
end

def initialize(level = Logger::INFO)
@open = true
super nil, level
end

def add(severity, message = nil, progname = nil)
return unless @open

if block_given?
message = yield message
elsif message.nil?
message = progname
end

if severity >= level # rubocop:disable Style/GuardClause
Bugsnag::Breadcrumbs::Logger.log_breadcrumb(
message,
{ :progname => progname },
Bugsnag::Breadcrumbs::Logger.get_severity_name(severity)
)
end
end
alias log add

def <<(message)
return unless @open
Bugsnag::Breadcrumbs::Logger.log_breadcrumb(message)
end

def close
@open = false
true
end

def reopen
@open = true
true
end
end
end
61 changes: 61 additions & 0 deletions spec/appender_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
# encoding: utf-8

# Necessary to avoid monkey patching thread methods
ENV["LOGGING_INHERIT_CONTEXT"] = "false"

require 'spec_helper'
require 'logger'
require 'logging'
require 'bugsnag/breadcrumbs/appender'

describe Bugsnag::Breadcrumbs::Appender do
let(:appender) { Bugsnag::Breadcrumbs::Appender.new }

it "writes breadcrumbs" do
expect(Bugsnag).to receive(:leave_breadcrumb).with(
"Log output",
{
:severity => "unknown",
:message => "message"
},
"log"
)
appender << "message"
end

it "write breadcrumbs from a logevent" do
expect(Bugsnag).to receive(:leave_breadcrumb).with(
"Log output",
{
:message => ["message1", "message2"].to_s,
:severity => "info",
},
"log"
)
logevent = Logging::LogEvent.new("testLogger", Logger::INFO, ["message1", "message2"], false)
appender.append logevent
end

it "adds trace metadata if available" do
expect(Bugsnag).to receive(:leave_breadcrumb) do |name, metadata, severity|
expect(name).to eq("Log output")
expect(metadata).to include(:message, :severity, :method, :file, :line)
expect(metadata).to include(:message => ["message1", "message2"].to_s, :severity => "info")
expect(severity).to eq("log")
end
logevent = Logging::LogEvent.new("testLogger", Logger::INFO, ["message1", "message2"], true)
appender.append logevent
end

it "doesn't write if closed" do
expect(Bugsnag).to_not receive(:leave_breadcrumb)
appender.close
appender << "message"
logevent = Logging::LogEvent.new("testLogger", Logger::INFO, ["message1", "message2"], false)
appender.append logevent
end

it "is an appender and a bugsnag appender" do
expect(appender.class.ancestors).to include(Bugsnag::Breadcrumbs::Appender, Logging::Appender)
end
end
14 changes: 7 additions & 7 deletions spec/integrations/logger_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,10 @@
context 'in a Rails app' do
key_warning = '[Bugsnag]: No valid API key has been set, notifications will not be sent'
is_jruby = defined?(RUBY_ENGINE) && RUBY_ENGINE == 'jruby'
incompatible = (RUBY_VERSION < '2.0.0') || is_jruby
incompatible = (RUBY_VERSION < '2.1.0') || is_jruby

before do
skip "Incompatible with Ruby <2.0 and JRuby" if incompatible
skip "Incompatible with Ruby <2.1 and JRuby" if incompatible
@env['RACK_ENV'] = 'production'
end

Expand All @@ -38,7 +38,7 @@ def run_app(name)
end
context 'sets an API key using the BUGSNAG_API_KEY env var' do
it 'does not log a warning' do
skip "Incompatible with Ruby <2.0 and JRuby" if incompatible
skip "Incompatible with Ruby <2.1 and JRuby" if incompatible
@env['BUGSNAG_API_KEY'] = 'c34a2472bd240ac0ab0f52715bbdc05d'
output = run_app('rails-no-config')
expect(output).not_to include(key_warning)
Expand All @@ -47,31 +47,31 @@ def run_app(name)

context 'sets an API key using the bugsnag initializer' do
it 'does not log a warning' do
skip "Incompatible with Ruby <2.0 and JRuby" if incompatible
skip "Incompatible with Ruby <2.1 and JRuby" if incompatible
output = run_app('rails-initializer-config')
expect(output).not_to include(key_warning)
end
end

context 'skips setting an API key' do
it 'logs a warning' do
skip "Incompatible with Ruby <2.0 and JRuby" if incompatible
skip "Incompatible with Ruby <2.1 and JRuby" if incompatible
output = run_app('rails-no-config')
expect(output).to include(key_warning)
end
end

context 'sets an invalid API key using the BUGSNAG_API_KEY env var' do
it 'logs a warning' do
skip "Incompatible with Ruby <2.0 and JRuby" if incompatible
skip "Incompatible with Ruby <2.1 and JRuby" if incompatible
output = run_app('rails-invalid-initializer-config')
expect(output).to include(key_warning)
end
end

context 'sets an invalid API key using the BUGSNAG_API_KEY env var' do
it 'logs a warning' do
skip "Incompatible with Ruby <2.0 and JRuby" if incompatible
skip "Incompatible with Ruby <2.1 and JRuby" if incompatible
@env['BUGSNAG_API_KEY'] = 'not a real key'
output = run_app('rails-no-config')
expect(output).to include(key_warning)
Expand Down
58 changes: 58 additions & 0 deletions spec/logger_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
# encoding: utf-8

require 'spec_helper'
require 'logger'
require 'bugsnag/breadcrumbs/logger'

describe Bugsnag::Breadcrumbs::Logger do
let(:logger) { Bugsnag::Breadcrumbs::Logger.new }

it "writes by default" do
expect(Bugsnag).to receive(:leave_breadcrumb).with(
"Log output",
{
:severity => "unknown",
:message => "message"
},
"log"
)
logger << "message"
end

it "doesn't write when closed" do
expect(Bugsnag).to_not receive(:leave_breadcrumb)
logger.close
logger << "message"
end

it "writes after being re-opened" do
expect(Bugsnag).to receive(:leave_breadcrumb).with(
"Log output",
{
:severity => "unknown",
:message => "message"
},
"log"
)
logger.close
logger.reopen
logger << "message"
end

it "allows a progname and severity" do
expect(Bugsnag).to receive(:leave_breadcrumb).with(
"Log output",
{
:progname => "logTests",
:severity => "info",
:message => "message"
},
"log"
)
logger.info("logTests") { "message" }
end

it "is a logger and a bugsnag logger" do
expect(logger.class.ancestors).to include(Bugsnag::Breadcrumbs::Logger, Logger)
end
end
2 changes: 1 addition & 1 deletion spec/report_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -119,7 +119,7 @@ def gloops
end

it "attaches added breadcrumbs" do
Bugsnag.leave_breadcrumb("Test", Bugsnag::Breadcrumbs::MANUAL_TYPE, {:foo => "foo", :bar => "bar"})
Bugsnag.leave_breadcrumb("Test", {:foo => "foo", :bar => "bar"})
Bugsnag.notify(BugsnagTestException.new("It crashed"))
expect(Bugsnag).to have_sent_notification{ |payload, headers|
breadcrumb = get_breadcrumb_from_payload(payload)
Expand Down