Skip to content

Remove config.capture_exception_frame_locals #2306

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

Open
wants to merge 3 commits into
base: 6.0-dev
Choose a base branch
from
Open
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
7 changes: 7 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,10 @@
## Unreleased (6.0.0)

### Breaking Changes

- Remove `config.async` ([#1894](https://github.com/getsentry/sentry-ruby/pull/1894))
- Remove `config.capture_exception_frame_locals` ([#2306](https://github.com/getsentry/sentry-ruby/pull/2306))

## Unreleased

### Features
Original file line number Diff line number Diff line change
@@ -5,7 +5,7 @@
config.traces_sample_rate = 1.0 # set a float between 0.0 and 1.0 to enable performance monitoring
config.dsn = 'https://2fb45f003d054a7ea47feb45898f7649@o447951.ingest.sentry.io/5434472'
config.release = `git branch --show-current`
config.capture_exception_frame_locals = true
config.include_local_variables = true
# you can use the pre-defined job for the async callback
#
# config.async = lambda do |event, hint|
Original file line number Diff line number Diff line change
@@ -5,7 +5,7 @@
config.traces_sample_rate = 1.0 # set a float between 0.0 and 1.0 to enable performance monitoring
config.dsn = 'https://2fb45f003d054a7ea47feb45898f7649@o447951.ingest.sentry.io/5434472'
config.release = `git branch --show-current`
config.capture_exception_frame_locals = true
config.include_local_variables = true
# you can use the pre-defined job for the async callback
#
# config.async = lambda do |event, hint|
7 changes: 1 addition & 6 deletions sentry-rails/lib/sentry/rails/active_job.rb
Original file line number Diff line number Diff line change
@@ -23,12 +23,7 @@ def record(job, &block)
Sentry.with_scope do |scope|
begin
scope.set_transaction_name(job.class.name, source: :task)
transaction =
if job.is_a?(::Sentry::SendEventJob)
nil
else
Sentry.start_transaction(name: scope.transaction_name, source: scope.transaction_source, op: OP_NAME)
end
transaction = Sentry.start_transaction(name: scope.transaction_name, source: scope.transaction_source, op: OP_NAME)

scope.set_span(transaction) if transaction

2 changes: 1 addition & 1 deletion sentry-rails/spec/dummy/test_rails_app/app.rb
Original file line number Diff line number Diff line change
@@ -82,7 +82,7 @@ def self.name
config.transport.transport_class = Sentry::DummyTransport
# for sending events synchronously
config.background_worker_threads = 0
config.capture_exception_frame_locals = true
config.include_local_variables = true
yield(config, app) if block_given?
end
end
44 changes: 0 additions & 44 deletions sentry-rails/spec/sentry/rails/activejob_spec.rb
Original file line number Diff line number Diff line change
@@ -230,50 +230,6 @@ def perform
event = transport.events.last.to_json_compatible
expect(event.dig("exception", "values", 0, "type")).to eq("ZeroDivisionError")
end

context "and in user-defined reporting job too" do
before do
Sentry.configuration.async = lambda do |event, hint|
UserDefinedReportingJob.perform_now(event, hint)
end
end

class UserDefinedReportingJob < ActiveJob::Base
def perform(event, hint)
Post.find(0)
rescue
raise ActiveJob::DeserializationError
end
end

it "doesn't cause infinite loop because of excluded exceptions" do
expect do
DeserializationErrorJob.perform_now
end.to raise_error(ActiveJob::DeserializationError, /divided by 0/)
end
end

context "and in customized SentryJob too" do
before do
class CustomSentryJob < ::Sentry::SendEventJob
def perform(event, hint)
raise "Not excluded exception"
rescue
raise ActiveJob::DeserializationError
end
end

Sentry.configuration.async = lambda do |event, hint|
CustomSentryJob.perform_now(event, hint)
end
end

it "doesn't cause infinite loop" do
expect do
DeserializationErrorJob.perform_now
end.to raise_error(ActiveJob::DeserializationError, /divided by 0/)
end
end
end

context 'using rescue_from' do
103 changes: 0 additions & 103 deletions sentry-rails/spec/sentry/send_event_job_spec.rb

This file was deleted.

2 changes: 1 addition & 1 deletion sentry-ruby/examples/crons/README.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# sentry-ruby Crons example

Crons monitoring allows you to track that certain that should be performed
on a certain schedule are indeed performed on time and without errors. See
on a certain schedule are indeed performed on time and without errors. See
[documentation](https://docs.sentry.io/platforms/ruby/crons/) for more details.

This example project has a few rake tasks that manually send monitor check-ins
5 changes: 1 addition & 4 deletions sentry-ruby/lib/sentry/background_worker.rb
Original file line number Diff line number Diff line change
@@ -24,10 +24,7 @@ def initialize(configuration)
@shutdown_callback = nil

@executor =
if configuration.async
log_debug("config.async is set, BackgroundWorker is disabled")
Concurrent::ImmediateExecutor.new
elsif @number_of_threads == 0
if @number_of_threads == 0
log_debug("config.background_worker_threads is set to 0, all events will be sent synchronously")
Concurrent::ImmediateExecutor.new
else
37 changes: 5 additions & 32 deletions sentry-ruby/lib/sentry/client.rb
Original file line number Diff line number Diff line change
@@ -53,8 +53,7 @@ def capture_event(event, scope, hint = {})
return
end

event_type = event.is_a?(Event) ? event.type : event["type"]
data_category = Envelope::Item.data_category(event_type)
data_category = Envelope::Item.data_category(event.type)
event = scope.apply_to_event(event, hint)

if event.nil?
@@ -63,9 +62,7 @@ def capture_event(event, scope, hint = {})
return
end

if async_block = configuration.async
dispatch_async_event(async_block, event, hint)
elsif configuration.background_worker_threads != 0 && hint.fetch(:background, true)
if configuration.background_worker_threads != 0 && hint.fetch(:background, true)
queued = dispatch_background_event(event, hint)
transport.record_lost_event(:queue_overflow, data_category) unless queued
else
@@ -166,10 +163,9 @@ def event_from_transaction(transaction)

# @!macro send_event
def send_event(event, hint = nil)
event_type = event.is_a?(Event) ? event.type : event["type"]
data_category = Envelope::Item.data_category(event_type)
data_category = Envelope::Item.data_category(event.type)

if event_type != TransactionEvent::TYPE && configuration.before_send
if event.type != TransactionEvent::TYPE && configuration.before_send
event = configuration.before_send.call(event, hint)

if event.nil?
@@ -179,7 +175,7 @@ def send_event(event, hint = nil)
end
end

if event_type == TransactionEvent::TYPE && configuration.before_send_transaction
if event.type == TransactionEvent::TYPE && configuration.before_send_transaction
event = configuration.before_send_transaction.call(event, hint)

if event.nil?
@@ -254,28 +250,5 @@ def dispatch_background_event(event, hint)
send_event(event, hint)
end
end

def dispatch_async_event(async_block, event, hint)
# We have to convert to a JSON-like hash, because background job
# processors (esp ActiveJob) may not like weird types in the event hash

event_hash =
begin
event.to_json_compatible
rescue => e
log_error("Converting #{event.type} (#{event.event_id}) to JSON compatible hash failed", e, debug: configuration.debug)
return
end

if async_block.arity == 2
hint = JSON.parse(JSON.generate(hint))
async_block.call(event_hash, hint)
else
async_block.call(event_hash)
end
rescue => e
log_error("Async #{event_hash["type"]} sending failed", e, debug: configuration.debug)
send_event(event, hint)
end
end
end
36 changes: 0 additions & 36 deletions sentry-ruby/lib/sentry/configuration.rb
Original file line number Diff line number Diff line change
@@ -25,13 +25,6 @@ class Configuration
# @return [Regexp, nil]
attr_accessor :app_dirs_pattern

# Provide an object that responds to `call` to send events asynchronously.
# E.g.: lambda { |event| Thread.new { Sentry.send_event(event) } }
#
# @deprecated It will be removed in the next major release. Please read https://github.com/getsentry/sentry-ruby/issues/1522 for more information
# @return [Proc, nil]
attr_reader :async

# to send events in a non-blocking way, sentry-ruby has its own background worker
# by default, the worker holds a thread pool that has [the number of processors] threads
# but you can configure it with this configuration option
@@ -73,7 +66,6 @@ class Configuration
# @example
# config.before_send = lambda do |event, hint|
# # skip ZeroDivisionError exceptions
# # note: hint[:exception] would be a String if you use async callback
# if hint[:exception].is_a?(ZeroDivisionError)
# nil
# else
@@ -159,18 +151,6 @@ class Configuration
# @return [Boolean, String]
attr_accessor :spotlight

# @deprecated Use {#include_local_variables} instead.
alias_method :capture_exception_frame_locals, :include_local_variables

# @deprecated Use {#include_local_variables=} instead.
def capture_exception_frame_locals=(value)
log_warn <<~MSG
`capture_exception_frame_locals` is now deprecated in favor of `include_local_variables`.
MSG

self.include_local_variables = value
end

# You may provide your own LineCache for matching paths with source files.
# This may be useful if you need to get source code from places other than the disk.
# @see LineCache
@@ -409,22 +389,6 @@ def release=(value)
@release = value
end

def async=(value)
check_callable!("async", value)

log_warn <<~MSG

sentry-ruby now sends events asynchronously by default with its background worker (supported since 4.1.0).
The `config.async` callback has become redundant while continuing to cause issues.
(The problems of `async` are detailed in https://github.com/getsentry/sentry-ruby/issues/1522)

Therefore, we encourage you to remove it and let the background worker take care of async job sending.
It's deprecation is planned in the next major release (6.0), which is scheduled around the 3rd quarter of 2022.
MSG

@async = value
end

def breadcrumbs_logger=(logger)
loggers =
if logger.is_a?(Array)
5 changes: 1 addition & 4 deletions sentry-ruby/lib/sentry/transport.rb
Original file line number Diff line number Diff line change
@@ -127,10 +127,7 @@ def envelope_from_event(event)
sent_at: Sentry.utc_now.iso8601
}

if event.is_a?(Event) && event.dynamic_sampling_context
envelope_headers[:trace] = event.dynamic_sampling_context
end

envelope_headers[:trace] = event.dynamic_sampling_context if event.dynamic_sampling_context
envelope = Envelope.new(envelope_headers)

envelope.add_item(
16 changes: 0 additions & 16 deletions sentry-ruby/spec/sentry/background_worker_spec.rb
Original file line number Diff line number Diff line change
@@ -10,22 +10,6 @@
end

describe "#initialize" do
context "when config.async is set" do
before do
configuration.async = proc { }
end

it "initializes a background_worker with ImmediateExecutor" do
worker = described_class.new(configuration)

expect(string_io.string).to match(
/config.async is set, BackgroundWorker is disabled/
)

expect(worker.instance_variable_get(:@executor)).to be_a(Concurrent::ImmediateExecutor)
end
end

context "when config.background_worker_threads is set" do
it "initializes a background worker with correct number of threads and queue size" do
worker = described_class.new(configuration)
142 changes: 4 additions & 138 deletions sentry-ruby/spec/sentry/client/event_sending_spec.rb
Original file line number Diff line number Diff line change
@@ -52,84 +52,6 @@
end
end

context 'with config.async set' do
let(:async_block) do
lambda do |event|
subject.send_event(event)
end
end

around do |example|
prior_async = configuration.async
configuration.async = async_block
example.run
configuration.async = prior_async
end

it "executes the given block" do
expect(async_block).to receive(:call).and_call_original

returned = subject.capture_event(event, scope)

expect(returned).to be_a(Sentry::ErrorEvent)
expect(subject.transport.events.first).to eq(event.to_json_compatible)
end

it "doesn't call the async block if not allow sending events" do
allow(configuration).to receive(:sending_allowed?).and_return(false)

expect(async_block).not_to receive(:call)

returned = subject.capture_event(event, scope)

expect(returned).to eq(nil)
end

context "with to json conversion failed" do
let(:logger) { ::Logger.new(string_io) }
let(:string_io) { StringIO.new }
let(:event) { subject.event_from_message("Bad data '\x80\xF8'") }

it "does not mask the exception" do
configuration.logger = logger

subject.capture_event(event, scope)

expect(string_io.string).to include("Converting event (#{event.event_id}) to JSON compatible hash failed: source sequence is illegal/malformed utf-8")
end
end

context "with nil as value (the legacy way to disable it)" do
let(:async_block) { nil }

it "doesn't cause any issue" do
returned = subject.capture_event(event, scope, { background: false })

expect(returned).to be_a(Sentry::ErrorEvent)
expect(subject.transport.events.first).to eq(event)
end
end

context "with 2 arity block" do
let(:async_block) do
lambda do |event, hint|
event["tags"]["hint"] = hint
subject.send_event(event)
end
end

it "serializes hint and supplies it as the second argument" do
expect(configuration.async).to receive(:call).and_call_original

returned = subject.capture_event(event, scope, { foo: "bar" })

expect(returned).to be_a(Sentry::ErrorEvent)
event = subject.transport.events.first
expect(event.dig("tags", "hint")).to eq({ "foo" => "bar" })
end
end
end

context "with background_worker enabled (default)" do
before do
Sentry.background_worker = Sentry::BackgroundWorker.new(configuration)
@@ -207,22 +129,12 @@

it "applies before_send callback before sending the event" do
configuration.before_send = lambda do |event, _hint|
if event.is_a?(Sentry::Event)
event.tags[:called] = true
else
event["tags"]["called"] = true
end

event.tags[:called] = true
event
end

subject.send_event(event)

if event.is_a?(Sentry::Event)
expect(event.tags[:called]).to eq(true)
else
expect(event["tags"]["called"]).to eq(true)
end
expect(event.tags[:called]).to eq(true)
end

it "doesn't apply before_send_transaction to Event" do
@@ -239,10 +151,6 @@
let(:event) { event_object }
end

it_behaves_like "Event in send_event" do
let(:event) { event_object.to_json_compatible }
end

shared_examples "TransactionEvent in send_event" do
it "sends data through the transport" do
subject.send_event(event)
@@ -258,32 +166,18 @@

it "applies before_send_transaction callback before sending the event" do
configuration.before_send_transaction = lambda do |event, _hint|
if event.is_a?(Sentry::TransactionEvent)
event.tags[:called] = true
else
event["tags"]["called"] = true
end

event.tags[:called] = true
event
end

subject.send_event(event)

if event.is_a?(Sentry::Event)
expect(event.tags[:called]).to eq(true)
else
expect(event["tags"]["called"]).to eq(true)
end
expect(event.tags[:called]).to eq(true)
end
end

it_behaves_like "TransactionEvent in send_event" do
let(:event) { transaction_event_object }
end

it_behaves_like "TransactionEvent in send_event" do
let(:event) { transaction_event_object.to_json_compatible }
end
end

describe "integrated error handling testing with HTTPTransport" do
@@ -303,12 +197,6 @@
let(:event) { subject.event_from_message(message) }

describe "#capture_event" do
around do |example|
prior_async = configuration.async
example.run
configuration.async = prior_async
end

context "when scope.apply_to_event returns nil" do
before do
scope.add_event_processor do |event, hint|
@@ -396,28 +284,6 @@
expect(string_io.string).to match(/Event sending failed: TypeError/)
end
end

context "when config.async causes error" do
before do
expect(subject).to receive(:send_event)
end

it "swallows Redis related error and send the event synchronizely" do
configuration.async = ->(_, _) { raise Redis::ConnectionError }

subject.capture_event(event, scope)

expect(string_io.string).to match(/Async event sending failed: Redis::ConnectionError/)
end

it "swallows and logs the exception" do
configuration.async = ->(_, _) { raise TypeError }

subject.capture_event(event, scope)

expect(string_io.string).to match(/Async event sending failed: TypeError/)
end
end
end

describe "#send_event" do
36 changes: 0 additions & 36 deletions sentry-ruby/spec/sentry/configuration_spec.rb
Original file line number Diff line number Diff line change
@@ -1,29 +1,6 @@
require 'spec_helper'

RSpec.describe Sentry::Configuration do
describe "#capture_exception_frame_locals" do
it "passes/received the value to #include_local_variables" do
subject.capture_exception_frame_locals = true
expect(subject.include_local_variables).to eq(true)
expect(subject.capture_exception_frame_locals).to eq(true)

subject.capture_exception_frame_locals = false
expect(subject.include_local_variables).to eq(false)
expect(subject.capture_exception_frame_locals).to eq(false)
end

it "prints deprecation message when being assigned" do
string_io = StringIO.new
subject.logger = Logger.new(string_io)

subject.capture_exception_frame_locals = true

expect(string_io.string).to include(
"WARN -- sentry: `capture_exception_frame_locals` is now deprecated in favor of `include_local_variables`."
)
end
end

describe "#csp_report_uri" do
it "returns nil if the dsn is not present" do
expect(subject.csp_report_uri).to eq(nil)
@@ -289,24 +266,11 @@
end
end

context 'configuring for async' do
it 'should be configurable to send events async' do
subject.async = ->(_e) { :ok }
expect(subject.async.call('event')).to eq(:ok)
end
end

it 'raises error when setting release to anything other than String' do
subject.release = "foo"
expect { subject.release = 42 }.to raise_error(ArgumentError, "expect the argument to be a String or NilClass, got Integer (42)")
end

it 'raises error when setting async to anything other than callable or nil' do
subject.async = -> { }
subject.async = nil
expect { subject.async = true }.to raise_error(ArgumentError, "async must be callable (or nil to disable)")
end

it 'raises error when setting before_send to anything other than callable or nil' do
subject.before_send = -> { }
subject.before_send = nil
Original file line number Diff line number Diff line change
@@ -14,7 +14,7 @@
let(:configuration) { Sentry.configuration }
let(:client) { Sentry.get_current_client }
let(:data) do
subject.envelope_from_event(client.event_from_message("foobarbaz").to_hash).to_s
subject.envelope_from_event(client.event_from_message("foobarbaz")).to_s
end

subject { Sentry::HTTPTransport.new(configuration) }
2 changes: 1 addition & 1 deletion sentry-ruby/spec/sentry/transport/http_transport_spec.rb
Original file line number Diff line number Diff line change
@@ -14,7 +14,7 @@
let(:event) { client.event_from_message("foobarbaz") }
let(:fake_time) { Time.now }
let(:data) do
subject.serialize_envelope(subject.envelope_from_event(event.to_hash)).first
subject.serialize_envelope(subject.envelope_from_event(event)).first
end

subject { client.transport }
Original file line number Diff line number Diff line change
@@ -18,7 +18,7 @@
let(:client) { Sentry::Client.new(configuration) }
let(:event) { client.event_from_message("foobarbaz") }
let(:data) do
subject.serialize_envelope(subject.envelope_from_event(event.to_hash)).first
subject.serialize_envelope(subject.envelope_from_event(event)).first
end

subject { described_class.new(configuration) }
18 changes: 0 additions & 18 deletions sentry-ruby/spec/sentry/transport_spec.rb
Original file line number Diff line number Diff line change
@@ -387,18 +387,6 @@
expect(io.string).to match(/Sending envelope with items \[event\]/)
end

context "when the event hash has string keys" do
let(:envelope) { subject.envelope_from_event(event.to_json_compatible) }

it "deletes the event's breadcrumbs and sends it" do
expect(subject).to receive(:send_data)

subject.send_envelope(envelope)

expect(io.string).to match(/Sending envelope with items \[event\]/)
end
end

context "if it's still oversized" do
before do
1000.times do |i|
@@ -450,12 +438,6 @@
expect(subject.send_event(event)).to eq(event)
end

it "sends Event hash" do
expect(subject).not_to receive(:failed_send)

expect(subject.send_event(event.to_json_compatible)).to eq(event.to_json_compatible)
end

it "logs correct message" do
expect(subject.send_event(event)).to eq(event)