newrelic_rpm 3.12.1.298 → 3.13.0.299

Sign up to get free protection for your applications and to get access to all the features.
Files changed (69) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG +37 -0
  3. data/GUIDELINES_FOR_CONTRIBUTING.md +1 -1
  4. data/LICENSE +4 -4
  5. data/README.md +3 -3
  6. data/lib/new_relic/agent/agent.rb +27 -0
  7. data/lib/new_relic/agent/commands/thread_profiler_session.rb +2 -0
  8. data/lib/new_relic/agent/configuration/default_source.rb +51 -1
  9. data/lib/new_relic/agent/configuration/high_security_source.rb +1 -0
  10. data/lib/new_relic/agent/database.rb +12 -2
  11. data/lib/new_relic/agent/database/obfuscator.rb +4 -3
  12. data/lib/new_relic/agent/datastores.rb +1 -1
  13. data/lib/new_relic/agent/datastores/redis.rb +131 -0
  14. data/lib/new_relic/agent/error_collector.rb +2 -2
  15. data/lib/new_relic/agent/instrumentation/action_controller_subscriber.rb +1 -0
  16. data/lib/new_relic/agent/instrumentation/controller_instrumentation.rb +1 -0
  17. data/lib/new_relic/agent/instrumentation/rails/action_controller.rb +2 -0
  18. data/lib/new_relic/agent/instrumentation/rails3/action_controller.rb +2 -0
  19. data/lib/new_relic/agent/instrumentation/rake.rb +170 -0
  20. data/lib/new_relic/agent/instrumentation/redis.rb +71 -0
  21. data/lib/new_relic/agent/instrumentation/sinatra.rb +1 -0
  22. data/lib/new_relic/agent/new_relic_service.rb +4 -0
  23. data/lib/new_relic/agent/sql_sampler.rb +14 -13
  24. data/lib/new_relic/agent/stats_engine/gc_profiler.rb +1 -0
  25. data/lib/new_relic/agent/transaction.rb +2 -0
  26. data/lib/new_relic/agent/transaction/attributes.rb +1 -1
  27. data/lib/new_relic/agent/transaction/trace.rb +2 -1
  28. data/lib/new_relic/agent/transaction/trace_node.rb +3 -2
  29. data/lib/new_relic/agent/transaction_sampler.rb +4 -15
  30. data/lib/new_relic/agent/transaction_state.rb +1 -0
  31. data/lib/new_relic/agent/vm/rubinius_vm.rb +27 -19
  32. data/lib/new_relic/language_support.rb +7 -0
  33. data/lib/new_relic/version.rb +2 -2
  34. data/lib/tasks/newrelic.rb +9 -0
  35. data/newrelic_rpm.gemspec +1 -1
  36. data/test/multiverse/README.md +1 -1
  37. data/test/multiverse/lib/multiverse/runner.rb +2 -2
  38. data/test/multiverse/suites/active_record/active_record_test.rb +6 -6
  39. data/test/multiverse/suites/agent_only/agent_attributes_test.rb +11 -0
  40. data/test/multiverse/suites/agent_only/script/warnings.rb +15 -0
  41. data/test/multiverse/suites/agent_only/start_up_test.rb +12 -4
  42. data/test/multiverse/suites/rake/Envfile +37 -0
  43. data/test/multiverse/suites/rake/Rakefile +54 -0
  44. data/test/multiverse/suites/rake/config/newrelic.yml +18 -0
  45. data/test/multiverse/suites/rake/multitask_test.rb +40 -0
  46. data/test/multiverse/suites/rake/rake_test.rb +209 -0
  47. data/test/multiverse/suites/rake/rake_test_helper.rb +66 -0
  48. data/test/multiverse/suites/rake/unsupported_rake_test.rb +19 -0
  49. data/test/multiverse/suites/redis/Envfile +14 -0
  50. data/test/multiverse/suites/redis/config/newrelic.yml +19 -0
  51. data/test/multiverse/suites/redis/redis_instrumentation_test.rb +212 -0
  52. data/test/multiverse/suites/redis/redis_unsupported_version_test.rb +20 -0
  53. data/test/multiverse/suites/resque/resque_marshalling_test.rb +9 -1
  54. data/test/new_relic/agent/agent_test.rb +78 -1
  55. data/test/new_relic/agent/configuration/high_security_source_test.rb +9 -0
  56. data/test/new_relic/agent/database/sql_obfuscation_test.rb +1 -3
  57. data/test/new_relic/agent/datastores/redis_test.rb +128 -0
  58. data/test/new_relic/agent/instrumentation/active_record_subscriber_test.rb +1 -1
  59. data/test/new_relic/agent/sql_sampler_test.rb +64 -52
  60. data/test/new_relic/agent/transaction/trace_node_test.rb +1 -1
  61. data/test/new_relic/agent/transaction/trace_test.rb +1 -1
  62. data/test/new_relic/agent/transaction_sampler_test.rb +9 -11
  63. data/test/new_relic/agent/vm/rubinius_vm_test.rb +1 -1
  64. data/test/new_relic/fake_collector.rb +18 -1
  65. data/test/new_relic/multiverse_helpers.rb +6 -0
  66. data/test/performance/suites/redis.rb +45 -0
  67. data/ui/views/newrelic/_sql_row.rhtml +1 -1
  68. data/ui/views/newrelic/explain_sql.rhtml +1 -1
  69. metadata +21 -5
