From c3c3ef84ca69ab61c34155c9fbf5bf16457c0b33 Mon Sep 17 00:00:00 2001 From: Hannah Stepanek Date: Fri, 6 Jun 2025 10:33:53 -0700 Subject: [PATCH 1/3] Reorder inheritance on span nodes Core tracing will be adding a bunch of logic to the span_event method which is called via super on inheriting classes before those inheriting classes add additional attributes. In order for the core tracing logic to work correctly, this inheritance call order has to be reversed; the inheriting classes must first add the attributes and THEN call super. --- newrelic/core/external_node.py | 11 +++++------ newrelic/core/function_node.py | 8 +++----- newrelic/core/loop_node.py | 8 +++----- newrelic/core/node_mixin.py | 25 ++++++++++++------------- newrelic/core/root_node.py | 8 ++++---- 5 files changed, 27 insertions(+), 33 deletions(-) diff --git a/newrelic/core/external_node.py b/newrelic/core/external_node.py index 9165d2081f..6afd6a7422 100644 --- a/newrelic/core/external_node.py +++ b/newrelic/core/external_node.py @@ -169,16 +169,15 @@ def trace_node(self, stats, root, connections): start_time=start_time, end_time=end_time, name=name, params=params, children=children, label=None ) - def span_event(self, *args, **kwargs): + def span_event(self, settings, base_attrs=None, parent_guid=None, attr_class=dict, *args, **kwargs): self.agent_attributes["http.url"] = self.http_url - attrs = super().span_event(*args, **kwargs) - i_attrs = attrs[0] + i_attrs = base_attrs and base_attrs.copy() or attr_class() i_attrs["category"] = "http" i_attrs["span.kind"] = "client" - _, i_attrs["component"] = attribute.process_user_attribute("component", self.library) + i_attrs["component"] = self.library if self.method: - _, i_attrs["http.method"] = attribute.process_user_attribute("http.method", self.method) + i_attrs["http.method"] = self.method - return attrs + return super().span_event(settings, base_attrs=i_attrs, parent_guid=parent_guid, attr_class=attr_class, *args, **kwargs) diff --git a/newrelic/core/function_node.py b/newrelic/core/function_node.py index 809f26742c..2973749c46 100644 --- a/newrelic/core/function_node.py +++ b/newrelic/core/function_node.py @@ -114,10 +114,8 @@ def trace_node(self, stats, root, connections): start_time=start_time, end_time=end_time, name=name, params=params, children=children, label=self.label ) - def span_event(self, *args, **kwargs): - attrs = super().span_event(*args, **kwargs) - i_attrs = attrs[0] - + def span_event(self, settings, base_attrs=None, parent_guid=None, attr_class=dict, *args, **kwargs): + i_attrs = base_attrs and base_attrs.copy() or attr_class() i_attrs["name"] = f"{self.group}/{self.name}" - return attrs + return super().span_event(settings, base_attrs=i_attrs, parent_guid=parent_guid, attr_class=attr_class, *args, **kwargs) diff --git a/newrelic/core/loop_node.py b/newrelic/core/loop_node.py index b9328e7013..7a9ae1c371 100644 --- a/newrelic/core/loop_node.py +++ b/newrelic/core/loop_node.py @@ -79,10 +79,8 @@ def trace_node(self, stats, root, connections): start_time=start_time, end_time=end_time, name=name, params=params, children=children, label=None ) - def span_event(self, *args, **kwargs): - attrs = super().span_event(*args, **kwargs) - i_attrs = attrs[0] - + def span_event(self, settings, base_attrs=None, parent_guid=None, attr_class=dict, *args, **kwargs): + i_attrs = base_attrs and base_attrs.copy() or attr_class() i_attrs["name"] = f"EventLoop/Wait/{self.name}" - return attrs + return super().span_event(settings, base_attrs=i_attrs, parent_guid=parent_guid, attr_class=attr_class, *args, **kwargs) diff --git a/newrelic/core/node_mixin.py b/newrelic/core/node_mixin.py index 8eedd191d4..2bc46e4187 100644 --- a/newrelic/core/node_mixin.py +++ b/newrelic/core/node_mixin.py @@ -52,11 +52,11 @@ def get_trace_segment_params(self, settings, params=None): def span_event(self, settings, base_attrs=None, parent_guid=None, attr_class=dict): i_attrs = (base_attrs and base_attrs.copy()) or attr_class() i_attrs["type"] = "Span" - i_attrs["name"] = self.name + i_attrs["name"] = i_attrs.get("name") or self.name i_attrs["guid"] = self.guid i_attrs["timestamp"] = int(self.start_time * 1000) i_attrs["duration"] = self.duration - i_attrs["category"] = "generic" + i_attrs["category"] = i_attrs.get("category") or "generic" if parent_guid: i_attrs["parentId"] = parent_guid @@ -108,24 +108,23 @@ def db_instance(self): self._db_instance = db_instance_attr return db_instance_attr - def span_event(self, *args, **kwargs): - self.agent_attributes["db.instance"] = self.db_instance - attrs = super().span_event(*args, **kwargs) - i_attrs = attrs[0] - a_attrs = attrs[2] + def span_event(self, settings, base_attrs=None, parent_guid=None, attr_class=dict, *args, **kwargs): + a_attrs = self.agent_attributes + a_attrs["db.instance"] = self.db_instance + i_attrs = base_attrs and base_attrs.copy() or attr_class() i_attrs["category"] = "datastore" i_attrs["span.kind"] = "client" if self.product: - i_attrs["component"] = a_attrs["db.system"] = attribute.process_user_attribute("db.system", self.product)[1] + i_attrs["component"] = a_attrs["db.system"] = self.product if self.operation: - a_attrs["db.operation"] = attribute.process_user_attribute("db.operation", self.operation)[1] + a_attrs["db.operation"] = self.operation if self.target: - a_attrs["db.collection"] = attribute.process_user_attribute("db.collection", self.target)[1] + a_attrs["db.collection"] = self.target if self.instance_hostname: - peer_hostname = attribute.process_user_attribute("peer.hostname", self.instance_hostname)[1] + peer_hostname = self.instance_hostname else: peer_hostname = "Unknown" @@ -133,7 +132,7 @@ def span_event(self, *args, **kwargs): peer_address = f"{peer_hostname}:{self.port_path_or_id or 'Unknown'}" - a_attrs["peer.address"] = attribute.process_user_attribute("peer.address", peer_address)[1] + a_attrs["peer.address"] = peer_address # Attempt to treat port_path_or_id as an integer, fallback to not including it try: @@ -141,4 +140,4 @@ def span_event(self, *args, **kwargs): except Exception: pass - return attrs + return super().span_event(settings, base_attrs=i_attrs, parent_guid=parent_guid, attr_class=attr_class, *args, **kwargs) diff --git a/newrelic/core/root_node.py b/newrelic/core/root_node.py index 1591afa3ad..030ea07a62 100644 --- a/newrelic/core/root_node.py +++ b/newrelic/core/root_node.py @@ -37,16 +37,16 @@ class RootNode(_RootNode, GenericNodeMixin): - def span_event(self, *args, **kwargs): - span = super().span_event(*args, **kwargs) - i_attrs = span[0] + def span_event(self, settings, base_attrs=None, parent_guid=None, attr_class=dict, *args, **kwargs): + i_attrs = base_attrs and base_attrs.copy() or attr_class() i_attrs["transaction.name"] = self.path i_attrs["nr.entryPoint"] = True if self.trusted_parent_span: i_attrs["trustedParentId"] = self.trusted_parent_span if self.tracing_vendors: i_attrs["tracingVendors"] = self.tracing_vendors - return span + + return super().span_event(settings, base_attrs=i_attrs, parent_guid=parent_guid, attr_class=attr_class, *args, **kwargs) def trace_node(self, stats, root, connections): name = self.path From 744cb4ea8bf5e2ada5cafb56e12876eaac85f78f Mon Sep 17 00:00:00 2001 From: Hannah Stepanek Date: Tue, 7 Oct 2025 13:49:29 -0700 Subject: [PATCH 2/3] Remove *args, **kwargs --- newrelic/core/external_node.py | 4 ++-- newrelic/core/function_node.py | 4 ++-- newrelic/core/loop_node.py | 4 ++-- newrelic/core/node_mixin.py | 4 ++-- newrelic/core/root_node.py | 4 ++-- 5 files changed, 10 insertions(+), 10 deletions(-) diff --git a/newrelic/core/external_node.py b/newrelic/core/external_node.py index 6afd6a7422..2e68a7062f 100644 --- a/newrelic/core/external_node.py +++ b/newrelic/core/external_node.py @@ -169,7 +169,7 @@ def trace_node(self, stats, root, connections): start_time=start_time, end_time=end_time, name=name, params=params, children=children, label=None ) - def span_event(self, settings, base_attrs=None, parent_guid=None, attr_class=dict, *args, **kwargs): + def span_event(self, settings, base_attrs=None, parent_guid=None, attr_class=dict): self.agent_attributes["http.url"] = self.http_url i_attrs = base_attrs and base_attrs.copy() or attr_class() @@ -180,4 +180,4 @@ def span_event(self, settings, base_attrs=None, parent_guid=None, attr_class=dic if self.method: i_attrs["http.method"] = self.method - return super().span_event(settings, base_attrs=i_attrs, parent_guid=parent_guid, attr_class=attr_class, *args, **kwargs) + return super().span_event(settings, base_attrs=i_attrs, parent_guid=parent_guid, attr_class=attr_class) diff --git a/newrelic/core/function_node.py b/newrelic/core/function_node.py index 2973749c46..bb34ff8916 100644 --- a/newrelic/core/function_node.py +++ b/newrelic/core/function_node.py @@ -114,8 +114,8 @@ def trace_node(self, stats, root, connections): start_time=start_time, end_time=end_time, name=name, params=params, children=children, label=self.label ) - def span_event(self, settings, base_attrs=None, parent_guid=None, attr_class=dict, *args, **kwargs): + def span_event(self, settings, base_attrs=None, parent_guid=None, attr_class=dict): i_attrs = base_attrs and base_attrs.copy() or attr_class() i_attrs["name"] = f"{self.group}/{self.name}" - return super().span_event(settings, base_attrs=i_attrs, parent_guid=parent_guid, attr_class=attr_class, *args, **kwargs) + return super().span_event(settings, base_attrs=i_attrs, parent_guid=parent_guid, attr_class=attr_class) diff --git a/newrelic/core/loop_node.py b/newrelic/core/loop_node.py index 7a9ae1c371..1baa08b9e8 100644 --- a/newrelic/core/loop_node.py +++ b/newrelic/core/loop_node.py @@ -79,8 +79,8 @@ def trace_node(self, stats, root, connections): start_time=start_time, end_time=end_time, name=name, params=params, children=children, label=None ) - def span_event(self, settings, base_attrs=None, parent_guid=None, attr_class=dict, *args, **kwargs): + def span_event(self, settings, base_attrs=None, parent_guid=None, attr_class=dict): i_attrs = base_attrs and base_attrs.copy() or attr_class() i_attrs["name"] = f"EventLoop/Wait/{self.name}" - return super().span_event(settings, base_attrs=i_attrs, parent_guid=parent_guid, attr_class=attr_class, *args, **kwargs) + return super().span_event(settings, base_attrs=i_attrs, parent_guid=parent_guid, attr_class=attr_class) diff --git a/newrelic/core/node_mixin.py b/newrelic/core/node_mixin.py index 2bc46e4187..df20da3c79 100644 --- a/newrelic/core/node_mixin.py +++ b/newrelic/core/node_mixin.py @@ -108,7 +108,7 @@ def db_instance(self): self._db_instance = db_instance_attr return db_instance_attr - def span_event(self, settings, base_attrs=None, parent_guid=None, attr_class=dict, *args, **kwargs): + def span_event(self, settings, base_attrs=None, parent_guid=None, attr_class=dict): a_attrs = self.agent_attributes a_attrs["db.instance"] = self.db_instance i_attrs = base_attrs and base_attrs.copy() or attr_class() @@ -140,4 +140,4 @@ def span_event(self, settings, base_attrs=None, parent_guid=None, attr_class=dic except Exception: pass - return super().span_event(settings, base_attrs=i_attrs, parent_guid=parent_guid, attr_class=attr_class, *args, **kwargs) + return super().span_event(settings, base_attrs=i_attrs, parent_guid=parent_guid, attr_class=attr_class) diff --git a/newrelic/core/root_node.py b/newrelic/core/root_node.py index 030ea07a62..84849e4a7c 100644 --- a/newrelic/core/root_node.py +++ b/newrelic/core/root_node.py @@ -37,7 +37,7 @@ class RootNode(_RootNode, GenericNodeMixin): - def span_event(self, settings, base_attrs=None, parent_guid=None, attr_class=dict, *args, **kwargs): + def span_event(self, settings, base_attrs=None, parent_guid=None, attr_class=dict): i_attrs = base_attrs and base_attrs.copy() or attr_class() i_attrs["transaction.name"] = self.path i_attrs["nr.entryPoint"] = True @@ -46,7 +46,7 @@ def span_event(self, settings, base_attrs=None, parent_guid=None, attr_class=dic if self.tracing_vendors: i_attrs["tracingVendors"] = self.tracing_vendors - return super().span_event(settings, base_attrs=i_attrs, parent_guid=parent_guid, attr_class=attr_class, *args, **kwargs) + return super().span_event(settings, base_attrs=i_attrs, parent_guid=parent_guid, attr_class=attr_class) def trace_node(self, stats, root, connections): name = self.path From ec37cdc0fb4e8db861a119c62ca0cac356eef7e0 Mon Sep 17 00:00:00 2001 From: hmstepanek <30059933+hmstepanek@users.noreply.github.com> Date: Tue, 7 Oct 2025 20:51:18 +0000 Subject: [PATCH 3/3] [MegaLinter] Apply linters fixes --- newrelic/core/external_node.py | 2 +- newrelic/core/function_node.py | 2 +- newrelic/core/loop_node.py | 2 +- newrelic/core/node_mixin.py | 2 +- newrelic/core/root_node.py | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/newrelic/core/external_node.py b/newrelic/core/external_node.py index 2e68a7062f..bd0fde04f6 100644 --- a/newrelic/core/external_node.py +++ b/newrelic/core/external_node.py @@ -172,7 +172,7 @@ def trace_node(self, stats, root, connections): def span_event(self, settings, base_attrs=None, parent_guid=None, attr_class=dict): self.agent_attributes["http.url"] = self.http_url - i_attrs = base_attrs and base_attrs.copy() or attr_class() + i_attrs = (base_attrs and base_attrs.copy()) or attr_class() i_attrs["category"] = "http" i_attrs["span.kind"] = "client" i_attrs["component"] = self.library diff --git a/newrelic/core/function_node.py b/newrelic/core/function_node.py index bb34ff8916..588f675f31 100644 --- a/newrelic/core/function_node.py +++ b/newrelic/core/function_node.py @@ -115,7 +115,7 @@ def trace_node(self, stats, root, connections): ) def span_event(self, settings, base_attrs=None, parent_guid=None, attr_class=dict): - i_attrs = base_attrs and base_attrs.copy() or attr_class() + i_attrs = (base_attrs and base_attrs.copy()) or attr_class() i_attrs["name"] = f"{self.group}/{self.name}" return super().span_event(settings, base_attrs=i_attrs, parent_guid=parent_guid, attr_class=attr_class) diff --git a/newrelic/core/loop_node.py b/newrelic/core/loop_node.py index 1baa08b9e8..58d1b3a746 100644 --- a/newrelic/core/loop_node.py +++ b/newrelic/core/loop_node.py @@ -80,7 +80,7 @@ def trace_node(self, stats, root, connections): ) def span_event(self, settings, base_attrs=None, parent_guid=None, attr_class=dict): - i_attrs = base_attrs and base_attrs.copy() or attr_class() + i_attrs = (base_attrs and base_attrs.copy()) or attr_class() i_attrs["name"] = f"EventLoop/Wait/{self.name}" return super().span_event(settings, base_attrs=i_attrs, parent_guid=parent_guid, attr_class=attr_class) diff --git a/newrelic/core/node_mixin.py b/newrelic/core/node_mixin.py index df20da3c79..699a2d1118 100644 --- a/newrelic/core/node_mixin.py +++ b/newrelic/core/node_mixin.py @@ -111,7 +111,7 @@ def db_instance(self): def span_event(self, settings, base_attrs=None, parent_guid=None, attr_class=dict): a_attrs = self.agent_attributes a_attrs["db.instance"] = self.db_instance - i_attrs = base_attrs and base_attrs.copy() or attr_class() + i_attrs = (base_attrs and base_attrs.copy()) or attr_class() i_attrs["category"] = "datastore" i_attrs["span.kind"] = "client" diff --git a/newrelic/core/root_node.py b/newrelic/core/root_node.py index 84849e4a7c..fa8b3de82b 100644 --- a/newrelic/core/root_node.py +++ b/newrelic/core/root_node.py @@ -38,7 +38,7 @@ class RootNode(_RootNode, GenericNodeMixin): def span_event(self, settings, base_attrs=None, parent_guid=None, attr_class=dict): - i_attrs = base_attrs and base_attrs.copy() or attr_class() + i_attrs = (base_attrs and base_attrs.copy()) or attr_class() i_attrs["transaction.name"] = self.path i_attrs["nr.entryPoint"] = True if self.trusted_parent_span: