DataDog / dd-trace-py

Datadog Python APM Client
https://ddtrace.readthedocs.io/
Other
532 stars 408 forks source link

Django patching not properly capturing function middleware names #2873

Closed anlu closed 2 years ago

anlu commented 2 years ago

Which version of dd-trace-py are you using?

0.53.2

Which version of pip are you using?

21.2.3

Which version of the libraries are you using?

aa-stripe==0.11.0
aiohttp==3.7.4.post0
amqp==2.6.1
anyio==3.3.0
appdirs==1.4.4
appnope==0.1.2
argon2-cffi==20.1.0
async-timeout==3.0.1
attrs==21.2.0
awscli==1.20.11
Babel==2.9.1
backcall==0.2.0
bcrypt==3.2.0
beautifulsoup4==4.10.0
billiard==3.6.4.0
black==21.9b0
bleach==4.1.0
boto3==1.18.44
botocore==1.21.44
braintree==4.12.0
cachetools==4.2.2
cairocffi==1.2.0
CairoSVG==2.5.2
celery==4.4.2
certifi==2021.5.30
cffi==1.14.6
chardet==4.0.0
charset-normalizer==2.0.4
click==8.0.1
colorama==0.4.3
ConfigArgParse==1.5.2
convertdate==2.3.2
coreapi==2.3.3
coreschema==0.0.4
coverage==5.5
cryptography==3.4.8
cssselect==1.1.0
cssselect2==0.4.1
cssutils==2.3.0
curlify==2.2.1
datadog==0.42.0
ddtrace==0.53.2
debugpy==1.4.3
decorator==5.1.0
deepdiff==5.5.0
defusedxml==0.7.1
Django==2.2.24
django-admin-rangefilter==0.8.1
django-appconf==1.0.4
django-better-admin-arrayfield==1.4.2
django-celery-email==3.0.0
django-crispy-forms==1.12.0
django-extensions==3.1.3
django-filter==2.4.0
django-formtools==2.3
django-health-check==3.16.4
django-html-sanitizer==0.1.5
django-ipware==4.0.0
django-jet==1.0.8
django-localflavor==3.1
django-migration-linter==3.0.1
django-picklefield==3.0.1
django-push-notifications==1.4.1
django-redis==5.0.0
django-related-admin==1.0.1
django-rest-swagger==2.2.0
django-rosetta==0.9.7
django-safedelete==0.3.5
django-sendgrid-v5==0.8.1
django-ses==2.2.1
django-storages==1.11.1
django-websocket-redis==0.6.0
djangorestframework==3.12.4
djangorestframework-dataclasses==0.10
docutils==0.17.1
drf-tweaks==0.9.6
easypost==5.1.3
elasticsearch==6.8.2
entrypoints==0.3
execnet==1.9.0
facebook-business==12.0.0
factory-boy==3.2.0
Faker==8.13.2
fakeredis==1.6.1
fdadb==0.1.1
flake8==3.9.2
Flask==1.1.2
Flask-BasicAuth==0.2.0
Flask-Cors==3.0.10
flower==0.9.7
flup6==1.1.1
freezegun==1.1.0
frogress==0.9.1
future==0.18.2
gevent==21.8.0
geventhttpclient==1.4.4
google-api-core==1.31.2
google-api-python-client==2.0.2
google-auth==1.35.0
google-auth-httplib2==0.1.0
googleapis-common-protos==1.53.0
greenlet==1.1.1
gunicorn==20.1.0
hijri-converter==2.2.0
hiredis==2.0.0
holidays==0.11.2
html5lib==1.1
http-ece==1.1.0
httplib2==0.19.1
humanize==3.11.0
idna==2.10
ijson==3.1.4
iniconfig==1.1.1
intervaltree==3.1.0
ipykernel==6.2.0
ipython==7.27.0
ipython-genutils==0.2.0
isodate==0.6.0
isort==5.9.3
itsdangerous==2.0.1
itypes==1.2.0
jedi==0.18.0
Jinja2==3.0.1
jmespath==0.10.0
json5==0.9.6
jsonschema==3.2.0
jupyter-client==6.1.12
jupyter-core==4.7.1
jupyter-server==1.10.2
jupyterlab==3.1.12
jupyterlab-pygments==0.1.2
jupyterlab-server==2.7.1
kombu==4.6.11
korean-lunar-calendar==0.2.1
locust==1.6.0
lxml==4.6.3
MarkupSafe==2.0.1
matplotlib-inline==0.1.2
mccabe==0.6.1
mistune==0.8.4
mixpanel==4.8.3
mmh3==3.0.0
mock==4.0.3
more-itertools==8.8.0
moto==2.2.7
msgpack==1.0.2
multidict==5.1.0
mypy==0.910
mypy-extensions==0.4.3
nbclassic==0.3.1
nbclient==0.5.4
nbconvert==6.1.0
nbformat==5.1.3
nest-asyncio==1.5.1
notebook==6.4.3
numpy==1.21.2
openapi-codec==1.3.2
ordered-set==4.0.2
<internal package>
packaging==21.0
pandas==1.3.3
pandocfilters==1.4.3
paramiko==2.7.2
parso==0.8.2
pathspec==0.9.0
pep8==1.7.1
pexpect==4.8.0
phonenumbers==8.12.31
pickleshare==0.7.5
Pillow==8.3.2
platformdirs==2.4.0
pluggy==0.13.1
polib==1.1.1
premailer==3.9.0
prometheus-client==0.8.0
prompt-toolkit==3.0.19
protobuf==3.17.3
psutil==5.8.0
psycogreen==1.0.2
psycopg2-binary==2.8.6
ptyprocess==0.7.0
py==1.10.0
py-vapid==1.8.2
pyasn1==0.4.8
pyasn1-modules==0.2.8
pycodestyle==2.7.0
pycountry==20.7.3
pycparser==2.20
pycryptodome==3.10.1
pycryptodomex==3.10.1
pydocstyle==6.1.1
pyfcm==1.5.4
pyflakes==2.3.1
Pygments==2.10.0
pyheif==0.5.1
PyJWT==2.1.0
pylama==7.7.1
PyMeeus==0.5.11
PyNaCl==1.4.0
pyparsing==2.4.7
pyphen==0.11.0
pyrsistent==0.18.0
pytest==6.2.5
pytest-django==4.2.0
pytest-env==0.6.2
pytest-forked==1.3.0
pytest-split==0.3.3
pytest-xdist==2.3.0
python-barcode==0.13.1
python-dateutil==2.8.2
python-http-client==3.1.0
python-magic==0.4.24
python-stdnum==1.16
pytz==2021.1
PyYAML==5.4.1
pyzipper==0.3.5
pyzmq==22.2.1
rapidfuzz==1.6.2
redis==3.5.3
regex==2021.8.3
requests==2.26.0
requests-mock==1.9.3
requests-toolbelt==0.9.1
requests-unixsocket==0.2.0
responses==0.13.4
rjsmin==1.1.0
<internal package>
rsa==4.7.2
s3transfer==0.5.0
Send2Trash==1.8.0
sendgrid==5.6.0
sentry-sdk==1.3.1
simplejson==3.17.5
six==1.16.0
sniffio==1.2.0
snowballstemmer==2.1.0
sorl-thumbnail==12.7.0
sortedcontainers==2.4.0
soupsieve==2.2.1
sqlparse==0.4.1
stripe==2.60.0
structlog==21.1.0
tenacity==8.0.1
terminado==0.11.0
testpath==0.5.0
text-unidecode==1.3
tinycss2==1.1.0
toml==0.10.2
tomli==1.2.1
tornado==6.1
traitlets==5.1.0
twilio==6.50.1
types-bleach==4.1.0
types-boto==2.49.0
types-certifi==2020.4.0
types-cryptography==3.3.3
types-enum34==1.1.0
types-freezegun==1.1.0
types-futures==3.3.0
types-ipaddress==1.0.0
types-mock==4.0.1
types-pkg-resources==0.1.3
types-protobuf==3.17.4
types-python-dateutil==2.8.0
types-pytz==2021.1.2
types-PyYAML==5.4.10
types-requests==2.25.7
types-simplejson==3.17.0
types-six==1.16.1
typing-extensions==3.10.0.0
ua-parser==0.10.0
Unidecode==1.3.2
universal-notifications==1.4.0
uritemplate==3.0.1
urllib3==1.26.6
user-agents==2.2.0
uWSGI==2.0.19.1
vine==1.3.0
wcwidth==0.2.5
WeasyPrint==52.5
webencodings==0.5.1
websocket-client==1.2.1
Werkzeug==2.0.1
wrapt==1.12.1
xmltodict==0.12.0
yarl==1.6.3
zope.event==4.5.0
zope.interface==5.4.0

How can we reproduce your problem?

What is the result that you get?

What is the result that you expected?

Set up a Django app with multiple function (not class based) middlewares. Make a request to any view. Observe that the Datadog APM spans for all function based middlewares are labeled with the last middleware as set in the Django MIDDLEWARE configuration variable in settings.py. They should be labeled correctly.

I believe the error lies in the delayed evaluation of the mw_path variable here, when it has already finished iterating over settings_middleware.

https://github.com/DataDog/dd-trace-py/blob/v0.53.2/ddtrace/contrib/django/patch.py#L260

brettlangdon commented 2 years ago

@anlu sorry for the long delay getting back to you.

Your investigation was spot on. That is exactly what is happening, we are using a reference to mw_path which is updated by the loop, so all function middleware share the same resource name.

I have a fix available in #2884 that will resolve this.

Thank you for reporting!!

brettlangdon commented 2 years ago

@anlu this is now released in ddtrace==0.53.3, please let us know if the issue continues!