@@ -3,6 +3,7 @@
3
3
  # See https://github.com/newrelic/rpm/blob/master/LICENSE for complete details.
4
4
  require 'new_relic/agent/instrumentation/evented_subscriber'
5
5
  require 'new_relic/agent/instrumentation/ignore_actions'
6
+ require 'new_relic/agent/parameter_filtering'
6
7
 
7
8
  module NewRelic
8
9
  module Agent
@@ -235,6 +235,7 @@ module NewRelic
235
235
  when :sinatra then ::NewRelic::Agent::Transaction::SINATRA_PREFIX
236
236
  when :middleware then ::NewRelic::Agent::Transaction::MIDDLEWARE_PREFIX
237
237
  when :grape then ::NewRelic::Agent::Transaction::GRAPE_PREFIX
238
+ when :rake then ::NewRelic::Agent::Transaction::RAKE_PREFIX
238
239
  else "#{category.to_s}/" # for internal use only
239
240
  end
240
241
  end
@@ -2,6 +2,8 @@
2
2
  # This file is distributed under New Relic's license terms.
3
3
  # See https://github.com/newrelic/rpm/blob/master/LICENSE for complete details.
4
4
 
5
+ require 'new_relic/agent/parameter_filtering'
6
+
5
7
  DependencyDetection.defer do
6
8
  @name = :rails21_view
7
9
 
@@ -2,6 +2,8 @@
2
2
  # This file is distributed under New Relic's license terms.
3
3
  # See https://github.com/newrelic/rpm/blob/master/LICENSE for complete details.
4
4
 
5
+ require 'new_relic/agent/parameter_filtering'
6
+
5
7
  module NewRelic
6
8
  module Agent
7
9
  module Instrumentation
