ddapm-test-agent 1.37.0__tar.gz → 1.39.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {ddapm_test_agent-1.37.0 → ddapm_test_agent-1.39.0}/.github/workflows/main.yml +7 -1
- {ddapm_test_agent-1.37.0 → ddapm_test_agent-1.39.0}/PKG-INFO +2 -2
- {ddapm_test_agent-1.37.0 → ddapm_test_agent-1.39.0}/ddapm_test_agent/agent.py +1 -1
- ddapm_test_agent-1.39.0/ddapm_test_agent/vcr_proxy.py +495 -0
- {ddapm_test_agent-1.37.0 → ddapm_test_agent-1.39.0}/ddapm_test_agent/web.py +2 -2
- {ddapm_test_agent-1.37.0 → ddapm_test_agent-1.39.0}/ddapm_test_agent.egg-info/PKG-INFO +2 -2
- {ddapm_test_agent-1.37.0 → ddapm_test_agent-1.39.0}/ddapm_test_agent.egg-info/SOURCES.txt +3 -0
- {ddapm_test_agent-1.37.0 → ddapm_test_agent-1.39.0}/ddapm_test_agent.egg-info/requires.txt +1 -1
- ddapm_test_agent-1.39.0/releasenotes/notes/controllable-test-agent-version-a12e61934bbce5fe.yaml +4 -0
- ddapm_test_agent-1.39.0/releasenotes/notes/ignore-transfer-encoding-header-3b22699615356f91.yaml +5 -0
- ddapm_test_agent-1.39.0/releasenotes/notes/remove-vcr-dependancy-ea09889df42b3975.yaml +4 -0
- {ddapm_test_agent-1.37.0 → ddapm_test_agent-1.39.0}/setup.py +1 -1
- {ddapm_test_agent-1.37.0 → ddapm_test_agent-1.39.0}/tests/test_agent.py +15 -0
- {ddapm_test_agent-1.37.0 → ddapm_test_agent-1.39.0}/tests/test_vcr_proxy.py +95 -7
- ddapm_test_agent-1.37.0/ddapm_test_agent/vcr_proxy.py +0 -246
- {ddapm_test_agent-1.37.0 → ddapm_test_agent-1.39.0}/.dockerignore +0 -0
- {ddapm_test_agent-1.37.0 → ddapm_test_agent-1.39.0}/.github/workflows/docker.yml +0 -0
- {ddapm_test_agent-1.37.0 → ddapm_test_agent-1.39.0}/.github/workflows/publish_pypi.yml +0 -0
- {ddapm_test_agent-1.37.0 → ddapm_test_agent-1.39.0}/.github/workflows/releasenote.yml +0 -0
- {ddapm_test_agent-1.37.0 → ddapm_test_agent-1.39.0}/.gitignore +0 -0
- {ddapm_test_agent-1.37.0 → ddapm_test_agent-1.39.0}/Dockerfile +0 -0
- {ddapm_test_agent-1.37.0 → ddapm_test_agent-1.39.0}/Dockerfile.windows +0 -0
- {ddapm_test_agent-1.37.0 → ddapm_test_agent-1.39.0}/LICENSE.BSD3 +0 -0
- {ddapm_test_agent-1.37.0 → ddapm_test_agent-1.39.0}/LICENSE.apache2 +0 -0
- {ddapm_test_agent-1.37.0 → ddapm_test_agent-1.39.0}/README.md +0 -0
- {ddapm_test_agent-1.37.0 → ddapm_test_agent-1.39.0}/ddapm_test_agent/__init__.py +0 -0
- {ddapm_test_agent-1.37.0 → ddapm_test_agent-1.39.0}/ddapm_test_agent/apmtelemetry.py +0 -0
- {ddapm_test_agent-1.37.0 → ddapm_test_agent-1.39.0}/ddapm_test_agent/checks.py +0 -0
- {ddapm_test_agent-1.37.0 → ddapm_test_agent-1.39.0}/ddapm_test_agent/client.py +0 -0
- {ddapm_test_agent-1.37.0 → ddapm_test_agent-1.39.0}/ddapm_test_agent/cmd.py +0 -0
- {ddapm_test_agent-1.37.0 → ddapm_test_agent-1.39.0}/ddapm_test_agent/context.py +0 -0
- {ddapm_test_agent-1.37.0 → ddapm_test_agent-1.39.0}/ddapm_test_agent/fmt.py +0 -0
- {ddapm_test_agent-1.37.0 → ddapm_test_agent-1.39.0}/ddapm_test_agent/integration.py +0 -0
- {ddapm_test_agent-1.37.0 → ddapm_test_agent-1.39.0}/ddapm_test_agent/logs.py +0 -0
- {ddapm_test_agent-1.37.0 → ddapm_test_agent-1.39.0}/ddapm_test_agent/metrics.py +0 -0
- {ddapm_test_agent-1.37.0 → ddapm_test_agent-1.39.0}/ddapm_test_agent/remoteconfig.py +0 -0
- {ddapm_test_agent-1.37.0 → ddapm_test_agent-1.39.0}/ddapm_test_agent/static/style.css +0 -0
- {ddapm_test_agent-1.37.0 → ddapm_test_agent-1.39.0}/ddapm_test_agent/templates/base.html +0 -0
- {ddapm_test_agent-1.37.0 → ddapm_test_agent-1.39.0}/ddapm_test_agent/templates/config.html +0 -0
- {ddapm_test_agent-1.37.0 → ddapm_test_agent-1.39.0}/ddapm_test_agent/templates/dashboard.html +0 -0
- {ddapm_test_agent-1.37.0 → ddapm_test_agent-1.39.0}/ddapm_test_agent/templates/macros.html +0 -0
- {ddapm_test_agent-1.37.0 → ddapm_test_agent-1.39.0}/ddapm_test_agent/templates/requests.html +0 -0
- {ddapm_test_agent-1.37.0 → ddapm_test_agent-1.39.0}/ddapm_test_agent/templates/session_detail.html +0 -0
- {ddapm_test_agent-1.37.0 → ddapm_test_agent-1.39.0}/ddapm_test_agent/templates/sessions.html +0 -0
- {ddapm_test_agent-1.37.0 → ddapm_test_agent-1.39.0}/ddapm_test_agent/templates/snapshot_detail.html +0 -0
- {ddapm_test_agent-1.37.0 → ddapm_test_agent-1.39.0}/ddapm_test_agent/templates/snapshots.html +0 -0
- {ddapm_test_agent-1.37.0 → ddapm_test_agent-1.39.0}/ddapm_test_agent/templates/trace_detail.html +0 -0
- {ddapm_test_agent-1.37.0 → ddapm_test_agent-1.39.0}/ddapm_test_agent/templates/tracer_flares.html +0 -0
- {ddapm_test_agent-1.37.0 → ddapm_test_agent-1.39.0}/ddapm_test_agent/templates/traces.html +0 -0
- {ddapm_test_agent-1.37.0 → ddapm_test_agent-1.39.0}/ddapm_test_agent/trace.py +0 -0
- {ddapm_test_agent-1.37.0 → ddapm_test_agent-1.39.0}/ddapm_test_agent/trace_checks.py +0 -0
- {ddapm_test_agent-1.37.0 → ddapm_test_agent-1.39.0}/ddapm_test_agent/trace_snapshot.py +0 -0
- {ddapm_test_agent-1.37.0 → ddapm_test_agent-1.39.0}/ddapm_test_agent/tracerflare.py +0 -0
- {ddapm_test_agent-1.37.0 → ddapm_test_agent-1.39.0}/ddapm_test_agent/tracestats.py +0 -0
- {ddapm_test_agent-1.37.0 → ddapm_test_agent-1.39.0}/ddapm_test_agent/tracestats_snapshot.py +0 -0
- {ddapm_test_agent-1.37.0 → ddapm_test_agent-1.39.0}/ddapm_test_agent.egg-info/dependency_links.txt +0 -0
- {ddapm_test_agent-1.37.0 → ddapm_test_agent-1.39.0}/ddapm_test_agent.egg-info/entry_points.txt +0 -0
- {ddapm_test_agent-1.37.0 → ddapm_test_agent-1.39.0}/ddapm_test_agent.egg-info/not-zip-safe +0 -0
- {ddapm_test_agent-1.37.0 → ddapm_test_agent-1.39.0}/ddapm_test_agent.egg-info/top_level.txt +0 -0
- {ddapm_test_agent-1.37.0 → ddapm_test_agent-1.39.0}/pyproject.toml +0 -0
- {ddapm_test_agent-1.37.0 → ddapm_test_agent-1.39.0}/releasenotes/check-releasenotes +0 -0
- {ddapm_test_agent-1.37.0 → ddapm_test_agent-1.39.0}/releasenotes/config.yaml +0 -0
- {ddapm_test_agent-1.37.0 → ddapm_test_agent-1.39.0}/releasenotes/notes/1.0-e192f5064e917083.yaml +0 -0
- {ddapm_test_agent-1.37.0 → ddapm_test_agent-1.39.0}/releasenotes/notes/Add-metrics.process_id-to-ignored-attributes-62b264f0ea591326.yaml +0 -0
- {ddapm_test_agent-1.37.0 → ddapm_test_agent-1.39.0}/releasenotes/notes/Add-values-handling-to-span_event-array_value-to-mirror-agent-ee7483c90c263ff4.yaml +0 -0
- {ddapm_test_agent-1.37.0 → ddapm_test_agent-1.39.0}/releasenotes/notes/Checks-changed-to-opt-in-8716cac4ecdbb1c2.yaml +0 -0
- {ddapm_test_agent-1.37.0 → ddapm_test_agent-1.39.0}/releasenotes/notes/SNAPSHOT_REGEX_PLACEHOLDERS-1d2c5e2711d1953b.yaml +0 -0
- {ddapm_test_agent-1.37.0 → ddapm_test_agent-1.39.0}/releasenotes/notes/SNAPSHOT_REGEX_PLACEHOLDERS-compare-c829e7a4df4fa1f4.yaml +0 -0
- {ddapm_test_agent-1.37.0 → ddapm_test_agent-1.39.0}/releasenotes/notes/Settings-endpoint-928ae5b6e8ddc625.yaml +0 -0
- {ddapm_test_agent-1.37.0 → ddapm_test_agent-1.39.0}/releasenotes/notes/Telemetry-requests-delay-2586180b286ce393.yaml +0 -0
- {ddapm_test_agent-1.37.0 → ddapm_test_agent-1.39.0}/releasenotes/notes/Use-default-value-for-null-fields-in-tracestats-55d465f489efb2ba.yaml +0 -0
- {ddapm_test_agent-1.37.0 → ddapm_test_agent-1.39.0}/releasenotes/notes/acceptV1TracePayloads-5435cff37cfb6a85.yaml +0 -0
- {ddapm_test_agent-1.37.0 → ddapm_test_agent-1.39.0}/releasenotes/notes/add-datadog-proxy-7e2e608c101a564b.yaml +0 -0
- {ddapm_test_agent-1.37.0 → ddapm_test_agent-1.39.0}/releasenotes/notes/add-distributed-trace-c35a314698a3b966.yaml +0 -0
- {ddapm_test_agent-1.37.0 → ddapm_test_agent-1.39.0}/releasenotes/notes/add-errors-intake-proxy-endpoint-7e0f31d72a130f1a.yaml +0 -0
- {ddapm_test_agent-1.37.0 → ddapm_test_agent-1.39.0}/releasenotes/notes/add-feature-flags-evp-endpoint-da7786735ac02f50.yaml +0 -0
- {ddapm_test_agent-1.37.0 → ddapm_test_agent-1.39.0}/releasenotes/notes/add-fmt-command-cc31769942a5fec3.yaml +0 -0
- {ddapm_test_agent-1.37.0 → ddapm_test_agent-1.39.0}/releasenotes/notes/add-nix-build-support-29dc8a347e3bd7c1.yaml +0 -0
- {ddapm_test_agent-1.37.0 → ddapm_test_agent-1.39.0}/releasenotes/notes/add-optional-json-parser-10aac54bd1cbe322.yaml +0 -0
- {ddapm_test_agent-1.37.0 → ddapm_test_agent-1.39.0}/releasenotes/notes/add-otel-metrics-support-a2ebeb28cae2f0ba.yaml +0 -0
- {ddapm_test_agent-1.37.0 → ddapm_test_agent-1.39.0}/releasenotes/notes/add-python-3.13-support-ae7b96f4a10f20f4.yaml +0 -0
- {ddapm_test_agent-1.37.0 → ddapm_test_agent-1.39.0}/releasenotes/notes/add-rcm-endpoints-7e1f949e83e21039.yaml +0 -0
- {ddapm_test_agent-1.37.0 → ddapm_test_agent-1.39.0}/releasenotes/notes/add-request-forwarding-middleware-d3f325166b0f8e9e.yaml +0 -0
- {ddapm_test_agent-1.37.0 → ddapm_test_agent-1.39.0}/releasenotes/notes/add-service-naming-checks-2b68ff51d1b5496d.yaml +0 -0
- {ddapm_test_agent-1.37.0 → ddapm_test_agent-1.39.0}/releasenotes/notes/add-session-to-rcm-endpoints-d97e925a04a99a65.yaml +0 -0
- {ddapm_test_agent-1.37.0 → ddapm_test_agent-1.39.0}/releasenotes/notes/add-span-events-306e697168373899.yaml +0 -0
- {ddapm_test_agent-1.37.0 → ddapm_test_agent-1.39.0}/releasenotes/notes/add-support-for-plain-text-responses-00d20bf7b335e75b.yaml +0 -0
- {ddapm_test_agent-1.37.0 → ddapm_test_agent-1.39.0}/releasenotes/notes/add-support-telemetry-requests-10737cd3da802ca6.yaml +0 -0
- {ddapm_test_agent-1.37.0 → ddapm_test_agent-1.39.0}/releasenotes/notes/add-tracer_flare-endpoint-b2c81510920974d7.yaml +0 -0
- {ddapm_test_agent-1.37.0 → ddapm_test_agent-1.39.0}/releasenotes/notes/add-web-ui-304c84316f2b4818.yaml +0 -0
- {ddapm_test_agent-1.37.0 → ddapm_test_agent-1.39.0}/releasenotes/notes/addAgentStateToInfo-f9a179ce88f2ab9e.yaml +0 -0
- {ddapm_test_agent-1.37.0 → ddapm_test_agent-1.39.0}/releasenotes/notes/addPeerTagsToInfo-4ccc2539d22c2993.yaml +0 -0
- {ddapm_test_agent-1.37.0 → ddapm_test_agent-1.39.0}/releasenotes/notes/allow-attribute-removal-snapshots-314b744b043b97c5.yaml +0 -0
- {ddapm_test_agent-1.37.0 → ddapm_test_agent-1.39.0}/releasenotes/notes/args-88f664c83a96075d.yaml +0 -0
- {ddapm_test_agent-1.37.0 → ddapm_test_agent-1.39.0}/releasenotes/notes/change-trace-proxy-headers-f9fcbb4efc4fcb95.yaml +0 -0
- {ddapm_test_agent-1.37.0 → ddapm_test_agent-1.39.0}/releasenotes/notes/check-http-header-sensitivity-daaa9d9595ae86d6.yaml +0 -0
- {ddapm_test_agent-1.37.0 → ddapm_test_agent-1.39.0}/releasenotes/notes/clearing-sessions-now-only-removes-6b0311673d8b37aa.yaml +0 -0
- {ddapm_test_agent-1.37.0 → ddapm_test_agent-1.39.0}/releasenotes/notes/client-173dbc6655e42337.yaml +0 -0
- {ddapm_test_agent-1.37.0 → ddapm_test_agent-1.39.0}/releasenotes/notes/content_length-e1bab75580aa1dcb.yaml +0 -0
- {ddapm_test_agent-1.37.0 → ddapm_test_agent-1.39.0}/releasenotes/notes/disable-error-responses-and-collect-trace-failures-in-memory-4a199bc7be416709.yaml +0 -0
- {ddapm_test_agent-1.37.0 → ddapm_test_agent-1.39.0}/releasenotes/notes/docker-arm64-images-a4b6b2cc527327d6.yaml +0 -0
- {ddapm_test_agent-1.37.0 → ddapm_test_agent-1.39.0}/releasenotes/notes/evp-proxy-on-info-d65cd077575306ca.yaml +0 -0
- {ddapm_test_agent-1.37.0 → ddapm_test_agent-1.39.0}/releasenotes/notes/exception-messages-21ee64461020edd1.yaml +0 -0
- {ddapm_test_agent-1.37.0 → ddapm_test_agent-1.39.0}/releasenotes/notes/fix-docker-image-tags-785d40f5bfdb8003.yaml +0 -0
- {ddapm_test_agent-1.37.0 → ddapm_test_agent-1.39.0}/releasenotes/notes/fix-fmt-logging-6a323fd8d5d4eb28.yaml +0 -0
- {ddapm_test_agent-1.37.0 → ddapm_test_agent-1.39.0}/releasenotes/notes/fix-getting-tested-integrations-multiple-session-tokens-4ee41d545754f87f.yaml +0 -0
- {ddapm_test_agent-1.37.0 → ddapm_test_agent-1.39.0}/releasenotes/notes/fix-matching-319744b82d2514c1.yaml +0 -0
- {ddapm_test_agent-1.37.0 → ddapm_test_agent-1.39.0}/releasenotes/notes/fix-missing-slim-deps-fa3b0fc0292a09b3.yaml +0 -0
- {ddapm_test_agent-1.37.0 → ddapm_test_agent-1.39.0}/releasenotes/notes/fix-otlp-endpoint-response-type-18822a3ac85e1cb7.yaml +0 -0
- {ddapm_test_agent-1.37.0 → ddapm_test_agent-1.39.0}/releasenotes/notes/fix-partial-chunks-0db14ce3017e6173.yaml +0 -0
- {ddapm_test_agent-1.37.0 → ddapm_test_agent-1.39.0}/releasenotes/notes/fix-racecondition-9bd0ef15b7da60fa.yaml +0 -0
- {ddapm_test_agent-1.37.0 → ddapm_test_agent-1.39.0}/releasenotes/notes/fix-tracerflare-request-parsing-fae18ff9997c216d.yaml +0 -0
- {ddapm_test_agent-1.37.0 → ddapm_test_agent-1.39.0}/releasenotes/notes/genai-vcr-support-b499ec54df84eaa3.yaml +0 -0
- {ddapm_test_agent-1.37.0 → ddapm_test_agent-1.39.0}/releasenotes/notes/ignore-dsm-pathway-hash-during-trace-snapshots-f0b99ea267fbad48.yaml +0 -0
- {ddapm_test_agent-1.37.0 → ddapm_test_agent-1.39.0}/releasenotes/notes/image-optimization-d614eccb59441217.yaml +0 -0
- {ddapm_test_agent-1.37.0 → ddapm_test_agent-1.39.0}/releasenotes/notes/improve-test-agent-debugging-5759413f1fc5f7fa.yaml +0 -0
- {ddapm_test_agent-1.37.0 → ddapm_test_agent-1.39.0}/releasenotes/notes/improve-test-agent-proxying-a207f0fc81b3ab2d.yaml +0 -0
- {ddapm_test_agent-1.37.0 → ddapm_test_agent-1.39.0}/releasenotes/notes/improve-trace-check-results-endpoints-6ab4132628520793.yaml +0 -0
- {ddapm_test_agent-1.37.0 → ddapm_test_agent-1.39.0}/releasenotes/notes/info-34dcd9cbcc382487.yaml +0 -0
- {ddapm_test_agent-1.37.0 → ddapm_test_agent-1.39.0}/releasenotes/notes/info-drop-p0s-c207889f590340fb.yaml +0 -0
- {ddapm_test_agent-1.37.0 → ddapm_test_agent-1.39.0}/releasenotes/notes/llmobs-eval-metric-endpoint-8b5222491969ab4f.yaml +0 -0
- {ddapm_test_agent-1.37.0 → ddapm_test_agent-1.39.0}/releasenotes/notes/llmobs-evp-proxy-1383f4b4962ac7c9.yaml +0 -0
- {ddapm_test_agent-1.37.0 → ddapm_test_agent-1.39.0}/releasenotes/notes/meta-struct-2cce08475cb05470.yaml +0 -0
- {ddapm_test_agent-1.37.0 → ddapm_test_agent-1.39.0}/releasenotes/notes/more-oai-cass-908eb5ea46bd2985.yaml +0 -0
- {ddapm_test_agent-1.37.0 → ddapm_test_agent-1.39.0}/releasenotes/notes/named-pipe-ded0ebbbeee2e7fa.yaml +0 -0
- {ddapm_test_agent-1.37.0 → ddapm_test_agent-1.39.0}/releasenotes/notes/new-process-id-tag-f0ab0daf652e05cc.yaml +0 -0
- {ddapm_test_agent-1.37.0 → ddapm_test_agent-1.39.0}/releasenotes/notes/oai-incomplete-cass-795ad19b6a226c1f.yaml +0 -0
- {ddapm_test_agent-1.37.0 → ddapm_test_agent-1.39.0}/releasenotes/notes/otlp-logs-grpc-45365879c22969aa.yaml +0 -0
- {ddapm_test_agent-1.37.0 → ddapm_test_agent-1.39.0}/releasenotes/notes/otlp-logs-support-d5a150d9f5304d7c.yaml +0 -0
- {ddapm_test_agent-1.37.0 → ddapm_test_agent-1.39.0}/releasenotes/notes/pipeline_stats_endpoint-e8ad6da735dc2647.yaml +0 -0
- {ddapm_test_agent-1.37.0 → ddapm_test_agent-1.39.0}/releasenotes/notes/profiling-endpoint-0cd209e4e5b6cfc0.yaml +0 -0
- {ddapm_test_agent-1.37.0 → ddapm_test_agent-1.39.0}/releasenotes/notes/provider-snapshot-server-f6a307acbf11d214.yaml +0 -0
- {ddapm_test_agent-1.37.0 → ddapm_test_agent-1.39.0}/releasenotes/notes/proxy-37c94e2fb428c6fc.yaml +0 -0
- {ddapm_test_agent-1.37.0 → ddapm_test_agent-1.39.0}/releasenotes/notes/python-3.12-952e06c6158af67d.yaml +0 -0
- {ddapm_test_agent-1.37.0 → ddapm_test_agent-1.39.0}/releasenotes/notes/python-support-1c447acc4607abc7.yaml +0 -0
- {ddapm_test_agent-1.37.0 → ddapm_test_agent-1.39.0}/releasenotes/notes/python310-025fbc190363de98.yaml +0 -0
- {ddapm_test_agent-1.37.0 → ddapm_test_agent-1.39.0}/releasenotes/notes/python310-docker-image-d4e329cfecf6510e.yaml +0 -0
- {ddapm_test_agent-1.37.0 → ddapm_test_agent-1.39.0}/releasenotes/notes/rc-encoding-length-fix-cc011edea7f8f5b2.yaml +0 -0
- {ddapm_test_agent-1.37.0 → ddapm_test_agent-1.39.0}/releasenotes/notes/rc-get-endpoint-e502f55b7df544e2.yaml +0 -0
- {ddapm_test_agent-1.37.0 → ddapm_test_agent-1.39.0}/releasenotes/notes/remoteconfig-requests-1af7abb99c61c069.yaml +0 -0
- {ddapm_test_agent-1.37.0 → ddapm_test_agent-1.39.0}/releasenotes/notes/remove-agent-state-header-from-info-87f920bf4ce5785c.yaml +0 -0
- {ddapm_test_agent-1.37.0 → ddapm_test_agent-1.39.0}/releasenotes/notes/remove-nix-ec1c4aca7dc002c4.yaml +0 -0
- {ddapm_test_agent-1.37.0 → ddapm_test_agent-1.39.0}/releasenotes/notes/remove-old-pythons-4667b182aacf0ce6.yaml +0 -0
- {ddapm_test_agent-1.37.0 → ddapm_test_agent-1.39.0}/releasenotes/notes/reuse-session-1670aa569907cf68.yaml +0 -0
- {ddapm_test_agent-1.37.0 → ddapm_test_agent-1.39.0}/releasenotes/notes/sample-rate-1e06ae4cdc933b14.yaml +0 -0
- {ddapm_test_agent-1.37.0 → ddapm_test_agent-1.39.0}/releasenotes/notes/session-requests-b8057811f976220e.yaml +0 -0
- {ddapm_test_agent-1.37.0 → ddapm_test_agent-1.39.0}/releasenotes/notes/session-tracerflares-400ce9b3d3838b40.yaml +0 -0
- {ddapm_test_agent-1.37.0 → ddapm_test_agent-1.39.0}/releasenotes/notes/snapshot-cmds-de4a561911afee11.yaml +0 -0
- {ddapm_test_agent-1.37.0 → ddapm_test_agent-1.39.0}/releasenotes/notes/snapshot-empty-maps-2cbe8cea3e7112fa.yaml +0 -0
- {ddapm_test_agent-1.37.0 → ddapm_test_agent-1.39.0}/releasenotes/notes/snapshot-error-messages-de41d9e3207fa30a.yaml +0 -0
- {ddapm_test_agent-1.37.0 → ddapm_test_agent-1.39.0}/releasenotes/notes/snapshot-filename-c068de1bc3e50c04.yaml +0 -0
- {ddapm_test_agent-1.37.0 → ddapm_test_agent-1.39.0}/releasenotes/notes/snapshot-order-type-2d6424e380b2c88f.yaml +0 -0
- {ddapm_test_agent-1.37.0 → ddapm_test_agent-1.39.0}/releasenotes/notes/snapshot-parent-id-7abb860008702e70.yaml +0 -0
- {ddapm_test_agent-1.37.0 → ddapm_test_agent-1.39.0}/releasenotes/notes/span-links-1ec76bd2b47a3880.yaml +0 -0
- {ddapm_test_agent-1.37.0 → ddapm_test_agent-1.39.0}/releasenotes/notes/span-ordering-1a7b383aa015bddc.yaml +0 -0
- {ddapm_test_agent-1.37.0 → ddapm_test_agent-1.39.0}/releasenotes/notes/span-parent-id-a4d7d63fa623361c.yaml +0 -0
- {ddapm_test_agent-1.37.0 → ddapm_test_agent-1.39.0}/releasenotes/notes/support-ant-vcr-1eff9a40caa0aba0.yaml +0 -0
- {ddapm_test_agent-1.37.0 → ddapm_test_agent-1.39.0}/releasenotes/notes/support-tracking-of-tested-integrations-ac19ccd1f8333c00.yaml +0 -0
- {ddapm_test_agent-1.37.0 → ddapm_test_agent-1.39.0}/releasenotes/notes/throttling-590bf58ecb3cc4a5.yaml +0 -0
- {ddapm_test_agent-1.37.0 → ddapm_test_agent-1.39.0}/releasenotes/notes/trace-stats-97da3a478dabfa99.yaml +0 -0
- {ddapm_test_agent-1.37.0 → ddapm_test_agent-1.39.0}/releasenotes/notes/trace-stats-snapshot-718ca37385c93e1e.yaml +0 -0
- {ddapm_test_agent-1.37.0 → ddapm_test_agent-1.39.0}/releasenotes/notes/traces-endpoint-f4f9c1d94d6ceda2.yaml +0 -0
- {ddapm_test_agent-1.37.0 → ddapm_test_agent-1.39.0}/releasenotes/notes/tracestats-fixes-07152c708e73ef96.yaml +0 -0
- {ddapm_test_agent-1.37.0 → ddapm_test_agent-1.39.0}/releasenotes/notes/tracestats-post-65ce788f81862532.yaml +0 -0
- {ddapm_test_agent-1.37.0 → ddapm_test_agent-1.39.0}/releasenotes/notes/tracestats-service-2a0a178cbd21b07d.yaml +0 -0
- {ddapm_test_agent-1.37.0 → ddapm_test_agent-1.39.0}/releasenotes/notes/uds-64b11960931d8b77.yaml +0 -0
- {ddapm_test_agent-1.37.0 → ddapm_test_agent-1.39.0}/releasenotes/notes/uds-c99ea5d099e67156.yaml +0 -0
- {ddapm_test_agent-1.37.0 → ddapm_test_agent-1.39.0}/releasenotes/notes/uds-container-8138f8b1438b1a0a.yaml +0 -0
- {ddapm_test_agent-1.37.0 → ddapm_test_agent-1.39.0}/releasenotes/notes/uds-permissions-903266ac6445b873.yaml +0 -0
- {ddapm_test_agent-1.37.0 → ddapm_test_agent-1.39.0}/releasenotes/notes/v0.5-traces-cf469b0b71398d97.yaml +0 -0
- {ddapm_test_agent-1.37.0 → ddapm_test_agent-1.39.0}/releasenotes/notes/v0.7-traces-7ea3ebbed7502d01.yaml +0 -0
- {ddapm_test_agent-1.37.0 → ddapm_test_agent-1.39.0}/releasenotes/notes/vcr-aws-bedrock-proxy-3bf018b1712d5105.yaml +0 -0
- {ddapm_test_agent-1.37.0 → ddapm_test_agent-1.39.0}/releasenotes/notes/vcr-cassette-name-middleware-fix-9e47c395892a9fe7.yaml +0 -0
- {ddapm_test_agent-1.37.0 → ddapm_test_agent-1.39.0}/releasenotes/notes/vcr-cassettes-for-openai-v5-6e9d78091de1f0c2.yaml +0 -0
- {ddapm_test_agent-1.37.0 → ddapm_test_agent-1.39.0}/releasenotes/notes/vcr-cassettes-for-vercel-ai-7a8275f9c2b48bc7.yaml +0 -0
- {ddapm_test_agent-1.37.0 → ddapm_test_agent-1.39.0}/releasenotes/notes/vcr-ci-mode-99dbd2940fff8d7a.yaml +0 -0
- {ddapm_test_agent-1.37.0 → ddapm_test_agent-1.39.0}/releasenotes/notes/vcr-custom-providers-map-a43b7e2d62d02015.yaml +0 -0
- {ddapm_test_agent-1.37.0 → ddapm_test_agent-1.39.0}/releasenotes/notes/vcr-prefix-instead-of-suffix-4c56dcb5038d222e.yaml +0 -0
- {ddapm_test_agent-1.37.0 → ddapm_test_agent-1.39.0}/releasenotes/notes/vcr-proxy-aws-recalculation-fix-2184c10270a7bca5.yaml +0 -0
- {ddapm_test_agent-1.37.0 → ddapm_test_agent-1.39.0}/releasenotes/notes/vcr-proxy-use-test-name-bugfix-be758294ba30ac78.yaml +0 -0
- {ddapm_test_agent-1.37.0 → ddapm_test_agent-1.39.0}/releasenotes/notes/vcr-proxy-use-test-name-e47891994c961c52.yaml +0 -0
- {ddapm_test_agent-1.37.0 → ddapm_test_agent-1.39.0}/releasenotes/notes/vcr-support-querystring-b06555fb9a7c90ae.yaml +0 -0
- {ddapm_test_agent-1.37.0 → ddapm_test_agent-1.39.0}/releasenotes/notes/version-0c32d2752f154eb9.yaml +0 -0
- {ddapm_test_agent-1.37.0 → ddapm_test_agent-1.39.0}/releasenotes/notes/wheels-68a7dc2f4b00e0c4.yaml +0 -0
- {ddapm_test_agent-1.37.0 → ddapm_test_agent-1.39.0}/releasenotes/notes/windows-docker-image-1f5d5e894558bb4b.yaml +0 -0
- {ddapm_test_agent-1.37.0 → ddapm_test_agent-1.39.0}/riotfile.py +0 -0
- {ddapm_test_agent-1.37.0 → ddapm_test_agent-1.39.0}/setup.cfg +0 -0
- {ddapm_test_agent-1.37.0 → ddapm_test_agent-1.39.0}/test_deps.txt +0 -0
- {ddapm_test_agent-1.37.0 → ddapm_test_agent-1.39.0}/tests/__init__.py +0 -0
- {ddapm_test_agent-1.37.0 → ddapm_test_agent-1.39.0}/tests/conftest.py +0 -0
- {ddapm_test_agent-1.37.0 → ddapm_test_agent-1.39.0}/tests/integration_snapshots/test_multi_trace.json +0 -0
- {ddapm_test_agent-1.37.0 → ddapm_test_agent-1.39.0}/tests/integration_snapshots/test_single_trace.json +0 -0
- {ddapm_test_agent-1.37.0 → ddapm_test_agent-1.39.0}/tests/integration_snapshots/test_trace_distributed_propagated.json +0 -0
- {ddapm_test_agent-1.37.0 → ddapm_test_agent-1.39.0}/tests/integration_snapshots/test_trace_distributed_same_payload.json +0 -0
- {ddapm_test_agent-1.37.0 → ddapm_test_agent-1.39.0}/tests/integration_snapshots/test_trace_missing_received.json +0 -0
- {ddapm_test_agent-1.37.0 → ddapm_test_agent-1.39.0}/tests/integration_snapshots/test_trace_stats.json +0 -0
- {ddapm_test_agent-1.37.0 → ddapm_test_agent-1.39.0}/tests/integration_snapshots/test_trace_stats_tracestats.json +0 -0
- {ddapm_test_agent-1.37.0 → ddapm_test_agent-1.39.0}/tests/test_apmtelemetry.py +0 -0
- {ddapm_test_agent-1.37.0 → ddapm_test_agent-1.39.0}/tests/test_checks.py +0 -0
- {ddapm_test_agent-1.37.0 → ddapm_test_agent-1.39.0}/tests/test_client.py +0 -0
- {ddapm_test_agent-1.37.0 → ddapm_test_agent-1.39.0}/tests/test_container.py +0 -0
- {ddapm_test_agent-1.37.0 → ddapm_test_agent-1.39.0}/tests/test_logs.py +0 -0
- {ddapm_test_agent-1.37.0 → ddapm_test_agent-1.39.0}/tests/test_metrics.py +0 -0
- {ddapm_test_agent-1.37.0 → ddapm_test_agent-1.39.0}/tests/test_remoteconfig.py +0 -0
- {ddapm_test_agent-1.37.0 → ddapm_test_agent-1.39.0}/tests/test_session.py +0 -0
- {ddapm_test_agent-1.37.0 → ddapm_test_agent-1.39.0}/tests/test_snapshot.py +0 -0
- {ddapm_test_agent-1.37.0 → ddapm_test_agent-1.39.0}/tests/test_snapshot_integration.py +0 -0
- {ddapm_test_agent-1.37.0 → ddapm_test_agent-1.39.0}/tests/test_trace.py +0 -0
- {ddapm_test_agent-1.37.0 → ddapm_test_agent-1.39.0}/tests/test_tracerflare.py +0 -0
- {ddapm_test_agent-1.37.0 → ddapm_test_agent-1.39.0}/tests/test_tracestats.py +0 -0
- {ddapm_test_agent-1.37.0 → ddapm_test_agent-1.39.0}/tests/trace_utils.py +0 -0
- {ddapm_test_agent-1.37.0 → ddapm_test_agent-1.39.0}/vcr-cassettes/anthropic/anthropic_v1_messages_post_26d618ee.yaml +0 -0
- {ddapm_test_agent-1.37.0 → ddapm_test_agent-1.39.0}/vcr-cassettes/anthropic/anthropic_v1_messages_post_595f439c.yaml +0 -0
- {ddapm_test_agent-1.37.0 → ddapm_test_agent-1.39.0}/vcr-cassettes/anthropic/anthropic_v1_messages_post_717ba0b4.yaml +0 -0
- {ddapm_test_agent-1.37.0 → ddapm_test_agent-1.39.0}/vcr-cassettes/anthropic/anthropic_v1_messages_post_a1af2c12.yaml +0 -0
- {ddapm_test_agent-1.37.0 → ddapm_test_agent-1.39.0}/vcr-cassettes/deepseek/deepseek_chat_completions_post_afb6ccab.yaml +0 -0
- {ddapm_test_agent-1.37.0 → ddapm_test_agent-1.39.0}/vcr-cassettes/openai/openai_audio_transcriptions_post_173af3e5.yaml +0 -0
- {ddapm_test_agent-1.37.0 → ddapm_test_agent-1.39.0}/vcr-cassettes/openai/openai_audio_transcriptions_post_71305a25.yaml +0 -0
- {ddapm_test_agent-1.37.0 → ddapm_test_agent-1.39.0}/vcr-cassettes/openai/openai_audio_translations_post_d5b5b8d6.yaml +0 -0
- {ddapm_test_agent-1.37.0 → ddapm_test_agent-1.39.0}/vcr-cassettes/openai/openai_audio_translations_post_dd92a18a.yaml +0 -0
- {ddapm_test_agent-1.37.0 → ddapm_test_agent-1.39.0}/vcr-cassettes/openai/openai_chat_completions_post_0f1514e1.yaml +0 -0
- {ddapm_test_agent-1.37.0 → ddapm_test_agent-1.39.0}/vcr-cassettes/openai/openai_chat_completions_post_172294b4.yaml +0 -0
- {ddapm_test_agent-1.37.0 → ddapm_test_agent-1.39.0}/vcr-cassettes/openai/openai_chat_completions_post_193ae44a.yaml +0 -0
- {ddapm_test_agent-1.37.0 → ddapm_test_agent-1.39.0}/vcr-cassettes/openai/openai_chat_completions_post_23558eed.yaml +0 -0
- {ddapm_test_agent-1.37.0 → ddapm_test_agent-1.39.0}/vcr-cassettes/openai/openai_chat_completions_post_2edb59ae.yaml +0 -0
- {ddapm_test_agent-1.37.0 → ddapm_test_agent-1.39.0}/vcr-cassettes/openai/openai_chat_completions_post_3517e44e.yaml +0 -0
- {ddapm_test_agent-1.37.0 → ddapm_test_agent-1.39.0}/vcr-cassettes/openai/openai_chat_completions_post_36bdc0cb.yaml +0 -0
- {ddapm_test_agent-1.37.0 → ddapm_test_agent-1.39.0}/vcr-cassettes/openai/openai_chat_completions_post_3c045664.yaml +0 -0
- {ddapm_test_agent-1.37.0 → ddapm_test_agent-1.39.0}/vcr-cassettes/openai/openai_chat_completions_post_432a8e46.yaml +0 -0
- {ddapm_test_agent-1.37.0 → ddapm_test_agent-1.39.0}/vcr-cassettes/openai/openai_chat_completions_post_4749eff9.yaml +0 -0
- {ddapm_test_agent-1.37.0 → ddapm_test_agent-1.39.0}/vcr-cassettes/openai/openai_chat_completions_post_4dce8db6.yaml +0 -0
- {ddapm_test_agent-1.37.0 → ddapm_test_agent-1.39.0}/vcr-cassettes/openai/openai_chat_completions_post_57612363.yaml +0 -0
- {ddapm_test_agent-1.37.0 → ddapm_test_agent-1.39.0}/vcr-cassettes/openai/openai_chat_completions_post_649d8162.yaml +0 -0
- {ddapm_test_agent-1.37.0 → ddapm_test_agent-1.39.0}/vcr-cassettes/openai/openai_chat_completions_post_655a8ef2.yaml +0 -0
- {ddapm_test_agent-1.37.0 → ddapm_test_agent-1.39.0}/vcr-cassettes/openai/openai_chat_completions_post_66dfc80e.yaml +0 -0
- {ddapm_test_agent-1.37.0 → ddapm_test_agent-1.39.0}/vcr-cassettes/openai/openai_chat_completions_post_67e8e833.yaml +0 -0
- {ddapm_test_agent-1.37.0 → ddapm_test_agent-1.39.0}/vcr-cassettes/openai/openai_chat_completions_post_6df851cc.yaml +0 -0
- {ddapm_test_agent-1.37.0 → ddapm_test_agent-1.39.0}/vcr-cassettes/openai/openai_chat_completions_post_7c2d1ac5.yaml +0 -0
- {ddapm_test_agent-1.37.0 → ddapm_test_agent-1.39.0}/vcr-cassettes/openai/openai_chat_completions_post_82a4bb3c.yaml +0 -0
- {ddapm_test_agent-1.37.0 → ddapm_test_agent-1.39.0}/vcr-cassettes/openai/openai_chat_completions_post_9122b1ae.yaml +0 -0
- {ddapm_test_agent-1.37.0 → ddapm_test_agent-1.39.0}/vcr-cassettes/openai/openai_chat_completions_post_917478d0.yaml +0 -0
- {ddapm_test_agent-1.37.0 → ddapm_test_agent-1.39.0}/vcr-cassettes/openai/openai_chat_completions_post_a73ecd7a.yaml +0 -0
- {ddapm_test_agent-1.37.0 → ddapm_test_agent-1.39.0}/vcr-cassettes/openai/openai_chat_completions_post_a925b737.yaml +0 -0
- {ddapm_test_agent-1.37.0 → ddapm_test_agent-1.39.0}/vcr-cassettes/openai/openai_chat_completions_post_ae4728c2.yaml +0 -0
- {ddapm_test_agent-1.37.0 → ddapm_test_agent-1.39.0}/vcr-cassettes/openai/openai_chat_completions_post_b29f1a87.yaml +0 -0
- {ddapm_test_agent-1.37.0 → ddapm_test_agent-1.39.0}/vcr-cassettes/openai/openai_chat_completions_post_ce69ed91.yaml +0 -0
- {ddapm_test_agent-1.37.0 → ddapm_test_agent-1.39.0}/vcr-cassettes/openai/openai_chat_completions_post_d8fb132a.yaml +0 -0
- {ddapm_test_agent-1.37.0 → ddapm_test_agent-1.39.0}/vcr-cassettes/openai/openai_chat_completions_post_d94d5844.yaml +0 -0
- {ddapm_test_agent-1.37.0 → ddapm_test_agent-1.39.0}/vcr-cassettes/openai/openai_chat_completions_post_d98ce00d.yaml +0 -0
- {ddapm_test_agent-1.37.0 → ddapm_test_agent-1.39.0}/vcr-cassettes/openai/openai_chat_completions_post_ebff79da.yaml +0 -0
- {ddapm_test_agent-1.37.0 → ddapm_test_agent-1.39.0}/vcr-cassettes/openai/openai_completions_post_33681ea4.yaml +0 -0
- {ddapm_test_agent-1.37.0 → ddapm_test_agent-1.39.0}/vcr-cassettes/openai/openai_completions_post_5d2418d4.yaml +0 -0
- {ddapm_test_agent-1.37.0 → ddapm_test_agent-1.39.0}/vcr-cassettes/openai/openai_completions_post_619dee1c.yaml +0 -0
- {ddapm_test_agent-1.37.0 → ddapm_test_agent-1.39.0}/vcr-cassettes/openai/openai_completions_post_6224acff.yaml +0 -0
- {ddapm_test_agent-1.37.0 → ddapm_test_agent-1.39.0}/vcr-cassettes/openai/openai_completions_post_87f617af.yaml +0 -0
- {ddapm_test_agent-1.37.0 → ddapm_test_agent-1.39.0}/vcr-cassettes/openai/openai_completions_post_98c30019.yaml +0 -0
- {ddapm_test_agent-1.37.0 → ddapm_test_agent-1.39.0}/vcr-cassettes/openai/openai_completions_post_9bb49464.yaml +0 -0
- {ddapm_test_agent-1.37.0 → ddapm_test_agent-1.39.0}/vcr-cassettes/openai/openai_completions_post_b24dbf7d.yaml +0 -0
- {ddapm_test_agent-1.37.0 → ddapm_test_agent-1.39.0}/vcr-cassettes/openai/openai_embeddings_post_0381abe4.yaml +0 -0
- {ddapm_test_agent-1.37.0 → ddapm_test_agent-1.39.0}/vcr-cassettes/openai/openai_embeddings_post_48694087.yaml +0 -0
- {ddapm_test_agent-1.37.0 → ddapm_test_agent-1.39.0}/vcr-cassettes/openai/openai_embeddings_post_541bd4d0.yaml +0 -0
- {ddapm_test_agent-1.37.0 → ddapm_test_agent-1.39.0}/vcr-cassettes/openai/openai_files_file-RpTpuvRVtnKpdKZb7DDGto_content_get_60bd10ef.yaml +0 -0
- {ddapm_test_agent-1.37.0 → ddapm_test_agent-1.39.0}/vcr-cassettes/openai/openai_files_file-RpTpuvRVtnKpdKZb7DDGto_delete_3ee48409.yaml +0 -0
- {ddapm_test_agent-1.37.0 → ddapm_test_agent-1.39.0}/vcr-cassettes/openai/openai_files_file-RpTpuvRVtnKpdKZb7DDGto_get_1afefb93.yaml +0 -0
- {ddapm_test_agent-1.37.0 → ddapm_test_agent-1.39.0}/vcr-cassettes/openai/openai_files_get_68efa25d.yaml +0 -0
- {ddapm_test_agent-1.37.0 → ddapm_test_agent-1.39.0}/vcr-cassettes/openai/openai_files_post_2fcf9545.yaml +0 -0
- {ddapm_test_agent-1.37.0 → ddapm_test_agent-1.39.0}/vcr-cassettes/openai/openai_files_post_957d63ba.yaml +0 -0
- {ddapm_test_agent-1.37.0 → ddapm_test_agent-1.39.0}/vcr-cassettes/openai/openai_fine_tuning_jobs_ftjob-q9CUUUsHJemGUVQ1Ecc01zcf_cancel_post_d7c16b38.yaml +0 -0
- {ddapm_test_agent-1.37.0 → ddapm_test_agent-1.39.0}/vcr-cassettes/openai/openai_fine_tuning_jobs_ftjob-q9CUUUsHJemGUVQ1Ecc01zcf_events_get_557d820e.yaml +0 -0
- {ddapm_test_agent-1.37.0 → ddapm_test_agent-1.39.0}/vcr-cassettes/openai/openai_fine_tuning_jobs_ftjob-q9CUUUsHJemGUVQ1Ecc01zcf_get_265489e7.yaml +0 -0
- {ddapm_test_agent-1.37.0 → ddapm_test_agent-1.39.0}/vcr-cassettes/openai/openai_fine_tuning_jobs_get_ebc57c6f.yaml +0 -0
- {ddapm_test_agent-1.37.0 → ddapm_test_agent-1.39.0}/vcr-cassettes/openai/openai_fine_tuning_jobs_post_c3b6e4a9.yaml +0 -0
- {ddapm_test_agent-1.37.0 → ddapm_test_agent-1.39.0}/vcr-cassettes/openai/openai_images_edits_post_075386c4.yaml +0 -0
- {ddapm_test_agent-1.37.0 → ddapm_test_agent-1.39.0}/vcr-cassettes/openai/openai_images_edits_post_57b4f4da.yaml +0 -0
- {ddapm_test_agent-1.37.0 → ddapm_test_agent-1.39.0}/vcr-cassettes/openai/openai_images_edits_post_660e9dd7.yaml +0 -0
- {ddapm_test_agent-1.37.0 → ddapm_test_agent-1.39.0}/vcr-cassettes/openai/openai_images_edits_post_993e0192.yaml +0 -0
- {ddapm_test_agent-1.37.0 → ddapm_test_agent-1.39.0}/vcr-cassettes/openai/openai_images_edits_post_a2f1eb43.yaml +0 -0
- {ddapm_test_agent-1.37.0 → ddapm_test_agent-1.39.0}/vcr-cassettes/openai/openai_images_edits_post_ae72c45f.yaml +0 -0
- {ddapm_test_agent-1.37.0 → ddapm_test_agent-1.39.0}/vcr-cassettes/openai/openai_images_edits_post_cf5af376.yaml +0 -0
- {ddapm_test_agent-1.37.0 → ddapm_test_agent-1.39.0}/vcr-cassettes/openai/openai_images_edits_post_dbefb624.yaml +0 -0
- {ddapm_test_agent-1.37.0 → ddapm_test_agent-1.39.0}/vcr-cassettes/openai/openai_images_generations_post_48272841.yaml +0 -0
- {ddapm_test_agent-1.37.0 → ddapm_test_agent-1.39.0}/vcr-cassettes/openai/openai_images_generations_post_736070ea.yaml +0 -0
- {ddapm_test_agent-1.37.0 → ddapm_test_agent-1.39.0}/vcr-cassettes/openai/openai_images_variations_post_5971e285.yaml +0 -0
- {ddapm_test_agent-1.37.0 → ddapm_test_agent-1.39.0}/vcr-cassettes/openai/openai_images_variations_post_f2f62f6c.yaml +0 -0
- {ddapm_test_agent-1.37.0 → ddapm_test_agent-1.39.0}/vcr-cassettes/openai/openai_models_ft_gpt-4.1-mini-2025-04-14_datadog-staging__BkaILRSh_delete_c70f2992.yaml +0 -0
- {ddapm_test_agent-1.37.0 → ddapm_test_agent-1.39.0}/vcr-cassettes/openai/openai_models_get_e04cf04b.yaml +0 -0
- {ddapm_test_agent-1.37.0 → ddapm_test_agent-1.39.0}/vcr-cassettes/openai/openai_models_gpt-4_get_b13c5b23.yaml +0 -0
- {ddapm_test_agent-1.37.0 → ddapm_test_agent-1.39.0}/vcr-cassettes/openai/openai_moderations_post_532b3315.yaml +0 -0
- {ddapm_test_agent-1.37.0 → ddapm_test_agent-1.39.0}/vcr-cassettes/openai/openai_responses_post_33fb1f66.yaml +0 -0
- {ddapm_test_agent-1.37.0 → ddapm_test_agent-1.39.0}/vcr-cassettes/openai/openai_responses_post_5ca556ec.yaml +0 -0
- {ddapm_test_agent-1.37.0 → ddapm_test_agent-1.39.0}/vcr-cassettes/openai/openai_responses_post_c05c936e.yaml +0 -0
- {ddapm_test_agent-1.37.0 → ddapm_test_agent-1.39.0}/vcr-cassettes/openai/openai_responses_post_c61e3067.yaml +0 -0
- {ddapm_test_agent-1.37.0 → ddapm_test_agent-1.39.0}/vcr-cassettes/openai/openai_responses_post_ee2423e6.yaml +0 -0
|
@@ -15,8 +15,8 @@ jobs:
|
|
|
15
15
|
- uses: actions/checkout@08eba0b27e820071cde6df949e0beb9ba4906955 # v4.3.0
|
|
16
16
|
with:
|
|
17
17
|
fetch-depth: 0
|
|
18
|
+
- run: pip install --upgrade 'pip<24.1'
|
|
18
19
|
- run: pip install .[testing]
|
|
19
|
-
- run: riot -v run -s check_fmt
|
|
20
20
|
- run: riot -v run -s flake8
|
|
21
21
|
- run: riot -v run mypy
|
|
22
22
|
test:
|
|
@@ -30,8 +30,14 @@ jobs:
|
|
|
30
30
|
- uses: actions/setup-python@e797f83bcb11b83ae66e0230d6156d7c80228e7c # v6.0.0
|
|
31
31
|
with:
|
|
32
32
|
python-version: ${{ matrix.python-version }}
|
|
33
|
+
- name: Downgrade pip for riot compatibility
|
|
34
|
+
if: runner.os != 'Windows'
|
|
35
|
+
run: pip install --upgrade 'pip<24.1'
|
|
33
36
|
- name: install deps
|
|
34
37
|
run: pip install .[testing]
|
|
38
|
+
- name: install pip-tools
|
|
39
|
+
if: runner.os != 'Windows'
|
|
40
|
+
run: pip install 'pip-tools>=7.4.0'
|
|
35
41
|
# Windows: Use vanilla pytest (riot doesn't support Windows - see https://github.com/DataDog/riot/issues/74)
|
|
36
42
|
- name: Run tests (Windows - direct pytest)
|
|
37
43
|
if: runner.os == 'Windows'
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: ddapm-test-agent
|
|
3
|
-
Version: 1.
|
|
3
|
+
Version: 1.39.0
|
|
4
4
|
Summary: Test agent for Datadog APM client libraries
|
|
5
5
|
Home-page: https://github.com/Datadog/dd-apm-test-agent
|
|
6
6
|
Author: Kyle Verhoog
|
|
@@ -20,9 +20,9 @@ Requires-Dist: msgpack
|
|
|
20
20
|
Requires-Dist: requests
|
|
21
21
|
Requires-Dist: typing_extensions
|
|
22
22
|
Requires-Dist: yarl
|
|
23
|
-
Requires-Dist: vcrpy
|
|
24
23
|
Requires-Dist: requests-aws4auth
|
|
25
24
|
Requires-Dist: jinja2>=3.0.0
|
|
25
|
+
Requires-Dist: pyyaml
|
|
26
26
|
Requires-Dist: opentelemetry-proto<1.37.0,>1.33.0
|
|
27
27
|
Requires-Dist: protobuf>=3.19.0
|
|
28
28
|
Requires-Dist: grpcio<2.0,>=1.66.2
|
|
@@ -883,7 +883,7 @@ class Agent:
|
|
|
883
883
|
async def handle_info(self, request: Request) -> web.Response:
|
|
884
884
|
return web.json_response(
|
|
885
885
|
{
|
|
886
|
-
"version": "test",
|
|
886
|
+
"version": os.environ.get("TEST_AGENT_VERSION", "test"),
|
|
887
887
|
"endpoints": [
|
|
888
888
|
"/v0.4/traces",
|
|
889
889
|
"/v0.5/traces",
|
|
@@ -0,0 +1,495 @@
|
|
|
1
|
+
import asyncio
|
|
2
|
+
import base64
|
|
3
|
+
from dataclasses import dataclass
|
|
4
|
+
from glob import glob
|
|
5
|
+
import hashlib
|
|
6
|
+
import json
|
|
7
|
+
import logging
|
|
8
|
+
import os
|
|
9
|
+
import re
|
|
10
|
+
from typing import Any
|
|
11
|
+
from typing import Dict
|
|
12
|
+
from typing import List
|
|
13
|
+
from typing import Optional
|
|
14
|
+
from typing import Union
|
|
15
|
+
from typing import cast
|
|
16
|
+
from urllib.parse import urljoin
|
|
17
|
+
|
|
18
|
+
from aiohttp.web import Request
|
|
19
|
+
from aiohttp.web import Response
|
|
20
|
+
import requests
|
|
21
|
+
from requests_aws4auth import AWS4Auth
|
|
22
|
+
import yaml
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
logger = logging.getLogger(__name__)
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
@dataclass
|
|
29
|
+
class CassetteDataRequest:
|
|
30
|
+
"""Represents the request portion of a cassette."""
|
|
31
|
+
|
|
32
|
+
method: str
|
|
33
|
+
url: str
|
|
34
|
+
headers: Dict[str, str]
|
|
35
|
+
body: str
|
|
36
|
+
|
|
37
|
+
@classmethod
|
|
38
|
+
def from_dict(cls, data: Dict[str, Any]) -> "CassetteDataRequest":
|
|
39
|
+
"""Create from a dictionary."""
|
|
40
|
+
return cls(
|
|
41
|
+
method=data["method"],
|
|
42
|
+
url=data["url"],
|
|
43
|
+
headers=data["headers"],
|
|
44
|
+
body=data["body"],
|
|
45
|
+
)
|
|
46
|
+
|
|
47
|
+
def to_dict(self) -> Dict[str, Any]:
|
|
48
|
+
"""Convert to a dictionary for JSON serialization."""
|
|
49
|
+
return {
|
|
50
|
+
"method": self.method,
|
|
51
|
+
"url": self.url,
|
|
52
|
+
"headers": self.headers,
|
|
53
|
+
"body": self.body,
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
|
|
57
|
+
@dataclass
|
|
58
|
+
class CassetteDataResponse:
|
|
59
|
+
"""Represents the response portion of a cassette."""
|
|
60
|
+
|
|
61
|
+
status: Dict[str, Any] # {"code": int, "message": str}
|
|
62
|
+
headers: Dict[str, str]
|
|
63
|
+
body: str
|
|
64
|
+
|
|
65
|
+
@classmethod
|
|
66
|
+
def from_dict(cls, data: Dict[str, Any]) -> "CassetteDataResponse":
|
|
67
|
+
"""Create from a dictionary."""
|
|
68
|
+
return cls(
|
|
69
|
+
status=data["status"],
|
|
70
|
+
headers=data["headers"],
|
|
71
|
+
body=data["body"],
|
|
72
|
+
)
|
|
73
|
+
|
|
74
|
+
def to_dict(self) -> Dict[str, Any]:
|
|
75
|
+
"""Convert to a dictionary for JSON serialization."""
|
|
76
|
+
return {
|
|
77
|
+
"status": self.status,
|
|
78
|
+
"headers": self.headers,
|
|
79
|
+
"body": self.body,
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
|
|
83
|
+
@dataclass
|
|
84
|
+
class CassetteData:
|
|
85
|
+
"""Represents a VCR cassette with request and response data."""
|
|
86
|
+
|
|
87
|
+
request: CassetteDataRequest
|
|
88
|
+
response: CassetteDataResponse
|
|
89
|
+
|
|
90
|
+
@classmethod
|
|
91
|
+
def from_dict(cls, data: Dict[str, Any]) -> "CassetteData":
|
|
92
|
+
"""Create from a dictionary (e.g., loaded from JSON)."""
|
|
93
|
+
return cls(
|
|
94
|
+
request=CassetteDataRequest.from_dict(data["request"]),
|
|
95
|
+
response=CassetteDataResponse.from_dict(data["response"]),
|
|
96
|
+
)
|
|
97
|
+
|
|
98
|
+
def to_dict(self) -> Dict[str, Any]:
|
|
99
|
+
"""Convert to a dictionary for JSON serialization."""
|
|
100
|
+
return {
|
|
101
|
+
"request": self.request.to_dict(),
|
|
102
|
+
"response": self.response.to_dict(),
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
|
|
106
|
+
# Used for AWS signature recalculation for aws services initial proxying
|
|
107
|
+
AWS_REGION = os.environ.get("AWS_REGION", "us-east-1")
|
|
108
|
+
AWS_SECRET_ACCESS_KEY = os.environ.get("AWS_SECRET_ACCESS_KEY")
|
|
109
|
+
|
|
110
|
+
|
|
111
|
+
AWS_SERVICES = {
|
|
112
|
+
"bedrock-runtime": "bedrock",
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
|
|
116
|
+
PROVIDER_BASE_URLS = {
|
|
117
|
+
"openai": "https://api.openai.com/v1",
|
|
118
|
+
"azure-openai": "https://dd.openai.azure.com/",
|
|
119
|
+
"deepseek": "https://api.deepseek.com/",
|
|
120
|
+
"anthropic": "https://api.anthropic.com/",
|
|
121
|
+
"datadog": "https://api.datadoghq.com/",
|
|
122
|
+
"genai": "https://generativelanguage.googleapis.com/",
|
|
123
|
+
"bedrock-runtime": f"https://bedrock-runtime.{AWS_REGION}.amazonaws.com",
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
CASSETTE_FILTER_HEADERS = [
|
|
127
|
+
"authorization",
|
|
128
|
+
"OpenAI-Organization",
|
|
129
|
+
"api-key",
|
|
130
|
+
"x-api-key",
|
|
131
|
+
"dd-api-key",
|
|
132
|
+
"dd-application-key",
|
|
133
|
+
"x-goog-api-key",
|
|
134
|
+
"x-amz-security-token",
|
|
135
|
+
"x-amz-content-sha256",
|
|
136
|
+
"x-amz-date",
|
|
137
|
+
"x-amz-user-agent",
|
|
138
|
+
"amz-sdk-invocation-id",
|
|
139
|
+
"amz-sdk-request",
|
|
140
|
+
]
|
|
141
|
+
|
|
142
|
+
NORMALIZERS = [
|
|
143
|
+
(
|
|
144
|
+
r"--form-data-boundary-[^\r\n]+",
|
|
145
|
+
"--form-data-boundary-normalized",
|
|
146
|
+
), # openai file types
|
|
147
|
+
(
|
|
148
|
+
r"------formdata-undici-[^\r\n]+",
|
|
149
|
+
"--form-data-boundary-normalized",
|
|
150
|
+
), # openai file types for undici (node.js)
|
|
151
|
+
]
|
|
152
|
+
|
|
153
|
+
|
|
154
|
+
def _url_path_join(base_url: str, path: str) -> str:
|
|
155
|
+
"""Join a base URL with a path, handling slashes automatically."""
|
|
156
|
+
return urljoin(base_url.rstrip("/") + "/", path.lstrip("/"))
|
|
157
|
+
|
|
158
|
+
|
|
159
|
+
def _file_safe_string(s: str) -> str:
|
|
160
|
+
return "".join(c if c.isalnum() or c in ".-" else "_" for c in s)
|
|
161
|
+
|
|
162
|
+
|
|
163
|
+
def _get_custom_vcr_providers(vcr_provider_map: str) -> Dict[str, str]:
|
|
164
|
+
return dict(
|
|
165
|
+
[
|
|
166
|
+
vcr_provider_map.strip().split("=", 1)
|
|
167
|
+
for vcr_provider_map in vcr_provider_map.split(",")
|
|
168
|
+
if vcr_provider_map.strip()
|
|
169
|
+
]
|
|
170
|
+
)
|
|
171
|
+
|
|
172
|
+
|
|
173
|
+
def _normalize_multipart_body(body: bytes) -> str:
|
|
174
|
+
if not body:
|
|
175
|
+
return ""
|
|
176
|
+
|
|
177
|
+
try:
|
|
178
|
+
body_str = body.decode("utf-8")
|
|
179
|
+
|
|
180
|
+
for pattern, replacement in NORMALIZERS:
|
|
181
|
+
body_str = re.sub(pattern, replacement, body_str)
|
|
182
|
+
|
|
183
|
+
return body_str
|
|
184
|
+
except UnicodeDecodeError:
|
|
185
|
+
try:
|
|
186
|
+
body_str = body.decode("latin-1")
|
|
187
|
+
|
|
188
|
+
for pattern, replacement in NORMALIZERS:
|
|
189
|
+
body_str = re.sub(pattern, replacement, body_str)
|
|
190
|
+
|
|
191
|
+
return body_str
|
|
192
|
+
except Exception:
|
|
193
|
+
hex_digest = hashlib.sha256(body).hexdigest()[:8]
|
|
194
|
+
return f"[binary_data_{hex_digest}]"
|
|
195
|
+
|
|
196
|
+
|
|
197
|
+
def _decode_body(body: bytes) -> str:
|
|
198
|
+
"""Decode body (request or response), handling binary data gracefully."""
|
|
199
|
+
if not body:
|
|
200
|
+
return ""
|
|
201
|
+
|
|
202
|
+
# Check for null bytes - strong indicator of binary data (e.g., event streams, protobuf)
|
|
203
|
+
if b"\x00" in body:
|
|
204
|
+
return "base64:" + base64.b64encode(body).decode("ascii")
|
|
205
|
+
|
|
206
|
+
try:
|
|
207
|
+
# Try UTF-8 decode - if successful, it's text
|
|
208
|
+
return body.decode("utf-8")
|
|
209
|
+
except UnicodeDecodeError:
|
|
210
|
+
# If UTF-8 fails, treat as binary
|
|
211
|
+
return "base64:" + base64.b64encode(body).decode("ascii")
|
|
212
|
+
|
|
213
|
+
|
|
214
|
+
def _encode_body(body: str) -> bytes:
|
|
215
|
+
"""Convert cassette body string back to bytes, handling base64-encoded data."""
|
|
216
|
+
if not body:
|
|
217
|
+
return b""
|
|
218
|
+
|
|
219
|
+
# Check for base64 marker first (for binary data that was base64-encoded)
|
|
220
|
+
if body.startswith("base64:"):
|
|
221
|
+
return base64.b64decode(body[7:])
|
|
222
|
+
|
|
223
|
+
try:
|
|
224
|
+
# Try to encode as UTF-8 (most common case)
|
|
225
|
+
return body.encode("utf-8")
|
|
226
|
+
except UnicodeEncodeError:
|
|
227
|
+
# If all else fails, encode as latin-1
|
|
228
|
+
return body.encode("latin-1")
|
|
229
|
+
|
|
230
|
+
|
|
231
|
+
def _parse_authorization_header(auth_header: str) -> Dict[str, str]:
|
|
232
|
+
"""Parse AWS Authorization header to extract components"""
|
|
233
|
+
if not auth_header.startswith("AWS4-HMAC-SHA256 "):
|
|
234
|
+
return {}
|
|
235
|
+
|
|
236
|
+
auth_parts = auth_header[len("AWS4-HMAC-SHA256 ") :].split(",")
|
|
237
|
+
parsed = {}
|
|
238
|
+
|
|
239
|
+
for part in auth_parts:
|
|
240
|
+
key, value = part.split("=", 1)
|
|
241
|
+
parsed[key.strip()] = value.strip()
|
|
242
|
+
|
|
243
|
+
return parsed
|
|
244
|
+
|
|
245
|
+
|
|
246
|
+
def _generate_cassette_name(path: str, method: str, body: bytes, vcr_cassette_prefix: Optional[str]) -> str:
|
|
247
|
+
decoded_body = _normalize_multipart_body(body) if body else ""
|
|
248
|
+
try:
|
|
249
|
+
parsed_body = json.loads(decoded_body) if decoded_body else {}
|
|
250
|
+
except json.JSONDecodeError:
|
|
251
|
+
parsed_body = decoded_body
|
|
252
|
+
|
|
253
|
+
request_details = f"{path}:{method}:{json.dumps(parsed_body, sort_keys=True)}"
|
|
254
|
+
hash_object = hashlib.sha256(request_details.encode())
|
|
255
|
+
hash_hex = hash_object.hexdigest()[:8]
|
|
256
|
+
safe_path = _file_safe_string(path)
|
|
257
|
+
|
|
258
|
+
safe_vcr_cassette_prefix = _file_safe_string(vcr_cassette_prefix) if vcr_cassette_prefix else None
|
|
259
|
+
|
|
260
|
+
return (
|
|
261
|
+
f"{safe_vcr_cassette_prefix}_{safe_path}_{method.lower()}_{hash_hex}"
|
|
262
|
+
if safe_vcr_cassette_prefix
|
|
263
|
+
else f"{safe_path}_{method.lower()}_{hash_hex}"
|
|
264
|
+
)
|
|
265
|
+
|
|
266
|
+
|
|
267
|
+
def _convert_vcr_cassette_to_custom_format(
|
|
268
|
+
cassette_file_path: str,
|
|
269
|
+
request_kwargs: Dict[str, Any],
|
|
270
|
+
vcr_ignore_headers: str,
|
|
271
|
+
) -> CassetteData:
|
|
272
|
+
"""Convert a VCR YAML cassette to our custom JSON format."""
|
|
273
|
+
cassette_file_path_yaml = f"{cassette_file_path}.yaml"
|
|
274
|
+
with open(cassette_file_path_yaml, "r") as f:
|
|
275
|
+
cassette_data = yaml.load(f, Loader=yaml.UnsafeLoader)
|
|
276
|
+
|
|
277
|
+
interaction = cast(Dict[str, Any], cassette_data["interactions"][0])
|
|
278
|
+
|
|
279
|
+
cassette = _write_cassette_file(cassette_file_path, request_kwargs, interaction["response"], vcr_ignore_headers)
|
|
280
|
+
|
|
281
|
+
logger.warning(f"Removing legacy VCR cassette file {cassette_file_path_yaml}.")
|
|
282
|
+
os.remove(cassette_file_path_yaml)
|
|
283
|
+
|
|
284
|
+
return cassette
|
|
285
|
+
|
|
286
|
+
|
|
287
|
+
def _normalize_header_value(value: Any) -> str:
|
|
288
|
+
"""Normalize header value to a string (handles list values)."""
|
|
289
|
+
if isinstance(value, list):
|
|
290
|
+
return str(value[0]) if value else ""
|
|
291
|
+
return str(value)
|
|
292
|
+
|
|
293
|
+
|
|
294
|
+
def _filter_headers(headers: Dict[str, Any], ignore_headers: List[str]) -> Dict[str, str]:
|
|
295
|
+
"""Filter headers and normalize their values."""
|
|
296
|
+
return {key: _normalize_header_value(value) for key, value in headers.items() if key.lower() not in ignore_headers}
|
|
297
|
+
|
|
298
|
+
|
|
299
|
+
def _create_cassette_from_requests_response(
|
|
300
|
+
request_kwargs: Dict[str, Any],
|
|
301
|
+
response: requests.Response,
|
|
302
|
+
ignore_headers: List[str],
|
|
303
|
+
) -> CassetteData:
|
|
304
|
+
"""Create cassette data from a requests.Response object."""
|
|
305
|
+
logger.info(f"Creating cassette data from requests.Response object: {response.content!r}")
|
|
306
|
+
return CassetteData(
|
|
307
|
+
request=CassetteDataRequest(
|
|
308
|
+
method=request_kwargs["method"],
|
|
309
|
+
url=request_kwargs["url"],
|
|
310
|
+
headers=_filter_headers(request_kwargs["headers"], ignore_headers),
|
|
311
|
+
body=_decode_body(request_kwargs["data"]) if request_kwargs["data"] else "",
|
|
312
|
+
),
|
|
313
|
+
response=CassetteDataResponse(
|
|
314
|
+
status={
|
|
315
|
+
"code": response.status_code,
|
|
316
|
+
"message": response.reason or "",
|
|
317
|
+
},
|
|
318
|
+
headers=_filter_headers(dict(response.headers), ignore_headers),
|
|
319
|
+
body=_decode_body(response.content) if response.content else "",
|
|
320
|
+
),
|
|
321
|
+
)
|
|
322
|
+
|
|
323
|
+
|
|
324
|
+
def _create_cassette_from_dict(
|
|
325
|
+
request_kwargs: Dict[str, Any],
|
|
326
|
+
response_dict: Dict[str, Any],
|
|
327
|
+
ignore_headers: List[str],
|
|
328
|
+
) -> CassetteData:
|
|
329
|
+
"""Create cassette data from a dictionary (e.g., from VCR YAML)."""
|
|
330
|
+
body_data = response_dict["body"]["string"]
|
|
331
|
+
if isinstance(body_data, bytes):
|
|
332
|
+
body_str = _decode_body(body_data)
|
|
333
|
+
else:
|
|
334
|
+
body_str = body_data
|
|
335
|
+
|
|
336
|
+
return CassetteData(
|
|
337
|
+
request=CassetteDataRequest(
|
|
338
|
+
method=request_kwargs["method"],
|
|
339
|
+
url=request_kwargs["url"],
|
|
340
|
+
headers=_filter_headers(request_kwargs["headers"], ignore_headers),
|
|
341
|
+
body=_decode_body(request_kwargs["data"]) if request_kwargs["data"] else "",
|
|
342
|
+
),
|
|
343
|
+
response=CassetteDataResponse(
|
|
344
|
+
status={
|
|
345
|
+
"code": response_dict["status"]["code"],
|
|
346
|
+
"message": response_dict["status"]["message"],
|
|
347
|
+
},
|
|
348
|
+
headers=_filter_headers(response_dict["headers"], ignore_headers),
|
|
349
|
+
body=body_str,
|
|
350
|
+
),
|
|
351
|
+
)
|
|
352
|
+
|
|
353
|
+
|
|
354
|
+
def _write_cassette_file(
|
|
355
|
+
cassette_file_path: str,
|
|
356
|
+
request_kwargs: Dict[str, Any],
|
|
357
|
+
response: Union[requests.Response, Dict[str, Any]],
|
|
358
|
+
vcr_ignore_headers: str,
|
|
359
|
+
) -> CassetteData:
|
|
360
|
+
"""Write cassette data to a JSON file."""
|
|
361
|
+
cassette_file_path_json = f"{cassette_file_path}.json"
|
|
362
|
+
logger.info(f"Writing cassette file to {cassette_file_path_json}")
|
|
363
|
+
|
|
364
|
+
cassette_dir = os.path.dirname(cassette_file_path_json)
|
|
365
|
+
os.makedirs(cassette_dir, exist_ok=True)
|
|
366
|
+
|
|
367
|
+
ignore_headers_list = [
|
|
368
|
+
header.lower() for header in CASSETTE_FILTER_HEADERS + vcr_ignore_headers.split(",") if header
|
|
369
|
+
]
|
|
370
|
+
|
|
371
|
+
if isinstance(response, requests.Response):
|
|
372
|
+
cassette = _create_cassette_from_requests_response(request_kwargs, response, ignore_headers_list)
|
|
373
|
+
else:
|
|
374
|
+
# conversion of legacy VCR cassette to JSON format
|
|
375
|
+
cassette = _create_cassette_from_dict(request_kwargs, response, ignore_headers_list)
|
|
376
|
+
|
|
377
|
+
with open(cassette_file_path_json, "w") as f:
|
|
378
|
+
json.dump(cassette.to_dict(), f, indent=2)
|
|
379
|
+
|
|
380
|
+
return cassette
|
|
381
|
+
|
|
382
|
+
|
|
383
|
+
async def _request(
|
|
384
|
+
cassette_file_path: str, cassette_exists: bool, request_kwargs: Dict[str, Any], vcr_ignore_headers: str
|
|
385
|
+
) -> Response:
|
|
386
|
+
"""
|
|
387
|
+
Load a cassette from file if it exists, otherwise make a request and save the response.
|
|
388
|
+
|
|
389
|
+
If the cassette was created with the VCR package (YAML format), convert it to JSON format.
|
|
390
|
+
"""
|
|
391
|
+
logger.info(f"Making a request to {request_kwargs['url']} with method {request_kwargs['method']}")
|
|
392
|
+
|
|
393
|
+
cassette: Optional[CassetteData] = None
|
|
394
|
+
|
|
395
|
+
if cassette_exists:
|
|
396
|
+
logger.info(f"Cassette file exists at {cassette_file_path}")
|
|
397
|
+
cassette_files = glob(f"{cassette_file_path}.*")
|
|
398
|
+
if not cassette_files:
|
|
399
|
+
raise FileNotFoundError(f"Expected cassette file at {cassette_file_path}.*")
|
|
400
|
+
|
|
401
|
+
file_extension = os.path.splitext(cassette_files[0])[1]
|
|
402
|
+
|
|
403
|
+
if file_extension == ".yaml": # TODO(sabrenner): in a breaking change, remove this
|
|
404
|
+
logger.warning(
|
|
405
|
+
"Converting legacy VCR cassette to JSON format. This will not be supported in ddapm-test-agent==2.0.0"
|
|
406
|
+
)
|
|
407
|
+
cassette = _convert_vcr_cassette_to_custom_format(cassette_file_path, request_kwargs, vcr_ignore_headers)
|
|
408
|
+
elif file_extension == ".json":
|
|
409
|
+
cassette_file_path_json = f"{cassette_file_path}.json"
|
|
410
|
+
with open(cassette_file_path_json, "r") as f:
|
|
411
|
+
cassette = CassetteData.from_dict(json.load(f))
|
|
412
|
+
else:
|
|
413
|
+
raise ValueError(f"Unsupported cassette file extension: {file_extension}")
|
|
414
|
+
else:
|
|
415
|
+
logger.info(f"Cassette file does not exist at {cassette_file_path}, making a request to the provider")
|
|
416
|
+
provider_response = await asyncio.to_thread(lambda: requests.request(**request_kwargs))
|
|
417
|
+
cassette = _write_cassette_file(cassette_file_path, request_kwargs, provider_response, vcr_ignore_headers)
|
|
418
|
+
|
|
419
|
+
# Build response from cassette data
|
|
420
|
+
response_body_str = cassette.response.body
|
|
421
|
+
response_body = _encode_body(response_body_str) if isinstance(response_body_str, str) else b""
|
|
422
|
+
|
|
423
|
+
response = Response(
|
|
424
|
+
body=response_body,
|
|
425
|
+
status=cassette.response.status["code"],
|
|
426
|
+
)
|
|
427
|
+
|
|
428
|
+
skip_headers = {"content-length", "transfer-encoding", "content-encoding", "connection"}
|
|
429
|
+
for key, value in cassette.response.headers.items():
|
|
430
|
+
if key.lower() not in skip_headers:
|
|
431
|
+
response.headers[key] = value
|
|
432
|
+
|
|
433
|
+
return response
|
|
434
|
+
|
|
435
|
+
|
|
436
|
+
async def proxy_request(
|
|
437
|
+
request: Request, vcr_cassettes_directory: str, vcr_ci_mode: bool, vcr_provider_map: str, vcr_ignore_headers: str
|
|
438
|
+
) -> Response:
|
|
439
|
+
provider_base_urls = PROVIDER_BASE_URLS.copy()
|
|
440
|
+
provider_base_urls.update(_get_custom_vcr_providers(vcr_provider_map))
|
|
441
|
+
|
|
442
|
+
path = request.match_info["path"]
|
|
443
|
+
if request.query_string:
|
|
444
|
+
path = path + "?" + request.query_string
|
|
445
|
+
|
|
446
|
+
parts = path.split("/", 1)
|
|
447
|
+
if len(parts) != 2:
|
|
448
|
+
return Response(body="Invalid path format. Expected /{provider}/...", status=400)
|
|
449
|
+
|
|
450
|
+
provider, remaining_path = parts
|
|
451
|
+
if provider not in provider_base_urls:
|
|
452
|
+
return Response(body=f"Unsupported provider: {provider}", status=400)
|
|
453
|
+
|
|
454
|
+
body_bytes = await request.read()
|
|
455
|
+
|
|
456
|
+
vcr_cassette_prefix = request.pop("vcr_cassette_prefix", None)
|
|
457
|
+
cassette_name = _generate_cassette_name(path, request.method, body_bytes, vcr_cassette_prefix)
|
|
458
|
+
cassette_file_path = os.path.join(vcr_cassettes_directory, provider, cassette_name)
|
|
459
|
+
cassette_exists = len(glob(f"{cassette_file_path}.*")) > 0
|
|
460
|
+
|
|
461
|
+
if vcr_ci_mode and not cassette_exists:
|
|
462
|
+
return Response(
|
|
463
|
+
body=f"Cassette {cassette_name} not found while running in CI mode. Please generate the cassette locally and commit it.",
|
|
464
|
+
status=500,
|
|
465
|
+
)
|
|
466
|
+
|
|
467
|
+
target_url = _url_path_join(provider_base_urls[provider], remaining_path)
|
|
468
|
+
skip_headers = {"host", "transfer-encoding"}
|
|
469
|
+
headers = {key: value for key, value in request.headers.items() if not (key.lower() in skip_headers)}
|
|
470
|
+
|
|
471
|
+
request_kwargs: Dict[str, Any] = {
|
|
472
|
+
"method": request.method,
|
|
473
|
+
"url": target_url,
|
|
474
|
+
"headers": headers,
|
|
475
|
+
"data": body_bytes,
|
|
476
|
+
"cookies": dict(request.cookies),
|
|
477
|
+
"allow_redirects": False,
|
|
478
|
+
"stream": True,
|
|
479
|
+
}
|
|
480
|
+
|
|
481
|
+
if provider in AWS_SERVICES and not cassette_exists:
|
|
482
|
+
if not AWS_SECRET_ACCESS_KEY:
|
|
483
|
+
return Response(
|
|
484
|
+
body="AWS_SECRET_ACCESS_KEY environment variable not set for aws signature recalculation",
|
|
485
|
+
status=400,
|
|
486
|
+
)
|
|
487
|
+
|
|
488
|
+
auth_header = request.headers.get("Authorization", "")
|
|
489
|
+
auth_parts = _parse_authorization_header(auth_header)
|
|
490
|
+
aws_access_key = auth_parts.get("Credential", "").split("/")[0]
|
|
491
|
+
|
|
492
|
+
auth = AWS4Auth(aws_access_key, AWS_SECRET_ACCESS_KEY, AWS_REGION, AWS_SERVICES[provider])
|
|
493
|
+
request_kwargs["auth"] = auth
|
|
494
|
+
|
|
495
|
+
return await _request(cassette_file_path, cassette_exists, request_kwargs, vcr_ignore_headers)
|
|
@@ -797,7 +797,7 @@ class WebUI:
|
|
|
797
797
|
|
|
798
798
|
# Get flares for all other session tokens
|
|
799
799
|
session_tokens = set()
|
|
800
|
-
for req_data in
|
|
800
|
+
for req_data in request_storage.get_all_requests() if request_storage is not None else []:
|
|
801
801
|
token = req_data.get("headers", {}).get("X-Datadog-Test-Session-Token")
|
|
802
802
|
if token:
|
|
803
803
|
session_tokens.add(token)
|
|
@@ -934,7 +934,7 @@ class WebUI:
|
|
|
934
934
|
|
|
935
935
|
# Get flares for all other session tokens
|
|
936
936
|
session_tokens = set()
|
|
937
|
-
for req_data in
|
|
937
|
+
for req_data in request_storage.get_all_requests() if request_storage is not None else []:
|
|
938
938
|
token = req_data.get("headers", {}).get("X-Datadog-Test-Session-Token")
|
|
939
939
|
if token:
|
|
940
940
|
session_tokens.add(token)
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: ddapm-test-agent
|
|
3
|
-
Version: 1.
|
|
3
|
+
Version: 1.39.0
|
|
4
4
|
Summary: Test agent for Datadog APM client libraries
|
|
5
5
|
Home-page: https://github.com/Datadog/dd-apm-test-agent
|
|
6
6
|
Author: Kyle Verhoog
|
|
@@ -20,9 +20,9 @@ Requires-Dist: msgpack
|
|
|
20
20
|
Requires-Dist: requests
|
|
21
21
|
Requires-Dist: typing_extensions
|
|
22
22
|
Requires-Dist: yarl
|
|
23
|
-
Requires-Dist: vcrpy
|
|
24
23
|
Requires-Dist: requests-aws4auth
|
|
25
24
|
Requires-Dist: jinja2>=3.0.0
|
|
25
|
+
Requires-Dist: pyyaml
|
|
26
26
|
Requires-Dist: opentelemetry-proto<1.37.0,>1.33.0
|
|
27
27
|
Requires-Dist: protobuf>=3.19.0
|
|
28
28
|
Requires-Dist: grpcio<2.0,>=1.66.2
|
|
@@ -93,6 +93,7 @@ releasenotes/notes/check-http-header-sensitivity-daaa9d9595ae86d6.yaml
|
|
|
93
93
|
releasenotes/notes/clearing-sessions-now-only-removes-6b0311673d8b37aa.yaml
|
|
94
94
|
releasenotes/notes/client-173dbc6655e42337.yaml
|
|
95
95
|
releasenotes/notes/content_length-e1bab75580aa1dcb.yaml
|
|
96
|
+
releasenotes/notes/controllable-test-agent-version-a12e61934bbce5fe.yaml
|
|
96
97
|
releasenotes/notes/disable-error-responses-and-collect-trace-failures-in-memory-4a199bc7be416709.yaml
|
|
97
98
|
releasenotes/notes/docker-arm64-images-a4b6b2cc527327d6.yaml
|
|
98
99
|
releasenotes/notes/evp-proxy-on-info-d65cd077575306ca.yaml
|
|
@@ -108,6 +109,7 @@ releasenotes/notes/fix-racecondition-9bd0ef15b7da60fa.yaml
|
|
|
108
109
|
releasenotes/notes/fix-tracerflare-request-parsing-fae18ff9997c216d.yaml
|
|
109
110
|
releasenotes/notes/genai-vcr-support-b499ec54df84eaa3.yaml
|
|
110
111
|
releasenotes/notes/ignore-dsm-pathway-hash-during-trace-snapshots-f0b99ea267fbad48.yaml
|
|
112
|
+
releasenotes/notes/ignore-transfer-encoding-header-3b22699615356f91.yaml
|
|
111
113
|
releasenotes/notes/image-optimization-d614eccb59441217.yaml
|
|
112
114
|
releasenotes/notes/improve-test-agent-debugging-5759413f1fc5f7fa.yaml
|
|
113
115
|
releasenotes/notes/improve-test-agent-proxying-a207f0fc81b3ab2d.yaml
|
|
@@ -137,6 +139,7 @@ releasenotes/notes/remoteconfig-requests-1af7abb99c61c069.yaml
|
|
|
137
139
|
releasenotes/notes/remove-agent-state-header-from-info-87f920bf4ce5785c.yaml
|
|
138
140
|
releasenotes/notes/remove-nix-ec1c4aca7dc002c4.yaml
|
|
139
141
|
releasenotes/notes/remove-old-pythons-4667b182aacf0ce6.yaml
|
|
142
|
+
releasenotes/notes/remove-vcr-dependancy-ea09889df42b3975.yaml
|
|
140
143
|
releasenotes/notes/reuse-session-1670aa569907cf68.yaml
|
|
141
144
|
releasenotes/notes/sample-rate-1e06ae4cdc933b14.yaml
|
|
142
145
|
releasenotes/notes/session-requests-b8057811f976220e.yaml
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
---
|
|
2
|
+
deprecations:
|
|
3
|
+
- |
|
|
4
|
+
VCR has been removed as a dependency, and instead JSON cassettes are produced. Legacy VCR cassettes are converted to JSON on first use, and the old VCR cassettes are removed. This functionality will be removed in ddapm-test-agent==2.0.0, at which point only JSON cassettes will be written and read.
|
|
@@ -33,9 +33,9 @@ setup(
|
|
|
33
33
|
"requests",
|
|
34
34
|
"typing_extensions",
|
|
35
35
|
"yarl",
|
|
36
|
-
"vcrpy",
|
|
37
36
|
"requests-aws4auth",
|
|
38
37
|
"jinja2>=3.0.0",
|
|
38
|
+
"pyyaml",
|
|
39
39
|
# ddtrace libraries officially support opentelemetry-proto 1.33.1
|
|
40
40
|
# which implements the v1.7.0 spec
|
|
41
41
|
"opentelemetry-proto>1.33.0,<1.37.0",
|
|
@@ -119,6 +119,21 @@ async def test_info(agent):
|
|
|
119
119
|
}
|
|
120
120
|
|
|
121
121
|
|
|
122
|
+
async def test_info_custom_version(agent, monkeypatch):
|
|
123
|
+
custom_version = "1.2.3"
|
|
124
|
+
monkeypatch.setenv("TEST_AGENT_VERSION", custom_version)
|
|
125
|
+
|
|
126
|
+
resp = await agent.get("/info")
|
|
127
|
+
assert resp.status == 200
|
|
128
|
+
|
|
129
|
+
info = await resp.json()
|
|
130
|
+
assert info["version"] == custom_version
|
|
131
|
+
|
|
132
|
+
# Verify other fields are still present
|
|
133
|
+
assert "endpoints" in info
|
|
134
|
+
assert "peer_tags" in info
|
|
135
|
+
|
|
136
|
+
|
|
122
137
|
async def test_apmtelemetry(
|
|
123
138
|
agent,
|
|
124
139
|
v2_reference_http_apmtelemetry_payload_headers,
|