Skip to content

Commit

Permalink
RUBY-587 new TT segments are only added to trace if the limit has not…
Browse files Browse the repository at this point in the history
… been reached
  • Loading branch information
gnarg committed Mar 7, 2012
1 parent caed421 commit 726f733
Show file tree
Hide file tree
Showing 3 changed files with 48 additions and 32 deletions.
15 changes: 12 additions & 3 deletions lib/new_relic/agent/transaction_sample_builder.rb
Expand Up @@ -9,31 +9,40 @@ module Agent
# accessed by any other thread so no need for synchronization.
class TransactionSampleBuilder
attr_reader :current_segment, :sample
attr_accessor :segment_limit

include NewRelic::CollectionHelper

def initialize(time=Time.now)
@sample = NewRelic::TransactionSample.new(time.to_f)
@sample_start = time.to_f
@current_segment = @sample.root_segment
@segment_limit = NewRelic::Control.instance.fetch('transaction_tracer', {}) \
.fetch('limit_segments', 4000)
end

def sample_id
@sample.sample_id
end

def ignored?
@ignore || @sample.params[:path].nil?
end

def ignore_transaction
@ignore = true
end

def trace_entry(metric_name, time)
segment = @sample.create_segment(time.to_f - @sample_start, metric_name)
@current_segment.add_called_segment(segment)
@current_segment = segment
if @sample.count_segments < @segment_limit
segment = @sample.create_segment(time.to_f - @sample_start, metric_name)
@current_segment.add_called_segment(segment)
@current_segment = segment
end
end

def trace_exit(metric_name, time)
return unless @sample.count_segments < @segment_limit
if metric_name != @current_segment.metric_name
fail "unbalanced entry/exit: #{metric_name} != #{@current_segment.metric_name}"
end
Expand Down
8 changes: 7 additions & 1 deletion test/new_relic/agent/transaction_sample_builder_test.rb
Expand Up @@ -159,7 +159,13 @@ def test_parallel_first_level_segments
@builder.finish_trace(Time.now.to_f)
validate_builder
end


def test_trace_should_not_record_more_than_segment_limit
@builder.segment_limit = 3
8.times {|i| build_segment i.to_s }
assert_equal 3, @builder.sample.count_segments
end

def validate_builder(check_names = true)
validate_segment @builder.sample.root_segment, check_names
end
Expand Down
57 changes: 29 additions & 28 deletions test/new_relic/agent/transaction_sampler_test.rb
Expand Up @@ -264,7 +264,6 @@ def test_store_slowest_sample_new_is_slowest
assert_equal(new_sample, @sampler.instance_variable_get('@slowest_sample'))
end


def test_store_slowest_sample_not_slowest
old_sample = mock('old_sample')
new_sample = mock('new_sample')
Expand Down Expand Up @@ -297,7 +296,7 @@ def test_slowest_sample_slower_sample
new_sample.expects(:duration).returns(1.0)
assert_equal(true, @sampler.slowest_sample?(old_sample, new_sample))
end

def test_truncate_samples_no_samples
@sampler.instance_eval { @max_samples = 10 }
@sampler.instance_eval { @samples = [] }
Expand Down Expand Up @@ -527,7 +526,6 @@ def test_add_random_sample_to_not_active
assert_equal([], result, "should not add samples to the array when harvest count is not moduli sampling rate")
end


def test_add_random_sample_to_activated
@sampler.instance_eval { @random_sampling = true }
sample = mock('sample')
Expand All @@ -554,7 +552,6 @@ def test_add_random_sample_to_sampling_rate_zero
assert_equal([], result, "should not add the sample to the array")
end


def test_add_samples_to_no_data
result = []
slow_threshold = 2.0
Expand Down Expand Up @@ -620,8 +617,7 @@ def test_add_samples_to_keep_older_slower_sample
@sampler.expects(:add_random_sample_to).with([slower_sample])
assert_equal([slower_sample], @sampler.add_samples_to(result, slow_threshold))
end



def test_keep_force_persist
sample1 = mock('regular')
sample1.stubs(:duration).returns(10)
Expand All @@ -636,8 +632,7 @@ def test_keep_force_persist
assert_equal 2, result.length
assert_equal sample1, result[0]
assert_equal sample2, result[1]
end

end

def test_start_builder_default
Thread.current[:record_tt] = true
Expand Down Expand Up @@ -679,7 +674,6 @@ def test_clear_builder
# generally usefully so

def test_multiple_samples

