Skip to content

Commit 7cc1ef5

Browse files
authored
test(debugger): align DI hit-limit test with SDK MaxHits semantics (#782)
## Summary The DI Flask `DIFlaskHitLimitTest` and the matching application target function had `MaxHits` semantics flipped relative to the SDK. With `MaxHits=3`, the test expected 2 snapshots, claiming the disable check was `hit_count >= max_hits`. The SDK's [increment_hit_count](https://github.com/aws-observability/aws-otel-python-instrumentation/blob/main/aws-opentelemetry-distro/src/amazon/opentelemetry/distro/debugger/instrumentation_manager.py#L631) actually uses `hit_count > max_hits`, so it emits 3 snapshots and disables on the 4th hit. ## Why this is surfacing now The test was passing on main by accident. `BatchLogRecordProcessor`'s default `schedule_delay_millis` was 5000ms, so the snapshot emitted on the 3rd hit was still sitting in the batch buffer when the test's `time.sleep(2)` elapsed and read the collector. The 3rd snapshot never reached the mock collector within the test's observation window. OpenTelemetry core 1.41.0 [tightened that default to 1000ms](open-telemetry/opentelemetry-python#4998) to comply with the OTel spec, so the upcoming dependency bump to 1.42.1 / 0.63b1 (#762) now sees the 3rd snapshot consistently and the latent off-by-one assertion fails the test. ## Changes - Update the test class docstring and both test methods so `MaxHits=3` → 3 snapshots, breakpoint disabled on the 4th hit. Send a 4th request to actually probe the disabled state. - Update the `limited_function` docstring in the di-flask sample app to match. ## Test plan - [ ] DI Debugger Contract Tests pass on this branch (currently the only test in the suite that was failing, on the `nightly-dependency-updates` branch) - [ ] No SDK behavior change — purely a test/comment alignment with current SDK semantics
1 parent bbc788a commit 7cc1ef5

5 files changed

Lines changed: 44 additions & 39 deletions

File tree

contract-tests/images/applications/di-fastapi/di_fastapi_server.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -62,8 +62,8 @@ def calculate_sum(a, b):
6262
def limited_function(x):
6363
"""Target function with hit limit (MaxHits=3).
6464
65-
MaxHits=3 means: allow 2 snapshots, disable at 3rd hit.
66-
(The check is hit_count >= max_hits, so hit 1&2 pass, hit 3 is blocked.)
65+
MaxHits=3 means: allow 3 snapshots, disable on the 4th hit.
66+
(The check is hit_count > max_hits, so hits 1-3 pass, hit 4 is blocked.)
6767
"""
6868
return x * 10
6969

contract-tests/images/applications/di-flask/di_flask_server.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -55,8 +55,8 @@ def calculate_sum(a, b):
5555
def limited_function(x):
5656
"""Target function with hit limit (MaxHits=3).
5757
58-
MaxHits=3 means: allow 2 snapshots, disable at 3rd hit.
59-
(The check is hit_count >= max_hits, so hit 1&2 pass, hit 3 is blocked.)
58+
MaxHits=3 means: allow 3 snapshots, disable on the 4th hit.
59+
(The check is hit_count > max_hits, so hits 1-3 pass, hit 4 is blocked.)
6060
"""
6161
return x * 10
6262

contract-tests/tests/test/amazon/di/django_test.py

Lines changed: 10 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -273,33 +273,34 @@ def get_application_wait_pattern(self) -> str:
273273
return "Ready"
274274

275275
def test_breakpoint_generates_snapshots_up_to_limit(self) -> None:
276-
"""BREAKPOINT generates snapshots up to (max_hits - 1)."""
276+
"""BREAKPOINT generates a snapshot for each hit up to and including max_hits."""
277+
self.send_request("GET", "limited")
277278
self.send_request("GET", "limited")
278279
self.send_request("GET", "limited")
279280

280-
logs = self.wait_for_snapshots(min_count=2)
281+
logs = self.wait_for_snapshots(min_count=3)
281282
limited_logs = self.logs_for_method(logs, "limited_function")
282-
self.assertEqual(len(limited_logs), 2, "Expected exactly 2 snapshots (MaxHits=3 allows 2)")
283+
self.assertEqual(len(limited_logs), 3, "Expected exactly 3 snapshots (MaxHits=3 allows 3)")
283284

284285
def test_breakpoint_disabled_after_hit_limit(self) -> None:
285286
"""BREAKPOINT stops generating snapshots after hit limit is reached."""
286287
self.send_request("GET", "limited")
287288
self.send_request("GET", "limited")
289+
self.send_request("GET", "limited")
288290

289-
logs = self.wait_for_snapshots(min_count=2)
291+
logs = self.wait_for_snapshots(min_count=3)
290292
initial_count = len(self.logs_for_method(logs, "limited_function"))
291-
self.assertEqual(initial_count, 2)
293+
self.assertEqual(initial_count, 3)
292294

293295
self.send_request("GET", "limited")
294-
self.send_request("GET", "limited")
295-
time.sleep(2)
296+
time.sleep(5)
296297

297298
final_logs = self._peek_snapshots()
298299
final_count = len(self.logs_for_method(final_logs, "limited_function"))
299300
self.assertEqual(
300301
final_count,
301-
2,
302-
f"Expected 2 snapshots (MaxHits=3), but got {final_count}. "
302+
3,
303+
f"Expected 3 snapshots (MaxHits=3), but got {final_count}. "
303304
"BREAKPOINT should be disabled after hitting limit.",
304305
)
305306

contract-tests/tests/test/amazon/di/fastapi_test.py

Lines changed: 15 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -278,7 +278,8 @@ class DIFastAPIHitLimitTest(DITestInfrastructure):
278278
"""Test BREAKPOINT hit limit behavior.
279279
280280
BREAKPOINTs have a max_hits limit. With MaxHits=3, the check is
281-
hit_count >= max_hits, so hits 1 and 2 generate snapshots, hit 3 is blocked.
281+
hit_count > max_hits, so hits 1, 2, and 3 generate snapshots and the
282+
breakpoint is disabled on hit 4.
282283
"""
283284

284285
__test__ = True
@@ -293,36 +294,37 @@ def get_application_wait_pattern(self) -> str:
293294
return "Ready"
294295

295296
def test_breakpoint_generates_snapshots_up_to_limit(self) -> None:
296-
"""BREAKPOINT generates snapshots up to (max_hits - 1)."""
297-
# limited_function has MaxHits=3, so 2 snapshots should be generated
297+
"""BREAKPOINT generates a snapshot for each hit up to and including max_hits."""
298+
# limited_function has MaxHits=3, so 3 snapshots should be generated
299+
self.send_request("GET", "limited")
298300
self.send_request("GET", "limited")
299301
self.send_request("GET", "limited")
300302

301-
logs = self.wait_for_snapshots(min_count=2)
303+
logs = self.wait_for_snapshots(min_count=3)
302304
limited_logs = self.logs_for_method(logs, "limited_function")
303-
self.assertEqual(len(limited_logs), 2, "Expected exactly 2 snapshots (MaxHits=3 allows 2)")
305+
self.assertEqual(len(limited_logs), 3, "Expected exactly 3 snapshots (MaxHits=3 allows 3)")
304306

305307
def test_breakpoint_disabled_after_hit_limit(self) -> None:
306308
"""BREAKPOINT stops generating snapshots after hit limit is reached."""
307-
# First 2 calls generate snapshots (hits 1 and 2)
309+
# First 3 calls generate snapshots (hits 1, 2, and 3)
310+
self.send_request("GET", "limited")
308311
self.send_request("GET", "limited")
309312
self.send_request("GET", "limited")
310313

311-
logs = self.wait_for_snapshots(min_count=2)
314+
logs = self.wait_for_snapshots(min_count=3)
312315
initial_count = len(self.logs_for_method(logs, "limited_function"))
313-
self.assertEqual(initial_count, 2)
316+
self.assertEqual(initial_count, 3)
314317

315-
# 3rd and 4th calls hit the limit -- no new snapshots
316-
self.send_request("GET", "limited")
318+
# 4th call hits the limit -- no new snapshot
317319
self.send_request("GET", "limited")
318-
time.sleep(2)
320+
time.sleep(5)
319321

320322
final_logs = self._peek_snapshots()
321323
final_count = len(self.logs_for_method(final_logs, "limited_function"))
322324
self.assertEqual(
323325
final_count,
324-
2,
325-
f"Expected 2 snapshots (MaxHits=3), but got {final_count}. "
326+
3,
327+
f"Expected 3 snapshots (MaxHits=3), but got {final_count}. "
326328
"BREAKPOINT should be disabled after hitting limit.",
327329
)
328330

contract-tests/tests/test/amazon/di/flask_test.py

Lines changed: 15 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -270,7 +270,8 @@ class DIFlaskHitLimitTest(DITestInfrastructure):
270270
"""Test BREAKPOINT hit limit behavior.
271271
272272
BREAKPOINTs have a max_hits limit. With MaxHits=3, the check is
273-
hit_count >= max_hits, so hits 1 and 2 generate snapshots, hit 3 is blocked.
273+
hit_count > max_hits, so hits 1, 2, and 3 generate snapshots and the
274+
breakpoint is disabled on hit 4.
274275
"""
275276

276277
__test__ = True
@@ -285,36 +286,37 @@ def get_application_wait_pattern(self) -> str:
285286
return "Ready"
286287

287288
def test_breakpoint_generates_snapshots_up_to_limit(self) -> None:
288-
"""BREAKPOINT generates snapshots up to (max_hits - 1)."""
289-
# limited_function has MaxHits=3, so 2 snapshots should be generated
289+
"""BREAKPOINT generates a snapshot for each hit up to and including max_hits."""
290+
# limited_function has MaxHits=3, so 3 snapshots should be generated
291+
self.send_request("GET", "limited")
290292
self.send_request("GET", "limited")
291293
self.send_request("GET", "limited")
292294

293-
logs = self.wait_for_snapshots(min_count=2)
295+
logs = self.wait_for_snapshots(min_count=3)
294296
limited_logs = self.logs_for_method(logs, "limited_function")
295-
self.assertEqual(len(limited_logs), 2, "Expected exactly 2 snapshots (MaxHits=3 allows 2)")
297+
self.assertEqual(len(limited_logs), 3, "Expected exactly 3 snapshots (MaxHits=3 allows 3)")
296298

297299
def test_breakpoint_disabled_after_hit_limit(self) -> None:
298300
"""BREAKPOINT stops generating snapshots after hit limit is reached."""
299-
# First 2 calls generate snapshots (hits 1 and 2)
301+
# First 3 calls generate snapshots (hits 1, 2, and 3)
302+
self.send_request("GET", "limited")
300303
self.send_request("GET", "limited")
301304
self.send_request("GET", "limited")
302305

303-
logs = self.wait_for_snapshots(min_count=2)
306+
logs = self.wait_for_snapshots(min_count=3)
304307
initial_count = len(self.logs_for_method(logs, "limited_function"))
305-
self.assertEqual(initial_count, 2)
308+
self.assertEqual(initial_count, 3)
306309

307-
# 3rd and 4th calls hit the limit -- no new snapshots
308-
self.send_request("GET", "limited")
310+
# 4th call hits the limit -- no new snapshot
309311
self.send_request("GET", "limited")
310-
time.sleep(2)
312+
time.sleep(5)
311313

312314
final_logs = self._peek_snapshots()
313315
final_count = len(self.logs_for_method(final_logs, "limited_function"))
314316
self.assertEqual(
315317
final_count,
316-
2,
317-
f"Expected 2 snapshots (MaxHits=3), but got {final_count}. "
318+
3,
319+
f"Expected 3 snapshots (MaxHits=3), but got {final_count}. "
318320
"BREAKPOINT should be disabled after hitting limit.",
319321
)
320322

0 commit comments

Comments
 (0)