async def test_nested_tasks(tracked_request): @instrument.async_("orchestrator") async def orchestrator(): await coro("1") await asyncio.gather( # Force this coroutine to finish later for idempotency coro("2a", wait=0.5), coro("2b"), ) ensure_installed() with BackgroundTransaction("test"): await orchestrator() spans = tracked_request.complete_spans assert len(spans) == 5 assert [span.operation for span in spans] == [ "Custom/coro", "Custom/coro", "Custom/coro", "Custom/orchestrator", "Job/test", ] # Verify the order of the coroutines assert [span.tags.get("value") for span in spans] == [ "1", "2b", "2a", None, None, ]
async def test_task_cancelled(tracked_request): ensure_installed() with BackgroundTransaction("test"): long = create_task(coro("long", wait=0.5)) long.cancel() assert len(tracked_request.complete_spans) == 1 assert tracked_request.complete_spans[0].operation == "Job/test"
async def test_coroutine_timeout(tracked_request): ensure_installed() with BackgroundTransaction("test"): with pytest.raises(asyncio.TimeoutError): await asyncio.wait_for(coro("long", wait=0.5), timeout=0.1) assert len(tracked_request.complete_spans) == 1 assert tracked_request.complete_spans[0].operation == "Job/test"
async def test_coroutine(tracked_request): ensure_installed() with BackgroundTransaction("test"): await coro() assert len(tracked_request.complete_spans) == 2 span = tracked_request.complete_spans[0] assert span.operation == "Custom/coro" assert tracked_request.complete_spans[1].operation == "Job/test"
def test_ensure_installed_twice(caplog): ensure_installed() ensure_installed() assert caplog.record_tuples == 2 * [ ( "scout_apm.instruments.asyncio", logging.DEBUG, "Instrumenting asyncio.", ) ]
async def test_future_cancelled(tracked_request): ensure_installed() with BackgroundTransaction("test"): gather_future = asyncio.gather( resolving_future(0.5), coro(wait=0.5), ) gather_future.cancel() assert len(tracked_request.complete_spans) == 1 assert tracked_request.complete_spans[0].operation == "Job/test"
async def test_future_awaited(tracked_request): ensure_installed() with BackgroundTransaction("test"): fut = get_future() create_task(set_future(fut, wait=0.5)) await fut assert len(tracked_request.complete_spans) == 1 assert tracked_request.complete_spans[0].operation == "Custom/set_future" assert len(tracked_request.complete_spans) == 2 assert tracked_request.complete_spans[1].operation == "Job/test"
async def test_future_gathered(tracked_request): ensure_installed() with BackgroundTransaction("test"): await asyncio.gather( resolving_future(0.5), coro(wait=0.5), ) assert len(tracked_request.complete_spans) == 2 # gather can run the coroutines/futures in any order. operations = {span.operation for span in tracked_request.complete_spans} assert operations == {"Custom/set_future", "Custom/coro"} assert len(tracked_request.complete_spans) == 3 assert tracked_request.complete_spans[2].operation == "Job/test"
def test_install_fail_no_asyncio(caplog): mock_no_asyncio = mock.patch("scout_apm.instruments.asyncio.asyncio", new=None) with mock_no_asyncio: ensure_installed() assert caplog.record_tuples == [ ( "scout_apm.instruments.asyncio", logging.DEBUG, "Instrumenting asyncio.", ), ( "scout_apm.instruments.asyncio", logging.DEBUG, "Couldn't import asyncio - probably old version of python.", ), ]
async def test_task_not_awaited(tracked_request): ensure_installed() with BackgroundTransaction("test"): await create_task(coro("short")) long = create_task(coro("long", wait=0.5)) assert len(tracked_request.complete_spans) == 2 span = tracked_request.complete_spans[0] assert span.operation == "Custom/coro" assert span.tags["value"] == "short" assert tracked_request.complete_spans[1].operation == "Job/test" assert not long.done() await long assert len(tracked_request.complete_spans) == 3 span = tracked_request.complete_spans[2] assert span.operation == "Custom/coro" assert span.tags["value"] == "long"