Skip to content

Commit 17f8275

Browse files
committed
Add support for Core Tracing FT and 2B options
1 parent 251d95a commit 17f8275

File tree

6 files changed

+69
-15
lines changed

6 files changed

+69
-15
lines changed

newrelic/api/transaction.py

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -658,6 +658,13 @@ def __exit__(self, exc, value, tb):
658658
def sampled(self):
659659
return self._sampled
660660

661+
@property
662+
def ct_sampled(self):
663+
# If DT doesn't sample it CT will.
664+
if not self.sampled and settings.core_tracing.enabled:
665+
return True
666+
return False
667+
661668
@property
662669
def priority(self):
663670
return self._priority
@@ -1082,12 +1089,13 @@ def _create_distributed_trace_data(self):
10821089
return
10831090

10841091
self._compute_sampled_and_priority()
1092+
sampled = self.sampled or self.ct_sampled
10851093
data = {
10861094
"ty": "App",
10871095
"ac": account_id,
10881096
"ap": application_id,
10891097
"tr": self.trace_id,
1090-
"sa": self.sampled,
1098+
"sa": sampled,
10911099
"pr": self.priority,
10921100
"tx": self.guid,
10931101
"ti": int(time.time() * 1000.0),

newrelic/common/streaming_utils.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ def __init__(self, maxlen, batching=False):
3838
self._bytes = 0
3939
self._ft_bytes = 0
4040
self._ct_bytes = 0
41+
self.ct_processing_time = 0
4142
self._settings = None
4243

4344
self.batching = batching
@@ -98,8 +99,10 @@ def stats(self):
9899
self._ft_seen, self._ft_dropped = 0, 0
99100
_bytes, ft_bytes, ct_bytes = self._bytes, self._ft_bytes, self._ct_bytes
100101
self._bytes, self._ft_bytes, self._ct_bytes = 0, 0, 0
102+
ct_processing_time = self._ct_processing_time
103+
self._ct_processing_time = 0
101104

102-
return seen, dropped, ft_seen, ft_dropped, _bytes, ft_bytes, ct_bytes
105+
return seen, dropped, ft_seen, ft_dropped, _bytes, ft_bytes, ct_byte, ct_processing_times
103106

104107
def __bool__(self):
105108
return bool(self._queue)

newrelic/core/application.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1364,7 +1364,7 @@ def harvest(self, shutdown=False, flexible=False):
13641364
# Only merge stats as part of default harvest
13651365
if span_stream is not None and not flexible:
13661366
print("\n\r\n\r\n\rSending Supportability metrics for inifinte tracing\n\r\n\r\n\r")
1367-
spans_seen, spans_dropped, spans_ft_seen, spans_ft_dropped, _bytes, ft_bytes, ct_bytes = span_stream.stats()
1367+
spans_seen, spans_dropped, spans_ft_seen, spans_ft_dropped, _bytes, ft_bytes, ct_bytes, ct_processing_time = span_stream.stats()
13681368
spans_sent = spans_seen - spans_dropped
13691369
spans_ft_sent = spans_ft_seen - spans_ft_dropped
13701370

@@ -1375,6 +1375,7 @@ def harvest(self, shutdown=False, flexible=False):
13751375
internal_count_metric("Supportability/InfiniteTracing/Bytes/Seen", _bytes)
13761376
internal_count_metric("Supportability/FullTracing/Bytes/Seen", ft_bytes)
13771377
internal_count_metric("Supportability/CoreTracing/Bytes/Seen", ct_bytes)
1378+
internal_count_metric("Supportability/CoreTracing/TotalTime", ct_processing_time*1000) # Time in ms.
13781379
else:
13791380
spans = stats.span_events
13801381
if spans:
@@ -1396,6 +1397,7 @@ def harvest(self, shutdown=False, flexible=False):
13961397
internal_count_metric("Supportability/DistributedTracing/Bytes/Seen", spans.bytes)
13971398
internal_count_metric("Supportability/FullTracing/Bytes/Seen", spans.ft_bytes)
13981399
internal_count_metric("Supportability/CoreTracing/Bytes/Seen", spans.ct_bytes)
1400+
internal_count_metric("Supportability/SpanEvent/TotalCoreTracingTime", spans.ct_processing_time*1000) # Time in ms.
13991401

14001402
stats.reset_span_events()
14011403

newrelic/core/node_mixin.py

Lines changed: 41 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -70,34 +70,69 @@ def span_event(self, settings, base_attrs=None, parent_guid=None, attr_class=dic
7070
)
7171

7272
# intrinsics, user attrs, agent attrs
73-
if settings.core_tracing.drop_inprocess_spans:
73+
if settings.core_tracing.drop_inprocess_spans or settings.core_tracing.enabled:
7474
if not parent_guid:
7575
return [i_attrs, u_attrs, a_attrs]
76-
set_inprocess_attrs = set(attribute.SPAN_ENTITY_RELATIONSHIP_ATTRIBUTES)
76+
set_inprocess_attrs = attribute.SPAN_ENTITY_RELATIONSHIP_ATTRIBUTES
7777
set_a_attrs = set(a_attrs)
7878
exit_span_attrs_present = set_inprocess_attrs & set_a_attrs
7979
if not exit_span_attrs_present:
8080
return None
81+
if settings.core_tracing.enabled:
82+
a_attrs["ids"] = [] # This is the list of span guids that share this unqiue exit span.
8183

8284
set_inprocess_attrs = set(attribute.SPAN_ENTITY_RELATIONSHIP_ATTRIBUTES)
8385
set_a_attrs = set(a_attrs)
8486
exit_span_attrs_present = set_inprocess_attrs & set_a_attrs
8587
return [i_attrs, u_attrs, a_attrs, exit_span_attrs_present]
8688

87-
def span_events(self, settings, base_attrs=None, parent_guid=None, attr_class=dict):
89+
def span_events(self, settings, base_attrs=None, parent_guid=None, attr_class=dict, ct_exit_spans=None, ct_processing_time=0):
8890
if settings.core_tracing.drop_inprocess_spans:
91+
ct_exit_spans = ct_exit_spans or {}
8992
span = self.span_event(settings, base_attrs=base_attrs, parent_guid=parent_guid, attr_class=attr_class)
93+
start_time = time.time()
9094
parent_id = parent_guid
9195
if span: # span will be None if the span is an inprocess span.
9296
yield span
9397
parent_id = self.guid
94-
9598
for child in self.children:
9699
for event in child.span_events( # noqa: UP028
97-
settings, base_attrs=base_attrs, parent_guid=parent_id, attr_class=attr_class
100+
settings, base_attrs=base_attrs, parent_guid=parent_id, attr_class=attr_class, ct_exit_spans=ct_exit_spans, ct_processing_time=ct_processing_time
98101
):
99102
if event:
100103
yield event
104+
elif settings.core_tracing.enabled:
105+
ct_exit_spans = ct_exit_spans or {}
106+
span = self.span_event(settings, base_attrs=base_attrs, parent_guid=parent_guid, attr_class=attr_class)
107+
start_time = time.time()
108+
parent_id = parent_guid
109+
if span: # span will be None if the span is an inprocess span.
110+
span_attrs = "".join([value for key, value in span[2].items() if key in attribute.SPAN_ENTITY_RELATIONSHIP_ATTRIBUTES])
111+
new_exit_span = span_attrs not in ct_exit_spans
112+
if parent_id: # If this is not the entry span.
113+
if new_exit_span:
114+
ct_exit_spans[span_attrs] = span
115+
else:
116+
ct_exit_spans[span_attrs][2]["ids"] = event[2]["guid"]
117+
ct_processing_time += (time.time() - start_time)
118+
if not parent_id or new_exit_span:
119+
yield span
120+
parent_id = self.guid
121+
for child in self.children:
122+
for event in child.span_events( # noqa: UP028
123+
settings, base_attrs=base_attrs, parent_guid=parent_id, attr_class=attr_class, ct_exit_spans=ct_exit_spans, ct_processing_time=ct_processing_time
124+
):
125+
if event:
126+
start_time = time.time()
127+
span_attrs = "".join([value for key, value in event[2].items() if key in attribute.SPAN_ENTITY_RELATIONSHIP_ATTRIBUTES])
128+
new_exit_span = span_attrs not in ct_exit_spans
129+
if new_exit_span:
130+
ct_exit_spans[span_attrs] = event
131+
else:
132+
ct_exit_spans[span_attrs][2]["ids"] = event[2]["guid"]
133+
ct_processing_time += (time.time() - start_time)
134+
if new_exit_span:
135+
yield event
101136
else:
102137
yield self.span_event(settings, base_attrs=base_attrs, parent_guid=parent_guid, attr_class=attr_class)
103138

@@ -168,7 +203,7 @@ def span_event(self, *args, **kwargs):
168203
pass
169204

170205
# intrinsics, user attrs, agent attrs
171-
if settings.core_tracing.drop_inprocess_spans:
206+
if settings.core_tracing.drop_inprocess_spans or settings.core_tracing.enabled:
172207
if not parent_guid:
173208
return [i_attrs, u_attrs, a_attrs]
174209
set_inprocess_attrs = set(attribute.SPAN_ENTITY_RELATIONSHIP_ATTRIBUTES)

newrelic/core/stats_engine.py

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -458,6 +458,7 @@ def __init__(self, capacity=100):
458458
self.bytes = 0
459459
self.ft_bytes = 0
460460
self.ct_bytes = 0
461+
self.ct_processing_time = 0
461462

462463
if capacity <= 0:
463464

@@ -1262,11 +1263,16 @@ def record_transaction(self, transaction):
12621263

12631264
if settings.distributed_tracing.enabled and settings.span_events.enabled and settings.collect_span_events:
12641265
if settings.infinite_tracing.enabled:
1265-
for event in transaction.span_protos(settings):
1266+
ct_processing_time = 0
1267+
for event in transaction.span_protos(settings, ct_processing_time=ct_processing_time):
12661268
self._span_stream.put(event)
1269+
self._span_stream._ct_processing_time += ct_processing_time
12671270
elif transaction.sampled:
1268-
for event in transaction.span_events(self.__settings):
1271+
ct_processing_time = 0
1272+
for event in transaction.span_events(self.__settings, ct_processing_time=ct_processing_time):
12691273
self._span_events.add(event, priority=transaction.priority)
1274+
self._span_events.ct_processing_time += ct_processing_time
1275+
12701276

12711277
# Merge in log events
12721278

newrelic/core/transaction_node.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -620,14 +620,14 @@ def _add_call_count(source, target):
620620

621621
return intrinsics
622622

623-
def span_protos(self, settings):
624-
for span in self.span_events(settings, attr_class=SpanProtoAttrs):
623+
def span_protos(self, settings, ct_process_time=0):
624+
for span in self.span_events(settings, attr_class=SpanProtoAttrs, ct_process_time=ct_process_time):
625625
if len(span) > 3:
626626
yield Span(trace_id=self.trace_id, intrinsics=span[0], user_attributes=span[1], agent_attributes=span[2]), span[3]
627627
else:
628628
yield Span(trace_id=self.trace_id, intrinsics=span[0], user_attributes=span[1], agent_attributes=span[2])
629629

630-
def span_events(self, settings, attr_class=dict):
630+
def span_events(self, settings, attr_class=dict, ct_processing_time=0):
631631
base_attrs = attr_class(
632632
(
633633
("transactionId", self.guid),
@@ -637,4 +637,4 @@ def span_events(self, settings, attr_class=dict):
637637
)
638638
)
639639

640-
yield from self.root.span_events(settings, base_attrs, parent_guid=self.parent_span, attr_class=attr_class)
640+
yield from self.root.span_events(settings, base_attrs, parent_guid=self.parent_span, attr_class=attr_class, ct_processing_time=ct_processing_time)

0 commit comments

Comments
 (0)