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
|
@@ -1,7 +1,15 @@
|
|
|
1
1
|
'use strict'
|
|
2
2
|
|
|
3
3
|
const LEADING_SLASHES = /^\/+/
|
|
4
|
-
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* @param {string} value
|
|
7
|
+
*/
|
|
8
|
+
function stripTrailingSlashes (value) {
|
|
9
|
+
let end = value.length
|
|
10
|
+
while (end > 0 && value[end - 1] === '/') end--
|
|
11
|
+
return end === value.length ? value : value.slice(0, end)
|
|
12
|
+
}
|
|
5
13
|
|
|
6
14
|
/**
|
|
7
15
|
* Joins a caller-supplied EVP proxy path and product endpoint.
|
|
@@ -10,13 +18,12 @@ const TRAILING_SLASHES = /\/+$/
|
|
|
10
18
|
*
|
|
11
19
|
* @param {string} basePath - EVP proxy base path
|
|
12
20
|
* @param {string} endpoint - Product intake endpoint
|
|
13
|
-
* @returns {string} Joined request path
|
|
14
21
|
*/
|
|
15
22
|
function joinEVPProxyPath (basePath, endpoint) {
|
|
16
|
-
const normalizedBasePath = basePath
|
|
23
|
+
const normalizedBasePath = stripTrailingSlashes(basePath)
|
|
17
24
|
const normalizedEndpoint = endpoint.replace(LEADING_SLASHES, '')
|
|
18
25
|
|
|
19
26
|
return `${normalizedBasePath}/${normalizedEndpoint}`
|
|
20
27
|
}
|
|
21
28
|
|
|
22
|
-
module.exports = { joinEVPProxyPath }
|
|
29
|
+
module.exports = { joinEVPProxyPath, stripTrailingSlashes }
|
|
@@ -44,7 +44,6 @@ class AgentWriter extends BaseWriter {
|
|
|
44
44
|
* Test Optimization owns its own request lifecycle tracking.
|
|
45
45
|
* @param {(error?: Error) => void} [done]
|
|
46
46
|
* @param {{ deadline?: number }} [options]
|
|
47
|
-
* @returns {void}
|
|
48
47
|
*/
|
|
49
48
|
flushDirect (done, options) {
|
|
50
49
|
if (this.#requestTracker) {
|
|
@@ -25,7 +25,6 @@ const INTAKE_PATH = '/api/v2/spans'
|
|
|
25
25
|
* reattach the TLD, e.g. 'us2.ddog-gov.com' -> 'https://browser-intake-us2-ddog-gov.com'.
|
|
26
26
|
*
|
|
27
27
|
* @param {string} [site] - The Datadog site, e.g. 'us3.datadoghq.com'. Defaults to 'datadoghq.com'.
|
|
28
|
-
* @returns {string} The intake origin, without a path.
|
|
29
28
|
*/
|
|
30
29
|
function computeIntakeUrl (site = 'datadoghq.com') {
|
|
31
30
|
const normalized = site.toLowerCase()
|
|
@@ -12,7 +12,10 @@ const uuidSource =
|
|
|
12
12
|
const containerSource = '[0-9a-f]{64}'
|
|
13
13
|
const taskSource = String.raw`[0-9a-f]{32}-\d+`
|
|
14
14
|
const lineReg = /^(\d+):([^:]*):(.+)$/m
|
|
15
|
-
const entityReg = new RegExp(
|
|
15
|
+
const entityReg = new RegExp(
|
|
16
|
+
String.raw`(?:^|/)[^/\r\n\u2028\u2029]*?(${uuidSource}|${containerSource}|${taskSource})(?:\.scope)?$`,
|
|
17
|
+
'm'
|
|
18
|
+
)
|
|
16
19
|
|
|
17
20
|
let inode = 0
|
|
18
21
|
let cgroup = ''
|
|
@@ -45,7 +45,6 @@ class FinalFlushRequestTracker {
|
|
|
45
45
|
*
|
|
46
46
|
* @param {(error?: Error) => void} [done]
|
|
47
47
|
* @param {{ deadline?: number }} [options]
|
|
48
|
-
* @returns {void}
|
|
49
48
|
*/
|
|
50
49
|
flush (done, options) {
|
|
51
50
|
if (options?.deadline === undefined) {
|
|
@@ -112,7 +111,6 @@ class FinalFlushRequestTracker {
|
|
|
112
111
|
* @param {RequestOptions} options
|
|
113
112
|
* @param {(error: Error|null, result?: string|null, statusCode?: number,
|
|
114
113
|
* headers?: import('node:http').IncomingHttpHeaders) => void} callback
|
|
115
|
-
* @returns {void}
|
|
116
114
|
*/
|
|
117
115
|
send (request, data, options, callback) {
|
|
118
116
|
const controller = new AbortController()
|
|
@@ -141,7 +139,6 @@ class FinalFlushRequestTracker {
|
|
|
141
139
|
|
|
142
140
|
/**
|
|
143
141
|
* @param {PendingRequest} pendingRequest
|
|
144
|
-
* @returns {void}
|
|
145
142
|
*/
|
|
146
143
|
#dropRequest (pendingRequest) {
|
|
147
144
|
this.#pendingRequests.delete(pendingRequest)
|
|
@@ -155,7 +152,6 @@ class FinalFlushRequestTracker {
|
|
|
155
152
|
/**
|
|
156
153
|
* @param {FinalFlush} finalFlush
|
|
157
154
|
* @param {PendingRequest} pendingRequest
|
|
158
|
-
* @returns {void}
|
|
159
155
|
*/
|
|
160
156
|
#attachRequest (finalFlush, pendingRequest) {
|
|
161
157
|
finalFlush.requests.add(pendingRequest)
|
|
@@ -165,7 +161,6 @@ class FinalFlushRequestTracker {
|
|
|
165
161
|
|
|
166
162
|
/**
|
|
167
163
|
* @param {PendingRequest} pendingRequest
|
|
168
|
-
* @returns {void}
|
|
169
164
|
*/
|
|
170
165
|
#updateRequestDeadline (pendingRequest) {
|
|
171
166
|
let deadline = 0
|
|
@@ -177,7 +172,6 @@ class FinalFlushRequestTracker {
|
|
|
177
172
|
|
|
178
173
|
/**
|
|
179
174
|
* @param {FinalFlush} finalFlush
|
|
180
|
-
* @returns {void}
|
|
181
175
|
*/
|
|
182
176
|
#finishFinalFlush (finalFlush) {
|
|
183
177
|
if (!this.#finalFlushes.has(finalFlush) || !finalFlush.writerDone || finalFlush.requests.size !== 0) return
|
|
@@ -44,6 +44,9 @@ function getHttpsProxyAgent (url, directAgent) {
|
|
|
44
44
|
? { keepAlive: directAgent.keepAlive, maxSockets: directAgent.maxSockets }
|
|
45
45
|
: undefined
|
|
46
46
|
agent = new HttpsProxyAgent(proxyUrl, options)
|
|
47
|
+
// AgentBase normally infers this from the node:https call stack. Interceptors such as MSW
|
|
48
|
+
// construct http.ClientRequest directly, so identify the target protocol explicitly.
|
|
49
|
+
agent.protocol = 'https:'
|
|
47
50
|
agents.set(proxyUrl, agent)
|
|
48
51
|
}
|
|
49
52
|
return agent
|
|
@@ -170,6 +170,7 @@ function request (data, options, callback) {
|
|
|
170
170
|
}
|
|
171
171
|
const error = new log.NoTransmitError(errorMessage)
|
|
172
172
|
error.status = res.statusCode
|
|
173
|
+
if (options.includeErrorResponseBody) error.responseBody = responseData
|
|
173
174
|
|
|
174
175
|
complete(error, null, res.statusCode, res.headers)
|
|
175
176
|
}
|
|
@@ -7,7 +7,6 @@ const { urlToHttpOptions } = require('./url-to-http-options-polyfill')
|
|
|
7
7
|
|
|
8
8
|
/**
|
|
9
9
|
* @param {string} hostname
|
|
10
|
-
* @returns {boolean}
|
|
11
10
|
*/
|
|
12
11
|
function isLoopbackHost (hostname) {
|
|
13
12
|
// Gate the 127/8 prefix on an IPv4 literal so names such as 127.example.com cannot pass.
|
|
@@ -20,7 +19,6 @@ function isLoopbackHost (hostname) {
|
|
|
20
19
|
/**
|
|
21
20
|
* @param {string|undefined} protocol
|
|
22
21
|
* @param {string|undefined} hostname
|
|
23
|
-
* @returns {boolean}
|
|
24
22
|
*/
|
|
25
23
|
function canSendApiKey (protocol, hostname) {
|
|
26
24
|
return protocol === 'https:' || protocol === 'unix:' ||
|
|
@@ -27,7 +27,6 @@ class Writer {
|
|
|
27
27
|
* Flushes queued telemetry, retaining delivery on supported serverless platforms.
|
|
28
28
|
* @param {(error?: Error) => void} [done]
|
|
29
29
|
* @param {{ deadline?: number }} [options]
|
|
30
|
-
* @returns {void}
|
|
31
30
|
*/
|
|
32
31
|
flush (done, options) {
|
|
33
32
|
if (this.#deliveryTracker) {
|
|
@@ -40,7 +39,6 @@ class Writer {
|
|
|
40
39
|
* Flushes queued telemetry without registering serverless delivery retention.
|
|
41
40
|
* @param {(error?: Error) => void} [done]
|
|
42
41
|
* @param {{ deadline?: number }} [options]
|
|
43
|
-
* @returns {void}
|
|
44
42
|
*/
|
|
45
43
|
flushDirect (done = noop, options) {
|
|
46
44
|
const count = this._encoder.count()
|
|
@@ -36,7 +36,6 @@ class Identifier {
|
|
|
36
36
|
|
|
37
37
|
/**
|
|
38
38
|
* @param {number} [radix]
|
|
39
|
-
* @returns {string}
|
|
40
39
|
*/
|
|
41
40
|
toString (radix = 16) {
|
|
42
41
|
if (radix === 16) {
|
|
@@ -50,9 +49,6 @@ class Identifier {
|
|
|
50
49
|
return toNumberString(this.#buffer, radix)
|
|
51
50
|
}
|
|
52
51
|
|
|
53
|
-
/**
|
|
54
|
-
* @returns {bigint}
|
|
55
|
-
*/
|
|
56
52
|
toBigInt () {
|
|
57
53
|
this.#bigInt ??= Buffer.from(this.#buffer).readBigUInt64BE(0)
|
|
58
54
|
return this.#bigInt
|
|
@@ -75,9 +71,6 @@ class Identifier {
|
|
|
75
71
|
return this.#buffer.slice(-8)
|
|
76
72
|
}
|
|
77
73
|
|
|
78
|
-
/**
|
|
79
|
-
* @returns {string}
|
|
80
|
-
*/
|
|
81
74
|
toJSON () {
|
|
82
75
|
return this.toString()
|
|
83
76
|
}
|
|
@@ -88,7 +81,6 @@ class Identifier {
|
|
|
88
81
|
* only this identifier's hex representation.
|
|
89
82
|
*
|
|
90
83
|
* @param {string | undefined} traceIdHigh - 16-char hex of the upper 64 bits, or undefined
|
|
91
|
-
* @returns {string}
|
|
92
84
|
*/
|
|
93
85
|
toTraceIdHex (traceIdHigh) {
|
|
94
86
|
if (traceIdHigh && this.#buffer.length <= 8) {
|
|
@@ -99,7 +91,6 @@ class Identifier {
|
|
|
99
91
|
|
|
100
92
|
/**
|
|
101
93
|
* @param {Identifier} other
|
|
102
|
-
* @returns {boolean}
|
|
103
94
|
*/
|
|
104
95
|
equals (other) {
|
|
105
96
|
// Big-endian suffix compare: when buffers differ in length, only the
|
|
@@ -182,7 +173,6 @@ function fromString (str, raddix) {
|
|
|
182
173
|
/**
|
|
183
174
|
* @param {number[] | Uint8Array} buffer
|
|
184
175
|
* @param {number} [radix]
|
|
185
|
-
* @returns {string}
|
|
186
176
|
*/
|
|
187
177
|
function toNumberString (buffer, radix) {
|
|
188
178
|
let high = readInt32(buffer, buffer.length - 8)
|
|
@@ -233,7 +223,6 @@ function pseudoRandom () {
|
|
|
233
223
|
/**
|
|
234
224
|
* @param {number[] | Uint8Array} buffer
|
|
235
225
|
* @param {number} offset
|
|
236
|
-
* @returns {number}
|
|
237
226
|
*/
|
|
238
227
|
function readInt32 (buffer, offset) {
|
|
239
228
|
return (buffer[offset + 0] * 16_777_216) +
|
|
@@ -0,0 +1,192 @@
|
|
|
1
|
+
'use strict'
|
|
2
|
+
|
|
3
|
+
// Raw-audio primitives shared by the LLM Observability integrations: mapping provider audio formats
|
|
4
|
+
// to MIME types, decoding telephony audio to PCM16, wrapping PCM16 in a WAV container, and deriving
|
|
5
|
+
// a segment's playback duration from its byte count. Deliberately free of LLM Observability concepts
|
|
6
|
+
// so the realtime instrumentation can use the timing half without pulling in span plumbing.
|
|
7
|
+
|
|
8
|
+
const { G711_SAMPLE_RATE, PCM16_BYTES_PER_SAMPLE, WAV_HEADER_BYTES } = require('./constants/audio')
|
|
9
|
+
|
|
10
|
+
// OpenAI Realtime audio `format` values (legacy string form) that don't map to `audio/<format>`.
|
|
11
|
+
// A Map rather than an object literal so a hostile format string ("constructor", "__proto__") can't
|
|
12
|
+
// resolve to something off Object.prototype.
|
|
13
|
+
const REALTIME_FORMAT_MIME_TYPES = new Map([
|
|
14
|
+
['pcm16', 'audio/pcm'],
|
|
15
|
+
['pcm', 'audio/pcm'],
|
|
16
|
+
['g711_ulaw', 'audio/pcmu'],
|
|
17
|
+
['g711_alaw', 'audio/pcma'],
|
|
18
|
+
])
|
|
19
|
+
|
|
20
|
+
// Raw little-endian PCM16. Not renderable on its own, but losslessly wrappable in a WAV container.
|
|
21
|
+
const PCM16_MIME_TYPES = new Set(['audio/pcm', 'audio/pcm16', 'audio/l16'])
|
|
22
|
+
|
|
23
|
+
// G.711 telephony audio (8 kHz, 8-bit companded), used by Realtime for phone-call integrations.
|
|
24
|
+
const G711_MIME_TO_VARIANT = new Map([
|
|
25
|
+
['audio/pcmu', 'ulaw'],
|
|
26
|
+
['audio/g711_ulaw', 'ulaw'],
|
|
27
|
+
['audio/pcma', 'alaw'],
|
|
28
|
+
['audio/g711_alaw', 'alaw'],
|
|
29
|
+
])
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* Decode one G.711 mu-law byte to a signed 16-bit linear PCM sample (CCITT G.711).
|
|
33
|
+
*
|
|
34
|
+
* @param {number} byte
|
|
35
|
+
*/
|
|
36
|
+
function decodeUlawSample (byte) {
|
|
37
|
+
byte = ~byte & 0xFF
|
|
38
|
+
let sample = ((byte & 0x0F) << 3) + 0x84
|
|
39
|
+
sample <<= (byte & 0x70) >> 4
|
|
40
|
+
return (byte & 0x80) ? (0x84 - sample) : (sample - 0x84)
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* Decode one G.711 A-law byte to a signed 16-bit linear PCM sample (CCITT G.711).
|
|
45
|
+
*
|
|
46
|
+
* @param {number} byte
|
|
47
|
+
*/
|
|
48
|
+
function decodeAlawSample (byte) {
|
|
49
|
+
byte ^= 0x55
|
|
50
|
+
let sample = (byte & 0x0F) << 4
|
|
51
|
+
const segment = (byte & 0x70) >> 4
|
|
52
|
+
if (segment === 0) {
|
|
53
|
+
sample += 8
|
|
54
|
+
} else if (segment === 1) {
|
|
55
|
+
sample += 0x1_08
|
|
56
|
+
} else {
|
|
57
|
+
sample = (sample + 0x1_08) << (segment - 1)
|
|
58
|
+
}
|
|
59
|
+
return (byte & 0x80) ? sample : -sample
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
// The input domain is a single byte, so both decodes collapse to a 256-entry lookup built once.
|
|
63
|
+
const ULAW_TABLE = new Int16Array(256)
|
|
64
|
+
const ALAW_TABLE = new Int16Array(256)
|
|
65
|
+
for (let byte = 0; byte < 256; byte++) {
|
|
66
|
+
ULAW_TABLE[byte] = decodeUlawSample(byte)
|
|
67
|
+
ALAW_TABLE[byte] = decodeAlawSample(byte)
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
/**
|
|
71
|
+
* Map an OpenAI Realtime audio format to a MIME type.
|
|
72
|
+
*
|
|
73
|
+
* Handles both the legacy string form (e.g. "pcm16", "g711_ulaw") and the newer discriminated-union
|
|
74
|
+
* object whose `type` is already a MIME type (e.g. "audio/pcm"). Yields an empty string when the
|
|
75
|
+
* format is absent or unusable, which callers treat as "unknown" rather than guessing a rate.
|
|
76
|
+
*
|
|
77
|
+
* @param {string | { type?: string } | undefined} format
|
|
78
|
+
*/
|
|
79
|
+
function realtimeAudioFormatToMime (format) {
|
|
80
|
+
const type = typeof format === 'object' && format !== null ? format.type : format
|
|
81
|
+
if (typeof type !== 'string') return ''
|
|
82
|
+
|
|
83
|
+
const normalized = type.trim().toLowerCase()
|
|
84
|
+
if (!normalized) return ''
|
|
85
|
+
if (normalized.startsWith('audio/')) return normalized
|
|
86
|
+
|
|
87
|
+
return REALTIME_FORMAT_MIME_TYPES.get(normalized) ?? `audio/${normalized}`
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
/**
|
|
91
|
+
* @param {string} mimeType
|
|
92
|
+
*/
|
|
93
|
+
function isPcm16AudioMime (mimeType) {
|
|
94
|
+
return typeof mimeType === 'string' && PCM16_MIME_TYPES.has(mimeType.trim().toLowerCase())
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
/**
|
|
98
|
+
* @param {string} mimeType
|
|
99
|
+
* @returns {'ulaw' | 'alaw' | undefined} The G.711 variant, or `undefined` for any other format.
|
|
100
|
+
*/
|
|
101
|
+
function g711Variant (mimeType) {
|
|
102
|
+
if (typeof mimeType !== 'string') return
|
|
103
|
+
return G711_MIME_TO_VARIANT.get(mimeType.trim().toLowerCase())
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
/**
|
|
107
|
+
* Decode G.711 audio to raw little-endian PCM16.
|
|
108
|
+
*
|
|
109
|
+
* @param {Buffer} data
|
|
110
|
+
* @param {'ulaw' | 'alaw'} variant
|
|
111
|
+
* @returns {Buffer}
|
|
112
|
+
*/
|
|
113
|
+
function g711ToPcm16 (data, variant) {
|
|
114
|
+
const table = variant === 'alaw' ? ALAW_TABLE : ULAW_TABLE
|
|
115
|
+
const pcm = Buffer.allocUnsafe(data.length * PCM16_BYTES_PER_SAMPLE)
|
|
116
|
+
for (let i = 0; i < data.length; i++) {
|
|
117
|
+
pcm.writeInt16LE(table[data[i]], i * PCM16_BYTES_PER_SAMPLE)
|
|
118
|
+
}
|
|
119
|
+
return pcm
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
/**
|
|
123
|
+
* Wrap raw little-endian PCM16 audio in a WAV container.
|
|
124
|
+
*
|
|
125
|
+
* Lossless and cheap — it only prepends a 44-byte header — and turns raw PCM, which the UI can't
|
|
126
|
+
* render, into a playable `audio/wav` payload.
|
|
127
|
+
*
|
|
128
|
+
* @param {Buffer} pcm
|
|
129
|
+
* @param {number} [sampleRate]
|
|
130
|
+
* @param {number} [channels]
|
|
131
|
+
* @returns {Buffer}
|
|
132
|
+
*/
|
|
133
|
+
function pcm16ToWav (pcm, sampleRate = 24_000, channels = 1) {
|
|
134
|
+
const blockAlign = channels * PCM16_BYTES_PER_SAMPLE
|
|
135
|
+
const header = Buffer.allocUnsafe(WAV_HEADER_BYTES)
|
|
136
|
+
|
|
137
|
+
header.write('RIFF', 0, 'latin1')
|
|
138
|
+
header.writeUInt32LE(WAV_HEADER_BYTES - 8 + pcm.length, 4) // RIFF chunk size: everything after this field
|
|
139
|
+
header.write('WAVE', 8, 'latin1')
|
|
140
|
+
header.write('fmt ', 12, 'latin1')
|
|
141
|
+
header.writeUInt32LE(16, 16) // fmt chunk size, 16 for PCM
|
|
142
|
+
header.writeUInt16LE(1, 20) // audio format, 1 for uncompressed PCM
|
|
143
|
+
header.writeUInt16LE(channels, 22)
|
|
144
|
+
header.writeUInt32LE(sampleRate, 24)
|
|
145
|
+
header.writeUInt32LE(sampleRate * blockAlign, 28) // byte rate
|
|
146
|
+
header.writeUInt16LE(blockAlign, 32)
|
|
147
|
+
header.writeUInt16LE(PCM16_BYTES_PER_SAMPLE * 8, 34) // bits per sample
|
|
148
|
+
header.write('data', 36, 'latin1')
|
|
149
|
+
header.writeUInt32LE(pcm.length, 40)
|
|
150
|
+
|
|
151
|
+
return Buffer.concat([header, pcm], WAV_HEADER_BYTES + pcm.length)
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
/**
|
|
155
|
+
* Byte rate of a raw audio format: PCM16 is 2 bytes per sample at the session's rate, G.711 is 1
|
|
156
|
+
* byte per sample at the fixed 8 kHz rate. Any other or unknown format returns `undefined` — we do
|
|
157
|
+
* not guess a rate, so durations and offsets derived from it are simply unavailable.
|
|
158
|
+
*
|
|
159
|
+
* @param {string} mimeType
|
|
160
|
+
* @param {number} sampleRate
|
|
161
|
+
* @returns {number | undefined}
|
|
162
|
+
*/
|
|
163
|
+
function bytesPerSecond (mimeType, sampleRate) {
|
|
164
|
+
if (sampleRate > 0 && isPcm16AudioMime(mimeType)) return sampleRate * PCM16_BYTES_PER_SAMPLE
|
|
165
|
+
if (g711Variant(mimeType) !== undefined) return G711_SAMPLE_RATE
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
/**
|
|
169
|
+
* Playback duration (in milliseconds) of an audio segment, from its decoded byte count. Sizes the
|
|
170
|
+
* user-speech and agent-speech spans and the turn root's end, so it may be fractional.
|
|
171
|
+
*
|
|
172
|
+
* @param {number} decodedBytes
|
|
173
|
+
* @param {string} mimeType
|
|
174
|
+
* @param {number} sampleRate
|
|
175
|
+
* @returns {number | undefined}
|
|
176
|
+
*/
|
|
177
|
+
function segmentDurationMs (decodedBytes, mimeType, sampleRate) {
|
|
178
|
+
if (!(decodedBytes > 0)) return
|
|
179
|
+
const rate = bytesPerSecond(mimeType, sampleRate)
|
|
180
|
+
if (!rate) return
|
|
181
|
+
return decodedBytes / rate * 1000
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
module.exports = {
|
|
185
|
+
bytesPerSecond,
|
|
186
|
+
g711ToPcm16,
|
|
187
|
+
g711Variant,
|
|
188
|
+
isPcm16AudioMime,
|
|
189
|
+
pcm16ToWav,
|
|
190
|
+
realtimeAudioFormatToMime,
|
|
191
|
+
segmentDurationMs,
|
|
192
|
+
}
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
'use strict'
|
|
2
|
+
|
|
3
|
+
// Building `audioPart`s for LLM Observability messages: mapping provider audio formats to MIME
|
|
4
|
+
// types, and keeping inline audio within the per-span-event size budget. The raw-audio primitives
|
|
5
|
+
// these build on (WAV wrapping, G.711 decoding, byte rates) live in `audio-codec.js`.
|
|
6
|
+
|
|
7
|
+
const log = require('../log')
|
|
8
|
+
const { LLMOBS_AUDIO_INLINE_MAX_BYTES } = require('./constants/audio')
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* @typedef {{ mimeType: string, content: string }} AudioPart
|
|
12
|
+
*/
|
|
13
|
+
|
|
14
|
+
// Raw audio formats the UI cannot render as a player. For these we keep the transcript as the
|
|
15
|
+
// message content and skip the inline audio part, since raw bytes would only bloat the payload.
|
|
16
|
+
const NON_RENDERABLE_AUDIO_MIME_TYPES = new Set([
|
|
17
|
+
'audio/pcm',
|
|
18
|
+
'audio/pcm16',
|
|
19
|
+
'audio/l16',
|
|
20
|
+
'audio/pcmu',
|
|
21
|
+
'audio/pcma',
|
|
22
|
+
'audio/g711_ulaw',
|
|
23
|
+
'audio/g711_alaw',
|
|
24
|
+
'audio/basic',
|
|
25
|
+
])
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* Length of `byteLength` bytes after standard base64 encoding: 4 characters per 3 bytes, padded.
|
|
29
|
+
*
|
|
30
|
+
* @param {number} byteLength
|
|
31
|
+
*/
|
|
32
|
+
function base64EncodedLength (byteLength) {
|
|
33
|
+
return Math.ceil(byteLength / 3) * 4
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
// Maps an audio `format` (e.g. "wav", "mp3") to a MIME type. Defaults to `audio/wav` when the
|
|
37
|
+
// format is missing. Provider-specific overrides (e.g. OpenAI's mp3 -> audio/mpeg) are passed in
|
|
38
|
+
// via `mimeTypeLookup` so this stays provider-agnostic. A non-string `format` is treated as missing
|
|
39
|
+
// so a malformed auto-instrumented payload can't throw and disable the plugin.
|
|
40
|
+
/**
|
|
41
|
+
* @param {string} fmt
|
|
42
|
+
* @param {Record<string, string>} [mimeTypeLookup]
|
|
43
|
+
*/
|
|
44
|
+
function audioMimeTypeFromFormat (fmt, mimeTypeLookup = {}) {
|
|
45
|
+
fmt = typeof fmt === 'string' ? fmt.trim().toLowerCase() : ''
|
|
46
|
+
if (!fmt) return 'audio/wav'
|
|
47
|
+
// `hasOwn` rather than a plain lookup: a format of "constructor" would otherwise resolve to
|
|
48
|
+
// something off Object.prototype and be returned as the MIME type.
|
|
49
|
+
return Object.hasOwn(mimeTypeLookup, fmt) ? mimeTypeLookup[fmt] : `audio/${fmt}`
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
/**
|
|
53
|
+
* Whether a MIME type can be rendered as an audio player in the UI. Raw PCM cannot.
|
|
54
|
+
*
|
|
55
|
+
* @param {string} mimeType
|
|
56
|
+
*/
|
|
57
|
+
function isRenderableAudioMime (mimeType) {
|
|
58
|
+
return typeof mimeType === 'string' &&
|
|
59
|
+
mimeType.length > 0 &&
|
|
60
|
+
!NON_RENDERABLE_AUDIO_MIME_TYPES.has(mimeType.trim().toLowerCase())
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
// Builds an audio part from raw audio bytes (base64-encoded) or an existing base64 string. Only
|
|
64
|
+
// Buffer/Uint8Array inputs are base64-encoded; any other shape is passed through so a malformed
|
|
65
|
+
// auto-instrumented payload can't throw (the tagger soft-skips a non-string `content`).
|
|
66
|
+
/**
|
|
67
|
+
* @param {Buffer | Uint8Array | string} data
|
|
68
|
+
* @param {string} mimeType
|
|
69
|
+
* @returns {AudioPart}
|
|
70
|
+
*/
|
|
71
|
+
function formatAudioPart (data, mimeType) {
|
|
72
|
+
const content = Buffer.isBuffer(data) || ArrayBuffer.isView(data)
|
|
73
|
+
? Buffer.from(data).toString('base64')
|
|
74
|
+
: data
|
|
75
|
+
return { mimeType, content }
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
/**
|
|
79
|
+
* Whether `byteLength` bytes of audio fit the inline budget once base64-encoded.
|
|
80
|
+
*
|
|
81
|
+
* Compares the *encoded* size: `formatAudioPart` base64-encodes the bytes (~4/3 expansion), and it
|
|
82
|
+
* is that encoded content which counts against the per-span-event limit. Exposed separately so a
|
|
83
|
+
* caller that has to allocate to produce those bytes — decoding G.711 to PCM16, wrapping raw PCM in
|
|
84
|
+
* a WAV container — can check the size it is about to produce before paying for it.
|
|
85
|
+
*
|
|
86
|
+
* @param {number} byteLength
|
|
87
|
+
* @param {number} [maxBytes]
|
|
88
|
+
*/
|
|
89
|
+
function fitsInlineAudioBudget (byteLength, maxBytes = LLMOBS_AUDIO_INLINE_MAX_BYTES) {
|
|
90
|
+
const encodedLength = base64EncodedLength(byteLength)
|
|
91
|
+
if (encodedLength <= maxBytes) return true
|
|
92
|
+
|
|
93
|
+
log.debug('Audio (%d encoded bytes) exceeds inline budget %d; omitting inline audio content',
|
|
94
|
+
encodedLength, maxBytes)
|
|
95
|
+
return false
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
/**
|
|
99
|
+
* Build a playable audio part, but only for renderable formats within the size budget. Returns
|
|
100
|
+
* `undefined` for a non-renderable format (e.g. raw PCM) or oversize audio; callers fall back to the
|
|
101
|
+
* transcript as the message content in that case.
|
|
102
|
+
*
|
|
103
|
+
* @param {Buffer} audioBytes
|
|
104
|
+
* @param {string} mimeType
|
|
105
|
+
* @param {number} [maxBytes]
|
|
106
|
+
* @returns {AudioPart | undefined}
|
|
107
|
+
*/
|
|
108
|
+
function formatAudioPartWithGuard (audioBytes, mimeType, maxBytes = LLMOBS_AUDIO_INLINE_MAX_BYTES) {
|
|
109
|
+
if (!audioBytes?.length || !isRenderableAudioMime(mimeType)) return
|
|
110
|
+
if (!fitsInlineAudioBudget(audioBytes.length, maxBytes)) return
|
|
111
|
+
|
|
112
|
+
return formatAudioPart(audioBytes, mimeType)
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
module.exports = {
|
|
116
|
+
audioMimeTypeFromFormat,
|
|
117
|
+
fitsInlineAudioBudget,
|
|
118
|
+
formatAudioPart,
|
|
119
|
+
formatAudioPartWithGuard,
|
|
120
|
+
isRenderableAudioMime,
|
|
121
|
+
}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
'use strict'
|
|
2
|
+
|
|
3
|
+
module.exports = {
|
|
4
|
+
// Surfaced as a message's content when audio was captured but couldn't be turned into a playable
|
|
5
|
+
// part (unsupported format, or over the size budget) and there is no transcript to show instead.
|
|
6
|
+
AUDIO_FALLBACK: '[audio]',
|
|
7
|
+
|
|
8
|
+
// G.711 telephony audio is always 8 kHz mono.
|
|
9
|
+
G711_SAMPLE_RATE: 8000,
|
|
10
|
+
|
|
11
|
+
// Budget for inline audio, measured on the *base64-encoded* size, since that is what actually
|
|
12
|
+
// rides the span event. Kept below the 5 MB per-span-event limit with headroom for the rest of the
|
|
13
|
+
// event, whose whole I/O is dropped backend-side when oversize. 4 MiB encoded is ~3 MiB of audio.
|
|
14
|
+
//
|
|
15
|
+
// Per *event*, not per audio part. An event carrying audio on more than one message — a realtime
|
|
16
|
+
// turn has both the user's and the agent's — has to divide this between them, or two individually
|
|
17
|
+
// accepted clips sum past the limit and cost the event all of its I/O.
|
|
18
|
+
LLMOBS_AUDIO_INLINE_MAX_BYTES: 4 * 1024 * 1024,
|
|
19
|
+
|
|
20
|
+
// Cap on the raw audio buffered per side of a realtime turn: the point at which base64 encoding
|
|
21
|
+
// would put a 1:1 format over `LLMOBS_AUDIO_INLINE_MAX_BYTES` anyway (4 chars per 3 bytes).
|
|
22
|
+
// Beyond this the size guard would drop the audio at tag time, so we stop retaining it rather
|
|
23
|
+
// than hold megabytes in memory only to discard them. A memory bound, not a correctness one — the
|
|
24
|
+
// guard still decides.
|
|
25
|
+
//
|
|
26
|
+
// A format that expands on the way to a playable part inlines less than this: G.711 decodes to
|
|
27
|
+
// PCM16 at 2 bytes per sample, so only about half of it can ever ride the span event. Callers
|
|
28
|
+
// check the *converted* size against the budget before converting (`fitsInlineAudioBudget`), so
|
|
29
|
+
// the excess is never paid for in allocations — it is only retained and then dropped.
|
|
30
|
+
LLMOBS_AUDIO_ACCUMULATE_MAX_BYTES: 3 * 1024 * 1024,
|
|
31
|
+
|
|
32
|
+
PCM16_BYTES_PER_SAMPLE: 2,
|
|
33
|
+
|
|
34
|
+
WAV_HEADER_BYTES: 44,
|
|
35
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
'use strict'
|
|
2
|
+
|
|
3
|
+
module.exports = {
|
|
4
|
+
ERROR_NAMES: {
|
|
5
|
+
API: 'PromptAPIError',
|
|
6
|
+
AUTH: 'PromptAuthError',
|
|
7
|
+
CONFLICT: 'PromptConflictError',
|
|
8
|
+
NOT_FOUND: 'PromptNotFoundError',
|
|
9
|
+
SERVER: 'PromptServerError',
|
|
10
|
+
VALIDATION: 'PromptValidationError',
|
|
11
|
+
},
|
|
12
|
+
PROMPTS_PATH: '/api/unstable/llm-obs/v1/prompts',
|
|
13
|
+
SOURCE_CACHE: 'cache',
|
|
14
|
+
}
|
|
@@ -69,6 +69,23 @@ module.exports = {
|
|
|
69
69
|
INSTRUMENTATION_METHOD_ANNOTATED: 'annotated',
|
|
70
70
|
INSTRUMENTATION_METHOD_UNKNOWN: 'unknown',
|
|
71
71
|
|
|
72
|
+
GEN_AI_OPERATION_NAME: 'gen_ai.operation.name',
|
|
73
|
+
GEN_AI_REQUEST_MODEL: 'gen_ai.request.model',
|
|
74
|
+
GEN_AI_PROVIDER_NAME: 'gen_ai.provider.name',
|
|
75
|
+
GEN_AI_APPLICATION_NAME: 'gen_ai.application.name',
|
|
76
|
+
GEN_AI_CONVERSATION_ID: 'gen_ai.conversation.id',
|
|
77
|
+
|
|
78
|
+
GEN_AI_USAGE_INPUT_TOKENS_METRIC_KEY: 'gen_ai.usage.input_tokens',
|
|
79
|
+
GEN_AI_USAGE_OUTPUT_TOKENS_METRIC_KEY: 'gen_ai.usage.output_tokens',
|
|
80
|
+
GEN_AI_USAGE_TOTAL_TOKENS_METRIC_KEY: 'gen_ai.usage.total_tokens',
|
|
81
|
+
GEN_AI_USAGE_CACHE_READ_INPUT_TOKENS_METRIC_KEY: 'gen_ai.usage.cache_read_input_tokens',
|
|
82
|
+
GEN_AI_USAGE_CACHE_WRITE_INPUT_TOKENS_METRIC_KEY: 'gen_ai.usage.cache_write_input_tokens',
|
|
83
|
+
GEN_AI_USAGE_REASONING_OUTPUT_TOKENS_METRIC_KEY: 'gen_ai.usage.reasoning_output_tokens',
|
|
84
|
+
|
|
85
|
+
// Marks the `gen_ai.*` tags on an APM span as tracer-emitted. Without it the backend reads them
|
|
86
|
+
// as user-set and builds a duplicate LLMObs span out of the APM span.
|
|
87
|
+
ARTIFICIAL_GEN_AI_TAGS: '_dd.llmobs.artificial_gen_ai_tags',
|
|
88
|
+
|
|
72
89
|
ROUTING_API_KEY: '_dd.llmobs.routing.api_key',
|
|
73
90
|
ROUTING_SITE: '_dd.llmobs.routing.site',
|
|
74
91
|
}
|
|
@@ -61,7 +61,6 @@ const TERMS = {
|
|
|
61
61
|
|
|
62
62
|
/**
|
|
63
63
|
* @param {string[]} metricTypes
|
|
64
|
-
* @returns {string} the quoted list, e.g. `"categorical", "score" or "json"`
|
|
65
64
|
*/
|
|
66
65
|
function formatMetricTypes (metricTypes) {
|
|
67
66
|
const quoted = metricTypes.map(metricType => `"${metricType}"`)
|
|
@@ -99,7 +98,6 @@ function invalidTagsError (kind) {
|
|
|
99
98
|
/**
|
|
100
99
|
* @param {unknown} timestampMs
|
|
101
100
|
* @param {MetricEventKind} kind
|
|
102
|
-
* @returns {void}
|
|
103
101
|
*/
|
|
104
102
|
function validateTimestamp (timestampMs, kind) {
|
|
105
103
|
if (typeof timestampMs !== 'number' || timestampMs < 0) {
|
|
@@ -137,7 +135,6 @@ function validateLabel (label, kind) {
|
|
|
137
135
|
/**
|
|
138
136
|
* @param {string | undefined} metricType - Already lower-cased metric type.
|
|
139
137
|
* @param {MetricEventKind} kind
|
|
140
|
-
* @returns {void}
|
|
141
138
|
*/
|
|
142
139
|
function validateMetricType (metricType, kind) {
|
|
143
140
|
if (!metricType || !METRIC_TYPES[kind].includes(metricType)) {
|
|
@@ -148,7 +145,6 @@ function validateMetricType (metricType, kind) {
|
|
|
148
145
|
/**
|
|
149
146
|
* @param {string | undefined} metricType - Metric type already validated for the submitted kind.
|
|
150
147
|
* @param {unknown} value
|
|
151
|
-
* @returns {void}
|
|
152
148
|
*/
|
|
153
149
|
function validateMetricValue (metricType, value) {
|
|
154
150
|
if (metricType === 'categorical' && typeof value !== 'string') {
|
|
@@ -170,7 +166,6 @@ function validateMetricValue (metricType, value) {
|
|
|
170
166
|
|
|
171
167
|
/**
|
|
172
168
|
* @param {unknown} assessment
|
|
173
|
-
* @returns {void}
|
|
174
169
|
*/
|
|
175
170
|
function validateAssessment (assessment) {
|
|
176
171
|
if (assessment != null && assessment !== 'pass' && assessment !== 'fail') {
|
|
@@ -180,7 +175,6 @@ function validateAssessment (assessment) {
|
|
|
180
175
|
|
|
181
176
|
/**
|
|
182
177
|
* @param {unknown} reasoning
|
|
183
|
-
* @returns {void}
|
|
184
178
|
*/
|
|
185
179
|
function validateReasoning (reasoning) {
|
|
186
180
|
if (reasoning != null && typeof reasoning !== 'string') {
|