run_sample_trace
run_sample_trace
run_sample_trace
Expand Down Expand Up @@ -752,7 +746,6 @@ def test_sample_id
# sample traces, for example. It's unfortunate, but we can't
# reliably turn off GC on all versions of ruby under test
def test_harvest_slowest

run_sample_trace
run_sample_trace
run_sample_trace { sleep 0.1 }
Expand All @@ -775,9 +768,7 @@ def test_harvest_slowest
assert((new_slowest.duration >= 0.15), "Slowest duration must be >= 0.15, but was: #{new_slowest.duration.inspect}")
end


def test_prepare_to_send

run_sample_trace { sleep 0.002 }
sample = @sampler.harvest(nil, 0)[0]

Expand All @@ -804,7 +795,6 @@ def test_multithread
end

def test_sample_with_parallel_paths

assert_equal 0, @sampler.scope_depth

@sampler.notice_first_scope_push Time.now.to_f
Expand All @@ -830,7 +820,6 @@ def test_sample_with_parallel_paths
end

def test_double_scope_stack_empty

@sampler.notice_first_scope_push Time.now.to_f
@sampler.notice_transaction "/path", nil, {}
@sampler.notice_push_scope "a"
Expand All @@ -845,7 +834,6 @@ def test_double_scope_stack_empty


def test_record_sql_off

@sampler.notice_first_scope_push Time.now.to_f

Thread::current[:record_sql] = false
Expand All @@ -869,8 +857,8 @@ def test_stack_trace__sql
assert segment[:sql]
assert segment[:backtrace]
end

def test_stack_trace__scope

@sampler.stack_trace_threshold = 0
t = Time.now
@sampler.notice_first_scope_push t.to_f
Expand All @@ -881,7 +869,6 @@ def test_stack_trace__scope
end

def test_nil_stacktrace

@sampler.stack_trace_threshold = 2

@sampler.notice_first_scope_push Time.now.to_f
Expand All @@ -895,7 +882,6 @@ def test_nil_stacktrace
end

def test_big_sql

@sampler.notice_first_scope_push Time.now.to_f

sql = "SADJKHASDHASD KAJSDH ASKDH ASKDHASDK JASHD KASJDH ASKDJHSAKDJHAS DKJHSADKJSAH DKJASHD SAKJDH SAKDJHS"
Expand All @@ -913,9 +899,7 @@ def test_big_sql
assert sql.length <= 16384
end


def test_segment_obfuscated

@sampler.notice_first_scope_push Time.now.to_f
@sampler.notice_push_scope "foo"

Expand All @@ -930,7 +914,6 @@ def test_segment_obfuscated
@sampler.notice_pop_scope "foo"
end


def test_param_capture
[true, false].each do |capture|
NewRelic::Control.instance.stubs(:capture_params).returns(capture)
Expand All @@ -943,23 +926,41 @@ def test_param_capture
assert_equal (capture) ? 1 : 0, tt.params[:request_params].length
end
end



def test_should_not_collect_segments_beyond_limit
NewRelic::Control.instance.merge_options('transaction_tracer' => {
'limit_segments' => 3,
})
@sampler.configure!
run_sample_trace do
@sampler.notice_push_scope 'a1'
@sampler.notice_sql("SELECT * FROM sandwiches WHERE bread = 'hallah'", nil, 0)
@sampler.notice_push_scope 'a11'
@sampler.notice_sql("SELECT * FROM sandwiches WHERE bread = 'semolina'", nil, 0)
@sampler.notice_pop_scope "a11"
@sampler.notice_pop_scope "a1"
end
assert_equal 3, @sampler.samples[0].count_segments
NewRelic::Control.instance.merge_options('transaction_tracer' => {
'limit_segments' => 4000,
})
end

private
def run_sample_trace(&proc)

def run_sample_trace
@sampler.notice_first_scope_push Time.now.to_f
@sampler.notice_transaction '/path', nil, {}
@sampler.notice_push_scope "a"
@sampler.notice_sql("SELECT * FROM sandwiches WHERE bread = 'wheat'", nil, 0)
@sampler.notice_push_scope "ab"
@sampler.notice_sql("SELECT * FROM sandwiches WHERE bread = 'white'", nil, 0)
proc.call if proc
yield if block_given?
@sampler.notice_pop_scope "ab"
@sampler.notice_push_scope "lew"
@sampler.notice_push_scope "ac"
@sampler.notice_sql("SELECT * FROM sandwiches WHERE bread = 'french'", nil, 0)
@sampler.notice_pop_scope "lew"
@sampler.notice_pop_scope "ac"
@sampler.notice_pop_scope "a"
@sampler.notice_scope_empty
end

end

0 comments on commit 726f733

Please sign in to comment.