newrelic_rpm 3.16.0.318 → 3.16.1.320

Sign up to get free protection for your applications and to get access to all the features.
Files changed (77) hide show
  1. checksums.yaml +4 -4
  2. data/.travis.yml +13 -4
  3. data/CHANGELOG +41 -2
  4. data/lib/new_relic/agent/database.rb +15 -4
  5. data/lib/new_relic/agent/database/explain_plan_helpers.rb +2 -1
  6. data/lib/new_relic/agent/datastores.rb +13 -13
  7. data/lib/new_relic/agent/datastores/metric_helper.rb +33 -2
  8. data/lib/new_relic/agent/datastores/mongo/metric_translator.rb +3 -9
  9. data/lib/new_relic/agent/error_collector.rb +2 -2
  10. data/lib/new_relic/agent/instrumentation/active_record.rb +9 -19
  11. data/lib/new_relic/agent/instrumentation/active_record_helper.rb +2 -6
  12. data/lib/new_relic/agent/instrumentation/active_record_subscriber.rb +49 -40
  13. data/lib/new_relic/agent/instrumentation/data_mapper.rb +29 -23
  14. data/lib/new_relic/agent/instrumentation/grape.rb +20 -11
  15. data/lib/new_relic/agent/instrumentation/memcache.rb +8 -10
  16. data/lib/new_relic/agent/instrumentation/mongo.rb +25 -16
  17. data/lib/new_relic/agent/instrumentation/mongodb_command_subscriber.rb +14 -19
  18. data/lib/new_relic/agent/method_tracer_helpers.rb +4 -8
  19. data/lib/new_relic/agent/sql_sampler.rb +14 -1
  20. data/lib/new_relic/agent/stats_engine/metric_stats.rb +18 -0
  21. data/lib/new_relic/agent/supported_versions.rb +2 -3
  22. data/lib/new_relic/agent/traced_method_stack.rb +7 -1
  23. data/lib/new_relic/agent/transaction.rb +6 -0
  24. data/lib/new_relic/agent/transaction/abstract_segment.rb +73 -0
  25. data/lib/new_relic/agent/transaction/datastore_segment.rb +49 -0
  26. data/lib/new_relic/agent/transaction/segment.rb +30 -0
  27. data/lib/new_relic/agent/transaction/tracing.rb +53 -0
  28. data/lib/new_relic/agent/transaction_sampler.rb +8 -1
  29. data/lib/new_relic/noticed_error.rb +3 -1
  30. data/lib/new_relic/version.rb +1 -1
  31. data/lib/sequel/extensions/newrelic_instrumentation.rb +22 -15
  32. data/lib/sequel/plugins/newrelic_instrumentation.rb +4 -3
  33. data/newrelic_rpm.gemspec +1 -9
  34. data/test/environments/lib/environments/runner.rb +6 -4
  35. data/test/environments/norails/Gemfile +9 -3
  36. data/test/environments/rails21/Gemfile +6 -3
  37. data/test/environments/rails22/Gemfile +5 -2
  38. data/test/environments/rails23/Gemfile +1 -1
  39. data/test/environments/rails30/Gemfile +1 -1
  40. data/test/environments/rails31/Gemfile +1 -1
  41. data/test/environments/rails32/Gemfile +1 -1
  42. data/test/environments/rails40/Gemfile +2 -2
  43. data/test/environments/rails41/Gemfile +2 -2
  44. data/test/environments/rails42/Gemfile +2 -2
  45. data/test/environments/rails50/Gemfile +2 -2
  46. data/test/helpers/mongo_metric_builder.rb +3 -4
  47. data/test/multiverse/lib/multiverse/shell_utils.rb +27 -0
  48. data/test/multiverse/lib/multiverse/suite.rb +47 -2
  49. data/test/multiverse/suites/active_record/Envfile +1 -1
  50. data/test/multiverse/suites/delayed_job/Envfile +2 -0
  51. data/test/multiverse/suites/grape/grape_versioning_test.rb +55 -1
  52. data/test/multiverse/suites/grape/grape_versioning_test_api.rb +61 -3
  53. data/test/multiverse/suites/mongo/mongo_instrumentation_test.rb +18 -0
  54. data/test/multiverse/suites/rails/Envfile +3 -3
  55. data/test/multiverse/suites/rails/error_tracing_test.rb +2 -2
  56. data/test/multiverse/suites/sequel/Envfile +7 -0
  57. data/test/multiverse/suites/sequel/sequel_extension_test.rb +1 -1
  58. data/test/new_relic/agent/database_test.rb +9 -0
  59. data/test/new_relic/agent/datastores/metric_helper_test.rb +76 -43
  60. data/test/new_relic/agent/datastores/mongo/metric_translator_test.rb +67 -117
  61. data/test/new_relic/agent/datastores_test.rb +17 -0
  62. data/test/new_relic/agent/error_collector_test.rb +21 -5
  63. data/test/new_relic/agent/instrumentation/active_record_helper_test.rb +40 -45
  64. data/test/new_relic/agent/instrumentation/active_record_subscriber_test.rb +2 -3
  65. data/test/new_relic/agent/instrumentation/mongodb_command_subscriber_test.rb +2 -0
  66. data/test/new_relic/agent/method_tracer_test.rb +54 -52
  67. data/test/new_relic/agent/mock_scope_listener.rb +4 -1
  68. data/test/new_relic/agent/sql_sampler_test.rb +15 -0
  69. data/test/new_relic/agent/transaction/abstract_segment_test.rb +94 -0
  70. data/test/new_relic/agent/transaction/datastore_segment_test.rb +99 -0
  71. data/test/new_relic/agent/transaction/segment_test.rb +53 -0
  72. data/test/new_relic/agent/transaction/tracing_test.rb +121 -0
  73. data/test/new_relic/agent/transaction_sampler_test.rb +13 -0
  74. data/test/new_relic/noticed_error_test.rb +7 -0
  75. data/test/performance/suites/datastores.rb +59 -0
  76. data/test/performance/suites/trace_execution_scoped.rb +8 -9
  77. metadata +13 -46
