feat: add resource name for Haystack Component Datadog spans (#9337)

* feat: add resource name for Haystack Component Datadog spans

* fest: format resource name

Signed-off-by: Ahmad Zidan <ahmad.zidan@traveloka.com>

* feat: add release notes

Signed-off-by: Ahmad Zidan <ahmad.zidan@traveloka.com>

---------

Signed-off-by: Ahmad Zidan <ahmad.zidan@traveloka.com>
Co-authored-by: Sebastian Husch Lee <10526848+sjrl@users.noreply.github.com>
This commit is contained in:
Ahmad Zidan 2025-06-18 16:15:15 +07:00 committed by GitHub
parent 3784889e5d
commit f911459647
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 35 additions and 3 deletions

View File

@ -14,6 +14,10 @@ with LazyImport("Run 'pip install ddtrace'") as ddtrace_import:
from ddtrace.trace import Span as ddSpan
from ddtrace.trace import Tracer as ddTracer
_COMPONENT_NAME_KEY = "haystack.component.name"
_COMPONENT_TYPE_KEY = "haystack.component.type"
_COMPONENT_RUN_OPERATION_NAME = "haystack.component.run"
class DatadogSpan(Span):
def __init__(self, span: "ddSpan") -> None:
@ -60,12 +64,27 @@ class DatadogTracer(Tracer):
ddtrace_import.check()
self._tracer = tracer
@staticmethod
def _get_span_resource_name(operation_name: str, tags: Optional[Dict[str, Any]]) -> Optional[str]:
"""
Get the resource name for the Datadog span.
"""
if operation_name == _COMPONENT_RUN_OPERATION_NAME and tags:
component_type = tags.get(_COMPONENT_TYPE_KEY, "")
component_name = tags.get(_COMPONENT_NAME_KEY, "")
return f"{component_type}: {component_name}"
return None
@contextlib.contextmanager
def trace(
self, operation_name: str, tags: Optional[Dict[str, Any]] = None, parent_span: Optional[Span] = None
) -> Iterator[Span]:
"""Activate and return a new span that inherits from the current active span."""
with self._tracer.trace(operation_name) as span:
resource_name = self._get_span_resource_name(operation_name, tags)
with self._tracer.trace(name=operation_name, resource=resource_name) as span:
custom_span = DatadogSpan(span)
if tags:
custom_span.set_tags(tags)

View File

@ -0,0 +1,4 @@
---
enhancements:
- |
For component run Datadog tracing, set the span resource name to the component name instead of the operation name.

View File

@ -47,7 +47,14 @@ class TestDatadogTracer:
def test_opentelemetry_tracer(self, datadog_tracer: ddTracer, capfd: CaptureFixture) -> None:
tracer = DatadogTracer(datadog_tracer)
with tracer.trace("test") as span:
component_tags = {
"haystack.component.name": "test_component",
"haystack.component.type": "TestType",
"haystack.component.input": {"input_key": "input_value"},
"haystack.component.output": {"output_key": "output_value"},
}
with tracer.trace("haystack.component.run", tags=component_tags) as span:
span.set_tag("key", "value")
traces = get_traces_from_console(capfd)
@ -55,7 +62,9 @@ class TestDatadogTracer:
trace = traces[0]
assert trace["name"] == "test"
assert trace["name"] == "haystack.component.run"
assert "test_component" in trace["resource"]
assert "TestType" in trace["resource"]
def test_tagging(self, datadog_tracer: ddTracer, capfd: CaptureFixture) -> None:
tracer = DatadogTracer(datadog_tracer)