ddapm-test-agent 1.31.0__tar.gz → 1.32.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.31.0 → ddapm_test_agent-1.32.0}/PKG-INFO +55 -2
- {ddapm_test_agent-1.31.0 → ddapm_test_agent-1.32.0}/README.md +51 -1
- {ddapm_test_agent-1.31.0 → ddapm_test_agent-1.32.0}/ddapm_test_agent/agent.py +240 -3
- {ddapm_test_agent-1.31.0 → ddapm_test_agent-1.32.0}/ddapm_test_agent/client.py +63 -20
- ddapm_test_agent-1.32.0/ddapm_test_agent/logs.py +67 -0
- ddapm_test_agent-1.32.0/ddapm_test_agent/metrics.py +94 -0
- {ddapm_test_agent-1.31.0 → ddapm_test_agent-1.32.0}/ddapm_test_agent/trace.py +399 -0
- {ddapm_test_agent-1.31.0 → ddapm_test_agent-1.32.0}/ddapm_test_agent.egg-info/PKG-INFO +55 -2
- {ddapm_test_agent-1.31.0 → ddapm_test_agent-1.32.0}/ddapm_test_agent.egg-info/SOURCES.txt +9 -0
- {ddapm_test_agent-1.31.0 → ddapm_test_agent-1.32.0}/ddapm_test_agent.egg-info/requires.txt +3 -0
- {ddapm_test_agent-1.31.0 → ddapm_test_agent-1.32.0}/flake.nix +4 -1
- ddapm_test_agent-1.32.0/releasenotes/notes/acceptV1TracePayloads-5435cff37cfb6a85.yaml +4 -0
- ddapm_test_agent-1.32.0/releasenotes/notes/add-otel-metrics-support-a2ebeb28cae2f0ba.yaml +7 -0
- ddapm_test_agent-1.32.0/releasenotes/notes/otlp-logs-grpc-45365879c22969aa.yaml +5 -0
- ddapm_test_agent-1.32.0/releasenotes/notes/otlp-logs-support-d5a150d9f5304d7c.yaml +4 -0
- ddapm_test_agent-1.32.0/releasenotes/notes/vcr-cassette-name-middleware-fix-9e47c395892a9fe7.yaml +4 -0
- {ddapm_test_agent-1.31.0 → ddapm_test_agent-1.32.0}/setup.cfg +1 -1
- {ddapm_test_agent-1.31.0 → ddapm_test_agent-1.32.0}/setup.py +5 -0
- {ddapm_test_agent-1.31.0 → ddapm_test_agent-1.32.0}/tests/conftest.py +237 -11
- {ddapm_test_agent-1.31.0 → ddapm_test_agent-1.32.0}/tests/test_agent.py +341 -8
- ddapm_test_agent-1.32.0/tests/test_logs.py +386 -0
- ddapm_test_agent-1.32.0/tests/test_metrics.py +523 -0
- {ddapm_test_agent-1.31.0 → ddapm_test_agent-1.32.0}/.dockerignore +0 -0
- {ddapm_test_agent-1.31.0 → ddapm_test_agent-1.32.0}/.envrc.example +0 -0
- {ddapm_test_agent-1.31.0 → ddapm_test_agent-1.32.0}/.github/workflows/docker.yml +0 -0
- {ddapm_test_agent-1.31.0 → ddapm_test_agent-1.32.0}/.github/workflows/main.yml +0 -0
- {ddapm_test_agent-1.31.0 → ddapm_test_agent-1.32.0}/.github/workflows/nix-auto.yml +0 -0
- {ddapm_test_agent-1.31.0 → ddapm_test_agent-1.32.0}/.github/workflows/publish_pypi.yml +0 -0
- {ddapm_test_agent-1.31.0 → ddapm_test_agent-1.32.0}/.github/workflows/releasenote.yml +0 -0
- {ddapm_test_agent-1.31.0 → ddapm_test_agent-1.32.0}/.gitignore +0 -0
- {ddapm_test_agent-1.31.0 → ddapm_test_agent-1.32.0}/Dockerfile +0 -0
- {ddapm_test_agent-1.31.0 → ddapm_test_agent-1.32.0}/Dockerfile.windows +0 -0
- {ddapm_test_agent-1.31.0 → ddapm_test_agent-1.32.0}/LICENSE.BSD3 +0 -0
- {ddapm_test_agent-1.31.0 → ddapm_test_agent-1.32.0}/LICENSE.apache2 +0 -0
- {ddapm_test_agent-1.31.0 → ddapm_test_agent-1.32.0}/build-on-darwin.Dockerfile +0 -0
- {ddapm_test_agent-1.31.0 → ddapm_test_agent-1.32.0}/ddapm_test_agent/__init__.py +0 -0
- {ddapm_test_agent-1.31.0 → ddapm_test_agent-1.32.0}/ddapm_test_agent/apmtelemetry.py +0 -0
- {ddapm_test_agent-1.31.0 → ddapm_test_agent-1.32.0}/ddapm_test_agent/checks.py +0 -0
- {ddapm_test_agent-1.31.0 → ddapm_test_agent-1.32.0}/ddapm_test_agent/cmd.py +0 -0
- {ddapm_test_agent-1.31.0 → ddapm_test_agent-1.32.0}/ddapm_test_agent/context.py +0 -0
- {ddapm_test_agent-1.31.0 → ddapm_test_agent-1.32.0}/ddapm_test_agent/fmt.py +0 -0
- {ddapm_test_agent-1.31.0 → ddapm_test_agent-1.32.0}/ddapm_test_agent/integration.py +0 -0
- {ddapm_test_agent-1.31.0 → ddapm_test_agent-1.32.0}/ddapm_test_agent/remoteconfig.py +0 -0
- {ddapm_test_agent-1.31.0 → ddapm_test_agent-1.32.0}/ddapm_test_agent/trace_checks.py +0 -0
- {ddapm_test_agent-1.31.0 → ddapm_test_agent-1.32.0}/ddapm_test_agent/trace_snapshot.py +0 -0
- {ddapm_test_agent-1.31.0 → ddapm_test_agent-1.32.0}/ddapm_test_agent/tracerflare.py +0 -0
- {ddapm_test_agent-1.31.0 → ddapm_test_agent-1.32.0}/ddapm_test_agent/tracestats.py +0 -0
- {ddapm_test_agent-1.31.0 → ddapm_test_agent-1.32.0}/ddapm_test_agent/tracestats_snapshot.py +0 -0
- {ddapm_test_agent-1.31.0 → ddapm_test_agent-1.32.0}/ddapm_test_agent/vcr_proxy.py +0 -0
- {ddapm_test_agent-1.31.0 → ddapm_test_agent-1.32.0}/ddapm_test_agent.egg-info/dependency_links.txt +0 -0
- {ddapm_test_agent-1.31.0 → ddapm_test_agent-1.32.0}/ddapm_test_agent.egg-info/entry_points.txt +0 -0
- {ddapm_test_agent-1.31.0 → ddapm_test_agent-1.32.0}/ddapm_test_agent.egg-info/not-zip-safe +0 -0
- {ddapm_test_agent-1.31.0 → ddapm_test_agent-1.32.0}/ddapm_test_agent.egg-info/top_level.txt +0 -0
- {ddapm_test_agent-1.31.0 → ddapm_test_agent-1.32.0}/ddsketch.nix +0 -0
- {ddapm_test_agent-1.31.0 → ddapm_test_agent-1.32.0}/ddtrace.nix +0 -0
- {ddapm_test_agent-1.31.0 → ddapm_test_agent-1.32.0}/flake.lock +0 -0
- {ddapm_test_agent-1.31.0 → ddapm_test_agent-1.32.0}/pyproject.toml +0 -0
- {ddapm_test_agent-1.31.0 → ddapm_test_agent-1.32.0}/releasenotes/check-releasenotes +0 -0
- {ddapm_test_agent-1.31.0 → ddapm_test_agent-1.32.0}/releasenotes/config.yaml +0 -0
- {ddapm_test_agent-1.31.0 → ddapm_test_agent-1.32.0}/releasenotes/notes/1.0-e192f5064e917083.yaml +0 -0
- {ddapm_test_agent-1.31.0 → ddapm_test_agent-1.32.0}/releasenotes/notes/Add-metrics.process_id-to-ignored-attributes-62b264f0ea591326.yaml +0 -0
- {ddapm_test_agent-1.31.0 → ddapm_test_agent-1.32.0}/releasenotes/notes/Add-values-handling-to-span_event-array_value-to-mirror-agent-ee7483c90c263ff4.yaml +0 -0
- {ddapm_test_agent-1.31.0 → ddapm_test_agent-1.32.0}/releasenotes/notes/Checks-changed-to-opt-in-8716cac4ecdbb1c2.yaml +0 -0
- {ddapm_test_agent-1.31.0 → ddapm_test_agent-1.32.0}/releasenotes/notes/SNAPSHOT_REGEX_PLACEHOLDERS-1d2c5e2711d1953b.yaml +0 -0
- {ddapm_test_agent-1.31.0 → ddapm_test_agent-1.32.0}/releasenotes/notes/SNAPSHOT_REGEX_PLACEHOLDERS-compare-c829e7a4df4fa1f4.yaml +0 -0
- {ddapm_test_agent-1.31.0 → ddapm_test_agent-1.32.0}/releasenotes/notes/Settings-endpoint-928ae5b6e8ddc625.yaml +0 -0
- {ddapm_test_agent-1.31.0 → ddapm_test_agent-1.32.0}/releasenotes/notes/Telemetry-requests-delay-2586180b286ce393.yaml +0 -0
- {ddapm_test_agent-1.31.0 → ddapm_test_agent-1.32.0}/releasenotes/notes/Use-default-value-for-null-fields-in-tracestats-55d465f489efb2ba.yaml +0 -0
- {ddapm_test_agent-1.31.0 → ddapm_test_agent-1.32.0}/releasenotes/notes/add-datadog-proxy-7e2e608c101a564b.yaml +0 -0
- {ddapm_test_agent-1.31.0 → ddapm_test_agent-1.32.0}/releasenotes/notes/add-distributed-trace-c35a314698a3b966.yaml +0 -0
- {ddapm_test_agent-1.31.0 → ddapm_test_agent-1.32.0}/releasenotes/notes/add-fmt-command-cc31769942a5fec3.yaml +0 -0
- {ddapm_test_agent-1.31.0 → ddapm_test_agent-1.32.0}/releasenotes/notes/add-nix-build-support-29dc8a347e3bd7c1.yaml +0 -0
- {ddapm_test_agent-1.31.0 → ddapm_test_agent-1.32.0}/releasenotes/notes/add-optional-json-parser-10aac54bd1cbe322.yaml +0 -0
- {ddapm_test_agent-1.31.0 → ddapm_test_agent-1.32.0}/releasenotes/notes/add-python-3.13-support-ae7b96f4a10f20f4.yaml +0 -0
- {ddapm_test_agent-1.31.0 → ddapm_test_agent-1.32.0}/releasenotes/notes/add-rcm-endpoints-7e1f949e83e21039.yaml +0 -0
- {ddapm_test_agent-1.31.0 → ddapm_test_agent-1.32.0}/releasenotes/notes/add-request-forwarding-middleware-d3f325166b0f8e9e.yaml +0 -0
- {ddapm_test_agent-1.31.0 → ddapm_test_agent-1.32.0}/releasenotes/notes/add-service-naming-checks-2b68ff51d1b5496d.yaml +0 -0
- {ddapm_test_agent-1.31.0 → ddapm_test_agent-1.32.0}/releasenotes/notes/add-session-to-rcm-endpoints-d97e925a04a99a65.yaml +0 -0
- {ddapm_test_agent-1.31.0 → ddapm_test_agent-1.32.0}/releasenotes/notes/add-span-events-306e697168373899.yaml +0 -0
- {ddapm_test_agent-1.31.0 → ddapm_test_agent-1.32.0}/releasenotes/notes/add-support-for-plain-text-responses-00d20bf7b335e75b.yaml +0 -0
- {ddapm_test_agent-1.31.0 → ddapm_test_agent-1.32.0}/releasenotes/notes/add-support-telemetry-requests-10737cd3da802ca6.yaml +0 -0
- {ddapm_test_agent-1.31.0 → ddapm_test_agent-1.32.0}/releasenotes/notes/add-tracer_flare-endpoint-b2c81510920974d7.yaml +0 -0
- {ddapm_test_agent-1.31.0 → ddapm_test_agent-1.32.0}/releasenotes/notes/addAgentStateToInfo-f9a179ce88f2ab9e.yaml +0 -0
- {ddapm_test_agent-1.31.0 → ddapm_test_agent-1.32.0}/releasenotes/notes/addPeerTagsToInfo-4ccc2539d22c2993.yaml +0 -0
- {ddapm_test_agent-1.31.0 → ddapm_test_agent-1.32.0}/releasenotes/notes/allow-attribute-removal-snapshots-314b744b043b97c5.yaml +0 -0
- {ddapm_test_agent-1.31.0 → ddapm_test_agent-1.32.0}/releasenotes/notes/args-88f664c83a96075d.yaml +0 -0
- {ddapm_test_agent-1.31.0 → ddapm_test_agent-1.32.0}/releasenotes/notes/change-trace-proxy-headers-f9fcbb4efc4fcb95.yaml +0 -0
- {ddapm_test_agent-1.31.0 → ddapm_test_agent-1.32.0}/releasenotes/notes/check-http-header-sensitivity-daaa9d9595ae86d6.yaml +0 -0
- {ddapm_test_agent-1.31.0 → ddapm_test_agent-1.32.0}/releasenotes/notes/clearing-sessions-now-only-removes-6b0311673d8b37aa.yaml +0 -0
- {ddapm_test_agent-1.31.0 → ddapm_test_agent-1.32.0}/releasenotes/notes/client-173dbc6655e42337.yaml +0 -0
- {ddapm_test_agent-1.31.0 → ddapm_test_agent-1.32.0}/releasenotes/notes/content_length-e1bab75580aa1dcb.yaml +0 -0
- {ddapm_test_agent-1.31.0 → ddapm_test_agent-1.32.0}/releasenotes/notes/disable-error-responses-and-collect-trace-failures-in-memory-4a199bc7be416709.yaml +0 -0
- {ddapm_test_agent-1.31.0 → ddapm_test_agent-1.32.0}/releasenotes/notes/docker-arm64-images-a4b6b2cc527327d6.yaml +0 -0
- {ddapm_test_agent-1.31.0 → ddapm_test_agent-1.32.0}/releasenotes/notes/evp-proxy-on-info-d65cd077575306ca.yaml +0 -0
- {ddapm_test_agent-1.31.0 → ddapm_test_agent-1.32.0}/releasenotes/notes/exception-messages-21ee64461020edd1.yaml +0 -0
- {ddapm_test_agent-1.31.0 → ddapm_test_agent-1.32.0}/releasenotes/notes/fix-docker-image-tags-785d40f5bfdb8003.yaml +0 -0
- {ddapm_test_agent-1.31.0 → ddapm_test_agent-1.32.0}/releasenotes/notes/fix-fmt-logging-6a323fd8d5d4eb28.yaml +0 -0
- {ddapm_test_agent-1.31.0 → ddapm_test_agent-1.32.0}/releasenotes/notes/fix-getting-tested-integrations-multiple-session-tokens-4ee41d545754f87f.yaml +0 -0
- {ddapm_test_agent-1.31.0 → ddapm_test_agent-1.32.0}/releasenotes/notes/fix-matching-319744b82d2514c1.yaml +0 -0
- {ddapm_test_agent-1.31.0 → ddapm_test_agent-1.32.0}/releasenotes/notes/fix-missing-slim-deps-fa3b0fc0292a09b3.yaml +0 -0
- {ddapm_test_agent-1.31.0 → ddapm_test_agent-1.32.0}/releasenotes/notes/fix-partial-chunks-0db14ce3017e6173.yaml +0 -0
- {ddapm_test_agent-1.31.0 → ddapm_test_agent-1.32.0}/releasenotes/notes/fix-racecondition-9bd0ef15b7da60fa.yaml +0 -0
- {ddapm_test_agent-1.31.0 → ddapm_test_agent-1.32.0}/releasenotes/notes/fix-tracerflare-request-parsing-fae18ff9997c216d.yaml +0 -0
- {ddapm_test_agent-1.31.0 → ddapm_test_agent-1.32.0}/releasenotes/notes/genai-vcr-support-b499ec54df84eaa3.yaml +0 -0
- {ddapm_test_agent-1.31.0 → ddapm_test_agent-1.32.0}/releasenotes/notes/ignore-dsm-pathway-hash-during-trace-snapshots-f0b99ea267fbad48.yaml +0 -0
- {ddapm_test_agent-1.31.0 → ddapm_test_agent-1.32.0}/releasenotes/notes/image-optimization-d614eccb59441217.yaml +0 -0
- {ddapm_test_agent-1.31.0 → ddapm_test_agent-1.32.0}/releasenotes/notes/improve-test-agent-debugging-5759413f1fc5f7fa.yaml +0 -0
- {ddapm_test_agent-1.31.0 → ddapm_test_agent-1.32.0}/releasenotes/notes/improve-test-agent-proxying-a207f0fc81b3ab2d.yaml +0 -0
- {ddapm_test_agent-1.31.0 → ddapm_test_agent-1.32.0}/releasenotes/notes/improve-trace-check-results-endpoints-6ab4132628520793.yaml +0 -0
- {ddapm_test_agent-1.31.0 → ddapm_test_agent-1.32.0}/releasenotes/notes/info-34dcd9cbcc382487.yaml +0 -0
- {ddapm_test_agent-1.31.0 → ddapm_test_agent-1.32.0}/releasenotes/notes/info-drop-p0s-c207889f590340fb.yaml +0 -0
- {ddapm_test_agent-1.31.0 → ddapm_test_agent-1.32.0}/releasenotes/notes/llmobs-eval-metric-endpoint-8b5222491969ab4f.yaml +0 -0
- {ddapm_test_agent-1.31.0 → ddapm_test_agent-1.32.0}/releasenotes/notes/llmobs-evp-proxy-1383f4b4962ac7c9.yaml +0 -0
- {ddapm_test_agent-1.31.0 → ddapm_test_agent-1.32.0}/releasenotes/notes/meta-struct-2cce08475cb05470.yaml +0 -0
- {ddapm_test_agent-1.31.0 → ddapm_test_agent-1.32.0}/releasenotes/notes/more-oai-cass-908eb5ea46bd2985.yaml +0 -0
- {ddapm_test_agent-1.31.0 → ddapm_test_agent-1.32.0}/releasenotes/notes/new-process-id-tag-f0ab0daf652e05cc.yaml +0 -0
- {ddapm_test_agent-1.31.0 → ddapm_test_agent-1.32.0}/releasenotes/notes/oai-incomplete-cass-795ad19b6a226c1f.yaml +0 -0
- {ddapm_test_agent-1.31.0 → ddapm_test_agent-1.32.0}/releasenotes/notes/pipeline_stats_endpoint-e8ad6da735dc2647.yaml +0 -0
- {ddapm_test_agent-1.31.0 → ddapm_test_agent-1.32.0}/releasenotes/notes/profiling-endpoint-0cd209e4e5b6cfc0.yaml +0 -0
- {ddapm_test_agent-1.31.0 → ddapm_test_agent-1.32.0}/releasenotes/notes/provider-snapshot-server-f6a307acbf11d214.yaml +0 -0
- {ddapm_test_agent-1.31.0 → ddapm_test_agent-1.32.0}/releasenotes/notes/proxy-37c94e2fb428c6fc.yaml +0 -0
- {ddapm_test_agent-1.31.0 → ddapm_test_agent-1.32.0}/releasenotes/notes/python-3.12-952e06c6158af67d.yaml +0 -0
- {ddapm_test_agent-1.31.0 → ddapm_test_agent-1.32.0}/releasenotes/notes/python-support-1c447acc4607abc7.yaml +0 -0
- {ddapm_test_agent-1.31.0 → ddapm_test_agent-1.32.0}/releasenotes/notes/python310-025fbc190363de98.yaml +0 -0
- {ddapm_test_agent-1.31.0 → ddapm_test_agent-1.32.0}/releasenotes/notes/python310-docker-image-d4e329cfecf6510e.yaml +0 -0
- {ddapm_test_agent-1.31.0 → ddapm_test_agent-1.32.0}/releasenotes/notes/rc-encoding-length-fix-cc011edea7f8f5b2.yaml +0 -0
- {ddapm_test_agent-1.31.0 → ddapm_test_agent-1.32.0}/releasenotes/notes/rc-get-endpoint-e502f55b7df544e2.yaml +0 -0
- {ddapm_test_agent-1.31.0 → ddapm_test_agent-1.32.0}/releasenotes/notes/remoteconfig-requests-1af7abb99c61c069.yaml +0 -0
- {ddapm_test_agent-1.31.0 → ddapm_test_agent-1.32.0}/releasenotes/notes/reuse-session-1670aa569907cf68.yaml +0 -0
- {ddapm_test_agent-1.31.0 → ddapm_test_agent-1.32.0}/releasenotes/notes/sample-rate-1e06ae4cdc933b14.yaml +0 -0
- {ddapm_test_agent-1.31.0 → ddapm_test_agent-1.32.0}/releasenotes/notes/session-requests-b8057811f976220e.yaml +0 -0
- {ddapm_test_agent-1.31.0 → ddapm_test_agent-1.32.0}/releasenotes/notes/session-tracerflares-400ce9b3d3838b40.yaml +0 -0
- {ddapm_test_agent-1.31.0 → ddapm_test_agent-1.32.0}/releasenotes/notes/snapshot-cmds-de4a561911afee11.yaml +0 -0
- {ddapm_test_agent-1.31.0 → ddapm_test_agent-1.32.0}/releasenotes/notes/snapshot-empty-maps-2cbe8cea3e7112fa.yaml +0 -0
- {ddapm_test_agent-1.31.0 → ddapm_test_agent-1.32.0}/releasenotes/notes/snapshot-error-messages-de41d9e3207fa30a.yaml +0 -0
- {ddapm_test_agent-1.31.0 → ddapm_test_agent-1.32.0}/releasenotes/notes/snapshot-filename-c068de1bc3e50c04.yaml +0 -0
- {ddapm_test_agent-1.31.0 → ddapm_test_agent-1.32.0}/releasenotes/notes/snapshot-order-type-2d6424e380b2c88f.yaml +0 -0
- {ddapm_test_agent-1.31.0 → ddapm_test_agent-1.32.0}/releasenotes/notes/snapshot-parent-id-7abb860008702e70.yaml +0 -0
- {ddapm_test_agent-1.31.0 → ddapm_test_agent-1.32.0}/releasenotes/notes/span-links-1ec76bd2b47a3880.yaml +0 -0
- {ddapm_test_agent-1.31.0 → ddapm_test_agent-1.32.0}/releasenotes/notes/span-ordering-1a7b383aa015bddc.yaml +0 -0
- {ddapm_test_agent-1.31.0 → ddapm_test_agent-1.32.0}/releasenotes/notes/span-parent-id-a4d7d63fa623361c.yaml +0 -0
- {ddapm_test_agent-1.31.0 → ddapm_test_agent-1.32.0}/releasenotes/notes/support-ant-vcr-1eff9a40caa0aba0.yaml +0 -0
- {ddapm_test_agent-1.31.0 → ddapm_test_agent-1.32.0}/releasenotes/notes/support-tracking-of-tested-integrations-ac19ccd1f8333c00.yaml +0 -0
- {ddapm_test_agent-1.31.0 → ddapm_test_agent-1.32.0}/releasenotes/notes/throttling-590bf58ecb3cc4a5.yaml +0 -0
- {ddapm_test_agent-1.31.0 → ddapm_test_agent-1.32.0}/releasenotes/notes/trace-stats-97da3a478dabfa99.yaml +0 -0
- {ddapm_test_agent-1.31.0 → ddapm_test_agent-1.32.0}/releasenotes/notes/trace-stats-snapshot-718ca37385c93e1e.yaml +0 -0
- {ddapm_test_agent-1.31.0 → ddapm_test_agent-1.32.0}/releasenotes/notes/traces-endpoint-f4f9c1d94d6ceda2.yaml +0 -0
- {ddapm_test_agent-1.31.0 → ddapm_test_agent-1.32.0}/releasenotes/notes/tracestats-fixes-07152c708e73ef96.yaml +0 -0
- {ddapm_test_agent-1.31.0 → ddapm_test_agent-1.32.0}/releasenotes/notes/tracestats-post-65ce788f81862532.yaml +0 -0
- {ddapm_test_agent-1.31.0 → ddapm_test_agent-1.32.0}/releasenotes/notes/tracestats-service-2a0a178cbd21b07d.yaml +0 -0
- {ddapm_test_agent-1.31.0 → ddapm_test_agent-1.32.0}/releasenotes/notes/uds-64b11960931d8b77.yaml +0 -0
- {ddapm_test_agent-1.31.0 → ddapm_test_agent-1.32.0}/releasenotes/notes/uds-c99ea5d099e67156.yaml +0 -0
- {ddapm_test_agent-1.31.0 → ddapm_test_agent-1.32.0}/releasenotes/notes/uds-container-8138f8b1438b1a0a.yaml +0 -0
- {ddapm_test_agent-1.31.0 → ddapm_test_agent-1.32.0}/releasenotes/notes/uds-permissions-903266ac6445b873.yaml +0 -0
- {ddapm_test_agent-1.31.0 → ddapm_test_agent-1.32.0}/releasenotes/notes/v0.5-traces-cf469b0b71398d97.yaml +0 -0
- {ddapm_test_agent-1.31.0 → ddapm_test_agent-1.32.0}/releasenotes/notes/v0.7-traces-7ea3ebbed7502d01.yaml +0 -0
- {ddapm_test_agent-1.31.0 → ddapm_test_agent-1.32.0}/releasenotes/notes/vcr-cassettes-for-openai-v5-6e9d78091de1f0c2.yaml +0 -0
- {ddapm_test_agent-1.31.0 → ddapm_test_agent-1.32.0}/releasenotes/notes/vcr-cassettes-for-vercel-ai-7a8275f9c2b48bc7.yaml +0 -0
- {ddapm_test_agent-1.31.0 → ddapm_test_agent-1.32.0}/releasenotes/notes/vcr-prefix-instead-of-suffix-4c56dcb5038d222e.yaml +0 -0
- {ddapm_test_agent-1.31.0 → ddapm_test_agent-1.32.0}/releasenotes/notes/vcr-proxy-use-test-name-bugfix-be758294ba30ac78.yaml +0 -0
- {ddapm_test_agent-1.31.0 → ddapm_test_agent-1.32.0}/releasenotes/notes/vcr-proxy-use-test-name-e47891994c961c52.yaml +0 -0
- {ddapm_test_agent-1.31.0 → ddapm_test_agent-1.32.0}/releasenotes/notes/vcr-support-querystring-b06555fb9a7c90ae.yaml +0 -0
- {ddapm_test_agent-1.31.0 → ddapm_test_agent-1.32.0}/releasenotes/notes/version-0c32d2752f154eb9.yaml +0 -0
- {ddapm_test_agent-1.31.0 → ddapm_test_agent-1.32.0}/releasenotes/notes/wheels-68a7dc2f4b00e0c4.yaml +0 -0
- {ddapm_test_agent-1.31.0 → ddapm_test_agent-1.32.0}/releasenotes/notes/windows-docker-image-1f5d5e894558bb4b.yaml +0 -0
- {ddapm_test_agent-1.31.0 → ddapm_test_agent-1.32.0}/riotfile.py +0 -0
- {ddapm_test_agent-1.31.0 → ddapm_test_agent-1.32.0}/shell.nix +0 -0
- {ddapm_test_agent-1.31.0 → ddapm_test_agent-1.32.0}/test_deps.txt +0 -0
- {ddapm_test_agent-1.31.0 → ddapm_test_agent-1.32.0}/tests/__init__.py +0 -0
- {ddapm_test_agent-1.31.0 → ddapm_test_agent-1.32.0}/tests/integration_snapshots/test_multi_trace.json +0 -0
- {ddapm_test_agent-1.31.0 → ddapm_test_agent-1.32.0}/tests/integration_snapshots/test_single_trace.json +0 -0
- {ddapm_test_agent-1.31.0 → ddapm_test_agent-1.32.0}/tests/integration_snapshots/test_trace_distributed_propagated.json +0 -0
- {ddapm_test_agent-1.31.0 → ddapm_test_agent-1.32.0}/tests/integration_snapshots/test_trace_distributed_same_payload.json +0 -0
- {ddapm_test_agent-1.31.0 → ddapm_test_agent-1.32.0}/tests/integration_snapshots/test_trace_missing_received.json +0 -0
- {ddapm_test_agent-1.31.0 → ddapm_test_agent-1.32.0}/tests/integration_snapshots/test_trace_stats_tracestats.json +0 -0
- {ddapm_test_agent-1.31.0 → ddapm_test_agent-1.32.0}/tests/test_apmtelemetry.py +0 -0
- {ddapm_test_agent-1.31.0 → ddapm_test_agent-1.32.0}/tests/test_checks.py +0 -0
- {ddapm_test_agent-1.31.0 → ddapm_test_agent-1.32.0}/tests/test_client.py +0 -0
- {ddapm_test_agent-1.31.0 → ddapm_test_agent-1.32.0}/tests/test_container.py +0 -0
- {ddapm_test_agent-1.31.0 → ddapm_test_agent-1.32.0}/tests/test_remoteconfig.py +0 -0
- {ddapm_test_agent-1.31.0 → ddapm_test_agent-1.32.0}/tests/test_session.py +0 -0
- {ddapm_test_agent-1.31.0 → ddapm_test_agent-1.32.0}/tests/test_snapshot.py +0 -0
- {ddapm_test_agent-1.31.0 → ddapm_test_agent-1.32.0}/tests/test_snapshot_integration.py +0 -0
- {ddapm_test_agent-1.31.0 → ddapm_test_agent-1.32.0}/tests/test_trace.py +0 -0
- {ddapm_test_agent-1.31.0 → ddapm_test_agent-1.32.0}/tests/test_tracerflare.py +0 -0
- {ddapm_test_agent-1.31.0 → ddapm_test_agent-1.32.0}/tests/test_tracestats.py +0 -0
- {ddapm_test_agent-1.31.0 → ddapm_test_agent-1.32.0}/tests/trace_utils.py +0 -0
- {ddapm_test_agent-1.31.0 → ddapm_test_agent-1.32.0}/treefmt.nix +0 -0
- {ddapm_test_agent-1.31.0 → ddapm_test_agent-1.32.0}/use-example.Dockerfile +0 -0
- {ddapm_test_agent-1.31.0 → ddapm_test_agent-1.32.0}/vcr-cassettes/anthropic/anthropic_v1_messages_post_26d618ee.yaml +0 -0
- {ddapm_test_agent-1.31.0 → ddapm_test_agent-1.32.0}/vcr-cassettes/anthropic/anthropic_v1_messages_post_595f439c.yaml +0 -0
- {ddapm_test_agent-1.31.0 → ddapm_test_agent-1.32.0}/vcr-cassettes/anthropic/anthropic_v1_messages_post_717ba0b4.yaml +0 -0
- {ddapm_test_agent-1.31.0 → ddapm_test_agent-1.32.0}/vcr-cassettes/anthropic/anthropic_v1_messages_post_a1af2c12.yaml +0 -0
- {ddapm_test_agent-1.31.0 → ddapm_test_agent-1.32.0}/vcr-cassettes/deepseek/deepseek_chat_completions_post_afb6ccab.yaml +0 -0
- {ddapm_test_agent-1.31.0 → ddapm_test_agent-1.32.0}/vcr-cassettes/openai/openai_audio_transcriptions_post_173af3e5.yaml +0 -0
- {ddapm_test_agent-1.31.0 → ddapm_test_agent-1.32.0}/vcr-cassettes/openai/openai_audio_transcriptions_post_71305a25.yaml +0 -0
- {ddapm_test_agent-1.31.0 → ddapm_test_agent-1.32.0}/vcr-cassettes/openai/openai_audio_translations_post_d5b5b8d6.yaml +0 -0
- {ddapm_test_agent-1.31.0 → ddapm_test_agent-1.32.0}/vcr-cassettes/openai/openai_audio_translations_post_dd92a18a.yaml +0 -0
- {ddapm_test_agent-1.31.0 → ddapm_test_agent-1.32.0}/vcr-cassettes/openai/openai_chat_completions_post_0f1514e1.yaml +0 -0
- {ddapm_test_agent-1.31.0 → ddapm_test_agent-1.32.0}/vcr-cassettes/openai/openai_chat_completions_post_172294b4.yaml +0 -0
- {ddapm_test_agent-1.31.0 → ddapm_test_agent-1.32.0}/vcr-cassettes/openai/openai_chat_completions_post_193ae44a.yaml +0 -0
- {ddapm_test_agent-1.31.0 → ddapm_test_agent-1.32.0}/vcr-cassettes/openai/openai_chat_completions_post_23558eed.yaml +0 -0
- {ddapm_test_agent-1.31.0 → ddapm_test_agent-1.32.0}/vcr-cassettes/openai/openai_chat_completions_post_2edb59ae.yaml +0 -0
- {ddapm_test_agent-1.31.0 → ddapm_test_agent-1.32.0}/vcr-cassettes/openai/openai_chat_completions_post_3517e44e.yaml +0 -0
- {ddapm_test_agent-1.31.0 → ddapm_test_agent-1.32.0}/vcr-cassettes/openai/openai_chat_completions_post_36bdc0cb.yaml +0 -0
- {ddapm_test_agent-1.31.0 → ddapm_test_agent-1.32.0}/vcr-cassettes/openai/openai_chat_completions_post_3c045664.yaml +0 -0
- {ddapm_test_agent-1.31.0 → ddapm_test_agent-1.32.0}/vcr-cassettes/openai/openai_chat_completions_post_432a8e46.yaml +0 -0
- {ddapm_test_agent-1.31.0 → ddapm_test_agent-1.32.0}/vcr-cassettes/openai/openai_chat_completions_post_4749eff9.yaml +0 -0
- {ddapm_test_agent-1.31.0 → ddapm_test_agent-1.32.0}/vcr-cassettes/openai/openai_chat_completions_post_4dce8db6.yaml +0 -0
- {ddapm_test_agent-1.31.0 → ddapm_test_agent-1.32.0}/vcr-cassettes/openai/openai_chat_completions_post_57612363.yaml +0 -0
- {ddapm_test_agent-1.31.0 → ddapm_test_agent-1.32.0}/vcr-cassettes/openai/openai_chat_completions_post_649d8162.yaml +0 -0
- {ddapm_test_agent-1.31.0 → ddapm_test_agent-1.32.0}/vcr-cassettes/openai/openai_chat_completions_post_655a8ef2.yaml +0 -0
- {ddapm_test_agent-1.31.0 → ddapm_test_agent-1.32.0}/vcr-cassettes/openai/openai_chat_completions_post_66dfc80e.yaml +0 -0
- {ddapm_test_agent-1.31.0 → ddapm_test_agent-1.32.0}/vcr-cassettes/openai/openai_chat_completions_post_67e8e833.yaml +0 -0
- {ddapm_test_agent-1.31.0 → ddapm_test_agent-1.32.0}/vcr-cassettes/openai/openai_chat_completions_post_6df851cc.yaml +0 -0
- {ddapm_test_agent-1.31.0 → ddapm_test_agent-1.32.0}/vcr-cassettes/openai/openai_chat_completions_post_7c2d1ac5.yaml +0 -0
- {ddapm_test_agent-1.31.0 → ddapm_test_agent-1.32.0}/vcr-cassettes/openai/openai_chat_completions_post_82a4bb3c.yaml +0 -0
- {ddapm_test_agent-1.31.0 → ddapm_test_agent-1.32.0}/vcr-cassettes/openai/openai_chat_completions_post_9122b1ae.yaml +0 -0
- {ddapm_test_agent-1.31.0 → ddapm_test_agent-1.32.0}/vcr-cassettes/openai/openai_chat_completions_post_917478d0.yaml +0 -0
- {ddapm_test_agent-1.31.0 → ddapm_test_agent-1.32.0}/vcr-cassettes/openai/openai_chat_completions_post_a73ecd7a.yaml +0 -0
- {ddapm_test_agent-1.31.0 → ddapm_test_agent-1.32.0}/vcr-cassettes/openai/openai_chat_completions_post_a925b737.yaml +0 -0
- {ddapm_test_agent-1.31.0 → ddapm_test_agent-1.32.0}/vcr-cassettes/openai/openai_chat_completions_post_ae4728c2.yaml +0 -0
- {ddapm_test_agent-1.31.0 → ddapm_test_agent-1.32.0}/vcr-cassettes/openai/openai_chat_completions_post_b29f1a87.yaml +0 -0
- {ddapm_test_agent-1.31.0 → ddapm_test_agent-1.32.0}/vcr-cassettes/openai/openai_chat_completions_post_ce69ed91.yaml +0 -0
- {ddapm_test_agent-1.31.0 → ddapm_test_agent-1.32.0}/vcr-cassettes/openai/openai_chat_completions_post_d8fb132a.yaml +0 -0
- {ddapm_test_agent-1.31.0 → ddapm_test_agent-1.32.0}/vcr-cassettes/openai/openai_chat_completions_post_d94d5844.yaml +0 -0
- {ddapm_test_agent-1.31.0 → ddapm_test_agent-1.32.0}/vcr-cassettes/openai/openai_chat_completions_post_d98ce00d.yaml +0 -0
- {ddapm_test_agent-1.31.0 → ddapm_test_agent-1.32.0}/vcr-cassettes/openai/openai_chat_completions_post_ebff79da.yaml +0 -0
- {ddapm_test_agent-1.31.0 → ddapm_test_agent-1.32.0}/vcr-cassettes/openai/openai_completions_post_33681ea4.yaml +0 -0
- {ddapm_test_agent-1.31.0 → ddapm_test_agent-1.32.0}/vcr-cassettes/openai/openai_completions_post_5d2418d4.yaml +0 -0
- {ddapm_test_agent-1.31.0 → ddapm_test_agent-1.32.0}/vcr-cassettes/openai/openai_completions_post_619dee1c.yaml +0 -0
- {ddapm_test_agent-1.31.0 → ddapm_test_agent-1.32.0}/vcr-cassettes/openai/openai_completions_post_6224acff.yaml +0 -0
- {ddapm_test_agent-1.31.0 → ddapm_test_agent-1.32.0}/vcr-cassettes/openai/openai_completions_post_87f617af.yaml +0 -0
- {ddapm_test_agent-1.31.0 → ddapm_test_agent-1.32.0}/vcr-cassettes/openai/openai_completions_post_98c30019.yaml +0 -0
- {ddapm_test_agent-1.31.0 → ddapm_test_agent-1.32.0}/vcr-cassettes/openai/openai_completions_post_9bb49464.yaml +0 -0
- {ddapm_test_agent-1.31.0 → ddapm_test_agent-1.32.0}/vcr-cassettes/openai/openai_completions_post_b24dbf7d.yaml +0 -0
- {ddapm_test_agent-1.31.0 → ddapm_test_agent-1.32.0}/vcr-cassettes/openai/openai_embeddings_post_0381abe4.yaml +0 -0
- {ddapm_test_agent-1.31.0 → ddapm_test_agent-1.32.0}/vcr-cassettes/openai/openai_embeddings_post_48694087.yaml +0 -0
- {ddapm_test_agent-1.31.0 → ddapm_test_agent-1.32.0}/vcr-cassettes/openai/openai_embeddings_post_541bd4d0.yaml +0 -0
- {ddapm_test_agent-1.31.0 → ddapm_test_agent-1.32.0}/vcr-cassettes/openai/openai_files_file-RpTpuvRVtnKpdKZb7DDGto_content_get_60bd10ef.yaml +0 -0
- {ddapm_test_agent-1.31.0 → ddapm_test_agent-1.32.0}/vcr-cassettes/openai/openai_files_file-RpTpuvRVtnKpdKZb7DDGto_delete_3ee48409.yaml +0 -0
- {ddapm_test_agent-1.31.0 → ddapm_test_agent-1.32.0}/vcr-cassettes/openai/openai_files_file-RpTpuvRVtnKpdKZb7DDGto_get_1afefb93.yaml +0 -0
- {ddapm_test_agent-1.31.0 → ddapm_test_agent-1.32.0}/vcr-cassettes/openai/openai_files_get_68efa25d.yaml +0 -0
- {ddapm_test_agent-1.31.0 → ddapm_test_agent-1.32.0}/vcr-cassettes/openai/openai_files_post_2fcf9545.yaml +0 -0
- {ddapm_test_agent-1.31.0 → ddapm_test_agent-1.32.0}/vcr-cassettes/openai/openai_files_post_957d63ba.yaml +0 -0
- {ddapm_test_agent-1.31.0 → ddapm_test_agent-1.32.0}/vcr-cassettes/openai/openai_fine_tuning_jobs_ftjob-q9CUUUsHJemGUVQ1Ecc01zcf_cancel_post_d7c16b38.yaml +0 -0
- {ddapm_test_agent-1.31.0 → ddapm_test_agent-1.32.0}/vcr-cassettes/openai/openai_fine_tuning_jobs_ftjob-q9CUUUsHJemGUVQ1Ecc01zcf_events_get_557d820e.yaml +0 -0
- {ddapm_test_agent-1.31.0 → ddapm_test_agent-1.32.0}/vcr-cassettes/openai/openai_fine_tuning_jobs_ftjob-q9CUUUsHJemGUVQ1Ecc01zcf_get_265489e7.yaml +0 -0
- {ddapm_test_agent-1.31.0 → ddapm_test_agent-1.32.0}/vcr-cassettes/openai/openai_fine_tuning_jobs_get_ebc57c6f.yaml +0 -0
- {ddapm_test_agent-1.31.0 → ddapm_test_agent-1.32.0}/vcr-cassettes/openai/openai_fine_tuning_jobs_post_c3b6e4a9.yaml +0 -0
- {ddapm_test_agent-1.31.0 → ddapm_test_agent-1.32.0}/vcr-cassettes/openai/openai_images_edits_post_075386c4.yaml +0 -0
- {ddapm_test_agent-1.31.0 → ddapm_test_agent-1.32.0}/vcr-cassettes/openai/openai_images_edits_post_57b4f4da.yaml +0 -0
- {ddapm_test_agent-1.31.0 → ddapm_test_agent-1.32.0}/vcr-cassettes/openai/openai_images_edits_post_660e9dd7.yaml +0 -0
- {ddapm_test_agent-1.31.0 → ddapm_test_agent-1.32.0}/vcr-cassettes/openai/openai_images_edits_post_993e0192.yaml +0 -0
- {ddapm_test_agent-1.31.0 → ddapm_test_agent-1.32.0}/vcr-cassettes/openai/openai_images_edits_post_a2f1eb43.yaml +0 -0
- {ddapm_test_agent-1.31.0 → ddapm_test_agent-1.32.0}/vcr-cassettes/openai/openai_images_edits_post_ae72c45f.yaml +0 -0
- {ddapm_test_agent-1.31.0 → ddapm_test_agent-1.32.0}/vcr-cassettes/openai/openai_images_edits_post_cf5af376.yaml +0 -0
- {ddapm_test_agent-1.31.0 → ddapm_test_agent-1.32.0}/vcr-cassettes/openai/openai_images_edits_post_dbefb624.yaml +0 -0
- {ddapm_test_agent-1.31.0 → ddapm_test_agent-1.32.0}/vcr-cassettes/openai/openai_images_generations_post_48272841.yaml +0 -0
- {ddapm_test_agent-1.31.0 → ddapm_test_agent-1.32.0}/vcr-cassettes/openai/openai_images_generations_post_736070ea.yaml +0 -0
- {ddapm_test_agent-1.31.0 → ddapm_test_agent-1.32.0}/vcr-cassettes/openai/openai_images_variations_post_5971e285.yaml +0 -0
- {ddapm_test_agent-1.31.0 → ddapm_test_agent-1.32.0}/vcr-cassettes/openai/openai_images_variations_post_f2f62f6c.yaml +0 -0
- {ddapm_test_agent-1.31.0 → ddapm_test_agent-1.32.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.31.0 → ddapm_test_agent-1.32.0}/vcr-cassettes/openai/openai_models_get_e04cf04b.yaml +0 -0
- {ddapm_test_agent-1.31.0 → ddapm_test_agent-1.32.0}/vcr-cassettes/openai/openai_models_gpt-4_get_b13c5b23.yaml +0 -0
- {ddapm_test_agent-1.31.0 → ddapm_test_agent-1.32.0}/vcr-cassettes/openai/openai_moderations_post_532b3315.yaml +0 -0
- {ddapm_test_agent-1.31.0 → ddapm_test_agent-1.32.0}/vcr-cassettes/openai/openai_responses_post_33fb1f66.yaml +0 -0
- {ddapm_test_agent-1.31.0 → ddapm_test_agent-1.32.0}/vcr-cassettes/openai/openai_responses_post_5ca556ec.yaml +0 -0
- {ddapm_test_agent-1.31.0 → ddapm_test_agent-1.32.0}/vcr-cassettes/openai/openai_responses_post_c05c936e.yaml +0 -0
- {ddapm_test_agent-1.31.0 → ddapm_test_agent-1.32.0}/vcr-cassettes/openai/openai_responses_post_c61e3067.yaml +0 -0
- {ddapm_test_agent-1.31.0 → ddapm_test_agent-1.32.0}/vcr-cassettes/openai/openai_responses_post_ee2423e6.yaml +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: ddapm-test-agent
|
|
3
|
-
Version: 1.
|
|
3
|
+
Version: 1.32.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
|
|
@@ -24,6 +24,9 @@ Requires-Dist: requests
|
|
|
24
24
|
Requires-Dist: typing_extensions
|
|
25
25
|
Requires-Dist: yarl
|
|
26
26
|
Requires-Dist: vcrpy
|
|
27
|
+
Requires-Dist: opentelemetry-proto<1.37.0,>1.33.0
|
|
28
|
+
Requires-Dist: protobuf>=3.19.0
|
|
29
|
+
Requires-Dist: grpcio<2.0,>=1.66.2
|
|
27
30
|
Provides-Extra: testing
|
|
28
31
|
Requires-Dist: ddtrace==3.11.0; extra == "testing"
|
|
29
32
|
Requires-Dist: pytest; extra == "testing"
|
|
@@ -69,13 +72,16 @@ The test agent can be installed from PyPI:
|
|
|
69
72
|
|
|
70
73
|
pip install ddapm-test-agent
|
|
71
74
|
|
|
72
|
-
|
|
75
|
+
# HTTP on port 8126, OTLP HTTP on port 4318, OTLP GRPC on port 4317
|
|
76
|
+
ddapm-test-agent --port=8126 --otlp-http-port=4318 --otlp-grpc-port=4317
|
|
73
77
|
|
|
74
78
|
or from Docker:
|
|
75
79
|
|
|
76
80
|
# Run the test agent and mount the snapshot directory
|
|
77
81
|
docker run --rm\
|
|
78
82
|
-p 8126:8126\
|
|
83
|
+
-p 4318:4318\
|
|
84
|
+
-p 4317:4317\
|
|
79
85
|
-e SNAPSHOT_CI=0\
|
|
80
86
|
-v $PWD/tests/snapshots:/snapshots\
|
|
81
87
|
ghcr.io/datadog/dd-apm-test-agent/ddapm-test-agent:latest
|
|
@@ -422,6 +428,24 @@ Return stats that have been received by the agent for the given session token.
|
|
|
422
428
|
|
|
423
429
|
Stats are returned as a JSON list of the stats payloads received.
|
|
424
430
|
|
|
431
|
+
### /test/session/logs
|
|
432
|
+
|
|
433
|
+
Return OpenTelemetry logs that have been received by the agent for the given session token.
|
|
434
|
+
|
|
435
|
+
#### [optional] `?test_session_token=`
|
|
436
|
+
#### [optional] `X-Datadog-Test-Session-Token`
|
|
437
|
+
|
|
438
|
+
Logs are returned as a JSON list of the OTLP logs payloads received. The logs are in the standard OpenTelemetry Protocol (OTLP) v1.7.0 format, decoded from protobuf into JSON.
|
|
439
|
+
|
|
440
|
+
### /test/session/metrics
|
|
441
|
+
|
|
442
|
+
Return OpenTelemetry metrics that have been received by the agent for the given session token.
|
|
443
|
+
|
|
444
|
+
#### [optional] `?test_session_token=`
|
|
445
|
+
#### [optional] `X-Datadog-Test-Session-Token`
|
|
446
|
+
|
|
447
|
+
Metrics are returned as a JSON list of the OTLP metrics payloads received. The metrics are in the standard OpenTelemetry Protocol (OTLP) v1.7.0 format, decoded from protobuf into JSON.
|
|
448
|
+
|
|
425
449
|
### /test/session/responses/config (POST)
|
|
426
450
|
Create a Remote Config payload to retrieve in endpoint `/v0.7/config`
|
|
427
451
|
|
|
@@ -522,6 +546,35 @@ curl -X GET 'http://0.0.0.0:8126/test/integrations/tested_versions'
|
|
|
522
546
|
|
|
523
547
|
Mimics the pipeline_stats endpoint of the agent, but always returns OK, and logs a line everytime it's called.
|
|
524
548
|
|
|
549
|
+
### /v1/logs (HTTP)
|
|
550
|
+
|
|
551
|
+
Accepts OpenTelemetry Protocol (OTLP) v1.7.0 logs in protobuf format via HTTP. This endpoint validates and decodes OTLP logs payloads for testing OpenTelemetry logs exporters and libraries.
|
|
552
|
+
|
|
553
|
+
The HTTP endpoint accepts `POST` requests with `Content-Type: application/x-protobuf` and `Content-Type: application/json` and stores the decoded logs for retrieval via the `/test/session/logs` endpoint.
|
|
554
|
+
|
|
555
|
+
### /v1/metrics (HTTP)
|
|
556
|
+
|
|
557
|
+
Accepts OpenTelemetry Protocol (OTLP) v1.7.0 metrics in protobuf format via HTTP. This endpoint validates and decodes OTLP metrics payloads for testing OpenTelemetry metrics exporters and libraries.
|
|
558
|
+
|
|
559
|
+
The HTTP endpoint accepts `POST` requests with `Content-Type: application/x-protobuf` and `Content-Type: application/json` and stores the decoded metrics for retrieval via the `/test/session/metrics` endpoint.
|
|
560
|
+
|
|
561
|
+
### OTLP Logs and Metrics via GRPC
|
|
562
|
+
|
|
563
|
+
OTLP logs and metrics can also be sent via GRPC using the OpenTelemetry `LogsService.Export` and `MetricsService.Export` methods respectively. The GRPC server implements the standard OTLP service interfaces and forwards all requests to the HTTP server, ensuring consistent processing and session management.
|
|
564
|
+
|
|
565
|
+
**Note:** OTLP endpoints are served on separate ports from the main APM endpoints (default: 8126):
|
|
566
|
+
- **HTTP**: Port 4318 (default) - Use `--otlp-http-port` to configure
|
|
567
|
+
- **GRPC**: Port 4317 (default) - Use `--otlp-grpc-port` to configure
|
|
568
|
+
|
|
569
|
+
Both protocols store decoded data for retrieval via the `/test/session/logs` and `/test/session/metrics` HTTP endpoints respectively.
|
|
570
|
+
|
|
571
|
+
GRPC Client → GRPC Server → HTTP POST → HTTP Server → Agent Storage
|
|
572
|
+
↓ ↓
|
|
573
|
+
(forwards protobuf) (session management)
|
|
574
|
+
↓ ↓
|
|
575
|
+
HTTP Retrievable via
|
|
576
|
+
Response /test/session/{logs,metrics}
|
|
577
|
+
|
|
525
578
|
### /tracer_flare/v1
|
|
526
579
|
|
|
527
580
|
Mimics the tracer_flare endpoint of the agent. Returns OK if the flare contains the required form fields, otherwise `400`.
|
|
@@ -26,13 +26,16 @@ The test agent can be installed from PyPI:
|
|
|
26
26
|
|
|
27
27
|
pip install ddapm-test-agent
|
|
28
28
|
|
|
29
|
-
|
|
29
|
+
# HTTP on port 8126, OTLP HTTP on port 4318, OTLP GRPC on port 4317
|
|
30
|
+
ddapm-test-agent --port=8126 --otlp-http-port=4318 --otlp-grpc-port=4317
|
|
30
31
|
|
|
31
32
|
or from Docker:
|
|
32
33
|
|
|
33
34
|
# Run the test agent and mount the snapshot directory
|
|
34
35
|
docker run --rm\
|
|
35
36
|
-p 8126:8126\
|
|
37
|
+
-p 4318:4318\
|
|
38
|
+
-p 4317:4317\
|
|
36
39
|
-e SNAPSHOT_CI=0\
|
|
37
40
|
-v $PWD/tests/snapshots:/snapshots\
|
|
38
41
|
ghcr.io/datadog/dd-apm-test-agent/ddapm-test-agent:latest
|
|
@@ -379,6 +382,24 @@ Return stats that have been received by the agent for the given session token.
|
|
|
379
382
|
|
|
380
383
|
Stats are returned as a JSON list of the stats payloads received.
|
|
381
384
|
|
|
385
|
+
### /test/session/logs
|
|
386
|
+
|
|
387
|
+
Return OpenTelemetry logs that have been received by the agent for the given session token.
|
|
388
|
+
|
|
389
|
+
#### [optional] `?test_session_token=`
|
|
390
|
+
#### [optional] `X-Datadog-Test-Session-Token`
|
|
391
|
+
|
|
392
|
+
Logs are returned as a JSON list of the OTLP logs payloads received. The logs are in the standard OpenTelemetry Protocol (OTLP) v1.7.0 format, decoded from protobuf into JSON.
|
|
393
|
+
|
|
394
|
+
### /test/session/metrics
|
|
395
|
+
|
|
396
|
+
Return OpenTelemetry metrics that have been received by the agent for the given session token.
|
|
397
|
+
|
|
398
|
+
#### [optional] `?test_session_token=`
|
|
399
|
+
#### [optional] `X-Datadog-Test-Session-Token`
|
|
400
|
+
|
|
401
|
+
Metrics are returned as a JSON list of the OTLP metrics payloads received. The metrics are in the standard OpenTelemetry Protocol (OTLP) v1.7.0 format, decoded from protobuf into JSON.
|
|
402
|
+
|
|
382
403
|
### /test/session/responses/config (POST)
|
|
383
404
|
Create a Remote Config payload to retrieve in endpoint `/v0.7/config`
|
|
384
405
|
|
|
@@ -479,6 +500,35 @@ curl -X GET 'http://0.0.0.0:8126/test/integrations/tested_versions'
|
|
|
479
500
|
|
|
480
501
|
Mimics the pipeline_stats endpoint of the agent, but always returns OK, and logs a line everytime it's called.
|
|
481
502
|
|
|
503
|
+
### /v1/logs (HTTP)
|
|
504
|
+
|
|
505
|
+
Accepts OpenTelemetry Protocol (OTLP) v1.7.0 logs in protobuf format via HTTP. This endpoint validates and decodes OTLP logs payloads for testing OpenTelemetry logs exporters and libraries.
|
|
506
|
+
|
|
507
|
+
The HTTP endpoint accepts `POST` requests with `Content-Type: application/x-protobuf` and `Content-Type: application/json` and stores the decoded logs for retrieval via the `/test/session/logs` endpoint.
|
|
508
|
+
|
|
509
|
+
### /v1/metrics (HTTP)
|
|
510
|
+
|
|
511
|
+
Accepts OpenTelemetry Protocol (OTLP) v1.7.0 metrics in protobuf format via HTTP. This endpoint validates and decodes OTLP metrics payloads for testing OpenTelemetry metrics exporters and libraries.
|
|
512
|
+
|
|
513
|
+
The HTTP endpoint accepts `POST` requests with `Content-Type: application/x-protobuf` and `Content-Type: application/json` and stores the decoded metrics for retrieval via the `/test/session/metrics` endpoint.
|
|
514
|
+
|
|
515
|
+
### OTLP Logs and Metrics via GRPC
|
|
516
|
+
|
|
517
|
+
OTLP logs and metrics can also be sent via GRPC using the OpenTelemetry `LogsService.Export` and `MetricsService.Export` methods respectively. The GRPC server implements the standard OTLP service interfaces and forwards all requests to the HTTP server, ensuring consistent processing and session management.
|
|
518
|
+
|
|
519
|
+
**Note:** OTLP endpoints are served on separate ports from the main APM endpoints (default: 8126):
|
|
520
|
+
- **HTTP**: Port 4318 (default) - Use `--otlp-http-port` to configure
|
|
521
|
+
- **GRPC**: Port 4317 (default) - Use `--otlp-grpc-port` to configure
|
|
522
|
+
|
|
523
|
+
Both protocols store decoded data for retrieval via the `/test/session/logs` and `/test/session/metrics` HTTP endpoints respectively.
|
|
524
|
+
|
|
525
|
+
GRPC Client → GRPC Server → HTTP POST → HTTP Server → Agent Storage
|
|
526
|
+
↓ ↓
|
|
527
|
+
(forwards protobuf) (session management)
|
|
528
|
+
↓ ↓
|
|
529
|
+
HTTP Retrievable via
|
|
530
|
+
Response /test/session/{logs,metrics}
|
|
531
|
+
|
|
482
532
|
### /tracer_flare/v1
|
|
483
533
|
|
|
484
534
|
Mimics the tracer_flare endpoint of the agent. Returns OK if the flare contains the required form fields, otherwise `400`.
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import argparse
|
|
2
|
+
import asyncio
|
|
2
3
|
import atexit
|
|
3
4
|
import base64
|
|
4
5
|
from collections import OrderedDict
|
|
@@ -12,6 +13,7 @@ import pprint
|
|
|
12
13
|
import re
|
|
13
14
|
import socket
|
|
14
15
|
import sys
|
|
16
|
+
from typing import Any
|
|
15
17
|
from typing import Awaitable
|
|
16
18
|
from typing import Callable
|
|
17
19
|
from typing import DefaultDict
|
|
@@ -32,8 +34,11 @@ from aiohttp import web
|
|
|
32
34
|
from aiohttp.web import HTTPException
|
|
33
35
|
from aiohttp.web import Request
|
|
34
36
|
from aiohttp.web import middleware
|
|
37
|
+
from grpc import aio as grpc_aio
|
|
35
38
|
from msgpack.exceptions import ExtraData as MsgPackExtraDataException
|
|
36
39
|
from multidict import CIMultiDict
|
|
40
|
+
from opentelemetry.proto.collector.logs.v1.logs_service_pb2_grpc import add_LogsServiceServicer_to_server
|
|
41
|
+
from opentelemetry.proto.collector.metrics.v1.metrics_service_pb2_grpc import add_MetricsServiceServicer_to_server
|
|
37
42
|
|
|
38
43
|
from . import _get_version
|
|
39
44
|
from . import trace_snapshot
|
|
@@ -44,10 +49,17 @@ from .checks import CheckTrace
|
|
|
44
49
|
from .checks import Checks
|
|
45
50
|
from .checks import start_trace
|
|
46
51
|
from .integration import Integration
|
|
52
|
+
from .logs import LOGS_ENDPOINT
|
|
53
|
+
from .logs import OTLPLogsGRPCServicer
|
|
54
|
+
from .logs import decode_logs_request
|
|
55
|
+
from .metrics import METRICS_ENDPOINT
|
|
56
|
+
from .metrics import OTLPMetricsGRPCServicer
|
|
57
|
+
from .metrics import decode_metrics_request
|
|
47
58
|
from .remoteconfig import RemoteConfigServer
|
|
48
59
|
from .trace import Span
|
|
49
60
|
from .trace import Trace
|
|
50
61
|
from .trace import TraceMap
|
|
62
|
+
from .trace import decode_v1 as trace_decode_v1
|
|
51
63
|
from .trace import decode_v04 as trace_decode_v04
|
|
52
64
|
from .trace import decode_v05 as trace_decode_v05
|
|
53
65
|
from .trace import decode_v07 as trace_decode_v07
|
|
@@ -66,6 +78,12 @@ from .tracestats import v06StatsPayload
|
|
|
66
78
|
from .vcr_proxy import proxy_request
|
|
67
79
|
|
|
68
80
|
|
|
81
|
+
# Default ports
|
|
82
|
+
DEFAULT_APM_PORT = 8126
|
|
83
|
+
DEFAULT_OTLP_HTTP_PORT = 4318
|
|
84
|
+
DEFAULT_OTLP_GRPC_PORT = 4317
|
|
85
|
+
|
|
86
|
+
|
|
69
87
|
class NoSuchSessionException(Exception):
|
|
70
88
|
pass
|
|
71
89
|
|
|
@@ -118,7 +136,7 @@ async def _vcr_proxy_cassette_prefix(request: Request) -> Optional[str]:
|
|
|
118
136
|
request_body: dict[str, str] = await request.json()
|
|
119
137
|
requested_test_name = request_body.get("test_name")
|
|
120
138
|
return requested_test_name
|
|
121
|
-
except json.JSONDecodeError:
|
|
139
|
+
except (json.JSONDecodeError, UnicodeDecodeError):
|
|
122
140
|
return None
|
|
123
141
|
|
|
124
142
|
|
|
@@ -247,6 +265,7 @@ class Agent:
|
|
|
247
265
|
"/v0.4/traces",
|
|
248
266
|
"/v0.5/traces",
|
|
249
267
|
"/v0.7/traces",
|
|
268
|
+
"/v1.0/traces",
|
|
250
269
|
"/v0.6/stats",
|
|
251
270
|
"/v0.7/config",
|
|
252
271
|
"/telemetry/proxy/api/v2/apmtelemetry",
|
|
@@ -428,6 +447,8 @@ class Agent:
|
|
|
428
447
|
return self._decode_v05_traces(req)
|
|
429
448
|
elif req.match_info.handler == self.handle_v07_traces:
|
|
430
449
|
return self._decode_v07_traces(req)
|
|
450
|
+
elif req.match_info.handler == self.handle_v1_traces:
|
|
451
|
+
return self._decode_v1_traces(req)
|
|
431
452
|
return []
|
|
432
453
|
|
|
433
454
|
async def _traces_by_session(self, token: Optional[str]) -> List[Trace]:
|
|
@@ -486,6 +507,34 @@ class Agent:
|
|
|
486
507
|
stats.append(s)
|
|
487
508
|
return stats
|
|
488
509
|
|
|
510
|
+
async def _logs_by_session(self, token: Optional[str]) -> List[Dict[str, Any]]:
|
|
511
|
+
"""Return the logs that belong to the given session token.
|
|
512
|
+
|
|
513
|
+
If token is None or if the token was used to manually start a session
|
|
514
|
+
with /session-start then return all logs that were sent since the last
|
|
515
|
+
/session-start request was made.
|
|
516
|
+
"""
|
|
517
|
+
logs: List[Dict[str, Any]] = []
|
|
518
|
+
for req in self._requests_by_session(token):
|
|
519
|
+
if req.match_info.handler == self.handle_v1_logs:
|
|
520
|
+
logs_data = self._decode_v1_logs(req)
|
|
521
|
+
logs.append(logs_data)
|
|
522
|
+
return logs
|
|
523
|
+
|
|
524
|
+
async def _metrics_by_session(self, token: Optional[str]) -> List[Dict[str, Any]]:
|
|
525
|
+
"""Return the metrics that belong to the given session token.
|
|
526
|
+
|
|
527
|
+
If token is None or if the token was used to manually start a session
|
|
528
|
+
with /session-start then return all metrics that were sent since the last
|
|
529
|
+
/session-start request was made.
|
|
530
|
+
"""
|
|
531
|
+
metrics: List[Dict[str, Any]] = []
|
|
532
|
+
for req in self._requests_by_session(token):
|
|
533
|
+
if req.match_info.handler == self.handle_v1_metrics:
|
|
534
|
+
metrics_data = self._decode_v1_metrics(req)
|
|
535
|
+
metrics.append(metrics_data)
|
|
536
|
+
return metrics
|
|
537
|
+
|
|
489
538
|
async def _integration_requests_by_session(
|
|
490
539
|
self,
|
|
491
540
|
token: Optional[str],
|
|
@@ -554,10 +603,30 @@ class Agent:
|
|
|
554
603
|
raw_data = self._request_data(request)
|
|
555
604
|
return trace_decode_v07(raw_data)
|
|
556
605
|
|
|
606
|
+
def _decode_v1_traces(self, request: Request) -> v04TracePayload:
|
|
607
|
+
raw_data = self._request_data(request)
|
|
608
|
+
return trace_decode_v1(raw_data)
|
|
609
|
+
|
|
557
610
|
def _decode_v06_tracestats(self, request: Request) -> v06StatsPayload:
|
|
558
611
|
raw_data = self._request_data(request)
|
|
559
612
|
return tracestats_decode_v06(raw_data)
|
|
560
613
|
|
|
614
|
+
def _decode_v1_logs(self, request: Request) -> Dict[str, Any]:
|
|
615
|
+
raw_data = self._request_data(request)
|
|
616
|
+
content_type = request.headers.get("Content-Type", "").lower().strip()
|
|
617
|
+
try:
|
|
618
|
+
return decode_logs_request(raw_data, content_type)
|
|
619
|
+
except Exception as e:
|
|
620
|
+
raise web.HTTPBadRequest(text=str(e))
|
|
621
|
+
|
|
622
|
+
def _decode_v1_metrics(self, request: Request) -> Dict[str, Any]:
|
|
623
|
+
raw_data = self._request_data(request)
|
|
624
|
+
content_type = request.headers.get("Content-Type", "").lower().strip()
|
|
625
|
+
try:
|
|
626
|
+
return decode_metrics_request(raw_data, content_type)
|
|
627
|
+
except Exception as e:
|
|
628
|
+
raise web.HTTPBadRequest(text=str(e))
|
|
629
|
+
|
|
561
630
|
async def handle_v04_traces(self, request: Request) -> web.Response:
|
|
562
631
|
return await self._handle_traces(request, version="v0.4")
|
|
563
632
|
|
|
@@ -567,6 +636,9 @@ class Agent:
|
|
|
567
636
|
async def handle_v07_traces(self, request: Request) -> web.Response:
|
|
568
637
|
return await self._handle_traces(request, version="v0.7")
|
|
569
638
|
|
|
639
|
+
async def handle_v1_traces(self, request: Request) -> web.Response:
|
|
640
|
+
return await self._handle_traces(request, version="v1")
|
|
641
|
+
|
|
570
642
|
async def handle_v06_tracestats(self, request: Request) -> web.Response:
|
|
571
643
|
stats = self._decode_v06_tracestats(request)
|
|
572
644
|
nstats = len(stats["Stats"])
|
|
@@ -581,6 +653,36 @@ class Agent:
|
|
|
581
653
|
log.info("received /v0.1/pipeline_stats payload")
|
|
582
654
|
return web.HTTPOk()
|
|
583
655
|
|
|
656
|
+
async def handle_v1_logs(self, request: Request) -> web.Response:
|
|
657
|
+
logs_data = self._decode_v1_logs(request)
|
|
658
|
+
num_resource_logs = len(logs_data.get("resource_logs", []))
|
|
659
|
+
total_log_records = sum(
|
|
660
|
+
len(scope_log.get("log_records", []))
|
|
661
|
+
for resource_log in logs_data.get("resource_logs", [])
|
|
662
|
+
for scope_log in resource_log.get("scope_logs", [])
|
|
663
|
+
)
|
|
664
|
+
log.info(
|
|
665
|
+
"received /v1/logs payload with %r resource log(s) containing %r log record(s)",
|
|
666
|
+
num_resource_logs,
|
|
667
|
+
total_log_records,
|
|
668
|
+
)
|
|
669
|
+
return web.HTTPOk()
|
|
670
|
+
|
|
671
|
+
async def handle_v1_metrics(self, request: Request) -> web.Response:
|
|
672
|
+
metrics_data = self._decode_v1_metrics(request)
|
|
673
|
+
num_resource_metrics = len(metrics_data.get("resource_metrics", []))
|
|
674
|
+
total_metrics = sum(
|
|
675
|
+
len(scope_metric.get("metrics", []))
|
|
676
|
+
for resource_metric in metrics_data.get("resource_metrics", [])
|
|
677
|
+
for scope_metric in resource_metric.get("scope_metrics", [])
|
|
678
|
+
)
|
|
679
|
+
log.info(
|
|
680
|
+
"received /v1/metrics payload with %r resource metric(s) containing %r metric(s)",
|
|
681
|
+
num_resource_metrics,
|
|
682
|
+
total_metrics,
|
|
683
|
+
)
|
|
684
|
+
return web.HTTPOk()
|
|
685
|
+
|
|
584
686
|
async def handle_v07_remoteconfig(self, request: Request) -> web.Response:
|
|
585
687
|
"""Emulates Remote Config endpoint: /v0.7/config"""
|
|
586
688
|
token = _session_token(request)
|
|
@@ -732,7 +834,7 @@ class Agent:
|
|
|
732
834
|
headers={"Datadog-Agent-State": "03e868b3ecdd62a91423cc4c3917d0d151fb9fa486736911ab7f5a0750c63824"},
|
|
733
835
|
)
|
|
734
836
|
|
|
735
|
-
async def _handle_traces(self, request: Request, version: Literal["v0.4", "v0.5", "v0.7"]) -> web.Response:
|
|
837
|
+
async def _handle_traces(self, request: Request, version: Literal["v0.4", "v0.5", "v0.7", "v1"]) -> web.Response:
|
|
736
838
|
token = request["session_token"]
|
|
737
839
|
checks: Checks = request.app["checks"]
|
|
738
840
|
headers = request.headers
|
|
@@ -753,6 +855,8 @@ class Agent:
|
|
|
753
855
|
traces = self._decode_v05_traces(request)
|
|
754
856
|
elif version == "v0.7":
|
|
755
857
|
traces = self._decode_v07_traces(request)
|
|
858
|
+
elif version == "v1":
|
|
859
|
+
traces = self._decode_v1_traces(request)
|
|
756
860
|
log.info(
|
|
757
861
|
"received trace for token %r payload with %r trace chunks",
|
|
758
862
|
token,
|
|
@@ -941,6 +1045,16 @@ class Agent:
|
|
|
941
1045
|
stats = await self._tracestats_by_session(token)
|
|
942
1046
|
return web.json_response(stats)
|
|
943
1047
|
|
|
1048
|
+
async def handle_session_logs(self, request: Request) -> web.Response:
|
|
1049
|
+
token = request["session_token"]
|
|
1050
|
+
logs = await self._logs_by_session(token)
|
|
1051
|
+
return web.json_response(logs)
|
|
1052
|
+
|
|
1053
|
+
async def handle_session_metrics(self, request: Request) -> web.Response:
|
|
1054
|
+
token = request["session_token"]
|
|
1055
|
+
metrics = await self._metrics_by_session(token)
|
|
1056
|
+
return web.json_response(metrics)
|
|
1057
|
+
|
|
944
1058
|
async def handle_session_requests(self, request: Request) -> web.Response:
|
|
945
1059
|
token = request["session_token"]
|
|
946
1060
|
resp = []
|
|
@@ -957,6 +1071,8 @@ class Agent:
|
|
|
957
1071
|
self.handle_v1_tracer_flare,
|
|
958
1072
|
self.handle_evp_proxy_v2_api_v2_llmobs,
|
|
959
1073
|
self.handle_evp_proxy_v2_llmobs_eval_metric,
|
|
1074
|
+
self.handle_v1_logs,
|
|
1075
|
+
self.handle_v1_metrics,
|
|
960
1076
|
):
|
|
961
1077
|
continue
|
|
962
1078
|
resp.append(
|
|
@@ -1174,6 +1290,59 @@ class Agent:
|
|
|
1174
1290
|
return response
|
|
1175
1291
|
|
|
1176
1292
|
|
|
1293
|
+
def make_otlp_http_app(agent: Agent) -> web.Application:
|
|
1294
|
+
"""Create a separate HTTP application for OTLP endpoints using the shared agent instance."""
|
|
1295
|
+
|
|
1296
|
+
@middleware
|
|
1297
|
+
async def otlp_store_request_middleware(request: Request, handler: _Handler) -> web.Response:
|
|
1298
|
+
# Always store requests for OTLP endpoints
|
|
1299
|
+
await agent._store_request(request)
|
|
1300
|
+
return await handler(request)
|
|
1301
|
+
|
|
1302
|
+
app = web.Application(
|
|
1303
|
+
middlewares=[
|
|
1304
|
+
otlp_store_request_middleware, # type: ignore
|
|
1305
|
+
session_token_middleware, # type: ignore
|
|
1306
|
+
],
|
|
1307
|
+
)
|
|
1308
|
+
|
|
1309
|
+
# Add only OTLP HTTP endpoints
|
|
1310
|
+
app.add_routes(
|
|
1311
|
+
[
|
|
1312
|
+
web.post(LOGS_ENDPOINT, agent.handle_v1_logs),
|
|
1313
|
+
web.post(METRICS_ENDPOINT, agent.handle_v1_metrics),
|
|
1314
|
+
web.get("/test/session/requests", agent.handle_session_requests),
|
|
1315
|
+
web.get("/test/session/logs", agent.handle_session_logs),
|
|
1316
|
+
web.get("/test/session/metrics", agent.handle_session_metrics),
|
|
1317
|
+
web.get("/test/session/clear", agent.handle_session_clear),
|
|
1318
|
+
web.get("/test/session/start", agent.handle_session_start),
|
|
1319
|
+
]
|
|
1320
|
+
)
|
|
1321
|
+
|
|
1322
|
+
return app
|
|
1323
|
+
|
|
1324
|
+
|
|
1325
|
+
async def make_otlp_grpc_server_async(agent: Agent, http_port: int, grpc_port: int) -> Any:
|
|
1326
|
+
"""Create and start a separate GRPC server for OTLP endpoints that forwards to HTTP server."""
|
|
1327
|
+
# Define the servicer class only when GRPC is available
|
|
1328
|
+
server = grpc_aio.server()
|
|
1329
|
+
|
|
1330
|
+
# Add the OTLP logs servicer
|
|
1331
|
+
logs_servicer = OTLPLogsGRPCServicer(http_port)
|
|
1332
|
+
add_LogsServiceServicer_to_server(logs_servicer, server)
|
|
1333
|
+
|
|
1334
|
+
# Add the OTLP metrics servicer
|
|
1335
|
+
metrics_servicer = OTLPMetricsGRPCServicer(http_port)
|
|
1336
|
+
add_MetricsServiceServicer_to_server(metrics_servicer, server)
|
|
1337
|
+
|
|
1338
|
+
# Setup and start the server
|
|
1339
|
+
listen_addr = f"[::]:{grpc_port}"
|
|
1340
|
+
server.add_insecure_port(listen_addr)
|
|
1341
|
+
await server.start()
|
|
1342
|
+
|
|
1343
|
+
return server
|
|
1344
|
+
|
|
1345
|
+
|
|
1177
1346
|
def make_app(
|
|
1178
1347
|
enabled_checks: List[str],
|
|
1179
1348
|
log_span_fmt: str,
|
|
@@ -1209,6 +1378,8 @@ def make_app(
|
|
|
1209
1378
|
web.put("/v0.5/traces", agent.handle_v05_traces),
|
|
1210
1379
|
web.post("/v0.7/traces", agent.handle_v07_traces),
|
|
1211
1380
|
web.put("/v0.7/traces", agent.handle_v07_traces),
|
|
1381
|
+
web.post("/v1.0/traces", agent.handle_v1_traces),
|
|
1382
|
+
web.put("/v1.0/traces", agent.handle_v1_traces),
|
|
1212
1383
|
web.post("/v0.6/stats", agent.handle_v06_tracestats),
|
|
1213
1384
|
web.post("/v0.1/pipeline_stats", agent.handle_v01_pipelinestats),
|
|
1214
1385
|
web.put("/v0.6/stats", agent.handle_v06_tracestats),
|
|
@@ -1262,6 +1433,7 @@ def make_app(
|
|
|
1262
1433
|
],
|
|
1263
1434
|
enabled=enabled_checks,
|
|
1264
1435
|
)
|
|
1436
|
+
app["agent"] = agent
|
|
1265
1437
|
app["checks"] = checks
|
|
1266
1438
|
app["snapshot_dir"] = snapshot_dir
|
|
1267
1439
|
app["snapshot_ci_mode"] = snapshot_ci_mode
|
|
@@ -1293,6 +1465,18 @@ def main(args: Optional[List[str]] = None) -> None:
|
|
|
1293
1465
|
help="Print version info and exit.",
|
|
1294
1466
|
)
|
|
1295
1467
|
parser.add_argument("-p", "--port", type=int, default=int(os.environ.get("PORT", 8126)))
|
|
1468
|
+
parser.add_argument(
|
|
1469
|
+
"--otlp-http-port",
|
|
1470
|
+
type=int,
|
|
1471
|
+
default=int(os.environ.get("OTLP_HTTP_PORT", 4318)),
|
|
1472
|
+
help="Port to listen for OTLP HTTP requests (default: 4318)",
|
|
1473
|
+
)
|
|
1474
|
+
parser.add_argument(
|
|
1475
|
+
"--otlp-grpc-port",
|
|
1476
|
+
type=int,
|
|
1477
|
+
default=int(os.environ.get("OTLP_GRPC_PORT", 4317)),
|
|
1478
|
+
help="Port to listen for OTLP GRPC requests (default: 4317)",
|
|
1479
|
+
)
|
|
1296
1480
|
parser.add_argument(
|
|
1297
1481
|
"--snapshot-dir",
|
|
1298
1482
|
type=str,
|
|
@@ -1444,7 +1628,60 @@ def main(args: Optional[List[str]] = None) -> None:
|
|
|
1444
1628
|
vcr_cassettes_directory=parsed_args.vcr_cassettes_directory,
|
|
1445
1629
|
)
|
|
1446
1630
|
|
|
1447
|
-
|
|
1631
|
+
# Validate port configuration
|
|
1632
|
+
if parsed_args.port == parsed_args.otlp_http_port:
|
|
1633
|
+
raise ValueError("APM and OTLP HTTP ports cannot be the same")
|
|
1634
|
+
if parsed_args.port == parsed_args.otlp_grpc_port:
|
|
1635
|
+
raise ValueError("APM and OTLP GRPC ports cannot be the same")
|
|
1636
|
+
if parsed_args.otlp_http_port == parsed_args.otlp_grpc_port:
|
|
1637
|
+
raise ValueError("OTLP HTTP and GRPC ports cannot be the same")
|
|
1638
|
+
|
|
1639
|
+
# Get the shared agent instance from the main app
|
|
1640
|
+
agent = app["agent"]
|
|
1641
|
+
otlp_http_app = make_otlp_http_app(agent)
|
|
1642
|
+
|
|
1643
|
+
async def run_servers():
|
|
1644
|
+
"""Run APM and OTLP HTTP servers concurrently."""
|
|
1645
|
+
# Create runners for both apps
|
|
1646
|
+
apm_runner = web.AppRunner(app)
|
|
1647
|
+
await apm_runner.setup()
|
|
1648
|
+
|
|
1649
|
+
otlp_http_runner = web.AppRunner(otlp_http_app)
|
|
1650
|
+
await otlp_http_runner.setup()
|
|
1651
|
+
|
|
1652
|
+
# Start GRPC server if available (async creation)
|
|
1653
|
+
otlp_grpc_server = await make_otlp_grpc_server_async(
|
|
1654
|
+
agent, parsed_args.otlp_http_port, parsed_args.otlp_grpc_port
|
|
1655
|
+
)
|
|
1656
|
+
|
|
1657
|
+
# Create sites for both apps
|
|
1658
|
+
if apm_sock:
|
|
1659
|
+
apm_site = web.SockSite(apm_runner, apm_sock)
|
|
1660
|
+
else:
|
|
1661
|
+
apm_site = web.TCPSite(apm_runner, port=parsed_args.port)
|
|
1662
|
+
|
|
1663
|
+
otlp_http_site = web.TCPSite(otlp_http_runner, port=parsed_args.otlp_http_port)
|
|
1664
|
+
|
|
1665
|
+
# Start both servers concurrently
|
|
1666
|
+
await asyncio.gather(apm_site.start(), otlp_http_site.start())
|
|
1667
|
+
|
|
1668
|
+
print(f"======== Running APM server on port {parsed_args.port} ========")
|
|
1669
|
+
print(f"======== Running OTLP HTTP server on port {parsed_args.otlp_http_port} ========")
|
|
1670
|
+
print(f"======== Running OTLP GRPC server on port {parsed_args.otlp_grpc_port} ========")
|
|
1671
|
+
print("(Press CTRL+C to quit)")
|
|
1672
|
+
|
|
1673
|
+
try:
|
|
1674
|
+
# Keep the servers running
|
|
1675
|
+
await asyncio.Event().wait()
|
|
1676
|
+
except KeyboardInterrupt:
|
|
1677
|
+
pass
|
|
1678
|
+
finally:
|
|
1679
|
+
await apm_runner.cleanup()
|
|
1680
|
+
await otlp_http_runner.cleanup()
|
|
1681
|
+
await otlp_grpc_server.stop(grace=5.0)
|
|
1682
|
+
|
|
1683
|
+
# Run the servers
|
|
1684
|
+
asyncio.run(run_servers())
|
|
1448
1685
|
|
|
1449
1686
|
|
|
1450
1687
|
if __name__ == "__main__":
|
|
@@ -9,7 +9,7 @@ import requests
|
|
|
9
9
|
from ddapm_test_agent.trace import Trace
|
|
10
10
|
|
|
11
11
|
|
|
12
|
-
class
|
|
12
|
+
class TestClient:
|
|
13
13
|
__test__ = False
|
|
14
14
|
|
|
15
15
|
def __init__(self, base_url: str):
|
|
@@ -19,6 +19,28 @@ class TestAgentClient:
|
|
|
19
19
|
def _url(self, path: str) -> str:
|
|
20
20
|
return urllib.parse.urljoin(self._base_url, path)
|
|
21
21
|
|
|
22
|
+
def requests(self, **kwargs: Any) -> List[Any]:
|
|
23
|
+
resp = self._session.get(self._url("/test/session/requests"), **kwargs)
|
|
24
|
+
json = resp.json()
|
|
25
|
+
return cast(List[Any], json)
|
|
26
|
+
|
|
27
|
+
def clear(self, **kwargs: Any) -> None:
|
|
28
|
+
self._session.get(self._url("/test/session/clear"), **kwargs)
|
|
29
|
+
|
|
30
|
+
def wait_to_start(self, num_tries: int = 50, delay: float = 0.1) -> None:
|
|
31
|
+
exc = []
|
|
32
|
+
for i in range(num_tries):
|
|
33
|
+
try:
|
|
34
|
+
self.requests()
|
|
35
|
+
except requests.exceptions.RequestException as e:
|
|
36
|
+
exc.append(e)
|
|
37
|
+
time.sleep(delay)
|
|
38
|
+
else:
|
|
39
|
+
return
|
|
40
|
+
raise AssertionError(f"Test agent did not start in time ({num_tries * delay} seconds). Got {exc[-1]}")
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
class TestAgentClient(TestClient):
|
|
22
44
|
def traces(self, clear: bool = False, **kwargs: Any) -> List[Trace]:
|
|
23
45
|
resp = self._session.get(self._url("/test/session/traces"), **kwargs)
|
|
24
46
|
if clear:
|
|
@@ -26,11 +48,6 @@ class TestAgentClient:
|
|
|
26
48
|
json = resp.json()
|
|
27
49
|
return cast(List[Trace], json)
|
|
28
50
|
|
|
29
|
-
def requests(self, **kwargs: Any) -> List[Any]:
|
|
30
|
-
resp = self._session.get(self._url("/test/session/requests"), **kwargs)
|
|
31
|
-
json = resp.json()
|
|
32
|
-
return cast(List[Any], json)
|
|
33
|
-
|
|
34
51
|
def raw_telemetry(self, clear: bool = False) -> List[Any]:
|
|
35
52
|
raw_reqs = self.requests()
|
|
36
53
|
reqs = []
|
|
@@ -47,9 +64,6 @@ class TestAgentClient:
|
|
|
47
64
|
self.clear()
|
|
48
65
|
return cast(List[Any], resp.json())
|
|
49
66
|
|
|
50
|
-
def clear(self, **kwargs: Any) -> None:
|
|
51
|
-
self._session.get(self._url("/test/session/clear"), **kwargs)
|
|
52
|
-
|
|
53
67
|
def info(self, **kwargs):
|
|
54
68
|
resp = self._session.get(self._url("/info"), **kwargs)
|
|
55
69
|
json = resp.json()
|
|
@@ -126,14 +140,43 @@ class TestAgentClient:
|
|
|
126
140
|
time.sleep(0.01)
|
|
127
141
|
raise AssertionError("Telemetry event %r not found" % event_name)
|
|
128
142
|
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
143
|
+
|
|
144
|
+
class TestOTLPClient(TestClient):
|
|
145
|
+
def __init__(self, host: str = "127.0.0.1", http_port: int = 4318, scheme: str = "http"):
|
|
146
|
+
# OTLP grpc server will forward all requests to the http server
|
|
147
|
+
# so we can use the same client to receive logs for both http and grpc endpoints
|
|
148
|
+
super().__init__(f"{scheme}://{host}:{http_port}")
|
|
149
|
+
|
|
150
|
+
def logs(self, clear: bool = False, **kwargs: Any) -> List[Any]:
|
|
151
|
+
resp = self._session.get(self._url("/test/session/logs"), **kwargs)
|
|
152
|
+
if clear:
|
|
153
|
+
self.clear()
|
|
154
|
+
return cast(List[Any], resp.json())
|
|
155
|
+
|
|
156
|
+
def wait_for_num_logs(self, num: int, clear: bool = False, wait_loops: int = 30) -> List[Any]:
|
|
157
|
+
"""Wait for `num` logs to be received from the test agent."""
|
|
158
|
+
for _ in range(wait_loops):
|
|
159
|
+
logs = self.logs(clear=False)
|
|
160
|
+
if len(logs) == num:
|
|
161
|
+
if clear:
|
|
162
|
+
self.clear()
|
|
163
|
+
return logs
|
|
164
|
+
time.sleep(0.1)
|
|
165
|
+
raise ValueError("Number (%r) of logs not available from test agent, got %r" % (num, len(logs)))
|
|
166
|
+
|
|
167
|
+
def metrics(self, clear: bool = False, **kwargs: Any) -> List[Any]:
|
|
168
|
+
resp = self._session.get(self._url("/test/session/metrics"), **kwargs)
|
|
169
|
+
if clear:
|
|
170
|
+
self.clear()
|
|
171
|
+
return cast(List[Any], resp.json())
|
|
172
|
+
|
|
173
|
+
def wait_for_num_metrics(self, num: int, clear: bool = False, wait_loops: int = 30) -> List[Any]:
|
|
174
|
+
"""Wait for `num` metrics to be received from the test agent."""
|
|
175
|
+
for _ in range(wait_loops):
|
|
176
|
+
metrics = self.metrics(clear=False)
|
|
177
|
+
if len(metrics) == num:
|
|
178
|
+
if clear:
|
|
179
|
+
self.clear()
|
|
180
|
+
return metrics
|
|
181
|
+
time.sleep(0.1)
|
|
182
|
+
raise ValueError("Number (%r) of metrics not available from test agent, got %r" % (num, len(metrics)))
|