newrelic_rpm 4.8.0.341 → 5.0.0.342

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (33) hide show
  1. checksums.yaml +5 -5
  2. data/.travis.yml +27 -0
  3. data/CHANGELOG.md +39 -0
  4. data/config.dot +0 -3
  5. data/lib/new_relic/agent/{throughput_monitor.rb → adaptive_sampler.rb} +22 -13
  6. data/lib/new_relic/agent/agent.rb +3 -4
  7. data/lib/new_relic/agent/configuration/default_source.rb +22 -17
  8. data/lib/new_relic/agent/configuration/high_security_source.rb +0 -2
  9. data/lib/new_relic/agent/database.rb +5 -0
  10. data/lib/new_relic/agent/database/explain_plan_helpers.rb +11 -0
  11. data/lib/new_relic/agent/distributed_trace_monitor.rb +4 -2
  12. data/lib/new_relic/agent/distributed_trace_payload.rb +88 -119
  13. data/lib/new_relic/agent/external.rb +14 -0
  14. data/lib/new_relic/agent/heap.rb +140 -0
  15. data/lib/new_relic/agent/instrumentation/bunny.rb +5 -1
  16. data/lib/new_relic/agent/instrumentation/rails5/action_cable.rb +5 -1
  17. data/lib/new_relic/agent/messaging.rb +10 -0
  18. data/lib/new_relic/agent/new_relic_service.rb +43 -23
  19. data/lib/new_relic/agent/priority_sampled_buffer.rb +68 -0
  20. data/lib/new_relic/agent/supported_versions.rb +1 -1
  21. data/lib/new_relic/agent/transaction.rb +14 -8
  22. data/lib/new_relic/agent/transaction/distributed_tracing.rb +113 -55
  23. data/lib/new_relic/agent/transaction/external_request_segment.rb +17 -11
  24. data/lib/new_relic/agent/transaction/message_broker_segment.rb +12 -4
  25. data/lib/new_relic/agent/transaction_error_primitive.rb +2 -8
  26. data/lib/new_relic/agent/transaction_event_aggregator.rb +16 -13
  27. data/lib/new_relic/agent/transaction_event_primitive.rb +5 -3
  28. data/lib/new_relic/agent/transaction_event_recorder.rb +3 -11
  29. data/lib/new_relic/recipes/capistrano3.rb +5 -2
  30. data/lib/new_relic/version.rb +2 -2
  31. data/newrelic_rpm.gemspec +3 -2
  32. metadata +38 -9
  33. data/lib/new_relic/agent/distributed_trace_priority_sampled_buffer.rb +0 -72
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: b51f94bfacea16c929d073a557db1c96c171da40
4
- data.tar.gz: 6b593714cfad1a3751dd07b410ba300fe46e4751
2
+ SHA256:
3
+ metadata.gz: 10c4b8fa117aaa061a4e13071bfa6a568e03dc27b4d9a75040cbf9c5b0772749
4
+ data.tar.gz: 1536ab0db32670d6f604cd9c662d1b7633366e77957051e8ace104df942ed97d
5
5
  SHA512:
6
- metadata.gz: 88aa0416e6c2a3f8e32b6b5536e1b4f58b5b423ce06085ba583830fca6c014c04ea318bad3b48bcc17f5f93506d27f1ac7fed3ce56fb157cfd43830650c74652
7
- data.tar.gz: afc0971db514b4b76e93725c6c7b299e26a281ba0a8cee2add9aba30a149f0c20a0dc74d7d08363f4977a54c5dc90f2e897edf64d2fa658cf286cc18358cc978
6
+ metadata.gz: aff7fb607ba79d6f8707a8c4f99bee62dc32c87df71a8809517ed1e29ba57760f0991c241d56816dfc50af99aad98bd918f82d97365cc36882962973efe12551
7
+ data.tar.gz: 8f2c281d13b955a25d9b7717ed248d5dc3a230e1e42ebf4fd25ad010253cfe42ba7692b288e2d093b9cd64a84d56d7a3edc1d274207ad01402c1ea36cc62af1a
@@ -16,6 +16,11 @@ before_install:
16
16
 
17
17
  install: bundle install
18
18
 
19
+ addons:
20
+ apt:
21
+ packages:
22
+ - haveged
23
+
19
24
  before_script: ./test/script/before_script/install_mongodb.sh
20
25
 
21
26
  script: ./test/script/ci.sh
@@ -171,3 +176,25 @@ matrix:
171
176
  env: TYPE=UNIT ENVIRONMENT=rails31
172
177
  - rvm: jruby-9.1.13.0
