diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index b29f243c474..47d2baf065c 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -6,6 +6,7 @@ stages: - shared-pipeline - benchmarks - macrobenchmarks + - benchmarks-report - release variables: diff --git a/.gitlab/benchmarks.yml b/.gitlab/benchmarks.yml index 6c7b48aea3a..e922d315444 100644 --- a/.gitlab/benchmarks.yml +++ b/.gitlab/benchmarks.yml @@ -59,8 +59,7 @@ microbenchmarks: benchmarks-pr-comment: image: $MICROBENCHMARKS_CI_IMAGE tags: ["arch:amd64"] - stage: benchmarks - needs: [ "microbenchmarks" ] + stage: benchmarks-report when: always script: - export REPORTS_DIR="$(pwd)/reports/" && (mkdir "${REPORTS_DIR}" || :) @@ -78,8 +77,7 @@ benchmarks-pr-comment: KUBERNETES_SERVICE_ACCOUNT_OVERWRITE: dd-trace-py check-big-regressions: - stage: benchmarks - needs: [ microbenchmarks, benchmark-serverless ] + stage: benchmarks-report when: always tags: ["arch:amd64"] image: $MICROBENCHMARKS_CI_IMAGE diff --git a/.riot/requirements/107d8f2.txt b/.riot/requirements/107d8f2.txt new file mode 100644 index 00000000000..7bed129ddaf --- /dev/null +++ b/.riot/requirements/107d8f2.txt @@ -0,0 +1,54 @@ +# +# This file is autogenerated by pip-compile with Python 3.9 +# by the following command: +# +# pip-compile --no-annotate --resolver=backtracking .riot/requirements/107d8f2.in +# +annotated-types==0.7.0 +anyio==4.8.0 +attrs==24.3.0 +certifi==2024.12.14 +coverage[toml]==7.6.10 +distro==1.9.0 +exceptiongroup==1.2.2 +h11==0.14.0 +httpcore==1.0.7 +httpx==0.27.2 +hypothesis==6.45.0 +idna==3.10 +importlib-metadata==8.6.1 +iniconfig==2.0.0 +mock==5.1.0 +multidict==6.1.0 +numpy==2.0.2 +openai[datalib,embeddings]==1.30.1 +opentracing==2.4.0 +packaging==24.2 +pandas==2.2.3 +pandas-stubs==2.2.2.240807 +pillow==9.5.0 +pluggy==1.5.0 +propcache==0.2.1 +pydantic==2.10.5 +pydantic-core==2.27.2 +pytest==8.3.4 +pytest-asyncio==0.21.1 +pytest-cov==6.0.0 +pytest-mock==3.14.0 +pytest-randomly==3.16.0 +python-dateutil==2.9.0.post0 +pytz==2024.2 +pyyaml==6.0.2 +six==1.17.0 +sniffio==1.3.1 +sortedcontainers==2.4.0 +tomli==2.2.1 +tqdm==4.67.1 +types-pytz==2024.2.0.20241221 +typing-extensions==4.12.2 +tzdata==2025.1 +urllib3==1.26.20 +vcrpy==4.2.1 +wrapt==1.17.2 +yarl==1.18.3 +zipp==3.21.0 diff --git a/.riot/requirements/130158f.txt b/.riot/requirements/130158f.txt new file mode 100644 index 00000000000..037c7010f33 --- /dev/null +++ b/.riot/requirements/130158f.txt @@ -0,0 +1,48 @@ +# +# This file is autogenerated by pip-compile with Python 3.12 +# by the following command: +# +# pip-compile --no-annotate .riot/requirements/130158f.in +# +annotated-types==0.7.0 +anyio==4.8.0 +attrs==24.3.0 +certifi==2024.12.14 +charset-normalizer==3.4.1 +coverage[toml]==7.6.10 +distro==1.9.0 +h11==0.14.0 +httpcore==1.0.7 +httpx==0.28.1 +hypothesis==6.45.0 +idna==3.10 +iniconfig==2.0.0 +jiter==0.8.2 +mock==5.1.0 +multidict==6.1.0 +openai==1.60.0 +opentracing==2.4.0 +packaging==24.2 +pillow==11.1.0 +pluggy==1.5.0 +propcache==0.2.1 +pydantic==2.10.5 +pydantic-core==2.27.2 +pytest==8.3.4 +pytest-asyncio==0.21.1 +pytest-cov==6.0.0 +pytest-mock==3.14.0 +pytest-randomly==3.16.0 +pyyaml==6.0.2 +regex==2024.11.6 +requests==2.32.3 +six==1.17.0 +sniffio==1.3.1 +sortedcontainers==2.4.0 +tiktoken==0.8.0 +tqdm==4.67.1 +typing-extensions==4.12.2 +urllib3==1.26.20 +vcrpy==4.2.1 +wrapt==1.17.2 +yarl==1.18.3 diff --git a/.riot/requirements/13804af.txt b/.riot/requirements/13804af.txt deleted file mode 100644 index 7035a764386..00000000000 --- a/.riot/requirements/13804af.txt +++ /dev/null @@ -1,57 +0,0 @@ -# -# This file is autogenerated by pip-compile with Python 3.8 -# by the following command: -# -# pip-compile --allow-unsafe --no-annotate .riot/requirements/13804af.in -# -annotated-types==0.7.0 -anyio==4.4.0 -attrs==24.2.0 -certifi==2024.7.4 -charset-normalizer==3.3.2 -coverage[toml]==7.6.1 -distro==1.9.0 -exceptiongroup==1.2.2 -h11==0.14.0 -httpcore==1.0.5 -httpx==0.27.0 -hypothesis==6.45.0 -idna==3.8 -importlib-metadata==8.4.0 -iniconfig==2.0.0 -mock==5.1.0 -multidict==6.0.5 -numpy==1.24.4 -openai[datalib]==1.30.1 -opentracing==2.4.0 -packaging==24.1 -pandas==2.0.3 -pandas-stubs==2.0.3.230814 -pillow==10.1.0 -pluggy==1.5.0 -pydantic==2.8.2 -pydantic-core==2.20.1 -pytest==8.3.2 -pytest-asyncio==0.21.1 -pytest-cov==5.0.0 -pytest-mock==3.14.0 -pytest-randomly==3.15.0 -python-dateutil==2.9.0.post0 -pytz==2024.1 -pyyaml==6.0.2 -regex==2024.7.24 -requests==2.32.3 -six==1.16.0 -sniffio==1.3.1 -sortedcontainers==2.4.0 -tiktoken==0.7.0 -tomli==2.0.1 -tqdm==4.66.5 -types-pytz==2024.1.0.20240417 -typing-extensions==4.12.2 -tzdata==2024.1 -urllib3==1.26.19 -vcrpy==4.2.1 -wrapt==1.16.0 -yarl==1.9.4 -zipp==3.20.1 diff --git a/.riot/requirements/13fec34.txt b/.riot/requirements/13fec34.txt deleted file mode 100644 index 8858506f793..00000000000 --- a/.riot/requirements/13fec34.txt +++ /dev/null @@ -1,49 +0,0 @@ -# -# This file is autogenerated by pip-compile with Python 3.11 -# by the following command: -# -# pip-compile --allow-unsafe --no-annotate .riot/requirements/13fec34.in -# -annotated-types==0.7.0 -anyio==3.7.1 -attrs==24.2.0 -certifi==2024.7.4 -coverage[toml]==7.6.1 -distro==1.9.0 -h11==0.14.0 -httpcore==1.0.5 -httpx==0.27.0 -hypothesis==6.45.0 -idna==3.8 -iniconfig==2.0.0 -mock==5.1.0 -multidict==6.0.5 -numpy==2.1.0 -openai[datalib,embeddings]==1.1.1 -opentracing==2.4.0 -packaging==24.1 -pandas==2.2.2 -pandas-stubs==2.2.2.240807 -pillow==9.5.0 -pluggy==1.5.0 -pydantic==2.8.2 -pydantic-core==2.20.1 -pytest==8.3.2 -pytest-asyncio==0.21.1 -pytest-cov==5.0.0 -pytest-mock==3.14.0 -pytest-randomly==3.15.0 -python-dateutil==2.9.0.post0 -pytz==2024.1 -pyyaml==6.0.2 -six==1.16.0 -sniffio==1.3.1 -sortedcontainers==2.4.0 -tqdm==4.66.5 -types-pytz==2024.1.0.20240417 -typing-extensions==4.12.2 -tzdata==2024.1 -urllib3==1.26.19 -vcrpy==4.2.1 -wrapt==1.16.0 -yarl==1.9.4 diff --git a/.riot/requirements/1825740.txt b/.riot/requirements/1825740.txt index b4660fad985..d1ef7a92bc0 100644 --- a/.riot/requirements/1825740.txt +++ b/.riot/requirements/1825740.txt @@ -9,13 +9,13 @@ aiosignal==1.3.1 async-timeout==4.0.3 asynctest==0.13.0 attrs==24.2.0 -certifi==2024.7.4 -charset-normalizer==3.3.2 +certifi==2024.12.14 +charset-normalizer==3.4.1 coverage[toml]==7.2.7 exceptiongroup==1.2.2 frozenlist==1.3.3 hypothesis==6.45.0 -idna==3.8 +idna==3.10 importlib-metadata==6.7.0 iniconfig==2.0.0 joblib==1.3.2 @@ -36,13 +36,13 @@ pyyaml==6.0.1 requests==2.31.0 scikit-learn==1.0.2 scipy==1.7.3 -six==1.16.0 +six==1.17.0 sortedcontainers==2.4.0 threadpoolctl==3.1.0 tomli==2.0.1 -tqdm==4.66.5 +tqdm==4.67.1 typing-extensions==4.7.1 -urllib3==1.26.19 +urllib3==1.26.20 vcrpy==4.2.1 wrapt==1.16.0 yarl==1.9.4 diff --git a/.riot/requirements/18de44f.txt b/.riot/requirements/18de44f.txt new file mode 100644 index 00000000000..702b980c641 --- /dev/null +++ b/.riot/requirements/18de44f.txt @@ -0,0 +1,52 @@ +# +# This file is autogenerated by pip-compile with Python 3.8 +# by the following command: +# +# pip-compile --no-annotate --resolver=backtracking .riot/requirements/18de44f.in +# +annotated-types==0.7.0 +anyio==4.5.2 +attrs==24.3.0 +certifi==2024.12.14 +charset-normalizer==3.4.1 +coverage[toml]==7.6.1 +distro==1.9.0 +exceptiongroup==1.2.2 +h11==0.14.0 +httpcore==1.0.7 +httpx==0.28.1 +hypothesis==6.45.0 +idna==3.10 +importlib-metadata==8.5.0 +iniconfig==2.0.0 +jiter==0.8.2 +mock==5.1.0 +multidict==6.1.0 +openai==1.60.0 +opentracing==2.4.0 +packaging==24.2 +pillow==10.4.0 +pluggy==1.5.0 +propcache==0.2.0 +pydantic==2.10.5 +pydantic-core==2.27.2 +pytest==8.3.4 +pytest-asyncio==0.21.1 +pytest-cov==5.0.0 +pytest-mock==3.14.0 +pytest-randomly==3.15.0 +pyyaml==6.0.2 +regex==2024.11.6 +requests==2.32.3 +six==1.17.0 +sniffio==1.3.1 +sortedcontainers==2.4.0 +tiktoken==0.7.0 +tomli==2.2.1 +tqdm==4.67.1 +typing-extensions==4.12.2 +urllib3==1.26.20 +vcrpy==4.2.1 +wrapt==1.17.2 +yarl==1.15.2 +zipp==3.20.2 diff --git a/.riot/requirements/1ad89c5.txt b/.riot/requirements/1ad89c5.txt new file mode 100644 index 00000000000..b10206e12d9 --- /dev/null +++ b/.riot/requirements/1ad89c5.txt @@ -0,0 +1,50 @@ +# +# This file is autogenerated by pip-compile with Python 3.10 +# by the following command: +# +# pip-compile --no-annotate .riot/requirements/1ad89c5.in +# +annotated-types==0.7.0 +anyio==4.8.0 +attrs==24.3.0 +certifi==2024.12.14 +charset-normalizer==3.4.1 +coverage[toml]==7.6.10 +distro==1.9.0 +exceptiongroup==1.2.2 +h11==0.14.0 +httpcore==1.0.7 +httpx==0.28.1 +hypothesis==6.45.0 +idna==3.10 +iniconfig==2.0.0 +jiter==0.8.2 +mock==5.1.0 +multidict==6.1.0 +openai==1.60.0 +opentracing==2.4.0 +packaging==24.2 +pillow==11.1.0 +pluggy==1.5.0 +propcache==0.2.1 +pydantic==2.10.5 +pydantic-core==2.27.2 +pytest==8.3.4 +pytest-asyncio==0.21.1 +pytest-cov==6.0.0 +pytest-mock==3.14.0 +pytest-randomly==3.16.0 +pyyaml==6.0.2 +regex==2024.11.6 +requests==2.32.3 +six==1.17.0 +sniffio==1.3.1 +sortedcontainers==2.4.0 +tiktoken==0.8.0 +tomli==2.2.1 +tqdm==4.67.1 +typing-extensions==4.12.2 +urllib3==1.26.20 +vcrpy==4.2.1 +wrapt==1.17.2 +yarl==1.18.3 diff --git a/.riot/requirements/1db5311.txt b/.riot/requirements/1e6bd37.txt similarity index 55% rename from .riot/requirements/1db5311.txt rename to .riot/requirements/1e6bd37.txt index c29bc9bdb8f..11bb5871c14 100644 --- a/.riot/requirements/1db5311.txt +++ b/.riot/requirements/1e6bd37.txt @@ -2,52 +2,53 @@ # This file is autogenerated by pip-compile with Python 3.8 # by the following command: # -# pip-compile --allow-unsafe --no-annotate .riot/requirements/1db5311.in +# pip-compile --no-annotate --resolver=backtracking .riot/requirements/1e6bd37.in # annotated-types==0.7.0 -anyio==4.4.0 -attrs==24.2.0 -certifi==2024.7.4 +anyio==4.5.2 +attrs==24.3.0 +certifi==2024.12.14 coverage[toml]==7.6.1 distro==1.9.0 exceptiongroup==1.2.2 h11==0.14.0 -httpcore==1.0.5 -httpx==0.27.0 +httpcore==1.0.7 +httpx==0.27.2 hypothesis==6.45.0 -idna==3.8 -importlib-metadata==8.4.0 +idna==3.10 +importlib-metadata==8.5.0 iniconfig==2.0.0 mock==5.1.0 -multidict==6.0.5 +multidict==6.1.0 numpy==1.24.4 openai[datalib,embeddings]==1.30.1 opentracing==2.4.0 -packaging==24.1 +packaging==24.2 pandas==2.0.3 pandas-stubs==2.0.3.230814 pillow==9.5.0 pluggy==1.5.0 -pydantic==2.8.2 -pydantic-core==2.20.1 -pytest==8.3.2 +propcache==0.2.0 +pydantic==2.10.5 +pydantic-core==2.27.2 +pytest==8.3.4 pytest-asyncio==0.21.1 pytest-cov==5.0.0 pytest-mock==3.14.0 pytest-randomly==3.15.0 python-dateutil==2.9.0.post0 -pytz==2024.1 +pytz==2024.2 pyyaml==6.0.2 -six==1.16.0 +six==1.17.0 sniffio==1.3.1 sortedcontainers==2.4.0 -tomli==2.0.1 -tqdm==4.66.5 -types-pytz==2024.1.0.20240417 +tomli==2.2.1 +tqdm==4.67.1 +types-pytz==2024.2.0.20241221 typing-extensions==4.12.2 -tzdata==2024.1 -urllib3==1.26.19 +tzdata==2025.1 +urllib3==1.26.20 vcrpy==4.2.1 -wrapt==1.16.0 -yarl==1.9.4 -zipp==3.20.1 +wrapt==1.17.2 +yarl==1.15.2 +zipp==3.20.2 diff --git a/.riot/requirements/1ec15f5.txt b/.riot/requirements/1ec15f5.txt deleted file mode 100644 index b4479a2fb39..00000000000 --- a/.riot/requirements/1ec15f5.txt +++ /dev/null @@ -1,57 +0,0 @@ -# -# This file is autogenerated by pip-compile with Python 3.9 -# by the following command: -# -# pip-compile --allow-unsafe --no-annotate .riot/requirements/1ec15f5.in -# -annotated-types==0.7.0 -anyio==4.4.0 -attrs==24.2.0 -certifi==2024.7.4 -charset-normalizer==3.3.2 -coverage[toml]==7.6.1 -distro==1.9.0 -exceptiongroup==1.2.2 -h11==0.14.0 -httpcore==1.0.5 -httpx==0.27.0 -hypothesis==6.45.0 -idna==3.8 -importlib-metadata==8.4.0 -iniconfig==2.0.0 -mock==5.1.0 -multidict==6.0.5 -numpy==2.0.1 -openai[datalib]==1.30.1 -opentracing==2.4.0 -packaging==24.1 -pandas==2.2.2 -pandas-stubs==2.2.2.240807 -pillow==10.1.0 -pluggy==1.5.0 -pydantic==2.8.2 -pydantic-core==2.20.1 -pytest==8.3.2 -pytest-asyncio==0.21.1 -pytest-cov==5.0.0 -pytest-mock==3.14.0 -pytest-randomly==3.15.0 -python-dateutil==2.9.0.post0 -pytz==2024.1 -pyyaml==6.0.2 -regex==2024.7.24 -requests==2.32.3 -six==1.16.0 -sniffio==1.3.1 -sortedcontainers==2.4.0 -tiktoken==0.7.0 -tomli==2.0.1 -tqdm==4.66.5 -types-pytz==2024.1.0.20240417 -typing-extensions==4.12.2 -tzdata==2024.1 -urllib3==1.26.19 -vcrpy==4.2.1 -wrapt==1.16.0 -yarl==1.9.4 -zipp==3.20.1 diff --git a/.riot/requirements/1ee49b9.txt b/.riot/requirements/1ee49b9.txt deleted file mode 100644 index f170e2885c4..00000000000 --- a/.riot/requirements/1ee49b9.txt +++ /dev/null @@ -1,53 +0,0 @@ -# -# This file is autogenerated by pip-compile with Python 3.11 -# by the following command: -# -# pip-compile --allow-unsafe --no-annotate .riot/requirements/1ee49b9.in -# -annotated-types==0.7.0 -anyio==4.4.0 -attrs==24.2.0 -certifi==2024.7.4 -charset-normalizer==3.3.2 -coverage[toml]==7.6.1 -distro==1.9.0 -h11==0.14.0 -httpcore==1.0.5 -httpx==0.27.0 -hypothesis==6.45.0 -idna==3.8 -iniconfig==2.0.0 -mock==5.1.0 -multidict==6.0.5 -numpy==2.1.0 -openai[datalib]==1.30.1 -opentracing==2.4.0 -packaging==24.1 -pandas==2.2.2 -pandas-stubs==2.2.2.240807 -pillow==10.1.0 -pluggy==1.5.0 -pydantic==2.8.2 -pydantic-core==2.20.1 -pytest==8.3.2 -pytest-asyncio==0.21.1 -pytest-cov==5.0.0 -pytest-mock==3.14.0 -pytest-randomly==3.15.0 -python-dateutil==2.9.0.post0 -pytz==2024.1 -pyyaml==6.0.2 -regex==2024.7.24 -requests==2.32.3 -six==1.16.0 -sniffio==1.3.1 -sortedcontainers==2.4.0 -tiktoken==0.7.0 -tqdm==4.66.5 -types-pytz==2024.1.0.20240417 -typing-extensions==4.12.2 -tzdata==2024.1 -urllib3==1.26.19 -vcrpy==4.2.1 -wrapt==1.16.0 -yarl==1.9.4 diff --git a/.riot/requirements/2634bf7.txt b/.riot/requirements/2634bf7.txt new file mode 100644 index 00000000000..0000f6e28ff --- /dev/null +++ b/.riot/requirements/2634bf7.txt @@ -0,0 +1,48 @@ +# +# This file is autogenerated by pip-compile with Python 3.11 +# by the following command: +# +# pip-compile --no-annotate --resolver=backtracking .riot/requirements/2634bf7.in +# +annotated-types==0.7.0 +anyio==4.8.0 +attrs==24.3.0 +certifi==2024.12.14 +charset-normalizer==3.4.1 +coverage[toml]==7.6.10 +distro==1.9.0 +h11==0.14.0 +httpcore==1.0.7 +httpx==0.28.1 +hypothesis==6.45.0 +idna==3.10 +iniconfig==2.0.0 +jiter==0.8.2 +mock==5.1.0 +multidict==6.1.0 +openai==1.60.0 +opentracing==2.4.0 +packaging==24.2 +pillow==11.1.0 +pluggy==1.5.0 +propcache==0.2.1 +pydantic==2.10.5 +pydantic-core==2.27.2 +pytest==8.3.4 +pytest-asyncio==0.21.1 +pytest-cov==6.0.0 +pytest-mock==3.14.0 +pytest-randomly==3.16.0 +pyyaml==6.0.2 +regex==2024.11.6 +requests==2.32.3 +six==1.17.0 +sniffio==1.3.1 +sortedcontainers==2.4.0 +tiktoken==0.8.0 +tqdm==4.67.1 +typing-extensions==4.12.2 +urllib3==1.26.20 +vcrpy==4.2.1 +wrapt==1.17.2 +yarl==1.18.3 diff --git a/.riot/requirements/35ce786.txt b/.riot/requirements/35ce786.txt deleted file mode 100644 index 3489155be91..00000000000 --- a/.riot/requirements/35ce786.txt +++ /dev/null @@ -1,55 +0,0 @@ -# -# This file is autogenerated by pip-compile with Python 3.10 -# by the following command: -# -# pip-compile --allow-unsafe --no-annotate .riot/requirements/35ce786.in -# -annotated-types==0.7.0 -anyio==4.4.0 -attrs==24.2.0 -certifi==2024.7.4 -charset-normalizer==3.3.2 -coverage[toml]==7.6.1 -distro==1.9.0 -exceptiongroup==1.2.2 -h11==0.14.0 -httpcore==1.0.5 -httpx==0.27.0 -hypothesis==6.45.0 -idna==3.8 -iniconfig==2.0.0 -mock==5.1.0 -multidict==6.0.5 -numpy==2.1.0 -openai[datalib]==1.30.1 -opentracing==2.4.0 -packaging==24.1 -pandas==2.2.2 -pandas-stubs==2.2.2.240807 -pillow==10.1.0 -pluggy==1.5.0 -pydantic==2.8.2 -pydantic-core==2.20.1 -pytest==8.3.2 -pytest-asyncio==0.21.1 -pytest-cov==5.0.0 -pytest-mock==3.14.0 -pytest-randomly==3.15.0 -python-dateutil==2.9.0.post0 -pytz==2024.1 -pyyaml==6.0.2 -regex==2024.7.24 -requests==2.32.3 -six==1.16.0 -sniffio==1.3.1 -sortedcontainers==2.4.0 -tiktoken==0.7.0 -tomli==2.0.1 -tqdm==4.66.5 -types-pytz==2024.1.0.20240417 -typing-extensions==4.12.2 -tzdata==2024.1 -urllib3==1.26.19 -vcrpy==4.2.1 -wrapt==1.16.0 -yarl==1.9.4 diff --git a/.riot/requirements/4a85f6d.txt b/.riot/requirements/4a85f6d.txt new file mode 100644 index 00000000000..41953c69178 --- /dev/null +++ b/.riot/requirements/4a85f6d.txt @@ -0,0 +1,50 @@ +# +# This file is autogenerated by pip-compile with Python 3.11 +# by the following command: +# +# pip-compile --no-annotate --resolver=backtracking .riot/requirements/4a85f6d.in +# +annotated-types==0.7.0 +anyio==4.8.0 +attrs==24.3.0 +certifi==2024.12.14 +coverage[toml]==7.6.10 +distro==1.9.0 +h11==0.14.0 +httpcore==1.0.7 +httpx==0.27.2 +hypothesis==6.45.0 +idna==3.10 +iniconfig==2.0.0 +mock==5.1.0 +multidict==6.1.0 +numpy==2.2.2 +openai[datalib,embeddings]==1.30.1 +opentracing==2.4.0 +packaging==24.2 +pandas==2.2.3 +pandas-stubs==2.2.3.241126 +pillow==9.5.0 +pluggy==1.5.0 +propcache==0.2.1 +pydantic==2.10.5 +pydantic-core==2.27.2 +pytest==8.3.4 +pytest-asyncio==0.21.1 +pytest-cov==6.0.0 +pytest-mock==3.14.0 +pytest-randomly==3.16.0 +python-dateutil==2.9.0.post0 +pytz==2024.2 +pyyaml==6.0.2 +six==1.17.0 +sniffio==1.3.1 +sortedcontainers==2.4.0 +tqdm==4.67.1 +types-pytz==2024.2.0.20241221 +typing-extensions==4.12.2 +tzdata==2025.1 +urllib3==1.26.20 +vcrpy==4.2.1 +wrapt==1.17.2 +yarl==1.18.3 diff --git a/.riot/requirements/4d27459.txt b/.riot/requirements/4d27459.txt new file mode 100644 index 00000000000..630c81558f3 --- /dev/null +++ b/.riot/requirements/4d27459.txt @@ -0,0 +1,48 @@ +# +# This file is autogenerated by pip-compile with Python 3.13 +# by the following command: +# +# pip-compile --no-annotate .riot/requirements/4d27459.in +# +annotated-types==0.7.0 +anyio==4.8.0 +attrs==24.3.0 +certifi==2024.12.14 +charset-normalizer==3.4.1 +coverage[toml]==7.6.10 +distro==1.9.0 +h11==0.14.0 +httpcore==1.0.7 +httpx==0.28.1 +hypothesis==6.45.0 +idna==3.10 +iniconfig==2.0.0 +jiter==0.8.2 +mock==5.1.0 +multidict==6.1.0 +openai==1.60.0 +opentracing==2.4.0 +packaging==24.2 +pillow==11.1.0 +pluggy==1.5.0 +propcache==0.2.1 +pydantic==2.10.5 +pydantic-core==2.27.2 +pytest==8.3.4 +pytest-asyncio==0.21.1 +pytest-cov==6.0.0 +pytest-mock==3.14.0 +pytest-randomly==3.16.0 +pyyaml==6.0.2 +regex==2024.11.6 +requests==2.32.3 +six==1.17.0 +sniffio==1.3.1 +sortedcontainers==2.4.0 +tiktoken==0.8.0 +tqdm==4.67.1 +typing-extensions==4.12.2 +urllib3==1.26.20 +vcrpy==4.2.1 +wrapt==1.17.2 +yarl==1.18.3 diff --git a/.riot/requirements/530c983.txt b/.riot/requirements/530c983.txt new file mode 100644 index 00000000000..c07f9a6b918 --- /dev/null +++ b/.riot/requirements/530c983.txt @@ -0,0 +1,52 @@ +# +# This file is autogenerated by pip-compile with Python 3.9 +# by the following command: +# +# pip-compile --no-annotate --resolver=backtracking .riot/requirements/530c983.in +# +annotated-types==0.7.0 +anyio==4.8.0 +attrs==24.3.0 +certifi==2024.12.14 +charset-normalizer==3.4.1 +coverage[toml]==7.6.10 +distro==1.9.0 +exceptiongroup==1.2.2 +h11==0.14.0 +httpcore==1.0.7 +httpx==0.28.1 +hypothesis==6.45.0 +idna==3.10 +importlib-metadata==8.6.1 +iniconfig==2.0.0 +jiter==0.8.2 +mock==5.1.0 +multidict==6.1.0 +openai==1.60.0 +opentracing==2.4.0 +packaging==24.2 +pillow==11.1.0 +pluggy==1.5.0 +propcache==0.2.1 +pydantic==2.10.5 +pydantic-core==2.27.2 +pytest==8.3.4 +pytest-asyncio==0.21.1 +pytest-cov==6.0.0 +pytest-mock==3.14.0 +pytest-randomly==3.16.0 +pyyaml==6.0.2 +regex==2024.11.6 +requests==2.32.3 +six==1.17.0 +sniffio==1.3.1 +sortedcontainers==2.4.0 +tiktoken==0.8.0 +tomli==2.2.1 +tqdm==4.67.1 +typing-extensions==4.12.2 +urllib3==1.26.20 +vcrpy==4.2.1 +wrapt==1.17.2 +yarl==1.18.3 +zipp==3.21.0 diff --git a/.riot/requirements/5da4fd8.txt b/.riot/requirements/5da4fd8.txt deleted file mode 100644 index a700b91bf81..00000000000 --- a/.riot/requirements/5da4fd8.txt +++ /dev/null @@ -1,49 +0,0 @@ -# -# This file is autogenerated by pip-compile with Python 3.11 -# by the following command: -# -# pip-compile --allow-unsafe --no-annotate .riot/requirements/5da4fd8.in -# -annotated-types==0.7.0 -anyio==4.4.0 -attrs==24.2.0 -certifi==2024.7.4 -coverage[toml]==7.6.1 -distro==1.9.0 -h11==0.14.0 -httpcore==1.0.5 -httpx==0.27.0 -hypothesis==6.45.0 -idna==3.8 -iniconfig==2.0.0 -mock==5.1.0 -multidict==6.0.5 -numpy==2.1.0 -openai[datalib,embeddings]==1.30.1 -opentracing==2.4.0 -packaging==24.1 -pandas==2.2.2 -pandas-stubs==2.2.2.240807 -pillow==9.5.0 -pluggy==1.5.0 -pydantic==2.8.2 -pydantic-core==2.20.1 -pytest==8.3.2 -pytest-asyncio==0.21.1 -pytest-cov==5.0.0 -pytest-mock==3.14.0 -pytest-randomly==3.15.0 -python-dateutil==2.9.0.post0 -pytz==2024.1 -pyyaml==6.0.2 -six==1.16.0 -sniffio==1.3.1 -sortedcontainers==2.4.0 -tqdm==4.66.5 -types-pytz==2024.1.0.20240417 -typing-extensions==4.12.2 -tzdata==2024.1 -urllib3==1.26.19 -vcrpy==4.2.1 -wrapt==1.16.0 -yarl==1.9.4 diff --git a/.riot/requirements/84ec59a.txt b/.riot/requirements/84ec59a.txt deleted file mode 100644 index 9b079cf3a38..00000000000 --- a/.riot/requirements/84ec59a.txt +++ /dev/null @@ -1,53 +0,0 @@ -# -# This file is autogenerated by pip-compile with Python 3.8 -# by the following command: -# -# pip-compile --allow-unsafe --no-annotate .riot/requirements/84ec59a.in -# -annotated-types==0.7.0 -anyio==3.7.1 -attrs==24.2.0 -certifi==2024.7.4 -coverage[toml]==7.6.1 -distro==1.9.0 -exceptiongroup==1.2.2 -h11==0.14.0 -httpcore==1.0.5 -httpx==0.27.0 -hypothesis==6.45.0 -idna==3.8 -importlib-metadata==8.4.0 -iniconfig==2.0.0 -mock==5.1.0 -multidict==6.0.5 -numpy==1.24.4 -openai[datalib,embeddings]==1.1.1 -opentracing==2.4.0 -packaging==24.1 -pandas==2.0.3 -pandas-stubs==2.0.3.230814 -pillow==9.5.0 -pluggy==1.5.0 -pydantic==2.8.2 -pydantic-core==2.20.1 -pytest==8.3.2 -pytest-asyncio==0.21.1 -pytest-cov==5.0.0 -pytest-mock==3.14.0 -pytest-randomly==3.15.0 -python-dateutil==2.9.0.post0 -pytz==2024.1 -pyyaml==6.0.2 -six==1.16.0 -sniffio==1.3.1 -sortedcontainers==2.4.0 -tomli==2.0.1 -tqdm==4.66.5 -types-pytz==2024.1.0.20240417 -typing-extensions==4.12.2 -tzdata==2024.1 -urllib3==1.26.19 -vcrpy==4.2.1 -wrapt==1.16.0 -yarl==1.9.4 -zipp==3.20.1 diff --git a/.riot/requirements/87a1fff.txt b/.riot/requirements/87a1fff.txt deleted file mode 100644 index b85e76cdd56..00000000000 --- a/.riot/requirements/87a1fff.txt +++ /dev/null @@ -1,53 +0,0 @@ -# -# This file is autogenerated by pip-compile with Python 3.9 -# by the following command: -# -# pip-compile --allow-unsafe --no-annotate .riot/requirements/87a1fff.in -# -annotated-types==0.7.0 -anyio==4.4.0 -attrs==24.2.0 -certifi==2024.7.4 -coverage[toml]==7.6.1 -distro==1.9.0 -exceptiongroup==1.2.2 -h11==0.14.0 -httpcore==1.0.5 -httpx==0.27.0 -hypothesis==6.45.0 -idna==3.8 -importlib-metadata==8.4.0 -iniconfig==2.0.0 -mock==5.1.0 -multidict==6.0.5 -numpy==2.0.1 -openai[datalib,embeddings]==1.30.1 -opentracing==2.4.0 -packaging==24.1 -pandas==2.2.2 -pandas-stubs==2.2.2.240807 -pillow==9.5.0 -pluggy==1.5.0 -pydantic==2.8.2 -pydantic-core==2.20.1 -pytest==8.3.2 -pytest-asyncio==0.21.1 -pytest-cov==5.0.0 -pytest-mock==3.14.0 -pytest-randomly==3.15.0 -python-dateutil==2.9.0.post0 -pytz==2024.1 -pyyaml==6.0.2 -six==1.16.0 -sniffio==1.3.1 -sortedcontainers==2.4.0 -tomli==2.0.1 -tqdm==4.66.5 -types-pytz==2024.1.0.20240417 -typing-extensions==4.12.2 -tzdata==2024.1 -urllib3==1.26.19 -vcrpy==4.2.1 -wrapt==1.16.0 -yarl==1.9.4 -zipp==3.20.1 diff --git a/.riot/requirements/b5d5a35.txt b/.riot/requirements/b5d5a35.txt new file mode 100644 index 00000000000..7838b7abd2c --- /dev/null +++ b/.riot/requirements/b5d5a35.txt @@ -0,0 +1,52 @@ +# +# This file is autogenerated by pip-compile with Python 3.10 +# by the following command: +# +# pip-compile --no-annotate .riot/requirements/b5d5a35.in +# +annotated-types==0.7.0 +anyio==4.8.0 +attrs==24.3.0 +certifi==2024.12.14 +coverage[toml]==7.6.10 +distro==1.9.0 +exceptiongroup==1.2.2 +h11==0.14.0 +httpcore==1.0.7 +httpx==0.27.2 +hypothesis==6.45.0 +idna==3.10 +iniconfig==2.0.0 +mock==5.1.0 +multidict==6.1.0 +numpy==2.2.2 +openai[datalib,embeddings]==1.30.1 +opentracing==2.4.0 +packaging==24.2 +pandas==2.2.3 +pandas-stubs==2.2.3.241126 +pillow==9.5.0 +pluggy==1.5.0 +propcache==0.2.1 +pydantic==2.10.5 +pydantic-core==2.27.2 +pytest==8.3.4 +pytest-asyncio==0.21.1 +pytest-cov==6.0.0 +pytest-mock==3.14.0 +pytest-randomly==3.16.0 +python-dateutil==2.9.0.post0 +pytz==2024.2 +pyyaml==6.0.2 +six==1.17.0 +sniffio==1.3.1 +sortedcontainers==2.4.0 +tomli==2.2.1 +tqdm==4.67.1 +types-pytz==2024.2.0.20241221 +typing-extensions==4.12.2 +tzdata==2025.1 +urllib3==1.26.20 +vcrpy==4.2.1 +wrapt==1.17.2 +yarl==1.18.3 diff --git a/.riot/requirements/c74f6e0.txt b/.riot/requirements/c74f6e0.txt deleted file mode 100644 index 63345853661..00000000000 --- a/.riot/requirements/c74f6e0.txt +++ /dev/null @@ -1,51 +0,0 @@ -# -# This file is autogenerated by pip-compile with Python 3.10 -# by the following command: -# -# pip-compile --allow-unsafe --no-annotate .riot/requirements/c74f6e0.in -# -annotated-types==0.7.0 -anyio==4.4.0 -attrs==24.2.0 -certifi==2024.7.4 -coverage[toml]==7.6.1 -distro==1.9.0 -exceptiongroup==1.2.2 -h11==0.14.0 -httpcore==1.0.5 -httpx==0.27.0 -hypothesis==6.45.0 -idna==3.8 -iniconfig==2.0.0 -mock==5.1.0 -multidict==6.0.5 -numpy==2.1.0 -openai[datalib,embeddings]==1.30.1 -opentracing==2.4.0 -packaging==24.1 -pandas==2.2.2 -pandas-stubs==2.2.2.240807 -pillow==9.5.0 -pluggy==1.5.0 -pydantic==2.8.2 -pydantic-core==2.20.1 -pytest==8.3.2 -pytest-asyncio==0.21.1 -pytest-cov==5.0.0 -pytest-mock==3.14.0 -pytest-randomly==3.15.0 -python-dateutil==2.9.0.post0 -pytz==2024.1 -pyyaml==6.0.2 -six==1.16.0 -sniffio==1.3.1 -sortedcontainers==2.4.0 -tomli==2.0.1 -tqdm==4.66.5 -types-pytz==2024.1.0.20240417 -typing-extensions==4.12.2 -tzdata==2024.1 -urllib3==1.26.19 -vcrpy==4.2.1 -wrapt==1.16.0 -yarl==1.9.4 diff --git a/.riot/requirements/cd2e4ea.txt b/.riot/requirements/cd2e4ea.txt deleted file mode 100644 index 24353dafa0c..00000000000 --- a/.riot/requirements/cd2e4ea.txt +++ /dev/null @@ -1,53 +0,0 @@ -# -# This file is autogenerated by pip-compile with Python 3.9 -# by the following command: -# -# pip-compile --allow-unsafe --no-annotate .riot/requirements/cd2e4ea.in -# -annotated-types==0.7.0 -anyio==3.7.1 -attrs==24.2.0 -certifi==2024.7.4 -coverage[toml]==7.6.1 -distro==1.9.0 -exceptiongroup==1.2.2 -h11==0.14.0 -httpcore==1.0.5 -httpx==0.27.0 -hypothesis==6.45.0 -idna==3.8 -importlib-metadata==8.4.0 -iniconfig==2.0.0 -mock==5.1.0 -multidict==6.0.5 -numpy==2.0.1 -openai[datalib,embeddings]==1.1.1 -opentracing==2.4.0 -packaging==24.1 -pandas==2.2.2 -pandas-stubs==2.2.2.240807 -pillow==9.5.0 -pluggy==1.5.0 -pydantic==2.8.2 -pydantic-core==2.20.1 -pytest==8.3.2 -pytest-asyncio==0.21.1 -pytest-cov==5.0.0 -pytest-mock==3.14.0 -pytest-randomly==3.15.0 -python-dateutil==2.9.0.post0 -pytz==2024.1 -pyyaml==6.0.2 -six==1.16.0 -sniffio==1.3.1 -sortedcontainers==2.4.0 -tomli==2.0.1 -tqdm==4.66.5 -types-pytz==2024.1.0.20240417 -typing-extensions==4.12.2 -tzdata==2024.1 -urllib3==1.26.19 -vcrpy==4.2.1 -wrapt==1.16.0 -yarl==1.9.4 -zipp==3.20.1 diff --git a/.riot/requirements/181216c.txt b/.riot/requirements/df60af6.txt similarity index 82% rename from .riot/requirements/181216c.txt rename to .riot/requirements/df60af6.txt index ac739930363..5143f0e0a74 100644 --- a/.riot/requirements/181216c.txt +++ b/.riot/requirements/df60af6.txt @@ -2,13 +2,13 @@ # This file is autogenerated by pip-compile with Python 3.7 # by the following command: # -# pip-compile --allow-unsafe --config=pyproject.toml --no-annotate --resolver=backtracking .riot/requirements/181216c.in +# pip-compile --allow-unsafe --config=pyproject.toml --no-annotate --resolver=backtracking .riot/requirements/df60af6.in # annotated-types==0.5.0 anyio==3.7.1 attrs==24.2.0 cached-property==1.5.2 -certifi==2024.7.4 +certifi==2024.12.14 coverage[toml]==7.2.7 distro==1.9.0 exceptiongroup==1.2.2 @@ -16,13 +16,13 @@ h11==0.14.0 httpcore==0.17.3 httpx==0.24.1 hypothesis==6.45.0 -idna==3.8 +idna==3.10 importlib-metadata==6.7.0 iniconfig==2.0.0 mock==5.1.0 multidict==6.0.5 numpy==1.21.6 -openai[datalib,embeddings]==1.30.1 +openai[datalib]==1.30.1 opentracing==2.4.0 packaging==24.0 pandas==1.3.5 @@ -37,15 +37,15 @@ pytest-cov==4.1.0 pytest-mock==3.11.1 pytest-randomly==3.12.0 python-dateutil==2.9.0.post0 -pytz==2024.1 +pytz==2024.2 pyyaml==6.0.1 -six==1.16.0 +six==1.17.0 sniffio==1.3.1 sortedcontainers==2.4.0 tomli==2.0.1 -tqdm==4.66.5 +tqdm==4.67.1 typing-extensions==4.7.1 -urllib3==1.26.19 +urllib3==1.26.20 vcrpy==4.2.1 wrapt==1.16.0 yarl==1.9.4 diff --git a/.riot/requirements/f1c37b1.txt b/.riot/requirements/f1c37b1.txt deleted file mode 100644 index 4da5078a988..00000000000 --- a/.riot/requirements/f1c37b1.txt +++ /dev/null @@ -1,51 +0,0 @@ -# -# This file is autogenerated by pip-compile with Python 3.10 -# by the following command: -# -# pip-compile --allow-unsafe --no-annotate .riot/requirements/f1c37b1.in -# -annotated-types==0.7.0 -anyio==3.7.1 -attrs==24.2.0 -certifi==2024.7.4 -coverage[toml]==7.6.1 -distro==1.9.0 -exceptiongroup==1.2.2 -h11==0.14.0 -httpcore==1.0.5 -httpx==0.27.0 -hypothesis==6.45.0 -idna==3.8 -iniconfig==2.0.0 -mock==5.1.0 -multidict==6.0.5 -numpy==2.1.0 -openai[datalib,embeddings]==1.1.1 -opentracing==2.4.0 -packaging==24.1 -pandas==2.2.2 -pandas-stubs==2.2.2.240807 -pillow==9.5.0 -pluggy==1.5.0 -pydantic==2.8.2 -pydantic-core==2.20.1 -pytest==8.3.2 -pytest-asyncio==0.21.1 -pytest-cov==5.0.0 -pytest-mock==3.14.0 -pytest-randomly==3.15.0 -python-dateutil==2.9.0.post0 -pytz==2024.1 -pyyaml==6.0.2 -six==1.16.0 -sniffio==1.3.1 -sortedcontainers==2.4.0 -tomli==2.0.1 -tqdm==4.66.5 -types-pytz==2024.1.0.20240417 -typing-extensions==4.12.2 -tzdata==2024.1 -urllib3==1.26.19 -vcrpy==4.2.1 -wrapt==1.16.0 -yarl==1.9.4 diff --git a/.riot/requirements/f7c30a0.txt b/.riot/requirements/f7c30a0.txt deleted file mode 100644 index 3e4716aede1..00000000000 --- a/.riot/requirements/f7c30a0.txt +++ /dev/null @@ -1,51 +0,0 @@ -# -# This file is autogenerated by pip-compile with Python 3.7 -# by the following command: -# -# pip-compile --allow-unsafe --config=pyproject.toml --no-annotate --resolver=backtracking .riot/requirements/f7c30a0.in -# -annotated-types==0.5.0 -anyio==3.7.1 -attrs==24.2.0 -certifi==2024.7.4 -coverage[toml]==7.2.7 -distro==1.9.0 -exceptiongroup==1.2.2 -h11==0.14.0 -httpcore==0.17.3 -httpx==0.24.1 -hypothesis==6.45.0 -idna==3.8 -importlib-metadata==6.7.0 -iniconfig==2.0.0 -mock==5.1.0 -multidict==6.0.5 -numpy==1.21.6 -openai[datalib,embeddings]==1.1.1 -opentracing==2.4.0 -packaging==24.0 -pandas==1.3.5 -pandas-stubs==1.2.0.62 -pillow==9.5.0 -pluggy==1.2.0 -pydantic==2.5.3 -pydantic-core==2.14.6 -pytest==7.4.4 -pytest-asyncio==0.21.1 -pytest-cov==4.1.0 -pytest-mock==3.11.1 -pytest-randomly==3.12.0 -python-dateutil==2.9.0.post0 -pytz==2024.1 -pyyaml==6.0.1 -six==1.16.0 -sniffio==1.3.1 -sortedcontainers==2.4.0 -tomli==2.0.1 -tqdm==4.66.5 -typing-extensions==4.7.1 -urllib3==1.26.19 -vcrpy==4.2.1 -wrapt==1.16.0 -yarl==1.9.4 -zipp==3.15.0 diff --git a/ddtrace/_trace/context.py b/ddtrace/_trace/context.py index 07bc3960b56..c69496c865e 100644 --- a/ddtrace/_trace/context.py +++ b/ddtrace/_trace/context.py @@ -12,9 +12,9 @@ from ddtrace._trace._span_link import SpanLink from ddtrace._trace.types import _MetaDictType from ddtrace._trace.types import _MetricDictType -from ddtrace.constants import ORIGIN_KEY -from ddtrace.constants import SAMPLING_PRIORITY_KEY -from ddtrace.constants import USER_ID_KEY +from ddtrace.constants import _ORIGIN_KEY +from ddtrace.constants import _SAMPLING_PRIORITY_KEY +from ddtrace.constants import _USER_ID_KEY from ddtrace.internal.compat import NumericType from ddtrace.internal.constants import MAX_UINT_64BITS as _MAX_UINT_64BITS from ddtrace.internal.constants import W3C_TRACEPARENT_KEY @@ -72,9 +72,9 @@ def __init__( self._is_remote: bool = is_remote if dd_origin is not None and _DD_ORIGIN_INVALID_CHARS_REGEX.search(dd_origin) is None: - self._meta[ORIGIN_KEY] = dd_origin + self._meta[_ORIGIN_KEY] = dd_origin if sampling_priority is not None: - self._metrics[SAMPLING_PRIORITY_KEY] = sampling_priority + self._metrics[_SAMPLING_PRIORITY_KEY] = sampling_priority if span_links is not None: self._span_links = span_links else: @@ -127,16 +127,16 @@ def _update_tags(self, span: "Span") -> None: @property def sampling_priority(self) -> Optional[NumericType]: """Return the context sampling priority for the trace.""" - return self._metrics.get(SAMPLING_PRIORITY_KEY) + return self._metrics.get(_SAMPLING_PRIORITY_KEY) @sampling_priority.setter def sampling_priority(self, value: Optional[NumericType]) -> None: with self._lock: if value is None: - if SAMPLING_PRIORITY_KEY in self._metrics: - del self._metrics[SAMPLING_PRIORITY_KEY] + if _SAMPLING_PRIORITY_KEY in self._metrics: + del self._metrics[_SAMPLING_PRIORITY_KEY] return - self._metrics[SAMPLING_PRIORITY_KEY] = value + self._metrics[_SAMPLING_PRIORITY_KEY] = value @property def _traceparent(self) -> str: @@ -180,22 +180,22 @@ def _tracestate(self) -> str: @property def dd_origin(self) -> Optional[Text]: """Get the origin of the trace.""" - return self._meta.get(ORIGIN_KEY) + return self._meta.get(_ORIGIN_KEY) @dd_origin.setter def dd_origin(self, value: Optional[Text]) -> None: """Set the origin of the trace.""" with self._lock: if value is None: - if ORIGIN_KEY in self._meta: - del self._meta[ORIGIN_KEY] + if _ORIGIN_KEY in self._meta: + del self._meta[_ORIGIN_KEY] return - self._meta[ORIGIN_KEY] = value + self._meta[_ORIGIN_KEY] = value @property def dd_user_id(self) -> Optional[Text]: """Get the user ID of the trace.""" - user_id = self._meta.get(USER_ID_KEY) + user_id = self._meta.get(_USER_ID_KEY) if user_id: return str(base64.b64decode(user_id), encoding="utf-8") return None @@ -205,10 +205,10 @@ def dd_user_id(self, value: Optional[Text]) -> None: """Set the user ID of the trace.""" with self._lock: if value is None: - if USER_ID_KEY in self._meta: - del self._meta[USER_ID_KEY] + if _USER_ID_KEY in self._meta: + del self._meta[_USER_ID_KEY] return - self._meta[USER_ID_KEY] = str(base64.b64encode(bytes(value, encoding="utf-8")), encoding="utf-8") + self._meta[_USER_ID_KEY] = str(base64.b64encode(bytes(value, encoding="utf-8")), encoding="utf-8") @property def _trace_id_64bits(self): diff --git a/ddtrace/_trace/processor/__init__.py b/ddtrace/_trace/processor/__init__.py index fc59a64828b..0437b65b364 100644 --- a/ddtrace/_trace/processor/__init__.py +++ b/ddtrace/_trace/processor/__init__.py @@ -14,7 +14,7 @@ from ddtrace._trace.span import _get_64_highest_order_bits_as_hex from ddtrace._trace.span import _is_top_level from ddtrace.constants import _APM_ENABLED_METRIC_KEY as MK_APM_ENABLED -from ddtrace.constants import SAMPLING_PRIORITY_KEY +from ddtrace.constants import _SAMPLING_PRIORITY_KEY from ddtrace.constants import USER_KEEP from ddtrace.internal import gitmetadata from ddtrace.internal import telemetry @@ -165,7 +165,7 @@ def process_trace(self, trace: List[Span]) -> Optional[List[Span]]: # In order to ensure that the agent does not update priority sampling rates # due to single spans sampling, we set all of these spans to manual keep. if config._trace_compute_stats: - span.set_metric(SAMPLING_PRIORITY_KEY, USER_KEEP) + span.set_metric(_SAMPLING_PRIORITY_KEY, USER_KEEP) break return trace diff --git a/ddtrace/_trace/sampler.py b/ddtrace/_trace/sampler.py index 6e2515ee152..961526e3f26 100644 --- a/ddtrace/_trace/sampler.py +++ b/ddtrace/_trace/sampler.py @@ -12,7 +12,7 @@ from typing import Tuple # noqa:F401 from ddtrace import config -from ddtrace.constants import SAMPLING_LIMIT_DECISION +from ddtrace.constants import _SAMPLING_LIMIT_DECISION from ..constants import ENV_KEY from ..internal.constants import _PRIORITY_CATEGORY @@ -342,7 +342,7 @@ def sample(self, span): # uses DatadogSampler._rate_limit_always_on to override this functionality. if sampled: sampled = self.limiter.is_allowed() - span.set_metric(SAMPLING_LIMIT_DECISION, self.limiter.effective_rate) + span.set_metric(_SAMPLING_LIMIT_DECISION, self.limiter.effective_rate) _set_sampling_tags( span, sampled, diff --git a/ddtrace/_trace/span.py b/ddtrace/_trace/span.py index afb3496db80..446239a8091 100644 --- a/ddtrace/_trace/span.py +++ b/ddtrace/_trace/span.py @@ -24,17 +24,17 @@ from ddtrace._trace.types import _MetricDictType from ddtrace._trace.types import _TagNameType from ddtrace.constants import _ANALYTICS_SAMPLE_RATE_KEY +from ddtrace.constants import _SAMPLING_AGENT_DECISION +from ddtrace.constants import _SAMPLING_LIMIT_DECISION +from ddtrace.constants import _SAMPLING_RULE_DECISION +from ddtrace.constants import _SPAN_MEASURED_KEY from ddtrace.constants import ERROR_MSG from ddtrace.constants import ERROR_STACK from ddtrace.constants import ERROR_TYPE from ddtrace.constants import MANUAL_DROP_KEY from ddtrace.constants import MANUAL_KEEP_KEY -from ddtrace.constants import SAMPLING_AGENT_DECISION -from ddtrace.constants import SAMPLING_LIMIT_DECISION -from ddtrace.constants import SAMPLING_RULE_DECISION from ddtrace.constants import SERVICE_KEY from ddtrace.constants import SERVICE_VERSION_KEY -from ddtrace.constants import SPAN_MEASURED_KEY from ddtrace.constants import USER_KEEP from ddtrace.constants import USER_REJECT from ddtrace.constants import VERSION_KEY @@ -327,7 +327,7 @@ def _override_sampling_decision(self, decision: Optional[NumericType]): self.context.sampling_priority = decision set_sampling_decision_maker(self.context, SamplingMechanism.MANUAL) if self._local_root: - for key in (SAMPLING_RULE_DECISION, SAMPLING_AGENT_DECISION, SAMPLING_LIMIT_DECISION): + for key in (_SAMPLING_RULE_DECISION, _SAMPLING_AGENT_DECISION, _SAMPLING_LIMIT_DECISION): if key in self._local_root._metrics: del self._local_root._metrics[key] @@ -401,7 +401,7 @@ def set_tag(self, key: _TagNameType, value: Any = None) -> None: # Also set the `version` tag to the same value # DEV: Note that we do no return, we want to set both self.set_tag(VERSION_KEY, value) - elif key == SPAN_MEASURED_KEY: + elif key == _SPAN_MEASURED_KEY: # Set `_dd.measured` tag as a metric # DEV: `set_metric` will ensure it is an integer 0 or 1 if value is None: @@ -458,7 +458,7 @@ def set_tags(self, tags: Dict[_TagNameType, Any]) -> None: def set_metric(self, key: _TagNameType, value: NumericType) -> None: """This method sets a numeric tag value for the given key.""" # Enforce a specific constant for `_dd.measured` - if key == SPAN_MEASURED_KEY: + if key == _SPAN_MEASURED_KEY: try: value = int(bool(value)) except (ValueError, TypeError): diff --git a/ddtrace/_trace/trace_handlers.py b/ddtrace/_trace/trace_handlers.py index 96c33da8c6b..dab3f743146 100644 --- a/ddtrace/_trace/trace_handlers.py +++ b/ddtrace/_trace/trace_handlers.py @@ -18,8 +18,8 @@ ) from ddtrace._trace.utils_botocore.span_tags import set_botocore_response_metadata_tags from ddtrace.constants import _ANALYTICS_SAMPLE_RATE_KEY +from ddtrace.constants import _SPAN_MEASURED_KEY from ddtrace.constants import SPAN_KIND -from ddtrace.constants import SPAN_MEASURED_KEY from ddtrace.contrib import trace_utils from ddtrace.contrib.internal.botocore.constants import BOTOCORE_STEPFUNCTIONS_INPUT_KEY from ddtrace.contrib.internal.trace_utils import _set_url_tag @@ -334,7 +334,7 @@ def _on_request_span_modifier( # RequestContext` and possibly a url rule span.resource = " ".join((request.method, request.path)) - span.set_tag(SPAN_MEASURED_KEY) + span.set_tag(_SPAN_MEASURED_KEY) # set analytics sample rate with global config enabled sample_rate = flask_config.get_analytics_sample_rate(use_global_config=True) if sample_rate is not None: @@ -366,7 +366,7 @@ def _on_request_span_modifier_post(ctx, flask_config, request, req_body): def _on_traced_get_response_pre(_, ctx: core.ExecutionContext, request, before_request_tags): before_request_tags(ctx["pin"], ctx.span, request) - ctx.span._metrics[SPAN_MEASURED_KEY] = 1 + ctx.span._metrics[_SPAN_MEASURED_KEY] = 1 def _on_django_finalize_response_pre(ctx, after_request_tags, request, response): diff --git a/ddtrace/_trace/tracer.py b/ddtrace/_trace/tracer.py index 84b9252930a..6e595bbe7c1 100644 --- a/ddtrace/_trace/tracer.py +++ b/ddtrace/_trace/tracer.py @@ -30,8 +30,8 @@ from ddtrace._trace.sampler import DatadogSampler from ddtrace._trace.span import Span from ddtrace.appsec._constants import APPSEC +from ddtrace.constants import _HOSTNAME_KEY from ddtrace.constants import ENV_KEY -from ddtrace.constants import HOSTNAME_KEY from ddtrace.constants import PID from ddtrace.constants import VERSION_KEY from ddtrace.internal import agent @@ -966,7 +966,7 @@ def _start_span( on_finish=[self._on_span_finish], ) if config._report_hostname: - span.set_tag_str(HOSTNAME_KEY, hostname.get_hostname()) + span.set_tag_str(_HOSTNAME_KEY, hostname.get_hostname()) if not span._parent: span.set_tag_str("runtime-id", get_runtime_id()) diff --git a/ddtrace/_trace/utils_botocore/span_tags.py b/ddtrace/_trace/utils_botocore/span_tags.py index 5394c2b397a..f90cbd60a51 100644 --- a/ddtrace/_trace/utils_botocore/span_tags.py +++ b/ddtrace/_trace/utils_botocore/span_tags.py @@ -7,8 +7,8 @@ from ddtrace import config from ddtrace._trace.utils_botocore.aws_payload_tagging import AWSPayloadTagging from ddtrace.constants import _ANALYTICS_SAMPLE_RATE_KEY +from ddtrace.constants import _SPAN_MEASURED_KEY from ddtrace.constants import SPAN_KIND -from ddtrace.constants import SPAN_MEASURED_KEY from ddtrace.ext import SpanKind from ddtrace.ext import aws from ddtrace.ext import http @@ -23,7 +23,7 @@ def set_botocore_patched_api_call_span_tags(span: Span, instance, args, params, span.set_tag_str(COMPONENT, config.botocore.integration_name) # set span.kind to the type of request being performed span.set_tag_str(SPAN_KIND, SpanKind.CLIENT) - span.set_tag(SPAN_MEASURED_KEY) + span.set_tag(_SPAN_MEASURED_KEY) if args: # DEV: join is the fastest way of concatenating strings that is compatible diff --git a/ddtrace/_trace/utils_redis.py b/ddtrace/_trace/utils_redis.py index 433d8578fbb..fde9c291cb5 100644 --- a/ddtrace/_trace/utils_redis.py +++ b/ddtrace/_trace/utils_redis.py @@ -7,8 +7,8 @@ from typing import Optional from ddtrace.constants import _ANALYTICS_SAMPLE_RATE_KEY +from ddtrace.constants import _SPAN_MEASURED_KEY from ddtrace.constants import SPAN_KIND -from ddtrace.constants import SPAN_MEASURED_KEY from ddtrace.contrib import trace_utils from ddtrace.contrib.internal.redis_utils import _extract_conn_tags from ddtrace.ext import SpanKind @@ -30,7 +30,7 @@ def _set_span_tags( span.set_tag_str(SPAN_KIND, SpanKind.CLIENT) span.set_tag_str(COMPONENT, config_integration.integration_name) span.set_tag_str(db.SYSTEM, redisx.APP) - span.set_tag(SPAN_MEASURED_KEY) + span.set_tag(_SPAN_MEASURED_KEY) if query is not None: span_name = schematize_cache_operation(redisx.RAWCMD, cache_provider=redisx.APP) # type: ignore[operator] span.set_tag_str(span_name, query) diff --git a/ddtrace/appsec/_iast/_iast_request_context.py b/ddtrace/appsec/_iast/_iast_request_context.py index 3a9acd2ce4e..e9c985d0b3d 100644 --- a/ddtrace/appsec/_iast/_iast_request_context.py +++ b/ddtrace/appsec/_iast/_iast_request_context.py @@ -14,7 +14,7 @@ from ddtrace.appsec._iast._taint_tracking._context import create_context as create_propagation_context from ddtrace.appsec._iast._taint_tracking._context import reset_context as reset_propagation_context from ddtrace.appsec._iast.reporter import IastSpanReporter -from ddtrace.constants import ORIGIN_KEY +from ddtrace.constants import _ORIGIN_KEY from ddtrace.internal import core from ddtrace.internal.logger import get_logger from ddtrace.internal.utils.formats import asbool @@ -147,8 +147,8 @@ def _create_and_attach_iast_report_to_span(req_span: Span, existing_data: Option set_iast_request_enabled(False) end_iast_context(req_span) - if req_span.get_tag(ORIGIN_KEY) is None: - req_span.set_tag_str(ORIGIN_KEY, APPSEC.ORIGIN_VALUE) + if req_span.get_tag(_ORIGIN_KEY) is None: + req_span.set_tag_str(_ORIGIN_KEY, APPSEC.ORIGIN_VALUE) oce.release_request() diff --git a/ddtrace/appsec/_processor.py b/ddtrace/appsec/_processor.py index 33f3ac8ced1..6102ba1ded2 100644 --- a/ddtrace/appsec/_processor.py +++ b/ddtrace/appsec/_processor.py @@ -27,8 +27,8 @@ from ddtrace.appsec._exploit_prevention.stack_traces import report_stack from ddtrace.appsec._trace_utils import _asm_manual_keep from ddtrace.appsec._utils import has_triggers -from ddtrace.constants import ORIGIN_KEY -from ddtrace.constants import RUNTIME_FAMILY +from ddtrace.constants import _ORIGIN_KEY +from ddtrace.constants import _RUNTIME_FAMILY from ddtrace.ext import SpanTypes from ddtrace.internal import core from ddtrace.internal._unpatched import unpatched_open as open # noqa: A001 @@ -235,7 +235,7 @@ def on_span_start(self, span: Span) -> None: headers_case_sensitive = _asm_request_context.get_headers_case_sensitive() span.set_metric(APPSEC.ENABLED, 1.0) - span.set_tag_str(RUNTIME_FAMILY, "python") + span.set_tag_str(_RUNTIME_FAMILY, "python") def waf_callable(custom_data=None, **kwargs): return self._waf_action(span._local_root or span, ctx, custom_data, **kwargs) @@ -391,8 +391,8 @@ def _waf_action( # Right now, we overwrite any value that could be already there. We need to reconsider when ASM/AppSec's # specs are updated. _asm_manual_keep(span) - if span.get_tag(ORIGIN_KEY) is None: - span.set_tag_str(ORIGIN_KEY, APPSEC.ORIGIN_VALUE) + if span.get_tag(_ORIGIN_KEY) is None: + span.set_tag_str(_ORIGIN_KEY, APPSEC.ORIGIN_VALUE) return waf_results def _is_needed(self, address: str) -> bool: diff --git a/ddtrace/constants.py b/ddtrace/constants.py index 1a112f677b8..b4694e24345 100644 --- a/ddtrace/constants.py +++ b/ddtrace/constants.py @@ -4,36 +4,36 @@ # TODO: Deprecate and remove the SAMPLE_RATE_METRIC_KEY constant. # This key enables legacy trace sampling support in the Datadog agent. -SAMPLE_RATE_METRIC_KEY = "_sample_rate" -SAMPLING_PRIORITY_KEY = "_sampling_priority_v1" +_SAMPLE_RATE_METRIC_KEY = SAMPLE_RATE_METRIC_KEY = "_sample_rate" +_SAMPLING_PRIORITY_KEY = SAMPLING_PRIORITY_KEY = "_sampling_priority_v1" _ANALYTICS_SAMPLE_RATE_KEY = ANALYTICS_SAMPLE_RATE_KEY = "_dd1.sr.eausr" -SAMPLING_AGENT_DECISION = "_dd.agent_psr" -SAMPLING_RULE_DECISION = "_dd.rule_psr" -SAMPLING_LIMIT_DECISION = "_dd.limit_psr" +_SAMPLING_AGENT_DECISION = SAMPLING_AGENT_DECISION = "_dd.agent_psr" +_SAMPLING_RULE_DECISION = SAMPLING_RULE_DECISION = "_dd.rule_psr" +_SAMPLING_LIMIT_DECISION = SAMPLING_LIMIT_DECISION = "_dd.limit_psr" _SINGLE_SPAN_SAMPLING_MECHANISM = "_dd.span_sampling.mechanism" _SINGLE_SPAN_SAMPLING_RATE = "_dd.span_sampling.rule_rate" _SINGLE_SPAN_SAMPLING_MAX_PER_SEC = "_dd.span_sampling.max_per_second" _SINGLE_SPAN_SAMPLING_MAX_PER_SEC_NO_LIMIT = -1 _APM_ENABLED_METRIC_KEY = "_dd.apm.enabled" -ORIGIN_KEY = "_dd.origin" -USER_ID_KEY = "_dd.p.usr.id" -HOSTNAME_KEY = "_dd.hostname" -RUNTIME_FAMILY = "_dd.runtime_family" +_ORIGIN_KEY = ORIGIN_KEY = "_dd.origin" +_USER_ID_KEY = USER_ID_KEY = "_dd.p.usr.id" +_HOSTNAME_KEY = HOSTNAME_KEY = "_dd.hostname" +_RUNTIME_FAMILY = RUNTIME_FAMILY = "_dd.runtime_family" ENV_KEY = "env" VERSION_KEY = "version" SERVICE_KEY = "service.name" -BASE_SERVICE_KEY = "_dd.base_service" +_BASE_SERVICE_KEY = BASE_SERVICE_KEY = "_dd.base_service" SERVICE_VERSION_KEY = "service.version" SPAN_KIND = "span.kind" -SPAN_MEASURED_KEY = "_dd.measured" -KEEP_SPANS_RATE_KEY = "_dd.tracer_kr" -MULTIPLE_IP_HEADERS = "_dd.multiple-ip-headers" +_SPAN_MEASURED_KEY = SPAN_MEASURED_KEY = "_dd.measured" +_KEEP_SPANS_RATE_KEY = KEEP_SPANS_RATE_KEY = "_dd.tracer_kr" +_MULTIPLE_IP_HEADERS = MULTIPLE_IP_HEADERS = "_dd.multiple-ip-headers" APPSEC_ENV = "DD_APPSEC_ENABLED" -CONFIG_ENDPOINT_ENV = "_DD_CONFIG_ENDPOINT" -CONFIG_ENDPOINT_RETRIES_ENV = "_DD_CONFIG_ENDPOINT_RETRIES" -CONFIG_ENDPOINT_TIMEOUT_ENV = "_DD_CONFIG_ENDPOINT_TIMEOUT" +_CONFIG_ENDPOINT_ENV = CONFIG_ENDPOINT_ENV = "_DD_CONFIG_ENDPOINT" +_CONFIG_ENDPOINT_RETRIES_ENV = CONFIG_ENDPOINT_RETRIES_ENV = "_DD_CONFIG_ENDPOINT_RETRIES" +_CONFIG_ENDPOINT_TIMEOUT_ENV = CONFIG_ENDPOINT_TIMEOUT_ENV = "_DD_CONFIG_ENDPOINT_TIMEOUT" IAST_ENV = "DD_IAST_ENABLED" MANUAL_DROP_KEY = "manual.drop" @@ -57,6 +57,22 @@ _DEPRECATED_MODULE_ATTRIBUTES = [ "ANALYTICS_SAMPLE_RATE_KEY", + "SAMPLE_RATE_METRIC_KEY", + "SAMPLING_PRIORITY_KEY", + "SAMPLING_AGENT_DECISION", + "SAMPLING_RULE_DECISION", + "SAMPLING_LIMIT_DECISION", + "USER_ID_KEY", + "ORIGIN_KEY", + "HOSTNAME_KEY", + "RUNTIME_FAMILY", + "BASE_SERVICE_KEY", + "SPAN_MEASURED_KEY", + "KEEP_SPANS_RATE_KEY", + "MULTIPLE_IP_HEADERS", + "CONFIG_ENDPOINT_ENV", + "CONFIG_ENDPOINT_RETRIES_ENV", + "CONFIG_ENDPOINT_TIMEOUT_ENV", ] diff --git a/ddtrace/contrib/dbapi/__init__.py b/ddtrace/contrib/dbapi/__init__.py index e511fc31657..fa733c19a63 100644 --- a/ddtrace/contrib/dbapi/__init__.py +++ b/ddtrace/contrib/dbapi/__init__.py @@ -14,8 +14,8 @@ from ...appsec._constants import IAST_SPAN_TAGS from ...appsec._iast._metrics import increment_iast_span_metric from ...constants import _ANALYTICS_SAMPLE_RATE_KEY +from ...constants import _SPAN_MEASURED_KEY from ...constants import SPAN_KIND -from ...constants import SPAN_MEASURED_KEY from ...ext import SpanKind from ...ext import SpanTypes from ...ext import db @@ -92,7 +92,7 @@ def _trace_method(self, method, name, resource, extra_tags, dbm_propagator, *arg name, service=ext_service(pin, self._self_config), resource=resource, span_type=SpanTypes.SQL ) as s: if measured: - s.set_tag(SPAN_MEASURED_KEY) + s.set_tag(_SPAN_MEASURED_KEY) # No reason to tag the query since it is set as the resource by the agent. See: # https://github.com/DataDog/datadog-trace-agent/blob/bda1ebbf170dd8c5879be993bdd4dbae70d10fda/obfuscate/sql.go#L232 s.set_tags(pin.tags) diff --git a/ddtrace/contrib/dbapi_async/__init__.py b/ddtrace/contrib/dbapi_async/__init__.py index 9ebf36847b0..a6ae676f4bd 100644 --- a/ddtrace/contrib/dbapi_async/__init__.py +++ b/ddtrace/contrib/dbapi_async/__init__.py @@ -9,8 +9,8 @@ from ...appsec._constants import IAST_SPAN_TAGS from ...appsec._iast._metrics import increment_iast_span_metric from ...constants import _ANALYTICS_SAMPLE_RATE_KEY +from ...constants import _SPAN_MEASURED_KEY from ...constants import SPAN_KIND -from ...constants import SPAN_MEASURED_KEY from ...ext import SpanKind from ...ext import SpanTypes from ...trace import Pin @@ -67,7 +67,7 @@ async def _trace_method(self, method, name, resource, extra_tags, dbm_propagator name, service=ext_service(pin, self._self_config), resource=resource, span_type=SpanTypes.SQL ) as s: if measured: - s.set_tag(SPAN_MEASURED_KEY) + s.set_tag(_SPAN_MEASURED_KEY) # No reason to tag the query since it is set as the resource by the agent. See: # https://github.com/DataDog/datadog-trace-agent/blob/bda1ebbf170dd8c5879be993bdd4dbae70d10fda/obfuscate/sql.go#L232 s.set_tags(pin.tags) diff --git a/ddtrace/contrib/internal/aiobotocore/patch.py b/ddtrace/contrib/internal/aiobotocore/patch.py index 0df89927ece..4b0fea48b96 100644 --- a/ddtrace/contrib/internal/aiobotocore/patch.py +++ b/ddtrace/contrib/internal/aiobotocore/patch.py @@ -5,8 +5,8 @@ from ddtrace import config from ddtrace.constants import _ANALYTICS_SAMPLE_RATE_KEY +from ddtrace.constants import _SPAN_MEASURED_KEY from ddtrace.constants import SPAN_KIND -from ddtrace.constants import SPAN_MEASURED_KEY from ddtrace.contrib.internal.trace_utils import ext_service from ddtrace.contrib.internal.trace_utils import unwrap from ddtrace.ext import SpanKind @@ -125,7 +125,7 @@ async def _wrapped_api_call(original_func, instance, args, kwargs): # set span.kind tag equal to type of request span.set_tag_str(SPAN_KIND, SpanKind.CLIENT) - span.set_tag(SPAN_MEASURED_KEY) + span.set_tag(_SPAN_MEASURED_KEY) try: operation = get_argument_value(args, kwargs, 0, "operation_name") diff --git a/ddtrace/contrib/internal/aiohttp/middlewares.py b/ddtrace/contrib/internal/aiohttp/middlewares.py index 59045d7bcc9..4f7abe5a12f 100644 --- a/ddtrace/contrib/internal/aiohttp/middlewares.py +++ b/ddtrace/contrib/internal/aiohttp/middlewares.py @@ -3,8 +3,8 @@ from ddtrace import config from ddtrace.constants import _ANALYTICS_SAMPLE_RATE_KEY +from ddtrace.constants import _SPAN_MEASURED_KEY from ddtrace.constants import SPAN_KIND -from ddtrace.constants import SPAN_MEASURED_KEY from ddtrace.contrib import trace_utils from ddtrace.contrib.asyncio import context_provider from ddtrace.ext import SpanKind @@ -50,7 +50,7 @@ async def attach_context(request): service=service, span_type=SpanTypes.WEB, ) - request_span.set_tag(SPAN_MEASURED_KEY) + request_span.set_tag(_SPAN_MEASURED_KEY) request_span.set_tag_str(COMPONENT, config.aiohttp.integration_name) diff --git a/ddtrace/contrib/internal/aiomysql/patch.py b/ddtrace/contrib/internal/aiomysql/patch.py index 193d471d124..8f33a4d6343 100644 --- a/ddtrace/contrib/internal/aiomysql/patch.py +++ b/ddtrace/contrib/internal/aiomysql/patch.py @@ -3,8 +3,8 @@ from ddtrace import config from ddtrace.constants import _ANALYTICS_SAMPLE_RATE_KEY +from ddtrace.constants import _SPAN_MEASURED_KEY from ddtrace.constants import SPAN_KIND -from ddtrace.constants import SPAN_MEASURED_KEY from ddtrace.contrib import dbapi from ddtrace.contrib import trace_utils from ddtrace.contrib.internal.trace_utils import _convert_to_string @@ -82,7 +82,7 @@ async def _trace_method(self, method, resource, extra_tags, *args, **kwargs): # set span.kind to the type of request being performed s.set_tag_str(SPAN_KIND, SpanKind.CLIENT) - s.set_tag(SPAN_MEASURED_KEY) + s.set_tag(_SPAN_MEASURED_KEY) s.set_tags(pin.tags) s.set_tags(extra_tags) diff --git a/ddtrace/contrib/internal/aiopg/connection.py b/ddtrace/contrib/internal/aiopg/connection.py index 1daf84b2987..b63a6352a27 100644 --- a/ddtrace/contrib/internal/aiopg/connection.py +++ b/ddtrace/contrib/internal/aiopg/connection.py @@ -4,8 +4,8 @@ from ddtrace import config from ddtrace.constants import _ANALYTICS_SAMPLE_RATE_KEY +from ddtrace.constants import _SPAN_MEASURED_KEY from ddtrace.constants import SPAN_KIND -from ddtrace.constants import SPAN_MEASURED_KEY from ddtrace.contrib import dbapi from ddtrace.contrib import trace_utils from ddtrace.ext import SpanKind @@ -47,7 +47,7 @@ async def _trace_method(self, method, resource, extra_tags, *args, **kwargs): # set span.kind to the type of request being performed s.set_tag_str(SPAN_KIND, SpanKind.CLIENT) - s.set_tag(SPAN_MEASURED_KEY) + s.set_tag(_SPAN_MEASURED_KEY) s.set_tags(pin.tags) s.set_tags(extra_tags) diff --git a/ddtrace/contrib/internal/aioredis/patch.py b/ddtrace/contrib/internal/aioredis/patch.py index 3e1f0c062a3..62b8ec9f80c 100644 --- a/ddtrace/contrib/internal/aioredis/patch.py +++ b/ddtrace/contrib/internal/aioredis/patch.py @@ -9,8 +9,8 @@ from ddtrace._trace.utils_redis import _instrument_redis_cmd from ddtrace._trace.utils_redis import _instrument_redis_execute_pipeline from ddtrace.constants import _ANALYTICS_SAMPLE_RATE_KEY +from ddtrace.constants import _SPAN_MEASURED_KEY from ddtrace.constants import SPAN_KIND -from ddtrace.constants import SPAN_MEASURED_KEY from ddtrace.contrib import trace_utils from ddtrace.contrib.internal.redis_utils import _run_redis_command_async from ddtrace.contrib.redis_utils import ROW_RETURNING_COMMANDS @@ -149,7 +149,7 @@ def traced_13_execute_command(func, instance, args, kwargs): span.set_tag_str(COMPONENT, config.aioredis.integration_name) span.set_tag_str(db.SYSTEM, redisx.APP) - span.set_tag(SPAN_MEASURED_KEY) + span.set_tag(_SPAN_MEASURED_KEY) span.set_tag_str(redisx.RAWCMD, query) if pin.tags: span.set_tags(pin.tags) @@ -225,7 +225,7 @@ async def traced_13_execute_pipeline(func, instance, args, kwargs): } ) - span.set_tag(SPAN_MEASURED_KEY) + span.set_tag(_SPAN_MEASURED_KEY) span.set_tag_str(redisx.RAWCMD, cmds_string) span.set_metric(redisx.PIPELINE_LEN, len(instance._pipeline)) # set analytics sample rate if enabled diff --git a/ddtrace/contrib/internal/algoliasearch/patch.py b/ddtrace/contrib/internal/algoliasearch/patch.py index e3074225570..bc1ba23a279 100644 --- a/ddtrace/contrib/internal/algoliasearch/patch.py +++ b/ddtrace/contrib/internal/algoliasearch/patch.py @@ -1,8 +1,8 @@ from wrapt import wrap_function_wrapper as _w from ddtrace import config +from ddtrace.constants import _SPAN_MEASURED_KEY from ddtrace.constants import SPAN_KIND -from ddtrace.constants import SPAN_MEASURED_KEY from ddtrace.contrib import trace_utils from ddtrace.ext import SpanKind from ddtrace.ext import SpanTypes @@ -129,7 +129,7 @@ def _patched_search(func, instance, wrapt_args, wrapt_kwargs): # set span.kind to the type of request being performed span.set_tag_str(SPAN_KIND, SpanKind.CLIENT) - span.set_tag(SPAN_MEASURED_KEY) + span.set_tag(_SPAN_MEASURED_KEY) if span.context.sampling_priority is not None and span.context.sampling_priority <= 0: return func(*wrapt_args, **wrapt_kwargs) diff --git a/ddtrace/contrib/internal/asyncpg/patch.py b/ddtrace/contrib/internal/asyncpg/patch.py index 538af434e0b..4eeae4d193e 100644 --- a/ddtrace/contrib/internal/asyncpg/patch.py +++ b/ddtrace/contrib/internal/asyncpg/patch.py @@ -9,7 +9,7 @@ import wrapt from ddtrace.constants import SPAN_KIND -from ddtrace.constants import SPAN_MEASURED_KEY +from ddtrace.constants import _SPAN_MEASURED_KEY from ddtrace.ext import SpanKind from ddtrace.ext import SpanTypes from ddtrace.ext import db @@ -117,7 +117,7 @@ async def _traced_query(pin, method, query, args, kwargs): # set span.kind to the type of request being performed span.set_tag_str(SPAN_KIND, SpanKind.CLIENT) - span.set_tag(SPAN_MEASURED_KEY) + span.set_tag(_SPAN_MEASURED_KEY) span.set_tags(pin.tags) # dispatch DBM diff --git a/ddtrace/contrib/internal/boto/patch.py b/ddtrace/contrib/internal/boto/patch.py index e7418aba878..87094751f9b 100644 --- a/ddtrace/contrib/internal/boto/patch.py +++ b/ddtrace/contrib/internal/boto/patch.py @@ -7,8 +7,8 @@ from ddtrace import config from ddtrace.constants import _ANALYTICS_SAMPLE_RATE_KEY +from ddtrace.constants import _SPAN_MEASURED_KEY from ddtrace.constants import SPAN_KIND -from ddtrace.constants import SPAN_MEASURED_KEY from ddtrace.ext import SpanKind from ddtrace.ext import SpanTypes from ddtrace.ext import aws @@ -93,7 +93,7 @@ def patched_query_request(original_func, instance, args, kwargs): # set span.kind to the type of request being performed span.set_tag_str(SPAN_KIND, SpanKind.CLIENT) - span.set_tag(SPAN_MEASURED_KEY) + span.set_tag(_SPAN_MEASURED_KEY) operation_name = None if args: @@ -164,7 +164,7 @@ def patched_auth_request(original_func, instance, args, kwargs): service=schematize_service_name("{}.{}".format(pin.service, endpoint_name)), span_type=SpanTypes.HTTP, ) as span: - span.set_tag(SPAN_MEASURED_KEY) + span.set_tag(_SPAN_MEASURED_KEY) if args: http_method = get_argument_value(args, kwargs, 0, "method") span.resource = "%s.%s" % (endpoint_name, http_method.lower()) diff --git a/ddtrace/contrib/internal/bottle/trace.py b/ddtrace/contrib/internal/bottle/trace.py index 2f86b1e780a..3aabb4ccc81 100644 --- a/ddtrace/contrib/internal/bottle/trace.py +++ b/ddtrace/contrib/internal/bottle/trace.py @@ -6,8 +6,8 @@ import ddtrace from ddtrace import config from ddtrace.constants import _ANALYTICS_SAMPLE_RATE_KEY +from ddtrace.constants import _SPAN_MEASURED_KEY from ddtrace.constants import SPAN_KIND -from ddtrace.constants import SPAN_MEASURED_KEY from ddtrace.contrib import trace_utils from ddtrace.ext import SpanKind from ddtrace.ext import SpanTypes @@ -57,7 +57,7 @@ def wrapped(*args, **kwargs): # set span.kind to the type of request being performed s.set_tag_str(SPAN_KIND, SpanKind.SERVER) - s.set_tag(SPAN_MEASURED_KEY) + s.set_tag(_SPAN_MEASURED_KEY) # set analytics sample rate with global config enabled s.set_tag(_ANALYTICS_SAMPLE_RATE_KEY, config.bottle.get_analytics_sample_rate(use_global_config=True)) diff --git a/ddtrace/contrib/internal/cassandra/session.py b/ddtrace/contrib/internal/cassandra/session.py index 7f02d8c0af6..3ccd44bb616 100644 --- a/ddtrace/contrib/internal/cassandra/session.py +++ b/ddtrace/contrib/internal/cassandra/session.py @@ -23,10 +23,10 @@ from ddtrace import Span from ddtrace import config from ddtrace.constants import _ANALYTICS_SAMPLE_RATE_KEY +from ddtrace.constants import _SPAN_MEASURED_KEY from ddtrace.constants import ERROR_MSG from ddtrace.constants import ERROR_TYPE from ddtrace.constants import SPAN_KIND -from ddtrace.constants import SPAN_MEASURED_KEY from ddtrace.ext import SpanKind from ddtrace.ext import SpanTypes from ddtrace.ext import cassandra as cassx @@ -214,7 +214,7 @@ def _start_span_and_set_tags( span.set_tag_str(COMPONENT, config.cassandra.integration_name) span.set_tag_str(db.SYSTEM, "cassandra") span.set_tag_str(SPAN_KIND, SpanKind.CLIENT) - span.set_tag(SPAN_MEASURED_KEY) + span.set_tag(_SPAN_MEASURED_KEY) span.set_tags(additional_tags) span.set_tag(_ANALYTICS_SAMPLE_RATE_KEY, config.cassandra.get_analytics_sample_rate()) if query is not None: diff --git a/ddtrace/contrib/internal/celery/app.py b/ddtrace/contrib/internal/celery/app.py index 54ad5834769..f338816243b 100644 --- a/ddtrace/contrib/internal/celery/app.py +++ b/ddtrace/contrib/internal/celery/app.py @@ -6,8 +6,8 @@ from ddtrace import config from ddtrace._trace.pin import _DD_PIN_NAME from ddtrace.constants import _ANALYTICS_SAMPLE_RATE_KEY +from ddtrace.constants import _SPAN_MEASURED_KEY from ddtrace.constants import SPAN_KIND -from ddtrace.constants import SPAN_MEASURED_KEY from ddtrace.contrib import trace_utils from ddtrace.contrib.internal.celery.signals import trace_after_publish from ddtrace.contrib.internal.celery.signals import trace_before_publish @@ -102,7 +102,7 @@ def _traced_beat_inner(func, instance, args, kwargs): rate = config.celery.get_analytics_sample_rate() if rate is not None: span.set_tag(_ANALYTICS_SAMPLE_RATE_KEY, rate) - span.set_tag(SPAN_MEASURED_KEY) + span.set_tag(_SPAN_MEASURED_KEY) return func(*args, **kwargs) diff --git a/ddtrace/contrib/internal/celery/signals.py b/ddtrace/contrib/internal/celery/signals.py index ea9d8c15863..dd03662e12f 100644 --- a/ddtrace/contrib/internal/celery/signals.py +++ b/ddtrace/contrib/internal/celery/signals.py @@ -5,8 +5,8 @@ from ddtrace import config from ddtrace.constants import _ANALYTICS_SAMPLE_RATE_KEY +from ddtrace.constants import _SPAN_MEASURED_KEY from ddtrace.constants import SPAN_KIND -from ddtrace.constants import SPAN_MEASURED_KEY from ddtrace.contrib import trace_utils from ddtrace.contrib.internal.celery import constants as c from ddtrace.contrib.internal.celery.utils import attach_span @@ -65,7 +65,7 @@ def trace_prerun(*args, **kwargs): if rate is not None: span.set_tag(_ANALYTICS_SAMPLE_RATE_KEY, rate) - span.set_tag(SPAN_MEASURED_KEY) + span.set_tag(_SPAN_MEASURED_KEY) attach_span(task, task_id, span) if config.celery["distributed_tracing"]: attach_span_context(task, task_id, span) @@ -139,7 +139,7 @@ def trace_before_publish(*args, **kwargs): if rate is not None: span.set_tag(_ANALYTICS_SAMPLE_RATE_KEY, rate) - span.set_tag(SPAN_MEASURED_KEY) + span.set_tag(_SPAN_MEASURED_KEY) span.set_tag_str(c.TASK_TAG_KEY, c.TASK_APPLY_ASYNC) span.set_tag_str("celery.id", task_id) set_tags_from_context(span, kwargs) diff --git a/ddtrace/contrib/internal/consul/patch.py b/ddtrace/contrib/internal/consul/patch.py index b24b138b632..d1761fdb05d 100644 --- a/ddtrace/contrib/internal/consul/patch.py +++ b/ddtrace/contrib/internal/consul/patch.py @@ -3,8 +3,8 @@ from ddtrace import config from ddtrace.constants import _ANALYTICS_SAMPLE_RATE_KEY +from ddtrace.constants import _SPAN_MEASURED_KEY from ddtrace.constants import SPAN_KIND -from ddtrace.constants import SPAN_MEASURED_KEY from ddtrace.ext import SpanKind from ddtrace.ext import SpanTypes from ddtrace.ext import consul as consulx @@ -73,7 +73,7 @@ def trace_func(wrapped, instance, args, kwargs): # set span.kind to the type of request being performed span.set_tag_str(SPAN_KIND, SpanKind.CLIENT) - span.set_tag(SPAN_MEASURED_KEY) + span.set_tag(_SPAN_MEASURED_KEY) rate = config.consul.get_analytics_sample_rate() if rate is not None: span.set_tag(_ANALYTICS_SAMPLE_RATE_KEY, rate) diff --git a/ddtrace/contrib/internal/django/utils.py b/ddtrace/contrib/internal/django/utils.py index 14f5e3dd4e6..a8d4c469e66 100644 --- a/ddtrace/contrib/internal/django/utils.py +++ b/ddtrace/contrib/internal/django/utils.py @@ -15,7 +15,7 @@ from ddtrace import config from ddtrace._trace.span import Span from ddtrace.constants import _ANALYTICS_SAMPLE_RATE_KEY -from ddtrace.constants import SPAN_MEASURED_KEY +from ddtrace.constants import _SPAN_MEASURED_KEY from ddtrace.contrib import trace_utils from ddtrace.contrib.internal.django.compat import get_resolver from ddtrace.contrib.internal.django.compat import user_is_authenticated @@ -255,7 +255,7 @@ def _before_request_tags(pin, span, request): # has explicitly set it during the request lifetime span.service = trace_utils.int_service(pin, config.django) span.span_type = SpanTypes.WEB - span._metrics[SPAN_MEASURED_KEY] = 1 + span._metrics[_SPAN_MEASURED_KEY] = 1 analytics_sr = config.django.get_analytics_sample_rate(use_global_config=True) if analytics_sr is not None: diff --git a/ddtrace/contrib/internal/dogpile_cache/region.py b/ddtrace/contrib/internal/dogpile_cache/region.py index 0c89d2d84d9..8b67f5bd2be 100644 --- a/ddtrace/contrib/internal/dogpile_cache/region.py +++ b/ddtrace/contrib/internal/dogpile_cache/region.py @@ -1,6 +1,6 @@ import dogpile -from ddtrace.constants import SPAN_MEASURED_KEY +from ddtrace.constants import _SPAN_MEASURED_KEY from ddtrace.ext import SpanTypes from ddtrace.ext import db from ddtrace.internal.constants import COMPONENT @@ -23,7 +23,7 @@ def _wrap_get_create(func, instance, args, kwargs): span_type=SpanTypes.CACHE, ) as span: span.set_tag_str(COMPONENT, "dogpile_cache") - span.set_tag(SPAN_MEASURED_KEY) + span.set_tag(_SPAN_MEASURED_KEY) span.set_tag("key", key) span.set_tag("region", instance.name) span.set_tag("backend", instance.actual_backend.__class__.__name__) @@ -45,7 +45,7 @@ def _wrap_get_create_multi(func, instance, args, kwargs): span_type="cache", ) as span: span.set_tag_str(COMPONENT, "dogpile_cache") - span.set_tag(SPAN_MEASURED_KEY) + span.set_tag(_SPAN_MEASURED_KEY) span.set_tag("keys", keys) span.set_tag("region", instance.name) span.set_tag("backend", instance.actual_backend.__class__.__name__) diff --git a/ddtrace/contrib/internal/elasticsearch/patch.py b/ddtrace/contrib/internal/elasticsearch/patch.py index 09eff66dbca..fa182ea3063 100644 --- a/ddtrace/contrib/internal/elasticsearch/patch.py +++ b/ddtrace/contrib/internal/elasticsearch/patch.py @@ -6,8 +6,8 @@ from ddtrace import config from ddtrace._trace import _limits from ddtrace.constants import _ANALYTICS_SAMPLE_RATE_KEY +from ddtrace.constants import _SPAN_MEASURED_KEY from ddtrace.constants import SPAN_KIND -from ddtrace.constants import SPAN_MEASURED_KEY from ddtrace.contrib.internal.elasticsearch.quantize import quantize from ddtrace.contrib.internal.trace_utils import ext_service from ddtrace.contrib.internal.trace_utils import extract_netloc_and_query_info_from_url @@ -140,7 +140,7 @@ def _perform_request(func, instance, args, kwargs): # set span.kind to the type of request being performed span.set_tag_str(SPAN_KIND, SpanKind.CLIENT) - span.set_tag(SPAN_MEASURED_KEY) + span.set_tag(_SPAN_MEASURED_KEY) method, target = args params = kwargs.get("params") diff --git a/ddtrace/contrib/internal/falcon/middleware.py b/ddtrace/contrib/internal/falcon/middleware.py index b6fe9498b1a..b4ec5434777 100644 --- a/ddtrace/contrib/internal/falcon/middleware.py +++ b/ddtrace/contrib/internal/falcon/middleware.py @@ -2,8 +2,8 @@ from ddtrace import config from ddtrace.constants import _ANALYTICS_SAMPLE_RATE_KEY +from ddtrace.constants import _SPAN_MEASURED_KEY from ddtrace.constants import SPAN_KIND -from ddtrace.constants import SPAN_MEASURED_KEY from ddtrace.contrib import trace_utils from ddtrace.ext import SpanKind from ddtrace.ext import SpanTypes @@ -39,7 +39,7 @@ def process_request(self, req, resp): # set span.kind to the type of operation being performed span.set_tag_str(SPAN_KIND, SpanKind.SERVER) - span.set_tag(SPAN_MEASURED_KEY) + span.set_tag(_SPAN_MEASURED_KEY) # set analytics sample rate with global config enabled span.set_tag(_ANALYTICS_SAMPLE_RATE_KEY, config.falcon.get_analytics_sample_rate(use_global_config=True)) diff --git a/ddtrace/contrib/internal/flask_cache/tracers.py b/ddtrace/contrib/internal/flask_cache/tracers.py index 2431ab2cbb7..9170bd4bd45 100644 --- a/ddtrace/contrib/internal/flask_cache/tracers.py +++ b/ddtrace/contrib/internal/flask_cache/tracers.py @@ -7,7 +7,7 @@ from ddtrace import config from ddtrace.constants import _ANALYTICS_SAMPLE_RATE_KEY -from ddtrace.constants import SPAN_MEASURED_KEY +from ddtrace.constants import _SPAN_MEASURED_KEY from ddtrace.ext import SpanTypes from ddtrace.ext import db from ddtrace.internal.constants import COMPONENT @@ -88,7 +88,7 @@ def __trace(self, cmd): s.set_tag_str(COMPONENT, config.flask_cache.integration_name) - s.set_tag(SPAN_MEASURED_KEY) + s.set_tag(_SPAN_MEASURED_KEY) # set span tags s.set_tag_str(CACHE_BACKEND, self.config.get("CACHE_TYPE")) s.set_tags(self._datadog_meta) diff --git a/ddtrace/contrib/internal/graphql/patch.py b/ddtrace/contrib/internal/graphql/patch.py index 18916f4222a..589bef80d4b 100644 --- a/ddtrace/contrib/internal/graphql/patch.py +++ b/ddtrace/contrib/internal/graphql/patch.py @@ -24,9 +24,9 @@ from ddtrace import config from ddtrace.constants import _ANALYTICS_SAMPLE_RATE_KEY +from ddtrace.constants import _SPAN_MEASURED_KEY from ddtrace.constants import ERROR_MSG from ddtrace.constants import ERROR_TYPE -from ddtrace.constants import SPAN_MEASURED_KEY from ddtrace.contrib import trace_utils from ddtrace.ext import SpanTypes from ddtrace.internal.constants import COMPONENT @@ -177,7 +177,7 @@ def _traced_execute(func, args, kwargs): ) as span: span.set_tag_str(COMPONENT, config.graphql.integration_name) - span.set_tag(SPAN_MEASURED_KEY) + span.set_tag(_SPAN_MEASURED_KEY) _set_span_operation_tags(span, document) span.set_tag_str(_GRAPHQL_SOURCE, source_str) @@ -207,7 +207,7 @@ def _traced_query(func, args, kwargs): span.set_tag_str(COMPONENT, config.graphql.integration_name) # mark span as measured and set sample rate - span.set_tag(SPAN_MEASURED_KEY) + span.set_tag(_SPAN_MEASURED_KEY) sample_rate = config.graphql.get_analytics_sample_rate() if sample_rate is not None: span.set_tag(_ANALYTICS_SAMPLE_RATE_KEY, sample_rate) diff --git a/ddtrace/contrib/internal/grpc/aio_client_interceptor.py b/ddtrace/contrib/internal/grpc/aio_client_interceptor.py index 5c03d1b8527..76455b1627f 100644 --- a/ddtrace/contrib/internal/grpc/aio_client_interceptor.py +++ b/ddtrace/contrib/internal/grpc/aio_client_interceptor.py @@ -14,10 +14,10 @@ from ddtrace import Span from ddtrace import config from ddtrace.constants import _ANALYTICS_SAMPLE_RATE_KEY +from ddtrace.constants import _SPAN_MEASURED_KEY from ddtrace.constants import ERROR_MSG from ddtrace.constants import ERROR_TYPE from ddtrace.constants import SPAN_KIND -from ddtrace.constants import SPAN_MEASURED_KEY from ddtrace.contrib import trace_utils from ddtrace.contrib.internal.grpc import constants from ddtrace.contrib.internal.grpc import utils @@ -151,7 +151,7 @@ def _intercept_client_call(self, method_kind, client_call_details): # set span.kind to the type of operation being performed span.set_tag_str(SPAN_KIND, SpanKind.CLIENT) - span.set_tag(SPAN_MEASURED_KEY) + span.set_tag(_SPAN_MEASURED_KEY) utils.set_grpc_method_meta(span, method_as_str, method_kind) utils.set_grpc_client_meta(span, self._host, self._port) diff --git a/ddtrace/contrib/internal/grpc/aio_server_interceptor.py b/ddtrace/contrib/internal/grpc/aio_server_interceptor.py index d5ec9ed32ab..d2e7efb0e00 100644 --- a/ddtrace/contrib/internal/grpc/aio_server_interceptor.py +++ b/ddtrace/contrib/internal/grpc/aio_server_interceptor.py @@ -16,10 +16,10 @@ from ddtrace import Span # noqa:F401 from ddtrace import config from ddtrace.constants import _ANALYTICS_SAMPLE_RATE_KEY +from ddtrace.constants import _SPAN_MEASURED_KEY from ddtrace.constants import ERROR_MSG from ddtrace.constants import ERROR_TYPE from ddtrace.constants import SPAN_KIND -from ddtrace.constants import SPAN_MEASURED_KEY from ddtrace.contrib import trace_utils from ddtrace.contrib.internal.grpc import constants from ddtrace.contrib.internal.grpc.utils import set_grpc_method_meta @@ -191,7 +191,7 @@ def _create_span(pin, method, invocation_metadata, method_kind): # set span.kind to the type of operation being performed span.set_tag_str(SPAN_KIND, SpanKind.SERVER) - span.set_tag(SPAN_MEASURED_KEY) + span.set_tag(_SPAN_MEASURED_KEY) set_grpc_method_meta(span, method, method_kind) span.set_tag_str(constants.GRPC_SPAN_KIND_KEY, constants.GRPC_SPAN_KIND_VALUE_SERVER) diff --git a/ddtrace/contrib/internal/grpc/client_interceptor.py b/ddtrace/contrib/internal/grpc/client_interceptor.py index b389bbe71c8..b2f259c2f3e 100644 --- a/ddtrace/contrib/internal/grpc/client_interceptor.py +++ b/ddtrace/contrib/internal/grpc/client_interceptor.py @@ -5,11 +5,11 @@ from ddtrace import config from ddtrace.constants import _ANALYTICS_SAMPLE_RATE_KEY +from ddtrace.constants import _SPAN_MEASURED_KEY from ddtrace.constants import ERROR_MSG from ddtrace.constants import ERROR_STACK from ddtrace.constants import ERROR_TYPE from ddtrace.constants import SPAN_KIND -from ddtrace.constants import SPAN_MEASURED_KEY from ddtrace.contrib import trace_utils from ddtrace.contrib.internal.grpc import constants from ddtrace.contrib.internal.grpc import utils @@ -196,7 +196,7 @@ def _intercept_client_call(self, method_kind, client_call_details): # set span.kind to the type of operation being performed span.set_tag_str(SPAN_KIND, SpanKind.CLIENT) - span.set_tag(SPAN_MEASURED_KEY) + span.set_tag(_SPAN_MEASURED_KEY) utils.set_grpc_method_meta(span, client_call_details.method, method_kind) utils.set_grpc_client_meta(span, self._host, self._port) diff --git a/ddtrace/contrib/internal/grpc/server_interceptor.py b/ddtrace/contrib/internal/grpc/server_interceptor.py index e221f170e80..482ca8b23c5 100644 --- a/ddtrace/contrib/internal/grpc/server_interceptor.py +++ b/ddtrace/contrib/internal/grpc/server_interceptor.py @@ -3,10 +3,10 @@ from ddtrace import config from ddtrace.constants import _ANALYTICS_SAMPLE_RATE_KEY +from ddtrace.constants import _SPAN_MEASURED_KEY from ddtrace.constants import ERROR_MSG from ddtrace.constants import ERROR_TYPE from ddtrace.constants import SPAN_KIND -from ddtrace.constants import SPAN_MEASURED_KEY from ddtrace.contrib import trace_utils from ddtrace.contrib.internal.grpc import constants from ddtrace.contrib.internal.grpc.utils import set_grpc_method_meta @@ -100,7 +100,7 @@ def _fn(self, method_kind, behavior, args, kwargs): # set span.kind tag equal to type of span span.set_tag_str(SPAN_KIND, SpanKind.SERVER) - span.set_tag(SPAN_MEASURED_KEY) + span.set_tag(_SPAN_MEASURED_KEY) set_grpc_method_meta(span, self._handler_call_details.method, method_kind) span.set_tag_str(constants.GRPC_SPAN_KIND_KEY, constants.GRPC_SPAN_KIND_VALUE_SERVER) diff --git a/ddtrace/contrib/internal/httpx/patch.py b/ddtrace/contrib/internal/httpx/patch.py index a3a677c14ac..1cf4e6f00e1 100644 --- a/ddtrace/contrib/internal/httpx/patch.py +++ b/ddtrace/contrib/internal/httpx/patch.py @@ -6,8 +6,8 @@ from ddtrace import config from ddtrace.constants import _ANALYTICS_SAMPLE_RATE_KEY +from ddtrace.constants import _SPAN_MEASURED_KEY from ddtrace.constants import SPAN_KIND -from ddtrace.constants import SPAN_MEASURED_KEY from ddtrace.contrib.internal.trace_utils import distributed_tracing_enabled from ddtrace.contrib.internal.trace_utils import ext_service from ddtrace.contrib.internal.trace_utils import set_http_meta @@ -86,7 +86,7 @@ def _get_service_name(pin, request): def _init_span(span, request): # type: (Span, httpx.Request) -> None - span.set_tag(SPAN_MEASURED_KEY) + span.set_tag(_SPAN_MEASURED_KEY) if distributed_tracing_enabled(config.httpx): HTTPPropagator.inject(span.context, request.headers) diff --git a/ddtrace/contrib/internal/jinja2/patch.py b/ddtrace/contrib/internal/jinja2/patch.py index 67c704c415d..6d044eb8ab8 100644 --- a/ddtrace/contrib/internal/jinja2/patch.py +++ b/ddtrace/contrib/internal/jinja2/patch.py @@ -4,7 +4,7 @@ from wrapt import wrap_function_wrapper as _w from ddtrace import config -from ddtrace.constants import SPAN_MEASURED_KEY +from ddtrace.constants import _SPAN_MEASURED_KEY from ddtrace.contrib.internal.trace_utils import unwrap as _u from ddtrace.ext import SpanTypes from ddtrace.internal.constants import COMPONENT @@ -64,7 +64,7 @@ def _wrap_render(wrapped, instance, args, kwargs): with pin.tracer.trace("jinja2.render", pin.service, span_type=SpanTypes.TEMPLATE) as span: span.set_tag_str(COMPONENT, config.jinja2.integration_name) - span.set_tag(SPAN_MEASURED_KEY) + span.set_tag(_SPAN_MEASURED_KEY) try: return wrapped(*args, **kwargs) finally: diff --git a/ddtrace/contrib/internal/kafka/patch.py b/ddtrace/contrib/internal/kafka/patch.py index 6f69cda3239..6818afbede0 100644 --- a/ddtrace/contrib/internal/kafka/patch.py +++ b/ddtrace/contrib/internal/kafka/patch.py @@ -6,8 +6,8 @@ from ddtrace import config from ddtrace.constants import _ANALYTICS_SAMPLE_RATE_KEY +from ddtrace.constants import _SPAN_MEASURED_KEY from ddtrace.constants import SPAN_KIND -from ddtrace.constants import SPAN_MEASURED_KEY from ddtrace.contrib import trace_utils from ddtrace.ext import SpanKind from ddtrace.ext import SpanTypes @@ -192,7 +192,7 @@ def traced_produce(func, instance, args, kwargs): span.set_tag(kafkax.PARTITION, partition) span.set_tag_str(kafkax.TOMBSTONE, str(value is None)) - span.set_tag(SPAN_MEASURED_KEY) + span.set_tag(_SPAN_MEASURED_KEY) if instance._dd_bootstrap_servers is not None: span.set_tag_str(kafkax.HOST_LIST, instance._dd_bootstrap_servers) rate = config.kafka.get_analytics_sample_rate() @@ -289,7 +289,7 @@ def _instrument_message(messages, pin, start_ns, instance, err): pass span.set_tag_str(kafkax.TOMBSTONE, str(is_tombstone)) span.set_tag(kafkax.MESSAGE_OFFSET, message_offset) - span.set_tag(SPAN_MEASURED_KEY) + span.set_tag(_SPAN_MEASURED_KEY) rate = config.kafka.get_analytics_sample_rate() if rate is not None: span.set_tag(_ANALYTICS_SAMPLE_RATE_KEY, rate) diff --git a/ddtrace/contrib/internal/kombu/patch.py b/ddtrace/contrib/internal/kombu/patch.py index fa63e5c4f86..9cbe8ac94a0 100644 --- a/ddtrace/contrib/internal/kombu/patch.py +++ b/ddtrace/contrib/internal/kombu/patch.py @@ -6,8 +6,8 @@ from ddtrace import config from ddtrace.constants import _ANALYTICS_SAMPLE_RATE_KEY +from ddtrace.constants import _SPAN_MEASURED_KEY from ddtrace.constants import SPAN_KIND -from ddtrace.constants import SPAN_MEASURED_KEY # project from ddtrace.contrib import trace_utils @@ -117,7 +117,7 @@ def traced_receive(func, instance, args, kwargs): # set span.kind to the type of operation being performed s.set_tag_str(SPAN_KIND, SpanKind.CONSUMER) - s.set_tag(SPAN_MEASURED_KEY) + s.set_tag(_SPAN_MEASURED_KEY) # run the command exchange = message.delivery_info["exchange"] s.resource = exchange @@ -147,7 +147,7 @@ def traced_publish(func, instance, args, kwargs): # set span.kind to the type of operation being performed s.set_tag_str(SPAN_KIND, SpanKind.PRODUCER) - s.set_tag(SPAN_MEASURED_KEY) + s.set_tag(_SPAN_MEASURED_KEY) exchange_name = get_exchange_from_args(args) s.resource = exchange_name s.set_tag_str(kombux.EXCHANGE, exchange_name) diff --git a/ddtrace/contrib/internal/mako/patch.py b/ddtrace/contrib/internal/mako/patch.py index ca569477773..1f65ce7e34a 100644 --- a/ddtrace/contrib/internal/mako/patch.py +++ b/ddtrace/contrib/internal/mako/patch.py @@ -3,7 +3,7 @@ from mako.template import Template from ddtrace import config -from ddtrace.constants import SPAN_MEASURED_KEY +from ddtrace.constants import _SPAN_MEASURED_KEY from ddtrace.contrib.internal.trace_utils import int_service from ddtrace.contrib.internal.trace_utils import unwrap as _u from ddtrace.contrib.internal.trace_utils import wrap as _w @@ -63,7 +63,7 @@ def _wrap_render(wrapped, instance, args, kwargs): ) as span: span.set_tag_str(COMPONENT, "mako") - span.set_tag(SPAN_MEASURED_KEY) + span.set_tag(_SPAN_MEASURED_KEY) try: return wrapped(*args, **kwargs) finally: diff --git a/ddtrace/contrib/internal/molten/patch.py b/ddtrace/contrib/internal/molten/patch.py index 6fc237a5b58..38fa949243c 100644 --- a/ddtrace/contrib/internal/molten/patch.py +++ b/ddtrace/contrib/internal/molten/patch.py @@ -6,8 +6,8 @@ from ddtrace import config from ddtrace.constants import _ANALYTICS_SAMPLE_RATE_KEY +from ddtrace.constants import _SPAN_MEASURED_KEY from ddtrace.constants import SPAN_KIND -from ddtrace.constants import SPAN_MEASURED_KEY from ddtrace.contrib import trace_utils from ddtrace.contrib.internal.trace_utils import unwrap as _u from ddtrace.ext import SpanKind @@ -105,7 +105,7 @@ def patch_app_call(wrapped, instance, args, kwargs): # set span.kind tag equal to type of operation being performed span.set_tag_str(SPAN_KIND, SpanKind.SERVER) - span.set_tag(SPAN_MEASURED_KEY) + span.set_tag(_SPAN_MEASURED_KEY) # set analytics sample rate with global config enabled span.set_tag(_ANALYTICS_SAMPLE_RATE_KEY, config.molten.get_analytics_sample_rate(use_global_config=True)) diff --git a/ddtrace/contrib/internal/mysqldb/patch.py b/ddtrace/contrib/internal/mysqldb/patch.py index e4d124ee1f6..cde0f58629f 100644 --- a/ddtrace/contrib/internal/mysqldb/patch.py +++ b/ddtrace/contrib/internal/mysqldb/patch.py @@ -6,8 +6,8 @@ from ddtrace import config from ddtrace.appsec._iast._metrics import _set_metric_iast_instrumented_sink from ddtrace.appsec._iast.constants import VULN_SQL_INJECTION +from ddtrace.constants import _SPAN_MEASURED_KEY from ddtrace.constants import SPAN_KIND -from ddtrace.constants import SPAN_MEASURED_KEY from ddtrace.contrib.dbapi import TracedConnection from ddtrace.contrib.internal.trace_utils import _convert_to_string from ddtrace.contrib.internal.trace_utils import ext_service @@ -101,7 +101,7 @@ def _connect(func, instance, args, kwargs): # set span.kind to the type of operation being performed span.set_tag_str(SPAN_KIND, SpanKind.CLIENT) - span.set_tag(SPAN_MEASURED_KEY) + span.set_tag(_SPAN_MEASURED_KEY) conn = func(*args, **kwargs) return patch_conn(conn, *args, **kwargs) diff --git a/ddtrace/contrib/internal/openai/_endpoint_hooks.py b/ddtrace/contrib/internal/openai/_endpoint_hooks.py index 979e1774a8a..00ee44aef4b 100644 --- a/ddtrace/contrib/internal/openai/_endpoint_hooks.py +++ b/ddtrace/contrib/internal/openai/_endpoint_hooks.py @@ -37,7 +37,7 @@ class _EndpointHook: OPERATION_ID = "" # Each endpoint hook must provide an operationID as specified in the OpenAI API specs: # https://raw.githubusercontent.com/openai/openai-openapi/master/openapi.yaml - def _record_request(self, pin, integration, span, args, kwargs): + def _record_request(self, pin, integration, instance, span, args, kwargs): """ Set base-level openai tags, as well as request params from args and kwargs. All inherited EndpointHook classes should include a super call to this method before performing @@ -45,12 +45,12 @@ def _record_request(self, pin, integration, span, args, kwargs): """ endpoint = self.ENDPOINT_NAME if endpoint is None: - endpoint = "%s" % args[0].OBJECT_NAME + endpoint = "%s" % getattr(instance, "OBJECT_NAME", "") span.set_tag_str("openai.request.endpoint", "/%s/%s" % (API_VERSION, endpoint)) span.set_tag_str("openai.request.method", self.HTTP_METHOD_TYPE) if self._request_arg_params and len(self._request_arg_params) > 1: - for idx, arg in enumerate(self._request_arg_params, 1): + for idx, arg in enumerate(self._request_arg_params): if idx >= len(args): break if arg is None or args[idx] is None: @@ -74,8 +74,8 @@ def _record_request(self, pin, integration, span, args, kwargs): else: span.set_tag_str("openai.request.%s" % kw_attr, str(kwargs[kw_attr])) - def handle_request(self, pin, integration, span, args, kwargs): - self._record_request(pin, integration, span, args, kwargs) + def handle_request(self, pin, integration, instance, span, args, kwargs): + self._record_request(pin, integration, instance, span, args, kwargs) resp, error = yield if hasattr(resp, "parse"): # Users can request the raw response, in which case we need to process on the parsed response @@ -186,8 +186,8 @@ class _CompletionHook(_BaseCompletionHook): HTTP_METHOD_TYPE = "POST" OPERATION_ID = "createCompletion" - def _record_request(self, pin, integration, span, args, kwargs): - super()._record_request(pin, integration, span, args, kwargs) + def _record_request(self, pin, integration, instance, span, args, kwargs): + super()._record_request(pin, integration, instance, span, args, kwargs) if integration.is_pc_sampled_span(span): prompt = kwargs.get("prompt", "") if isinstance(prompt, str): @@ -241,8 +241,8 @@ class _ChatCompletionHook(_BaseCompletionHook): HTTP_METHOD_TYPE = "POST" OPERATION_ID = "createChatCompletion" - def _record_request(self, pin, integration, span, args, kwargs): - super()._record_request(pin, integration, span, args, kwargs) + def _record_request(self, pin, integration, instance, span, args, kwargs): + super()._record_request(pin, integration, instance, span, args, kwargs) for idx, m in enumerate(kwargs.get("messages", [])): role = getattr(m, "role", "") name = getattr(m, "name", "") @@ -305,12 +305,12 @@ class _EmbeddingHook(_EndpointHook): HTTP_METHOD_TYPE = "POST" OPERATION_ID = "createEmbedding" - def _record_request(self, pin, integration, span, args, kwargs): + def _record_request(self, pin, integration, instance, span, args, kwargs): """ Embedding endpoint allows multiple inputs, each of which we specify a request tag for, so have to manually set them in _pre_response(). """ - super()._record_request(pin, integration, span, args, kwargs) + super()._record_request(pin, integration, instance, span, args, kwargs) embedding_input = kwargs.get("input", "") if integration.is_pc_sampled_span(span): if isinstance(embedding_input, str) or isinstance(embedding_input[0], int): @@ -340,8 +340,8 @@ class _ListHook(_EndpointHook): HTTP_METHOD_TYPE = "GET" OPERATION_ID = "list" - def _record_request(self, pin, integration, span, args, kwargs): - super()._record_request(pin, integration, span, args, kwargs) + def _record_request(self, pin, integration, instance, span, args, kwargs): + super()._record_request(pin, integration, instance, span, args, kwargs) endpoint = span.get_tag("openai.request.endpoint") if endpoint.endswith("/models"): span.resource = "listModels" @@ -399,15 +399,21 @@ class _RetrieveHook(_EndpointHook): HTTP_METHOD_TYPE = "GET" OPERATION_ID = "retrieve" - def _record_request(self, pin, integration, span, args, kwargs): - super()._record_request(pin, integration, span, args, kwargs) + def _record_request(self, pin, integration, instance, span, args, kwargs): + super()._record_request(pin, integration, instance, span, args, kwargs) endpoint = span.get_tag("openai.request.endpoint") if endpoint.endswith("/models"): span.resource = "retrieveModel" - span.set_tag_str("openai.request.model", args[1] if len(args) >= 2 else kwargs.get("model", "")) + if len(args) >= 1: + span.set_tag_str("openai.request.model", args[0]) + else: + span.set_tag_str("openai.request.model", kwargs.get("model", kwargs.get("id", ""))) elif endpoint.endswith("/files"): span.resource = "retrieveFile" - span.set_tag_str("openai.request.file_id", args[1] if len(args) >= 2 else kwargs.get("file_id", "")) + if len(args) >= 1: + span.set_tag_str("openai.request.file_id", args[0]) + else: + span.set_tag_str("openai.request.file_id", kwargs.get("file_id", kwargs.get("id", ""))) span.set_tag_str("openai.request.endpoint", "%s/*" % endpoint) def _record_response(self, pin, integration, span, args, kwargs, resp, error): @@ -434,10 +440,6 @@ class _ModelRetrieveHook(_RetrieveHook): ENDPOINT_NAME = "models" OPERATION_ID = "retrieveModel" - def _record_request(self, pin, integration, span, args, kwargs): - super()._record_request(pin, integration, span, args, kwargs) - span.set_tag_str("openai.request.model", args[1] if len(args) >= 2 else kwargs.get("model", "")) - class _FileRetrieveHook(_RetrieveHook): """ @@ -447,10 +449,6 @@ class _FileRetrieveHook(_RetrieveHook): ENDPOINT_NAME = "files" OPERATION_ID = "retrieveFile" - def _record_request(self, pin, integration, span, args, kwargs): - super()._record_request(pin, integration, span, args, kwargs) - span.set_tag_str("openai.request.file_id", args[1] if len(args) >= 2 else kwargs.get("file_id", "")) - class _DeleteHook(_EndpointHook): """Hook for openai.DeletableAPIResource, which is used by File.delete, and Model.delete.""" @@ -461,15 +459,21 @@ class _DeleteHook(_EndpointHook): HTTP_METHOD_TYPE = "DELETE" OPERATION_ID = "delete" - def _record_request(self, pin, integration, span, args, kwargs): - super()._record_request(pin, integration, span, args, kwargs) + def _record_request(self, pin, integration, instance, span, args, kwargs): + super()._record_request(pin, integration, instance, span, args, kwargs) endpoint = span.get_tag("openai.request.endpoint") if endpoint.endswith("/models"): span.resource = "deleteModel" - span.set_tag_str("openai.request.model", args[1] if len(args) >= 2 else kwargs.get("model", "")) + if len(args) >= 1: + span.set_tag_str("openai.request.model", args[0]) + else: + span.set_tag_str("openai.request.model", kwargs.get("model", kwargs.get("sid", ""))) elif endpoint.endswith("/files"): span.resource = "deleteFile" - span.set_tag_str("openai.request.file_id", args[1] if len(args) >= 2 else kwargs.get("file_id", "")) + if len(args) >= 1: + span.set_tag_str("openai.request.file_id", args[0]) + else: + span.set_tag_str("openai.request.file_id", kwargs.get("file_id", kwargs.get("sid", ""))) span.set_tag_str("openai.request.endpoint", "%s/*" % endpoint) def _record_response(self, pin, integration, span, args, kwargs, resp, error): @@ -508,8 +512,8 @@ class _ImageHook(_EndpointHook): ENDPOINT_NAME = "images" HTTP_METHOD_TYPE = "POST" - def _record_request(self, pin, integration, span, args, kwargs): - super()._record_request(pin, integration, span, args, kwargs) + def _record_request(self, pin, integration, instance, span, args, kwargs): + super()._record_request(pin, integration, instance, span, args, kwargs) span.set_tag_str("openai.request.model", "dall-e") def _record_response(self, pin, integration, span, args, kwargs, resp, error): @@ -526,10 +530,10 @@ def _record_response(self, pin, integration, span, args, kwargs, resp, error): if "prompt" in self._request_kwarg_params: attrs_dict.update({"prompt": kwargs.get("prompt", "")}) if "image" in self._request_kwarg_params: - image = args[1] if len(args) >= 2 else kwargs.get("image", "") + image = args[0] if len(args) >= 1 else kwargs.get("image", "") attrs_dict.update({"image": image.name.split("/")[-1]}) if "mask" in self._request_kwarg_params: - mask = args[2] if len(args) >= 3 else kwargs.get("mask", "") + mask = args[1] if len(args) >= 2 else kwargs.get("mask", "") attrs_dict.update({"mask": mask.name.split("/")[-1]}) integration.log( span, "info" if error is None else "error", "sampled %s" % self.OPERATION_ID, attrs=attrs_dict @@ -560,12 +564,12 @@ class _ImageEditHook(_ImageHook): ENDPOINT_NAME = "images/edits" OPERATION_ID = "createImageEdit" - def _record_request(self, pin, integration, span, args, kwargs): - super()._record_request(pin, integration, span, args, kwargs) + def _record_request(self, pin, integration, instance, span, args, kwargs): + super()._record_request(pin, integration, instance, span, args, kwargs) if not integration.is_pc_sampled_span: return - image = args[1] if len(args) >= 2 else kwargs.get("image", "") - mask = args[2] if len(args) >= 3 else kwargs.get("mask", "") + image = args[0] if len(args) >= 1 else kwargs.get("image", "") + mask = args[1] if len(args) >= 2 else kwargs.get("mask", "") if image: if hasattr(image, "name"): span.set_tag_str("openai.request.image", integration.trunc(image.name.split("/")[-1])) @@ -584,11 +588,11 @@ class _ImageVariationHook(_ImageHook): ENDPOINT_NAME = "images/variations" OPERATION_ID = "createImageVariation" - def _record_request(self, pin, integration, span, args, kwargs): - super()._record_request(pin, integration, span, args, kwargs) + def _record_request(self, pin, integration, instance, span, args, kwargs): + super()._record_request(pin, integration, instance, span, args, kwargs) if not integration.is_pc_sampled_span: return - image = args[1] if len(args) >= 2 else kwargs.get("image", "") + image = args[0] if len(args) >= 1 else kwargs.get("image", "") if image: if hasattr(image, "name"): span.set_tag_str("openai.request.image", integration.trunc(image.name.split("/")[-1])) @@ -602,11 +606,11 @@ class _BaseAudioHook(_EndpointHook): ENDPOINT_NAME = "audio" HTTP_METHOD_TYPE = "POST" - def _record_request(self, pin, integration, span, args, kwargs): - super()._record_request(pin, integration, span, args, kwargs) + def _record_request(self, pin, integration, instance, span, args, kwargs): + super()._record_request(pin, integration, instance, span, args, kwargs) if not integration.is_pc_sampled_span: return - audio_file = args[2] if len(args) >= 3 else kwargs.get("file", "") + audio_file = args[1] if len(args) >= 2 else kwargs.get("file", "") if audio_file and hasattr(audio_file, "name"): span.set_tag_str("openai.request.filename", integration.trunc(audio_file.name.split("/")[-1])) else: @@ -626,7 +630,7 @@ def _record_response(self, pin, integration, span, args, kwargs, resp, error): if integration.is_pc_sampled_span(span): span.set_tag_str("openai.response.text", integration.trunc(text)) if integration.is_pc_sampled_log(span): - file_input = args[2] if len(args) >= 3 else kwargs.get("file", "") + file_input = args[1] if len(args) >= 2 else kwargs.get("file", "") integration.log( span, "info" if error is None else "error", @@ -685,8 +689,8 @@ class _ModerationHook(_EndpointHook): HTTP_METHOD_TYPE = "POST" OPERATION_ID = "createModeration" - def _record_request(self, pin, integration, span, args, kwargs): - super()._record_request(pin, integration, span, args, kwargs) + def _record_request(self, pin, integration, instance, span, args, kwargs): + super()._record_request(pin, integration, instance, span, args, kwargs) def _record_response(self, pin, integration, span, args, kwargs, resp, error): resp = super()._record_response(pin, integration, span, args, kwargs, resp, error) @@ -718,14 +722,14 @@ class _FileCreateHook(_BaseFileHook): "organization", "user_provided_filename", ) - _request_kwarg_params = ("purpose",) + _request_kwarg_params = ("purpose", "user_provided_filename") _response_attrs = ("id", "bytes", "created_at", "filename", "purpose", "status", "status_details") HTTP_METHOD_TYPE = "POST" OPERATION_ID = "createFile" - def _record_request(self, pin, integration, span, args, kwargs): - super()._record_request(pin, integration, span, args, kwargs) - fp = args[1] if len(args) >= 2 else kwargs.get("file", "") + def _record_request(self, pin, integration, instance, span, args, kwargs): + super()._record_request(pin, integration, instance, span, args, kwargs) + fp = args[0] if len(args) >= 1 else kwargs.get("file", "") if fp and hasattr(fp, "name"): span.set_tag_str("openai.request.filename", fp.name.split("/")[-1]) else: @@ -742,9 +746,9 @@ class _FileDownloadHook(_BaseFileHook): OPERATION_ID = "downloadFile" ENDPOINT_NAME = "files/*/content" - def _record_request(self, pin, integration, span, args, kwargs): - super()._record_request(pin, integration, span, args, kwargs) - span.set_tag_str("openai.request.file_id", args[1] if len(args) >= 2 else kwargs.get("file_id", "")) + def _record_request(self, pin, integration, instance, span, args, kwargs): + super()._record_request(pin, integration, instance, span, args, kwargs) + span.set_tag_str("openai.request.file_id", args[0] if len(args) >= 1 else kwargs.get("file_id", "")) def _record_response(self, pin, integration, span, args, kwargs, resp, error): resp = super()._record_response(pin, integration, span, args, kwargs, resp, error) diff --git a/ddtrace/contrib/internal/openai/patch.py b/ddtrace/contrib/internal/openai/patch.py index d87b06b3aba..39f79d13795 100644 --- a/ddtrace/contrib/internal/openai/patch.py +++ b/ddtrace/contrib/internal/openai/patch.py @@ -6,12 +6,14 @@ from ddtrace import config from ddtrace.contrib.internal.openai import _endpoint_hooks from ddtrace.contrib.internal.openai.utils import _format_openai_api_key +from ddtrace.contrib.trace_utils import unwrap +from ddtrace.contrib.trace_utils import with_traced_module +from ddtrace.contrib.trace_utils import wrap from ddtrace.internal.logger import get_logger from ddtrace.internal.schema import schematize_service_name from ddtrace.internal.utils.formats import asbool from ddtrace.internal.utils.formats import deep_getattr from ddtrace.internal.utils.version import parse_version -from ddtrace.internal.wrapping import wrap from ddtrace.llmobs._integrations import OpenAIIntegration from ddtrace.trace import Pin @@ -80,8 +82,9 @@ def get_version(): else: _RESOURCES = { "model.Model": { - "list": _endpoint_hooks._ListHook, - "retrieve": _endpoint_hooks._RetrieveHook, + "list": _endpoint_hooks._ModelListHook, + "retrieve": _endpoint_hooks._ModelRetrieveHook, + "delete": _endpoint_hooks._ModelDeleteHook, }, "completion.Completion": { "create": _endpoint_hooks._CompletionHook, @@ -105,19 +108,15 @@ def get_version(): "create": _endpoint_hooks._ModerationHook, }, "file.File": { - # File.list() and File.retrieve() share the same underlying method as Model.list() and Model.retrieve() - # which means they are already wrapped + "list": _endpoint_hooks._FileListHook, + "retrieve": _endpoint_hooks._FileRetrieveHook, "create": _endpoint_hooks._FileCreateHook, - "delete": _endpoint_hooks._DeleteHook, + "delete": _endpoint_hooks._FileDeleteHook, "download": _endpoint_hooks._FileDownloadHook, }, } -def _wrap_classmethod(obj, wrapper): - wrap(obj.__func__, wrapper) - - def patch(): # Avoid importing openai at the module level, eventually will be an import hook import openai @@ -127,72 +126,106 @@ def patch(): Pin().onto(openai) integration = OpenAIIntegration(integration_config=config.openai, openai=openai) + openai._datadog_integration = integration if OPENAI_VERSION >= (1, 0, 0): if OPENAI_VERSION >= (1, 8, 0): - wrap(openai._base_client.SyncAPIClient._process_response, _patched_convert(openai, integration)) - wrap(openai._base_client.AsyncAPIClient._process_response, _patched_convert(openai, integration)) + wrap(openai, "_base_client.SyncAPIClient._process_response", patched_convert(openai)) + wrap(openai, "_base_client.AsyncAPIClient._process_response", patched_convert(openai)) else: - wrap(openai._base_client.BaseClient._process_response, _patched_convert(openai, integration)) - wrap(openai.OpenAI.__init__, _patched_client_init(openai, integration)) - wrap(openai.AsyncOpenAI.__init__, _patched_client_init(openai, integration)) - wrap(openai.AzureOpenAI.__init__, _patched_client_init(openai, integration)) - wrap(openai.AsyncAzureOpenAI.__init__, _patched_client_init(openai, integration)) + wrap(openai, "_base_client.BaseClient._process_response", patched_convert(openai)) + wrap(openai, "OpenAI.__init__", patched_client_init(openai)) + wrap(openai, "AsyncOpenAI.__init__", patched_client_init(openai)) + wrap(openai, "AzureOpenAI.__init__", patched_client_init(openai)) + wrap(openai, "AsyncAzureOpenAI.__init__", patched_client_init(openai)) for resource, method_hook_dict in _RESOURCES.items(): if deep_getattr(openai.resources, resource) is None: continue for method_name, endpoint_hook in method_hook_dict.items(): - sync_method = deep_getattr(openai.resources, "%s.%s" % (resource, method_name)) - async_method = deep_getattr( - openai.resources, "%s.%s" % (".Async".join(resource.split(".")), method_name) - ) - wrap(sync_method, _patched_endpoint(openai, integration, endpoint_hook)) - wrap(async_method, _patched_endpoint_async(openai, integration, endpoint_hook)) + sync_method = "resources.{}.{}".format(resource, method_name) + async_method = "resources.{}.{}".format(".Async".join(resource.split(".")), method_name) + wrap(openai, sync_method, _patched_endpoint(openai, endpoint_hook)) + wrap(openai, async_method, _patched_endpoint_async(openai, endpoint_hook)) else: import openai.api_requestor - wrap(openai.api_requestor._make_session, _patched_make_session) - wrap(openai.util.convert_to_openai_object, _patched_convert(openai, integration)) + wrap(openai, "api_requestor._make_session", _patched_make_session) + wrap(openai, "util.convert_to_openai_object", patched_convert(openai)) for resource, method_hook_dict in _RESOURCES.items(): if deep_getattr(openai.api_resources, resource) is None: continue for method_name, endpoint_hook in method_hook_dict.items(): - sync_method = deep_getattr(openai.api_resources, "%s.%s" % (resource, method_name)) - async_method = deep_getattr(openai.api_resources, "%s.a%s" % (resource, method_name)) - _wrap_classmethod(sync_method, _patched_endpoint(openai, integration, endpoint_hook)) - _wrap_classmethod(async_method, _patched_endpoint_async(openai, integration, endpoint_hook)) + sync_method = "api_resources.{}.{}".format(resource, method_name) + async_method = "api_resources.{}.a{}".format(resource, method_name) + wrap(openai, sync_method, _patched_endpoint(openai, endpoint_hook)) + wrap(openai, async_method, _patched_endpoint_async(openai, endpoint_hook)) openai.__datadog_patch = True def unpatch(): - # FIXME: add unpatching. The current wrapping.unwrap method requires - # the wrapper function to be provided which we don't keep a reference to. - pass + import openai + if not getattr(openai, "__datadog_patch", False): + return -def _patched_client_init(openai, integration): - """ - Patch for `openai.OpenAI/AsyncOpenAI` client init methods to add the client object to the OpenAIIntegration object. - """ + openai.__datadog_patch = False - def patched_client_init(func, args, kwargs): - func(*args, **kwargs) - client = args[0] - integration._client = client - api_key = kwargs.get("api_key") - if api_key is None: - api_key = client.api_key - if api_key is not None: - integration.user_api_key = api_key - return + if OPENAI_VERSION >= (1, 0, 0): + if OPENAI_VERSION >= (1, 8, 0): + unwrap(openai._base_client.SyncAPIClient, "_process_response") + unwrap(openai._base_client.AsyncAPIClient, "_process_response") + else: + unwrap(openai._base_client.BaseClient, "_process_response") + unwrap(openai.OpenAI, "__init__") + unwrap(openai.AsyncOpenAI, "__init__") + unwrap(openai.AzureOpenAI, "__init__") + unwrap(openai.AsyncAzureOpenAI, "__init__") + + for resource, method_hook_dict in _RESOURCES.items(): + if deep_getattr(openai.resources, resource) is None: + continue + for method_name, _ in method_hook_dict.items(): + sync_resource = deep_getattr(openai.resources, resource) + async_resource = deep_getattr(openai.resources, ".Async".join(resource.split("."))) + unwrap(sync_resource, method_name) + unwrap(async_resource, method_name) + else: + import openai.api_requestor + + unwrap(openai.api_requestor, "_make_session") + unwrap(openai.util, "convert_to_openai_object") - return patched_client_init + for resource, method_hook_dict in _RESOURCES.items(): + if deep_getattr(openai.api_resources, resource) is None: + continue + for method_name, _ in method_hook_dict.items(): + resource_obj = deep_getattr(openai.api_resources, resource) + unwrap(resource_obj, method_name) + unwrap(resource_obj, "a{}".format(method_name)) + delattr(openai, "_datadog_integration") -def _patched_make_session(func, args, kwargs): + +@with_traced_module +def patched_client_init(openai, pin, func, instance, args, kwargs): + """ + Patch for `openai.OpenAI/AsyncOpenAI` client init methods to add the client object to the OpenAIIntegration object. + """ + func(*args, **kwargs) + integration = openai._datadog_integration + integration._client = instance + api_key = kwargs.get("api_key") + if api_key is None: + api_key = instance.api_key + if api_key is not None: + integration.user_api_key = api_key + return + + +def _patched_make_session(func, instance, args, kwargs): """Patch for `openai.api_requestor._make_session` which sets the service name on the requests session so that spans from the requests integration will use the service name openai. This is done so that the service break down will include OpenAI time spent querying the OpenAI backend. @@ -205,7 +238,7 @@ def _patched_make_session(func, args, kwargs): return session -def _traced_endpoint(endpoint_hook, integration, pin, args, kwargs): +def _traced_endpoint(endpoint_hook, integration, instance, pin, args, kwargs): span = integration.trace(pin, endpoint_hook.OPERATION_ID) openai_api_key = _format_openai_api_key(kwargs.get("api_key")) err = None @@ -214,7 +247,7 @@ def _traced_endpoint(endpoint_hook, integration, pin, args, kwargs): span.set_tag_str("openai.user.api_key", openai_api_key) try: # Start the hook - hook = endpoint_hook().handle_request(pin, integration, span, args, kwargs) + hook = endpoint_hook().handle_request(pin, integration, instance, span, args, kwargs) hook.send(None) resp, err = yield @@ -238,19 +271,11 @@ def _traced_endpoint(endpoint_hook, integration, pin, args, kwargs): integration.metric(span, "dist", "request.duration", span.duration_ns) -def _patched_endpoint(openai, integration, patch_hook): - def patched_endpoint(func, args, kwargs): - # FIXME: this is a temporary workaround for the fact that our bytecode wrapping seems to modify - # a function keyword argument into a cell when it shouldn't. This is only an issue on - # Python 3.11+. - if sys.version_info >= (3, 11) and kwargs.get("encoding_format", None): - kwargs["encoding_format"] = kwargs["encoding_format"].cell_contents - - pin = Pin._find(openai, args[0]) - if not pin or not pin.enabled(): - return func(*args, **kwargs) - - g = _traced_endpoint(patch_hook, integration, pin, args, kwargs) +def _patched_endpoint(openai, patch_hook): + @with_traced_module + def patched_endpoint(openai, pin, func, instance, args, kwargs): + integration = openai._datadog_integration + g = _traced_endpoint(patch_hook, integration, instance, pin, args, kwargs) g.send(None) resp, err = None, None try: @@ -267,22 +292,15 @@ def patched_endpoint(func, args, kwargs): # This return takes priority over `return resp` return e.value # noqa: B012 - return patched_endpoint + return patched_endpoint(openai) -def _patched_endpoint_async(openai, integration, patch_hook): +def _patched_endpoint_async(openai, patch_hook): # Same as _patched_endpoint but async - async def patched_endpoint(func, args, kwargs): - # FIXME: this is a temporary workaround for the fact that our bytecode wrapping seems to modify - # a function keyword argument into a cell when it shouldn't. This is only an issue on - # Python 3.11+. - if sys.version_info >= (3, 11) and kwargs.get("encoding_format", None): - kwargs["encoding_format"] = kwargs["encoding_format"].cell_contents - - pin = Pin._find(openai, args[0]) - if not pin or not pin.enabled(): - return await func(*args, **kwargs) - g = _traced_endpoint(patch_hook, integration, pin, args, kwargs) + @with_traced_module + async def patched_endpoint(openai, pin, func, instance, args, kwargs): + integration = openai._datadog_integration + g = _traced_endpoint(patch_hook, integration, instance, pin, args, kwargs) g.send(None) resp, err = None, None try: @@ -304,59 +322,54 @@ async def patched_endpoint(func, args, kwargs): # This return takes priority over `return resp` return e.value # noqa: B012 - return patched_endpoint + return patched_endpoint(openai) -def _patched_convert(openai, integration): - def patched_convert(func, args, kwargs): - """Patch convert captures header information in the openai response""" - pin = Pin.get_from(openai) - if not pin or not pin.enabled(): - return func(*args, **kwargs) - - span = pin.tracer.current_span() - if not span: - return func(*args, **kwargs) +@with_traced_module +def patched_convert(openai, pin, func, instance, args, kwargs): + """Patch convert captures header information in the openai response""" + integration = openai._datadog_integration + span = pin.tracer.current_span() + if not span: + return func(*args, **kwargs) - if OPENAI_VERSION < (1, 0, 0): - resp = args[0] - if not isinstance(resp, openai.openai_response.OpenAIResponse): - return func(*args, **kwargs) - headers = resp._headers - else: - resp = kwargs.get("response", {}) - headers = resp.headers - # This function is called for each chunk in the stream. - # To prevent needlessly setting the same tags for each chunk, short-circuit here. - if span.get_tag("openai.organization.name") is not None: + if OPENAI_VERSION < (1, 0, 0): + resp = args[0] + if not isinstance(resp, openai.openai_response.OpenAIResponse): return func(*args, **kwargs) - if headers.get("openai-organization"): - org_name = headers.get("openai-organization") - span.set_tag_str("openai.organization.name", org_name) - - # Gauge total rate limit - if headers.get("x-ratelimit-limit-requests"): - v = headers.get("x-ratelimit-limit-requests") - if v is not None: - integration.metric(span, "gauge", "ratelimit.requests", int(v)) - span.set_metric("openai.organization.ratelimit.requests.limit", int(v)) - if headers.get("x-ratelimit-limit-tokens"): - v = headers.get("x-ratelimit-limit-tokens") - if v is not None: - integration.metric(span, "gauge", "ratelimit.tokens", int(v)) - span.set_metric("openai.organization.ratelimit.tokens.limit", int(v)) - # Gauge and set span info for remaining requests and tokens - if headers.get("x-ratelimit-remaining-requests"): - v = headers.get("x-ratelimit-remaining-requests") - if v is not None: - integration.metric(span, "gauge", "ratelimit.remaining.requests", int(v)) - span.set_metric("openai.organization.ratelimit.requests.remaining", int(v)) - if headers.get("x-ratelimit-remaining-tokens"): - v = headers.get("x-ratelimit-remaining-tokens") - if v is not None: - integration.metric(span, "gauge", "ratelimit.remaining.tokens", int(v)) - span.set_metric("openai.organization.ratelimit.tokens.remaining", int(v)) - + headers = resp._headers + else: + resp = kwargs.get("response", {}) + headers = resp.headers + # This function is called for each chunk in the stream. + # To prevent needlessly setting the same tags for each chunk, short-circuit here. + if span.get_tag("openai.organization.name") is not None: return func(*args, **kwargs) - - return patched_convert + if headers.get("openai-organization"): + org_name = headers.get("openai-organization") + span.set_tag_str("openai.organization.name", org_name) + + # Gauge total rate limit + if headers.get("x-ratelimit-limit-requests"): + v = headers.get("x-ratelimit-limit-requests") + if v is not None: + integration.metric(span, "gauge", "ratelimit.requests", int(v)) + span.set_metric("openai.organization.ratelimit.requests.limit", int(v)) + if headers.get("x-ratelimit-limit-tokens"): + v = headers.get("x-ratelimit-limit-tokens") + if v is not None: + integration.metric(span, "gauge", "ratelimit.tokens", int(v)) + span.set_metric("openai.organization.ratelimit.tokens.limit", int(v)) + # Gauge and set span info for remaining requests and tokens + if headers.get("x-ratelimit-remaining-requests"): + v = headers.get("x-ratelimit-remaining-requests") + if v is not None: + integration.metric(span, "gauge", "ratelimit.remaining.requests", int(v)) + span.set_metric("openai.organization.ratelimit.requests.remaining", int(v)) + if headers.get("x-ratelimit-remaining-tokens"): + v = headers.get("x-ratelimit-remaining-tokens") + if v is not None: + integration.metric(span, "gauge", "ratelimit.remaining.tokens", int(v)) + span.set_metric("openai.organization.ratelimit.tokens.remaining", int(v)) + + return func(*args, **kwargs) diff --git a/ddtrace/contrib/internal/psycopg/async_connection.py b/ddtrace/contrib/internal/psycopg/async_connection.py index 8d400330ff5..f17b4c7a953 100644 --- a/ddtrace/contrib/internal/psycopg/async_connection.py +++ b/ddtrace/contrib/internal/psycopg/async_connection.py @@ -1,6 +1,6 @@ from ddtrace import config +from ddtrace.constants import _SPAN_MEASURED_KEY from ddtrace.constants import SPAN_KIND -from ddtrace.constants import SPAN_MEASURED_KEY from ddtrace.contrib import dbapi_async from ddtrace.contrib.internal.psycopg.async_cursor import Psycopg3FetchTracedAsyncCursor from ddtrace.contrib.internal.psycopg.async_cursor import Psycopg3TracedAsyncCursor @@ -58,7 +58,7 @@ async def patched_connect_async(connect_func, _, args, kwargs): if span.get_tag(db.SYSTEM) is None: span.set_tag_str(db.SYSTEM, pin._config.dbms_name) - span.set_tag(SPAN_MEASURED_KEY) + span.set_tag(_SPAN_MEASURED_KEY) conn = await connect_func(*args, **kwargs) return patch_conn(conn, pin=pin, traced_conn_cls=traced_conn_cls) diff --git a/ddtrace/contrib/internal/psycopg/connection.py b/ddtrace/contrib/internal/psycopg/connection.py index c3b7caef2c4..6e9190421cb 100644 --- a/ddtrace/contrib/internal/psycopg/connection.py +++ b/ddtrace/contrib/internal/psycopg/connection.py @@ -1,6 +1,6 @@ from ddtrace import config +from ddtrace.constants import _SPAN_MEASURED_KEY from ddtrace.constants import SPAN_KIND -from ddtrace.constants import SPAN_MEASURED_KEY from ddtrace.contrib import dbapi from ddtrace.contrib.internal.psycopg.cursor import Psycopg2FetchTracedCursor from ddtrace.contrib.internal.psycopg.cursor import Psycopg2TracedCursor @@ -102,7 +102,7 @@ def patched_connect(connect_func, _, args, kwargs): if span.get_tag(db.SYSTEM) is None: span.set_tag_str(db.SYSTEM, pin._config.dbms_name) - span.set_tag(SPAN_MEASURED_KEY) + span.set_tag(_SPAN_MEASURED_KEY) conn = connect_func(*args, **kwargs) return patch_conn(conn, pin=pin, traced_conn_cls=traced_conn_cls) diff --git a/ddtrace/contrib/internal/psycopg/extensions.py b/ddtrace/contrib/internal/psycopg/extensions.py index cebe5c1cdf8..f5960e073aa 100644 --- a/ddtrace/contrib/internal/psycopg/extensions.py +++ b/ddtrace/contrib/internal/psycopg/extensions.py @@ -6,8 +6,8 @@ import wrapt from ddtrace import config +from ddtrace.constants import _SPAN_MEASURED_KEY from ddtrace.constants import SPAN_KIND -from ddtrace.constants import SPAN_MEASURED_KEY from ddtrace.ext import SpanKind from ddtrace.ext import SpanTypes from ddtrace.ext import db @@ -42,7 +42,7 @@ def execute(self, query, vars=None): # noqa: A002 # set span.kind to the type of operation being performed s.set_tag_str(SPAN_KIND, SpanKind.CLIENT) - s.set_tag(SPAN_MEASURED_KEY) + s.set_tag(_SPAN_MEASURED_KEY) if s.context.sampling_priority is None or s.context.sampling_priority <= 0: return super(TracedCursor, self).execute(query, vars) diff --git a/ddtrace/contrib/internal/pylibmc/client.py b/ddtrace/contrib/internal/pylibmc/client.py index 3ea6f09c62c..5321b533293 100644 --- a/ddtrace/contrib/internal/pylibmc/client.py +++ b/ddtrace/contrib/internal/pylibmc/client.py @@ -8,8 +8,8 @@ import ddtrace from ddtrace import config from ddtrace.constants import _ANALYTICS_SAMPLE_RATE_KEY +from ddtrace.constants import _SPAN_MEASURED_KEY from ddtrace.constants import SPAN_KIND -from ddtrace.constants import SPAN_MEASURED_KEY from ddtrace.contrib.internal.pylibmc.addrs import parse_addresses from ddtrace.ext import SpanKind from ddtrace.ext import SpanTypes @@ -177,7 +177,7 @@ def _span(self, cmd_name): # set span.kind to the type of operation being performed span.set_tag_str(SPAN_KIND, SpanKind.CLIENT) - span.set_tag(SPAN_MEASURED_KEY) + span.set_tag(_SPAN_MEASURED_KEY) try: self._tag_span(span) diff --git a/ddtrace/contrib/internal/pymemcache/client.py b/ddtrace/contrib/internal/pymemcache/client.py index 37e14842a94..574332586e5 100644 --- a/ddtrace/contrib/internal/pymemcache/client.py +++ b/ddtrace/contrib/internal/pymemcache/client.py @@ -18,8 +18,8 @@ # project from ddtrace.constants import _ANALYTICS_SAMPLE_RATE_KEY +from ddtrace.constants import _SPAN_MEASURED_KEY from ddtrace.constants import SPAN_KIND -from ddtrace.constants import SPAN_MEASURED_KEY from ddtrace.ext import SpanKind from ddtrace.ext import SpanTypes from ddtrace.ext import db @@ -319,7 +319,7 @@ def _trace(func, p, method_name, *args, **kwargs): # set span.kind to the type of operation being performed span.set_tag_str(SPAN_KIND, SpanKind.CLIENT) - span.set_tag(SPAN_MEASURED_KEY) + span.set_tag(_SPAN_MEASURED_KEY) # set analytics sample rate span.set_tag(_ANALYTICS_SAMPLE_RATE_KEY, config.pymemcache.get_analytics_sample_rate()) diff --git a/ddtrace/contrib/internal/pymongo/client.py b/ddtrace/contrib/internal/pymongo/client.py index 2cdf2185586..269a3120fbd 100644 --- a/ddtrace/contrib/internal/pymongo/client.py +++ b/ddtrace/contrib/internal/pymongo/client.py @@ -12,8 +12,8 @@ import ddtrace from ddtrace import config from ddtrace.constants import _ANALYTICS_SAMPLE_RATE_KEY +from ddtrace.constants import _SPAN_MEASURED_KEY from ddtrace.constants import SPAN_KIND -from ddtrace.constants import SPAN_MEASURED_KEY from ddtrace.contrib import trace_utils from ddtrace.ext import SpanKind from ddtrace.ext import SpanTypes @@ -141,7 +141,7 @@ def _datadog_trace_operation(operation, wrapped): # set span.kind to the operation type being performed span.set_tag_str(SPAN_KIND, SpanKind.CLIENT) - span.set_tag(SPAN_MEASURED_KEY) + span.set_tag(_SPAN_MEASURED_KEY) span.set_tag_str(mongox.DB, cmd.db) span.set_tag_str(mongox.COLLECTION, cmd.coll) span.set_tag_str(db.SYSTEM, mongox.SERVICE) @@ -265,7 +265,7 @@ def _trace_cmd(cmd, socket_instance, address): # set span.kind to the type of operation being performed s.set_tag_str(SPAN_KIND, SpanKind.CLIENT) - s.set_tag(SPAN_MEASURED_KEY) + s.set_tag(_SPAN_MEASURED_KEY) if cmd.db: s.set_tag_str(mongox.DB, cmd.db) if cmd: diff --git a/ddtrace/contrib/internal/pymongo/patch.py b/ddtrace/contrib/internal/pymongo/patch.py index 200a4a902b8..f37a07be5cd 100644 --- a/ddtrace/contrib/internal/pymongo/patch.py +++ b/ddtrace/contrib/internal/pymongo/patch.py @@ -3,8 +3,8 @@ import pymongo from ddtrace import config +from ddtrace.constants import _SPAN_MEASURED_KEY from ddtrace.constants import SPAN_KIND -from ddtrace.constants import SPAN_MEASURED_KEY from ddtrace.contrib import trace_utils from ddtrace.ext import SpanKind from ddtrace.ext import SpanTypes @@ -129,7 +129,7 @@ def traced_get_socket(func, args, kwargs): with func(*args, **kwargs) as sock_info: set_address_tags(span, sock_info.address) - span.set_tag(SPAN_MEASURED_KEY) + span.set_tag(_SPAN_MEASURED_KEY) # Ensure the pin used on the traced mongo client is passed down to the socket instance # (via the server instance) Pin.get_from(instance).onto(sock_info) diff --git a/ddtrace/contrib/internal/pynamodb/patch.py b/ddtrace/contrib/internal/pynamodb/patch.py index 93171d176bd..29bf44b8df9 100644 --- a/ddtrace/contrib/internal/pynamodb/patch.py +++ b/ddtrace/contrib/internal/pynamodb/patch.py @@ -7,8 +7,8 @@ from ddtrace import config from ddtrace.constants import _ANALYTICS_SAMPLE_RATE_KEY +from ddtrace.constants import _SPAN_MEASURED_KEY from ddtrace.constants import SPAN_KIND -from ddtrace.constants import SPAN_MEASURED_KEY from ddtrace.contrib import trace_utils from ddtrace.contrib.internal.trace_utils import unwrap from ddtrace.ext import SpanKind @@ -70,7 +70,7 @@ def patched_api_call(original_func, instance, args, kwargs): # set span.kind to the type of operation being performed span.set_tag_str(SPAN_KIND, SpanKind.CLIENT) - span.set_tag(SPAN_MEASURED_KEY) + span.set_tag(_SPAN_MEASURED_KEY) try: operation = get_argument_value(args, kwargs, 0, "operation_name") diff --git a/ddtrace/contrib/internal/pyramid/trace.py b/ddtrace/contrib/internal/pyramid/trace.py index cd0569f62df..9942c673d4e 100644 --- a/ddtrace/contrib/internal/pyramid/trace.py +++ b/ddtrace/contrib/internal/pyramid/trace.py @@ -7,8 +7,8 @@ import ddtrace from ddtrace import config from ddtrace.constants import _ANALYTICS_SAMPLE_RATE_KEY +from ddtrace.constants import _SPAN_MEASURED_KEY from ddtrace.constants import SPAN_KIND -from ddtrace.constants import SPAN_MEASURED_KEY from ddtrace.contrib import trace_utils from ddtrace.ext import SpanKind from ddtrace.ext import SpanTypes @@ -83,7 +83,7 @@ def trace_tween(request): # set span.kind to the type of operation being performed span.set_tag_str(SPAN_KIND, SpanKind.SERVER) - span.set_tag(SPAN_MEASURED_KEY) + span.set_tag(_SPAN_MEASURED_KEY) # Configure trace search sample rate # DEV: pyramid is special case maintains separate configuration from config api analytics_enabled = settings.get(SETTINGS_ANALYTICS_ENABLED) diff --git a/ddtrace/contrib/internal/rediscluster/patch.py b/ddtrace/contrib/internal/rediscluster/patch.py index c550df7e9ea..23b37502310 100644 --- a/ddtrace/contrib/internal/rediscluster/patch.py +++ b/ddtrace/contrib/internal/rediscluster/patch.py @@ -7,8 +7,8 @@ # project from ddtrace import config from ddtrace.constants import _ANALYTICS_SAMPLE_RATE_KEY +from ddtrace.constants import _SPAN_MEASURED_KEY from ddtrace.constants import SPAN_KIND -from ddtrace.constants import SPAN_MEASURED_KEY from ddtrace.contrib import trace_utils from ddtrace.contrib.internal.redis.patch import instrumented_execute_command from ddtrace.contrib.internal.redis.patch import instrumented_pipeline @@ -102,7 +102,7 @@ def traced_execute_pipeline(func, instance, args, kwargs): s.set_tag_str(SPAN_KIND, SpanKind.CLIENT) s.set_tag_str(COMPONENT, config.rediscluster.integration_name) s.set_tag_str(db.SYSTEM, redisx.APP) - s.set_tag(SPAN_MEASURED_KEY) + s.set_tag(_SPAN_MEASURED_KEY) s.set_tag_str(redisx.RAWCMD, resource) s.set_metric(redisx.PIPELINE_LEN, len(instance.command_stack)) diff --git a/ddtrace/contrib/internal/requests/connection.py b/ddtrace/contrib/internal/requests/connection.py index 9ad198faacd..c6d7706ef54 100644 --- a/ddtrace/contrib/internal/requests/connection.py +++ b/ddtrace/contrib/internal/requests/connection.py @@ -3,8 +3,8 @@ import ddtrace from ddtrace import config from ddtrace.constants import _ANALYTICS_SAMPLE_RATE_KEY +from ddtrace.constants import _SPAN_MEASURED_KEY from ddtrace.constants import SPAN_KIND -from ddtrace.constants import SPAN_MEASURED_KEY from ddtrace.contrib import trace_utils from ddtrace.contrib.internal.trace_utils import _sanitized_url from ddtrace.ext import SpanKind @@ -93,7 +93,7 @@ def _wrap_send(func, instance, args, kwargs): # set span.kind to the type of operation being performed span.set_tag_str(SPAN_KIND, SpanKind.CLIENT) - span.set_tag(SPAN_MEASURED_KEY) + span.set_tag(_SPAN_MEASURED_KEY) # Configure trace search sample rate # DEV: analytics enabled on per-session basis diff --git a/ddtrace/contrib/internal/sqlalchemy/engine.py b/ddtrace/contrib/internal/sqlalchemy/engine.py index 3b5f96be9e7..6e123c97db8 100644 --- a/ddtrace/contrib/internal/sqlalchemy/engine.py +++ b/ddtrace/contrib/internal/sqlalchemy/engine.py @@ -19,8 +19,8 @@ import ddtrace from ddtrace import config from ddtrace.constants import _ANALYTICS_SAMPLE_RATE_KEY +from ddtrace.constants import _SPAN_MEASURED_KEY from ddtrace.constants import SPAN_KIND -from ddtrace.constants import SPAN_MEASURED_KEY from ddtrace.ext import SpanKind from ddtrace.ext import SpanTypes from ddtrace.ext import db @@ -102,7 +102,7 @@ def _before_cur_exec(self, conn, cursor, statement, *args): # set span.kind to the type of operation being performed span.set_tag_str(SPAN_KIND, SpanKind.CLIENT) - span.set_tag(SPAN_MEASURED_KEY) + span.set_tag(_SPAN_MEASURED_KEY) if not _set_tags_from_url(span, conn.engine.url): _set_tags_from_cursor(span, self.vendor, cursor) diff --git a/ddtrace/contrib/internal/tornado/handlers.py b/ddtrace/contrib/internal/tornado/handlers.py index ff3a97cf2b8..3c4a046bfb9 100644 --- a/ddtrace/contrib/internal/tornado/handlers.py +++ b/ddtrace/contrib/internal/tornado/handlers.py @@ -4,8 +4,8 @@ from ddtrace import config from ddtrace.constants import _ANALYTICS_SAMPLE_RATE_KEY +from ddtrace.constants import _SPAN_MEASURED_KEY from ddtrace.constants import SPAN_KIND -from ddtrace.constants import SPAN_MEASURED_KEY from ddtrace.contrib import trace_utils from ddtrace.contrib.internal.trace_utils import set_http_meta from ddtrace.ext import SpanKind @@ -50,7 +50,7 @@ def execute(func, handler, args, kwargs): # set span.kind to the type of operation being performed request_span.set_tag_str(SPAN_KIND, SpanKind.SERVER) - request_span.set_tag(SPAN_MEASURED_KEY) + request_span.set_tag(_SPAN_MEASURED_KEY) # set analytics sample rate # DEV: tornado is special case maintains separate configuration from config api analytics_enabled = settings["analytics_enabled"] diff --git a/ddtrace/contrib/internal/vertica/patch.py b/ddtrace/contrib/internal/vertica/patch.py index b365ade8c05..b223a17275d 100644 --- a/ddtrace/contrib/internal/vertica/patch.py +++ b/ddtrace/contrib/internal/vertica/patch.py @@ -5,8 +5,8 @@ import ddtrace from ddtrace import config from ddtrace.constants import _ANALYTICS_SAMPLE_RATE_KEY +from ddtrace.constants import _SPAN_MEASURED_KEY from ddtrace.constants import SPAN_KIND -from ddtrace.constants import SPAN_MEASURED_KEY from ddtrace.contrib import trace_utils from ddtrace.ext import SpanKind from ddtrace.ext import SpanTypes @@ -233,7 +233,7 @@ def wrapper(wrapped, instance, args, kwargs): span.set_tag_str(SPAN_KIND, SpanKind.CLIENT) if conf.get("measured", False): - span.set_tag(SPAN_MEASURED_KEY) + span.set_tag(_SPAN_MEASURED_KEY) span.set_tags(pin.tags) if "span_start" in conf: diff --git a/ddtrace/contrib/openai/__init__.py b/ddtrace/contrib/openai/__init__.py index 88090b5f85a..da94047c2e8 100644 --- a/ddtrace/contrib/openai/__init__.py +++ b/ddtrace/contrib/openai/__init__.py @@ -248,7 +248,6 @@ Pin.override(openai, service="my-openai-service") """ # noqa: E501 - # Required to allow users to import from `ddtrace.contrib.openai.patch` directly import warnings as _w diff --git a/ddtrace/debugging/_signal/tracing.py b/ddtrace/debugging/_signal/tracing.py index 3c9eb3f447e..d509e336d52 100644 --- a/ddtrace/debugging/_signal/tracing.py +++ b/ddtrace/debugging/_signal/tracing.py @@ -4,7 +4,7 @@ import ddtrace from ddtrace._trace.span import Span -from ddtrace.constants import ORIGIN_KEY +from ddtrace.constants import _ORIGIN_KEY from ddtrace.debugging._expressions import DDExpressionEvaluationError from ddtrace.debugging._probe.model import Probe from ddtrace.debugging._probe.model import SpanDecorationFunctionProbe @@ -52,7 +52,7 @@ def enter(self, scope: t.Mapping[str, t.Any]) -> None: span.set_tags(probe.tags) # type: ignore[arg-type] span.set_tag_str(PROBE_ID_TAG_NAME, probe.probe_id) - span.set_tag_str(ORIGIN_KEY, "di") + span.set_tag_str(_ORIGIN_KEY, "di") def exit(self, retval: t.Any, exc_info: ExcInfoType, duration: float, scope: t.Mapping[str, t.Any]) -> None: if self._span_cm is not None: diff --git a/ddtrace/internal/_encoding.pyx b/ddtrace/internal/_encoding.pyx index f85fe7c6776..8db5bad7544 100644 --- a/ddtrace/internal/_encoding.pyx +++ b/ddtrace/internal/_encoding.pyx @@ -19,7 +19,7 @@ from ._utils cimport PyBytesLike_Check # DEV: This only occurs because there is a `constants.py` module # in both `ddtrace` and `ddtrace.internal` -from ..constants import ORIGIN_KEY +from ..constants import _ORIGIN_KEY as ORIGIN_KEY from .constants import SPAN_LINKS_KEY from .constants import SPAN_EVENTS_KEY from .constants import MAX_UINT_64BITS diff --git a/ddtrace/internal/processor/stats.py b/ddtrace/internal/processor/stats.py index b99c6aad526..295a6e289a2 100644 --- a/ddtrace/internal/processor/stats.py +++ b/ddtrace/internal/processor/stats.py @@ -11,7 +11,7 @@ from ddtrace.internal.native import DDSketch from ddtrace.internal.utils.retry import fibonacci_backoff_with_jitter -from ...constants import SPAN_MEASURED_KEY +from ...constants import _SPAN_MEASURED_KEY from .._encoding import packb from ..agent import get_connection from ..compat import get_connection_response @@ -38,7 +38,7 @@ def _is_measured(span): # type: (Span) -> bool """Return whether the span is flagged to be measured or not.""" - return span._metrics.get(SPAN_MEASURED_KEY) == 1 + return span._metrics.get(_SPAN_MEASURED_KEY) == 1 """ diff --git a/ddtrace/internal/sampling.py b/ddtrace/internal/sampling.py index 997d3af77fd..b1d3f7957f4 100644 --- a/ddtrace/internal/sampling.py +++ b/ddtrace/internal/sampling.py @@ -15,12 +15,12 @@ from typing_extensions import TypedDict from ddtrace._trace.sampling_rule import SamplingRule # noqa:F401 +from ddtrace.constants import _SAMPLING_AGENT_DECISION +from ddtrace.constants import _SAMPLING_RULE_DECISION from ddtrace.constants import _SINGLE_SPAN_SAMPLING_MAX_PER_SEC from ddtrace.constants import _SINGLE_SPAN_SAMPLING_MAX_PER_SEC_NO_LIMIT from ddtrace.constants import _SINGLE_SPAN_SAMPLING_MECHANISM from ddtrace.constants import _SINGLE_SPAN_SAMPLING_RATE -from ddtrace.constants import SAMPLING_AGENT_DECISION -from ddtrace.constants import SAMPLING_RULE_DECISION from ddtrace.internal.constants import _CATEGORY_TO_PRIORITIES from ddtrace.internal.constants import _KEEP_PRIORITY_INDEX from ddtrace.internal.constants import _REJECT_PRIORITY_INDEX @@ -282,18 +282,18 @@ def _set_sampling_tags(span, sampled, sample_rate, priority_category): # type: (Span, bool, float, str) -> None mechanism = SamplingMechanism.TRACE_SAMPLING_RULE if priority_category == PriorityCategory.RULE_DEFAULT: - span.set_metric(SAMPLING_RULE_DECISION, sample_rate) + span.set_metric(_SAMPLING_RULE_DECISION, sample_rate) if priority_category == PriorityCategory.RULE_CUSTOMER: - span.set_metric(SAMPLING_RULE_DECISION, sample_rate) + span.set_metric(_SAMPLING_RULE_DECISION, sample_rate) mechanism = SamplingMechanism.REMOTE_USER_RULE if priority_category == PriorityCategory.RULE_DYNAMIC: - span.set_metric(SAMPLING_RULE_DECISION, sample_rate) + span.set_metric(_SAMPLING_RULE_DECISION, sample_rate) mechanism = SamplingMechanism.REMOTE_DYNAMIC_RULE elif priority_category == PriorityCategory.DEFAULT: mechanism = SamplingMechanism.DEFAULT elif priority_category == PriorityCategory.AUTO: mechanism = SamplingMechanism.AGENT_RATE - span.set_metric(SAMPLING_AGENT_DECISION, sample_rate) + span.set_metric(_SAMPLING_AGENT_DECISION, sample_rate) priorities = _CATEGORY_TO_PRIORITIES[priority_category] _set_priority(span, priorities[_KEEP_PRIORITY_INDEX] if sampled else priorities[_REJECT_PRIORITY_INDEX]) set_sampling_decision_maker(span.context, mechanism) diff --git a/ddtrace/internal/schema/processor.py b/ddtrace/internal/schema/processor.py index 33d9b431c1b..91b0feff5dc 100644 --- a/ddtrace/internal/schema/processor.py +++ b/ddtrace/internal/schema/processor.py @@ -1,6 +1,6 @@ from ddtrace import config from ddtrace._trace.processor import TraceProcessor -from ddtrace.constants import BASE_SERVICE_KEY +from ddtrace.constants import _BASE_SERVICE_KEY from . import schematize_service_name @@ -22,4 +22,4 @@ def process_trace(self, trace): return trace def _update_dd_base_service(self, span): - span.set_tag_str(key=BASE_SERVICE_KEY, value=self._global_service) + span.set_tag_str(key=_BASE_SERVICE_KEY, value=self._global_service) diff --git a/ddtrace/internal/utils/http.py b/ddtrace/internal/utils/http.py index 7e85ce01356..f9c13827d3d 100644 --- a/ddtrace/internal/utils/http.py +++ b/ddtrace/internal/utils/http.py @@ -16,7 +16,7 @@ from typing import Tuple # noqa:F401 from typing import Union # noqa:F401 -from ddtrace.constants import USER_ID_KEY +from ddtrace.constants import _USER_ID_KEY from ddtrace.internal import compat from ddtrace.internal._unpatched import unpatched_open as open # noqa: A001 from ddtrace.internal.compat import parse @@ -164,13 +164,13 @@ def w3c_get_dd_list_member(context): "t.dm:{}".format((w3c_encode_tag((_W3C_TRACESTATE_INVALID_CHARS_REGEX_VALUE, "_", sampling_decision)))) ) # since this can change, we need to grab the value off the current span - usr_id = context._meta.get(USER_ID_KEY) + usr_id = context._meta.get(_USER_ID_KEY) if usr_id: tags.append("t.usr.id:{}".format(w3c_encode_tag((_W3C_TRACESTATE_INVALID_CHARS_REGEX_VALUE, "_", usr_id)))) current_tags_len = sum(len(i) for i in tags) for k, v in _get_metas_to_propagate(context): - if k not in [SAMPLING_DECISION_TRACE_TAG_KEY, USER_ID_KEY]: + if k not in [SAMPLING_DECISION_TRACE_TAG_KEY, _USER_ID_KEY]: # for key replace ",", "=", and characters outside the ASCII range 0x20 to 0x7E # for value replace ",", ";", "~" and characters outside the ASCII range 0x20 to 0x7E k = k.replace("_dd.p.", "t.") diff --git a/ddtrace/internal/writer/writer.py b/ddtrace/internal/writer/writer.py index 01b05515984..c494aa206a2 100644 --- a/ddtrace/internal/writer/writer.py +++ b/ddtrace/internal/writer/writer.py @@ -18,7 +18,7 @@ from ddtrace.settings.asm import config as asm_config from ddtrace.vendor.dogstatsd import DogStatsd -from ...constants import KEEP_SPANS_RATE_KEY +from ...constants import _KEEP_SPANS_RATE_KEY from ...internal.utils.formats import parse_tags_str from ...internal.utils.http import Response from ...internal.utils.time import StopWatch @@ -219,7 +219,7 @@ def _set_drop_rate(self) -> None: def _set_keep_rate(self, trace): if trace: - trace[0].set_metric(KEEP_SPANS_RATE_KEY, 1.0 - self._drop_sma.get()) + trace[0].set_metric(_KEEP_SPANS_RATE_KEY, 1.0 - self._drop_sma.get()) def _reset_connection(self) -> None: with self._conn_lck: diff --git a/ddtrace/llmobs/_integrations/base.py b/ddtrace/llmobs/_integrations/base.py index e7e405827b3..6b205202efd 100644 --- a/ddtrace/llmobs/_integrations/base.py +++ b/ddtrace/llmobs/_integrations/base.py @@ -9,13 +9,15 @@ from ddtrace import config from ddtrace._trace.sampler import RateSampler from ddtrace._trace.span import Span -from ddtrace.constants import SPAN_MEASURED_KEY +from ddtrace.constants import _SPAN_MEASURED_KEY from ddtrace.contrib.internal.trace_utils import int_service from ddtrace.ext import SpanTypes from ddtrace.internal.agent import get_stats_url from ddtrace.internal.dogstatsd import get_dogstatsd_client from ddtrace.internal.hostname import get_hostname from ddtrace.internal.logger import get_logger +from ddtrace.internal.telemetry import telemetry_writer +from ddtrace.internal.telemetry.constants import TELEMETRY_NAMESPACE from ddtrace.internal.utils.formats import asbool from ddtrace.llmobs._constants import PARENT_ID_KEY from ddtrace.llmobs._constants import PROPAGATED_PARENT_ID_KEY @@ -127,7 +129,7 @@ def trace(self, pin: Pin, operation_id: str, submit_to_llmobs: bool = False, **k span_type=SpanTypes.LLM if (submit_to_llmobs and self.llmobs_enabled) else None, ) # Enable trace metrics for these spans so users can see per-service openai usage in APM. - span.set_tag(SPAN_MEASURED_KEY) + span.set_tag(_SPAN_MEASURED_KEY) self._set_base_span_tags(span, **kwargs) if submit_to_llmobs and self.llmobs_enabled: if span.get_tag(PROPAGATED_PARENT_ID_KEY) is None: @@ -136,6 +138,15 @@ def trace(self, pin: Pin, operation_id: str, submit_to_llmobs: bool = False, **k # in these cases to avoid conflicting with the later propagated tags. parent_id = _get_llmobs_parent_id(span) or "undefined" span._set_ctx_item(PARENT_ID_KEY, str(parent_id)) + telemetry_writer.add_count_metric( + namespace=TELEMETRY_NAMESPACE.MLOBS, + name="span.start", + value=1, + tags=( + ("integration", self._integration_name), + ("autoinstrumented", "true"), + ), + ) return span @classmethod diff --git a/ddtrace/llmobs/_llmobs.py b/ddtrace/llmobs/_llmobs.py index 809afcf9011..768f4bdb292 100644 --- a/ddtrace/llmobs/_llmobs.py +++ b/ddtrace/llmobs/_llmobs.py @@ -27,6 +27,7 @@ from ddtrace.internal.service import ServiceStatusError from ddtrace.internal.telemetry import telemetry_writer from ddtrace.internal.telemetry.constants import TELEMETRY_APM_PRODUCT +from ddtrace.internal.telemetry.constants import TELEMETRY_NAMESPACE from ddtrace.internal.utils.formats import asbool from ddtrace.internal.utils.formats import parse_tags_str from ddtrace.llmobs import _constants as constants @@ -520,6 +521,15 @@ def _start_span( model_provider: Optional[str] = None, ml_app: Optional[str] = None, ) -> Span: + telemetry_writer.add_count_metric( + namespace=TELEMETRY_NAMESPACE.MLOBS, + name="span.start", + value=1, + tags=( + ("autoinstrumented", "false"), + ("kind", operation_kind), + ), + ) if name is None: name = operation_kind span = self.tracer.trace(name, resource=operation_kind, span_type=SpanTypes.LLM) diff --git a/ddtrace/settings/endpoint_config.py b/ddtrace/settings/endpoint_config.py index e721df65a10..aee1fdc5cad 100644 --- a/ddtrace/settings/endpoint_config.py +++ b/ddtrace/settings/endpoint_config.py @@ -5,9 +5,9 @@ """ import os -from ddtrace.constants import CONFIG_ENDPOINT_ENV -from ddtrace.constants import CONFIG_ENDPOINT_RETRIES_ENV -from ddtrace.constants import CONFIG_ENDPOINT_TIMEOUT_ENV +from ddtrace.constants import _CONFIG_ENDPOINT_ENV +from ddtrace.constants import _CONFIG_ENDPOINT_RETRIES_ENV +from ddtrace.constants import _CONFIG_ENDPOINT_TIMEOUT_ENV from ddtrace.internal.constants import DEFAULT_TIMEOUT from ddtrace.internal.logger import get_logger from ddtrace.internal.utils.http import Response @@ -20,10 +20,10 @@ RETRIES = 1 try: - if CONFIG_ENDPOINT_RETRIES_ENV in os.environ: - RETRIES = int(os.getenv(CONFIG_ENDPOINT_RETRIES_ENV, str(RETRIES))) + if _CONFIG_ENDPOINT_RETRIES_ENV in os.environ: + RETRIES = int(os.getenv(_CONFIG_ENDPOINT_RETRIES_ENV, str(RETRIES))) except ValueError: - log.error("Invalid value for %s. Using default value: %s", CONFIG_ENDPOINT_RETRIES_ENV, RETRIES) + log.error("Invalid value for %s. Using default value: %s", _CONFIG_ENDPOINT_RETRIES_ENV, RETRIES) def _get_retries(): @@ -32,10 +32,10 @@ def _get_retries(): TIMEOUT = DEFAULT_TIMEOUT try: - if CONFIG_ENDPOINT_TIMEOUT_ENV in os.environ: - TIMEOUT = int(os.getenv(CONFIG_ENDPOINT_TIMEOUT_ENV, str(TIMEOUT))) + if _CONFIG_ENDPOINT_TIMEOUT_ENV in os.environ: + TIMEOUT = int(os.getenv(_CONFIG_ENDPOINT_TIMEOUT_ENV, str(TIMEOUT))) except ValueError: - log.error("Invalid value for %s. Using default value: %s", CONFIG_ENDPOINT_TIMEOUT_ENV, TIMEOUT) + log.error("Invalid value for %s. Using default value: %s", _CONFIG_ENDPOINT_TIMEOUT_ENV, TIMEOUT) def _get_timeout(): @@ -59,7 +59,7 @@ def fetch_config_from_endpoint() -> dict: """ Fetch the configuration from the configuration endpoint. """ - config_endpoint = os.getenv(CONFIG_ENDPOINT_ENV, None) + config_endpoint = os.getenv(_CONFIG_ENDPOINT_ENV, None) if config_endpoint is None: log.debug("Configuration endpoint not set. Skipping fetching configuration.") diff --git a/releasenotes/notes/fix-openai-313-29ec43cbf2f35947.yaml b/releasenotes/notes/fix-openai-313-29ec43cbf2f35947.yaml new file mode 100644 index 00000000000..59d818de9a9 --- /dev/null +++ b/releasenotes/notes/fix-openai-313-29ec43cbf2f35947.yaml @@ -0,0 +1,7 @@ +--- +features: + - | + openai: Introduces tracing support to the OpenAI integration for Python versions 3.12 and 3.13. +fixes: + - | + openai: Fixes a patching issue where asynchronous moderation endpoint calls resulted in coroutine scheduling errors. diff --git a/releasenotes/notes/internalize-constants-3-0-73b6970b5a6f3aa5.yaml b/releasenotes/notes/internalize-constants-3-0-73b6970b5a6f3aa5.yaml new file mode 100644 index 00000000000..4f62108293e --- /dev/null +++ b/releasenotes/notes/internalize-constants-3-0-73b6970b5a6f3aa5.yaml @@ -0,0 +1,21 @@ +--- +deprecations: + - | + tracing: Deprecates the following constants in ``ddtrace.constants`` module: + - ANALYTICS_SAMPLE_RATE_KEY + - SAMPLE_RATE_METRIC_KEY + - SAMPLING_PRIORITY_KEY + - SAMPLING_AGENT_DECISION + - SAMPLING_RULE_DECISION + - SAMPLING_LIMIT_DECISION + - ORIGIN_KEY + - USER_ID_KEY + - HOSTNAME_KEY + - RUNTIME_FAMILY + - BASE_SERVICE_KEY + - SPAN_MEASURED_KEY + - KEEP_SPANS_RATE_KEY + - MULTIPLE_IP_HEADERS + - CONFIG_ENDPOINT_ENV + - CONFIG_ENDPOINT_RETRIES_ENV + - CONFIG_ENDPOINT_TIMEOUT_ENV diff --git a/riotfile.py b/riotfile.py index aa51b9349a6..bf3e0eede96 100644 --- a/riotfile.py +++ b/riotfile.py @@ -2504,18 +2504,26 @@ def select_pys(min_version: str = MIN_PYTHON_VERSION, max_version: str = MAX_PYT }, ), Venv( - pys=select_pys(min_version="3.7", max_version="3.11"), + pys="3.7", pkgs={ - "openai[embeddings,datalib]": ["==1.1.1", "==1.30.1"], + "openai[datalib]": "==1.30.1", "pillow": "==9.5.0", }, ), Venv( pys=select_pys(min_version="3.8", max_version="3.11"), pkgs={ - "openai[datalib]": ["==1.30.1"], + "openai[embeddings,datalib]": "==1.30.1", + "pillow": "==9.5.0", + "httpx": "==0.27.2", + }, + ), + Venv( + pys=select_pys(min_version="3.8"), + pkgs={ + "openai": latest, "tiktoken": latest, - "pillow": "==10.1.0", + "pillow": latest, }, env={"TIKTOKEN_AVAILABLE": "True"}, ), diff --git a/tests/appsec/iast/test_processor.py b/tests/appsec/iast/test_processor.py index d35b548b216..3bb5eaa5015 100644 --- a/tests/appsec/iast/test_processor.py +++ b/tests/appsec/iast/test_processor.py @@ -5,8 +5,8 @@ from ddtrace.appsec._constants import IAST from ddtrace.appsec._iast import oce from ddtrace.appsec._iast._iast_request_context import get_iast_reporter +from ddtrace.constants import _SAMPLING_PRIORITY_KEY from ddtrace.constants import AUTO_KEEP -from ddtrace.constants import SAMPLING_PRIORITY_KEY from ddtrace.constants import USER_KEEP from ddtrace.ext import SpanTypes from tests.utils import DummyTracer @@ -61,7 +61,7 @@ def test_appsec_iast_processor_ensure_span_is_manual_keep(iast_context_defaults, result = span.get_tag(IAST.JSON) assert len(json.loads(result)["vulnerabilities"]) == 1 - assert span.get_metric(SAMPLING_PRIORITY_KEY) is USER_KEEP + assert span.get_metric(_SAMPLING_PRIORITY_KEY) is USER_KEEP @pytest.mark.skip_iast_check_logs @@ -87,9 +87,9 @@ def test_appsec_iast_processor_ensure_span_is_sampled(iast_context_defaults, sam result = span.get_tag(IAST.JSON) if sampling_rate == 0.0: assert result is None - assert span.get_metric(SAMPLING_PRIORITY_KEY) is AUTO_KEEP + assert span.get_metric(_SAMPLING_PRIORITY_KEY) is AUTO_KEEP assert span.get_metric(IAST.ENABLED) == 0.0 else: assert len(json.loads(result)["vulnerabilities"]) == 1 - assert span.get_metric(SAMPLING_PRIORITY_KEY) is USER_KEEP + assert span.get_metric(_SAMPLING_PRIORITY_KEY) is USER_KEEP assert span.get_metric(IAST.ENABLED) == 1.0 diff --git a/tests/contrib/aiohttp/test_middleware.py b/tests/contrib/aiohttp/test_middleware.py index 30d40654314..097548d7b2b 100644 --- a/tests/contrib/aiohttp/test_middleware.py +++ b/tests/contrib/aiohttp/test_middleware.py @@ -4,8 +4,8 @@ import pytest from ddtrace._trace.sampler import RateSampler +from ddtrace.constants import _SAMPLING_PRIORITY_KEY from ddtrace.constants import ERROR_MSG -from ddtrace.constants import SAMPLING_PRIORITY_KEY from ddtrace.constants import USER_KEEP from ddtrace.contrib.internal.aiohttp.middlewares import CONFIG_KEY from ddtrace.contrib.internal.aiohttp.middlewares import trace_app @@ -381,7 +381,7 @@ async def test_distributed_tracing(app_tracer, aiohttp_client): # with the right trace_id and parent_id assert span.trace_id == 100 assert span.parent_id == 42 - assert span.get_metric(SAMPLING_PRIORITY_KEY) is USER_KEEP + assert span.get_metric(_SAMPLING_PRIORITY_KEY) is USER_KEEP @flaky(1735812000) @@ -408,7 +408,7 @@ async def test_distributed_tracing_with_sampling_true(app_tracer, aiohttp_client # with the right trace_id and parent_id assert 100 == span.trace_id assert 42 == span.parent_id - assert 1 == span.get_metric(SAMPLING_PRIORITY_KEY) + assert 1 == span.get_metric(_SAMPLING_PRIORITY_KEY) @flaky(1735812000) @@ -435,7 +435,7 @@ async def test_distributed_tracing_with_sampling_false(app_tracer, aiohttp_clien # with the right trace_id and parent_id assert 100 == span.trace_id assert 42 == span.parent_id - assert 0 == span.get_metric(SAMPLING_PRIORITY_KEY) + assert 0 == span.get_metric(_SAMPLING_PRIORITY_KEY) async def test_distributed_tracing_disabled(app_tracer, aiohttp_client): @@ -487,11 +487,11 @@ async def test_distributed_tracing_sub_span(app_tracer, aiohttp_client): # with the right trace_id and parent_id assert 100 == span.trace_id assert 42 == span.parent_id - assert 0 == span.get_metric(SAMPLING_PRIORITY_KEY) + assert 0 == span.get_metric(_SAMPLING_PRIORITY_KEY) # check parenting is OK with custom sub-span created within server code assert 100 == sub_span.trace_id assert span.span_id == sub_span.parent_id - assert sub_span.get_metric(SAMPLING_PRIORITY_KEY) is None + assert sub_span.get_metric(_SAMPLING_PRIORITY_KEY) is None def _assert_200_parenting(client, traces): diff --git a/tests/contrib/cherrypy/test_middleware.py b/tests/contrib/cherrypy/test_middleware.py index 000f15610a0..9bc4a600136 100644 --- a/tests/contrib/cherrypy/test_middleware.py +++ b/tests/contrib/cherrypy/test_middleware.py @@ -11,10 +11,10 @@ import ddtrace from ddtrace import config +from ddtrace.constants import _SAMPLING_PRIORITY_KEY from ddtrace.constants import ERROR_MSG from ddtrace.constants import ERROR_STACK from ddtrace.constants import ERROR_TYPE -from ddtrace.constants import SAMPLING_PRIORITY_KEY from ddtrace.contrib.internal.cherrypy.middleware import TraceMiddleware from ddtrace.ext import http from tests.contrib.patch import emit_integration_and_version_to_test_agent @@ -286,7 +286,7 @@ def test_propagation(self): # ensure the propagation worked well assert s.trace_id == 1234 assert s.parent_id == 4567 - assert s.get_metric(SAMPLING_PRIORITY_KEY) == 2 + assert s.get_metric(_SAMPLING_PRIORITY_KEY) == 2 def test_disabled_distributed_tracing_config(self): previous_distributed_tracing = config.cherrypy["distributed_tracing"] @@ -313,7 +313,7 @@ def test_disabled_distributed_tracing_config(self): # ensure the propagation worked well assert s.trace_id != 1234 assert s.parent_id != 4567 - assert s.get_metric(SAMPLING_PRIORITY_KEY) != 2 + assert s.get_metric(_SAMPLING_PRIORITY_KEY) != 2 config.cherrypy["distributed_tracing"] = previous_distributed_tracing @@ -342,7 +342,7 @@ def test_disabled_distributed_tracing_middleware(self): # ensure the propagation worked well assert s.trace_id != 1234 assert s.parent_id != 4567 - assert s.get_metric(SAMPLING_PRIORITY_KEY) != 2 + assert s.get_metric(_SAMPLING_PRIORITY_KEY) != 2 cherrypy.tools.tracer.use_distributed_tracing = previous_distributed_tracing diff --git a/tests/contrib/django/test_django.py b/tests/contrib/django/test_django.py index 7b8a0e18ef7..79baceb1652 100644 --- a/tests/contrib/django/test_django.py +++ b/tests/contrib/django/test_django.py @@ -18,10 +18,10 @@ import wrapt from ddtrace import config +from ddtrace.constants import _SAMPLING_PRIORITY_KEY from ddtrace.constants import ERROR_MSG from ddtrace.constants import ERROR_STACK from ddtrace.constants import ERROR_TYPE -from ddtrace.constants import SAMPLING_PRIORITY_KEY from ddtrace.constants import USER_KEEP from ddtrace.contrib import trace_utils from ddtrace.contrib.internal.django.patch import instrument_view @@ -1729,7 +1729,7 @@ def test_django_request_distributed(client, test_spans): trace_id=12345, parent_id=78910, metrics={ - SAMPLING_PRIORITY_KEY: USER_KEEP, + _SAMPLING_PRIORITY_KEY: USER_KEEP, }, ) assert root.get_tag("span.kind") == "server" diff --git a/tests/contrib/gevent/test_tracer.py b/tests/contrib/gevent/test_tracer.py index c34f06d41d6..d804a4e9c59 100644 --- a/tests/contrib/gevent/test_tracer.py +++ b/tests/contrib/gevent/test_tracer.py @@ -6,7 +6,7 @@ import ddtrace from ddtrace.constants import ERROR_MSG -from ddtrace.constants import SAMPLING_PRIORITY_KEY +from ddtrace.constants import _SAMPLING_PRIORITY_KEY from ddtrace.constants import USER_KEEP from ddtrace._trace.context import Context from ddtrace.contrib.internal.gevent.patch import patch @@ -143,9 +143,9 @@ def green_2(): worker_1 = spans[1] worker_2 = spans[2] # check sampling priority - assert parent_span.get_metric(SAMPLING_PRIORITY_KEY) == USER_KEEP - assert worker_1.get_metric(SAMPLING_PRIORITY_KEY) is None - assert worker_2.get_metric(SAMPLING_PRIORITY_KEY) is None + assert parent_span.get_metric(_SAMPLING_PRIORITY_KEY) == USER_KEEP + assert worker_1.get_metric(_SAMPLING_PRIORITY_KEY) is None + assert worker_2.get_metric(_SAMPLING_PRIORITY_KEY) is None def test_trace_spawn_multiple_greenlets_multiple_traces(self): # multiple greenlets must be part of the same trace diff --git a/tests/contrib/openai/cassettes/v1/completion_stream_wrong_api_key.yaml b/tests/contrib/openai/cassettes/v1/completion_stream_wrong_api_key.yaml new file mode 100644 index 00000000000..512263ce56c --- /dev/null +++ b/tests/contrib/openai/cassettes/v1/completion_stream_wrong_api_key.yaml @@ -0,0 +1,77 @@ +interactions: +- request: + body: '{"model":"text-curie-001","prompt":"how does openai tokenize prompts?","max_tokens":150,"n":1,"stream":true,"temperature":0.8}' + headers: + accept: + - application/json + accept-encoding: + - gzip, deflate + connection: + - keep-alive + content-length: + - '126' + content-type: + - application/json + host: + - api.openai.com + user-agent: + - OpenAI/Python 1.59.7 + x-stainless-arch: + - arm64 + x-stainless-async: + - 'false' + x-stainless-lang: + - python + x-stainless-os: + - MacOS + x-stainless-package-version: + - 1.59.7 + x-stainless-retry-count: + - '0' + x-stainless-runtime: + - CPython + x-stainless-runtime-version: + - 3.13.1 + method: POST + uri: https://api.openai.com/v1/completions + response: + body: + string: "{\n \"error\": {\n \"message\": \"Incorrect API key provided: + sk-wrong****-key. You can find your API key at https://platform.openai.com/account/api-keys.\",\n + \ \"type\": \"invalid_request_error\",\n \"param\": null,\n \"code\": + \"invalid_api_key\"\n }\n}\n" + headers: + CF-Cache-Status: + - DYNAMIC + CF-RAY: + - 9058b3cc3bcdd63c-IAD + Connection: + - keep-alive + Content-Length: + - '266' + Content-Type: + - application/json; charset=utf-8 + Date: + - Tue, 21 Jan 2025 16:32:48 GMT + Server: + - cloudflare + Set-Cookie: + - __cf_bm=WUZdhCkUNTJUEkju8qgk4MKCHL7CFOaIUNvU0L9XmvA-1737477168-1.0.1.1-RJ7MOiDyJEfHrXSN0WQVgZFtkxlkwBL3p.5t3._uu77WPJSM8tYzI3wMHSu.yMwD9QkrbgR5yavkTN.RTWl_1A; + path=/; expires=Tue, 21-Jan-25 17:02:48 GMT; domain=.api.openai.com; HttpOnly; + Secure; SameSite=None + - _cfuvid=7KOfpy1ICNI532AjhDxBh2qtnyNpsjauHeWi6dEJgT4-1737477168271-0.0.1.1-604800000; + path=/; domain=.api.openai.com; HttpOnly; Secure; SameSite=None + X-Content-Type-Options: + - nosniff + alt-svc: + - h3=":443"; ma=86400 + strict-transport-security: + - max-age=31536000; includeSubDomains; preload + vary: + - Origin + x-request-id: + - req_c45bfc7515dca54ef87c667f8210af23 + status: + code: 401 + message: Unauthorized +version: 1 diff --git a/tests/contrib/openai/test_openai_llmobs.py b/tests/contrib/openai/test_openai_llmobs.py index a145877c8c8..4c15b1ffad3 100644 --- a/tests/contrib/openai/test_openai_llmobs.py +++ b/tests/contrib/openai/test_openai_llmobs.py @@ -339,6 +339,10 @@ def test_completion(self, openai, ddtrace_global_config, mock_llmobs_writer, moc ) ) + @pytest.mark.skipif( + parse_version(openai_module.version.VERSION) >= (1, 60), + reason="latest openai versions use modified azure requests", + ) def test_completion_azure( self, openai, azure_openai_config, ddtrace_global_config, mock_llmobs_writer, mock_tracer ): @@ -369,6 +373,10 @@ def test_completion_azure( ) ) + @pytest.mark.skipif( + parse_version(openai_module.version.VERSION) >= (1, 60), + reason="latest openai versions use modified azure requests", + ) async def test_completion_azure_async( self, openai, azure_openai_config, ddtrace_global_config, mock_llmobs_writer, mock_tracer ): @@ -458,6 +466,10 @@ def test_chat_completion(self, openai, ddtrace_global_config, mock_llmobs_writer ) ) + @pytest.mark.skipif( + parse_version(openai_module.version.VERSION) >= (1, 60), + reason="latest openai versions use modified azure requests", + ) def test_chat_completion_azure( self, openai, azure_openai_config, ddtrace_global_config, mock_llmobs_writer, mock_tracer ): @@ -488,6 +500,10 @@ def test_chat_completion_azure( ) ) + @pytest.mark.skipif( + parse_version(openai_module.version.VERSION) >= (1, 60), + reason="latest openai versions use modified azure requests", + ) async def test_chat_completion_azure_async( self, openai, azure_openai_config, ddtrace_global_config, mock_llmobs_writer, mock_tracer ): diff --git a/tests/contrib/openai/test_openai_patch.py b/tests/contrib/openai/test_openai_patch.py index caab79117cf..6a995213180 100644 --- a/tests/contrib/openai/test_openai_patch.py +++ b/tests/contrib/openai/test_openai_patch.py @@ -3,14 +3,10 @@ # removed the ``_generated`` suffix from the file name, to prevent the content # from being overwritten by future re-generations. +from ddtrace.contrib.internal.openai.patch import OPENAI_VERSION from ddtrace.contrib.internal.openai.patch import get_version from ddtrace.contrib.internal.openai.patch import patch - - -try: - from ddtrace.contrib.internal.openai.patch import unpatch -except ImportError: - unpatch = None +from ddtrace.contrib.internal.openai.patch import unpatch from tests.contrib.patch import PatchTestCase @@ -22,10 +18,268 @@ class TestOpenaiPatch(PatchTestCase.Base): __get_version__ = get_version def assert_module_patched(self, openai): - pass + if OPENAI_VERSION >= (1, 0, 0): + if OPENAI_VERSION >= (1, 8, 0): + self.assert_wrapped(openai._base_client.SyncAPIClient._process_response) + self.assert_wrapped(openai._base_client.AsyncAPIClient._process_response) + else: + self.assert_wrapped(openai._base_client.BaseClient._process_response) + self.assert_wrapped(openai.OpenAI.__init__) + self.assert_wrapped(openai.AsyncOpenAI.__init__) + self.assert_wrapped(openai.AzureOpenAI.__init__) + self.assert_wrapped(openai.AsyncAzureOpenAI.__init__) + self.assert_wrapped(openai.resources.models.Models.list) + self.assert_wrapped(openai.resources.models.Models.retrieve) + self.assert_wrapped(openai.resources.models.Models.delete) + self.assert_wrapped(openai.resources.models.AsyncModels.list) + self.assert_wrapped(openai.resources.models.AsyncModels.retrieve) + self.assert_wrapped(openai.resources.models.AsyncModels.delete) + self.assert_wrapped(openai.resources.completions.Completions.create) + self.assert_wrapped(openai.resources.chat.Completions.create) + self.assert_wrapped(openai.resources.completions.AsyncCompletions.create) + self.assert_wrapped(openai.resources.chat.AsyncCompletions.create) + self.assert_wrapped(openai.resources.images.Images.generate) + self.assert_wrapped(openai.resources.images.Images.edit) + self.assert_wrapped(openai.resources.images.Images.create_variation) + self.assert_wrapped(openai.resources.images.AsyncImages.generate) + self.assert_wrapped(openai.resources.images.AsyncImages.edit) + self.assert_wrapped(openai.resources.images.AsyncImages.create_variation) + self.assert_wrapped(openai.resources.audio.Transcriptions.create) + self.assert_wrapped(openai.resources.audio.Translations.create) + self.assert_wrapped(openai.resources.audio.AsyncTranscriptions.create) + self.assert_wrapped(openai.resources.audio.AsyncTranslations.create) + self.assert_wrapped(openai.resources.embeddings.Embeddings.create) + self.assert_wrapped(openai.resources.moderations.Moderations.create) + self.assert_wrapped(openai.resources.embeddings.AsyncEmbeddings.create) + self.assert_wrapped(openai.resources.moderations.AsyncModerations.create) + self.assert_wrapped(openai.resources.files.Files.create) + self.assert_wrapped(openai.resources.files.Files.retrieve) + self.assert_wrapped(openai.resources.files.Files.list) + self.assert_wrapped(openai.resources.files.Files.delete) + self.assert_wrapped(openai.resources.files.Files.retrieve_content) + self.assert_wrapped(openai.resources.files.AsyncFiles.create) + self.assert_wrapped(openai.resources.files.AsyncFiles.retrieve) + self.assert_wrapped(openai.resources.files.AsyncFiles.list) + self.assert_wrapped(openai.resources.files.AsyncFiles.delete) + self.assert_wrapped(openai.resources.files.AsyncFiles.retrieve_content) + else: + self.assert_wrapped(openai.api_resources.completion.Completion.create) + self.assert_wrapped(openai.api_resources.completion.Completion.acreate) + self.assert_wrapped(openai.api_requestor._make_session) + self.assert_wrapped(openai.util.convert_to_openai_object) + self.assert_wrapped(openai.api_resources.embedding.Embedding.create) + self.assert_wrapped(openai.api_resources.embedding.Embedding.acreate) + if hasattr(openai, "Model"): + self.assert_wrapped(openai.api_resources.model.Model.list) + self.assert_wrapped(openai.api_resources.model.Model.retrieve) + self.assert_wrapped(openai.api_resources.model.Model.delete) + self.assert_wrapped(openai.api_resources.model.Model.alist) + self.assert_wrapped(openai.api_resources.model.Model.aretrieve) + self.assert_wrapped(openai.api_resources.model.Model.adelete) + if hasattr(openai, "ChatCompletion"): + self.assert_wrapped(openai.api_resources.chat_completion.ChatCompletion.create) + self.assert_wrapped(openai.api_resources.chat_completion.ChatCompletion.acreate) + if hasattr(openai, "Image"): + self.assert_wrapped(openai.api_resources.image.Image.create) + self.assert_wrapped(openai.api_resources.image.Image.acreate) + self.assert_wrapped(openai.api_resources.image.Image.create_edit) + self.assert_wrapped(openai.api_resources.image.Image.acreate_edit) + self.assert_wrapped(openai.api_resources.image.Image.create_variation) + self.assert_wrapped(openai.api_resources.image.Image.acreate_variation) + if hasattr(openai, "Audio"): + self.assert_wrapped(openai.api_resources.audio.Audio.transcribe) + self.assert_wrapped(openai.api_resources.audio.Audio.atranscribe) + self.assert_wrapped(openai.api_resources.audio.Audio.translate) + self.assert_wrapped(openai.api_resources.audio.Audio.atranslate) + if hasattr(openai, "Moderation"): + self.assert_wrapped(openai.api_resources.moderation.Moderation.create) + self.assert_wrapped(openai.api_resources.moderation.Moderation.acreate) + if hasattr(openai, "File"): + self.assert_wrapped(openai.api_resources.file.File.create) + self.assert_wrapped(openai.api_resources.file.File.retrieve) + self.assert_wrapped(openai.api_resources.file.File.list) + self.assert_wrapped(openai.api_resources.file.File.delete) + self.assert_wrapped(openai.api_resources.file.File.download) + self.assert_wrapped(openai.api_resources.file.File.acreate) + self.assert_wrapped(openai.api_resources.file.File.aretrieve) + self.assert_wrapped(openai.api_resources.file.File.alist) + self.assert_wrapped(openai.api_resources.file.File.adelete) + self.assert_wrapped(openai.api_resources.file.File.adownload) def assert_not_module_patched(self, openai): - pass + if OPENAI_VERSION >= (1, 0, 0): + if OPENAI_VERSION >= (1, 8, 0): + self.assert_not_wrapped(openai._base_client.SyncAPIClient._process_response) + self.assert_not_wrapped(openai._base_client.AsyncAPIClient._process_response) + else: + self.assert_not_wrapped(openai._base_client.BaseClient._process_response) + self.assert_not_wrapped(openai.OpenAI.__init__) + self.assert_not_wrapped(openai.AsyncOpenAI.__init__) + self.assert_not_wrapped(openai.AzureOpenAI.__init__) + self.assert_not_wrapped(openai.AsyncAzureOpenAI.__init__) + self.assert_not_wrapped(openai.resources.models.Models.list) + self.assert_not_wrapped(openai.resources.models.Models.retrieve) + self.assert_not_wrapped(openai.resources.models.Models.delete) + self.assert_not_wrapped(openai.resources.models.AsyncModels.list) + self.assert_not_wrapped(openai.resources.models.AsyncModels.retrieve) + self.assert_not_wrapped(openai.resources.models.AsyncModels.delete) + self.assert_not_wrapped(openai.resources.completions.Completions.create) + self.assert_not_wrapped(openai.resources.chat.Completions.create) + self.assert_not_wrapped(openai.resources.completions.AsyncCompletions.create) + self.assert_not_wrapped(openai.resources.chat.AsyncCompletions.create) + self.assert_not_wrapped(openai.resources.images.Images.generate) + self.assert_not_wrapped(openai.resources.images.Images.edit) + self.assert_not_wrapped(openai.resources.images.Images.create_variation) + self.assert_not_wrapped(openai.resources.images.AsyncImages.generate) + self.assert_not_wrapped(openai.resources.images.AsyncImages.edit) + self.assert_not_wrapped(openai.resources.images.AsyncImages.create_variation) + self.assert_not_wrapped(openai.resources.audio.Transcriptions.create) + self.assert_not_wrapped(openai.resources.audio.Translations.create) + self.assert_not_wrapped(openai.resources.audio.AsyncTranscriptions.create) + self.assert_not_wrapped(openai.resources.audio.AsyncTranslations.create) + self.assert_not_wrapped(openai.resources.embeddings.Embeddings.create) + self.assert_not_wrapped(openai.resources.moderations.Moderations.create) + self.assert_not_wrapped(openai.resources.embeddings.AsyncEmbeddings.create) + self.assert_not_wrapped(openai.resources.moderations.AsyncModerations.create) + self.assert_not_wrapped(openai.resources.files.Files.create) + self.assert_not_wrapped(openai.resources.files.Files.retrieve) + self.assert_not_wrapped(openai.resources.files.Files.list) + self.assert_not_wrapped(openai.resources.files.Files.delete) + self.assert_not_wrapped(openai.resources.files.AsyncFiles.retrieve_content) + self.assert_not_wrapped(openai.resources.files.AsyncFiles.create) + self.assert_not_wrapped(openai.resources.files.AsyncFiles.retrieve) + self.assert_not_wrapped(openai.resources.files.AsyncFiles.list) + self.assert_not_wrapped(openai.resources.files.AsyncFiles.delete) + self.assert_not_wrapped(openai.resources.files.AsyncFiles.retrieve_content) + else: + self.assert_not_wrapped(openai.api_resources.completion.Completion.create) + self.assert_not_wrapped(openai.api_resources.completion.Completion.acreate) + self.assert_not_wrapped(openai.api_requestor._make_session) + self.assert_not_wrapped(openai.util.convert_to_openai_object) + self.assert_not_wrapped(openai.api_resources.embedding.Embedding.create) + self.assert_not_wrapped(openai.api_resources.embedding.Embedding.acreate) + if hasattr(openai, "Model"): + self.assert_not_wrapped(openai.api_resources.model.Model.list) + self.assert_not_wrapped(openai.api_resources.model.Model.retrieve) + self.assert_not_wrapped(openai.api_resources.model.Model.delete) + self.assert_not_wrapped(openai.api_resources.model.Model.alist) + self.assert_not_wrapped(openai.api_resources.model.Model.aretrieve) + self.assert_not_wrapped(openai.api_resources.model.Model.adelete) + if hasattr(openai, "ChatCompletion"): + self.assert_not_wrapped(openai.api_resources.chat_completion.ChatCompletion.create) + self.assert_not_wrapped(openai.api_resources.chat_completion.ChatCompletion.acreate) + if hasattr(openai, "Image"): + self.assert_not_wrapped(openai.api_resources.image.Image.create) + self.assert_not_wrapped(openai.api_resources.image.Image.acreate) + self.assert_not_wrapped(openai.api_resources.image.Image.create_edit) + self.assert_not_wrapped(openai.api_resources.image.Image.acreate_edit) + self.assert_not_wrapped(openai.api_resources.image.Image.create_variation) + self.assert_not_wrapped(openai.api_resources.image.Image.acreate_variation) + if hasattr(openai, "Audio"): + self.assert_not_wrapped(openai.api_resources.audio.Audio.transcribe) + self.assert_not_wrapped(openai.api_resources.audio.Audio.atranscribe) + self.assert_not_wrapped(openai.api_resources.audio.Audio.translate) + self.assert_not_wrapped(openai.api_resources.audio.Audio.atranslate) + if hasattr(openai, "Moderation"): + self.assert_not_wrapped(openai.api_resources.moderation.Moderation.create) + self.assert_not_wrapped(openai.api_resources.moderation.Moderation.acreate) + if hasattr(openai, "File"): + self.assert_not_wrapped(openai.api_resources.file.File.create) + self.assert_not_wrapped(openai.api_resources.file.File.retrieve) + self.assert_not_wrapped(openai.api_resources.file.File.list) + self.assert_not_wrapped(openai.api_resources.file.File.delete) + self.assert_not_wrapped(openai.api_resources.file.File.download) + self.assert_not_wrapped(openai.api_resources.file.File.acreate) + self.assert_not_wrapped(openai.api_resources.file.File.aretrieve) + self.assert_not_wrapped(openai.api_resources.file.File.alist) + self.assert_not_wrapped(openai.api_resources.file.File.adelete) + self.assert_not_wrapped(openai.api_resources.file.File.adownload) def assert_not_module_double_patched(self, openai): - pass + if OPENAI_VERSION >= (1, 0, 0): + if OPENAI_VERSION >= (1, 8, 0): + self.assert_not_double_wrapped(openai._base_client.SyncAPIClient._process_response) + self.assert_not_double_wrapped(openai._base_client.AsyncAPIClient._process_response) + else: + self.assert_not_double_wrapped(openai._base_client.BaseClient._process_response) + self.assert_not_double_wrapped(openai.OpenAI.__init__) + self.assert_not_double_wrapped(openai.AsyncOpenAI.__init__) + self.assert_not_double_wrapped(openai.AzureOpenAI.__init__) + self.assert_not_double_wrapped(openai.AsyncAzureOpenAI.__init__) + self.assert_not_double_wrapped(openai.resources.models.Models.list) + self.assert_not_double_wrapped(openai.resources.models.Models.retrieve) + self.assert_not_double_wrapped(openai.resources.models.Models.delete) + self.assert_not_double_wrapped(openai.resources.models.AsyncModels.list) + self.assert_not_double_wrapped(openai.resources.models.AsyncModels.retrieve) + self.assert_not_double_wrapped(openai.resources.models.AsyncModels.delete) + self.assert_not_double_wrapped(openai.resources.completions.Completions.create) + self.assert_not_double_wrapped(openai.resources.chat.Completions.create) + self.assert_not_double_wrapped(openai.resources.completions.AsyncCompletions.create) + self.assert_not_double_wrapped(openai.resources.chat.AsyncCompletions.create) + self.assert_not_double_wrapped(openai.resources.images.Images.generate) + self.assert_not_double_wrapped(openai.resources.images.Images.edit) + self.assert_not_double_wrapped(openai.resources.images.Images.create_variation) + self.assert_not_double_wrapped(openai.resources.images.AsyncImages.generate) + self.assert_not_double_wrapped(openai.resources.images.AsyncImages.edit) + self.assert_not_double_wrapped(openai.resources.images.AsyncImages.create_variation) + self.assert_not_double_wrapped(openai.resources.audio.Transcriptions.create) + self.assert_not_double_wrapped(openai.resources.audio.Translations.create) + self.assert_not_double_wrapped(openai.resources.audio.AsyncTranscriptions.create) + self.assert_not_double_wrapped(openai.resources.audio.AsyncTranslations.create) + self.assert_not_double_wrapped(openai.resources.embeddings.Embeddings.create) + self.assert_not_double_wrapped(openai.resources.moderations.Moderations.create) + self.assert_not_double_wrapped(openai.resources.embeddings.AsyncEmbeddings.create) + self.assert_not_double_wrapped(openai.resources.moderations.AsyncModerations.create) + self.assert_not_double_wrapped(openai.resources.files.Files.create) + self.assert_not_double_wrapped(openai.resources.files.Files.retrieve) + self.assert_not_double_wrapped(openai.resources.files.Files.list) + self.assert_not_double_wrapped(openai.resources.files.Files.delete) + self.assert_not_double_wrapped(openai.resources.files.Files.retrieve_content) + self.assert_not_double_wrapped(openai.resources.files.AsyncFiles.create) + self.assert_not_double_wrapped(openai.resources.files.AsyncFiles.retrieve) + self.assert_not_double_wrapped(openai.resources.files.AsyncFiles.list) + self.assert_not_double_wrapped(openai.resources.files.AsyncFiles.delete) + self.assert_not_double_wrapped(openai.resources.files.AsyncFiles.retrieve_content) + else: + self.assert_not_double_wrapped(openai.api_resources.completion.Completion.create) + self.assert_not_double_wrapped(openai.api_resources.completion.Completion.acreate) + self.assert_not_double_wrapped(openai.api_requestor._make_session) + self.assert_not_double_wrapped(openai.util.convert_to_openai_object) + self.assert_not_double_wrapped(openai.api_resources.embedding.Embedding.create) + self.assert_not_double_wrapped(openai.api_resources.embedding.Embedding.acreate) + if hasattr(openai, "Model"): + self.assert_not_double_wrapped(openai.api_resources.model.Model.list) + self.assert_not_double_wrapped(openai.api_resources.model.Model.retrieve) + self.assert_not_double_wrapped(openai.api_resources.model.Model.delete) + self.assert_not_double_wrapped(openai.api_resources.model.Model.alist) + self.assert_not_double_wrapped(openai.api_resources.model.Model.aretrieve) + self.assert_not_double_wrapped(openai.api_resources.model.Model.adelete) + if hasattr(openai, "ChatCompletion"): + self.assert_not_double_wrapped(openai.api_resources.chat_completion.ChatCompletion.create) + self.assert_not_double_wrapped(openai.api_resources.chat_completion.ChatCompletion.acreate) + if hasattr(openai, "Image"): + self.assert_not_double_wrapped(openai.api_resources.image.Image.create) + self.assert_not_double_wrapped(openai.api_resources.image.Image.acreate) + self.assert_not_double_wrapped(openai.api_resources.image.Image.create_edit) + self.assert_not_double_wrapped(openai.api_resources.image.Image.acreate_edit) + self.assert_not_double_wrapped(openai.api_resources.image.Image.create_variation) + self.assert_not_double_wrapped(openai.api_resources.image.Image.acreate_variation) + if hasattr(openai, "Audio"): + self.assert_not_double_wrapped(openai.api_resources.audio.Audio.transcribe) + self.assert_not_double_wrapped(openai.api_resources.audio.Audio.atranscribe) + self.assert_not_double_wrapped(openai.api_resources.audio.Audio.translate) + self.assert_not_double_wrapped(openai.api_resources.audio.Audio.atranslate) + if hasattr(openai, "Moderation"): + self.assert_not_double_wrapped(openai.api_resources.moderation.Moderation.create) + self.assert_not_double_wrapped(openai.api_resources.moderation.Moderation.acreate) + if hasattr(openai, "File"): + self.assert_not_double_wrapped(openai.api_resources.file.File.create) + self.assert_not_double_wrapped(openai.api_resources.file.File.retrieve) + self.assert_not_double_wrapped(openai.api_resources.file.File.list) + self.assert_not_double_wrapped(openai.api_resources.file.File.delete) + self.assert_not_double_wrapped(openai.api_resources.file.File.download) + self.assert_not_double_wrapped(openai.api_resources.file.File.acreate) + self.assert_not_double_wrapped(openai.api_resources.file.File.aretrieve) + self.assert_not_double_wrapped(openai.api_resources.file.File.alist) + self.assert_not_double_wrapped(openai.api_resources.file.File.adelete) + self.assert_not_double_wrapped(openai.api_resources.file.File.adownload) diff --git a/tests/contrib/openai/test_openai_v0.py b/tests/contrib/openai/test_openai_v0.py index 0dbd537c3ff..0a618b4bffc 100644 --- a/tests/contrib/openai/test_openai_v0.py +++ b/tests/contrib/openai/test_openai_v0.py @@ -9,9 +9,7 @@ import pytest import ddtrace -from ddtrace import patch from ddtrace.contrib.internal.openai.utils import _est_tokens -from ddtrace.contrib.internal.trace_utils import iswrapped from ddtrace.internal.utils.version import parse_version from tests.contrib.openai.utils import chat_completion_custom_functions from tests.contrib.openai.utils import chat_completion_input_description @@ -41,42 +39,6 @@ def test_config(ddtrace_config_openai, mock_tracer, openai): assert ddtrace.config.openai.metrics_enabled is ddtrace_config_openai["metrics_enabled"] -def test_patching(openai): - """Ensure that the correct objects are patched and not double patched.""" - - # for some reason these can't be specified as the real python objects... - # no clue why (eg. openai.Completion.create doesn't work) - methods = [ - (openai.Completion, "create"), - (openai.api_resources.completion.Completion, "create"), - (openai.Completion, "acreate"), - (openai.api_resources.completion.Completion, "acreate"), - (openai.api_requestor, "_make_session"), - (openai.util, "convert_to_openai_object"), - (openai.Embedding, "create"), - (openai.Embedding, "acreate"), - ] - if hasattr(openai, "ChatCompletion"): - methods += [ - (openai.ChatCompletion, "create"), - (openai.api_resources.chat_completion.ChatCompletion, "create"), - (openai.ChatCompletion, "acreate"), - (openai.api_resources.chat_completion.ChatCompletion, "acreate"), - ] - - for m in methods: - assert not iswrapped(getattr(m[0], m[1])) - - patch(openai=True) - for m in methods: - assert iswrapped(getattr(m[0], m[1])) - - # Ensure double patching does not occur - patch(openai=True) - for m in methods: - assert not iswrapped(getattr(m[0], m[1]).__dd_wrapped__) - - @pytest.mark.parametrize("api_key_in_env", [True, False]) def test_model_list(api_key_in_env, request_api_key, openai, openai_vcr, mock_metrics, snapshot_tracer): with snapshot_context( diff --git a/tests/contrib/openai/test_openai_v1.py b/tests/contrib/openai/test_openai_v1.py index 47ed05ea1bd..438b980d5b5 100644 --- a/tests/contrib/openai/test_openai_v1.py +++ b/tests/contrib/openai/test_openai_v1.py @@ -5,9 +5,7 @@ import pytest import ddtrace -from ddtrace import patch from ddtrace.contrib.internal.openai.utils import _est_tokens -from ddtrace.contrib.internal.trace_utils import iswrapped from ddtrace.internal.utils.version import parse_version from tests.contrib.openai.utils import chat_completion_custom_functions from tests.contrib.openai.utils import chat_completion_input_description @@ -37,56 +35,6 @@ def test_config(ddtrace_config_openai, mock_tracer, openai): assert ddtrace.config.openai.metrics_enabled is ddtrace_config_openai["metrics_enabled"] -def test_patching(openai): - """Ensure that the correct objects are patched and not double patched.""" - methods = [ - (openai.resources.completions.Completions, "create"), - (openai.resources.completions.AsyncCompletions, "create"), - (openai.resources.chat.Completions, "create"), - (openai.resources.chat.AsyncCompletions, "create"), - (openai.resources.embeddings.Embeddings, "create"), - (openai.resources.embeddings.AsyncEmbeddings, "create"), - (openai.resources.models.Models, "list"), - (openai.resources.models.Models, "retrieve"), - (openai.resources.models.AsyncModels, "list"), - (openai.resources.models.AsyncModels, "retrieve"), - (openai.resources.images.Images, "generate"), - (openai.resources.images.Images, "edit"), - (openai.resources.images.Images, "create_variation"), - (openai.resources.images.AsyncImages, "generate"), - (openai.resources.images.AsyncImages, "edit"), - (openai.resources.images.AsyncImages, "create_variation"), - (openai.resources.audio.Transcriptions, "create"), - (openai.resources.audio.AsyncTranscriptions, "create"), - (openai.resources.audio.Translations, "create"), - (openai.resources.audio.AsyncTranslations, "create"), - (openai.resources.moderations.Moderations, "create"), - (openai.resources.moderations.AsyncModerations, "create"), - (openai.resources.files.Files, "create"), - (openai.resources.files.Files, "retrieve"), - (openai.resources.files.Files, "list"), - (openai.resources.files.Files, "delete"), - (openai.resources.files.Files, "retrieve_content"), - (openai.resources.files.AsyncFiles, "create"), - (openai.resources.files.AsyncFiles, "retrieve"), - (openai.resources.files.AsyncFiles, "list"), - (openai.resources.files.AsyncFiles, "delete"), - (openai.resources.files.AsyncFiles, "retrieve_content"), - ] - - for m in methods: - assert not iswrapped(getattr(m[0], m[1])) - - patch(openai=True) - for m in methods: - assert iswrapped(getattr(m[0], m[1])) - - # Ensure double patching does not occur - patch(openai=True) - for m in methods: - assert not iswrapped(getattr(m[0], m[1]).__dd_wrapped__) - - @pytest.mark.parametrize("api_key_in_env", [True, False]) def test_model_list(api_key_in_env, request_api_key, openai, openai_vcr, mock_metrics, snapshot_tracer): with snapshot_context( @@ -908,17 +856,16 @@ def test_misuse(openai, snapshot_tracer): ) def test_span_finish_on_stream_error(openai, openai_vcr, snapshot_tracer): with openai_vcr.use_cassette("completion_stream_wrong_api_key.yaml"): - with pytest.raises(openai.APIConnectionError): - with pytest.raises(openai.AuthenticationError): - client = openai.OpenAI(api_key="sk-wrong-api-key") - client.completions.create( - model="text-curie-001", - prompt="how does openai tokenize prompts?", - temperature=0.8, - n=1, - max_tokens=150, - stream=True, - ) + with pytest.raises((openai.APIConnectionError, openai.AuthenticationError)): + client = openai.OpenAI(api_key="sk-wrong-api-key") + client.completions.create( + model="text-curie-001", + prompt="how does openai tokenize prompts?", + temperature=0.8, + n=1, + max_tokens=150, + stream=True, + ) @pytest.mark.snapshot @@ -1383,6 +1330,9 @@ def test_est_tokens(): ) # oracle: 92 +@pytest.mark.skipif( + parse_version(openai_module.version.VERSION) >= (1, 60), reason="latest openai versions use modified azure requests" +) @pytest.mark.snapshot( token="tests.contrib.openai.test_openai.test_azure_openai_completion", ignores=["meta.http.useragent", "meta.openai.api_base", "meta.openai.api_type", "meta.openai.api_version"], @@ -1405,6 +1355,9 @@ def test_azure_openai_completion(openai, azure_openai_config, openai_vcr, snapsh ) +@pytest.mark.skipif( + parse_version(openai_module.version.VERSION) >= (1, 60), reason="latest openai versions use modified azure requests" +) @pytest.mark.snapshot( token="tests.contrib.openai.test_openai.test_azure_openai_completion", ignores=[ @@ -1434,6 +1387,9 @@ async def test_azure_openai_acompletion(openai, azure_openai_config, openai_vcr, ) +@pytest.mark.skipif( + parse_version(openai_module.version.VERSION) >= (1, 60), reason="latest openai versions use modified azure requests" +) @pytest.mark.snapshot( token="tests.contrib.openai.test_openai.test_azure_openai_chat_completion", ignores=["meta.http.useragent", "meta.openai.api_base", "meta.openai.api_type", "meta.openai.api_version"], @@ -1456,6 +1412,9 @@ def test_azure_openai_chat_completion(openai, azure_openai_config, openai_vcr, s ) +@pytest.mark.skipif( + parse_version(openai_module.version.VERSION) >= (1, 60), reason="latest openai versions use modified azure requests" +) @pytest.mark.snapshot( token="tests.contrib.openai.test_openai.test_azure_openai_chat_completion", ignores=["meta.http.useragent", "meta.openai.api_base", "meta.openai.api_type", "meta.openai.api_version"], @@ -1478,6 +1437,9 @@ async def test_azure_openai_chat_acompletion(openai, azure_openai_config, openai ) +@pytest.mark.skipif( + parse_version(openai_module.version.VERSION) >= (1, 60), reason="latest openai versions use modified azure requests" +) @pytest.mark.snapshot( token="tests.contrib.openai.test_openai.test_azure_openai_embedding", ignores=["meta.http.useragent", "meta.openai.api_base", "meta.openai.api_type", "meta.openai.api_version"], @@ -1497,6 +1459,9 @@ def test_azure_openai_embedding(openai, azure_openai_config, openai_vcr, snapsho ) +@pytest.mark.skipif( + parse_version(openai_module.version.VERSION) >= (1, 60), reason="latest openai versions use modified azure requests" +) @pytest.mark.snapshot( token="tests.contrib.openai.test_openai.test_azure_openai_embedding", ignores=["meta.http.useragent", "meta.openai.api_base", "meta.openai.api_type", "meta.openai.api_version"], diff --git a/tests/contrib/pyramid/test_pyramid.py b/tests/contrib/pyramid/test_pyramid.py index 3cc9b2688ca..28fd7616cdd 100644 --- a/tests/contrib/pyramid/test_pyramid.py +++ b/tests/contrib/pyramid/test_pyramid.py @@ -4,8 +4,8 @@ import pytest from ddtrace import config -from ddtrace.constants import ORIGIN_KEY -from ddtrace.constants import SAMPLING_PRIORITY_KEY +from ddtrace.constants import _ORIGIN_KEY +from ddtrace.constants import _SAMPLING_PRIORITY_KEY from ddtrace.internal.schema import DEFAULT_SPAN_SERVICE_NAME from tests.utils import TracerTestCase from tests.utils import flaky @@ -89,8 +89,8 @@ def test_distributed_tracing(self): assert span.get_tag("span.kind") == "server" assert span.trace_id == 100 assert span.parent_id == 42 - assert span.get_metric(SAMPLING_PRIORITY_KEY) == 2 - assert span.get_tag(ORIGIN_KEY) == "synthetics" + assert span.get_metric(_SAMPLING_PRIORITY_KEY) == 2 + assert span.get_tag(_ORIGIN_KEY) == "synthetics" def test_distributed_tracing_patterned(self): # ensure the Context is properly created @@ -112,8 +112,8 @@ def test_distributed_tracing_patterned(self): assert span.get_tag("http.route") == "/hello/{param}" assert span.trace_id == 100 assert span.parent_id == 42 - assert span.get_metric(SAMPLING_PRIORITY_KEY) == 2 - assert span.get_tag(ORIGIN_KEY) == "synthetics" + assert span.get_metric(_SAMPLING_PRIORITY_KEY) == 2 + assert span.get_tag(_ORIGIN_KEY) == "synthetics" class TestPyramidDistributedTracingDisabled(PyramidBase): @@ -141,8 +141,8 @@ def test_distributed_tracing_disabled(self): assert span.get_tag("span.kind") == "server" assert span.trace_id != 100 assert span.parent_id != 42 - assert span.get_metric(SAMPLING_PRIORITY_KEY) != 2 - assert span.get_tag(ORIGIN_KEY) != "synthetics" + assert span.get_metric(_SAMPLING_PRIORITY_KEY) != 2 + assert span.get_tag(_ORIGIN_KEY) != "synthetics" class TestSchematization(PyramidBase): diff --git a/tests/contrib/pytest/test_pytest.py b/tests/contrib/pytest/test_pytest.py index 267a9d97eac..3918b82174b 100644 --- a/tests/contrib/pytest/test_pytest.py +++ b/tests/contrib/pytest/test_pytest.py @@ -7,8 +7,8 @@ import pytest import ddtrace +from ddtrace.constants import _SAMPLING_PRIORITY_KEY from ddtrace.constants import ERROR_MSG -from ddtrace.constants import SAMPLING_PRIORITY_KEY from ddtrace.contrib.internal.pytest._utils import _USE_PLUGIN_V2 from ddtrace.contrib.internal.pytest.constants import XFAIL_REASON from ddtrace.contrib.internal.pytest.patch import get_version @@ -805,7 +805,7 @@ def test_sample_priority(): spans = self.pop_spans() assert len(spans) == 4 - assert spans[0].get_metric(SAMPLING_PRIORITY_KEY) == 1 + assert spans[0].get_metric(_SAMPLING_PRIORITY_KEY) == 1 def test_pytest_exception(self): """Test that pytest sets exception information correctly.""" diff --git a/tests/contrib/tornado/test_tornado_web.py b/tests/contrib/tornado/test_tornado_web.py index 1630f8b16b3..2a22651cdf1 100644 --- a/tests/contrib/tornado/test_tornado_web.py +++ b/tests/contrib/tornado/test_tornado_web.py @@ -2,9 +2,9 @@ import tornado from ddtrace import config +from ddtrace.constants import _ORIGIN_KEY +from ddtrace.constants import _SAMPLING_PRIORITY_KEY from ddtrace.constants import ERROR_MSG -from ddtrace.constants import ORIGIN_KEY -from ddtrace.constants import SAMPLING_PRIORITY_KEY from ddtrace.ext import http from ddtrace.internal.schema import DEFAULT_SPAN_SERVICE_NAME from tests.opentracer.utils import init_tracer @@ -379,7 +379,7 @@ def test_propagation(self): # check propagation assert 1234 == request_span.trace_id assert 4567 == request_span.parent_id - assert 2 == request_span.get_metric(SAMPLING_PRIORITY_KEY) + assert 2 == request_span.get_metric(_SAMPLING_PRIORITY_KEY) assert request_span.get_tag("component") == "tornado" assert request_span.get_tag("span.kind") == "server" @@ -463,8 +463,8 @@ def test_no_propagation(self): # check non-propagation assert request_span.trace_id != 1234 assert request_span.parent_id != 4567 - assert request_span.get_metric(SAMPLING_PRIORITY_KEY) != 2 - assert request_span.get_tag(ORIGIN_KEY) != "synthetics" + assert request_span.get_metric(_SAMPLING_PRIORITY_KEY) != 2 + assert request_span.get_tag(_ORIGIN_KEY) != "synthetics" assert request_span.get_tag("component") == "tornado" assert request_span.get_tag("span.kind") == "server" @@ -502,8 +502,8 @@ def test_no_propagation_via_int_config(self): # check non-propagation assert request_span.trace_id != 1234 assert request_span.parent_id != 4567 - assert request_span.get_metric(SAMPLING_PRIORITY_KEY) != 2 - assert request_span.get_tag(ORIGIN_KEY) != "synthetics" + assert request_span.get_metric(_SAMPLING_PRIORITY_KEY) != 2 + assert request_span.get_tag(_ORIGIN_KEY) != "synthetics" assert request_span.get_tag("component") == "tornado" assert request_span.get_tag("span.kind") == "server" @@ -536,8 +536,8 @@ def test_no_propagation_via_env_var(self): # check non-propagation assert request_span.trace_id != 1234 assert request_span.parent_id != 4567 - assert request_span.get_metric(SAMPLING_PRIORITY_KEY) != 2 - assert request_span.get_tag(ORIGIN_KEY) != "synthetics" + assert request_span.get_metric(_SAMPLING_PRIORITY_KEY) != 2 + assert request_span.get_tag(_ORIGIN_KEY) != "synthetics" assert request_span.get_tag("component") == "tornado" assert request_span.get_tag("span.kind") == "server" diff --git a/tests/debugging/test_debugger.py b/tests/debugging/test_debugger.py index bacfcbcdd45..c9f04cee6ee 100644 --- a/tests/debugging/test_debugger.py +++ b/tests/debugging/test_debugger.py @@ -8,7 +8,7 @@ import pytest import ddtrace -from ddtrace.constants import ORIGIN_KEY +from ddtrace.constants import _ORIGIN_KEY from ddtrace.debugging._debugger import DebuggerWrappingContext from ddtrace.debugging._probe.model import DDExpression from ddtrace.debugging._probe.model import MetricProbeKind @@ -929,7 +929,7 @@ def test_debugger_span_probe(self): tags = span.get_tags() assert tags["debugger.probeid"] == "span-probe" assert tags["tag"] == "value" - assert tags[ORIGIN_KEY] == "di" + assert tags[_ORIGIN_KEY] == "di" def test_debugger_span_not_created_when_condition_was_false(self): from tests.submod.stuff import mutator diff --git a/tests/integration/test_integration_snapshots.py b/tests/integration/test_integration_snapshots.py index 3c8bae602f4..dc80f9508ca 100644 --- a/tests/integration/test_integration_snapshots.py +++ b/tests/integration/test_integration_snapshots.py @@ -228,13 +228,13 @@ def test_trace_with_wrong_metrics_types_not_sent(encoding, metrics, monkeypatch) @pytest.mark.snapshot() def test_tracetagsprocessor_only_adds_new_tags(): from ddtrace import tracer + from ddtrace.constants import _SAMPLING_PRIORITY_KEY from ddtrace.constants import AUTO_KEEP - from ddtrace.constants import SAMPLING_PRIORITY_KEY from ddtrace.constants import USER_KEEP with tracer.trace(name="web.request") as span: span.context.sampling_priority = AUTO_KEEP - span.set_metric(SAMPLING_PRIORITY_KEY, USER_KEEP) + span.set_metric(_SAMPLING_PRIORITY_KEY, USER_KEEP) tracer.flush() diff --git a/tests/integration/test_priority_sampling.py b/tests/integration/test_priority_sampling.py index 653ef96d49e..8ea46591a1a 100644 --- a/tests/integration/test_priority_sampling.py +++ b/tests/integration/test_priority_sampling.py @@ -2,9 +2,9 @@ import pytest +from ddtrace.constants import _SAMPLING_PRIORITY_KEY from ddtrace.constants import AUTO_KEEP from ddtrace.constants import AUTO_REJECT -from ddtrace.constants import SAMPLING_PRIORITY_KEY from ddtrace.internal.encoding import JSONEncoder from ddtrace.internal.encoding import MsgpackEncoderV04 as Encoder from ddtrace.internal.writer import AgentWriter @@ -82,7 +82,7 @@ def test_priority_sampling_rate_honored(): pass t.flush() assert len(t._writer.traces) == captured_span_count - sampled_spans = [s for s in t._writer.spans if s.context._metrics[SAMPLING_PRIORITY_KEY] == AUTO_KEEP] + sampled_spans = [s for s in t._writer.spans if s.context._metrics[_SAMPLING_PRIORITY_KEY] == AUTO_KEEP] sampled_ratio = len(sampled_spans) / captured_span_count diff_magnitude = abs(sampled_ratio - rate_from_agent) assert diff_magnitude < 0.3, "the proportion of sampled spans should approximate the sample rate given by the agent" diff --git a/tests/integration/test_trace_stats.py b/tests/integration/test_trace_stats.py index 46c153bc8d5..37982dbf7b2 100644 --- a/tests/integration/test_trace_stats.py +++ b/tests/integration/test_trace_stats.py @@ -7,7 +7,7 @@ from ddtrace._trace.sampler import DatadogSampler from ddtrace._trace.sampler import SamplingRule -from ddtrace.constants import SPAN_MEASURED_KEY +from ddtrace.constants import _SPAN_MEASURED_KEY from ddtrace.ext import http from ddtrace.internal.processor.stats import SpanStatsProcessorV06 from tests.integration.utils import AGENT_VERSION @@ -222,7 +222,7 @@ def test_measured_span(send_once_stats_tracer): for _ in range(10): with send_once_stats_tracer.trace("parent"): # Should have stats with send_once_stats_tracer.trace("child_stats") as span: # Should have stats - span.set_tag(SPAN_MEASURED_KEY) + span.set_tag(_SPAN_MEASURED_KEY) @pytest.mark.snapshot() diff --git a/tests/internal/service_name/test_processor.py b/tests/internal/service_name/test_processor.py index 02e238b8955..a765491c67c 100644 --- a/tests/internal/service_name/test_processor.py +++ b/tests/internal/service_name/test_processor.py @@ -25,7 +25,7 @@ def test_base_service(ddtrace_run_python_code_in_subprocess, schema_version, glo import sys from ddtrace import config -from ddtrace.constants import BASE_SERVICE_KEY +from ddtrace.constants import _BASE_SERVICE_KEY from ddtrace.internal.schema.processor import BaseServiceProcessor from ddtrace._trace.span import Span from tests.internal.service_name.test_processor import processor @@ -54,11 +54,11 @@ def test(processor): ] processor.process_trace(fake_trace) - assert BASE_SERVICE_KEY not in fake_trace[0].get_tags() - assert BASE_SERVICE_KEY not in fake_trace[1].get_tags(), config.service - assert fake_trace[2].get_tag(BASE_SERVICE_KEY) is not None - assert fake_trace[2].get_tag(BASE_SERVICE_KEY) == '{}' - assert BASE_SERVICE_KEY not in fake_trace[3].get_tags(), fake_trace[3].service + fake_trace[3].get_tags() + assert _BASE_SERVICE_KEY not in fake_trace[0].get_tags() + assert _BASE_SERVICE_KEY not in fake_trace[1].get_tags(), config.service + assert fake_trace[2].get_tag(_BASE_SERVICE_KEY) is not None + assert fake_trace[2].get_tag(_BASE_SERVICE_KEY) == '{}' + assert _BASE_SERVICE_KEY not in fake_trace[3].get_tags(), fake_trace[3].service + fake_trace[3].get_tags() if __name__ == "__main__": sys.exit(pytest.main(["-x", __file__])) diff --git a/tests/tracer/test_encoders.py b/tests/tracer/test_encoders.py index f96e063502e..00321a59924 100644 --- a/tests/tracer/test_encoders.py +++ b/tests/tracer/test_encoders.py @@ -21,7 +21,7 @@ from ddtrace._trace._span_pointer import _SpanPointerDirection from ddtrace._trace.context import Context from ddtrace._trace.span import Span -from ddtrace.constants import ORIGIN_KEY +from ddtrace.constants import _ORIGIN_KEY as ORIGIN_KEY from ddtrace.ext import SpanTypes from ddtrace.ext.ci import CI_APP_TEST_ORIGIN from ddtrace.internal._encoding import BufferFull diff --git a/tests/tracer/test_processors.py b/tests/tracer/test_processors.py index f7bf413d916..ad9360deec2 100644 --- a/tests/tracer/test_processors.py +++ b/tests/tracer/test_processors.py @@ -12,13 +12,13 @@ from ddtrace._trace.processor import TraceTagsProcessor from ddtrace._trace.sampler import DatadogSampler from ddtrace._trace.span import Span +from ddtrace.constants import _SAMPLING_PRIORITY_KEY from ddtrace.constants import _SINGLE_SPAN_SAMPLING_MAX_PER_SEC from ddtrace.constants import _SINGLE_SPAN_SAMPLING_MECHANISM from ddtrace.constants import _SINGLE_SPAN_SAMPLING_RATE from ddtrace.constants import AUTO_KEEP from ddtrace.constants import AUTO_REJECT from ddtrace.constants import MANUAL_KEEP_KEY -from ddtrace.constants import SAMPLING_PRIORITY_KEY from ddtrace.constants import USER_KEEP from ddtrace.constants import USER_REJECT from ddtrace.ext import SpanTypes @@ -581,7 +581,7 @@ def assert_span_sampling_decision_tags( assert span.get_metric(_SINGLE_SPAN_SAMPLING_MAX_PER_SEC) == limit if trace_sampling_priority: - assert span.get_metric(SAMPLING_PRIORITY_KEY) == trace_sampling_priority + assert span.get_metric(_SAMPLING_PRIORITY_KEY) == trace_sampling_priority def switch_out_trace_sampling_processor(tracer, sampling_processor): diff --git a/tests/tracer/test_sampler.py b/tests/tracer/test_sampler.py index 54c9c1abef3..4bf9de2019e 100644 --- a/tests/tracer/test_sampler.py +++ b/tests/tracer/test_sampler.py @@ -12,12 +12,12 @@ from ddtrace._trace.sampler import RateSampler from ddtrace._trace.sampling_rule import SamplingRule from ddtrace._trace.span import Span +from ddtrace.constants import _SAMPLING_AGENT_DECISION +from ddtrace.constants import _SAMPLING_LIMIT_DECISION +from ddtrace.constants import _SAMPLING_PRIORITY_KEY +from ddtrace.constants import _SAMPLING_RULE_DECISION from ddtrace.constants import AUTO_KEEP from ddtrace.constants import AUTO_REJECT -from ddtrace.constants import SAMPLING_AGENT_DECISION -from ddtrace.constants import SAMPLING_LIMIT_DECISION -from ddtrace.constants import SAMPLING_PRIORITY_KEY -from ddtrace.constants import SAMPLING_RULE_DECISION from ddtrace.constants import USER_KEEP from ddtrace.constants import USER_REJECT from ddtrace.internal.rate_limiter import RateLimiter @@ -51,10 +51,10 @@ def assert_sampling_decision_tags( :param sampling_priority: expected sampling priority ``_sampling_priority_v1`` :param trace_tag: expected sampling decision trace tag ``_dd.p.dm``. Format is ``-{SAMPLINGMECHANISM}``. """ - metric_agent = span.get_metric(SAMPLING_AGENT_DECISION) - metric_limit = span.get_metric(SAMPLING_LIMIT_DECISION) - metric_rule = span.get_metric(SAMPLING_RULE_DECISION) - metric_sampling_priority = span.get_metric(SAMPLING_PRIORITY_KEY) + metric_agent = span.get_metric(_SAMPLING_AGENT_DECISION) + metric_limit = span.get_metric(_SAMPLING_LIMIT_DECISION) + metric_rule = span.get_metric(_SAMPLING_RULE_DECISION) + metric_sampling_priority = span.get_metric(_SAMPLING_PRIORITY_KEY) if agent: assert metric_agent == agent if limit: diff --git a/tests/tracer/test_single_span_sampling_rules.py b/tests/tracer/test_single_span_sampling_rules.py index 3ebffed00d5..24dfda91ad5 100644 --- a/tests/tracer/test_single_span_sampling_rules.py +++ b/tests/tracer/test_single_span_sampling_rules.py @@ -3,10 +3,10 @@ import pytest from ddtrace import Tracer +from ddtrace.constants import _SAMPLING_PRIORITY_KEY from ddtrace.constants import _SINGLE_SPAN_SAMPLING_MAX_PER_SEC from ddtrace.constants import _SINGLE_SPAN_SAMPLING_MECHANISM from ddtrace.constants import _SINGLE_SPAN_SAMPLING_RATE -from ddtrace.constants import SAMPLING_PRIORITY_KEY from ddtrace.internal.sampling import SamplingMechanism from ddtrace.internal.sampling import SpanSamplingRule from ddtrace.internal.sampling import _get_file_json @@ -41,7 +41,7 @@ def assert_sampling_decision_tags( assert span.get_metric(_SINGLE_SPAN_SAMPLING_MAX_PER_SEC) == limit if trace_sampling: - assert span.get_metric(SAMPLING_PRIORITY_KEY) > 0 + assert span.get_metric(_SAMPLING_PRIORITY_KEY) > 0 def test_single_rule_init_via_env(): diff --git a/tests/tracer/test_span.py b/tests/tracer/test_span.py index 8cdaad831f0..1725f0d7675 100644 --- a/tests/tracer/test_span.py +++ b/tests/tracer/test_span.py @@ -11,12 +11,12 @@ from ddtrace._trace._span_link import SpanLink from ddtrace._trace._span_pointer import _SpanPointerDirection from ddtrace._trace.span import Span +from ddtrace.constants import _SPAN_MEASURED_KEY from ddtrace.constants import ENV_KEY from ddtrace.constants import ERROR_MSG from ddtrace.constants import ERROR_STACK from ddtrace.constants import ERROR_TYPE from ddtrace.constants import SERVICE_VERSION_KEY -from ddtrace.constants import SPAN_MEASURED_KEY from ddtrace.constants import VERSION_KEY from ddtrace.ext import SpanTypes from ddtrace.internal import core @@ -552,7 +552,7 @@ def test_span_pointers(self): ) def test_set_tag_measured(value, assertion): s = Span(name="test.span") - s.set_tag(SPAN_MEASURED_KEY, value) + s.set_tag(_SPAN_MEASURED_KEY, value) assertion(s) @@ -564,19 +564,19 @@ def test_set_tag_measured_not_set(): def test_set_tag_measured_no_value(): s = Span(name="test.span") - s.set_tag(SPAN_MEASURED_KEY) + s.set_tag(_SPAN_MEASURED_KEY) assert_is_measured(s) def test_set_tag_measured_change_value(): s = Span(name="test.span") - s.set_tag(SPAN_MEASURED_KEY, True) + s.set_tag(_SPAN_MEASURED_KEY, True) assert_is_measured(s) - s.set_tag(SPAN_MEASURED_KEY, False) + s.set_tag(_SPAN_MEASURED_KEY, False) assert_is_not_measured(s) - s.set_tag(SPAN_MEASURED_KEY) + s.set_tag(_SPAN_MEASURED_KEY) assert_is_measured(s) diff --git a/tests/tracer/test_tracer.py b/tests/tracer/test_tracer.py index e647397cc50..1c45f424679 100644 --- a/tests/tracer/test_tracer.py +++ b/tests/tracer/test_tracer.py @@ -18,15 +18,15 @@ from ddtrace._trace.context import Context from ddtrace._trace.span import _is_top_level from ddtrace._trace.tracer import Tracer +from ddtrace.constants import _HOSTNAME_KEY +from ddtrace.constants import _ORIGIN_KEY +from ddtrace.constants import _SAMPLING_PRIORITY_KEY from ddtrace.constants import AUTO_KEEP from ddtrace.constants import AUTO_REJECT from ddtrace.constants import ENV_KEY -from ddtrace.constants import HOSTNAME_KEY from ddtrace.constants import MANUAL_DROP_KEY from ddtrace.constants import MANUAL_KEEP_KEY -from ddtrace.constants import ORIGIN_KEY from ddtrace.constants import PID -from ddtrace.constants import SAMPLING_PRIORITY_KEY from ddtrace.constants import USER_KEEP from ddtrace.constants import USER_REJECT from ddtrace.constants import VERSION_KEY @@ -1459,9 +1459,9 @@ def test_ctx(tracer, test_spans): assert s3.parent_id == s2.span_id assert s4.parent_id == s1.span_id assert s1.trace_id == s2.trace_id == s3.trace_id == s4.trace_id - assert s1.get_metric(SAMPLING_PRIORITY_KEY) == 1 - assert s2.get_metric(SAMPLING_PRIORITY_KEY) is None - assert ORIGIN_KEY not in s1.get_tags() + assert s1.get_metric(_SAMPLING_PRIORITY_KEY) == 1 + assert s2.get_metric(_SAMPLING_PRIORITY_KEY) is None + assert _ORIGIN_KEY not in s1.get_tags() t = test_spans.pop_traces() assert len(t) == 1 @@ -1535,8 +1535,8 @@ def test_ctx_distributed(tracer, test_spans): trace = test_spans.pop_traces() assert len(trace) == 1 - assert s2.get_metric(SAMPLING_PRIORITY_KEY) == 2 - assert s2.get_tag(ORIGIN_KEY) == "somewhere" + assert s2.get_metric(_SAMPLING_PRIORITY_KEY) == 2 + assert s2.get_tag(_ORIGIN_KEY) == "somewhere" def test_manual_keep(tracer, test_spans): @@ -1544,14 +1544,14 @@ def test_manual_keep(tracer, test_spans): with tracer.trace("asdf") as s: s.set_tag(MANUAL_KEEP_KEY) spans = test_spans.pop() - assert spans[0].get_metric(SAMPLING_PRIORITY_KEY) is USER_KEEP + assert spans[0].get_metric(_SAMPLING_PRIORITY_KEY) is USER_KEEP # On a child span with tracer.trace("asdf"): with tracer.trace("child") as s: s.set_tag(MANUAL_KEEP_KEY) spans = test_spans.pop() - assert spans[0].get_metric(SAMPLING_PRIORITY_KEY) is USER_KEEP + assert spans[0].get_metric(_SAMPLING_PRIORITY_KEY) is USER_KEEP def test_manual_keep_then_drop(tracer, test_spans): @@ -1561,7 +1561,7 @@ def test_manual_keep_then_drop(tracer, test_spans): child.set_tag(MANUAL_KEEP_KEY) root.set_tag(MANUAL_DROP_KEY) spans = test_spans.pop() - assert spans[0].get_metric(SAMPLING_PRIORITY_KEY) is USER_REJECT + assert spans[0].get_metric(_SAMPLING_PRIORITY_KEY) is USER_REJECT def test_manual_drop(tracer, test_spans): @@ -1569,14 +1569,14 @@ def test_manual_drop(tracer, test_spans): with tracer.trace("asdf") as s: s.set_tag(MANUAL_DROP_KEY) spans = test_spans.pop() - assert spans[0].get_metric(SAMPLING_PRIORITY_KEY) is USER_REJECT + assert spans[0].get_metric(_SAMPLING_PRIORITY_KEY) is USER_REJECT # On a child span with tracer.trace("asdf"): with tracer.trace("child") as s: s.set_tag(MANUAL_DROP_KEY) spans = test_spans.pop() - assert spans[0].get_metric(SAMPLING_PRIORITY_KEY) is USER_REJECT + assert spans[0].get_metric(_SAMPLING_PRIORITY_KEY) is USER_REJECT @mock.patch("ddtrace.internal.hostname.get_hostname") @@ -1590,8 +1590,8 @@ def test_get_report_hostname_enabled(get_hostname, tracer, test_spans): spans = test_spans.pop() root = spans[0] child = spans[1] - assert root.get_tag(HOSTNAME_KEY) == "test-hostname" - assert child.get_tag(HOSTNAME_KEY) is None + assert root.get_tag(_HOSTNAME_KEY) == "test-hostname" + assert child.get_tag(_HOSTNAME_KEY) is None @mock.patch("ddtrace.internal.hostname.get_hostname") @@ -1605,8 +1605,8 @@ def test_get_report_hostname_disabled(get_hostname, tracer, test_spans): spans = test_spans.pop() root = spans[0] child = spans[1] - assert root.get_tag(HOSTNAME_KEY) is None - assert child.get_tag(HOSTNAME_KEY) is None + assert root.get_tag(_HOSTNAME_KEY) is None + assert child.get_tag(_HOSTNAME_KEY) is None @mock.patch("ddtrace.internal.hostname.get_hostname") @@ -1620,8 +1620,8 @@ def test_get_report_hostname_default(get_hostname, tracer, test_spans): spans = test_spans.pop() root = spans[0] child = spans[1] - assert root.get_tag(HOSTNAME_KEY) is None - assert child.get_tag(HOSTNAME_KEY) is None + assert root.get_tag(_HOSTNAME_KEY) is None + assert child.get_tag(_HOSTNAME_KEY) is None def test_non_active_span(tracer, test_spans): @@ -1743,7 +1743,7 @@ def test_context_priority(tracer, test_spans): spans = test_spans.pop() assert len(spans) == 1, "trace should be sampled" if p in [USER_REJECT, AUTO_REJECT, AUTO_KEEP, USER_KEEP]: - assert spans[0].get_metric(SAMPLING_PRIORITY_KEY) == p + assert spans[0].get_metric(_SAMPLING_PRIORITY_KEY) == p def test_spans_sampled_out(tracer, test_spans): diff --git a/tests/tracer/test_writer.py b/tests/tracer/test_writer.py index 2089971c554..6abb7681ab8 100644 --- a/tests/tracer/test_writer.py +++ b/tests/tracer/test_writer.py @@ -15,7 +15,7 @@ import ddtrace from ddtrace import config from ddtrace._trace.span import Span -from ddtrace.constants import KEEP_SPANS_RATE_KEY +from ddtrace.constants import _KEEP_SPANS_RATE_KEY from ddtrace.internal.ci_visibility.writer import CIVisibilityWriter from ddtrace.internal.compat import get_connection_response from ddtrace.internal.compat import httplib @@ -366,7 +366,7 @@ def test_keep_rate(self): # 100% of traces kept (refers to the past). # No traces sent before now so 100% kept. for trace in payload: - assert 1.0 == trace[0]["metrics"].get(KEEP_SPANS_RATE_KEY, -1) + assert 1.0 == trace[0]["metrics"].get(_KEEP_SPANS_RATE_KEY, -1) # 2. We fail to write 4 traces because of size limitation. for trace in traces_too_big: @@ -392,7 +392,7 @@ def test_keep_rate(self): # 50% of traces kept (refers to the past). # We had 4 successfully written and 4 dropped. for trace in payload: - assert 0.5 == trace[0]["metrics"].get(KEEP_SPANS_RATE_KEY, -1) + assert 0.5 == trace[0]["metrics"].get(_KEEP_SPANS_RATE_KEY, -1) # 4. We write 1 trace successfully and fail to write 3. writer.write(traces[0]) @@ -408,7 +408,7 @@ def test_keep_rate(self): # 60% of traces kept (refers to the past). # We had 4 successfully written, then 4 dropped, then 2 written. for trace in payload: - assert 0.6 == trace[0]["metrics"].get(KEEP_SPANS_RATE_KEY, -1) + assert 0.6 == trace[0]["metrics"].get(_KEEP_SPANS_RATE_KEY, -1) class CIVisibilityWriterTests(AgentWriterTests): diff --git a/tests/utils.py b/tests/utils.py index 1932033152f..5283e27e7cf 100644 --- a/tests/utils.py +++ b/tests/utils.py @@ -20,7 +20,7 @@ from ddtrace import Tracer from ddtrace import config as dd_config from ddtrace._trace.span import Span -from ddtrace.constants import SPAN_MEASURED_KEY +from ddtrace.constants import _SPAN_MEASURED_KEY from ddtrace.ext import http from ddtrace.internal import agent from ddtrace.internal import core @@ -55,18 +55,18 @@ def assert_is_measured(span): """Assert that the span has the proper _dd.measured tag set""" - assert SPAN_MEASURED_KEY in span.get_metrics() - assert SPAN_MEASURED_KEY not in span.get_tags() - assert span.get_metric(SPAN_MEASURED_KEY) == 1 + assert _SPAN_MEASURED_KEY in span.get_metrics() + assert _SPAN_MEASURED_KEY not in span.get_tags() + assert span.get_metric(_SPAN_MEASURED_KEY) == 1 def assert_is_not_measured(span): """Assert that the span does not set _dd.measured""" - assert SPAN_MEASURED_KEY not in span.get_tags() - if SPAN_MEASURED_KEY in span.get_metrics(): - assert span.get_metric(SPAN_MEASURED_KEY) == 0 + assert _SPAN_MEASURED_KEY not in span.get_tags() + if _SPAN_MEASURED_KEY in span.get_metrics(): + assert span.get_metric(_SPAN_MEASURED_KEY) == 0 else: - assert SPAN_MEASURED_KEY not in span.get_metrics() + assert _SPAN_MEASURED_KEY not in span.get_metrics() def assert_span_http_status_code(span, code):