Skip to content

Add integration tests for ASGI Django 3#2640

Merged
mergify[bot] merged 10 commits intoDataDog:masterfrom
Kyle-Verhoog:django-integration
Jul 26, 2021
Merged

Add integration tests for ASGI Django 3#2640
mergify[bot] merged 10 commits intoDataDog:masterfrom
Kyle-Verhoog:django-integration

Conversation

@Kyle-Verhoog
Copy link
Copy Markdown
Member

@Kyle-Verhoog Kyle-Verhoog commented Jul 13, 2021

Add integration tests which run a real Django instance using ASGI
and daphne.

A new function-scope daphne_client fixture is introduced which
initializes a real daphne Django server using the one in our
test suite. The client fixture provides an API to query the server much
like the pytest Django client.

Traces from the test cases are captured with the test agent and
snapshotted. Traces produced as a part of setup and teardown
are sent with distributed tracing headers which assign a trace id
of 1 which an installed TraceFilter will filter out.

Any temporal dependency is removed by adding a special shutdown
endpoint to the Django app which does a tracer.shutdown() to flush
the traces for the test case.

@Kyle-Verhoog Kyle-Verhoog added the changelog/no-changelog A changelog entry is not required for this PR. label Jul 13, 2021
@Kyle-Verhoog Kyle-Verhoog force-pushed the django-integration branch 11 times, most recently from 5a1c530 to ee17085 Compare July 16, 2021 02:02
@Kyle-Verhoog Kyle-Verhoog marked this pull request as ready for review July 16, 2021 13:37
@Kyle-Verhoog Kyle-Verhoog requested a review from a team as a code owner July 16, 2021 13:37
Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Introduce an endpoint to force a flush of the traces to reduce this flakiness. Thanks @P403n1x87!

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Interesting idea! We'd want to disable tracing for such an endpoint so we don't end up getting it's trace in the snapshot as well.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Another option would be to have the client fixture be per test such that flushing occurs during shutdown.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We'd want to disable tracing for such an endpoint so we don't end up getting it's trace in the snapshot as well.

Ah yes... good point!

Another option would be to have the client fixture be per test such that flushing occurs during shutdown.

yes - this would be more ideal IMO but there is a non-trivial cost of starting up the webserver unfortunately... although we don't run a lot of test scenarios

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

glad to say that all the time.sleep()s have been purged! Instead,

  • the django instance is started per process
  • traces are sent with a test token directly thanks to Add internal setting for additional writer headers #2689
  • polling spans are filtered by using http propagation headers with a special trace id
  • TraceFilter filters traces with the special trace id
  • traces are force-flushed with a call to a special endpoint

@Kyle-Verhoog Kyle-Verhoog force-pushed the django-integration branch 6 times, most recently from dab0c2e to b9dc65c Compare July 20, 2021 22:52
Add integration tests which run a real Django instance using ASGI
and daphne.
@Kyle-Verhoog Kyle-Verhoog force-pushed the django-integration branch 4 times, most recently from 2d3ee99 to 0bc3679 Compare July 21, 2021 18:35
Kyle-Verhoog added a commit to Kyle-Verhoog/dd-trace-py that referenced this pull request Jul 21, 2021
For testing it's desirable to be able to pass additional headers with
the trace requests made to the agent. With this ability we can propagate
tokens which can be used to associate traces with test cases when
running snapshot tests in subprocesses (like in DataDog#2640).

I debated having the flag be read at run-time instead of
initialization-time but opted against it as reading from the env is not
cheap (on the order of 1µs):

    >>> %timeit os.environ.get("")
    1.23 µs ± 49.6 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)
mergify Bot added a commit that referenced this pull request Jul 22, 2021
For testing it's desirable to be able to pass additional headers with
the trace requests made to the agent. With this ability we can propagate
tokens which can be used to associate traces with test cases when
running snapshot tests in subprocesses (like in #2640).

I debated having the flag be read at run-time instead of
initialization-time but opted against it as reading from the env is not
cheap (on the order of 1µs):

    >>> %timeit os.environ.get("")
    1.23 µs ± 49.6 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)

Co-authored-by: mergify[bot] <37929162+mergify[bot]@users.noreply.github.com>
Comment thread ddtrace/internal/writer.py Outdated
Comment thread tests/snapshots/tests.contrib.django.test_django_snapshots.test_asgi_200_31.snap Outdated
Comment thread tests/snapshots/tests.contrib.django.test_django_snapshots.test_asgi_200_3x.snap Outdated
@mergify mergify Bot removed the conflict label Jul 22, 2021
Comment thread tests/contrib/django/django_app/settings.py Outdated
from ddtrace.contrib.asgi import TraceMiddleware


application = TraceMiddleware(get_asgi_application())
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

is this what we are recommending for customers to do now?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A bit of a long story.... because of #2559 there's no way to be able to identify traces as coming from a particular route (no route tagging, no http propagation, no query params, etc) in order to filter traces that we don't care about (polling, startup, teardown, etc).

I added in the ASGI middleware to mitigate this for now so that we don't get a bunch of flaky time.sleep()s everywhere.

I think it's ok because the ASGI spans just wrap the Django ones. With #2656 we'll remove this explicit usage.

Comment thread tests/contrib/django/django_app/urls.py
Avoid the redirect
P403n1x87
P403n1x87 previously approved these changes Jul 23, 2021
Comment thread tests/contrib/django/django_app/settings.py
Comment thread tests/contrib/django/django_app/urls.py
Comment thread tests/contrib/django/test_django_snapshots.py Outdated
Comment thread tests/contrib/django/test_django_snapshots.py Outdated
Comment thread tests/contrib/django/test_django_snapshots.py
@Kyle-Verhoog Kyle-Verhoog requested a review from P403n1x87 July 26, 2021 12:32
@mabdinur
Copy link
Copy Markdown
Contributor

LGTM

@mergify mergify Bot merged commit fddcd82 into DataDog:master Jul 26, 2021
@Kyle-Verhoog Kyle-Verhoog deleted the django-integration branch July 26, 2021 14:05
@Kyle-Verhoog Kyle-Verhoog restored the django-integration branch May 10, 2022 04:32
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

changelog/no-changelog A changelog entry is not required for this PR.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants