Skip to content

Commit b51cb4f

Browse files
authored
Merge branch 'main' into avara1986/APPSEC-59983
2 parents 4f81193 + 33c52d1 commit b51cb4f

File tree

7 files changed

+79
-9
lines changed

7 files changed

+79
-9
lines changed

ddtrace/appsec/_utils.py

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -173,14 +173,26 @@ def __init__(
173173
self.location = location.replace(APPSEC.SECURITY_RESPONSE_ID, security_response_id)
174174
self.content_type: str = "application/json"
175175

176-
def get(self, method_name: str, default: Any = None) -> Any:
176+
def get(self, key: str, default: Any = None) -> Union[str, int]:
177177
"""
178178
Dictionary-like get method for backward compatibility with Lambda integration.
179179
180180
Returns the attribute value if it exists, otherwise returns the default value.
181181
This allows Block_config to be used in contexts that expect dictionary-like access.
182182
"""
183-
return getattr(self, method_name, default)
183+
if key == "content-type":
184+
key = "content_type"
185+
return getattr(self, key, default)
186+
187+
def __getitem__(self, key: str) -> Optional[Union[str, int]]:
188+
if key == "content-type":
189+
key = "content_type"
190+
return getattr(self, key, None)
191+
192+
def __contains__(self, key: str) -> bool:
193+
if key == "content-type":
194+
key = "content_type"
195+
return bool(getattr(self, key, None))
184196

185197

186198
class Telemetry_result:

ddtrace/internal/process_tags/__init__.py

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,9 @@
22
from pathlib import Path
33
import re
44
import sys
5+
from typing import List
56
from typing import Optional
7+
from typing import Tuple
68

79
from ddtrace.internal.logger import get_logger
810
from ddtrace.internal.settings.process_tags import process_tags_config as config
@@ -44,12 +46,12 @@ def is_allowed_char(char: str) -> str:
4446
return result.strip("_")
4547

4648

47-
def generate_process_tags() -> Optional[str]:
49+
def generate_process_tags() -> Tuple[Optional[str], Optional[List[str]]]:
4850
if not config.enabled:
49-
return None
51+
return None, None
5052

5153
try:
52-
return ",".join(
54+
process_tags_list = [
5355
f"{key}:{normalize_tag_value(value)}"
5456
for key, value in sorted(
5557
[
@@ -59,10 +61,12 @@ def generate_process_tags() -> Optional[str]:
5961
(ENTRYPOINT_TYPE_TAG, ENTRYPOINT_TYPE_SCRIPT),
6062
]
6163
)
62-
)
64+
]
65+
process_tags = ",".join(process_tags_list)
66+
return process_tags, process_tags_list
6367
except Exception as e:
6468
log.debug("failed to get process_tags: %s", e)
65-
return None
69+
return None, None
6670

6771

68-
process_tags = generate_process_tags()
72+
process_tags, process_tags_list = generate_process_tags()

ddtrace/internal/remoteconfig/client.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
import ddtrace
2222
from ddtrace.internal import agent
2323
from ddtrace.internal import gitmetadata
24+
from ddtrace.internal import process_tags
2425
from ddtrace.internal import runtime
2526
from ddtrace.internal.hostname import get_hostname
2627
from ddtrace.internal.logger import get_logger
@@ -233,6 +234,10 @@ def __init__(self) -> None:
233234
app_version=ddtrace.config.version,
234235
tags=[":".join(_) for _ in tags.items()],
235236
)
237+
238+
if p_tags_list := process_tags.process_tags_list:
239+
self._client_tracer["process_tags"] = p_tags_list
240+
236241
self.cached_target_files: List[AppliedConfigType] = []
237242

238243
self._products: MutableMapping[str, PubSub] = dict()

ddtrace/internal/utils/__init__.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,12 @@ class Block_config(Protocol):
8787
location: str
8888
content_type: str
8989

90+
def get(self, key: str, default: Any = None) -> Union[str, int]: ...
91+
92+
def __getitem__(self, key: str) -> Optional[Union[str, int]]: ...
93+
94+
def __contains__(self, key: str) -> bool: ...
95+
9096

9197
def get_blocked() -> Optional[Block_config]:
9298
# local import to avoid circular dependency

tests/internal/remoteconfig/test_remoteconfig.py

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -802,3 +802,44 @@ def test_apm_tracing_sampling_rules_none_override(remote_config_worker):
802802
# Restore original config
803803
config.service = original_service
804804
config.env = original_env
805+
806+
807+
def test_remote_config_payload_not_includes_process_tags():
808+
client = RemoteConfigClient()
809+
payload = client._build_payload({})
810+
811+
assert "process_tags" not in payload["client"]["client_tracer"]
812+
813+
814+
@pytest.mark.subprocess(env={"DD_EXPERIMENTAL_PROPAGATE_PROCESS_TAGS_ENABLED": "True"})
815+
def test_remote_config_payload_includes_process_tags():
816+
import os
817+
import sys
818+
from unittest.mock import patch
819+
820+
from ddtrace.internal.process_tags import ENTRYPOINT_BASEDIR_TAG
821+
from ddtrace.internal.process_tags import ENTRYPOINT_NAME_TAG
822+
from ddtrace.internal.process_tags import ENTRYPOINT_TYPE_SCRIPT
823+
from ddtrace.internal.process_tags import ENTRYPOINT_TYPE_TAG
824+
from ddtrace.internal.process_tags import ENTRYPOINT_WORKDIR_TAG
825+
from ddtrace.internal.remoteconfig.client import RemoteConfigClient
826+
from tests.utils import process_tag_reload
827+
828+
with (
829+
patch.object(sys, "argv", ["/path/to/test_script.py"]),
830+
patch.object(os, "getcwd", return_value="/path/to/workdir"),
831+
):
832+
process_tag_reload()
833+
834+
client = RemoteConfigClient()
835+
payload = client._build_payload({})
836+
837+
assert "process_tags" in payload["client"]["client_tracer"]
838+
839+
process_tags = payload["client"]["client_tracer"]["process_tags"]
840+
841+
assert isinstance(process_tags, list)
842+
assert f"{ENTRYPOINT_BASEDIR_TAG}:to" in process_tags
843+
assert f"{ENTRYPOINT_NAME_TAG}:test_script" in process_tags
844+
assert f"{ENTRYPOINT_TYPE_TAG}:{ENTRYPOINT_TYPE_SCRIPT}" in process_tags
845+
assert f"{ENTRYPOINT_WORKDIR_TAG}:workdir" in process_tags

tests/internal/test_process_tags.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,10 +81,12 @@ def setUp(self):
8181
super(TestProcessTags, self).setUp()
8282
self._original_process_tags_enabled = config.enabled
8383
self._original_process_tags = process_tags.process_tags
84+
self._original_process_tags_list = process_tags.process_tags_list
8485

8586
def tearDown(self):
8687
config.enabled = self._original_process_tags_enabled
8788
process_tags.process_tags = self._original_process_tags
89+
process_tags.process_tags_list = self._original_process_tags_list
8890
super().tearDown()
8991

9092
@pytest.mark.snapshot

tests/utils.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1623,4 +1623,4 @@ def override_third_party_packages(packages: List[str]):
16231623

16241624

16251625
def process_tag_reload():
1626-
process_tags.process_tags = process_tags.generate_process_tags()
1626+
process_tags.process_tags, process_tags.process_tags_list = process_tags.generate_process_tags()

0 commit comments

Comments
 (0)