@@ -0,0 +1,170 @@
1
+ # encoding: utf-8
2
+ # This file is distributed under New Relic's license terms.
3
+ # See https://github.com/newrelic/rpm/blob/master/LICENSE for complete details.
4
+
5
+ DependencyDetection.defer do
6
+ # Why not :rake? newrelic-rake used that name, so avoid conflicting
7
+ named :rake_instrumentation
8
+
9
+ depends_on do
10
+ defined?(::Rake) &&
11
+ ::NewRelic::Agent.config[:'disable_rake'] == false &&
12
+ ::NewRelic::Agent.config[:'rake.tasks'].any? &&
13
+ ::NewRelic::Agent::Instrumentation::RakeInstrumentation.should_install?
14
+ end
15
+
16
+ executes do
17
+ ::NewRelic::Agent.logger.info "Installing Rake instrumentation"
18
+ ::NewRelic::Agent.logger.debug "Instrumenting Rake tasks: #{::NewRelic::Agent.config[:'rake.tasks']}"
19
+ end
20
+
21
+ executes do
22
+ module Rake
23
+ class Task
24
+ alias_method :invoke_without_newrelic, :invoke
25
+
26
+ def invoke(*args)
27
+ unless NewRelic::Agent::Instrumentation::RakeInstrumentation.should_trace? name
28
+ return invoke_without_newrelic(*args)
29
+ end
30
+
31
+ begin
32
+ timeout = NewRelic::Agent.config[:'rake.connect_timeout']
33
+ NewRelic::Agent.instance.wait_on_connect(timeout)
34
+ rescue => e
35
+ NewRelic::Agent.logger.error("Exception in wait_on_connect", e)
36
+ return invoke_without_newrelic(*args)
37
+ end
38
+
39
+ NewRelic::Agent::Instrumentation::RakeInstrumentation.before_invoke_transaction(self)
40
+
41
+ state = NewRelic::Agent::TransactionState.tl_get
42
+ NewRelic::Agent::Transaction.wrap(state, "OtherTransaction/Rake/invoke/#{name}", :rake) do
43
+ NewRelic::Agent::Instrumentation::RakeInstrumentation.record_attributes(args, self)
44
+ invoke_without_newrelic(*args)
45
+ end
46
+ end
47
+ end
48
+ end
49
+ end
50
+ end
51
+
52
+ module NewRelic
53
+ module Agent
54
+ module Instrumentation
55
+ module RakeInstrumentation
56
+ def self.should_install?
57
+ is_supported_version? && safe_from_third_party_gem?
58
+ end
59
+
60
+ def self.is_supported_version?
61
+ ::NewRelic::VersionNumber.new(::Rake::VERSION) >= ::NewRelic::VersionNumber.new("10.0.0")
62
+ end
63
+
64
+ def self.safe_from_third_party_gem?
65
+ if NewRelic::LanguageSupport.bundled_gem?("newrelic-rake")
66
+ ::NewRelic::Agent.logger.info("Not installing New Relic supported Rake instrumentation because the third party newrelic-rake gem is present")
67
+ false
68
+ else
69
+ true
70
+ end
71
+ end
72
+
73
+ def self.should_trace?(name)
74
+ NewRelic::Agent.config[:'rake.tasks'].any? do |regex|
75
+ regex.match(name)
76
+ end
77
+ end
78
+
79
+ def self.instrument_execute_on_prereqs(task)
80
+ task.prerequisite_tasks.each do |child_task|
81
+ instrument_execute(child_task)
82
+ end
83
+ end
84
+
85
+ def self.instrument_execute(task)
86
+ return if task.instance_variable_get(:@__newrelic_instrumented_execute)
87
+
88
+ task.instance_variable_set(:@__newrelic_instrumented_execute, true)
89
+ task.instance_eval do
90
+ def execute(*args, &block)
91
+ NewRelic::Agent::MethodTracer.trace_execution_scoped("Rake/execute/#{self.name}") do
92
+ super
93
+ end
94
+ end
95
+ end
96
+
97
+ instrument_execute_on_prereqs(task)
98
+ end
99
+
100
+ def self.instrument_invoke_prerequisites_concurrently(task)
101
+ task.instance_eval do
102
+ def invoke_prerequisites_concurrently(*_)
103
+ NewRelic::Agent::MethodTracer.trace_execution_scoped("Rake/execute/multitask") do
104
+ prereqs = self.prerequisite_tasks.map(&:name).join(", ")
105
+ NewRelic::Agent::Datastores.notice_statement("Couldn't trace concurrent prereq tasks: #{prereqs}", 0)
106
+ super
107
+ end
108
+ end
109
+ end
110
+ end
111
+
112
+ def self.before_invoke_transaction(task)
113
+ ensure_at_exit
114
+
115
+ # We can't represent overlapping operations yet, so if multitask just
116
+ # make one node and annotate with prereq task names
117
+ if task.application.options.always_multitask
118
+ instrument_invoke_prerequisites_concurrently(task)
119
+ else
120
+ instrument_execute_on_prereqs(task)
121
+ end
122
+ rescue => e
123
+ NewRelic::Agent.logger.error("Error during Rake task invoke", e)
124
+ end
125
+
126
+ def self.record_attributes(args, task)
127
+ command_line = task.application.top_level_tasks.join(" ")
128
+ NewRelic::Agent::Transaction.merge_untrusted_agent_attributes({ :command => command_line },
129
+ :'job.rake',
130
+ NewRelic::Agent::AttributeFilter::DST_NONE)
131
+ named_args = name_the_args(args, task.arg_names)
132
+ unless named_args.empty?
133
+ NewRelic::Agent::Transaction.merge_untrusted_agent_attributes(named_args,
134
+ :'job.rake.args',
135
+ NewRelic::Agent::AttributeFilter::DST_NONE)
136
+ end
137
+ rescue => e
138
+ NewRelic::Agent.logger.error("Error during Rake task attribute recording.", e)
139
+ end
140
+
141
+ # Expects literal args passed to the task and array of task names
142
+ # If names are present without matching args, still sets them with nils
143
+ def self.name_the_args(args, names)
144
+ unfulfilled_names_length = names.length - args.length
145
+ if unfulfilled_names_length > 0
146
+ args.concat(Array.new(unfulfilled_names_length))
147
+ end
148
+
149
+ result = {}
150
+ args.zip(names).each_with_index do |(value, key), index|
151
+ result[key || index.to_s] = value
152
+ end
153
+ result
154
+ end
155
+
156
+ def self.ensure_at_exit
157
+ return if @installed_at_exit
158
+
159
+ at_exit do
160
+ # The agent's default at_exit might not default to installing, but
161
+ # if we are running an instrumented rake task, we always want it.
162
+ NewRelic::Agent.shutdown
163
+ end
164
+
165
+ @installed_at_exit = true
166
+ end
167
+ end
168
+ end
169
+ end
170
+ end
@@ -0,0 +1,71 @@
1
+ # encoding: utf-8
2
+ # This file is distributed under New Relic's license terms.
3
+ # See https://github.com/newrelic/rpm/blob/master/LICENSE for complete details.
4
+
5
+ require 'new_relic/agent/datastores'
6
+ require 'new_relic/agent/datastores/redis'
7
+
8
+ DependencyDetection.defer do
9
+ # Why not :redis? newrelic-redis used that name, so avoid conflicting
10
+ named :redis_instrumentation
11
+
12
+ depends_on do
13
+ defined? ::Redis
14
+ end
15
+
16
+ depends_on do
17
+ NewRelic::Agent.config[:disable_redis] == false
18
+ end
19
+
20
+ depends_on do
21
+ NewRelic::Agent::Datastores::Redis.is_supported_version? &&
22
+ NewRelic::Agent::Datastores::Redis.safe_from_third_party_gem?
23
+ end
24
+
25
+ executes do
26
+ NewRelic::Agent.logger.info 'Installing Redis Instrumentation'
27
+
28
+ Redis::Client.class_eval do
29
+ alias_method :call_without_new_relic, :call
30
+
31
+ def call(*args, &block)
32
+ operation = args[0][0]
33
+ statement = ::NewRelic::Agent::Datastores::Redis.format_command(args[0])
34
+
35
+ if statement
36
+ callback = Proc.new do |result, _, elapsed|
37
+ NewRelic::Agent::Datastores.notice_statement(statement, elapsed)
38
+ end
39
+ end
40
+
41
+ NewRelic::Agent::Datastores.wrap(NewRelic::Agent::Datastores::Redis::PRODUCT_NAME, operation, nil, callback) do
42
+ call_without_new_relic(*args, &block)
43
+ end
44
+ end
45
+
46
+ alias_method :call_pipeline_without_new_relic, :call_pipeline
47
+
48
+ def call_pipeline(*args, &block)
49
+ pipeline = args[0]
50
+ operation = pipeline.is_a?(::Redis::Pipeline::Multi) ? NewRelic::Agent::Datastores::Redis::MULTI_OPERATION : NewRelic::Agent::Datastores::Redis::PIPELINE_OPERATION
51
+ statement = ::NewRelic::Agent::Datastores::Redis.format_pipeline_commands(pipeline.commands)
52
+
53
+ callback = Proc.new do |result, _, elapsed|
54
+ NewRelic::Agent::Datastores.notice_statement(statement, elapsed)
55
+ end
56
+
57
+ NewRelic::Agent::Datastores.wrap(NewRelic::Agent::Datastores::Redis::PRODUCT_NAME, operation, nil, callback) do
58
+ call_pipeline_without_new_relic(*args, &block)
59
+ end
60
+ end
61
+
62
+ alias_method :connect_without_new_relic, :connect
63
+
64
+ def connect(*args, &block)
65
+ NewRelic::Agent::Datastores.wrap(NewRelic::Agent::Datastores::Redis::PRODUCT_NAME, NewRelic::Agent::Datastores::Redis::CONNECT) do
66
+ connect_without_new_relic(*args, &block)
67
+ end
68
+ end
69
+ end
70
+ end
71
+ end
@@ -5,6 +5,7 @@
5
5
  require 'new_relic/agent/instrumentation/controller_instrumentation'
