Skip to content

Commit 2f180af

Browse files
refactor(profiling): add type annotations to native-heap arming observability
Annotate the arming-observability additions: the _NATIVE_HEAP_SIZE_THRESHOLD_BYTES / _NATIVE_HEAP_PARTITION_ARMED_METRIC module globals and the _emit_native_heap_partition_armed_gauge local (profiler.py), plus the locals in the new dogstatsd-gauge/WARNING tests.
1 parent 8b3d607 commit 2f180af

2 files changed

Lines changed: 16 additions & 11 deletions

File tree

ddtrace/profiling/profiler.py

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
# -*- encoding: utf-8 -*-
22
import json
33
import logging
4+
from typing import TYPE_CHECKING
45
from typing import Any
56
from typing import Callable
67
from typing import Mapping
@@ -32,17 +33,21 @@
3233
from ddtrace.profiling.collector import threading
3334

3435

36+
if TYPE_CHECKING:
37+
from ddtrace.vendor.dogstatsd import DogStatsd
38+
39+
3540
LOG = logging.getLogger(__name__)
3641

3742
# pymalloc's small-request threshold (see CPython Objects/obmalloc.c). Requests
3843
# larger than this are delegated to glibc malloc, where the native-heap gotter
3944
# owns them, so the in-process sampler skips them when the partition is armed.
40-
_NATIVE_HEAP_SIZE_THRESHOLD_BYTES = 512
45+
_NATIVE_HEAP_SIZE_THRESHOLD_BYTES: int = 512
4146
# Dogstatsd gauge surfacing the native-heap ownership-partition arming decision
4247
# (1=armed, 0=not). Structured JSON loggers in real deploys drop ddtrace stdlib
4348
# records and pods/exec is RBAC-blocked, so the log line alone is not always
4449
# observable; this gauge gives an out-of-band, queryable signal at service start.
45-
_NATIVE_HEAP_PARTITION_ARMED_METRIC = "profiling.native_heap.partition_armed"
50+
_NATIVE_HEAP_PARTITION_ARMED_METRIC: str = "profiling.native_heap.partition_armed"
4651

4752

4853
class Profiler(object):
@@ -428,7 +433,7 @@ def _emit_native_heap_partition_armed_gauge(self, armed: bool) -> None:
428433
from ddtrace.internal.dogstatsd import get_dogstatsd_client
429434
from ddtrace.internal.settings._agent import config as agent_config
430435

431-
client = get_dogstatsd_client(agent_config.dogstatsd_url)
436+
client: DogStatsd = get_dogstatsd_client(agent_config.dogstatsd_url)
432437
client.gauge(
433438
_NATIVE_HEAP_PARTITION_ARMED_METRIC,
434439
1 if armed else 0,

tests/profiling/test_native_heap_gotter.py

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ def _only_arming_warning(err: str) -> bool:
4949
harness would otherwise reject as unexpected stderr. Runs in the parent test
5050
process against the subprocess's decoded stderr.
5151
"""
52-
lines = [line for line in err.splitlines() if line.strip()]
52+
lines: list[str] = [line for line in err.splitlines() if line.strip()]
5353
return all("native heap ownership partition:" in line for line in lines)
5454

5555

@@ -248,24 +248,24 @@ def test_profiler_start_emits_partition_armed_gauge_when_armed() -> None:
248248

249249
profiling_config.native_heap.enabled = True # pyright: ignore[reportAttributeAccessIssue]
250250

251-
client = mock.Mock()
251+
client: mock.Mock = mock.Mock()
252252
with mock.patch.object(heap_gotter, "install", return_value=True):
253253
with mock.patch.object(heap_gotter, "live_heap_enabled", return_value=False):
254254
with mock.patch.object(ddtrace.internal.dogstatsd, "get_dogstatsd_client", return_value=client):
255255
with mock.patch.object(profiler_mod.LOG, "warning") as warning:
256-
prof = profiler_mod.Profiler()
256+
prof: profiler_mod.Profiler = profiler_mod.Profiler()
257257
prof.start()
258258
try:
259259
assert client.gauge.call_count == 1
260260
args, kwargs = client.gauge.call_args
261261
assert args[0] == "profiling.native_heap.partition_armed"
262262
assert args[1] == 1, "gauge value must be 1 when armed"
263-
tags = kwargs["tags"]
263+
tags: list[str] = kwargs["tags"]
264264
assert "domains:OBJ_MEM" in tags
265265
assert "size_threshold_bytes:512" in tags
266266

267267
assert warning.called, "arming decision must be logged at WARNING"
268-
msg = warning.call_args[0][0]
268+
msg: str = warning.call_args[0][0]
269269
assert "native heap ownership partition" in msg
270270
assert warning.call_args[0][1] is True, "WARNING must report armed=True"
271271
finally:
@@ -286,11 +286,11 @@ def test_profiler_start_emits_partition_armed_gauge_zero_when_not_armed() -> Non
286286

287287
profiling_config.native_heap.enabled = True # pyright: ignore[reportAttributeAccessIssue]
288288

289-
client = mock.Mock()
289+
client: mock.Mock = mock.Mock()
290290
with mock.patch.object(heap_gotter, "install", return_value=False):
291291
with mock.patch.object(ddtrace.internal.dogstatsd, "get_dogstatsd_client", return_value=client):
292292
with mock.patch.object(profiler_mod.LOG, "warning") as warning:
293-
prof = profiler_mod.Profiler()
293+
prof: profiler_mod.Profiler = profiler_mod.Profiler()
294294
prof.start()
295295
try:
296296
assert client.gauge.call_count == 1
@@ -322,7 +322,7 @@ def test_profiler_start_survives_partition_armed_gauge_error() -> None:
322322
with mock.patch.object(
323323
ddtrace.internal.dogstatsd, "get_dogstatsd_client", side_effect=RuntimeError("no agent")
324324
):
325-
prof = profiler_mod.Profiler()
325+
prof: profiler_mod.Profiler = profiler_mod.Profiler()
326326
prof.start() # must not raise
327327
try:
328328
assert prof.status.value == "running"

0 commit comments

Comments
 (0)