@@ -133,30 +133,36 @@ module NewRelic
133
133
  name = self.class.name
134
134
  end
135
135
 
136
- metrics = NewRelic::Agent::Datastores::MetricHelper.metrics_for(
137
- DATA_MAPPER,
138
- metric_operation,
139
- name)
140
-
141
- NewRelic::Agent::MethodTracer.trace_execution_scoped(metrics) do
142
- begin
143
- self.send("#{method_name}_without_newrelic", *args, &blk)
144
- rescue ::DataObjects::SQLError => e
145
- e.uri.gsub!(PASSWORD_REGEX, AMPERSAND) if e.uri.include?(PASSWORD_PARAM)
146
-
147
- strategy = NewRelic::Agent::Database.record_sql_method(:slow_sql)
148
- case strategy
149
- when :obfuscated
150
- adapter_name = self.respond_to?(:options) ? self.options[:adapter] : self.repository.adapter.uri.scheme
151
- statement = NewRelic::Agent::Database::Statement.new(e.query, :adapter => adapter_name)
152
- obfuscated_sql = NewRelic::Agent::Database.obfuscate_sql(statement)
153
- e.instance_variable_set(:@query, obfuscated_sql)
154
- when :off
155
- e.instance_variable_set(:@query, nil)
156
- end
157
-
158
- raise
136
+ segment = NewRelic::Agent::Transaction.start_datastore_segment DATA_MAPPER, metric_operation, name
137
+
138
+ begin
139
+ self.send("#{method_name}_without_newrelic", *args, &blk)
140
+ rescue ::DataObjects::SQLError => e
141
+ e.uri.gsub!(PASSWORD_REGEX, AMPERSAND) if e.uri.include?(PASSWORD_PARAM)
142
+
143
+ strategy = NewRelic::Agent::Database.record_sql_method(:slow_sql)
144
+ case strategy
145
+ when :obfuscated
146
+ adapter_name = if self.respond_to?(:options)
147
+ self.options[:adapter]
148
+ else
149
+ if self.repository.adapter.respond_to?(:options)
150
+ self.repository.adapter.options[:adapter]
151
+ else
152
+ # DataMapper < 0.10.0
153
+ self.repository.adapter.uri.scheme
154
+ end
155
+ end
156
+ statement = NewRelic::Agent::Database::Statement.new(e.query, :adapter => adapter_name)
157
+ obfuscated_sql = NewRelic::Agent::Database.obfuscate_sql(statement)
158
+ e.instance_variable_set(:@query, obfuscated_sql)
159
+ when :off
160
+ e.instance_variable_set(:@query, nil)
159
161
  end
162
+
163
+ raise
164
+ ensure
165
+ segment.finish
160
166
  end
161
167
  end
162
168
  end
@@ -11,43 +11,51 @@ module NewRelic
11
11
  extend self
12
12
 
13
13
  API_ENDPOINT = 'api.endpoint'.freeze
14
+ API_VERSION = 'api.version'.freeze
14
15
  FORMAT_REGEX = /\(\/?\.[\:\w]*\)/.freeze # either :format (< 0.12.0) or .ext (>= 0.12.0)
15
16
  VERSION_REGEX = /:version(\/|$)/.freeze
16
17
  EMPTY_STRING = ''.freeze
17
18
  MIN_VERSION = VersionNumber.new("0.2.0")
19
+ PIPE_STRING = '|'.freeze
18
20
 
19
- def handle_transaction(endpoint, class_name)
21
+ def handle_transaction(endpoint, class_name, version)
20
22
  return unless endpoint && route = endpoint.route
21
- name_transaction(route, class_name)
23
+ name_transaction(route, class_name, version)
22
24
  capture_params(endpoint)
23
25
  end
24
26
 
25
- def name_transaction(route, class_name)
26
- txn_name = name_for_transaction(route, class_name)
27
+ def name_transaction(route, class_name, version)
28
+ txn_name = name_for_transaction(route, class_name, version)
27
29
  node_name = "Middleware/Grape/#{class_name}/call"
28
30
  Transaction.set_default_transaction_name(txn_name, :grape, node_name)
29
31
  end
30
32
 
31
33
  if defined?(Grape::VERSION) && VersionNumber.new(::Grape::VERSION) >= VersionNumber.new("0.16.0")
32
- def name_for_transaction(route, class_name)
34
+ def name_for_transaction(route, class_name, version)
33
35
  action_name = route.path.sub(FORMAT_REGEX, EMPTY_STRING)
34
36
  method_name = route.request_method
37
+ version ||= route.version
35
38
 
36
- if route.version
39
+ # defaulting does not set rack.env['api.version'] and route.version may return Array
40
+ #
41
+ version = version.join(PIPE_STRING) if Array === version
42
+
43
+ if version
37
44
  action_name = action_name.sub(VERSION_REGEX, EMPTY_STRING)
38
- "#{class_name}-#{route.version}#{action_name} (#{method_name})"
45
+ "#{class_name}-#{version}#{action_name} (#{method_name})"
39
46
  else
40
47
  "#{class_name}#{action_name} (#{method_name})"
41
48
  end
42
49
  end
43
50
  else
44
- def name_for_transaction(route, class_name)
51
+ def name_for_transaction(route, class_name, version)
45
52
  action_name = route.route_path.sub(FORMAT_REGEX, EMPTY_STRING)
46
53
  method_name = route.route_method
54
+ version ||= route.route_version
47
55
 
48
- if route.route_version
56
+ if version
49
57
  action_name = action_name.sub(VERSION_REGEX, EMPTY_STRING)
50
- "#{class_name}-#{route.route_version}#{action_name} (#{method_name})"
58
+ "#{class_name}-#{version}#{action_name} (#{method_name})"
51
59
  else
52
60
  "#{class_name}#{action_name} (#{method_name})"
53
61
  end
@@ -108,7 +116,8 @@ DependencyDetection.defer do
108
116
  ensure
