newrelic_rpm 4.8.0.341 → 5.0.0.342

Sign up to get free protection for your applications and to get access to all the features.
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