dd-trace 6.15.0 → 6.17.0
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.
- package/README.md +15 -0
- package/ci/diagnose.js +0 -23
- package/ci/test-optimization-validation/approval-artifacts.js +0 -3
- package/ci/test-optimization-validation/approval.js +0 -6
- package/ci/test-optimization-validation/artifact-id.js +0 -1
- package/ci/test-optimization-validation/bounded-json.js +0 -1
- package/ci/test-optimization-validation/cli.js +0 -12
- package/ci/test-optimization-validation/command-output-policy.js +0 -1
- package/ci/test-optimization-validation/command-runner.js +0 -3
- package/ci/test-optimization-validation/environment.js +0 -4
- package/ci/test-optimization-validation/executable-approval.js +0 -1
- package/ci/test-optimization-validation/executable.js +0 -5
- package/ci/test-optimization-validation/framework-adapters/cucumber.js +4 -8
- package/ci/test-optimization-validation/framework-adapters/cypress.js +0 -3
- package/ci/test-optimization-validation/framework-adapters/playwright.js +0 -6
- package/ci/test-optimization-validation/framework-adapters/vitest.js +0 -4
- package/ci/test-optimization-validation/generated-test-contract.js +0 -5
- package/ci/test-optimization-validation/generated-verifier.js +0 -1
- package/ci/test-optimization-validation/literal-environment.js +0 -1
- package/ci/test-optimization-validation/manifest-scaffold.js +0 -17
- package/ci/test-optimization-validation/manifest-schema.js +0 -21
- package/ci/test-optimization-validation/offline-fixtures.js +0 -4
- package/ci/test-optimization-validation/package-check.js +4 -1
- package/ci/test-optimization-validation/plan-writer.js +0 -11
- package/ci/test-optimization-validation/preflight-runner.js +0 -1
- package/ci/test-optimization-validation/redaction.js +0 -4
- package/ci/test-optimization-validation/report-writer.js +0 -16
- package/ci/test-optimization-validation/runner-command.js +0 -3
- package/ci/test-optimization-validation/runner-contract.js +0 -4
- package/ci/test-optimization-validation/safe-files.js +0 -1
- package/ci/test-optimization-validation/scenarios/basic-reporting.js +0 -1
- package/ci/test-optimization-validation/scenarios/ci-wiring.js +1 -2
- package/ci/test-optimization-validation/source-text.js +0 -3
- package/ci/vitest-no-worker-init-setup.mjs +41 -16
- package/index.d.ts +169 -0
- package/next.d.ts +27 -0
- package/next.js +3 -0
- package/package.json +28 -23
- package/packages/datadog-esbuild/index.js +14 -1
- package/packages/datadog-esbuild/src/resolver.js +284 -0
- package/packages/datadog-esbuild/src/utils.js +162 -120
- package/packages/datadog-instrumentations/src/aerospike.js +28 -6
- package/packages/datadog-instrumentations/src/ai.js +39 -97
- package/packages/datadog-instrumentations/src/anthropic.js +76 -134
- package/packages/datadog-instrumentations/src/aws-durable-execution-sdk-js.js +1 -3
- package/packages/datadog-instrumentations/src/aws-sdk.js +0 -2
- package/packages/datadog-instrumentations/src/azure-cosmos.js +1 -1
- package/packages/datadog-instrumentations/src/azure-durable-functions.js +23 -9
- package/packages/datadog-instrumentations/src/azure-functions.js +48 -0
- package/packages/datadog-instrumentations/src/bullmq.js +1 -1
- package/packages/datadog-instrumentations/src/claude-agent-sdk.js +1 -3
- package/packages/datadog-instrumentations/src/console.js +97 -0
- package/packages/datadog-instrumentations/src/cucumber.js +72 -12
- package/packages/datadog-instrumentations/src/cypress-config.js +0 -23
- package/packages/datadog-instrumentations/src/dd-trace-api.js +2 -2
- package/packages/datadog-instrumentations/src/graphql.js +1 -1
- package/packages/datadog-instrumentations/src/helpers/bundler-register.js +39 -14
- package/packages/datadog-instrumentations/src/helpers/channel.js +0 -2
- package/packages/datadog-instrumentations/src/helpers/graphql-jit-runtime.js +0 -5
- package/packages/datadog-instrumentations/src/helpers/hooks.js +8 -0
- package/packages/datadog-instrumentations/src/helpers/instrument.js +25 -8
- package/packages/datadog-instrumentations/src/helpers/instrumentation-utils.js +69 -0
- package/packages/datadog-instrumentations/src/helpers/pool-acquire.js +0 -6
- package/packages/datadog-instrumentations/src/helpers/register.js +13 -64
- package/packages/datadog-instrumentations/src/helpers/rewriter/index.js +109 -29
- package/packages/datadog-instrumentations/src/helpers/rewriter/instrumentation-registry.js +39 -0
- package/packages/datadog-instrumentations/src/helpers/rewriter/instrumentations/azure-durable-functions.js +17 -0
- package/packages/datadog-instrumentations/src/helpers/rewriter/instrumentations/index.js +3 -16
- package/packages/datadog-instrumentations/src/helpers/rewriter/instrumentations/playwright.js +12 -0
- package/packages/datadog-instrumentations/src/helpers/rewriter/instrumentations/postgres.js +36 -0
- package/packages/datadog-instrumentations/src/helpers/rewriter/instrumentations/supabase.js +128 -0
- package/packages/datadog-instrumentations/src/helpers/rewriter/instrumentations/webdriverio.js +6 -7
- package/packages/datadog-instrumentations/src/helpers/rewriter/targets.json +17 -0
- package/packages/datadog-instrumentations/src/helpers/rewriter/transforms/postgres.js +388 -0
- package/packages/datadog-instrumentations/src/helpers/rewriter/transforms.js +99 -75
- package/packages/datadog-instrumentations/src/helpers/router-helper.js +0 -1
- package/packages/datadog-instrumentations/src/jest.js +141 -51
- package/packages/datadog-instrumentations/src/knex.js +0 -1
- package/packages/datadog-instrumentations/src/langchain.js +1 -1
- package/packages/datadog-instrumentations/src/langgraph.js +1 -1
- package/packages/datadog-instrumentations/src/mariadb-bundle.js +0 -24
- package/packages/datadog-instrumentations/src/mariadb.js +0 -2
- package/packages/datadog-instrumentations/src/mercurius.js +1 -1
- package/packages/datadog-instrumentations/src/mocha/common.js +0 -1
- package/packages/datadog-instrumentations/src/mocha/main.js +22 -25
- package/packages/datadog-instrumentations/src/mocha/utils.js +119 -49
- package/packages/datadog-instrumentations/src/mocha/webdriverio-protocol.js +0 -6
- package/packages/datadog-instrumentations/src/mocha/worker.js +14 -17
- package/packages/datadog-instrumentations/src/modelcontextprotocol-sdk.js +1 -1
- package/packages/datadog-instrumentations/src/mysql2.js +0 -2
- package/packages/datadog-instrumentations/src/openai-agents.js +1 -1
- package/packages/datadog-instrumentations/src/openai-realtime/audio-accumulator.js +241 -0
- package/packages/datadog-instrumentations/src/openai-realtime/events.js +76 -0
- package/packages/datadog-instrumentations/src/openai-realtime/index.js +301 -0
- package/packages/datadog-instrumentations/src/openai-realtime/session.js +998 -0
- package/packages/datadog-instrumentations/src/openai-realtime/turns.js +211 -0
- package/packages/datadog-instrumentations/src/openai.js +97 -80
- package/packages/datadog-instrumentations/src/oracledb.js +9 -3
- package/packages/datadog-instrumentations/src/playwright-reporter.js +3 -16
- package/packages/datadog-instrumentations/src/playwright.js +238 -55
- package/packages/datadog-instrumentations/src/postgres.js +7 -0
- package/packages/datadog-instrumentations/src/router.js +0 -2
- package/packages/datadog-instrumentations/src/rum-browser-scripts.js +0 -2
- package/packages/datadog-instrumentations/src/sequelize.js +0 -1
- package/packages/datadog-instrumentations/src/supabase.js +15 -0
- package/packages/datadog-instrumentations/src/vitest-main-no-worker-init.js +18 -18
- package/packages/datadog-instrumentations/src/vitest-main.js +37 -17
- package/packages/datadog-instrumentations/src/vitest-util.js +7 -1
- package/packages/datadog-instrumentations/src/vitest-worker.js +56 -23
- package/packages/datadog-instrumentations/src/webdriverio.js +23 -42
- package/packages/datadog-instrumentations/src/ws.js +0 -1
- package/packages/datadog-plugin-ai/src/utils.js +0 -2
- package/packages/datadog-plugin-aws-durable-execution-sdk-js/src/trace-checkpoint.js +0 -1
- package/packages/datadog-plugin-aws-durable-execution-sdk-js/src/util.js +0 -2
- package/packages/datadog-plugin-aws-sdk/src/base.js +0 -1
- package/packages/datadog-plugin-aws-sdk/src/services/bedrockruntime/utils.js +7 -2
- package/packages/datadog-plugin-aws-sdk/src/services/eventbridge.js +0 -1
- package/packages/datadog-plugin-aws-sdk/src/util.js +0 -1
- package/packages/datadog-plugin-azure-cosmos/src/index.js +1 -1
- package/packages/datadog-plugin-azure-durable-functions/src/index.js +95 -1
- package/packages/datadog-plugin-cucumber/src/index.js +10 -0
- package/packages/datadog-plugin-cypress/src/cypress-plugin.js +171 -75
- package/packages/datadog-plugin-cypress/src/finalization.js +0 -3
- package/packages/datadog-plugin-cypress/src/source-map-utils.js +0 -4
- package/packages/datadog-plugin-cypress/src/support.js +52 -7
- package/packages/datadog-plugin-google-cloud-pubsub/src/consumer.js +2 -24
- package/packages/datadog-plugin-google-cloud-pubsub/src/pubsub-push-subscription.js +2 -36
- package/packages/datadog-plugin-google-cloud-pubsub/src/pubsub-request-context.js +31 -0
- package/packages/datadog-plugin-graphql/src/resolve-error.js +32 -11
- package/packages/datadog-plugin-graphql/src/utils.js +0 -5
- package/packages/datadog-plugin-jest/src/index.js +13 -0
- package/packages/datadog-plugin-kafkajs/src/producer.js +0 -1
- package/packages/datadog-plugin-mocha/src/index.js +39 -11
- package/packages/datadog-plugin-mongodb-core/src/query.js +0 -1
- package/packages/datadog-plugin-openai/src/index.js +16 -1
- package/packages/datadog-plugin-openai/src/realtime.js +144 -0
- package/packages/datadog-plugin-openai-agents/src/integration.js +0 -4
- package/packages/datadog-plugin-openai-agents/src/util.js +0 -1
- package/packages/datadog-plugin-playwright/src/index.js +76 -9
- package/packages/datadog-plugin-postgres/src/index.js +167 -0
- package/packages/datadog-plugin-prisma/src/datadog-tracing-helper.js +0 -1
- package/packages/datadog-plugin-redis/src/index.js +15 -1
- package/packages/datadog-plugin-supabase/src/error.js +18 -0
- package/packages/datadog-plugin-supabase/src/index.js +21 -0
- package/packages/datadog-plugin-supabase/src/supabase-auth-js-gotrueclient-getuser.js +69 -0
- package/packages/datadog-plugin-supabase/src/supabase-functions-js-functionsclient-invoke.js +70 -0
- package/packages/datadog-plugin-supabase/src/supabase-postgrest-js-postgrestbuilder-then.js +122 -0
- package/packages/datadog-plugin-supabase/src/supabase-realtime-js-realtimechannel-send.js +66 -0
- package/packages/datadog-plugin-supabase/src/supabase-storage-js-handle-request.js +93 -0
- package/packages/datadog-plugin-supabase/src/url.js +17 -0
- package/packages/datadog-plugin-vitest/src/index.js +10 -0
- package/packages/datadog-plugin-ws/src/util.js +0 -4
- package/packages/datadog-turbopack/index.js +206 -0
- package/packages/datadog-turbopack/src/constants.js +5 -0
- package/packages/datadog-turbopack/src/loader.js +484 -0
- package/packages/datadog-webpack/src/loader.js +0 -1
- package/packages/dd-trace/src/aiguard/client.js +2 -3
- package/packages/dd-trace/src/aiguard/evaluation.js +6 -12
- package/packages/dd-trace/src/aiguard/index.js +3 -2
- package/packages/dd-trace/src/aiguard/integrations/anthropic.js +53 -25
- package/packages/dd-trace/src/aiguard/integrations/evaluate.js +49 -25
- package/packages/dd-trace/src/aiguard/integrations/index.js +4 -3
- package/packages/dd-trace/src/aiguard/integrations/openai.js +132 -29
- package/packages/dd-trace/src/aiguard/integrations/vercel-ai.js +116 -42
- package/packages/dd-trace/src/aiguard/messages/anthropic.js +0 -2
- package/packages/dd-trace/src/aiguard/messages/openai.js +64 -1
- package/packages/dd-trace/src/aiguard/messages/utils.js +29 -2
- package/packages/dd-trace/src/aiguard/messages/vercel-ai.js +25 -0
- package/packages/dd-trace/src/aiguard/redaction.js +0 -1
- package/packages/dd-trace/src/aiguard/sdk.js +1 -1
- package/packages/dd-trace/src/appsec/activation.js +1 -1
- package/packages/dd-trace/src/appsec/api_security/normalized-route.js +0 -5
- package/packages/dd-trace/src/appsec/api_security/sampler.js +0 -4
- package/packages/dd-trace/src/appsec/blocking/index.js +3 -3
- package/packages/dd-trace/src/appsec/downstream_requests.js +1 -4
- package/packages/dd-trace/src/appsec/iast/index.js +1 -1
- package/packages/dd-trace/src/appsec/iast/overhead-controller.js +5 -5
- package/packages/dd-trace/src/appsec/iast/taint-tracking/index.js +1 -1
- package/packages/dd-trace/src/appsec/iast/taint-tracking/plugin.js +1 -1
- package/packages/dd-trace/src/appsec/iast/taint-tracking/rewriter.js +3 -3
- package/packages/dd-trace/src/appsec/iast/vulnerabilities-formatter/evidence-redaction/sensitive-analyzers/sql-sensitive-analyzer.js +8 -10
- package/packages/dd-trace/src/appsec/iast/vulnerabilities-formatter/evidence-redaction/sensitive-analyzers/url-sensitive-analyzer.js +2 -2
- package/packages/dd-trace/src/appsec/iast/vulnerabilities-formatter/evidence-redaction/sensitive-handler.js +2 -2
- package/packages/dd-trace/src/appsec/iast/vulnerabilities-formatter/utils.js +4 -1
- package/packages/dd-trace/src/appsec/iast/vulnerability-reporter.js +7 -7
- package/packages/dd-trace/src/appsec/index.js +2 -2
- package/packages/dd-trace/src/appsec/lambda.js +71 -2
- package/packages/dd-trace/src/appsec/rasp/utils.js +5 -1
- package/packages/dd-trace/src/appsec/remote_config.js +8 -6
- package/packages/dd-trace/src/appsec/reporter.js +10 -6
- package/packages/dd-trace/src/appsec/rule_manager.js +3 -3
- package/packages/dd-trace/src/appsec/sdk/track_event.js +0 -2
- package/packages/dd-trace/src/appsec/telemetry/api_security.js +1 -3
- package/packages/dd-trace/src/appsec/telemetry/common.js +4 -0
- package/packages/dd-trace/src/appsec/telemetry/index.js +23 -5
- package/packages/dd-trace/src/appsec/telemetry/rasp.js +1 -20
- package/packages/dd-trace/src/appsec/telemetry/user.js +1 -3
- package/packages/dd-trace/src/appsec/telemetry/waf.js +1 -20
- package/packages/dd-trace/src/appsec/waf/index.js +2 -2
- package/packages/dd-trace/src/appsec/waf/waf_manager.js +8 -5
- package/packages/dd-trace/src/carrier.js +0 -5
- package/packages/dd-trace/src/ci-visibility/dynamic-atr-retries.js +104 -0
- package/packages/dd-trace/src/ci-visibility/dynamic-instrumentation/worker/index.js +0 -2
- package/packages/dd-trace/src/ci-visibility/efd-retry-policy.js +34 -3
- package/packages/dd-trace/src/ci-visibility/exporters/agentless/coverage-writer.js +0 -1
- package/packages/dd-trace/src/ci-visibility/exporters/agentless/di-logs-writer.js +0 -1
- package/packages/dd-trace/src/ci-visibility/exporters/agentless/writer.js +0 -1
- package/packages/dd-trace/src/ci-visibility/exporters/ci-validation/index.js +0 -4
- package/packages/dd-trace/src/ci-visibility/exporters/ci-validation/msgpack-to-json.js +0 -1
- package/packages/dd-trace/src/ci-visibility/exporters/ci-validation/sink.js +0 -2
- package/packages/dd-trace/src/ci-visibility/exporters/ci-visibility-exporter.js +37 -15
- package/packages/dd-trace/src/ci-visibility/exporters/git/git_metadata.js +0 -3
- package/packages/dd-trace/src/ci-visibility/exporters/request.js +0 -11
- package/packages/dd-trace/src/ci-visibility/exporters/settings-cache-key.js +0 -1
- package/packages/dd-trace/src/ci-visibility/intelligent-test-runner/get-skippable-suites.js +0 -1
- package/packages/dd-trace/src/ci-visibility/requests/fs-cache.js +0 -6
- package/packages/dd-trace/src/ci-visibility/requests/get-library-configuration.js +2 -2
- package/packages/dd-trace/src/ci-visibility/requests/rate-limit.js +0 -1
- package/packages/dd-trace/src/ci-visibility/requests/upload-test-screenshot.js +0 -5
- package/packages/dd-trace/src/ci-visibility/requests/video-request.js +0 -1
- package/packages/dd-trace/src/ci-visibility/telemetry.js +13 -0
- package/packages/dd-trace/src/ci-visibility/test-optimization-cache.js +0 -1
- package/packages/dd-trace/src/ci-visibility/test-screenshot.js +0 -2
- package/packages/dd-trace/src/ci-visibility/test-video.js +0 -1
- package/packages/dd-trace/src/config/defaults.js +3 -2
- package/packages/dd-trace/src/config/generated-config-types.d.ts +74 -66
- package/packages/dd-trace/src/config/helper.js +9 -2
- package/packages/dd-trace/src/config/index.js +44 -29
- package/packages/dd-trace/src/config/parsers.js +34 -6
- package/packages/dd-trace/src/config/remote_config.js +25 -109
- package/packages/dd-trace/src/config/supported-configurations.json +146 -9
- package/packages/dd-trace/src/datastreams/encoding.js +0 -1
- package/packages/dd-trace/src/datastreams/pathway.js +0 -1
- package/packages/dd-trace/src/debugger/constants.js +10 -0
- package/packages/dd-trace/src/debugger/devtools_client/breakpoints.js +76 -17
- package/packages/dd-trace/src/debugger/devtools_client/config.js +2 -0
- package/packages/dd-trace/src/debugger/devtools_client/guardrail-metrics.js +15 -0
- package/packages/dd-trace/src/debugger/devtools_client/index.js +103 -27
- package/packages/dd-trace/src/debugger/devtools_client/json-buffer.js +50 -7
- package/packages/dd-trace/src/debugger/devtools_client/log.js +3 -1
- package/packages/dd-trace/src/debugger/devtools_client/probe_sampler.js +34 -8
- package/packages/dd-trace/src/debugger/devtools_client/send.js +40 -14
- package/packages/dd-trace/src/debugger/devtools_client/snapshot/index.js +53 -13
- package/packages/dd-trace/src/debugger/devtools_client/snapshot/processor.js +118 -71
- package/packages/dd-trace/src/debugger/devtools_client/snapshot-pruner.js +0 -3
- package/packages/dd-trace/src/debugger/devtools_client/status.js +20 -6
- package/packages/dd-trace/src/debugger/guardrail-metrics.js +167 -0
- package/packages/dd-trace/src/debugger/index.js +50 -2
- package/packages/dd-trace/src/debugger/inspect-segment.js +0 -3
- package/packages/dd-trace/src/debugger/probe_sampler.js +133 -9
- package/packages/dd-trace/src/debugger/probe_sampler_constants.js +31 -1
- package/packages/dd-trace/src/dogstatsd.js +0 -23
- package/packages/dd-trace/src/encode/0.4-cross-payload.js +0 -3
- package/packages/dd-trace/src/encode/0.4.js +0 -7
- package/packages/dd-trace/src/encode/0.5.js +0 -2
- package/packages/dd-trace/src/encode/tags-processors.js +0 -1
- package/packages/dd-trace/src/evp_proxy/discovery.js +3 -5
- package/packages/dd-trace/src/evp_proxy/path.js +11 -4
- package/packages/dd-trace/src/exporters/agent/writer.js +0 -1
- package/packages/dd-trace/src/exporters/agentless/index.js +0 -1
- package/packages/dd-trace/src/exporters/agentless/intake.js +0 -1
- package/packages/dd-trace/src/exporters/agentless/writer.js +0 -3
- package/packages/dd-trace/src/exporters/common/docker.js +4 -1
- package/packages/dd-trace/src/exporters/common/final-flush-request-tracker.js +0 -6
- package/packages/dd-trace/src/exporters/common/proxy.js +3 -0
- package/packages/dd-trace/src/exporters/common/request.js +1 -0
- package/packages/dd-trace/src/exporters/common/url.js +0 -2
- package/packages/dd-trace/src/exporters/common/writer.js +0 -2
- package/packages/dd-trace/src/id.js +0 -11
- package/packages/dd-trace/src/llmobs/audio-codec.js +192 -0
- package/packages/dd-trace/src/llmobs/audio-utils.js +121 -0
- package/packages/dd-trace/src/llmobs/constants/audio.js +35 -0
- package/packages/dd-trace/src/llmobs/constants/prompts.js +14 -0
- package/packages/dd-trace/src/llmobs/constants/tags.js +17 -0
- package/packages/dd-trace/src/llmobs/eval-metric.js +0 -6
- package/packages/dd-trace/src/llmobs/experiments/dataset.js +0 -4
- package/packages/dd-trace/src/llmobs/experiments/experiment.js +0 -3
- package/packages/dd-trace/src/llmobs/experiments/index.js +7 -6
- package/packages/dd-trace/src/llmobs/experiments/util.js +1 -11
- package/packages/dd-trace/src/llmobs/index.js +1 -3
- package/packages/dd-trace/src/llmobs/noop.js +10 -0
- package/packages/dd-trace/src/llmobs/plugins/ai/util.js +0 -4
- package/packages/dd-trace/src/llmobs/plugins/anthropic/util.js +0 -1
- package/packages/dd-trace/src/llmobs/plugins/genai/util.js +0 -4
- package/packages/dd-trace/src/llmobs/plugins/modelcontextprotocol-sdk/utils.js +0 -2
- package/packages/dd-trace/src/llmobs/plugins/openai/constants.js +0 -2
- package/packages/dd-trace/src/llmobs/plugins/openai/index.js +4 -6
- package/packages/dd-trace/src/llmobs/plugins/openai/realtime.js +285 -0
- package/packages/dd-trace/src/llmobs/plugins/openai/utils.js +16 -3
- package/packages/dd-trace/src/llmobs/prompts/cache.js +272 -0
- package/packages/dd-trace/src/llmobs/prompts/manager.js +639 -0
- package/packages/dd-trace/src/llmobs/prompts/noop.js +29 -0
- package/packages/dd-trace/src/llmobs/prompts/prompt.js +92 -0
- package/packages/dd-trace/src/llmobs/sdk.js +21 -6
- package/packages/dd-trace/src/llmobs/span_processor.js +81 -2
- package/packages/dd-trace/src/llmobs/tagger.js +30 -7
- package/packages/dd-trace/src/llmobs/telemetry.js +36 -4
- package/packages/dd-trace/src/llmobs/util.js +0 -34
- package/packages/dd-trace/src/llmobs/writers/base.js +0 -1
- package/packages/dd-trace/src/llmobs/writers/util.js +1 -2
- package/packages/dd-trace/src/log/channels.js +3 -0
- package/packages/dd-trace/src/log/index.js +23 -5
- package/packages/dd-trace/src/log-submission/log-submission-plugin.js +74 -6
- package/packages/dd-trace/src/msgpack/chunk.js +0 -1
- package/packages/dd-trace/src/openfeature/agentless_configuration_source.js +0 -12
- package/packages/dd-trace/src/openfeature/encoding.js +0 -2
- package/packages/dd-trace/src/openfeature/eval-metrics-hook.js +0 -1
- package/packages/dd-trace/src/openfeature/index.js +0 -4
- package/packages/dd-trace/src/openfeature/span-enrichment-hook.js +0 -1
- package/packages/dd-trace/src/openfeature/span-enrichment.js +0 -4
- package/packages/dd-trace/src/openfeature/writers/base.js +0 -6
- package/packages/dd-trace/src/openfeature/writers/exposures.js +0 -5
- package/packages/dd-trace/src/openfeature/writers/util.js +0 -4
- package/packages/dd-trace/src/opentelemetry/logs/logger.js +0 -1
- package/packages/dd-trace/src/opentelemetry/logs/logger_provider.js +0 -1
- package/packages/dd-trace/src/opentelemetry/logs/otlp_http_log_exporter.js +0 -1
- package/packages/dd-trace/src/opentelemetry/logs/otlp_transformer.js +0 -2
- package/packages/dd-trace/src/opentelemetry/metrics/index.js +1 -1
- package/packages/dd-trace/src/opentelemetry/metrics/meter_provider.js +4 -4
- package/packages/dd-trace/src/opentelemetry/metrics/otlp_span_stats_transformer.js +0 -1
- package/packages/dd-trace/src/opentelemetry/metrics/otlp_transformer.js +0 -1
- package/packages/dd-trace/src/opentelemetry/metrics/periodic_metric_reader.js +103 -35
- package/packages/dd-trace/src/opentelemetry/metrics/time.js +0 -1
- package/packages/dd-trace/src/opentelemetry/otlp/otlp_http_exporter_base.js +36 -13
- package/packages/dd-trace/src/opentelemetry/otlp/otlp_transformer_base.js +0 -1
- package/packages/dd-trace/src/opentelemetry/span-helpers.js +0 -1
- package/packages/dd-trace/src/opentelemetry/trace/otlp_http_trace_exporter.js +0 -1
- package/packages/dd-trace/src/opentelemetry/trace/otlp_transformer.js +0 -3
- package/packages/dd-trace/src/opentracing/propagation/text_map.js +0 -6
- package/packages/dd-trace/src/opentracing/span_context.js +0 -1
- package/packages/dd-trace/src/otel-thread-ctx.js +38 -11
- package/packages/dd-trace/src/payload-tagging/tagging.js +15 -3
- package/packages/dd-trace/src/plugin_manager.js +9 -3
- package/packages/dd-trace/src/plugins/ci_plugin.js +0 -1
- package/packages/dd-trace/src/plugins/database.js +2 -6
- package/packages/dd-trace/src/plugins/index.js +8 -0
- package/packages/dd-trace/src/plugins/plugin.js +0 -4
- package/packages/dd-trace/src/plugins/tracing.js +1 -1
- package/packages/dd-trace/src/plugins/util/git.js +1 -3
- package/packages/dd-trace/src/plugins/util/http-otel-semantics.js +0 -1
- package/packages/dd-trace/src/plugins/util/llm.js +0 -2
- package/packages/dd-trace/src/plugins/util/status-validator.js +0 -1
- package/packages/dd-trace/src/plugins/util/test.js +25 -21
- package/packages/dd-trace/src/plugins/util/url.js +0 -5
- package/packages/dd-trace/src/priority_sampler.js +0 -6
- package/packages/dd-trace/src/process-tags/index.js +0 -1
- package/packages/dd-trace/src/profiler.js +132 -35
- package/packages/dd-trace/src/profiling/exporters/event_serializer.js +0 -1
- package/packages/dd-trace/src/profiling/profiler.js +101 -41
- package/packages/dd-trace/src/profiling/ssi-heuristics.js +29 -15
- package/packages/dd-trace/src/propagation-hash/index.js +0 -1
- package/packages/dd-trace/src/proxy.js +21 -45
- package/packages/dd-trace/src/random_sampler.js +0 -4
- package/packages/dd-trace/src/rate_limiter.js +0 -4
- package/packages/dd-trace/src/remote_config/capabilities.js +1 -9
- package/packages/dd-trace/src/remote_config/index.js +0 -1
- package/packages/dd-trace/src/runtime_metrics/otlp_runtime_metrics.js +0 -3
- package/packages/dd-trace/src/sampler.js +0 -4
- package/packages/dd-trace/src/sampling_rule.js +0 -7
- package/packages/dd-trace/src/serverless/vercel.js +0 -1
- package/packages/dd-trace/src/serverless.js +0 -1
- package/packages/dd-trace/src/service-naming/index.js +0 -1
- package/packages/dd-trace/src/service-naming/schemas/util.js +0 -1
- package/packages/dd-trace/src/service-naming/schemas/v0/storage.js +7 -0
- package/packages/dd-trace/src/service-naming/schemas/v1/storage.js +5 -0
- package/packages/dd-trace/src/span_processor.js +2 -2
- package/packages/dd-trace/src/span_sampler.js +0 -1
- package/packages/dd-trace/src/standalone/product.js +2 -2
- package/packages/dd-trace/src/standalone/tracesource.js +0 -1
- package/packages/dd-trace/src/startup-log.js +1 -1
- package/packages/dd-trace/src/telemetry/endpoints.js +0 -8
- package/packages/dd-trace/src/telemetry/logs/index.js +16 -5
- package/packages/dd-trace/src/telemetry/logs/log-collector.js +16 -6
- package/packages/dd-trace/src/telemetry/metrics.js +0 -2
- package/packages/dd-trace/src/telemetry/telemetry.js +4 -1
- package/packages/dd-trace/src/util.js +13 -1
- package/vendor/dist/@datadog/openfeature-node-server/index.js +1 -1
- package/packages/dd-trace/src/llmobs/plugins/claude-agent-sdk/utils.js +0 -10
|
@@ -4,15 +4,19 @@ const { readFile } = require('fs')
|
|
|
4
4
|
const { types } = require('util')
|
|
5
5
|
const { join } = require('path')
|
|
6
6
|
const { Worker, MessageChannel, threadId: parentThreadId } = require('worker_threads')
|
|
7
|
+
const dc = require('dc-polyfill')
|
|
7
8
|
const log = require('../log')
|
|
8
9
|
const { fetchAgentInfo } = require('../agent/info')
|
|
10
|
+
const telemetryMetrics = require('../telemetry/metrics')
|
|
9
11
|
const getDebuggerConfig = require('./config')
|
|
10
12
|
const {
|
|
11
13
|
DEBUGGER_DIAGNOSTICS_V1,
|
|
12
14
|
DEBUGGER_INPUT_DIRECT,
|
|
13
15
|
DEBUGGER_INPUT_V2,
|
|
16
|
+
GUARDRAIL_METRICS_FLUSH_INTERVAL_MS,
|
|
14
17
|
INSPECT_SEGMENT_GLOBAL_PROPERTY,
|
|
15
18
|
} = require('./constants')
|
|
19
|
+
const { GuardrailMetrics, TELEMETRY_NAMESPACE } = require('./guardrail-metrics')
|
|
16
20
|
const { installProbeSampler, uninstallProbeSampler } = require('./probe_sampler')
|
|
17
21
|
|
|
18
22
|
/**
|
|
@@ -23,12 +27,20 @@ const { installProbeSampler, uninstallProbeSampler } = require('./probe_sampler'
|
|
|
23
27
|
* @typedef {import('../remote_config')} RemoteConfig
|
|
24
28
|
*/
|
|
25
29
|
|
|
30
|
+
// Published by telemetry right before it sends its final metrics on process exit. The flush interval timer is unref'ed
|
|
31
|
+
// and the worker does not keep the process alive, so without this hook everything counted since the last tick would
|
|
32
|
+
// be lost when the application exits on its own.
|
|
33
|
+
const TELEMETRY_APP_CLOSING_CHANNEL = 'datadog:telemetry:app-closing'
|
|
34
|
+
|
|
26
35
|
let worker = null
|
|
27
36
|
let configChannel = null
|
|
28
37
|
let ackId = 0
|
|
29
38
|
let rcAckCallbacks = null
|
|
30
39
|
let rc = null
|
|
31
40
|
let inputPath = null
|
|
41
|
+
/** @type {GuardrailMetrics | null} */
|
|
42
|
+
let guardrailMetrics = null
|
|
43
|
+
let guardrailMetricsTimer = null
|
|
32
44
|
|
|
33
45
|
// eslint-disable-next-line eslint-rules/eslint-process-env
|
|
34
46
|
const { NODE_OPTIONS, ...env } = process.env
|
|
@@ -43,7 +55,6 @@ module.exports = {
|
|
|
43
55
|
/**
|
|
44
56
|
* Check if the Debugger worker is currently running
|
|
45
57
|
*
|
|
46
|
-
* @returns {boolean} True if the worker is started, false otherwise
|
|
47
58
|
*/
|
|
48
59
|
function isStarted () {
|
|
49
60
|
return worker !== null
|
|
@@ -77,7 +88,13 @@ function start (config, rcInstance) {
|
|
|
77
88
|
debuggerGlobals.utilTypes = types
|
|
78
89
|
debuggerGlobals[INSPECT_SEGMENT_GLOBAL_PROPERTY] = require('./inspect-segment')
|
|
79
90
|
|
|
80
|
-
const
|
|
91
|
+
const guardrailMetricsBuffer = GuardrailMetrics.createBuffer()
|
|
92
|
+
guardrailMetrics = new GuardrailMetrics(guardrailMetricsBuffer)
|
|
93
|
+
guardrailMetricsTimer = setInterval(flushGuardrailMetrics, GUARDRAIL_METRICS_FLUSH_INTERVAL_MS)
|
|
94
|
+
guardrailMetricsTimer.unref?.()
|
|
95
|
+
dc.subscribe(TELEMETRY_APP_CLOSING_CHANNEL, flushGuardrailMetrics)
|
|
96
|
+
|
|
97
|
+
const probeSamplerBuffer = installProbeSampler(guardrailMetrics)
|
|
81
98
|
|
|
82
99
|
readProbeFile(config.dynamicInstrumentation.probeFile, (probes) => {
|
|
83
100
|
const action = 'apply'
|
|
@@ -125,6 +142,7 @@ function start (config, rcInstance) {
|
|
|
125
142
|
logPort: logChannel.port1,
|
|
126
143
|
configPort: configChannel.port1,
|
|
127
144
|
probeSamplerBuffer,
|
|
145
|
+
guardrailMetricsBuffer,
|
|
128
146
|
},
|
|
129
147
|
transferList: [probeChannel.port1, logChannel.port1, configChannel.port1],
|
|
130
148
|
}
|
|
@@ -137,6 +155,11 @@ function start (config, rcInstance) {
|
|
|
137
155
|
)
|
|
138
156
|
})
|
|
139
157
|
|
|
158
|
+
const threadPausedMetric = telemetryMetrics.manager.namespace(TELEMETRY_NAMESPACE)
|
|
159
|
+
.distribution('execution.pause.duration')
|
|
160
|
+
worker.on('message', (/** @type {{ type: string, durationMs: number }} */ { type, durationMs }) => {
|
|
161
|
+
if (type === 'thread-paused') threadPausedMetric.track(durationMs)
|
|
162
|
+
})
|
|
140
163
|
worker.on('error', (err) => log.error('[debugger] worker thread error', err))
|
|
141
164
|
worker.on('messageerror', (err) => log.error('[debugger] received "messageerror" from worker', err))
|
|
142
165
|
|
|
@@ -211,6 +234,20 @@ function cleanup (error) {
|
|
|
211
234
|
configChannel = null
|
|
212
235
|
inputPath = null
|
|
213
236
|
|
|
237
|
+
if (guardrailMetricsTimer !== null) {
|
|
238
|
+
clearInterval(guardrailMetricsTimer)
|
|
239
|
+
guardrailMetricsTimer = null
|
|
240
|
+
}
|
|
241
|
+
if (guardrailMetrics !== null) {
|
|
242
|
+
dc.unsubscribe(TELEMETRY_APP_CLOSING_CHANNEL, flushGuardrailMetrics)
|
|
243
|
+
// Report what the worker counted up until it was stopped. Known limitation: `Worker#terminate()` interrupts the
|
|
244
|
+
// worker asynchronously, so anything it counts between this drain and its actual termination is lost. That only
|
|
245
|
+
// concerns events still sitting in the worker's upload buffer, which die with the worker anyway, so it isn't worth
|
|
246
|
+
// deferring the drain until the worker has exited.
|
|
247
|
+
flushGuardrailMetrics()
|
|
248
|
+
guardrailMetrics = null
|
|
249
|
+
}
|
|
250
|
+
|
|
214
251
|
// Call any pending ack callbacks
|
|
215
252
|
// Pass error for unexpected exits, or undefined for graceful shutdown
|
|
216
253
|
if (rcAckCallbacks) {
|
|
@@ -223,6 +260,17 @@ function cleanup (error) {
|
|
|
223
260
|
}
|
|
224
261
|
}
|
|
225
262
|
|
|
263
|
+
/**
|
|
264
|
+
* Convert the guardrail counters accumulated by the probe sampler and the worker into telemetry metrics.
|
|
265
|
+
*/
|
|
266
|
+
function flushGuardrailMetrics () {
|
|
267
|
+
if (guardrailMetrics === null) return
|
|
268
|
+
const namespace = telemetryMetrics.manager.namespace(TELEMETRY_NAMESPACE)
|
|
269
|
+
guardrailMetrics.drain((metric, tags, count) => {
|
|
270
|
+
namespace.count(metric, tags).inc(count)
|
|
271
|
+
})
|
|
272
|
+
}
|
|
273
|
+
|
|
226
274
|
/**
|
|
227
275
|
* Detect which debugger endpoint is available on the agent
|
|
228
276
|
*
|
|
@@ -34,7 +34,6 @@ module.exports = inspectSegment
|
|
|
34
34
|
* truncates objects before inspecting them.
|
|
35
35
|
*
|
|
36
36
|
* @param {unknown} value
|
|
37
|
-
* @returns {string}
|
|
38
37
|
*/
|
|
39
38
|
function inspectSegment (value) {
|
|
40
39
|
if (value === null || (typeof value !== 'object' && typeof value !== 'function')) {
|
|
@@ -99,7 +98,6 @@ function inspectSegment (value) {
|
|
|
99
98
|
*
|
|
100
99
|
* @param {Collection} value
|
|
101
100
|
* @param {boolean} isMap
|
|
102
|
-
* @returns {string}
|
|
103
101
|
*/
|
|
104
102
|
function inspectCollection (value, isMap) {
|
|
105
103
|
if (NODE_MAJOR !== 18) return inspect(value, segmentInspectOptions)
|
|
@@ -137,7 +135,6 @@ function inspectCollection (value, isMap) {
|
|
|
137
135
|
* Determine whether inspecting a value could invoke a proxy trap or toStringTag getter.
|
|
138
136
|
*
|
|
139
137
|
* @param {unknown} value
|
|
140
|
-
* @returns {boolean}
|
|
141
138
|
*/
|
|
142
139
|
function inspectionCanRunUserCode (value) {
|
|
143
140
|
const type = typeof value
|
|
@@ -1,7 +1,13 @@
|
|
|
1
1
|
'use strict'
|
|
2
2
|
|
|
3
|
+
const { types } = require('node:util')
|
|
4
|
+
|
|
3
5
|
const { MAX_SNAPSHOTS_PER_SECOND_GLOBALLY } = require('./devtools_client/defaults')
|
|
6
|
+
const { MAX_MESSAGE_LENGTH } = require('./constants')
|
|
7
|
+
const { EVENT_TYPE, SKIPPED_REASON } = require('./guardrail-metrics')
|
|
4
8
|
const {
|
|
9
|
+
CONDITION_ERROR_FLAG,
|
|
10
|
+
CONDITION_ERROR_THROTTLE_NS,
|
|
5
11
|
DD_TRACE_SYMBOL,
|
|
6
12
|
MAX_SAMPLED_PROBES_PER_PAUSE,
|
|
7
13
|
PROBE_SAMPLER_SYMBOL,
|
|
@@ -22,12 +28,20 @@ module.exports = {
|
|
|
22
28
|
/**
|
|
23
29
|
* Install the runtime sampler in the debuggee context.
|
|
24
30
|
*
|
|
31
|
+
* @param {import('./guardrail-metrics').GuardrailMetrics} guardrailMetrics - Counters for skipped probe hits.
|
|
25
32
|
* @returns {SharedArrayBuffer} The shared sampler buffer to pass to the debugger worker.
|
|
26
33
|
*/
|
|
27
|
-
function installProbeSampler () {
|
|
34
|
+
function installProbeSampler (guardrailMetrics) {
|
|
28
35
|
const buffer = createProbeSamplerBuffer()
|
|
29
36
|
|
|
30
37
|
const lastCaptureNsByProbeId = new Map()
|
|
38
|
+
/**
|
|
39
|
+
* Probes whose condition recently failed to evaluate, keyed by probe id. The error is kept until the worker picks it
|
|
40
|
+
* up for the error result.
|
|
41
|
+
*
|
|
42
|
+
* @type {Map<string, { throttledUntilNs: bigint, error: string | undefined }>}
|
|
43
|
+
*/
|
|
44
|
+
const conditionErrorByProbeId = new Map()
|
|
31
45
|
const sampledProbeIndexes = new Int32Array(buffer)
|
|
32
46
|
Atomics.store(sampledProbeIndexes, SAMPLED_PROBE_COUNT_INDEX, 0)
|
|
33
47
|
Atomics.store(sampledProbeIndexes, SAMPLED_PROBE_OVERFLOW_INDEX, 0)
|
|
@@ -44,27 +58,29 @@ function installProbeSampler () {
|
|
|
44
58
|
* @param {string} probeId - The probe id.
|
|
45
59
|
* @param {bigint} nsBetweenSampling - Minimum nanoseconds between samples for this probe.
|
|
46
60
|
* @param {boolean} isSnapshotProducingProbe - Whether this probe counts toward the global snapshot sample limit.
|
|
47
|
-
* @returns {boolean} Whether this probe should make the breakpoint condition pause.
|
|
48
61
|
*/
|
|
49
62
|
makeSampleDecision (probeIndex, probeId, nsBetweenSampling, isSnapshotProducingProbe) {
|
|
50
63
|
const now = process.hrtime.bigint()
|
|
51
64
|
const lastCaptureNs = lastCaptureNsByProbeId.get(probeId)
|
|
52
|
-
if (lastCaptureNs !== undefined && now - lastCaptureNs < nsBetweenSampling)
|
|
65
|
+
if (lastCaptureNs !== undefined && now - lastCaptureNs < nsBetweenSampling) {
|
|
66
|
+
guardrailMetrics.eventSkipped(
|
|
67
|
+
SKIPPED_REASON.RATE_LIMIT_PROBE,
|
|
68
|
+
isSnapshotProducingProbe === true ? EVENT_TYPE.SNAPSHOT : EVENT_TYPE.LOG
|
|
69
|
+
)
|
|
70
|
+
return false
|
|
71
|
+
}
|
|
53
72
|
|
|
54
73
|
let shouldResetGlobalSnapshotRateWindow = false
|
|
55
74
|
if (isSnapshotProducingProbe === true) {
|
|
56
75
|
if (now - globalSnapshotSamplingRateWindowStart > oneSecondNs) {
|
|
57
76
|
shouldResetGlobalSnapshotRateWindow = true
|
|
58
77
|
} else if (snapshotsSampledWithinTheLastSecond >= MAX_SNAPSHOTS_PER_SECOND_GLOBALLY) {
|
|
78
|
+
guardrailMetrics.eventSkipped(SKIPPED_REASON.RATE_LIMIT_GLOBAL, EVENT_TYPE.SNAPSHOT)
|
|
59
79
|
return false
|
|
60
80
|
}
|
|
61
81
|
}
|
|
62
82
|
|
|
63
|
-
|
|
64
|
-
if (sampledProbeCount >= MAX_SAMPLED_PROBES_PER_PAUSE) {
|
|
65
|
-
Atomics.store(sampledProbeIndexes, SAMPLED_PROBE_OVERFLOW_INDEX, 1)
|
|
66
|
-
return false
|
|
67
|
-
}
|
|
83
|
+
if (!storeSampledProbeIndex(probeIndex)) return false
|
|
68
84
|
|
|
69
85
|
if (isSnapshotProducingProbe === true) {
|
|
70
86
|
if (shouldResetGlobalSnapshotRateWindow === true) {
|
|
@@ -76,10 +92,56 @@ function installProbeSampler () {
|
|
|
76
92
|
}
|
|
77
93
|
|
|
78
94
|
lastCaptureNsByProbeId.set(probeId, now)
|
|
79
|
-
Atomics.store(sampledProbeIndexes, SAMPLED_PROBE_INDEXES_START + sampledProbeCount, probeIndex)
|
|
80
95
|
return true
|
|
81
96
|
},
|
|
82
97
|
|
|
98
|
+
/**
|
|
99
|
+
* Decide if a probe's condition should be evaluated, or skipped because a recent evaluation error throttled it.
|
|
100
|
+
*
|
|
101
|
+
* @param {string} probeId - The probe id.
|
|
102
|
+
*/
|
|
103
|
+
shouldEvaluateCondition (probeId) {
|
|
104
|
+
const state = conditionErrorByProbeId.get(probeId)
|
|
105
|
+
if (state === undefined) return true
|
|
106
|
+
if (process.hrtime.bigint() < state.throttledUntilNs) return false
|
|
107
|
+
conditionErrorByProbeId.delete(probeId)
|
|
108
|
+
return true
|
|
109
|
+
},
|
|
110
|
+
|
|
111
|
+
/**
|
|
112
|
+
* Record that a probe's condition threw, throttle the probe, and request a pause if the error can be reported.
|
|
113
|
+
*
|
|
114
|
+
* Error results bypass the per-probe and global rate limits: they are rate limited by the throttle instead, which
|
|
115
|
+
* allows one error result per probe per window. If the shared buffer is full, the error is dropped but the throttle
|
|
116
|
+
* is retained.
|
|
117
|
+
*
|
|
118
|
+
* @param {number} probeIndex - The worker-side probe sampling index.
|
|
119
|
+
* @param {string} probeId - The probe id.
|
|
120
|
+
* @param {unknown} error - The value thrown by the condition.
|
|
121
|
+
*/
|
|
122
|
+
conditionError (probeIndex, probeId, error) {
|
|
123
|
+
const stored = storeSampledProbeIndex(probeIndex | CONDITION_ERROR_FLAG)
|
|
124
|
+
conditionErrorByProbeId.set(probeId, {
|
|
125
|
+
throttledUntilNs: process.hrtime.bigint() + CONDITION_ERROR_THROTTLE_NS,
|
|
126
|
+
error: stored ? describeError(error) : undefined,
|
|
127
|
+
})
|
|
128
|
+
return stored
|
|
129
|
+
},
|
|
130
|
+
|
|
131
|
+
/**
|
|
132
|
+
* Hand over the recorded condition error for a probe to the worker. Called by the worker on the paused thread.
|
|
133
|
+
*
|
|
134
|
+
* @param {string} probeId - The probe id.
|
|
135
|
+
* @returns {string | undefined} The error description, if any.
|
|
136
|
+
*/
|
|
137
|
+
takeConditionError (probeId) {
|
|
138
|
+
const state = conditionErrorByProbeId.get(probeId)
|
|
139
|
+
if (state === undefined) return
|
|
140
|
+
const { error } = state
|
|
141
|
+
state.error = undefined
|
|
142
|
+
return error
|
|
143
|
+
},
|
|
144
|
+
|
|
83
145
|
/**
|
|
84
146
|
* Remove cached sampling state for a probe.
|
|
85
147
|
*
|
|
@@ -87,9 +149,25 @@ function installProbeSampler () {
|
|
|
87
149
|
*/
|
|
88
150
|
remove (probeId) {
|
|
89
151
|
lastCaptureNsByProbeId.delete(probeId)
|
|
152
|
+
conditionErrorByProbeId.delete(probeId)
|
|
90
153
|
},
|
|
91
154
|
}
|
|
92
155
|
|
|
156
|
+
/**
|
|
157
|
+
* Hand a sampled probe index over to the worker for the upcoming pause.
|
|
158
|
+
*
|
|
159
|
+
* @param {number} value - The probe sampling index, possibly with flags set.
|
|
160
|
+
*/
|
|
161
|
+
function storeSampledProbeIndex (value) {
|
|
162
|
+
const sampledProbeCount = Atomics.add(sampledProbeIndexes, SAMPLED_PROBE_COUNT_INDEX, 1)
|
|
163
|
+
if (sampledProbeCount >= MAX_SAMPLED_PROBES_PER_PAUSE) {
|
|
164
|
+
Atomics.store(sampledProbeIndexes, SAMPLED_PROBE_OVERFLOW_INDEX, 1)
|
|
165
|
+
return false
|
|
166
|
+
}
|
|
167
|
+
Atomics.store(sampledProbeIndexes, SAMPLED_PROBE_INDEXES_START + sampledProbeCount, value)
|
|
168
|
+
return true
|
|
169
|
+
}
|
|
170
|
+
|
|
93
171
|
return buffer
|
|
94
172
|
}
|
|
95
173
|
|
|
@@ -100,6 +178,52 @@ function uninstallProbeSampler () {
|
|
|
100
178
|
delete ddTraceGlobal[Symbol.for(PROBE_SAMPLER_SYMBOL)]
|
|
101
179
|
}
|
|
102
180
|
|
|
181
|
+
/**
|
|
182
|
+
* Describe a value thrown by a probe condition without invoking user code. Conditions can throw anything, including
|
|
183
|
+
* errors with accessors and proxies whose traps have side effects.
|
|
184
|
+
*
|
|
185
|
+
* @param {unknown} error - The thrown value.
|
|
186
|
+
*/
|
|
187
|
+
function describeError (error) {
|
|
188
|
+
if (typeof error === 'string') return truncateErrorDescription(error)
|
|
189
|
+
if (error === null || (typeof error !== 'object' && typeof error !== 'function')) {
|
|
190
|
+
return 'Unknown evaluation error'
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
const name = getErrorStringProperty(error, 'name')
|
|
194
|
+
const message = getErrorStringProperty(error, 'message')
|
|
195
|
+
if (name === undefined) return truncateErrorDescription(message ?? 'Unknown evaluation error')
|
|
196
|
+
if (message === undefined) return truncateErrorDescription(name)
|
|
197
|
+
|
|
198
|
+
return truncateErrorDescription(`${name}: ${message}`)
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
/**
|
|
202
|
+
* Bound an error description before retaining or transferring it.
|
|
203
|
+
*
|
|
204
|
+
* @param {string} description - The description to bound.
|
|
205
|
+
*/
|
|
206
|
+
function truncateErrorDescription (description) {
|
|
207
|
+
return description.length > MAX_MESSAGE_LENGTH
|
|
208
|
+
? `${description.slice(0, MAX_MESSAGE_LENGTH)}…`
|
|
209
|
+
: description
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
/**
|
|
213
|
+
* Read a string-valued error property without invoking accessors or proxy traps.
|
|
214
|
+
*
|
|
215
|
+
* @param {object} error - The thrown object to inspect.
|
|
216
|
+
* @param {'name' | 'message'} property - The property to find.
|
|
217
|
+
*/
|
|
218
|
+
function getErrorStringProperty (error, property) {
|
|
219
|
+
while (error !== null) {
|
|
220
|
+
if (types.isProxy(error)) return
|
|
221
|
+
const descriptor = Object.getOwnPropertyDescriptor(error, property)
|
|
222
|
+
if (descriptor !== undefined) return typeof descriptor.value === 'string' ? descriptor.value : undefined
|
|
223
|
+
error = Object.getPrototypeOf(error)
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
|
|
103
227
|
/**
|
|
104
228
|
* Create the shared buffer used to hand sampled probe indexes from breakpoint conditions to the debugger worker.
|
|
105
229
|
*
|
|
@@ -3,13 +3,43 @@
|
|
|
3
3
|
const DD_TRACE_SYMBOL = 'dd-trace'
|
|
4
4
|
const PROBE_SAMPLER_SYMBOL = 'dd-trace.debugger.probeSampler'
|
|
5
5
|
|
|
6
|
-
// Shared sampler contract used by the main debugger bootstrap and the devtools worker.
|
|
6
|
+
// Shared sampler contract used by the main debugger bootstrap and the devtools worker. The debuggee hands sampled
|
|
7
|
+
// probes to the worker through a shared Int32Array, drained by the worker on every pause:
|
|
8
|
+
//
|
|
9
|
+
// +----------+----------+----------+----------+- - - -+------------+
|
|
10
|
+
// slot | 0 | 1 | 2 | 3 | | 2+MAX-1 |
|
|
11
|
+
// holds | count | overflow | value | value | ... | value |
|
|
12
|
+
// +----------+----------+----------+----------+- - - -+------------+
|
|
13
|
+
// ^COUNT ^OVERFLOW ^INDEXES_START
|
|
7
14
|
const MAX_SAMPLED_PROBES_PER_PAUSE = 256
|
|
8
15
|
const SAMPLED_PROBE_COUNT_INDEX = 0
|
|
9
16
|
const SAMPLED_PROBE_OVERFLOW_INDEX = 1
|
|
10
17
|
const SAMPLED_PROBE_INDEXES_START = 2
|
|
11
18
|
|
|
19
|
+
// Each value above is a probe sampling index, with this flag set in bit 30 when the pause is for reporting a
|
|
20
|
+
// condition evaluation error instead of a probe result. Bit 31 stays unused because the array is signed:
|
|
21
|
+
//
|
|
22
|
+
// +--------+------------+--------------------------------------------+
|
|
23
|
+
// bit | 31 | 30 | 29..0 |
|
|
24
|
+
// means | unused | CONDITION_ | samplingIndex |
|
|
25
|
+
// | (sign) | ERROR_FLAG | |
|
|
26
|
+
// +--------+------------+--------------------------------------------+
|
|
27
|
+
//
|
|
28
|
+
// 0x0000_0007 probe #7 matched -> worker captures as usual
|
|
29
|
+
// 0x4000_0007 probe #7's condition threw -> worker takes the recorded error, captures nothing
|
|
30
|
+
//
|
|
31
|
+
// write: probeIndex | CONDITION_ERROR_FLAG
|
|
32
|
+
// read: value & ~CONDITION_ERROR_FLAG -> the sampling index
|
|
33
|
+
// value & CONDITION_ERROR_FLAG -> non-zero when the condition threw
|
|
34
|
+
const CONDITION_ERROR_FLAG = 1 << 30
|
|
35
|
+
|
|
36
|
+
// A probe whose condition failed to evaluate is not evaluated again for this long. One error result is reported per
|
|
37
|
+
// window, so a probe with a broken condition stays visible without repeatedly paying for the failing evaluation.
|
|
38
|
+
const CONDITION_ERROR_THROTTLE_NS = 5n * 60n * 1_000_000_000n // 5 minutes
|
|
39
|
+
|
|
12
40
|
module.exports = {
|
|
41
|
+
CONDITION_ERROR_FLAG,
|
|
42
|
+
CONDITION_ERROR_THROTTLE_NS,
|
|
13
43
|
DD_TRACE_SYMBOL,
|
|
14
44
|
MAX_SAMPLED_PROBES_PER_PAUSE,
|
|
15
45
|
PROBE_SAMPLER_SYMBOL,
|
|
@@ -207,7 +207,6 @@ class DogStatsDClient {
|
|
|
207
207
|
/**
|
|
208
208
|
* @param {boolean|(() => void)} [forceTelemetry] - Whether to ignore the telemetry interval, or completion callback
|
|
209
209
|
* @param {() => void} [done] - Called after serverless deliveries complete
|
|
210
|
-
* @returns {void}
|
|
211
210
|
*/
|
|
212
211
|
flush (forceTelemetry = false, done) {
|
|
213
212
|
if (typeof forceTelemetry === 'function') {
|
|
@@ -238,7 +237,6 @@ class DogStatsDClient {
|
|
|
238
237
|
/**
|
|
239
238
|
* @param {boolean} force - Whether to ignore the telemetry interval
|
|
240
239
|
* @param {((send: (done?: () => void) => void) => void)} [track] - Tracks a non-serverless delivery
|
|
241
|
-
* @returns {void}
|
|
242
240
|
*/
|
|
243
241
|
#flushTelemetry (force, track) {
|
|
244
242
|
const telemetry = this.telemetry
|
|
@@ -291,7 +289,6 @@ class DogStatsDClient {
|
|
|
291
289
|
* @param {DogStatsDBufferState} state - Payload state to flush
|
|
292
290
|
* @param {boolean} recordTelemetry - Whether to record the transport outcome
|
|
293
291
|
* @param {((send: (done?: () => void) => void) => void)} [track] - Tracks a non-serverless delivery
|
|
294
|
-
* @returns {void}
|
|
295
292
|
*/
|
|
296
293
|
#flush (state, recordTelemetry, track) {
|
|
297
294
|
const queue = this._enqueue(state)
|
|
@@ -314,7 +311,6 @@ class DogStatsDClient {
|
|
|
314
311
|
|
|
315
312
|
/**
|
|
316
313
|
* @param {number} bytes - Number of bytes sent
|
|
317
|
-
* @returns {void}
|
|
318
314
|
*/
|
|
319
315
|
#recordSent (bytes) {
|
|
320
316
|
const telemetry = this.telemetry
|
|
@@ -326,7 +322,6 @@ class DogStatsDClient {
|
|
|
326
322
|
/**
|
|
327
323
|
* @param {number} bytes - Number of bytes dropped
|
|
328
324
|
* @param {number} [packets] - Number of packets dropped
|
|
329
|
-
* @returns {void}
|
|
330
325
|
*/
|
|
331
326
|
#recordDropped (bytes, packets = 1) {
|
|
332
327
|
const telemetry = this.telemetry
|
|
@@ -341,7 +336,6 @@ class DogStatsDClient {
|
|
|
341
336
|
* @param {Buffer[]} queue - The metrics to send
|
|
342
337
|
* @param {boolean} recordTelemetry - Whether to record the transport outcome
|
|
343
338
|
* @param {() => void} [done] - Called after delivery completes
|
|
344
|
-
* @returns {void}
|
|
345
339
|
* @memberof DogStatsDClient
|
|
346
340
|
*/
|
|
347
341
|
_sendHttp (queue, recordTelemetry, done) {
|
|
@@ -375,7 +369,6 @@ class DogStatsDClient {
|
|
|
375
369
|
* @param {Buffer[]} queue - The metrics to send
|
|
376
370
|
* @param {boolean} recordTelemetry - Whether to record the transport outcome
|
|
377
371
|
* @param {() => void} [done] - Called after delivery completes
|
|
378
|
-
* @returns {void}
|
|
379
372
|
* @memberof DogStatsDClient
|
|
380
373
|
*/
|
|
381
374
|
_sendUdp (queue, recordTelemetry, done) {
|
|
@@ -411,7 +404,6 @@ class DogStatsDClient {
|
|
|
411
404
|
* @param {number} family - The family of the address
|
|
412
405
|
* @param {boolean} recordTelemetry - Whether to record the transport outcome
|
|
413
406
|
* @param {() => void} [done] - Called after every packet completes
|
|
414
|
-
* @returns {void}
|
|
415
407
|
* @memberof DogStatsDClient
|
|
416
408
|
*/
|
|
417
409
|
_sendUdpFromQueue (queue, address, family, recordTelemetry, done) {
|
|
@@ -457,7 +449,6 @@ class DogStatsDClient {
|
|
|
457
449
|
* @param {string[]} tags - The metric tags
|
|
458
450
|
* @param {string} [tagsPrefix] - Serialized global tags
|
|
459
451
|
* @param {DogStatsDBufferState} [state] - Payload state receiving the metric
|
|
460
|
-
* @returns {void}
|
|
461
452
|
* @memberof DogStatsDClient
|
|
462
453
|
*/
|
|
463
454
|
_add (stat, value, type, tags, tagsPrefix = this.#tagsPrefix, state = this.#metrics) {
|
|
@@ -482,7 +473,6 @@ class DogStatsDClient {
|
|
|
482
473
|
* @param {string} stat - Telemetry metric name
|
|
483
474
|
* @param {number} value - Telemetry metric value
|
|
484
475
|
* @param {string} [typeLabel] - Submitted or aggregated metric type
|
|
485
|
-
* @returns {void}
|
|
486
476
|
*/
|
|
487
477
|
#addTelemetry (stat, value, typeLabel) {
|
|
488
478
|
const tags = typeLabel === undefined ? undefined : [`metrics_type:${typeLabel}`]
|
|
@@ -496,7 +486,6 @@ class DogStatsDClient {
|
|
|
496
486
|
*
|
|
497
487
|
* @param {string} message - The message to write
|
|
498
488
|
* @param {DogStatsDBufferState} [state] - Payload state receiving the message
|
|
499
|
-
* @returns {void}
|
|
500
489
|
* @memberof DogStatsDClient
|
|
501
490
|
*/
|
|
502
491
|
_write (message, state = this.#metrics) {
|
|
@@ -605,7 +594,6 @@ class MetricsAggregationClient {
|
|
|
605
594
|
/**
|
|
606
595
|
* @param {boolean|(() => void)} [forceTelemetry] - Whether to ignore the telemetry interval, or completion callback
|
|
607
596
|
* @param {() => void} [done] - Called after serverless deliveries complete
|
|
608
|
-
* @returns {void}
|
|
609
597
|
*/
|
|
610
598
|
flush (forceTelemetry = false, done) {
|
|
611
599
|
if (typeof forceTelemetry === 'function') {
|
|
@@ -680,9 +668,6 @@ class MetricsAggregationClient {
|
|
|
680
668
|
this.count(name, -count, tags)
|
|
681
669
|
}
|
|
682
670
|
|
|
683
|
-
/**
|
|
684
|
-
* @returns {number} Number of gauge contexts flushed
|
|
685
|
-
*/
|
|
686
671
|
_captureGauges () {
|
|
687
672
|
let metrics = 0
|
|
688
673
|
const contexts = this._captureTree(this._gauges, (node, name, tags) => {
|
|
@@ -696,9 +681,6 @@ class MetricsAggregationClient {
|
|
|
696
681
|
return contexts
|
|
697
682
|
}
|
|
698
683
|
|
|
699
|
-
/**
|
|
700
|
-
* @returns {number} Number of counter contexts flushed
|
|
701
|
-
*/
|
|
702
684
|
_captureCounters () {
|
|
703
685
|
let metrics = 0
|
|
704
686
|
const contexts = this._captureTree(this._counters, (node, name, tags) => {
|
|
@@ -712,9 +694,6 @@ class MetricsAggregationClient {
|
|
|
712
694
|
return contexts
|
|
713
695
|
}
|
|
714
696
|
|
|
715
|
-
/**
|
|
716
|
-
* @returns {number} Number of histogram contexts flushed
|
|
717
|
-
*/
|
|
718
697
|
_captureHistograms () {
|
|
719
698
|
let metrics = 0
|
|
720
699
|
const contexts = this._captureTree(this._histograms, (node, name, tags) => {
|
|
@@ -740,7 +719,6 @@ class MetricsAggregationClient {
|
|
|
740
719
|
/**
|
|
741
720
|
* @param {Map<string, MetricNode>} tree - Metric context tree
|
|
742
721
|
* @param {CaptureMetric} fn - Called for every context with submissions
|
|
743
|
-
* @returns {number} Number of contexts with submissions
|
|
744
722
|
*/
|
|
745
723
|
_captureTree (tree, fn) {
|
|
746
724
|
let contexts = 0
|
|
@@ -757,7 +735,6 @@ class MetricsAggregationClient {
|
|
|
757
735
|
* @param {string} name - Metric name
|
|
758
736
|
* @param {string[]} tags - Current metric tags
|
|
759
737
|
* @param {CaptureMetric} fn - Called for every context with submissions
|
|
760
|
-
* @returns {number} Number of contexts with submissions
|
|
761
738
|
*/
|
|
762
739
|
_captureNode (node, name, tags, fn) {
|
|
763
740
|
let contexts = 0
|
|
@@ -74,13 +74,11 @@ class CrossPayloadAgentEncoder extends AgentEncoder {
|
|
|
74
74
|
return super.makePayload()
|
|
75
75
|
}
|
|
76
76
|
|
|
77
|
-
/** @returns {void} */
|
|
78
77
|
reset () {
|
|
79
78
|
this.#prepareReset()
|
|
80
79
|
super.reset()
|
|
81
80
|
}
|
|
82
81
|
|
|
83
|
-
/** @returns {void} */
|
|
84
82
|
#prepareReset () {
|
|
85
83
|
const crossPayloadState = this.#crossPayloadState
|
|
86
84
|
if (crossPayloadState !== undefined && !prepareCrossPayloadReset(crossPayloadState)) {
|
|
@@ -129,7 +127,6 @@ function markPayloadString (crossPayloadState, value) {
|
|
|
129
127
|
|
|
130
128
|
/**
|
|
131
129
|
* @param {ReturnType<typeof createCrossPayloadState>} crossPayloadState
|
|
132
|
-
* @returns {boolean}
|
|
133
130
|
*/
|
|
134
131
|
function prepareCrossPayloadReset (crossPayloadState) {
|
|
135
132
|
const learning = crossPayloadState.learningPayloadCount < CROSS_PAYLOAD_LEARNING_PAYLOAD_LIMIT
|
|
@@ -136,7 +136,6 @@ function formatSpanWithLegacyEvents (span) {
|
|
|
136
136
|
* replacer hooks).
|
|
137
137
|
*
|
|
138
138
|
* @param {Array<{ name: unknown, startTime: number, attributes?: object }>} spanEvents
|
|
139
|
-
* @returns {string}
|
|
140
139
|
*/
|
|
141
140
|
function stringifySpanEvents (spanEvents) {
|
|
142
141
|
let result = '['
|
|
@@ -200,7 +199,6 @@ function stringifyAttributeValue (value) {
|
|
|
200
199
|
* conversion (which is what `JSON.stringify` calls internally).
|
|
201
200
|
*
|
|
202
201
|
* @param {number} value
|
|
203
|
-
* @returns {string}
|
|
204
202
|
*/
|
|
205
203
|
function jsonNumber (value) {
|
|
206
204
|
if (Number.isFinite(value)) return String(value)
|
|
@@ -215,7 +213,6 @@ function jsonNumber (value) {
|
|
|
215
213
|
* lone surrogates, etc.).
|
|
216
214
|
*
|
|
217
215
|
* @param {string} value
|
|
218
|
-
* @returns {string}
|
|
219
216
|
*/
|
|
220
217
|
function escapeJsonString (value) {
|
|
221
218
|
for (let index = 0; index < value.length; index++) {
|
|
@@ -649,7 +646,6 @@ class AgentEncoder {
|
|
|
649
646
|
* @param {number} offset
|
|
650
647
|
* @param {Buffer} keyPrefix Precomputed `[key, 0xCF]`.
|
|
651
648
|
* @param {{ toBuffer: () => Uint8Array | number[] }} identifier
|
|
652
|
-
* @returns {number}
|
|
653
649
|
*/
|
|
654
650
|
#writeIdAt (target, offset, keyPrefix, identifier) {
|
|
655
651
|
target.set(keyPrefix, offset)
|
|
@@ -871,7 +867,6 @@ class AgentEncoder {
|
|
|
871
867
|
* @param {MsgpackChunk} bytes
|
|
872
868
|
* @param {string} key
|
|
873
869
|
* @param {unknown} value
|
|
874
|
-
* @returns {boolean}
|
|
875
870
|
*/
|
|
876
871
|
#emitAttribute (bytes, key, value) {
|
|
877
872
|
if (typeof value === 'string') {
|
|
@@ -911,7 +906,6 @@ class AgentEncoder {
|
|
|
911
906
|
* @param {MsgpackChunk} bytes
|
|
912
907
|
* @param {string} key
|
|
913
908
|
* @param {Array<unknown>} array
|
|
914
|
-
* @returns {boolean}
|
|
915
909
|
*/
|
|
916
910
|
#emitArrayAttribute (bytes, key, array) {
|
|
917
911
|
const sectionStart = bytes.length
|
|
@@ -946,7 +940,6 @@ class AgentEncoder {
|
|
|
946
940
|
* @param {MsgpackChunk} bytes
|
|
947
941
|
* @param {string} key
|
|
948
942
|
* @param {unknown} value
|
|
949
|
-
* @returns {boolean}
|
|
950
943
|
*/
|
|
951
944
|
#emitArrayItem (bytes, key, value) {
|
|
952
945
|
if (typeof value === 'string') {
|
|
@@ -173,7 +173,6 @@ class AgentEncoder extends BaseEncoder {
|
|
|
173
173
|
* @param {Uint8Array} target
|
|
174
174
|
* @param {number} offset
|
|
175
175
|
* @param {number} index
|
|
176
|
-
* @returns {number}
|
|
177
176
|
*/
|
|
178
177
|
#writeIndexAt (target, offset, index) {
|
|
179
178
|
target[offset] = 0xCE
|
|
@@ -192,7 +191,6 @@ class AgentEncoder extends BaseEncoder {
|
|
|
192
191
|
* @param {Uint8Array} target
|
|
193
192
|
* @param {number} offset
|
|
194
193
|
* @param {{ toBuffer: () => Uint8Array | number[] }} identifier
|
|
195
|
-
* @returns {number}
|
|
196
194
|
*/
|
|
197
195
|
#writeIdAt (target, offset, identifier) {
|
|
198
196
|
target[offset] = 0xCF
|
|
@@ -53,7 +53,6 @@ function truncateSpanTestOpt (span) {
|
|
|
53
53
|
* the formatter no longer reshapes events, it hands the raw array through.
|
|
54
54
|
*
|
|
55
55
|
* @param {{ startTime: number }} event
|
|
56
|
-
* @returns {number}
|
|
57
56
|
*/
|
|
58
57
|
function eventTimeNano (event) {
|
|
59
58
|
return Math.round(event.startTime * 1e6)
|
|
@@ -2,8 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
const { fetchAgentInfo } = require('../agent/info')
|
|
4
4
|
const log = require('../log')
|
|
5
|
-
|
|
6
|
-
const TRAILING_SLASHES = /\/+$/
|
|
5
|
+
const { stripTrailingSlashes } = require('./path')
|
|
7
6
|
|
|
8
7
|
/**
|
|
9
8
|
* Receiver discovery contract
|
|
@@ -81,14 +80,14 @@ function selectEVPProxyPath (agentInfo, { supportedPaths, requiredHeaders = [] }
|
|
|
81
80
|
const advertisedPaths = new Set()
|
|
82
81
|
for (const endpoint of agentInfo.endpoints) {
|
|
83
82
|
if (typeof endpoint === 'string') {
|
|
84
|
-
advertisedPaths.add(endpoint
|
|
83
|
+
advertisedPaths.add(stripTrailingSlashes(endpoint))
|
|
85
84
|
}
|
|
86
85
|
}
|
|
87
86
|
|
|
88
87
|
for (const supportedPath of supportedPaths) {
|
|
89
88
|
if (typeof supportedPath !== 'string') continue
|
|
90
89
|
|
|
91
|
-
const normalizedPath = supportedPath
|
|
90
|
+
const normalizedPath = stripTrailingSlashes(supportedPath)
|
|
92
91
|
if (advertisedPaths.has(normalizedPath)) {
|
|
93
92
|
return normalizedPath
|
|
94
93
|
}
|
|
@@ -107,7 +106,6 @@ function selectEVPProxyPath (agentInfo, { supportedPaths, requiredHeaders = [] }
|
|
|
107
106
|
* @param {string[]} [options.requiredHeaders] - Headers that the proxy must forward unchanged to intake. Each
|
|
108
107
|
* header must appear in `evp_proxy_allowed_headers`. Do not include routing headers that the Agent consumes.
|
|
109
108
|
* @param {(error: Error|null, route?: {url: URL, basePath: string}) => void} callback - Result callback
|
|
110
|
-
* @returns {void}
|
|
111
109
|
*/
|
|
112
110
|
function discoverEVPProxy (url, options, callback) {
|
|
113
111
|
fetchAgentInfo(url, (error, agentInfo) => {
|