109
117
  begin
110
118
  endpoint = env[::NewRelic::Agent::Instrumentation::GrapeInstrumentation::API_ENDPOINT]
111
- ::NewRelic::Agent::Instrumentation::GrapeInstrumentation.handle_transaction(endpoint, self.class.name)
119
+ version = env[::NewRelic::Agent::Instrumentation::GrapeInstrumentation::API_VERSION]
120
+ ::NewRelic::Agent::Instrumentation::GrapeInstrumentation.handle_transaction(endpoint, self.class.name, version)
112
121
  rescue => e
113
122
  ::NewRelic::Agent.logger.warn("Error in Grape instrumentation", e)
114
123
  end
@@ -40,17 +40,15 @@ module NewRelic
40
40
  alias_method method_name_without, method_name
41
41
 
42
42
  define_method method_name do |*args, &block|
43
- metrics = Datastores::MetricHelper.metrics_for("Memcached", method_name)
44
-
45
- NewRelic::Agent::MethodTracer.trace_execution_scoped(metrics) do
46
- t0 = Time.now
47
- begin
48
- send method_name_without, *args, &block
49
- ensure
50
- if NewRelic::Agent.config[:capture_memcache_keys]
51
- NewRelic::Agent.instance.transaction_sampler.notice_nosql(args.first.inspect, (Time.now - t0).to_f) rescue nil
52
- end
43
+ segment = NewRelic::Agent::Transaction.start_datastore_segment "Memcached", method_name
44
+ begin
45
+ send method_name_without, *args, &block
46
+ ensure
47
+ if NewRelic::Agent.config[:capture_memcache_keys]
48
+ NewRelic::Agent.instance.transaction_sampler.notice_nosql(args.first.inspect,
49
+ (Time.now - segment.start_time).to_f) rescue nil
53
50
  end
51
+ segment.finish
54
52
  end
55
53
  end
56
54
 
@@ -65,23 +65,30 @@ DependencyDetection.defer do
65
65
  NewRelic::Agent.logger.debug("Exception during Mongo statement gathering", e)
66
66
  end
67
67
 
68
- def new_relic_generate_metrics(operation, payload = nil)
69
- payload ||= { :collection => self.name, :database => self.db.name }
70
- NewRelic::Agent::Datastores::Mongo::MetricTranslator.metrics_for(operation, payload)
68
+ def new_relic_default_payload
69
+ { :collection => self.name, :database => self.db.name }
71
70
  end
72
71
 
73
- def instrument_with_new_relic_trace(name, payload = {}, &block)
74
- metrics = new_relic_generate_metrics(name, payload)
72
+ def new_relic_start_segment name, payload
73
+ product = NewRelic::Agent::Datastores::Mongo::MetricTranslator::MONGO_PRODUCT_NAME
74
+ op_and_col = NewRelic::Agent::Datastores::Mongo::MetricTranslator.operation_and_collection_for name, payload
75
+ if op_and_col
76
+ NewRelic::Agent::Transaction.start_datastore_segment product, *op_and_col
77
+ end
78
+ end
75
79
 
76
- trace_execution_scoped(metrics) do
77
- t0 = Time.now
80
+ def instrument_with_new_relic_trace(name, payload = {}, &block)
81
+ segment = new_relic_start_segment name, payload
78
82
 
83
+ begin
79
84
  result = NewRelic::Agent.disable_all_tracing do
80
85
  instrument_without_new_relic_trace(name, payload, &block)
81
86
  end
82
87
 
83
- new_relic_notice_statement(t0, payload, name)
88
+ new_relic_notice_statement(segment.start_time, payload, name) if segment
84
89
  result
90
+ ensure
91
+ segment.finish if segment
85
92
  end
86
93
  end
87
94
 
@@ -93,16 +100,17 @@ DependencyDetection.defer do
93
100
  def instrument_save
94
101
  ::Mongo::Collection.class_eval do
95
102
  def save_with_new_relic_trace(doc, opts = {}, &block)