6
6
  require 'new_relic/agent/instrumentation/sinatra/transaction_namer'
7
7
  require 'new_relic/agent/instrumentation/sinatra/ignorer'
8
+ require 'new_relic/agent/parameter_filtering'
8
9
 
9
10
  DependencyDetection.defer do
10
11
  @name = :sinatra
@@ -38,6 +38,10 @@ module NewRelic
38
38
  @collector = collector
39
39
  @request_timeout = Agent.config[:timeout]
40
40
  @metric_id_cache = {}
41
+ @ssl_cert_store = nil
42
+ @in_session = nil
43
+ @agent_id = nil
44
+ @shared_tcp_connection = nil
41
45
 
42
46
  @audit_logger = ::NewRelic::Agent::AuditLogger.new
43
47
  Agent.config.register_callback(:'audit_log.enabled') do |enabled|
@@ -148,9 +148,8 @@ module NewRelic
148
148
  if state.is_sql_recorded?
149
149
  if duration > Agent.config[:'slow_sql.explain_threshold']
150
150
  backtrace = caller.join("\n")
151
- data.sql_data << SlowSql.new(Database.capture_query(sql),
152
- metric_name, config,
153
- duration, backtrace, explainer)
151
+ statement = Database::Statement.new(sql, config, explainer)
152
+ data.sql_data << SlowSql.new(statement, metric_name, duration, backtrace)
154
153
  end