173
178
  env: TYPE=UNIT ENVIRONMENT=rails32
179
+
180
+ # Travis (and only Travis) has been throwing difficult-to-reproduce
181
+ # errors in various JRuby tests. These appeared after a build image
182
+ # update, and they seem to be unrelated to any agent code changes.
183
+ # So, we'll allow these specific test runs to fail while we track
184
+ # the issue (RUBY-1869).
185
+ #
186
+ allow_failures:
187
+ - rvm: jruby-9.1.13.0
188
+ env: TYPE=UNIT ENVIRONMENT=rails40
189
+ - rvm: jruby-9.1.13.0
190
+ env: TYPE=UNIT ENVIRONMENT=rails41
191
+ - rvm: jruby-9.1.13.0
192
+ env: TYPE=UNIT ENVIRONMENT=rails42
193
+ - rvm: jruby-9.1.13.0
194
+ env: TYPE=UNIT ENVIRONMENT=rails50
195
+ - rvm: jruby-9.1.13.0
196
+ env: TYPE=UNIT ENVIRONMENT=rails51
197
+ - rvm: jruby-9.1.13.0
198
+ env: TYPE=UNIT ENVIRONMENT=norails
199
+ - rvm: jruby-9.1.13.0
200
+ env: TYPE=FUNCTIONAL GROUP=background_2
@@ -1,5 +1,44 @@
1
1
  # New Relic Ruby Agent Release Notes #
2
2
 
3
+ ## v5.0.0 ##
4
+
5
+ * SSL connections to New Relic are now mandatory
6
+
7
+ Prior to this version, using an SSL connection to New Relic was
8
+ the default behavior, but could be overridden. SSL connections are
9
+ now enforced (not overrideable).
10
+
11
+ * Additional security checking before trying to explain
12
+ multi-statement SQL queries
13
+
14
+ Customer applications might submit SQL queries containing multiple
15
+ statements (e.g., SELECT * FROM table; SELECT * FROM table). For
16
+ security reasons, we should not generate explain plans in this
17
+ situation.
18
+
19
+ Although the agent correctly skipped explain plans for these
20
+ queries during testing, we have added extra checks for this
21
+ scenario.
22
+
23
+ * Bugfix for RabbitMQ exchange names that are symbols
24
+
25
+ The agent no longer raises a TypeError when a RabbitMQ exchange
26
+ name is a Ruby symbol instead of a string.
27
+
28
+ * Bugfix for audit logging to stdout
29
+
30
+ Previous agents configured to log to stdout would correctly send
31
+ regular agent logs to stdout, but would incorrectly send audit
32
+ logs to a text file named "stdout". This release corrects the
33
+ error.
34
+
35
+ * Bugfix for Capistrano deployment notifications on v3.7 and beyond
36
+
37
+ Starting with version 3.7, Capistrano uses a different technique
38
+ to determine a project's version control system. The agent now
39
+ works correctly with this new behavior. Thanks to Jimmy Zhang for
40
+ the contribution.
41
+
3
42
  ## v4.8.0 ##
4
43
 
5
44
  * Initialize New Relic Agent before config initializers
data/config.dot CHANGED
@@ -21,7 +21,6 @@ digraph AgentEnabled {
21
21
  "[error_collector.ignore_errors]"
22
22
  "[browser_monitoring.auto_instrument]"
23
23
  "[license_key]"
24
- "[ssl]"
25
24
  "[verify_certificate]"
26
25
  "[api_host]"
27
26
  "[api_port]"
@@ -164,14 +163,12 @@ digraph AgentEnabled {
164
163
  "Control#server_from_host" -> "[host]"
165
164
  "Control#server_from_host" -> "[port]"
166
165
  "Control#server_from_host" -> "Control#convert_to_ip_address"
167
- "Control#http_connection" -> "[ssl]"
168
166
  "Control#http_connection" -> "[verify_certificate]"
169
167
  "Control#http_connection" -> "Control#proxy_server"
170
168
  "Control#set_log_level!" -> "[log_level]"
171
169
  "Control#log_path" -> "[log_file_path]"
172
170
  "Control#log_path" -> "Control#log_to_stdout?"
173
171
  "Control#log_to_stdout?" -> "[log_file_path]"
174
- "Control#convert_to_ip_address" -> "[ssl]"
175
172
  "Control#convert_to_ip_address" -> "[verify_certificate]"
176
173
  "Control#server" -> "Control#server_from_host"
177
174
  "Control#setup_log" -> "Control#set_log_level!"
@@ -4,14 +4,16 @@
4
4
 
5
5
  module NewRelic
6
6
  module Agent
7
- class ThroughputMonitor
7
+ class AdaptiveSampler
8
8
 
9
- def initialize target_samples = 10
9
+ def initialize target_samples = 10, interval_duration = 60
10
10
  @target = target_samples
11
11
  @seen = 0
12
12
  @seen_last = 0
13
13
  @sampled_count = 0
14
- @first_cycle = true
14
+ @interval_duration = interval_duration
15
+ @first_interval = true
16
+ @interval_start = Time.now.to_f
15
17
  @lock = Mutex.new
16
18
  end
17
19
 
@@ -20,7 +22,8 @@ module NewRelic
20
22
  # sampled. This uses the adaptive sampling algorithm.
21
23
  def sampled?
22
24
  @lock.synchronize do
23
- sampled = if @first_cycle
25
+ reset_if_interval_expired!
26
+ sampled = if @first_interval
24
27
  @sampled_count < 10
25
28
  elsif @sampled_count < @target
26
29
  rand(@seen_last) < @target
@@ -35,15 +38,6 @@ module NewRelic
35
38
  end
36
39
  end
37
40
 
38
- def reset!
39
- @lock.synchronize do
40
- @first_cycle = false
41
- @seen_last = @seen
42
- @seen = 0
43
- @sampled_count = 0
44
- end
45
- end
46
-
47
41
  def stats
48
42
  @lock.synchronize do
49
43
  {
@@ -54,6 +48,21 @@ module NewRelic
54
48
  }
55
49
  end
56
50
  end
51
+
52
+ private
53
+
54
+ def reset_if_interval_expired!
55
+ now = Time.now.to_f
56
+ return unless @interval_start + @interval_duration <= now
57
+
58
+ elapsed_intervals = Integer((now - @interval_start) / @interval_duration)
59
+ @interval_start = @interval_start + elapsed_intervals * @interval_duration
60
+
61
+ @first_interval = false
62
+ @seen_last = elapsed_intervals > 1 ? 0 : @seen
63
+ @seen = 0
64
+ @sampled_count = 0
65
+ end
57
66
  end
58
67
  end
59
68
  end
@@ -30,7 +30,7 @@ require 'new_relic/agent/vm/monotonic_gc_profiler'
30
30
  require 'new_relic/agent/utilization_data'
31
31
  require 'new_relic/environment_report'
32
32
  require 'new_relic/agent/attribute_filter'
33
- require 'new_relic/agent/throughput_monitor'
33
+ require 'new_relic/agent/adaptive_sampler'
34
34
 
35
35
  module NewRelic
36
36
  module Agent
@@ -63,7 +63,7 @@ module NewRelic
63
63
  @harvest_samplers = NewRelic::Agent::SamplerCollection.new(@events)
64
64
  @monotonic_gc_profiler = NewRelic::Agent::VM::MonotonicGCProfiler.new
65
65
  @javascript_instrumentor = NewRelic::Agent::JavascriptInstrumentor.new(@events)
66
- @throughput_monitor = NewRelic::Agent::ThroughputMonitor.new
66
+ @adaptive_sampler = NewRelic::Agent::AdaptiveSampler.new
67
67
 
68
68
  @harvester = NewRelic::Agent::Harvester.new(@events)
69
69
  @after_fork_lock = Mutex.new
@@ -144,7 +144,7 @@ module NewRelic
144
144
  attr_reader :custom_event_aggregator
145
145
  attr_reader :transaction_event_recorder
146
146
  attr_reader :attribute_filter
147
- attr_reader :throughput_monitor
147
+ attr_reader :adaptive_sampler
148
148
 
149
149
  def transaction_event_aggregator
150
150
  @transaction_event_recorder.transaction_event_aggregator
@@ -1154,7 +1154,6 @@ module NewRelic
1154
1154
  harvest_and_send_for_agent_commands
1155
1155
  end
1156
1156
  ensure
1157
- throughput_monitor.reset!
1158
1157
  NewRelic::Agent::Database.close_connections
1159
1158
  duration = (Time.now - now).to_f
1160
1159
  NewRelic::Agent.record_metric('Supportability/Harvest', duration)
@@ -113,9 +113,15 @@ module NewRelic
113
113
  }
114
114
  end
115
115
 
116
+ DEFAULT_LOG_DIR = 'log/'.freeze
117
+
116
118
  def self.audit_log_path
117
119
  Proc.new {
118
- File.join(NewRelic::Agent.config[:log_file_path], 'newrelic_audit.log')
120
+ log_file_path = NewRelic::Agent.config[:log_file_path]
121
+ wants_stdout = (log_file_path.upcase == 'STDOUT')
122
+ audit_log_dir = wants_stdout ? DEFAULT_LOG_DIR : log_file_path
123
+
124
+ File.join(audit_log_dir, 'newrelic_audit.log')
119
125
  }
120
126
  end
121
127
 
@@ -142,10 +148,6 @@ module NewRelic
142
148
  Proc.new { NewRelic::Agent.config[:apdex_t] * 4 }
143
149
  end
144
150
 
145
- def self.port
146
- Proc.new { NewRelic::Agent.config[:ssl] ? 443 : 80 }
147
- end
148
-
149
151
  def self.profiling_available
150
152
  Proc.new {
151
153
  begin
@@ -157,6 +159,17 @@ module NewRelic
157
159
  }
158
160
  end
159
161
 
162
+ def self.host
163
+ Proc.new do
164
+ regex = /\A(?<identifier>.+?)x/
165
+ if matches = regex.match(String(NewRelic::Agent.config[:license_key]))
166
+ "collector.#{matches['identifier']}.nr-data.net"
167
+ else
168
+ 'collector.newrelic.com'
169
+ end
170
+ end
171
+ end
172
+
160
173
  def self.convert_to_regexp_list(raw_value)
161
174
  value_list = convert_to_list(raw_value)
162
175
  value_list.map do |value|
@@ -299,14 +312,6 @@ module NewRelic
299
312
  :allowed_from_server => false,
300
313
  :description => 'If <code>true</code>, enables <a href="https://docs.newrelic.com/docs/accounts-partnerships/accounts/security/high-security">high security mode</a>. Ensure you understand the implications of high security mode before enabling this setting.'
301
314
  },
