newrelic_rpm 5.2.0.345 → 5.3.0.346
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.gitignore +1 -0
- data/.travis.yml +1 -0
- data/.yardopts +3 -1
- data/CHANGELOG.md +31 -6
- data/lib/new_relic/agent/adaptive_sampler.rb +49 -13
- data/lib/new_relic/agent/agent.rb +14 -5
- data/lib/new_relic/agent/configuration/default_source.rb +54 -2
- data/lib/new_relic/agent/configuration/server_source.rb +6 -1
- data/lib/new_relic/agent/cross_app_tracing.rb +3 -1
- data/lib/new_relic/agent/database.rb +14 -0
- data/lib/new_relic/agent/distributed_trace_monitor.rb +14 -4
- data/lib/new_relic/agent/distributed_trace_payload.rb +104 -47
- data/lib/new_relic/agent/distributed_tracing.rb +67 -0
- data/lib/new_relic/agent/error_event_aggregator.rb +1 -1
- data/lib/new_relic/agent/event_aggregator.rb +25 -0
- data/lib/new_relic/agent/external.rb +7 -14
- data/lib/new_relic/agent/messaging.rb +26 -13
- data/lib/new_relic/agent/new_relic_service.rb +7 -0
- data/lib/new_relic/agent/span_event_aggregator.rb +51 -0
- data/lib/new_relic/agent/span_event_primitive.rb +144 -0
- data/lib/new_relic/agent/sql_sampler.rb +19 -3
- data/lib/new_relic/agent/transaction.rb +21 -17
- data/lib/new_relic/agent/transaction/abstract_segment.rb +4 -2
- data/lib/new_relic/agent/transaction/datastore_segment.rb +26 -0
- data/lib/new_relic/agent/transaction/distributed_tracing.rb +47 -23
- data/lib/new_relic/agent/transaction/external_request_segment.rb +11 -2
- data/lib/new_relic/agent/transaction/message_broker_segment.rb +2 -2
- data/lib/new_relic/agent/transaction/segment.rb +14 -0
- data/lib/new_relic/agent/transaction/trace.rb +1 -10
- data/lib/new_relic/agent/transaction_event_primitive.rb +0 -2
- data/lib/new_relic/version.rb +1 -1
- metadata +5 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: a104aa20426e4da3129e97dfaa651e7232ef804cf91de87b0aa4ac68d00d3fe7
|
4
|
+
data.tar.gz: f8ae7ba61e0dc5442212c8d4a8d985d4e9ac353c23e9ff61ebb709ff11bfd28a
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 58d78970fa151543b165d1ef8b37a9ab7adefabf35ccad2292df5038812a1d5d5524f21cb7822a8d99bc4eabed8ceafc537b6f913b829f2a25ff0cf19a399e3a
|
7
|
+
data.tar.gz: 6859b4ba6ceaab1faeac5634ea264e015329f20af436872da764e3f17ac6b22f2ad2cbfc4604eccc883d9f7b1a0ef5c1fb193c9faf7fdbfab107bae3a2109b8d
|
data/.gitignore
CHANGED
data/.travis.yml
CHANGED
@@ -9,6 +9,7 @@ language: ruby
|
|
9
9
|
sudo: required
|
10
10
|
|
11
11
|
before_install:
|
12
|
+
- sudo apt-get update && sudo apt-get install --only-upgrade openssl && sudo apt-get install --only-upgrade libssl-dev
|
12
13
|
- gem --version
|
13
14
|
- gem update --system
|
14
15
|
- ./test/script/before_install/gemstash_mirror.sh
|
data/.yardopts
CHANGED
@@ -2,6 +2,8 @@
|
|
2
2
|
--api public
|
3
3
|
lib/new_relic/agent.rb
|
4
4
|
lib/new_relic/agent/method_tracer.rb
|
5
|
+
lib/new_relic/agent/distributed_tracing.rb
|
6
|
+
lib/new_relic/agent/distributed_trace_payload.rb
|
5
7
|
lib/new_relic/agent/external.rb
|
6
8
|
lib/new_relic/agent/instrumentation/controller_instrumentation.rb
|
7
9
|
lib/new_relic/agent/instrumentation/rack.rb
|
@@ -19,5 +21,5 @@ lib/new_relic/rack.rb
|
|
19
21
|
lib/new_relic/agent/transaction/external_request_segment.rb
|
20
22
|
-
|
21
23
|
LICENSE
|
22
|
-
CHANGELOG
|
24
|
+
CHANGELOG.md
|
23
25
|
CONTRIBUTING.md
|
data/CHANGELOG.md
CHANGED
@@ -1,6 +1,26 @@
|
|
1
1
|
# New Relic Ruby Agent Release Notes #
|
2
2
|
|
3
|
-
|
3
|
+
## v5.3.0 ##
|
4
|
+
|
5
|
+
* Distributed Tracing
|
6
|
+
|
7
|
+
Distributed tracing lets you see the path that a request takes as
|
8
|
+
it travels through your distributed system. By showing the
|
9
|
+
distributed activity through a unified view, you can troubleshoot
|
10
|
+
and understand a complex system better than ever before.
|
11
|
+
|
12
|
+
Distributed tracing is available with an APM Pro or equivalent
|
13
|
+
subscription. To see a complete distributed trace, you need to
|
14
|
+
enable the feature on a set of neighboring services. Enabling
|
15
|
+
distributed tracing changes the behavior of some New Relic
|
16
|
+
features, so carefully consult the
|
17
|
+
[transition guide](https://docs.newrelic.com/docs/transition-guide-distributed-tracing)
|
18
|
+
before you enable this feature.
|
19
|
+
|
20
|
+
To enable distributed tracing, set the
|
21
|
+
`distributed_tracing.enabled` configuration option to `true`.
|
22
|
+
|
23
|
+
## v5.2.0 ##
|
4
24
|
|
5
25
|
* Use priority sampling for errors and custom events
|
6
26
|
|
@@ -14,7 +34,12 @@
|
|
14
34
|
The agent will now complete the process of wrapping datastore
|
15
35
|
operations even if an error occurs during execution of a callback.
|
16
36
|
|
17
|
-
|
37
|
+
* Span Events
|
38
|
+
|
39
|
+
Finished segments whose `sampled` property is `true` will now post
|
40
|
+
Span events to Insights.
|
41
|
+
|
42
|
+
## v5.1.0 ##
|
18
43
|
|
19
44
|
* Rails 5.2 support
|
20
45
|
|
@@ -68,7 +93,7 @@
|
|
68
93
|
data to New Relic. This version truncates long traces to 50 frames
|
69
94
|
(split evenly between the top and bottom of the trace).
|
70
95
|
|
71
|
-
|
96
|
+
## v5.0.0 ##
|
72
97
|
|
73
98
|
* SSL connections to New Relic are now mandatory
|
74
99
|
|
@@ -107,7 +132,7 @@
|
|
107
132
|
works correctly with this new behavior. Thanks to Jimmy Zhang for
|
108
133
|
the contribution.
|
109
134
|
|
110
|
-
|
135
|
+
## v4.8.0 ##
|
111
136
|
|
112
137
|
* Initialize New Relic Agent before config initializers
|
113
138
|
|
@@ -129,7 +154,7 @@
|
|
129
154
|
It is now an agent attribute that can be controlled via the attributes config.
|
130
155
|
For more information on agent attributes [see here](https://docs.newrelic.com/docs/agents/manage-apm-agents/agent-data/agent-attributes).
|
131
156
|
|
132
|
-
|
157
|
+
## 4.7.1 ##
|
133
158
|
|
134
159
|
* Bugfix for Manual Browser Instrumentation
|
135
160
|
|
@@ -139,7 +164,7 @@
|
|
139
164
|
instrumentation. Those changes have been reverted. We will revisit this issue
|
140
165
|
in an upcoming release.
|
141
166
|
|
142
|
-
|
167
|
+
## v4.7.0 ##
|
143
168
|
|
144
169
|
* Expected Error API
|
145
170
|
|
@@ -6,15 +6,16 @@ module NewRelic
|
|
6
6
|
module Agent
|
7
7
|
class AdaptiveSampler
|
8
8
|
|
9
|
-
def initialize target_samples = 10,
|
9
|
+
def initialize target_samples = 10, period_duration = 60
|
10
10
|
@target = target_samples
|
11
11
|
@seen = 0
|
12
12
|
@seen_last = 0
|
13
13
|
@sampled_count = 0
|
14
|
-
@
|
15
|
-
@
|
16
|
-
@
|
14
|
+
@period_duration = period_duration
|
15
|
+
@first_period = true
|
16
|
+
@period_start = Time.now.to_f
|
17
17
|
@lock = Mutex.new
|
18
|
+
register_config_callbacks
|
18
19
|
end
|
19
20
|
|
20
21
|
# Called at the beginning of each transaction, increments seen and
|
@@ -22,13 +23,13 @@ module NewRelic
|
|
22
23
|
# sampled. This uses the adaptive sampling algorithm.
|
23
24
|
def sampled?
|
24
25
|
@lock.synchronize do
|
25
|
-
|
26
|
-
sampled = if @
|
26
|
+
reset_if_period_expired!
|
27
|
+
sampled = if @first_period
|
27
28
|
@sampled_count < 10
|
28
29
|
elsif @sampled_count < @target
|
29
30
|
rand(@seen_last) < @target
|
30
31
|
else
|
31
|
-
rand(@seen) < (@target ** (@target / @sampled_count) - @target ** 0.
|
32
|
+
rand(@seen) < (@target ** (@target / @sampled_count) - @target ** 0.5)
|
32
33
|
end
|
33
34
|
|
34
35
|
@sampled_count += 1 if sampled
|
@@ -51,18 +52,53 @@ module NewRelic
|
|
51
52
|
|
52
53
|
private
|
53
54
|
|
54
|
-
def
|
55
|
+
def reset_if_period_expired!
|
55
56
|
now = Time.now.to_f
|
56
|
-
return unless @
|
57
|
+
return unless @period_start + @period_duration <= now
|
57
58
|
|
58
|
-
|
59
|
-
@
|
59
|
+
elapsed_periods = Integer((now - @period_start) / @period_duration)
|
60
|
+
@period_start = @period_start + elapsed_periods * @period_duration
|
60
61
|
|
61
|
-
@
|
62
|
-
@seen_last =
|
62
|
+
@first_period = false
|
63
|
+
@seen_last = elapsed_periods > 1 ? 0 : @seen
|
63
64
|
@seen = 0
|
64
65
|
@sampled_count = 0
|
65
66
|
end
|
67
|
+
|
68
|
+
def register_config_callbacks
|
69
|
+
register_sampling_target_callback
|
70
|
+
register_sampling_period_callback
|
71
|
+
end
|
72
|
+
|
73
|
+
def register_sampling_target_callback
|
74
|
+
NewRelic::Agent.config.register_callback(:sampling_target) do |target|
|
75
|
+
target_changed = false
|
76
|
+
@lock.synchronize do
|
77
|
+
if @target != target
|
78
|
+
@target = target
|
79
|
+
target_changed = true
|
80
|
+
end
|
81
|
+
end
|
82
|
+
if target_changed
|
83
|
+
NewRelic::Agent.logger.debug "Sampling target set to: #{target}"
|
84
|
+
end
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
88
|
+
def register_sampling_period_callback
|
89
|
+
NewRelic::Agent.config.register_callback(:sampling_target_period_in_seconds) do |period_duration|
|
90
|
+
period_changed = false
|
91
|
+
@lock.synchronize do
|
92
|
+
if @period_duration != period_duration
|
93
|
+
@period_duration = period_duration
|
94
|
+
period_changed = true
|
95
|
+
end
|
96
|
+
end
|
97
|
+
if period_changed
|
98
|
+
NewRelic::Agent.logger.debug "Sampling period set to: #{period_duration}"
|
99
|
+
end
|
100
|
+
end
|
101
|
+
end
|
66
102
|
end
|
67
103
|
end
|
68
104
|
end
|
@@ -22,6 +22,7 @@ require 'new_relic/agent/distributed_trace_monitor'
|
|
22
22
|
require 'new_relic/agent/synthetics_monitor'
|
23
23
|
require 'new_relic/agent/transaction_event_recorder'
|
24
24
|
require 'new_relic/agent/custom_event_aggregator'
|
25
|
+
require 'new_relic/agent/span_event_aggregator'
|
25
26
|
require 'new_relic/agent/sampler_collection'
|
26
27
|
require 'new_relic/agent/javascript_instrumentor'
|
27
28
|
require 'new_relic/agent/vm/monotonic_gc_profiler'
|
@@ -61,14 +62,15 @@ module NewRelic
|
|
61
62
|
@harvest_samplers = NewRelic::Agent::SamplerCollection.new(@events)
|
62
63
|
@monotonic_gc_profiler = NewRelic::Agent::VM::MonotonicGCProfiler.new
|
63
64
|
@javascript_instrumentor = NewRelic::Agent::JavascriptInstrumentor.new(@events)
|
64
|
-
@adaptive_sampler = NewRelic::Agent::AdaptiveSampler.new
|
65
|
+
@adaptive_sampler = NewRelic::Agent::AdaptiveSampler.new(self.class.config[:sampling_target],
|
66
|
+
self.class.config[:sampling_target_period_in_seconds])
|
65
67
|
|
66
68
|
@harvester = NewRelic::Agent::Harvester.new(@events)
|
67
69
|
@after_fork_lock = Mutex.new
|
68
70
|
|
69
71
|
@transaction_event_recorder = NewRelic::Agent::TransactionEventRecorder.new
|
70
|
-
|
71
|
-
@
|
72
|
+
@custom_event_aggregator = NewRelic::Agent::CustomEventAggregator.new
|
73
|
+
@span_event_aggregator = NewRelic::Agent::SpanEventAggregator.new
|
72
74
|
|
73
75
|
@connect_state = :pending
|
74
76
|
@connect_attempts = 0
|
@@ -140,6 +142,7 @@ module NewRelic
|
|
140
142
|
# GC::Profiler.total_time is not monotonic so we wrap it.
|
141
143
|
attr_reader :monotonic_gc_profiler
|
142
144
|
attr_reader :custom_event_aggregator
|
145
|
+
attr_reader :span_event_aggregator
|
143
146
|
attr_reader :transaction_event_recorder
|
144
147
|
attr_reader :attribute_filter
|
145
148
|
attr_reader :adaptive_sampler
|
@@ -546,6 +549,7 @@ module NewRelic
|
|
546
549
|
@transaction_sampler.reset!
|
547
550
|
@transaction_event_recorder.drop_buffered_data
|
548
551
|
@custom_event_aggregator.reset!
|
552
|
+
@span_event_aggregator.reset!
|
549
553
|
@sql_sampler.reset!
|
550
554
|
|
551
555
|
if Agent.config[:clear_transaction_state_after_fork]
|
@@ -1108,8 +1112,9 @@ module NewRelic
|
|
1108
1112
|
|
1109
1113
|
def harvest_and_send_analytic_event_data
|
1110
1114
|
harvest_and_send_from_container(transaction_event_aggregator, :analytic_event_data)
|
1111
|
-
harvest_and_send_from_container(synthetics_event_aggregator,
|
1112
|
-
harvest_and_send_from_container(@custom_event_aggregator,
|
1115
|
+
harvest_and_send_from_container(synthetics_event_aggregator, :analytic_event_data)
|
1116
|
+
harvest_and_send_from_container(@custom_event_aggregator, :custom_event_data)
|
1117
|
+
harvest_and_send_from_container(span_event_aggregator, :span_event_data)
|
1113
1118
|
end
|
1114
1119
|
|
1115
1120
|
def harvest_and_send_error_event_data
|
@@ -1138,6 +1143,10 @@ module NewRelic
|
|
1138
1143
|
transmit_single_data_type(:harvest_and_send_analytic_event_data, "TransactionEvent")
|
1139
1144
|
end
|
1140
1145
|
|
1146
|
+
def transmit_span_event_data
|
1147
|
+
transmit_single_data_type(:harvest_and_send_span_event_data, "SpanEvent")
|
1148
|
+
end
|
1149
|
+
|
1141
1150
|
def transmit_single_data_type(harvest_method, supportability_name)
|
1142
1151
|
now = Time.now
|
1143
1152
|
|
@@ -1676,12 +1676,64 @@ module NewRelic
|
|
1676
1676
|
:allowed_from_server => false,
|
1677
1677
|
:description => 'If <code>true</code>, the agent will clear <code>TransactionState</code> in <code>Agent.drop_buffered_data</code>.'
|
1678
1678
|
},
|
1679
|
+
:account_id => {
|
1680
|
+
:default => nil,
|
1681
|
+
:allow_nil => true,
|
1682
|
+
:public => false,
|
1683
|
+
:type => String,
|
1684
|
+
:allowed_from_server => true,
|
1685
|
+
:description => 'The account id associated with this application.'
|
1686
|
+
},
|
1687
|
+
:primary_application_id => {
|
1688
|
+
:default => nil,
|
1689
|
+
:allow_nil => true,
|
1690
|
+
:public => false,
|
1691
|
+
:type => String,
|
1692
|
+
:allowed_from_server => true,
|
1693
|
+
:description => 'The primary id associated with this application.'
|
1694
|
+
},
|
1679
1695
|
:'distributed_tracing.enabled' => {
|
1680
1696
|
:default => false,
|
1681
|
-
:public =>
|
1697
|
+
:public => true,
|
1682
1698
|
:type => Boolean,
|
1683
1699
|
:allowed_from_server => false,
|
1684
|
-
:description => '
|
1700
|
+
:description => 'Distributed tracing lets you see the path that a request takes through your distributed system. Enabling distributed tracing changes the behavior of some New Relic features, so carefully consult the <a href="https://docs.newrelic.com/docs/transition-guide-distributed-tracing">transition guide</a> before you enable this feature.'
|
1701
|
+
},
|
1702
|
+
:trusted_account_key => {
|
1703
|
+
:default => nil,
|
1704
|
+
:allow_nil => true,
|
1705
|
+
:public => false,
|
1706
|
+
:type => String,
|
1707
|
+
:allowed_from_server => true,
|
1708
|
+
:description => 'A shared key to validate that a distributed trace payload came from a trusted account.'
|
1709
|
+
},
|
1710
|
+
:sampling_target => {
|
1711
|
+
:default => 10,
|
1712
|
+
:public => false,
|
1713
|
+
:type => Integer,
|
1714
|
+
:allowed_from_server => true,
|
1715
|
+
:description => 'The target number of transactions to mark as sampled during a sampled period.'
|
1716
|
+
},
|
1717
|
+
:sampling_target_period_in_seconds => {
|
1718
|
+
:default => 60,
|
1719
|
+
:public => false,
|
1720
|
+
:type => Integer,
|
1721
|
+
:allowed_from_server => true,
|
1722
|
+
:description => 'The period during which a target number of transactions should be marked as sampled.'
|
1723
|
+
},
|
1724
|
+
:'span_events.enabled' => {
|
1725
|
+
:default => true,
|
1726
|
+
:public => false,
|
1727
|
+
:type => Boolean,
|
1728
|
+
:allowed_from_server => true,
|
1729
|
+
:description => 'If <code>true</code>, enables span event sampling.'
|
1730
|
+
},
|
1731
|
+
:'span_events.max_samples_stored' => {
|
1732
|
+
:default => 1000,
|
1733
|
+
:public => false,
|
1734
|
+
:type => Integer,
|
1735
|
+
:allowed_from_server => true,
|
1736
|
+
:description => 'Defines the maximum number of span events reported from a single harvest.'
|
1685
1737
|
}
|
1686
1738
|
}.freeze
|
1687
1739
|
end
|
@@ -10,6 +10,7 @@ module NewRelic
|
|
10
10
|
# response, but should still be merged in as config settings to the
|
11
11
|
# main agent configuration.
|
12
12
|
TOP_LEVEL_KEYS = [
|
13
|
+
"account_id",
|
13
14
|
"apdex_t",
|
14
15
|
"application_id",
|
15
16
|
"beacon",
|
@@ -24,7 +25,11 @@ module NewRelic
|
|
24
25
|
"error_beacon",
|
25
26
|
"js_agent_file",
|
26
27
|
"js_agent_loader",
|
27
|
-
"
|
28
|
+
"primary_application_id",
|
29
|
+
"sampling_target",
|
30
|
+
"sampling_target_period_in_seconds",
|
31
|
+
"trusted_account_ids",
|
32
|
+
"trusted_account_key"
|
28
33
|
]
|
29
34
|
|
30
35
|
def initialize(connect_reply, existing_config={})
|
@@ -51,7 +51,9 @@ module NewRelic
|
|
51
51
|
end
|
52
52
|
|
53
53
|
def cross_application_tracer_enabled?
|
54
|
-
NewRelic::Agent.config[:"
|
54
|
+
!NewRelic::Agent.config[:"distributed_tracing.enabled"] &&
|
55
|
+
(NewRelic::Agent.config[:"cross_application_tracer.enabled"] ||
|
56
|
+
NewRelic::Agent.config[:cross_application_tracing])
|
55
57
|
end
|
56
58
|
|
57
59
|
def obfuscator
|
@@ -195,6 +195,20 @@ module NewRelic
|
|
195
195
|
@host = host
|
196
196
|
@port_path_or_id = port_path_or_id
|
197
197
|
@database_name = database_name
|
198
|
+
@safe_sql = nil
|
199
|
+
end
|
200
|
+
|
201
|
+
# Returns an sql statement that will be in the form most permissable by
|
202
|
+
# the config. The format will be safe for transmission to New Relic.
|
203
|
+
def safe_sql
|
204
|
+
@safe_sql ||= case Database.record_sql_method
|
205
|
+
when :obfuscated
|
206
|
+
Database.obfuscate_sql(sql)
|
207
|
+
when :raw
|
208
|
+
sql.to_s
|
209
|
+
else
|
210
|
+
nil
|
211
|
+
end
|
198
212
|
end
|
199
213
|
|
200
214
|
# This takes a connection config hash from ActiveRecord or Sequel and
|
@@ -8,14 +8,13 @@ require 'new_relic/agent/cross_app_tracing'
|
|
8
8
|
module NewRelic
|
9
9
|
module Agent
|
10
10
|
class DistributedTraceMonitor < InboundRequestMonitor
|
11
|
-
NEWRELIC_TRACE_KEY = 'HTTP_X_NEWRELIC_TRACE'.freeze
|
12
|
-
HTTP_TRANSPORT_TYPE = 'HTTP'.freeze
|
13
|
-
|
14
11
|
def on_finished_configuring(events)
|
15
12
|
return unless NewRelic::Agent.config[:'distributed_tracing.enabled']
|
16
13
|
events.subscribe(:before_call, &method(:on_before_call))
|
17
14
|
end
|
18
15
|
|
16
|
+
NEWRELIC_TRACE_KEY = 'HTTP_NEWRELIC'
|
17
|
+
|
19
18
|
def on_before_call(request)
|
20
19
|
return unless NewRelic::Agent.config[:'distributed_tracing.enabled']
|
21
20
|
return unless payload = request[NEWRELIC_TRACE_KEY]
|
@@ -23,9 +22,20 @@ module NewRelic
|
|
23
22
|
state = NewRelic::Agent::TransactionState.tl_get
|
24
23
|
txn = state.current_transaction
|
25
24
|
if txn.accept_distributed_trace_payload payload
|
26
|
-
txn.distributed_trace_payload.caller_transport_type =
|
25
|
+
txn.distributed_trace_payload.caller_transport_type = transport_type(request)
|
27
26
|
end
|
28
27
|
end
|
28
|
+
|
29
|
+
URL_SCHEMES = {
|
30
|
+
'http' => 'HTTP'.freeze,
|
31
|
+
'https' => 'HTTPS'.freeze
|
32
|
+
}
|
33
|
+
|
34
|
+
RACK_URL_SCHEME = 'rack.url_scheme'.freeze
|
35
|
+
|
36
|
+
def transport_type(request)
|
37
|
+
URL_SCHEMES[request[RACK_URL_SCHEME]]
|
38
|
+
end
|
29
39
|
end
|
30
40
|
end
|
31
41
|
end
|
@@ -3,9 +3,16 @@
|
|
3
3
|
# See https://github.com/newrelic/rpm/blob/master/LICENSE for complete details.
|
4
4
|
require 'json'
|
5
5
|
require 'base64'
|
6
|
+
require 'set'
|
6
7
|
|
7
8
|
module NewRelic
|
8
9
|
module Agent
|
10
|
+
#
|
11
|
+
# This class contains properties related to distributed traces.
|
12
|
+
# To obtain an instance, call
|
13
|
+
# {DistributedTracing#create_distributed_trace_payload}
|
14
|
+
#
|
15
|
+
# @api public
|
9
16
|
class DistributedTracePayload
|
10
17
|
VERSION =[0, 1].freeze
|
11
18
|
PARENT_TYPE = "App".freeze
|
@@ -17,10 +24,11 @@ module NewRelic
|
|
17
24
|
PARENT_TYPE_KEY = 'ty'.freeze
|
18
25
|
PARENT_ACCOUNT_ID_KEY = 'ac'.freeze
|
19
26
|
PARENT_APP_KEY = 'ap'.freeze
|
27
|
+
TRUSTED_ACCOUNT_KEY = 'tk'.freeze
|
20
28
|
ID_KEY = 'id'.freeze
|
29
|
+
TX_KEY = 'tx'.freeze
|
21
30
|
TRACE_ID_KEY = 'tr'.freeze
|
22
31
|
SAMPLED_KEY = 'sa'.freeze
|
23
|
-
PARENT_ID_KEY = 'pa'.freeze
|
24
32
|
TIMESTAMP_KEY = 'ti'.freeze
|
25
33
|
PRIORITY_KEY = 'pr'.freeze
|
26
34
|
|
@@ -32,9 +40,9 @@ module NewRelic
|
|
32
40
|
PARENT_TRANSPORT_DURATION_INTRINSIC_KEY = "parent.transportDuration".freeze
|
33
41
|
GUID_INTRINSIC_KEY = "guid".freeze
|
34
42
|
TRACE_ID_INTRINSIC_KEY = "traceId".freeze
|
35
|
-
TRIP_ID_INTRINSIC_KEY = "nr.tripId".freeze
|
36
43
|
PARENT_ID_INTRINSIC_KEY = "parentId".freeze
|
37
|
-
|
44
|
+
PARENT_SPAN_ID_INTRINSIC_KEY = "parentSpanId".freeze
|
45
|
+
SAMPLED_INTRINSIC_KEY = "sampled".freeze
|
38
46
|
COMMA = ",".freeze
|
39
47
|
|
40
48
|
INTRINSIC_KEYS = [
|
@@ -45,58 +53,54 @@ module NewRelic
|
|
45
53
|
PARENT_TRANSPORT_DURATION_INTRINSIC_KEY,
|
46
54
|
GUID_INTRINSIC_KEY,
|
47
55
|
TRACE_ID_INTRINSIC_KEY,
|
48
|
-
TRIP_ID_INTRINSIC_KEY,
|
49
56
|
PARENT_ID_INTRINSIC_KEY,
|
50
|
-
|
57
|
+
PARENT_SPAN_ID_INTRINSIC_KEY,
|
58
|
+
SAMPLED_INTRINSIC_KEY
|
51
59
|
].freeze
|
52
60
|
|
53
61
|
# Intrinsic Values
|
54
|
-
PARENT_TRANSPORT_TYPE_UNKNOWN = '
|
62
|
+
PARENT_TRANSPORT_TYPE_UNKNOWN = 'Unknown'.freeze
|
55
63
|
|
56
64
|
class << self
|
65
|
+
|
57
66
|
def for_transaction transaction
|
58
|
-
|
59
|
-
return payload unless connected?
|
67
|
+
return nil unless connected?
|
60
68
|
|
69
|
+
payload = new
|
61
70
|
payload.version = VERSION
|
62
71
|
payload.parent_type = PARENT_TYPE
|
72
|
+
payload.parent_account_id = Agent.config[:account_id]
|
73
|
+
payload.parent_app_id = Agent.config[:primary_application_id]
|
63
74
|
|
64
|
-
|
65
|
-
# seen nil account ids coming down in staging for some accounts
|
66
|
-
account_id, fallback_app_id = Agent.config[:cross_process_id].split(POUND)
|
67
|
-
payload.parent_account_id = account_id
|
68
|
-
|
69
|
-
payload.parent_app_id = if Agent.config[:application_id].empty?
|
70
|
-
fallback_app_id
|
71
|
-
else
|
72
|
-
Agent.config[:application_id]
|
73
|
-
end
|
75
|
+
assign_trusted_account_key(payload, payload.parent_account_id)
|
74
76
|
|
77
|
+
payload.id = current_segment_id(transaction)
|
78
|
+
payload.transaction_id = transaction.guid
|
75
79
|
payload.timestamp = (Time.now.to_f * 1000).round
|
76
|
-
payload.id = transaction.guid
|
77
80
|
payload.trace_id = transaction.trace_id
|
78
81
|
payload.sampled = transaction.sampled?
|
79
82
|
payload.priority = transaction.priority
|
80
|
-
payload.parent_id = transaction.parent_id
|
81
83
|
|
82
84
|
payload
|
83
85
|
end
|
84
86
|
|
85
87
|
def from_json serialized_payload
|
86
88
|
raw_payload = JSON.parse serialized_payload
|
89
|
+
return raw_payload if raw_payload.nil?
|
87
90
|
payload_data = raw_payload[DATA_KEY]
|
88
91
|
|
89
92
|
payload = new
|
90
|
-
payload.version
|
91
|
-
payload.parent_type
|
92
|
-
payload.parent_account_id
|
93
|
-
payload.parent_app_id
|
94
|
-
payload.
|
95
|
-
payload.
|
96
|
-
payload.
|
97
|
-
payload.
|
98
|
-
payload.
|
99
|
-
payload.
|
93
|
+
payload.version = raw_payload[VERSION_KEY]
|
94
|
+
payload.parent_type = payload_data[PARENT_TYPE_KEY]
|
95
|
+
payload.parent_account_id = payload_data[PARENT_ACCOUNT_ID_KEY]
|
96
|
+
payload.parent_app_id = payload_data[PARENT_APP_KEY]
|
97
|
+
payload.trusted_account_key = payload_data[TRUSTED_ACCOUNT_KEY]
|
98
|
+
payload.timestamp = payload_data[TIMESTAMP_KEY]
|
99
|
+
payload.id = payload_data[ID_KEY]
|
100
|
+
payload.transaction_id = payload_data[TX_KEY]
|
101
|
+
payload.trace_id = payload_data[TRACE_ID_KEY]
|
102
|
+
payload.sampled = payload_data[SAMPLED_KEY]
|
103
|
+
payload.priority = payload_data[PRIORITY_KEY]
|
100
104
|
|
101
105
|
payload
|
102
106
|
end
|
@@ -106,11 +110,10 @@ module NewRelic
|
|
106
110
|
from_json decoded_payload
|
107
111
|
end
|
108
112
|
|
109
|
-
|
110
|
-
def assign_intrinsics_for_first_trace transaction, transaction_payload
|
113
|
+
def assign_initial_intrinsics transaction, transaction_payload
|
111
114
|
transaction_payload[GUID_INTRINSIC_KEY] = transaction.guid
|
112
115
|
transaction_payload[TRACE_ID_INTRINSIC_KEY] = transaction.trace_id
|
113
|
-
transaction_payload[
|
116
|
+
transaction_payload[SAMPLED_INTRINSIC_KEY] = transaction.sampled?
|
114
117
|
end
|
115
118
|
|
116
119
|
def major_version_matches?(payload)
|
@@ -119,27 +122,48 @@ module NewRelic
|
|
119
122
|
|
120
123
|
private
|
121
124
|
|
122
|
-
# We use the presence of the
|
123
|
-
# have connected yet.
|
125
|
+
# We use the presence of the account_id and primary_application in the
|
126
|
+
# config to tell if we have connected yet.
|
124
127
|
def connected?
|
125
|
-
|
128
|
+
Agent.config[:account_id] && Agent.config[:primary_application_id]
|
129
|
+
end
|
130
|
+
|
131
|
+
def assign_trusted_account_key payload, account_id
|
132
|
+
trusted_account_key = Agent.config[:trusted_account_key]
|
133
|
+
|
134
|
+
if account_id != trusted_account_key
|
135
|
+
payload.trusted_account_key = trusted_account_key
|
136
|
+
end
|
137
|
+
end
|
138
|
+
|
139
|
+
def current_segment_id(transaction)
|
140
|
+
if Agent.config[:'span_events.enabled'] && transaction.sampled? &&
|
141
|
+
transaction.current_segment
|
142
|
+
transaction.current_segment.guid
|
143
|
+
end
|
126
144
|
end
|
127
145
|
end
|
128
146
|
|
129
147
|
attr_accessor :version,
|
130
148
|
:parent_type,
|
131
|
-
:caller_transport_type,
|
132
149
|
:parent_account_id,
|
133
150
|
:parent_app_id,
|
151
|
+
:trusted_account_key,
|
134
152
|
:id,
|
153
|
+
:transaction_id,
|
135
154
|
:trace_id,
|
136
155
|
:sampled,
|
137
156
|
:priority,
|
138
|
-
:parent_id,
|
139
157
|
:timestamp
|
140
158
|
|
141
159
|
alias_method :sampled?, :sampled
|
142
160
|
|
161
|
+
attr_reader :caller_transport_type
|
162
|
+
|
163
|
+
def caller_transport_type=(type)
|
164
|
+
@caller_transport_type = valid_transport_type_for(type)
|
165
|
+
end
|
166
|
+
|
143
167
|
def initialize
|
144
168
|
@caller_transport_type = PARENT_TRANSPORT_TYPE_UNKNOWN
|
145
169
|
end
|
@@ -153,25 +177,39 @@ module NewRelic
|
|
153
177
|
PARENT_TYPE_KEY => parent_type,
|
154
178
|
PARENT_ACCOUNT_ID_KEY => parent_account_id,
|
155
179
|
PARENT_APP_KEY => parent_app_id,
|
156
|
-
|
180
|
+
TX_KEY => transaction_id,
|
157
181
|
TRACE_ID_KEY => trace_id,
|
158
182
|
SAMPLED_KEY => sampled,
|
159
183
|
PRIORITY_KEY => priority,
|
160
|
-
|
161
|
-
# GRANDPARENT_ID_KEY does not go into the outbound JSON payload;
|
162
|
-
# the callee will take our parent ID as its grandparent ID
|
163
|
-
TIMESTAMP_KEY => timestamp,
|
184
|
+
TIMESTAMP_KEY => timestamp,
|
164
185
|
}
|
165
186
|
|
187
|
+
result[DATA_KEY][ID_KEY] = id if id
|
188
|
+
result[DATA_KEY][TRUSTED_ACCOUNT_KEY] = trusted_account_key if trusted_account_key
|
189
|
+
|
166
190
|
JSON.dump(result)
|
167
191
|
end
|
168
192
|
|
169
|
-
|
170
|
-
|
193
|
+
# Encode this payload as a string suitable for passing via an
|
194
|
+
# HTTP header.
|
195
|
+
#
|
196
|
+
# @return [String] Payload translated to JSON and encoded for
|
197
|
+
# inclusion in headers
|
198
|
+
#
|
199
|
+
# @api public
|
171
200
|
def http_safe
|
172
201
|
Base64.strict_encode64 to_json
|
173
202
|
end
|
174
203
|
|
204
|
+
# Represent this payload as a raw JSON string.
|
205
|
+
#
|
206
|
+
# @return [String] Payload translated to JSON
|
207
|
+
#
|
208
|
+
# @api public
|
209
|
+
def text
|
210
|
+
to_json
|
211
|
+
end
|
212
|
+
|
175
213
|
def assign_intrinsics transaction, transaction_payload
|
176
214
|
transaction_payload[PARENT_TYPE_INTRINSIC_KEY] = parent_type
|
177
215
|
transaction_payload[PARENT_APP_INTRINSIC_KEY] = parent_app_id
|
@@ -180,9 +218,28 @@ module NewRelic
|
|
180
218
|
transaction_payload[PARENT_TRANSPORT_DURATION_INTRINSIC_KEY] = transaction.transport_duration
|
181
219
|
transaction_payload[GUID_INTRINSIC_KEY] = transaction.guid
|
182
220
|
transaction_payload[TRACE_ID_INTRINSIC_KEY] = trace_id
|
183
|
-
transaction_payload[TRIP_ID_INTRINSIC_KEY] = trace_id
|
184
221
|
transaction_payload[PARENT_ID_INTRINSIC_KEY] = transaction.parent_id if transaction.parent_id
|
185
|
-
transaction_payload[
|
222
|
+
transaction_payload[PARENT_SPAN_ID_INTRINSIC_KEY] = id if id
|
223
|
+
transaction_payload[SAMPLED_INTRINSIC_KEY] = transaction.sampled?
|
224
|
+
end
|
225
|
+
|
226
|
+
private
|
227
|
+
|
228
|
+
ALLOWABLE_TRANSPORT_TYPES = Set.new(%w[
|
229
|
+
Unknown
|
230
|
+
HTTP
|
231
|
+
HTTPS
|
232
|
+
Kafka
|
233
|
+
JMS
|
234
|
+
IronMQ
|
235
|
+
AMQP
|
236
|
+
Queue
|
237
|
+
Other
|
238
|
+
]).freeze
|
239
|
+
|
240
|
+
def valid_transport_type_for(value)
|
241
|
+
return value if ALLOWABLE_TRANSPORT_TYPES.include?(value)
|
242
|
+
PARENT_TRANSPORT_TYPE_UNKNOWN
|
186
243
|
end
|
187
244
|
end
|
188
245
|
end
|