diff --git a/.travis.yml b/.travis.yml
index a95a9d8..04390fc 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -4,7 +4,7 @@ crystal:
- latest
- nightly
-matrix:
+jobs:
allow_failures:
- crystal: nightly
@@ -16,5 +16,7 @@ script:
- crystal spec --no-debug
- crystal spec --release
- crystal spec --release --no-debug
+ - shards build crash_handler
+ - shards build crash_handler --release
- crystal tool format --check
- - bin/ameba src
+ - bin/ameba
diff --git a/README.md b/README.md
index a977d4d..d26b050 100644
--- a/README.md
+++ b/README.md
@@ -7,7 +7,7 @@
-
+
diff --git a/shard.yml b/shard.yml
index 37c37f5..94866a3 100644
--- a/shard.yml
+++ b/shard.yml
@@ -1,5 +1,5 @@
name: raven
-version: 1.6.0
+version: 1.7.0
authors:
- Sijawusz Pur Rahnama
@@ -15,12 +15,12 @@ development_dependencies:
version: ~> 0.4.0
ameba:
github: crystal-ameba/ameba
- version: ~> 0.11.0
+ version: ~> 0.13.0
targets:
crash_handler:
main: src/crash_handler.cr
-crystal: 0.32.0
+crystal: 0.35.0
license: MIT
diff --git a/spec/raven/backtrace_line_spec.cr b/spec/raven/backtrace_line_spec.cr
index 533bedf..692f223 100644
--- a/spec/raven/backtrace_line_spec.cr
+++ b/spec/raven/backtrace_line_spec.cr
@@ -1,6 +1,6 @@
require "../spec_helper"
-def with_line(path = "#{__DIR__}/foo.cr", method = "foo_bar?")
+private def with_line(path = "#{__DIR__}/foo.cr", method = "foo_bar?")
line = "#{path}:1:7 in '#{method}'"
yield Raven::Backtrace::Line.parse(line)
end
diff --git a/spec/raven/breadcrumb_buffer_spec.cr b/spec/raven/breadcrumb_buffer_spec.cr
index 4b2a7a4..3294dee 100644
--- a/spec/raven/breadcrumb_buffer_spec.cr
+++ b/spec/raven/breadcrumb_buffer_spec.cr
@@ -1,6 +1,6 @@
require "../spec_helper"
-def with_breadcrumb_buffer
+private def with_breadcrumb_buffer
breadcrumbs = Raven::BreadcrumbBuffer.new(10)
yield breadcrumbs
end
diff --git a/spec/raven/client_spec.cr b/spec/raven/client_spec.cr
index 97683ec..8b13572 100644
--- a/spec/raven/client_spec.cr
+++ b/spec/raven/client_spec.cr
@@ -1,6 +1,6 @@
require "../spec_helper"
-class ClientTest < Raven::Client
+private class ClientTest < Raven::Client
def generate_auth_header
super
end
@@ -10,12 +10,7 @@ class ClientTest < Raven::Client
end
end
-def build_configuration
- Raven::Configuration.new
- .tap(&.dsn = "dummy://12345:67890@sentry.localdomain:3000/sentry/42")
-end
-
-def with_client
+private def with_client
yield ClientTest.new(build_configuration)
end
@@ -96,7 +91,7 @@ describe Raven::Client do
last_event[:options].should eq({:content_type => "application/octet-stream"})
last_event[:data].should be_a(String)
io = IO::Memory.new(last_event[:data].as(String))
- Gzip::Reader.open(io) do |gzip|
+ Compress::Gzip::Reader.open(io) do |gzip|
data = JSON.parse(gzip.gets_to_end)
data.as_h?.should_not be_nil
data["event_id"].should eq(event.id)
diff --git a/spec/raven/client_state_spec.cr b/spec/raven/client_state_spec.cr
index 6862eed..a8820ac 100644
--- a/spec/raven/client_state_spec.cr
+++ b/spec/raven/client_state_spec.cr
@@ -1,7 +1,7 @@
require "../spec_helper"
require "timecop"
-def with_client_state
+private def with_client_state
yield Raven::Client::State.new
end
diff --git a/spec/raven/configuration_spec.cr b/spec/raven/configuration_spec.cr
index f43230b..68006a2 100644
--- a/spec/raven/configuration_spec.cr
+++ b/spec/raven/configuration_spec.cr
@@ -12,13 +12,13 @@ private class RandomSampleFail < Random::PCG32
end
end
-def with_configuration
+private def with_configuration
with_clean_env do
yield Raven::Configuration.new
end
end
-def with_configuration_with_dsn
+private def with_configuration_with_dsn
with_configuration do |configuration|
configuration.dsn = "http://12345:67890@sentry.localdomain:3000/sentry/42"
yield configuration
diff --git a/spec/raven/event_spec.cr b/spec/raven/event_spec.cr
index 4848d11..a8ca6e6 100644
--- a/spec/raven/event_spec.cr
+++ b/spec/raven/event_spec.cr
@@ -4,7 +4,7 @@ module Raven::Test
class Exception < ::Exception; end
end
-def with_event(clear = true, **opts)
+private def with_event(clear = true, **opts)
if clear
Raven::Context.clear!
Raven::BreadcrumbBuffer.clear!
@@ -13,18 +13,24 @@ def with_event(clear = true, **opts)
yield event
end
-def with_event_hash(**opts)
+private def with_event_hash(**opts)
with_event(**opts) do |event|
yield event.to_hash
end
end
-def exception_value_from_event_hash(hash, index)
+private def exception_value_from_event_hash(hash, index)
ex_values = hash.to_any_json[:exception, :values].as(Array)
ex_values[index].as(Hash)
end
describe Raven::Event do
+ around_each do |example|
+ Raven::Context.clear!
+ example.run
+ Raven::Context.clear!
+ end
+
context "with fully implemented event" do
opts = {
message: "test",
@@ -190,8 +196,6 @@ describe Raven::Event do
{% for key in %i(user extra tags) %}
context "with {{key.id}} context specified" do
it "prioritizes event context" do
- Raven::Context.clear!
-
Raven.{{key.id}}_context({
"context_event_key" => "context_value",
"context_key" => "context_value",
diff --git a/spec/raven/instance_spec.cr b/spec/raven/instance_spec.cr
index adff4d4..ea348bd 100644
--- a/spec/raven/instance_spec.cr
+++ b/spec/raven/instance_spec.cr
@@ -16,24 +16,7 @@ private class InstanceTest < Raven::Instance
end
end
-private class LoggerTest < Raven::Logger
- getter infos = [] of String
-
- def info(message, *args)
- super.tap do
- @infos << message
- end
- end
-end
-
-def build_configuration
- Raven::Configuration.new.tap do |config|
- config.dsn = "dummy://12345:67890@sentry.localdomain:3000/sentry/42"
- config.logger = LoggerTest.new(nil)
- end
-end
-
-def with_instance(context = nil)
+private def with_instance(context = nil)
yield InstanceTest.new(context, build_configuration)
end
@@ -214,8 +197,10 @@ describe Raven::Instance do
with_instance do |instance|
instance.configuration.silence_ready = false
- instance.report_status
- instance.logger.as(LoggerTest).infos.should contain(ready_message)
+ Log.capture do |logs|
+ instance.report_status
+ logs.check(:info, ready_message)
+ end
end
end
@@ -223,8 +208,10 @@ describe Raven::Instance do
with_instance do |instance|
instance.configuration.silence_ready = true
- instance.report_status
- instance.logger.as(LoggerTest).infos.should_not contain(ready_message)
+ Log.capture do |logs|
+ instance.report_status
+ logs.empty
+ end
end
end
@@ -233,8 +220,10 @@ describe Raven::Instance do
instance.configuration.silence_ready = false
instance.configuration.dsn = "dummy://foo"
- instance.report_status
- instance.logger.as(LoggerTest).infos.first.should contain(not_ready_message)
+ Log.capture do |logs|
+ instance.report_status
+ logs.check(:info, /#{not_ready_message}/)
+ end
end
end
@@ -243,10 +232,12 @@ describe Raven::Instance do
instance.configuration.silence_ready = false
instance.configuration.environments = %w(production)
- instance.report_status
- instance.logger.as(LoggerTest).infos.should contain(
- "#{not_ready_message}: Not configured to send/capture in environment 'default'"
- )
+ Log.capture do |logs|
+ instance.report_status
+ logs.check(:info,
+ "#{not_ready_message}: Not configured to send/capture in environment 'default'"
+ )
+ end
end
end
end
@@ -255,7 +246,9 @@ describe Raven::Instance do
it "sends the result of Event.capture" do
with_instance do |instance|
event = instance.capture("Test message")
- instance.last_sent_event.try(&.id).should eq(event.as?(Raven::Event).try(&.id))
+
+ last_sent_event = instance.last_sent_event.should_not be_nil
+ last_sent_event.id.should eq(event.as(Raven::Event).id)
end
end
end
diff --git a/spec/raven/logger_spec.cr b/spec/raven/logger_spec.cr
deleted file mode 100644
index 4c3ebec..0000000
--- a/spec/raven/logger_spec.cr
+++ /dev/null
@@ -1,12 +0,0 @@
-require "../spec_helper"
-
-describe Raven::Logger do
- it "should log to a given IO" do
- io = IO::Memory.new
-
- logger = Raven::Logger.new(io)
- logger.fatal("Oh noes!")
-
- io.to_s.should match(/FATAL -- sentry: Oh noes!\n\Z/)
- end
-end
diff --git a/spec/raven/processors/sanitize_data_spec.cr b/spec/raven/processors/sanitize_data_spec.cr
index 73913b5..b84d2e9 100644
--- a/spec/raven/processors/sanitize_data_spec.cr
+++ b/spec/raven/processors/sanitize_data_spec.cr
@@ -9,9 +9,11 @@ end
STRING_MASK = Raven::Processor::SanitizeData::STRING_MASK
INT_MASK = Raven::Processor::SanitizeData::INT_MASK
-describe Raven::Processor::SanitizeData do
- processor = build_processor(Raven::Processor::SanitizeData)
+private def test_processor
+ build_processor(Raven::Processor::SanitizeData)
+end
+describe Raven::Processor::SanitizeData do
context "configuration for sanitize fields" do
it "should union default sanitize fields with user-defined sanitize fields" do
with_processor(SanitizeDataTest) do |processor|
@@ -133,7 +135,7 @@ describe Raven::Processor::SanitizeData do
},
}
- result = processor.process(data_with_embedded_json)
+ result = test_processor.process(data_with_embedded_json)
result = result.to_any_json
JSON.parse(result["data", "json"].as(String)).should eq(%w(foo bar))
@@ -148,7 +150,7 @@ describe Raven::Processor::SanitizeData do
},
}
- result = processor.process(data_with_invalid_json)
+ result = test_processor.process(data_with_invalid_json)
result = result.to_any_json
expect_raises(JSON::ParseException) do
@@ -162,7 +164,7 @@ describe Raven::Processor::SanitizeData do
"ccnumba_int" => 4242424242424242,
}
- result = processor.process(data)
+ result = test_processor.process(data)
result["ccnumba"].should eq(STRING_MASK)
result["ccnumba_int"].should eq(INT_MASK)
@@ -192,7 +194,7 @@ describe Raven::Processor::SanitizeData do
"symbol_hash_array" => [{:password => "secret"}],
}
- result = processor.process(data)
+ result = test_processor.process(data)
result["string_hash_array"].should eq([{"password" => STRING_MASK}])
result["symbol_hash_array"].should eq([{:password => STRING_MASK}])
@@ -208,7 +210,7 @@ describe Raven::Processor::SanitizeData do
},
}
- result = processor.process(data)
+ result = test_processor.process(data)
result = result.to_any_json
result["sentry.interfaces.Http", "data", "query_string"].as(String).should_not contain("secret")
@@ -223,7 +225,7 @@ describe Raven::Processor::SanitizeData do
},
}
- result = processor.process(data)
+ result = test_processor.process(data)
result = result.to_any_json
result["sentry.interfaces.Http", "data", :query_string].as(String).should_not contain("secret")
@@ -238,7 +240,7 @@ describe Raven::Processor::SanitizeData do
},
}
- result = processor.process(data)
+ result = test_processor.process(data)
result.should eq(data)
end
@@ -252,7 +254,7 @@ describe Raven::Processor::SanitizeData do
},
}
- result = processor.process(data)
+ result = test_processor.process(data)
result.should eq(data)
end
end
@@ -264,7 +266,7 @@ describe Raven::Processor::SanitizeData do
:millis_since_epoch => "1507671610403",
}
- result = processor.process(data)
+ result = test_processor.process(data)
result.should eq(data)
end
end
diff --git a/spec/raven/processors/utf8_conversion_spec.cr b/spec/raven/processors/utf8_conversion_spec.cr
index 91a5f35..f6c047a 100644
--- a/spec/raven/processors/utf8_conversion_spec.cr
+++ b/spec/raven/processors/utf8_conversion_spec.cr
@@ -27,7 +27,7 @@ describe Raven::Processor::UTF8Conversion do
it "should retain #cause and #callstack in cleaned up Exception" do
ex = Exception.new(nil, Exception.new)
- ex.callstack = CallStack.new
+ ex.callstack = Exception::CallStack.new
results = processor.process(ex)
results.cause.should eq(ex.cause)
diff --git a/spec/raven/version_spec.cr b/spec/raven/version_spec.cr
index 47241a1..9c1478f 100644
--- a/spec/raven/version_spec.cr
+++ b/spec/raven/version_spec.cr
@@ -7,7 +7,7 @@ describe Raven::VERSION do
end
it "should match shard.yml" do
- version = YAML.parse(File.read(File.join(__DIR__, "../..", "shard.yml")))["version"].as_s
+ version = YAML.parse(File.read(Path[__DIR__, "..", "..", "shard.yml"]))["version"].as_s
version.should eq Raven::VERSION
end
end
diff --git a/spec/spec_helper.cr b/spec/spec_helper.cr
index ca8c162..567c790 100644
--- a/spec/spec_helper.cr
+++ b/spec/spec_helper.cr
@@ -1,4 +1,5 @@
require "spec"
+require "log/spec"
require "../src/raven"
# Make sure we reset the env in case something leaks in
@@ -48,3 +49,9 @@ def build_exception_with_two_causes
rescue exception
exception
end
+
+def build_configuration
+ Raven::Configuration.new.tap do |config|
+ config.dsn = "dummy://12345:67890@sentry.localdomain:3000/sentry/42"
+ end
+end
diff --git a/src/crash_handler.cr b/src/crash_handler.cr
index 4eb3e74..8fd80b4 100644
--- a/src/crash_handler.cr
+++ b/src/crash_handler.cr
@@ -1,5 +1,14 @@
require "./raven"
+Log.setup do |c|
+ level = case
+ when {{ flag?(:release) }} then Log::Severity::None
+ when {{ flag?(:debug) }} then Log::Severity::Debug
+ else Log::Severity::Error
+ end
+ c.bind("raven.*", level, Log::IOBackend.new)
+end
+
module Raven
class CrashHandler
# Example:
@@ -15,7 +24,8 @@ module Raven
# [0x10578706c] __crystal_main +2940
# [0x105798128] main +40
# ```
- CRYSTAL_CRASH_PATTERN = /(?[^\n]+)\n(?\[#{Backtrace::Line::ADDR_FORMAT}\] .*)$/m
+ CRYSTAL_CRASH_PATTERN =
+ /(?[^\n]+)\n(?\[#{Backtrace::Line::ADDR_FORMAT}\] .*)$/m
# Example:
#
@@ -27,7 +37,8 @@ module Raven
# from /usr/local/Cellar/crystal/0.26.0/src/crystal/main.cr:93:7 in 'main'
# from /usr/local/Cellar/crystal/0.26.0/src/crystal/main.cr:133:3 in 'main'
# ```
- CRYSTAL_EXCEPTION_PATTERN = /Unhandled exception(? in spawn(?:\(name: (?.*?)\))?)?: (?[^\n]+) \((?[A-Z]\w+)\)\n(?(?:\s+from\s+.*?){1,})$/m
+ CRYSTAL_EXCEPTION_PATTERN =
+ /Unhandled exception(? in spawn(?:\(name: (?.*?)\))?)?: (?[^\n]+) \((?[A-Z]\w+)\)\n(?(?:\s+from\s+.*?){1,})$/m
# Default event options.
DEFAULT_OPTS = {
@@ -50,13 +61,6 @@ module Raven
delegate :context, :configuration, :configure, :capture,
to: raven
- property logger : ::Logger {
- Logger.new({{ "STDOUT".id unless flag?(:release) }}).tap do |logger|
- logger.level = {{ flag?(:debug) ? "Logger::DEBUG".id : "Logger::ERROR".id }}
- logger.progname = "raven.crash_handler"
- end
- }
-
def initialize(@name, @args)
context.extra.merge!({
process: {name: @name, args: @args},
@@ -65,7 +69,6 @@ module Raven
private def configure!
configure do |config|
- config.logger = logger
config.send_modules = false
config.processors = [
Processor::UTF8Conversion,
@@ -131,16 +134,14 @@ module Raven
getter! started_at : Time
getter! process_status : Process::Status
- delegate :exit_code, :success?,
- to: process_status
-
- private def run_process(error : IO = IO::Memory.new)
+ private def run_process
+ error = IO::Memory.new
@process_status = Process.run command: name, args: args,
shell: true,
- input: Process::Redirect::Inherit,
- output: Process::Redirect::Inherit,
+ input: :inherit,
+ output: :inherit,
error: IO::MultiWriter.new(STDERR, error)
- error.to_s.chomp
+ error.to_s.chomp.presence
end
def run : Nil
@@ -152,6 +153,9 @@ module Raven
error = run_process
running_for = Time.monotonic - start
+ exit_code = process_status.exit_code
+ success = process_status.success?
+
context.tags.merge!({
exit_code: exit_code,
})
@@ -161,7 +165,7 @@ module Raven
})
captured = false
- error.scan CRYSTAL_EXCEPTION_PATTERN do |match|
+ error.try &.scan CRYSTAL_EXCEPTION_PATTERN do |match|
msg = match["message"]
klass = match["class"]
backtrace = match["backtrace"]
@@ -174,7 +178,7 @@ module Raven
})
captured = true
end
- unless success?
+ unless success
if error =~ CRYSTAL_CRASH_PATTERN
msg = $~["message"]
backtrace = $~["backtrace"]
@@ -193,11 +197,10 @@ module Raven
end
if ARGV.empty?
- puts "Usage: #{PROGRAM_NAME} [OPTION]..."
- exit(1)
+ abort "Usage: #{PROGRAM_NAME} [OPTION]..."
end
-name, args = ARGV[0], ARGV.size > 1 ? ARGV[1..-1] : nil
+name, args = ARGV[0], ARGV.size > 1 ? ARGV[1..] : nil
handler = Raven::CrashHandler.new(name, args)
handler.raven.tap do |raven|
raven.configuration.src_path = Dir.current
diff --git a/src/raven.cr b/src/raven.cr
index 58392b8..f6a6f23 100644
--- a/src/raven.cr
+++ b/src/raven.cr
@@ -7,7 +7,7 @@ require "./raven/*"
module Raven
# `Raven.instance` delegators.
module Delegators
- delegate :context, :logger, :configuration, :client,
+ delegate :context, :configuration, :client,
:report_status, :configure, :send_feedback, :send_event,
:capture, :last_event_id, :annotate_exception,
:user_context, :tags_context, :extra_context, :breadcrumbs,
diff --git a/src/raven/backtrace.cr b/src/raven/backtrace.cr
index 64ee5ea..cf6d58e 100644
--- a/src/raven/backtrace.cr
+++ b/src/raven/backtrace.cr
@@ -32,12 +32,12 @@ module Raven
def_equals @lines
def to_s(io : IO) : Nil
- @lines.join('\n', io)
+ @lines.join(io, '\n')
end
def inspect(io : IO) : Nil
io << "#'
end
end
diff --git a/src/raven/client.cr b/src/raven/client.cr
index 681839c..2ee2a28 100644
--- a/src/raven/client.cr
+++ b/src/raven/client.cr
@@ -1,6 +1,6 @@
require "base64"
require "json"
-require "zlib"
+require "compress/gzip"
module Raven
# Encodes events and sends them to the Sentry server.
@@ -9,7 +9,6 @@ module Raven
USER_AGENT = "raven.cr/#{Raven::VERSION}"
property configuration : Configuration
- delegate logger, to: configuration
@state : State
@processors : Array(Processor)
@@ -36,7 +35,9 @@ module Raven
def send_feedback(event_id : String, data : Hash)
unless configuration.valid?
- logger.debug "Client#send_feedback with event id '#{event_id}' failed: #{configuration.error_messages}"
+ Log.debug {
+ "Client#send_feedback with event id '#{event_id}' failed: #{configuration.error_messages}"
+ }
return false
end
transport.send_feedback(event_id, data)
@@ -44,14 +45,16 @@ module Raven
def send_event(event : Event | Event::HashType, hint : Event::Hint? = nil)
unless configuration.valid?
- logger.debug "Client#send_event with event '#{event}' failed: #{configuration.error_messages}"
+ Log.debug {
+ "Client#send_event with event '#{event}' failed: #{configuration.error_messages}"
+ }
return false
end
if event.is_a?(Event)
configuration.before_send.try do |before_send|
event = before_send.call(event, hint)
unless event
- logger.info "Discarded event because before_send returned nil"
+ Log.info { "Discarded event because before_send returned nil" }
return
end
end
@@ -61,7 +64,7 @@ module Raven
failed_send nil, event
return
end
- logger.info "Sending event #{event[:event_id]} to Sentry"
+ Log.info { "Sending event #{event[:event_id]} to Sentry" }
content_type, encoded_data = encode(event)
begin
@@ -84,7 +87,7 @@ module Raven
case configuration.encoding
when .gzip?
io_gzipped = IO::Memory.new
- Gzip::Writer.open(io_gzipped) do |gzip|
+ Compress::Gzip::Writer.open(io_gzipped) do |gzip|
IO.copy(io, gzip)
end
io_gzipped.rewind
@@ -127,14 +130,13 @@ module Raven
private def failed_send(ex, event)
if ex
@state.failure
- logger.warn "Unable to record event with remote Sentry server \
- (#{ex.class} - #{ex.message}): #{ex.backtrace[0..10].join('\n')}"
+ Log.warn(exception: ex) { "Unable to record event with remote Sentry server" }
else
- logger.warn "Not sending event due to previous failure(s)"
+ Log.warn { "Not sending event due to previous failure(s)" }
end
message = get_log_message(event)
- logger.warn "Failed to submit event: #{message}"
+ Log.warn { "Failed to submit event: #{message}" }
configuration.transport_failure_callback.try &.call(event)
end
diff --git a/src/raven/configuration.cr b/src/raven/configuration.cr
index c79d40c..263af6d 100644
--- a/src/raven/configuration.cr
+++ b/src/raven/configuration.cr
@@ -49,14 +49,6 @@ module Raven
# ```
property async : Proc(Event, Nil)?
- # ditto
- def async=(block : Event -> _)
- @async = ->(event : Event) {
- block.call(event)
- nil
- }
- end
-
# Sets `async` callback to either `Fiber`-based implementation (see below),
# or `nil`, depending on the given *switch* value.
#
@@ -90,9 +82,9 @@ module Raven
# Whitelist of environments that will send notifications to Sentry.
property environments = [] of String
- # Logger "progname"s to exclude from breadcrumbs.
+ # `::Log#source` patterns excluded from breadcrumb recording.
#
- # Defaults to `[Raven::Logger::PROGNAME]`.
+ # Defaults to `raven.*`.
#
# NOTE: You should probably append to this rather than overwrite it.
property exclude_loggers : Array(String)
@@ -107,10 +99,6 @@ module Raven
# NOTE: DSN component - set automatically if DSN provided.
property host : String?
- # Logger used by Raven. You can use any other `::Logger`,
- # defaults to `Raven::Logger`.
- property logger : ::Logger
-
# Timeout waiting for the Sentry server connection to open in seconds.
property connect_timeout : Time::Span = 1.second
@@ -239,14 +227,6 @@ module Raven
# ```
property transport_failure_callback : Proc(Event::HashType, Nil)?
- # ditto
- def transport_failure_callback=(block : Event::HashType -> _)
- @transport_failure_callback = ->(event : Event::HashType) {
- block.call(event)
- nil
- }
- end
-
# Optional `Proc`, called before sending an event to the server:
#
# ```
@@ -276,9 +256,8 @@ module Raven
def initialize
@current_environment = current_environment_from_env
- @exclude_loggers = [Logger::PROGNAME]
+ @exclude_loggers = ["#{Log.source}.*"]
@excluded_exceptions = IGNORE_DEFAULT.dup
- @logger = Logger.new(STDOUT)
@processors = DEFAULT_PROCESSORS.dup
@sanitize_data_for_request_methods = DEFAULT_REQUEST_METHODS_FOR_DATA_SANITIZATION.dup
@release = detect_release
@@ -355,16 +334,16 @@ module Raven
if commit = ENV["HEROKU_SLUG_COMMIT"]?
return commit
end
- logger.warn(HEROKU_DYNO_METADATA_MESSAGE)
+ Log.warn { HEROKU_DYNO_METADATA_MESSAGE }
nil
end
private def detect_release_from_capistrano
- version = File.read(File.join(project_root, "REVISION")).strip rescue nil
+ version = File.read(Path[project_root, "REVISION"]).strip rescue nil
return version if version
# Capistrano 3.0 - 3.1.x
- File.read_lines(File.join(project_root, "..", "revisions.log"))
+ File.read_lines(Path[project_root, "..", "revisions.log"])
.last.strip.sub(/.*as release ([0-9]+).*/, "\1") rescue nil
end
@@ -395,6 +374,12 @@ module Raven
ENV["SENTRY_ENVIRONMENT"]? || "default"
end
+ def ignored_logger?(source)
+ exclude_loggers.any? do |pattern|
+ ::Log::Builder.matches(source, pattern)
+ end
+ end
+
def capture_allowed?
@errors = [] of String
valid? &&
diff --git a/src/raven/event.cr b/src/raven/event.cr
index feeedbc..1c48feb 100644
--- a/src/raven/event.cr
+++ b/src/raven/event.cr
@@ -101,7 +101,7 @@ module Raven
{% end %}
new(**options).tap do |event|
- exc.callstack ||= CallStack.new
+ exc.callstack ||= Exception::CallStack.new
add_exception_interface(event, exc)
end
end
diff --git a/src/raven/instance.cr b/src/raven/instance.cr
index 3b1293c..28df104 100644
--- a/src/raven/instance.cr
+++ b/src/raven/instance.cr
@@ -25,8 +25,6 @@ module Raven
# See `Raven::Configuration`.
property configuration : Configuration { Configuration.new }
- delegate logger, to: configuration
-
# The client object is responsible for delivering formatted data to the
# Sentry server.
property client : Client { Client.new(configuration) }
@@ -51,9 +49,11 @@ module Raven
def report_status
return if configuration.silence_ready?
if configuration.capture_allowed?
- logger.info "Raven #{VERSION} ready to catch errors"
+ Log.info { "Raven #{VERSION} ready to catch errors" }
else
- logger.info "Raven #{VERSION} configured not to capture errors: #{configuration.error_messages}"
+ Log.info {
+ "Raven #{VERSION} configured not to capture errors: #{configuration.error_messages}"
+ }
end
end
@@ -129,7 +129,9 @@ module Raven
# ```
def capture(obj : Exception | String, **options, &block)
unless configuration.capture_allowed?(obj)
- logger.debug "'#{obj}' excluded from capture: #{configuration.error_messages}"
+ Log.debug {
+ "'#{obj}' excluded from capture: #{configuration.error_messages}"
+ }
return false
end
default_options = {
@@ -149,7 +151,7 @@ module Raven
begin
async.call(event)
rescue ex
- logger.error "Async event sending failed: #{ex.message}"
+ Log.error(exception: ex) { "Async event sending failed" }
send_event(event, hint)
end
else
diff --git a/src/raven/integrations/kernel/at_exit.cr b/src/raven/integrations/kernel/at_exit.cr
index b189a39..b946136 100644
--- a/src/raven/integrations/kernel/at_exit.cr
+++ b/src/raven/integrations/kernel/at_exit.cr
@@ -1,6 +1,6 @@
at_exit do |_, exception|
if exception
- Raven.logger.debug "Caught a post-mortem exception: #{exception.inspect}"
+ Raven::Log.debug(exception: exception) { "Caught a post-mortem exception" }
Raven.capture(exception)
end
end
diff --git a/src/raven/integrations/kernel/log.cr b/src/raven/integrations/kernel/log.cr
new file mode 100644
index 0000000..2095292
--- /dev/null
+++ b/src/raven/integrations/kernel/log.cr
@@ -0,0 +1,52 @@
+require "log"
+require "log/json"
+require "../shared/breadcrumb_log_helper"
+
+module Raven
+ # ```
+ # require "raven"
+ # require "raven/integrations/kernel/log"
+ # ```
+ #
+ # `::Log::Backend` recording logged messages as breadcrumbs.
+ #
+ # ```
+ # Log.setup do |c|
+ # c.bind "*", :info, Log::IOBackend.new
+ # c.bind "*", :info, Raven::BreadcrumbLogBackend.new
+ # end
+ # ```
+ class BreadcrumbLogBackend < ::Log::Backend
+ include Raven::BreadcrumbLogHelper
+
+ private BREADCRUMB_LEVELS = {
+ :trace => :debug,
+ :debug => :debug,
+ :info => :info,
+ :notice => :info,
+ :warn => :warning,
+ :error => :error,
+ :fatal => :critical,
+ } of ::Log::Severity => Raven::Breadcrumb::Severity
+
+ def write(entry : ::Log::Entry)
+ message = entry.message
+ if ex = entry.exception
+ message += " -- (#{ex.class}): #{ex.message || "n/a"}"
+ end
+
+ level = BREADCRUMB_LEVELS[entry.severity]?
+
+ data = entry.context.extend(entry.data.to_h)
+ data = data.empty? ? nil : JSON.parse(data.to_json).as_h
+
+ record_breadcrumb(
+ message,
+ level,
+ entry.timestamp,
+ entry.source,
+ data,
+ )
+ end
+ end
+end
diff --git a/src/raven/integrations/kernel/logger.cr b/src/raven/integrations/kernel/logger.cr
index c3e9da9..dc1ef5a 100644
--- a/src/raven/integrations/kernel/logger.cr
+++ b/src/raven/integrations/kernel/logger.cr
@@ -1,47 +1,25 @@
require "logger"
-
-module Raven::Breadcrumb::Logger
- private LOGGER_BREADCRUMB_LEVELS = {
- ::Logger::DEBUG => Severity::DEBUG,
- ::Logger::INFO => Severity::INFO,
- ::Logger::WARN => Severity::WARNING,
- ::Logger::ERROR => Severity::ERROR,
- ::Logger::FATAL => Severity::CRITICAL,
- }
-
- protected def self.ignored_logger?(progname)
- Raven.configuration.exclude_loggers.includes?(progname)
- end
-
- protected def record_breadcrumb(severity, datetime, progname, message)
- return if Logger.ignored_logger?(progname)
- Raven.breadcrumbs.record do |crumb|
- crumb.timestamp = datetime
- crumb.level = LOGGER_BREADCRUMB_LEVELS[severity]?
- crumb.category = progname || "logger"
- crumb.message = message
- end
- end
-end
+require "../shared/breadcrumb_log_helper"
class Logger
- include Raven::Breadcrumb::Logger
+ include Raven::BreadcrumbLogHelper
- protected def self.deansify(message)
- case message
- when Nil then nil
- when String then message.gsub(/\x1b[^m]*m/, "")
- when Exception then deansify(message.message)
- else deansify(message.to_s)
- end
- end
+ private BREADCRUMB_LEVELS = {
+ :debug => :debug,
+ :info => :info,
+ :warn => :warning,
+ :error => :error,
+ :fatal => :critical,
+ } of ::Logger::Severity => Raven::Breadcrumb::Severity
private def write(severity, datetime, progname, message)
+ level = BREADCRUMB_LEVELS[severity]?
+
record_breadcrumb(
- severity,
+ message,
+ level,
datetime,
- self.class.deansify(progname),
- self.class.deansify(message),
+ progname,
)
previous_def
end
diff --git a/src/raven/integrations/shared/breadcrumb_log_helper.cr b/src/raven/integrations/shared/breadcrumb_log_helper.cr
new file mode 100644
index 0000000..137f21c
--- /dev/null
+++ b/src/raven/integrations/shared/breadcrumb_log_helper.cr
@@ -0,0 +1,23 @@
+module Raven
+ module BreadcrumbLogHelper
+ protected def deansify(message) : String?
+ case message
+ when Nil then nil
+ when String then message.gsub(/\x1b[^m]*m/, "")
+ when Exception then deansify(message.message)
+ else deansify(message.to_s)
+ end
+ end
+
+ protected def record_breadcrumb(message, level, timestamp, source, data = nil)
+ return if Raven.configuration.ignored_logger?(source)
+ Raven.breadcrumbs.record do |crumb|
+ crumb.message = deansify(message).presence
+ crumb.level = level if level
+ crumb.timestamp = timestamp if timestamp
+ crumb.category = source.presence || "logger"
+ crumb.data = data if data
+ end
+ end
+ end
+end
diff --git a/src/raven/log.cr b/src/raven/log.cr
new file mode 100644
index 0000000..23eb8e0
--- /dev/null
+++ b/src/raven/log.cr
@@ -0,0 +1,5 @@
+require "log"
+
+module Raven
+ Log = ::Log.for(self)
+end
diff --git a/src/raven/logger.cr b/src/raven/logger.cr
deleted file mode 100644
index 4d4ca1b..0000000
--- a/src/raven/logger.cr
+++ /dev/null
@@ -1,13 +0,0 @@
-require "logger"
-
-module Raven
- class Logger < ::Logger
- PROGNAME = "sentry"
-
- def self.new(*args, **options)
- super.tap do |logger|
- logger.progname = PROGNAME
- end
- end
- end
-end
diff --git a/src/raven/transport.cr b/src/raven/transport.cr
index f3eabb1..5380df1 100644
--- a/src/raven/transport.cr
+++ b/src/raven/transport.cr
@@ -1,7 +1,6 @@
module Raven
abstract class Transport
property configuration : Configuration
- delegate logger, to: configuration
def initialize(@configuration)
end
diff --git a/src/raven/transports/http.cr b/src/raven/transports/http.cr
index 1867219..cb0cbe6 100644
--- a/src/raven/transports/http.cr
+++ b/src/raven/transports/http.cr
@@ -42,7 +42,7 @@ module Raven
str << "/api/embed/error-page/?"
str << params
end
- logger.debug "HTTP Transport connecting to #{path}"
+ Log.debug { "HTTP Transport connecting to #{path}" }
client = build_client
client.post(path, form: data, headers: headers).tap do |response|
@@ -52,7 +52,7 @@ module Raven
def send_event(auth_header, data, **options)
unless configuration.capture_allowed?
- logger.debug "Event not sent: #{configuration.error_messages}"
+ Log.debug { "Event not sent: #{configuration.error_messages}" }
return
end
@@ -66,7 +66,7 @@ module Raven
if configuration.encoding.gzip?
headers["Content-Encoding"] = "gzip"
end
- logger.debug "HTTP Transport connecting to #{configuration.dsn}"
+ Log.debug { "HTTP Transport connecting to #{configuration.dsn}" }
client = build_client
client.post("#{path}/api/#{project_id}/store/", headers, data).tap do |response|
diff --git a/src/raven/version.cr b/src/raven/version.cr
index aef1cfa..ba68bff 100644
--- a/src/raven/version.cr
+++ b/src/raven/version.cr
@@ -1,3 +1,3 @@
module Raven
- VERSION = "1.6.0"
+ VERSION = {{ `shards version "#{__DIR__}"`.chomp.stringify }}
end