302
- :ssl => {
303
- :default => true,
304
- :allow_nil => true,
305
- :public => true,
306
- :type => Boolean,
307
- :allowed_from_server => false,
308
- :description => 'If <code>true</code>, enables SSL for transmissions to the New Relic <a href="https://docs.newrelic.com/docs/apm/new-relic-apm/getting-started/glossary#collector">collector</a>.'
309
- },
310
315
  :proxy_host => {
311
316
  :default => nil,
312
317
  :allow_nil => true,
@@ -450,7 +455,7 @@ module NewRelic
450
455
  :description => 'Specify a whitelist of exceptions you do not want the agent to strip when <a href="#strip_exception_messages-enabled">strip_exception_messages</a> is <code>true</code>. Separate exceptions with a comma. For example, <code>"ImportantException,PreserveMessageException"</code>.'
451
456
  },
452
457
  :host => {
453
- :default => 'collector.newrelic.com',
458
+ :default => DefaultSource.host,
454
459
  :public => false,
455
460
  :type => String,
456
461
  :allowed_from_server => false,
@@ -464,7 +469,7 @@ module NewRelic
464
469
  :description => 'API host for New Relic.'
465
470
  },
466
471
  :port => {
467
- :default => DefaultSource.port,
472
+ :default => 443,
468
473
  :public => false,
469
474
  :type => Integer,
470
475
  :allowed_from_server => false,
@@ -578,7 +583,7 @@ module NewRelic
578
583
  :description => 'Defines a name for the log file.'
579
584
  },
580
585
  :log_file_path => {
581
- :default => 'log/',
586
+ :default => DefaultSource::DEFAULT_LOG_DIR,
582
587
  :public => true,
583
588
  :type => String,
584
589
  :allowed_from_server => false,
@@ -1082,7 +1087,7 @@ module NewRelic
1082
1087
  :description => 'List of trusted New Relic account IDs for the purposes of cross-application tracing. Inbound requests from applications including cross-application headers that do not come from an account in this list will be ignored.'
1083
1088
  },
1084
1089
  :"cross_application_tracer.enabled" => {
1085
- :default => true,
1090
+ :default => Proc.new { !NewRelic::Agent.config[:'distributed_tracing.enabled'] },
1086
1091
  :public => true,
1087
1092
  :type => Boolean,
1088
1093
  :allowed_from_server => true,
@@ -10,8 +10,6 @@ module NewRelic
10
10
  class HighSecuritySource < DottedHash
11
11
  def initialize(local_settings)
12
12
  super({
13
- :ssl => true,
14
-
15
13
  :capture_params => false,
16
14
  :'resque.capture_params' => false,
17
15
  :'sidekiq.capture_params' => false,
@@ -271,6 +271,11 @@ module NewRelic
271
271
  return false
272
272
  end
273
273
 
274
+ if multiple_queries?(@sql)
275
+ NewRelic::Agent.logger.debug('Unable to collect explain plan for multiple queries.')
276
+ return false
277
+ end
278
+
274
279
  true
275
280
  end
276
281
  end
@@ -21,6 +21,17 @@ module NewRelic
21
21
  Obfuscator.instance.obfuscate_single_quote_literals(sql) =~ /\$\d+/
22
22
  end
23
23
 
24
+ # SQL containing a semicolon in the middle (with something
25
+ # other than whitespace after it) may contain two or more
26
+ # queries. It's not safe to EXPLAIN this kind of expression,
27
+ # since it could lead to executing unwanted SQL.
28
+ #
29
+ MULTIPLE_QUERIES = Regexp.new(';\s*\S+')
30
+
31
+ def multiple_queries?(sql)
32
+ sql =~ MULTIPLE_QUERIES
33
+ end
34
+
24
35
  def handle_exception_in_explain
25
36
  yield
26
37
  rescue => e
@@ -17,12 +17,14 @@ module NewRelic
17
17
  end
18
18
 
19
19
  def on_before_call(request)
20
- return unless CrossAppTracing.cross_app_enabled?
20
+ return unless NewRelic::Agent.config[:'distributed_tracing.enabled']
21
21
  return unless payload = request[NEWRELIC_TRACE_KEY]
22
22
 
23
23
  state = NewRelic::Agent::TransactionState.tl_get
24
24
  txn = state.current_transaction
25
- txn.accept_distributed_trace_payload HTTP_TRANSPORT_TYPE, payload
25
+ if txn.accept_distributed_trace_payload payload
26
+ txn.distributed_trace_payload.caller_transport_type = HTTP_TRANSPORT_TYPE
27
+ end
26
28
  end
27
29
  end
28
30
  end
@@ -7,73 +7,66 @@ require 'base64'
7
7
  module NewRelic
8
8
  module Agent
9
9
  class DistributedTracePayload
10
- VERSION =[0, 0].freeze
11
- CALLER_TYPE = "App".freeze
10
+ VERSION =[0, 1].freeze
11
+ PARENT_TYPE = "App".freeze
12
12
  POUND = '#'.freeze
13
13
 
14
14
  # Key names for serialization
15
- VERSION_KEY = 'v'.freeze
16
- DATA_KEY = 'd'.freeze
17
- CALLER_TYPE_KEY = 'ty'.freeze
18
- CALLER_ACCOUNT_KEY = 'ac'.freeze
19
- CALLER_APP_KEY = 'ap'.freeze
20
- ID_KEY = 'id'.freeze
21
- TRIP_ID_KEY = 'tr'.freeze
22
- SAMPLED_KEY = 'sa'.freeze
23
- PARENT_IDS_KEY = 'pa'.freeze
24
- DEPTH_KEY = 'de'.freeze
25
- ORDER_KEY = 'or'.freeze
26
- TIMESTAMP_KEY = 'ti'.freeze
27
- HOST_KEY = 'ho'.freeze
28
- SYNTHETICS_KEY = 'sy'.freeze
29
- SYNTHETICS_RESOURCE_KEY = 'r'.freeze
30
- SYNTHETICS_JOB_KEY = 'j'.freeze
31
- SYNTHETICS_MONITOR_KEY = 'm'.freeze
15
+ VERSION_KEY = 'v'.freeze
16
+ DATA_KEY = 'd'.freeze
17
+ PARENT_TYPE_KEY = 'ty'.freeze
18
+ PARENT_ACCOUNT_ID_KEY = 'ac'.freeze
19
+ PARENT_APP_KEY = 'ap'.freeze
20
+ ID_KEY = 'id'.freeze
21
+ TRACE_ID_KEY = 'tr'.freeze
22
+ SAMPLED_KEY = 'sa'.freeze
23
+ PARENT_ID_KEY = 'pa'.freeze
24
+ TIMESTAMP_KEY = 'ti'.freeze
25
+ PRIORITY_KEY = 'pr'.freeze
32
26
 
33
27
  # Intrinsic Keys
34
- CALLER_TYPE_INTRINSIC_KEY = "caller.type".freeze
35
- CALLER_APP_INTRINSIC_KEY = "caller.app".freeze
36
- CALLER_ACCOUNT_ID_INTRINSIC_KEY = "caller.account".freeze
37
- CALLER_TRANSPORT_TYPE_INTRINSIC_KEY = "caller.transportType".freeze
38
- CALLER_TRANSPORT_DURATION_INTRINSIC_KEY = "caller.transportDuration".freeze
39
- CALLER_HOST_INTRINSIC_KEY = "caller.host".freeze
40
- DEPTH_INTRINSIC_KEY = "nr.depth".freeze
41
- ORDER_INTRINSIC_KEY = "nr.order".freeze
42
- GUID_INTRINSIC_KEY = "nr.guid".freeze
43
- REFERRING_TRANSACTION_GUID_INTRINSIC_KEY = "nr.referringTransactionGuid".freeze
28
+ PARENT_TYPE_INTRINSIC_KEY = "parent.type".freeze
29
+ PARENT_APP_INTRINSIC_KEY = "parent.app".freeze
30
+ PARENT_ACCOUNT_ID_INTRINSIC_KEY = "parent.account".freeze
31
+ PARENT_TRANSPORT_TYPE_INTRINSIC_KEY = "parent.transportType".freeze
32
+ PARENT_TRANSPORT_DURATION_INTRINSIC_KEY = "parent.transportDuration".freeze
33
+ GUID_INTRINSIC_KEY = "guid".freeze
34
+ TRACE_ID_INTRINSIC_KEY = "traceId".freeze
44
35
  TRIP_ID_INTRINSIC_KEY = "nr.tripId".freeze
45
- PARENT_IDS_INTRINSIC_KEY = "nr.parentIds".freeze
36
+ PARENT_ID_INTRINSIC_KEY = "parentId".freeze
37
+ GRANDPARENT_ID_INTRINSIC_KEY = "grandparentId".freeze
46
38
  COMMA = ",".freeze
47
39
 
48
40
  INTRINSIC_KEYS = [
49
- CALLER_TYPE_INTRINSIC_KEY,
50
- CALLER_APP_INTRINSIC_KEY,
51
- CALLER_ACCOUNT_ID_INTRINSIC_KEY,
52
- CALLER_TRANSPORT_TYPE_INTRINSIC_KEY,
53
- CALLER_TRANSPORT_DURATION_INTRINSIC_KEY,
54
- CALLER_HOST_INTRINSIC_KEY,
55
- DEPTH_INTRINSIC_KEY,
56
- ORDER_INTRINSIC_KEY,
41
+ PARENT_TYPE_INTRINSIC_KEY,
42
+ PARENT_APP_INTRINSIC_KEY,
43
+ PARENT_ACCOUNT_ID_INTRINSIC_KEY,
44
+ PARENT_TRANSPORT_TYPE_INTRINSIC_KEY,
45
+ PARENT_TRANSPORT_DURATION_INTRINSIC_KEY,
57
46
  GUID_INTRINSIC_KEY,
58
- REFERRING_TRANSACTION_GUID_INTRINSIC_KEY,
47
+ TRACE_ID_INTRINSIC_KEY,
59
48
  TRIP_ID_INTRINSIC_KEY,
60
- PARENT_IDS_INTRINSIC_KEY
49
+ PARENT_ID_INTRINSIC_KEY,
50
+ GRANDPARENT_ID_INTRINSIC_KEY
61
51
  ].freeze
62
52
 
53
+ # Intrinsic Values
54
+ PARENT_TRANSPORT_TYPE_UNKNOWN = 'unknown'.freeze
55
+
63
56
  class << self
64
- def for_transaction transaction, uri=nil
57
+ def for_transaction transaction
65
58
  payload = new
66
59
  return payload unless connected?
67
60
 
68
61
  payload.version = VERSION
69
- payload.caller_type = CALLER_TYPE
62
+ payload.parent_type = PARENT_TYPE
70
63
 
71
64
  # We should not rely on the xp_id being formulated this way, but we have
72
65
  # seen nil account ids coming down in staging for some accounts
73
66
  account_id, fallback_app_id = Agent.config[:cross_process_id].split(POUND)
74
- payload.caller_account_id = account_id
67
+ payload.parent_account_id = account_id
75
68
 
76
- payload.caller_app_id = if Agent.config[:application_id].empty?
69
+ payload.parent_app_id = if Agent.config[:application_id].empty?
77
70
  fallback_app_id
78
71
  else
79
72
  Agent.config[:application_id]
@@ -81,18 +74,11 @@ module NewRelic
81
74
 
82
75
  payload.timestamp = (Time.now.to_f * 1000).round
83
76
  payload.id = transaction.guid
84
- payload.trip_id = transaction.distributed_tracing_trip_id
77
+ payload.trace_id = transaction.trace_id
85
78
  payload.sampled = transaction.sampled?
86
- payload.parent_ids = transaction.parent_ids
87
- payload.depth = transaction.depth + 1
88
- payload.order = transaction.order
89
- payload.host = uri.host if uri
90
-
91
- if transaction.synthetics_payload
92
- payload.synthetics_resource = transaction.synthetics_payload[2]
93
- payload.synthetics_job = transaction.synthetics_payload[3]
94
- payload.synthetics_monitor = transaction.synthetics_payload[4]
95
- end
79
+ payload.priority = transaction.priority
80
+ payload.parent_id = transaction.parent_id
81
+ payload.grandparent_id = transaction.grandparent_id
96
82
 
97
83
  payload
98
84
  end
@@ -103,23 +89,16 @@ module NewRelic
103
89
 
104
90
  payload = new
105
91
  payload.version = raw_payload[VERSION_KEY]
106
- payload.caller_type = payload_data[CALLER_TYPE_KEY]
107
- payload.caller_account_id = payload_data[CALLER_ACCOUNT_KEY]
108
- payload.caller_app_id = payload_data[CALLER_APP_KEY]
92
+ payload.parent_type = payload_data[PARENT_TYPE_KEY]
93
+ payload.parent_account_id = payload_data[PARENT_ACCOUNT_ID_KEY]
94
+ payload.parent_app_id = payload_data[PARENT_APP_KEY]
109
95
  payload.timestamp = payload_data[TIMESTAMP_KEY]
110
96
  payload.id = payload_data[ID_KEY]
111
- payload.trip_id = payload_data[TRIP_ID_KEY]
97
+ payload.trace_id = payload_data[TRACE_ID_KEY]
112
98
  payload.sampled = payload_data[SAMPLED_KEY]
113
- payload.parent_ids = payload_data[PARENT_IDS_KEY]
114
- payload.depth = payload_data[DEPTH_KEY]
115
- payload.order = payload_data[ORDER_KEY]
116
- payload.host = payload_data[HOST_KEY]
117
-
118
- if payload_synthetics = payload_data[SYNTHETICS_KEY]
119
- payload.synthetics_resource = payload_synthetics[SYNTHETICS_RESOURCE_KEY]
120
- payload.synthetics_job = payload_synthetics[SYNTHETICS_JOB_KEY]
121
- payload.synthetics_monitor = payload_synthetics[SYNTHETICS_MONITOR_KEY]
122
- end
99
+ payload.priority = payload_data[PRIORITY_KEY]
100
+ payload.parent_id = payload_data[ID_KEY] # Our parent ID is the caller's GUID
101
+ payload.grandparent_id = payload_data[PARENT_ID_KEY] # Our grandparent ID is the caller's parent ID
123
102
 
124
103
  payload
125
104
  end
@@ -129,11 +108,15 @@ module NewRelic
129
108
  from_json decoded_payload
130
109
  end
131
110
 
132
- #assigns intrinsics for the first distributed trace in a trip
133
- def assign_initial_intrinsics transaction, payload
134
- payload[TRIP_ID_INTRINSIC_KEY] = transaction.distributed_tracing_trip_id
135
- payload[DEPTH_INTRINSIC_KEY] = transaction.depth
136
- payload[PARENT_IDS_INTRINSIC_KEY] = transaction.parent_ids
111
+ # Assigns intrinsics for the first distributed trace in a trip
112
+ def assign_intrinsics_for_first_trace transaction, transaction_payload
113
+ transaction_payload[GUID_INTRINSIC_KEY] = transaction.guid
114
+ transaction_payload[TRACE_ID_INTRINSIC_KEY] = transaction.trace_id
115
+ transaction_payload[TRIP_ID_INTRINSIC_KEY] = transaction.trace_id
116
+ end
117
+
118
+ def major_version_matches?(payload)
119
+ payload.version[0] == VERSION[0]
137
120
  end
138
121
 
139
122
  private
@@ -146,26 +129,22 @@ module NewRelic
146
129
  end
147
130
 
148
131
  attr_accessor :version,
149
- :caller_type,
132
+ :parent_type,
150
133
  :caller_transport_type,
151
- :caller_account_id,
152
- :caller_app_id,
134
+ :parent_account_id,
135
+ :parent_app_id,
153
136
  :id,
154
- :trip_id,
137
+ :trace_id,
155
138
  :sampled,
156
- :parent_ids,
157
- :synthetics_resource,
158
- :synthetics_job,
159
- :synthetics_monitor,
160
- :order,
161
- :depth,
162
- :timestamp,
163
- :host
139
+ :priority,
140
+ :parent_id,
141
+ :grandparent_id,
142
+ :timestamp
164
143
 
165
144
  alias_method :sampled?, :sampled
166
145
 
167
- def synthetics?
168
- !!(synthetics_resource || synthetics_job || synthetics_monitor)
146
+ def initialize
147
+ @caller_transport_type = PARENT_TRANSPORT_TYPE_UNKNOWN
169
148
  end
170
149
 
171
150
  def to_json
@@ -174,27 +153,19 @@ module NewRelic
174
153
  }
175
154
 
176
155
  result[DATA_KEY] = {
177
- CALLER_TYPE_KEY => caller_type,
178
- CALLER_ACCOUNT_KEY => caller_account_id,
179
- CALLER_APP_KEY => caller_app_id,
180
- ID_KEY => id,
181
- TRIP_ID_KEY => trip_id,
182
- SAMPLED_KEY => sampled,
183
- PARENT_IDS_KEY => parent_ids,
184
- DEPTH_KEY => depth,
185
- ORDER_KEY => order,
186
- HOST_KEY => host,
156
+ PARENT_TYPE_KEY => parent_type,
157
+ PARENT_ACCOUNT_ID_KEY => parent_account_id,
158
+ PARENT_APP_KEY => parent_app_id,
159
+ ID_KEY => id,
160
+ TRACE_ID_KEY => trace_id,
161
+ SAMPLED_KEY => sampled,
162
+ PRIORITY_KEY => priority,
163
+ PARENT_ID_KEY => parent_id,
164
+ # GRANDPARENT_ID_KEY does not go into the outbound JSON payload;
165
+ # the callee will take our parent ID as its grandparent ID
187
166
  TIMESTAMP_KEY => timestamp,
188
167
  }
189
168
 
190
- if synthetics?
191
- result[DATA_KEY][SYNTHETICS_KEY] = {
192
- SYNTHETICS_RESOURCE_KEY => synthetics_resource,
193
- SYNTHETICS_JOB_KEY => synthetics_job,
194
- SYNTHETICS_MONITOR_KEY => synthetics_monitor
195
- }
196
- end
197
-
198
169
  JSON.dump(result)
199
170
  end
200
171
 
@@ -204,19 +175,17 @@ module NewRelic
204
175
  Base64.strict_encode64 to_json
205
176
  end
206
177
 
207
- def assign_intrinsics transaction, payload
208
- payload[CALLER_TYPE_INTRINSIC_KEY] = caller_type
209
- payload[CALLER_APP_INTRINSIC_KEY] = caller_app_id
210
- payload[CALLER_ACCOUNT_ID_INTRINSIC_KEY] = caller_account_id
211
- payload[CALLER_TRANSPORT_TYPE_INTRINSIC_KEY] = caller_transport_type
212
- payload[CALLER_TRANSPORT_DURATION_INTRINSIC_KEY] = transaction.transport_duration
213
- payload[CALLER_HOST_INTRINSIC_KEY] = host
214
- payload[DEPTH_INTRINSIC_KEY] = depth
215
- payload[ORDER_INTRINSIC_KEY] = order
216
- payload[GUID_INTRINSIC_KEY] = transaction.guid
217
- payload[REFERRING_TRANSACTION_GUID_INTRINSIC_KEY] = id
218
- payload[TRIP_ID_INTRINSIC_KEY] = trip_id
219
- payload[PARENT_IDS_INTRINSIC_KEY] = parent_ids.join COMMA if parent_ids
178
+ def assign_intrinsics transaction, transaction_payload
179
+ transaction_payload[PARENT_TYPE_INTRINSIC_KEY] = parent_type
180
+ transaction_payload[PARENT_APP_INTRINSIC_KEY] = parent_app_id
181
+ transaction_payload[PARENT_ACCOUNT_ID_INTRINSIC_KEY] = parent_account_id
182
+ transaction_payload[PARENT_TRANSPORT_TYPE_INTRINSIC_KEY] = caller_transport_type
183
+ transaction_payload[PARENT_TRANSPORT_DURATION_INTRINSIC_KEY] = transaction.transport_duration
184
+ transaction_payload[GUID_INTRINSIC_KEY] = transaction.guid
185
+ transaction_payload[TRACE_ID_INTRINSIC_KEY] = trace_id
186
+ transaction_payload[TRIP_ID_INTRINSIC_KEY] = trace_id
187
+ transaction_payload[PARENT_ID_INTRINSIC_KEY] = parent_id if parent_id
188
+ transaction_payload[GRANDPARENT_ID_INTRINSIC_KEY] = grandparent_id if grandparent_id
220
189
  end
221
190
  end
222
191
  end