Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 21 additions & 2 deletions ddtrace/_trace/span.py
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@
from ddtrace.internal.utils.time import Time
from ddtrace.settings._config import config
from ddtrace.vendor.debtcollector import deprecate
from ddtrace.vendor.debtcollector import removals


class SpanEvent:
Expand Down Expand Up @@ -406,17 +407,35 @@ def set_tag(self, key: _TagNameType, value: Any = None) -> None:
except Exception:
log.warning("error setting tag %s, ignoring it", key, exc_info=True)

def set_struct_tag(self, key: str, value: Dict[str, Any]) -> None:
def _set_struct_tag(self, key: str, value: Dict[str, Any]) -> None:
"""
Set a tag key/value pair on the span meta_struct
Currently it will only be exported with V4 encoding
"""
self._meta_struct[key] = value

def get_struct_tag(self, key: str) -> Optional[Dict[str, Any]]:
@removals.remove(removal_version="4.0.0")
def set_struct_tag(self, key: str, value: Dict[str, Any]) -> None:
"""
DEPRECATED

Set a tag key/value pair on the span meta_struct
Currently it will only be exported with V4 encoding
"""
self._set_struct_tag(key, value)

def _get_struct_tag(self, key: str) -> Optional[Dict[str, Any]]:
"""Return the given struct or None if it doesn't exist."""
return self._meta_struct.get(key, None)

@removals.remove(removal_version="4.0.0")
def get_struct_tag(self, key: str) -> Optional[Dict[str, Any]]:
"""DEPRECATED

Return the given struct or None if it doesn't exist.
"""
return self._get_struct_tag(key)

