Skip to content

Commit 6fbf25c

Browse files
committed
Support multiple combos of span and attr reductions
1 parent 282e879 commit 6fbf25c

File tree

5 files changed

+46
-23
lines changed

5 files changed

+46
-23
lines changed

newrelic/api/transaction.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -661,7 +661,7 @@ def sampled(self):
661661
@property
662662
def ct_sampled(self):
663663
# If DT doesn't sample it CT will.
664-
if not self.sampled and self._settings.core_tracing.enabled:
664+
if not self.sampled and (self._settings.distributed_tracing.drop_inprocess_spans.enabled or self._settings.distributed_tracing.unique_spans.enabled):
665665
return True
666666
return False
667667

newrelic/config.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -398,9 +398,10 @@ def _process_configuration(section):
398398
_process_setting(section, "custom_insights_events.max_attribute_value", "getint", None)
399399
_process_setting(section, "ml_insights_events.enabled", "getboolean", None)
400400
_process_setting(section, "distributed_tracing.enabled", "getboolean", None)
401+
_process_setting(section, "distributed_tracing.drop_inprocess_spans.enabled", "getboolean", None)
402+
_process_setting(section, "distributed_tracing.unique_spans.enabled", "getboolean", None)
403+
_process_setting(section, "distributed_tracing.minimize_attributes.enabled", "getboolean", None)
401404
_process_setting(section, "distributed_tracing.exclude_newrelic_header", "getboolean", None)
402-
_process_setting(section, "core_tracing.drop_inprocess_spans", "getboolean", None)
403-
_process_setting(section, "core_tracing.enabled", "getboolean", None)
404405
_process_setting(section, "span_events.enabled", "getboolean", None)
405406
_process_setting(section, "span_events.max_samples_stored", "getint", None)
406407
_process_setting(section, "span_events.attributes.enabled", "getboolean", None)

newrelic/core/application.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -508,8 +508,8 @@ def connect_to_data_collector(self, activate_agent):
508508
else:
509509
sampling_target_period = configuration.sampling_target_period_in_seconds
510510
sampling_target = configuration.sampling_target
511-
# If CT is enabled double the transaction reservoir size.
512-
if configuration.core_tracing.enabled:
511+
# If span reduction is enabled double the transaction reservoir size.
512+
if configuration.distributed_tracing.drop_inprocess_spans.enabled or configuration.distributed_tracing.unique_spans.enabled:
513513
sampling_target = configuration.sampling_target*2
514514
self.adaptive_sampler = AdaptiveSampler(sampling_target, sampling_target_period)
515515

newrelic/core/config.py

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -324,7 +324,15 @@ class DistributedTracingSettings(Settings):
324324
pass
325325

326326

327-
class CoreTracingSettings(Settings):
327+
class DistributedTracingDropInprocessSpansSettings(Settings):
328+
pass
329+
330+
331+
class DistributedTracingUniqueSpansSettings(Settings):
332+
pass
333+
334+
335+
class DistributedTracingMinimizeAttributesSettings(Settings):
328336
pass
329337

330338

@@ -497,7 +505,9 @@ class EventHarvestConfigHarvestLimitSettings(Settings):
497505
_settings.datastore_tracer.instance_reporting = DatastoreTracerInstanceReportingSettings()
498506
_settings.debug = DebugSettings()
499507
_settings.distributed_tracing = DistributedTracingSettings()
500-
_settings.core_tracing = CoreTracingSettings()
508+
_settings.distributed_tracing.drop_inprocess_spans = DistributedTracingDropInprocessSpansSettings()
509+
_settings.distributed_tracing.unique_spans = DistributedTracingUniqueSpansSettings()
510+
_settings.distributed_tracing.minimize_attributes = DistributedTracingMinimizeAttributesSettings()
501511
_settings.error_collector = ErrorCollectorSettings()
502512
_settings.error_collector.attributes = ErrorCollectorAttributesSettings()
503513
_settings.event_harvest_config = EventHarvestConfigSettings()
@@ -819,8 +829,9 @@ def default_otlp_host(host):
819829
_settings.ml_insights_events.enabled = False
820830

821831
_settings.distributed_tracing.enabled = _environ_as_bool("NEW_RELIC_DISTRIBUTED_TRACING_ENABLED", default=True)
822-
_settings.core_tracing.drop_inprocess_spans = _environ_as_bool("NEW_RELIC_CORE_TRACING_DROP_INPROCESS_SPANS", default=False)
823-
_settings.core_tracing.enabled = _environ_as_bool("NEW_RELIC_CORE_TRACING_ENABLED", default=True)
832+
_settings.distributed_tracing.drop_inprocess_spans.enabled = _environ_as_bool("NEW_RELIC_DISTRIBUTED_TRACING_DROP_INPROCESS_SPANS_ENABLED", default=True)
833+
_settings.distributed_tracing.unique_spans.enabled = _environ_as_bool("NEW_RELIC_DISTRIBUTED_TRACING_UNIQUE_SPANS_ENABLED", default=False)
834+
_settings.distributed_tracing.minimize_attributes.enabled = _environ_as_bool("NEW_RELIC_DISTRIBUTED_TRACING_MINIMIZE_ATTRIBUTES_ENABLED", default=True)
824835
_settings.distributed_tracing.exclude_newrelic_header = False
825836
_settings.span_events.enabled = _environ_as_bool("NEW_RELIC_SPAN_EVENTS_ENABLED", default=True)
826837
_settings.span_events.attributes.enabled = True

newrelic/core/node_mixin.py

Lines changed: 25 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,7 @@ def span_event(self, settings, base_attrs=None, parent_guid=None, attr_class=dic
6363
i_attrs["duration"] = self.duration
6464
i_attrs["category"] = "generic"
6565
# TODO: limit intrinsic attributes but this likely requires changes in the pipeline.
66-
#if settings.core_tracing.enabled:
66+
#if settings.distributed_tracing.minimize_attributes.enabled:
6767
# i_ct_attrs = {"type", "name", "guid", "parentId", "transaction.name", "traceId", "timestamp", "duration", "nr.entryPoint", "transactionId"}
6868
# i_attrs = {key: value for key, value in i_attrs.items() if key in i_ct_attrs}
6969

@@ -74,38 +74,49 @@ def span_event(self, settings, base_attrs=None, parent_guid=None, attr_class=dic
7474
self.agent_attributes, settings.attribute_filter, DST_SPAN_EVENTS, attr_class=attr_class
7575
)
7676
u_attrs = self.processed_user_attributes
77-
if settings.core_tracing.enabled:
77+
if settings.distributed_tracing.unique_spans.enabled:
7878
# ids is the list of span guids that share this unqiue exit span.
79-
u_attrs = {"ids": self.ids}
79+
u_attrs["ids"] = self.ids
8080

8181
u_attrs = attribute.resolve_user_attributes(
8282
u_attrs, settings.attribute_filter, DST_SPAN_EVENTS, attr_class=attr_class
8383
)
8484

8585
start_time = time.time()
86-
if settings.core_tracing.drop_inprocess_spans or settings.core_tracing.enabled:
86+
if settings.distributed_tracing.drop_inprocess_spans.enabled or settings.distributed_tracing.unique_spans.enabled:
8787
exit_span_attrs_present = attribute.SPAN_ENTITY_RELATIONSHIP_ATTRIBUTES & set(a_attrs)
88+
# If this is the entry node, always return it.
8889
if self.__class__.__name__ == "RootNode":
8990
ct_processing_time[0] += (time.time() - start_time)
90-
return [i_attrs, {}, {}] if settings.core_tracing.enabled else [i_attrs, u_attrs, a_attrs]
91+
return [i_attrs, u_attrs, {}] if settings.distributed_tracing.minimize_attributes.enabled else [i_attrs, u_attrs, a_attrs]
92+
# If the span is not an exit span, skip it by returning None.
9193
if not exit_span_attrs_present:
9294
ct_processing_time[0] += (time.time() - start_time)
9395
return None
94-
if settings.core_tracing.enabled:
95-
a_attrs = attr_class({key: a_attrs[key] for key in exit_span_attrs_present})
96-
# TODO: use attr value name rather than str casting.
97-
span_attrs = "".join([str(a_attrs[key]) for key in exit_span_attrs_present])
96+
# If the span is an exit span but unique spans is enabled, we need to check
97+
# for uniqueness before returning it.
98+
if settings.distributed_tracing.unique_spans.enabled:
99+
a_minimized_attrs = attr_class({key: a_attrs[key] for key in exit_span_attrs_present})
100+
# Combine all the entity relationship attr values into a string to be
101+
# used as the hash to check for uniqueness.
102+
# TODO: use attr value name rather than str casting for infinite tracing.
103+
span_attrs = "".join([str(a_minimized_attrs[key]) for key in exit_span_attrs_present])
98104
new_exit_span = span_attrs not in ct_exit_spans
105+
# If this is a new exit span, add it to the known ct_exit_spans and return it.
99106
if new_exit_span:
100107
ct_exit_spans[span_attrs] = self.ids
101-
else:
102-
# For now add ids to user attributes list
103-
ct_exit_spans[span_attrs].append(self.guid)
104-
if new_exit_span:
105108
ct_processing_time[0] += (time.time() - start_time)
106-
return [i_attrs, u_attrs, a_attrs]
109+
return [i_attrs, u_attrs, a_minimized_attrs] if settings.distributed_tracing.minimize_attributes.enabled else [i_attrs, u_attrs, a_attrs]
110+
# If this is an exit span we've already seen, add it's guid to the list
111+
# of ids on the seen span and return None.
112+
# For now add ids to user attributes list
113+
ct_exit_spans[span_attrs].append(self.guid)
107114
ct_processing_time[0] += (time.time() - start_time)
108115
return None
116+
elif settings.distributed_tracing.minimize_attributes.enabled:
117+
# Drop all non-entity relationship attributes from the span.
118+
exit_span_attrs_present = attribute.SPAN_ENTITY_RELATIONSHIP_ATTRIBUTES & set(a_attrs)
119+
a_attrs = attr_class({key: a_attrs[key] for key in exit_span_attrs_present})
109120
ct_processing_time[0] += (time.time() - start_time)
110121
return [i_attrs, u_attrs, a_attrs]
111122

0 commit comments

Comments
 (0)