96
- metrics = new_relic_generate_metrics(:save)
97
- trace_execution_scoped(metrics) do
98
- t0 = Time.now
103
+ segment = new_relic_start_segment :save, new_relic_default_payload
99
104
 
105
+ begin
100
106
  result = NewRelic::Agent.disable_all_tracing do
101
107
  save_without_new_relic_trace(doc, opts, &block)
102
108
  end
103
109
 
104
- new_relic_notice_statement(t0, doc, :save)
110
+ new_relic_notice_statement(segment.start_time, doc, :save) if segment
105
111
  result
112
+ ensure
113
+ segment.finish if segment
106
114
  end
107
115
  end
108
116
 
@@ -114,10 +122,9 @@ DependencyDetection.defer do
114
122
  def instrument_ensure_index
115
123
  ::Mongo::Collection.class_eval do
116
124
  def ensure_index_with_new_relic_trace(spec, opts = {}, &block)
117
- metrics = new_relic_generate_metrics(:ensureIndex)
118
- trace_execution_scoped(metrics) do
119
- t0 = Time.now
125
+ segment = new_relic_start_segment :ensureIndex, new_relic_default_payload
120
126
 
127
+ begin
121
128
  result = NewRelic::Agent.disable_all_tracing do
122
129
  ensure_index_without_new_relic_trace(spec, opts, &block)
123
130
  end
@@ -131,8 +138,10 @@ DependencyDetection.defer do
131
138
  spec.dup
132
139
  end
133
140
 
134
- new_relic_notice_statement(t0, spec, :ensureIndex)
141
+ new_relic_notice_statement(segment.start_time, spec, :ensureIndex) if segment
135
142
  result
143
+ ensure
144
+ segment.finish if segment
136
145
  end
137
146
  end
138
147
 
@@ -7,13 +7,13 @@ module NewRelic
7
7
  module Agent
8
8
  module Instrumentation
9
9
  class MongodbCommandSubscriber
10
-
11
10
  MONGODB = 'MongoDB'.freeze
12
11
  COLLECTION = "collection".freeze
13
12
 
14
13
  def started(event)
15
14
  begin
16
15
  return unless NewRelic::Agent.tl_is_execution_traced?
16
+ segments[event.operation_id] = start_segment event
17
17
  operations[event.operation_id] = event
18
18
  rescue Exception => e
19
19
  log_notification_error('started', e)
@@ -25,14 +25,9 @@ module NewRelic
25
25
  state = NewRelic::Agent::TransactionState.tl_get
26
26
  return unless state.is_execution_traced?
27
27
  started_event = operations.delete(event.operation_id)
28
-
29
- base, *other_metrics = metrics(started_event)
30
-
31
- NewRelic::Agent.instance.stats_engine.tl_record_scoped_and_unscoped_metrics(
32
- base, other_metrics, event.duration
33
- )
34
-
35
- notice_nosql_statement(state, started_event, base, event.duration)
28
+ segment = segments.delete(event.operation_id)
29
+ notice_nosql_statement(state, started_event, segment.name, event.duration)
30
+ segment.finish
36
31
  rescue Exception => e
37
32
  log_notification_error('completed', e)
38
33
  end
@@ -43,6 +38,12 @@ module NewRelic
43
38
 
44
39
  private
45
40
 
41
+ def start_segment event
42
+ NewRelic::Agent::Transaction.start_datastore_segment(
43
+ MONGODB, event.command_name, collection(event)
44
+ )
45
+ end
46
+
46
47
  def collection(event)
47
48
  event.command[COLLECTION] || event.command[:collection] || event.command.values.first
48
49
  end
@@ -60,6 +61,10 @@ module NewRelic
60
61
  @operations ||= {}
61
62
  end
62
63
 
64
+ def segments
65
+ @segments ||= {}
66
+ end
67
+
63
68
  def generate_statement(event)