def set_tag_str(self, key: _TagNameType, value: Text) -> None:
"""Set a value for a tag. Values are coerced to unicode in Python 2 and
str in Python 3, with decoding errors in conversion being replaced with
Expand Down
2 changes: 1 addition & 1 deletion ddtrace/appsec/_asm_request_context.py
Original file line number Diff line number Diff line change
Expand Up @@ -232,7 +232,7 @@ def flush_waf_triggers(env: ASM_Environment) -> None:
else:
report_list = env.waf_triggers
if asm_config._use_metastruct_for_triggers:
entry_span.set_struct_tag(APPSEC.STRUCT, {"triggers": report_list})
entry_span._set_struct_tag(APPSEC.STRUCT, {"triggers": report_list})
else:
entry_span.set_tag(APPSEC.JSON, json.dumps({"triggers": report_list}, separators=(",", ":")))
env.waf_triggers = []
Expand Down
4 changes: 2 additions & 2 deletions ddtrace/appsec/_exploit_prevention/stack_traces.py
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ def report_stack(

if span is None or stack_id is None:
return False
appsec_traces = span.get_struct_tag(STACK_TRACE.TAG) or {}
appsec_traces = span._get_struct_tag(STACK_TRACE.TAG) or {}
current_list = appsec_traces.get(namespace, [])
total_length = len(current_list)

Expand Down Expand Up @@ -80,5 +80,5 @@ def report_stack(
res["frames"] = frames
current_list.append(res)
appsec_traces[namespace] = current_list
span.set_struct_tag(STACK_TRACE.TAG, appsec_traces)
span._set_struct_tag(STACK_TRACE.TAG, appsec_traces)
return True
4 changes: 2 additions & 2 deletions ddtrace/appsec/_iast/_iast_request_context.py
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ def _create_and_attach_iast_report_to_span(
for source in data.get("sources", []):
if isinstance(source.get("origin"), OriginType):
source["origin"] = origin_to_str(source["origin"])
req_span.set_struct_tag(IAST.STRUCT, data)
req_span._set_struct_tag(IAST.STRUCT, data)
else:
req_span.set_tag_str(IAST.JSON, report_data._to_str(data))
_set_metric_iast_request_tainted()
Expand Down Expand Up @@ -82,7 +82,7 @@ def _iast_end_request(ctx=None, span=None, *args, **kwargs):
return

if asm_config._iast_enabled:
existing_data = req_span.get_tag(IAST.JSON) or req_span.get_struct_tag(IAST.STRUCT)
existing_data = req_span.get_tag(IAST.JSON) or req_span._get_struct_tag(IAST.STRUCT)
if existing_data is None:
if req_span.get_metric(IAST.ENABLED) is None:
if not base.is_iast_request_enabled():
Expand Down
2 changes: 1 addition & 1 deletion ddtrace/internal/ci_visibility/api/_base.py
Original file line number Diff line number Diff line change
Expand Up @@ -517,7 +517,7 @@ def _add_coverage_data_tag(self) -> None:
if self._span is None:
return
if self._coverage_data:
self._span.set_struct_tag(
self._span._set_struct_tag(
COVERAGE_TAG_NAME, self._coverage_data.build_payload(self._session_settings.workspace_path)
)

Expand Down
4 changes: 2 additions & 2 deletions ddtrace/internal/ci_visibility/encoder.py
Original file line number Diff line number Diff line change
Expand Up @@ -304,7 +304,7 @@ def _build_data(self, traces: List[List[Span]]) -> Optional[bytes]:
self._convert_span(span, new_parent_session_span_id=new_parent_session_span_id)
for trace in traces
for span in trace
if (COVERAGE_TAG_NAME in span.get_tags() or span.get_struct_tag(COVERAGE_TAG_NAME) is not None)
if (COVERAGE_TAG_NAME in span.get_tags() or span._get_struct_tag(COVERAGE_TAG_NAME) is not None)
]
if not normalized_covs:
return None
Expand All @@ -324,7 +324,7 @@ def _convert_span(
# DEV: new_parent_session_span_id is unused here, but it is used in super class
files: dict[str, Any] = {}

files_struct_tag_value = span.get_struct_tag(COVERAGE_TAG_NAME)
files_struct_tag_value = span._get_struct_tag(COVERAGE_TAG_NAME)
if files_struct_tag_value is not None and "files" in files_struct_tag_value:
files = files_struct_tag_value["files"]
elif COVERAGE_TAG_NAME in span.get_tags():
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
---
deprecations:
- |
tracing: ``Span.set_struct_tag`` is deprecated and will be removed in v4.0.0 with no direct replacement.
- |
tracing: ``Span.get_struct_tag`` is deprecated and will be removed in v4.0.0 with no direct replacement.
4 changes: 2 additions & 2 deletions tests/appsec/ai_guard/api/test_api_client.py
Original file line number Diff line number Diff line change
Expand Up @@ -253,7 +253,7 @@ def test_span_meta_history_truncation(mock_execute_request, ai_guard_client, tra
workflow.evaluate_prompt("user", "Tell me 10 things I should know about DataDog")

span = find_ai_guard_span(tracer)
meta = span.get_struct_tag(AI_GUARD.TAG)
meta = span._get_struct_tag(AI_GUARD.TAG)
assert len(meta["history"]) == ai_guard_config._ai_guard_max_history_length


Expand All @@ -268,7 +268,7 @@ def test_span_meta_content_truncation(mock_execute_request, ai_guard_client, tra
workflow.evaluate_prompt("user", random_output)

span = find_ai_guard_span(tracer)
meta = span.get_struct_tag(AI_GUARD.TAG)
meta = span._get_struct_tag(AI_GUARD.TAG)
tool_call = meta["history"][0]
assert len(tool_call["output"]) == ai_guard_config._ai_guard_max_content_size

Expand Down
2 changes: 1 addition & 1 deletion tests/appsec/ai_guard/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ def assert_ai_guard_span(
span = find_ai_guard_span(tracer)
for key, value in tags.items():
assert span.get_tag(key) == value
struct = span.get_struct_tag(AI_GUARD.TAG)
struct = span._get_struct_tag(AI_GUARD.TAG)
assert struct["history"] == history
assert struct["current"] == current

Expand Down
2 changes: 1 addition & 1 deletion tests/contrib/pytest/test_coverage_per_suite.py
Original file line number Diff line number Diff line change
Expand Up @@ -228,7 +228,7 @@ def test_second():
assert first_suite_coverage["/test_cov.py"] == [(1, 2), (4, 5), (7, 9)]
assert first_suite_coverage["/lib_fn.py"] == [(1, 2)]
assert first_suite_coverage["/ret_false.py"] == [(1, 2)]
assert second_suite_span.get_struct_tag(COVERAGE_TAG_NAME) is None
assert second_suite_span._get_struct_tag(COVERAGE_TAG_NAME) is None
else:
assert len(first_suite_coverage) == 3
assert first_suite_coverage["test_cov.py"] == [(5, 5), (8, 9)]
Expand Down
8 changes: 4 additions & 4 deletions tests/contrib/pytest/test_pytest.py
Original file line number Diff line number Diff line change
Expand Up @@ -1942,7 +1942,7 @@ def test_skipif_mark_true():

fourth_test_span = spans[3]
assert fourth_test_span.get_tag("test.name") == "test_skipif_mark_true"
assert fourth_test_span.get_struct_tag(COVERAGE_TAG_NAME) is None
assert fourth_test_span._get_struct_tag(COVERAGE_TAG_NAME) is None

@pytest.mark.skipif(
not _PYTEST_SUPPORTS_ITR,
Expand Down Expand Up @@ -4751,7 +4751,7 @@ def test_coverage_target():
assert len(test_spans) >= 3

for span in test_spans:
coverage_data = span.get_struct_tag("test.coverage")
coverage_data = span._get_struct_tag("test.coverage")
assert coverage_data is not None, f"Test {span.get_tag('test.name')} missing coverage data"
# Coverage data should be a dict with 'files' key
assert isinstance(coverage_data, dict) and "files" in coverage_data
Expand Down Expand Up @@ -4848,7 +4848,7 @@ def test_coverage_target():
if span in atr_retry_spans:
# Coverage not attached to retry spans
continue
coverage_data = span.get_struct_tag("test.coverage")
coverage_data = span._get_struct_tag("test.coverage")
assert coverage_data is not None, f"Test {span.get_tag('test.name')} missing coverage data"
# Coverage data should be a dict with 'files' key
assert isinstance(coverage_data, dict) and "files" in coverage_data
Expand Down Expand Up @@ -4915,7 +4915,7 @@ def test_simple():
assert len(test_spans) >= 2

for span in test_spans:
coverage_data = span.get_struct_tag("test.coverage")
coverage_data = span._get_struct_tag("test.coverage")
assert coverage_data is not None, f"Test {span.get_tag('test.name')} missing coverage data"
# Coverage data should be a dict with 'files' key
assert isinstance(coverage_data, dict) and "files" in coverage_data
Expand Down
2 changes: 1 addition & 1 deletion tests/tracer/test_encoders.py
Original file line number Diff line number Diff line change
Expand Up @@ -233,7 +233,7 @@ def test_encode_meta_struct():
super_span = Span(name="client.testing", trace_id=1)
payload = {"tttt": {"iuopç": [{"abcd": 1, "bcde": True}, {}]}, "zzzz": b"\x93\x01\x02\x03", "ZZZZ": [1, 2, 3]}

super_span.set_struct_tag("payload", payload)
super_span._set_struct_tag("payload", payload)
super_span.set_tag("payload", "meta_payload")
encoder.put(
[
Expand Down
Loading