155
154
  end
156
155
  end
@@ -208,38 +207,40 @@ module NewRelic
208
207
  end
209
208
 
210
209
  class SlowSql
211
- attr_reader :sql
210
+ attr_reader :statement
212
211
  attr_reader :metric_name
213
212
  attr_reader :duration
214
213
  attr_reader :backtrace
215
214
 
216
- def initialize(sql, metric_name, config, duration, backtrace=nil, explainer=nil)
217
- @sql = sql
215
+ def initialize(statement, metric_name, duration, backtrace=nil)
216
+ @statement = statement
218
217
  @metric_name = metric_name
219
- @config = config
220
218
  @duration = duration
221
219
  @backtrace = backtrace
222
- @explainer = explainer
220
+ end
221
+
222
+ def sql
223
+ statement.sql
223
224
  end
224
225
 
225
226
  def obfuscate
226
- NewRelic::Agent::Database.obfuscate_sql(@sql)
227
+ NewRelic::Agent::Database.obfuscate_sql(statement)
227
228
  end
228
229
 
229
230
  def normalize
230
231
  NewRelic::Agent::Database::Obfuscator.instance \
231
- .default_sql_obfuscator(@sql).gsub(/\?\s*\,\s*/, '').gsub(/\s/, '')
232
+ .default_sql_obfuscator(statement).gsub(/\?\s*\,\s*/, '').gsub(/\s/, '')
232
233
  end
233
234
 
234
235
  def explain
235
- if @config && @explainer
236
- NewRelic::Agent::Database.explain_sql(@sql, @config, @explainer)
236
+ if statement.config && statement.explainer
237
+ NewRelic::Agent::Database.explain_sql(statement.sql, statement.config, statement.explainer)
237
238
  end
238
239
  end
239
240
 
240
241
  # We can't serialize the explainer, so clear it before we transmit
241
242
  def prepare_to_send
242
- @explainer = nil
243
+ statement.explainer = nil
243
244
  end
244
245
  end
245
246
 
@@ -10,6 +10,7 @@ module NewRelic
10
10
  GCSnapshot = Struct.new(:gc_time_s, :gc_call_count)
11
11
 
12
12
  def self.init
13
+ @initialized ||= nil
13
14
  return @profiler if @initialized
14
15
  @profiler = if RailsBenchProfiler.enabled?
15
16
  RailsBenchProfiler.new
@@ -21,6 +21,7 @@ module NewRelic
21
21
  CONTROLLER_PREFIX = 'Controller/'.freeze
22
22
  MIDDLEWARE_PREFIX = 'Middleware/Rack/'.freeze
23
23
  TASK_PREFIX = 'OtherTransaction/Background/'.freeze
