Skip to content

Commit b5118df

Browse files
committed
More fixes
1 parent 976a86e commit b5118df

6 files changed

Lines changed: 48 additions & 5 deletions

File tree

drift/core/adaptive_sampling.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,7 @@ def __init__(
8181
self._admission_multiplier = 1.0
8282
self._state: AdaptiveSamplingState = "fixed" if config.mode == "fixed" else "healthy"
8383
self._paused_until_s = 0.0
84-
self._last_updated_at_s = 0.0
84+
self._last_updated_at_s: float | None = None
8585
self._last_decrease_at_s = 0.0
8686

8787
self._prev_dropped_span_count = 0
@@ -99,7 +99,7 @@ def update(self, snapshot: AdaptiveSamplingHealthSnapshot) -> None:
9999
return
100100

101101
now_s = self._now_fn()
102-
elapsed_s = 2.0 if self._last_updated_at_s == 0 else max(0.001, now_s - self._last_updated_at_s)
102+
elapsed_s = 2.0 if self._last_updated_at_s is None else max(0.001, now_s - self._last_updated_at_s)
103103
self._last_updated_at_s = now_s
104104

105105
decay = math.exp(-(elapsed_s * 1000.0) / 30000.0)

drift/core/mode_utils.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -180,7 +180,8 @@ def should_record_inbound_http_request(
180180
Returns:
181181
Tuple of (should_record, skip_reason):
182182
- should_record: True if request should be recorded
183-
- skip_reason: If False, explains why ("dropped" or "not_sampled"), None otherwise
183+
- skip_reason: If False, explains why ("dropped", "not_sampled",
184+
"load_shed", or "critical_pause"), None otherwise
184185
"""
185186
if transform_engine and transform_engine.should_drop_inbound_request(method, target, headers):
186187
return False, "dropped"
@@ -191,6 +192,6 @@ def should_record_inbound_http_request(
191192
sdk = TuskDrift.get_instance()
192193
decision = sdk.should_record_root_request(is_pre_app_start=is_pre_app_start)
193194
if not decision.should_record:
194-
return False, "not_sampled"
195+
return False, decision.reason
195196

196197
return True, None

drift/instrumentation/wsgi/handler.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -250,7 +250,8 @@ def _create_and_handle_request(
250250
)
251251
if not should_record:
252252
logger.debug(f"[WSGI] Skipping request ({skip_reason}), path={path}")
253-
response = original_wsgi_app(app, environ, start_response)
253+
with suppress_recording():
254+
response = original_wsgi_app(app, environ, start_response)
254255
return SuppressedResponseIterable(response)
255256

256257
# Capture request body

tests/unit/test_adaptive_sampling.py

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import math
12
import threading
23

34
from drift.core.adaptive_sampling import (
@@ -44,6 +45,22 @@ def test_controller_load_sheds_and_pauses_on_drops():
4445
assert paused_decision.reason == "critical_pause"
4546

4647

48+
def test_elapsed_time_uses_zero_timestamp_as_real_value():
49+
now = {"value": 0.0}
50+
controller = AdaptiveSamplingController(
51+
ResolvedSamplingConfig(mode="adaptive", base_rate=0.5, min_rate=0.1),
52+
random_fn=lambda: 0.0,
53+
now_fn=lambda: now["value"],
54+
)
55+
56+
controller.update(AdaptiveSamplingHealthSnapshot(export_failure_count=1))
57+
now["value"] = 0.5
58+
controller.update(AdaptiveSamplingHealthSnapshot(export_failure_count=1))
59+
60+
expected_decay = math.exp(-(0.5 * 1000.0) / 30000.0)
61+
assert math.isclose(controller._recent_failure_signal, expected_decay, rel_tol=1e-6)
62+
63+
4764
def test_get_decision_waits_for_controller_lock():
4865
controller = AdaptiveSamplingController(
4966
ResolvedSamplingConfig(mode="adaptive", base_rate=0.5, min_rate=0.1),

tests/unit/test_mode_utils.py

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -360,6 +360,7 @@ def test_returns_false_when_not_sampled(self, mocker):
360360
mock_drift = mocker.patch("drift.core.drift_sdk.TuskDrift")
361361
mock_sdk = mocker.MagicMock()
362362
mock_sdk.should_record_root_request.return_value.should_record = False
363+
mock_sdk.should_record_root_request.return_value.reason = "not_sampled"
363364
mock_drift.get_instance.return_value = mock_sdk
364365

365366
result, reason = should_record_inbound_http_request(
@@ -373,6 +374,25 @@ def test_returns_false_when_not_sampled(self, mocker):
373374
assert result is False
374375
assert reason == "not_sampled"
375376

377+
def test_returns_controller_reason_when_adaptive_sampling_skips(self, mocker):
378+
"""Should preserve adaptive controller reasons for debug logging."""
379+
mock_drift = mocker.patch("drift.core.drift_sdk.TuskDrift")
380+
mock_sdk = mocker.MagicMock()
381+
mock_sdk.should_record_root_request.return_value.should_record = False
382+
mock_sdk.should_record_root_request.return_value.reason = "critical_pause"
383+
mock_drift.get_instance.return_value = mock_sdk
384+
385+
result, reason = should_record_inbound_http_request(
386+
method="GET",
387+
target="/api/users",
388+
headers={},
389+
transform_engine=None,
390+
is_pre_app_start=False,
391+
)
392+
393+
assert result is False
394+
assert reason == "critical_pause"
395+
376396
def test_drop_check_happens_before_sampling(self, mocker):
377397
"""Should check drop rules before sampling."""
378398
mock_transform = mocker.MagicMock()

tests/unit/test_wsgi_handler.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,9 @@ def test_skipped_wsgi_request_keeps_suppression_during_streaming_iteration_and_c
4444
)
4545

4646
def original_wsgi_app(_app: Any, _environ: dict[str, Any], _start_response: Any) -> Iterable[bytes]:
47+
from drift.core.no_recording import is_recording_suppressed
48+
49+
observed.append(("call", is_recording_suppressed()))
4750
return response
4851

4952
def app(_environ: dict[str, Any], _start_response: Any) -> Iterable[bytes]:
@@ -72,6 +75,7 @@ def app(_environ: dict[str, Any], _start_response: Any) -> Iterable[bytes]:
7275
close_method()
7376

7477
assert observed == [
78+
("call", True),
7579
("iter", True),
7680
("next", True),
7781
("next", True),

0 commit comments

Comments
 (0)