-
-
Notifications
You must be signed in to change notification settings - Fork 505
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
Prevent starting Vernier in nested transactions #2528
base: master
Are you sure you want to change the base?
Prevent starting Vernier in nested transactions #2528
Conversation
f4e835c
to
2b53dd7
Compare
|
||
unless @hub.profiler_running? | ||
@profiler = @configuration.profiler_class.new(@configuration) | ||
end |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This thing right here is the heart of the fix, if I remove this conditional the spec I added easily reproduces the crash from the issue:
Failures:
1) Sentry transactions / profiler starts profiler just once inside nested transactions
Failure/Error: @stack_table_hash ||= profile._stack_table.to_h
NoMethodError:
undefined method `_stack_table' for nil
# ./lib/sentry/vernier/output.rb:85:in `stack_table_hash'
# ./lib/sentry/vernier/output.rb:57:in `frames'
# ./lib/sentry/vernier/output.rb:22:in `to_h'
# ./lib/sentry/vernier/profiler.rb:100:in `to_hash'
# ./lib/sentry/transaction_event.rb:65:in `populate_profile'
# ./lib/sentry/transaction_event.rb:40:in `initialize'
# ./lib/sentry/client.rb:174:in `new'
# ./lib/sentry/client.rb:174:in `event_from_transaction'
# ./lib/sentry/transaction.rb:267:in `finish'
# ./spec/sentry/transactions/profiler_spec.rb:35:in `block (3 levels) in <top (required)>'
# ./spec/sentry/transactions/profiler_spec.rb:18:in `block (2 levels) in <top (required)>'
# /usr/local/rvm/gems/default/gems/rspec-retry-0.6.2/lib/rspec/retry.rb:124:in `block in run'
# /usr/local/rvm/gems/default/gems/rspec-retry-0.6.2/lib/rspec/retry.rb:110:in `run'
# /usr/local/rvm/gems/default/gems/rspec-retry-0.6.2/lib/rspec_ext/rspec_ext.rb:12:in `run_with_retry'
# /usr/local/rvm/gems/default/gems/rspec-retry-0.6.2/lib/rspec/retry.rb:37:in `block (2 levels) in setup'
Finished in 0.02769 seconds (files took 0.20007 seconds to load)
1 example, 1 failure
Failed examples:
rspec ./spec/sentry/transactions/profiler_spec.rb:17 # Sentry transactions / profiler starts profiler just once inside nested transactions
Codecov ReportAttention: Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## master #2528 +/- ##
==========================================
+ Coverage 69.32% 69.41% +0.08%
==========================================
Files 125 125
Lines 4721 4738 +17
==========================================
+ Hits 3273 3289 +16
- Misses 1448 1449 +1
|
@@ -257,7 +261,7 @@ def finish(hub: nil, end_timestamp: nil) | |||
@name = UNLABELD_NAME | |||
end | |||
|
|||
@profiler.stop | |||
@hub.stop_profiler!(self) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Given that the hub is responsible for starting a profiler, making this change actually felt like an improvement. Transactions are coupled to hub anyway.
I think more of profiler related logic can actually be moved out of |
Something like this? diff --git a/sentry-ruby/lib/sentry/hub.rb b/sentry-ruby/lib/sentry/hub.rb
index 788e8902..a1343831 100644
--- a/sentry-ruby/lib/sentry/hub.rb
+++ b/sentry-ruby/lib/sentry/hub.rb
@@ -23,8 +23,17 @@ module Sentry
def start_profiler!(transaction)
MUTEX.synchronize do
- transaction.start_profiler!
- @current_profiler[transaction.__id__] = transaction.profiler
+ return if !@current_profiler.empty?
+ profiler = configuration.profiler_class.new(configuration)
+ profiler.set_initial_sample_decision(transaction.sampled)
+ profiler.start
+ @current_profiler[transaction.__id__] = profiler
+ end
+ end
+
+ def profiler_for(transaction)
+ MUTEX.synchronize do
+ @current_profiler[transaction.__id__]
end
end
@@ -34,12 +43,6 @@ module Sentry
end
end
- def profiler_running?
- MUTEX.synchronize do
- !@current_profiler.empty?
- end
- end
-
def new_from_top
Hub.new(current_client, current_scope)
end
diff --git a/sentry-ruby/lib/sentry/transaction.rb b/sentry-ruby/lib/sentry/transaction.rb
index 6fc2524b..8fc077e5 100644
--- a/sentry-ruby/lib/sentry/transaction.rb
+++ b/sentry-ruby/lib/sentry/transaction.rb
@@ -56,10 +56,6 @@ module Sentry
# @return [Hash]
attr_reader :contexts
- # The Profiler instance for this transaction.
- # @return [Profiler]
- attr_reader :profiler
-
def initialize(
hub:,
name: nil,
@@ -86,10 +82,6 @@ module Sentry
@contexts = {}
@measurements = {}
- unless @hub.profiler_running?
- @profiler = @configuration.profiler_class.new(@configuration)
- end
-
init_span_recorder
end
@@ -300,13 +292,16 @@ module Sentry
@contexts[key] = value
end
+ # The Profiler instance for this transaction.
+ # @return [Profiler]
+ def profiler
+ @hub.profiler_for(self)
+ end
+
# Start the profiler.
# @return [void]
def start_profiler!
- return unless profiler
-
- profiler.set_initial_sample_decision(sampled)
- profiler.start
+ @hub.start_profiler!(self)
end
# These are high cardinality and thus bad
diff --git a/sentry-ruby/spec/sentry/transactions/profiler_spec.rb b/sentry-ruby/spec/sentry/transactions/profiler_spec.rb
index 78bb385b..fb1efd7b 100644
--- a/sentry-ruby/spec/sentry/transactions/profiler_spec.rb
+++ b/sentry-ruby/spec/sentry/transactions/profiler_spec.rb
@@ -21,8 +21,6 @@ RSpec.describe Sentry, 'transactions / profiler', when: [:vernier_installed?, :r
ProfilerTest::Bar.bar
- expect(Sentry.get_current_hub.profiler_running?).to be(true)
-
expect(parent_transaction.profiler).to_not be_nil
expect(nested_transaction.profiler).to be_nil |
not for now since the profile is currently linked to the transaction. |
df9f4b3
to
4d00641
Compare
I'd prefer to not make any more changes than the minimum to get the issue fixed, especially that hub doesn't expose a method for finishing a transaction, and all code that finishes transactions uses Transaction#finish, so it's the best place to stop profiling. |
4d00641
to
b359bfd
Compare
I agree with both but I don't think my patch would change them? We can also just pass down the profiler to the transaction through a keyword argument if we want to actually retain a reference to it there. Also, under the current implementation there's a gap between If we only create the profiler in |
ok let's take a step back, is this
|
Fixes #2525
I suspect this will also help with #2457