24
+ RAKE_PREFIX = 'OtherTransaction/Rake/'.freeze
24
25
  RACK_PREFIX = 'Controller/Rack/'.freeze
25
26
  SINATRA_PREFIX = 'Controller/Sinatra/'.freeze
26
27
  GRAPE_PREFIX = 'Controller/Grape/'.freeze
@@ -279,6 +280,7 @@ module NewRelic
279
280
  @ignore_this_transaction = false
280
281
  @ignore_apdex = false
281
282
  @ignore_enduser = false
283
+ @ignore_trace = false
282
284
 
283
285
  @attributes = Attributes.new(NewRelic::Agent.instance.attribute_filter)
284
286
 
@@ -110,7 +110,7 @@ module NewRelic
110
110
  end
111
111
 
112
112
  def add(attributes, key, value)
113
- return unless value
113
+ return if value.nil?
114
114
 
115
115
  if exceeds_bytesize_limit?(value, VALUE_LIMIT)
116
116
  value = slice(value)
@@ -19,6 +19,7 @@ module NewRelic
19
19
  @start_time = start_time
20
20
  @node_count = 0
21
21
  @root_node = NewRelic::Agent::Transaction::TraceNode.new(0.0, "ROOT")
22
+ @prepared = false
22
23
  end
23
24
 
24
25
  def sample_id
@@ -91,7 +92,7 @@ module NewRelic
91
92
  when :obfuscated
92
93
  node[:sql] = NewRelic::Agent::Database.obfuscate_sql(node[:sql])
93
94
  when :raw
94
- node[:sql] = node[:sql].to_s
95
+ node[:sql] = node[:sql].sql.to_s
95
96
  else
96
97
  node[:sql] = nil
97
98
  end
@@ -19,6 +19,7 @@ module NewRelic
19
19
  def initialize(timestamp, metric_name)
20
20
  @entry_timestamp = timestamp
21
21
  @metric_name = metric_name || UNKNOWN_NODE_NAME
22
+ @called_nodes = nil
22
23
  end
23
24
 
24
25
  # sets the final timestamp on a node to indicate the exit
@@ -167,13 +168,13 @@ module NewRelic
167
168
  return nil unless statement.respond_to?(:config) &&
168
169
  statement.respond_to?(:explainer)
169
170
 
170
- NewRelic::Agent::Database.explain_sql(statement,
171
+ NewRelic::Agent::Database.explain_sql(statement.sql,
171
172
  statement.config,
172
173
  statement.explainer)
173
174
  end
174
175
 
175
176
  def obfuscated_sql
176
- NewRelic::Agent::Database.obfuscate_sql(params[:sql])
177
+ NewRelic::Agent::Database.obfuscate_sql(params[:sql].sql)
177
178
  end
178
179
 
179
180
  def called_nodes=(nodes)
@@ -132,9 +132,9 @@ module NewRelic
132
132
  node = builder.current_node
133
133
  if node
134
134
  if key == :sql
135
- sql = node[:sql]
136
- if(sql && !sql.empty?)
137
- sql = self.class.truncate_message(sql << "\n#{message}") if sql.length <= MAX_DATA_LENGTH
135
+ statement = node[:sql]
136
+ if(statement && !statement.sql.empty?)
137
+ statement.sql = self.class.truncate_message(statement.sql + "\n#{message.sql}") if statement.sql.length <= MAX_DATA_LENGTH
138
138
  else
139
139
  # message is expected to have been pre-truncated by notice_sql
140
140
  node[:sql] = message
@@ -189,22 +189,11 @@ module NewRelic
189
189
  state ||= TransactionState.tl_get
190
190
  builder = state.transaction_sample_builder
191
191
  if state.is_sql_recorded?
192
- statement = build_database_statement(sql, config, explainer)
192
+ statement = Database::Statement.new(sql, config, explainer)
193
193
  notice_extra_data(builder, statement, duration, :sql)
194
194
  end
195
195
  end
196
196
 
197
- def build_database_statement(sql, config, explainer)
198
- statement = Database::Statement.new(Database.capture_query(sql))
199
- if config
200
- statement.adapter = config[:adapter]
201
- statement.config = config
202
- end
203
- statement.explainer = explainer
204
-
205
- statement
206
- end
207
-
208
197
  # Attaches an additional non-SQL query parameter to the current
209
198
  # transaction trace node.
210
199
  #