64
69
  NewRelic::Agent::Datastores::Mongo::EventFormatter.format(
65
70
  event.command_name,
@@ -69,19 +74,9 @@ module NewRelic
69
74
  end
70
75
 
71
76
  def notice_nosql_statement(state, event, metric, duration)
72
- end_time = Time.now.to_f
73
-
74
- stack = state.traced_method_stack
75
-
76
- # enter transaction trace node
77
- frame = stack.push_frame(state, :mongo_db, end_time - duration)
78
-
79
77
  NewRelic::Agent.instance.transaction_sampler.notice_nosql_statement(
80
78
  generate_statement(event), duration
81
79
  )
82
-
83
- # exit transaction trace node
84
- stack.pop_frame(state, frame, metric, end_time)
85
80
  end
86
81
  end
87
82
  end
@@ -74,19 +74,15 @@ module NewRelic
74
74
  first_name = metric_names.shift
75
75
  return yield unless first_name
76
76
 
77
- additional_metrics_callback = options[:additional_metrics_callback]
78
- start_time = Time.now.to_f
79
- expected_scope = trace_execution_scoped_header(state, start_time)
77
+ segment = NewRelic::Agent::Transaction.start_segment first_name, metric_names
78
+ segment.record_metrics = options.fetch(:metric, true)
80
79
 
81
80
  begin
82
- result = yield
83
- metric_names += Array(additional_metrics_callback.call) if additional_metrics_callback
84
- result
81
+ yield
85
82
  ensure
86
- trace_execution_scoped_footer(state, start_time, first_name, metric_names, expected_scope, options)
83
+ segment.finish
87
84
  end
88
85
  end
89
-
90
86
  end
91
87
  end
92
88
  end
@@ -140,7 +140,7 @@ module NewRelic
140
140
  # @api public
141
141
  # @deprecated Use {Datastores.notice_sql} instead.
142
142
  #
143
- def notice_sql(sql, metric_name, config, duration, state=nil, explainer=nil, binds=[], name="SQL") #THREAD_LOCAL_ACCESS sometimes
143
+ def notice_sql(sql, metric_name, config, duration, state=nil, explainer=nil, binds=nil, name=nil) #THREAD_LOCAL_ACCESS sometimes
144
144
  state ||= TransactionState.tl_get
145
145
  data = state.sql_sampler_transaction_data
146
146
  return unless data
@@ -154,6 +154,19 @@ module NewRelic
154
154
  end
155
155
  end
156
156
 
157
+ def notice_sql_statement(statement, metric_name, duration)
158
+ state ||= TransactionState.tl_get
159
+ data = state.sql_sampler_transaction_data
160
+ return unless data
161
+
162
+ if state.is_sql_recorded?
163
+ if duration > Agent.config[:'slow_sql.explain_threshold']
164
+ backtrace = caller.join("\n")
165
+ data.sql_data << SlowSql.new(statement, metric_name, duration, backtrace)
166
+ end
167
+ end
168
+ end
169
+
157
170
  def merge!(sql_traces)
158
171
  @samples_lock.synchronize do
159
172
  sql_traces.each do |trace|
@@ -66,6 +66,15 @@ module NewRelic
66
66
  end
67
67
  end
68
68
 
69
+ # This aliasing was introduced for T2 so that MetricsStats and
70
+ # TransactionStates have the same interface for recording
71
+ # unscoped metrics. The tl_ version should be used outside of the
72
+ # segment api.
73
+ #
74
+ # @api private
75
+ #
76
+ alias_method :record_unscoped, :tl_record_unscoped_metrics
77
+
69
78
  # Like tl_record_unscoped_metrics, but records a scoped metric as well.
70
79
  #
71
80
  # This is an internal method, subject to change at any time. Client apps
@@ -108,6 +117,15 @@ module NewRelic
108
117
  end
109
118
  end
110
119
 
120
+ # This aliasing was introduced for T2 so that MetricsStats and
121
+ # TransactionStates have the same interface for recording
122
+ # scoped metrics. The tl_ version should be used outside of the
123
+ # segment api.
124
+ #
125
+ # @api private
126
+ #
127
+ alias_method :record_scoped_and_unscoped, :tl_record_scoped_and_unscoped_metrics
128
+
111
129
  # This method is deprecated and not thread safe, and should not be used
112
130
  # by any new client code.
113
131
  #
@@ -11,7 +11,7 @@ module NewRelic
11
11
  {
12
12
  :type => :ruby,
13
13
  :name => "MRI",
14
- :supported => ["1.8.7", "1.9.2", "1.9.3", "2.0.0", "~> 2.1.0", "~> 2.2.0" ],
14
+ :supported => ["1.8.7", "1.9.2", "1.9.3", "2.0.0", "~> 2.1.0", "~> 2.2.0", "~> 2.3.0"],
15
15
  :url => "https://www.ruby-lang.org",
16
16
  :feed => "https://www.ruby-lang.org/en/feeds/news.rss",
17
17
  :notes => [
@@ -85,8 +85,7 @@ module NewRelic
85
85
  :rails =>
86
86
  {
87
87
  :type => :web,
88
- :supported => ["~>2.1.0", "~>2.2.0", "~>2.3.0", "~3.0.0", "~>3.1.0", "~>3.2.0", "~>4.0.0", "~>4.1.0", "~>4.2.0"],
89
- :experimental=> ["5.0.0.rc1"],
88
+ :supported => ["~>2.1.0", "~>2.2.0", "~>2.3.0", "~3.0.0", "~>3.1.0", "~>3.2.0", "~>4.0.0", "~>4.1.0", "~>4.2.0", "~> 5.0.0"],
90
89
  :deprecated => ["~>2.0.0"],
91
90
  :url => "https://rubygems.org/gems/rails",
92
91
  :feed => "https://rubygems.org/gems/rails/versions.atom",
@@ -37,6 +37,12 @@ module NewRelic
37
37
  frame
38
38
  end
39
39
 
40
+ def push_segment state, segment
41
+ transaction_sampler.notice_push_frame(state, segment.start_time) if sampler_enabled?
42
+ @stack.push segment
43
+ segment
44
+ end
45
+
40
46
  # Pops a frame off the transaction stack - this updates the transaction
41
47
  # sampler that we've finished execution of a traced method.
42
48
  #
@@ -50,7 +56,7 @@ module NewRelic
50
56
  note_children_time(frame, time, deduct_call_time_from_parent)
51
57
 
52
58
  transaction_sampler.notice_pop_frame(state, name, time) if sampler_enabled?
53
- frame.name = name
59
+ frame.name = name if frame.is_a? TracedMethodFrame
54
60
  frame
55
61
  end
56
62
 
@@ -8,6 +8,7 @@ require 'new_relic/agent/transaction_metrics'
8
8
  require 'new_relic/agent/method_tracer_helpers'
9
9
  require 'new_relic/agent/transaction/attributes'
10
10
  require 'new_relic/agent/transaction/request_attributes'
11
+ require 'new_relic/agent/transaction/tracing'
11
12
 
12
13
  module NewRelic
13
14
  module Agent
@@ -16,6 +17,7 @@ module NewRelic
16
17
  #
17
18
  # @api public
18
19
  class Transaction
20
+ include Tracing
19
21
 
20
22
  # for nested transactions
21
23
  SUBTRANSACTION_PREFIX = 'Nested/'.freeze
@@ -41,6 +43,9 @@ module NewRelic
41
43
  TRACE_OPTIONS_SCOPED = { :metric => true, :scoped_metric => true }.freeze
42
44
  TRACE_OPTIONS_UNSCOPED = { :metric => true, :scoped_metric => false }.freeze
43
45
 
46
+ # reference to the transaction state managing this transaction
47
+ attr_accessor :state
48
+
44
49
  # A Time instance for the start time, never nil
45
50
  attr_accessor :start_time
46
51
 
@@ -128,6 +133,7 @@ module NewRelic
128
133
  def self.start_new_transaction(state, category, options)
129
134
  txn = Transaction.new(category, options)
130
135
  state.reset(txn)
136
+ txn.state = state
131
137
  txn.start(state)
132
138
  txn
133
139
  end