dd-trace 4.51.1 → 4.53.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/LICENSE-3rdparty.csv +8 -2
- package/ci/init.js +16 -0
- package/index.d.ts +31 -13
- package/init.js +4 -66
- package/initialize.mjs +13 -10
- package/loader-hook.mjs +4 -0
- package/package.json +16 -11
- package/packages/datadog-core/src/storage.js +39 -2
- package/packages/datadog-instrumentations/src/aerospike.js +1 -1
- package/packages/datadog-instrumentations/src/azure-functions.js +1 -1
- package/packages/datadog-instrumentations/src/cucumber.js +29 -3
- package/packages/datadog-instrumentations/src/express.js +38 -4
- package/packages/datadog-instrumentations/src/helpers/bundler-register.js +3 -3
- package/packages/datadog-instrumentations/src/helpers/hooks.js +0 -1
- package/packages/datadog-instrumentations/src/helpers/register.js +3 -4
- package/packages/datadog-instrumentations/src/http/client.js +1 -1
- package/packages/datadog-instrumentations/src/jest.js +27 -8
- package/packages/datadog-instrumentations/src/mocha/utils.js +2 -1
- package/packages/datadog-instrumentations/src/mysql2.js +13 -8
- package/packages/datadog-instrumentations/src/next.js +7 -4
- package/packages/datadog-instrumentations/src/passport-http.js +2 -14
- package/packages/datadog-instrumentations/src/passport-local.js +2 -14
- package/packages/datadog-instrumentations/src/passport-utils.js +43 -19
- package/packages/datadog-instrumentations/src/pg.js +6 -6
- package/packages/datadog-instrumentations/src/playwright.js +17 -4
- package/packages/datadog-instrumentations/src/router.js +97 -1
- package/packages/datadog-instrumentations/src/sequelize.js +9 -4
- package/packages/datadog-instrumentations/src/url.js +4 -0
- package/packages/datadog-instrumentations/src/vitest.js +27 -2
- package/packages/datadog-plugin-avsc/src/schema_iterator.js +8 -3
- package/packages/datadog-plugin-aws-sdk/src/services/dynamodb.js +154 -0
- package/packages/datadog-plugin-aws-sdk/src/services/eventbridge.js +1 -1
- package/packages/datadog-plugin-aws-sdk/src/services/kinesis.js +1 -1
- package/packages/datadog-plugin-aws-sdk/src/services/lambda.js +1 -1
- package/packages/datadog-plugin-aws-sdk/src/services/s3.js +1 -1
- package/packages/datadog-plugin-aws-sdk/src/services/sqs.js +1 -1
- package/packages/datadog-plugin-aws-sdk/src/util.js +92 -0
- package/packages/datadog-plugin-azure-functions/src/index.js +1 -1
- package/packages/datadog-plugin-child_process/src/scrub-cmd-params.js +1 -1
- package/packages/datadog-plugin-cucumber/src/index.js +39 -4
- package/packages/datadog-plugin-cypress/src/cypress-plugin.js +3 -3
- package/packages/datadog-plugin-grpc/src/client.js +2 -2
- package/packages/datadog-plugin-grpc/src/util.js +1 -1
- package/packages/datadog-plugin-jest/src/index.js +39 -4
- package/packages/datadog-plugin-langchain/src/handlers/language_models/chat_model.js +1 -1
- package/packages/datadog-plugin-langchain/src/handlers/language_models/llm.js +1 -1
- package/packages/datadog-plugin-mocha/src/index.js +36 -2
- package/packages/datadog-plugin-oracledb/src/index.js +1 -1
- package/packages/datadog-plugin-vitest/src/index.js +34 -2
- package/packages/datadog-shimmer/src/shimmer.js +8 -4
- package/packages/dd-trace/src/appsec/addresses.js +3 -0
- package/packages/dd-trace/src/appsec/api_security_sampler.js +1 -1
- package/packages/dd-trace/src/appsec/blocked_templates.js +1 -1
- package/packages/dd-trace/src/appsec/blocking.js +1 -1
- package/packages/dd-trace/src/appsec/channels.js +1 -0
- package/packages/dd-trace/src/appsec/iast/analyzers/code-injection-analyzer.js +4 -0
- package/packages/dd-trace/src/appsec/iast/analyzers/cookie-analyzer.js +2 -2
- package/packages/dd-trace/src/appsec/iast/analyzers/hardcoded-password-rules.js +1 -1
- package/packages/dd-trace/src/appsec/iast/analyzers/hardcoded-secret-rules.js +1 -1
- package/packages/dd-trace/src/appsec/iast/analyzers/hardcoded-secrets-rules.js +1 -1
- package/packages/dd-trace/src/appsec/iast/analyzers/injection-analyzer.js +10 -3
- package/packages/dd-trace/src/appsec/iast/analyzers/sql-injection-analyzer.js +4 -0
- package/packages/dd-trace/src/appsec/iast/analyzers/template-injection-analyzer.js +4 -0
- package/packages/dd-trace/src/appsec/iast/iast-plugin.js +8 -21
- package/packages/dd-trace/src/appsec/iast/taint-tracking/index.js +3 -3
- package/packages/dd-trace/src/appsec/iast/taint-tracking/operations-taint-object.js +2 -2
- package/packages/dd-trace/src/appsec/iast/taint-tracking/plugin.js +64 -3
- package/packages/dd-trace/src/appsec/iast/taint-tracking/rewriter.js +5 -8
- package/packages/dd-trace/src/appsec/iast/taint-tracking/source-types.js +2 -1
- package/packages/dd-trace/src/appsec/iast/taint-tracking/taint-tracking-impl.js +7 -11
- package/packages/dd-trace/src/appsec/iast/telemetry/namespaces.js +2 -3
- package/packages/dd-trace/src/appsec/iast/vulnerabilities-formatter/evidence-redaction/sensitive-analyzers/command-sensitive-analyzer.js +2 -2
- package/packages/dd-trace/src/appsec/iast/vulnerabilities-formatter/evidence-redaction/sensitive-analyzers/ldap-sensitive-analyzer.js +2 -2
- package/packages/dd-trace/src/appsec/iast/vulnerabilities-formatter/evidence-redaction/sensitive-analyzers/sql-sensitive-analyzer.js +2 -2
- 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 +3 -3
- package/packages/dd-trace/src/appsec/iast/vulnerabilities-formatter/evidence-redaction/sensitive-regex.js +2 -2
- package/packages/dd-trace/src/appsec/iast/vulnerabilities-formatter/utils.js +1 -1
- package/packages/dd-trace/src/appsec/iast/vulnerability-reporter.js +32 -37
- package/packages/dd-trace/src/appsec/index.js +18 -13
- package/packages/dd-trace/src/appsec/rasp/fs-plugin.js +2 -2
- package/packages/dd-trace/src/appsec/rasp/utils.js +1 -1
- package/packages/dd-trace/src/appsec/remote_config/capabilities.js +1 -0
- package/packages/dd-trace/src/appsec/remote_config/index.js +25 -1
- package/packages/dd-trace/src/appsec/remote_config/manager.js +2 -2
- package/packages/dd-trace/src/appsec/reporter.js +3 -1
- package/packages/dd-trace/src/appsec/sdk/set_user.js +2 -2
- package/packages/dd-trace/src/appsec/sdk/track_event.js +37 -24
- package/packages/dd-trace/src/appsec/sdk/user_blocking.js +4 -4
- package/packages/dd-trace/src/appsec/telemetry.js +10 -0
- package/packages/dd-trace/src/appsec/user_tracking.js +168 -0
- package/packages/dd-trace/src/appsec/waf/index.js +2 -2
- package/packages/dd-trace/src/appsec/waf/waf_context_wrapper.js +2 -3
- package/packages/dd-trace/src/appsec/waf/waf_manager.js +1 -1
- package/packages/dd-trace/src/azure_metadata.js +4 -4
- package/packages/dd-trace/src/ci-visibility/dynamic-instrumentation/index.js +5 -4
- package/packages/dd-trace/src/ci-visibility/dynamic-instrumentation/worker/index.js +39 -3
- package/packages/dd-trace/src/ci-visibility/exporters/agentless/coverage-writer.js +1 -1
- package/packages/dd-trace/src/ci-visibility/exporters/agentless/di-logs-writer.js +1 -1
- package/packages/dd-trace/src/ci-visibility/exporters/agentless/index.js +1 -1
- package/packages/dd-trace/src/ci-visibility/exporters/agentless/writer.js +1 -1
- package/packages/dd-trace/src/ci-visibility/exporters/ci-visibility-exporter.js +29 -9
- package/packages/dd-trace/src/ci-visibility/requests/get-library-configuration.js +4 -2
- package/packages/dd-trace/src/config.js +24 -32
- package/packages/dd-trace/src/constants.js +1 -0
- package/packages/dd-trace/src/crashtracking/crashtracker.js +3 -2
- package/packages/dd-trace/src/datastreams/processor.js +4 -6
- package/packages/dd-trace/src/datastreams/writer.js +6 -5
- package/packages/dd-trace/src/debugger/devtools_client/breakpoints.js +80 -0
- package/packages/dd-trace/src/debugger/devtools_client/config.js +3 -1
- package/packages/dd-trace/src/debugger/devtools_client/defaults.js +6 -0
- package/packages/dd-trace/src/debugger/devtools_client/index.js +63 -8
- package/packages/dd-trace/src/debugger/devtools_client/remote_config.js +10 -67
- package/packages/dd-trace/src/debugger/devtools_client/send.js +2 -1
- package/packages/dd-trace/src/debugger/devtools_client/state.js +1 -1
- package/packages/dd-trace/src/debugger/devtools_client/status.js +4 -4
- package/packages/dd-trace/src/debugger/index.js +14 -10
- package/packages/dd-trace/src/dogstatsd.js +2 -2
- package/packages/dd-trace/src/encode/0.4.js +23 -78
- package/packages/dd-trace/src/encode/agentless-ci-visibility.js +0 -32
- package/packages/dd-trace/src/encode/coverage-ci-visibility.js +1 -2
- package/packages/dd-trace/src/encode/span-stats.js +0 -30
- package/packages/dd-trace/src/exporters/agent/writer.js +3 -3
- package/packages/dd-trace/src/exporters/common/request.js +1 -1
- package/packages/dd-trace/src/exporters/span-stats/writer.js +1 -1
- package/packages/dd-trace/src/flare/index.js +1 -1
- package/packages/dd-trace/src/guardrails/index.js +64 -0
- package/packages/dd-trace/src/guardrails/log.js +32 -0
- package/packages/dd-trace/src/guardrails/telemetry.js +78 -0
- package/packages/dd-trace/src/guardrails/util.js +10 -0
- package/packages/dd-trace/src/lambda/runtime/ritm.js +2 -2
- package/packages/dd-trace/src/llmobs/storage.js +2 -3
- package/packages/dd-trace/src/llmobs/writers/base.js +2 -2
- package/packages/dd-trace/src/{encode → msgpack}/chunk.js +8 -5
- package/packages/dd-trace/src/msgpack/encoder.js +309 -0
- package/packages/dd-trace/src/msgpack/index.js +6 -0
- package/packages/dd-trace/src/opentelemetry/context_manager.js +2 -2
- package/packages/dd-trace/src/opentracing/propagation/text_map.js +12 -9
- package/packages/dd-trace/src/opentracing/span.js +1 -1
- package/packages/dd-trace/src/opentracing/tracer.js +2 -2
- package/packages/dd-trace/src/plugin_manager.js +4 -2
- package/packages/dd-trace/src/plugins/ci_plugin.js +47 -4
- package/packages/dd-trace/src/plugins/plugin.js +1 -1
- package/packages/dd-trace/src/plugins/tracing.js +1 -1
- package/packages/dd-trace/src/plugins/util/git.js +7 -7
- package/packages/dd-trace/src/plugins/util/test.js +36 -3
- package/packages/dd-trace/src/plugins/util/web.js +2 -2
- package/packages/dd-trace/src/profiling/config.js +3 -0
- package/packages/dd-trace/src/profiling/exporters/agent.js +9 -68
- package/packages/dd-trace/src/profiling/exporters/event_serializer.js +76 -0
- package/packages/dd-trace/src/profiling/exporters/file.js +8 -4
- package/packages/dd-trace/src/profiling/profiler.js +62 -10
- package/packages/dd-trace/src/profiling/profilers/event_plugins/event.js +22 -12
- package/packages/dd-trace/src/profiling/profilers/events.js +47 -8
- package/packages/dd-trace/src/profiling/profilers/wall.js +2 -17
- package/packages/dd-trace/src/profiling/webspan-utils.js +23 -0
- package/packages/dd-trace/src/proxy.js +7 -2
- package/packages/dd-trace/src/runtime_metrics.js +107 -4
- package/packages/dd-trace/src/serverless.js +1 -1
- package/packages/dd-trace/src/service-naming/schemas/v0/serverless.js +1 -1
- package/packages/dd-trace/src/service-naming/schemas/v1/serverless.js +1 -1
- package/packages/dd-trace/src/span_processor.js +10 -10
- package/packages/dd-trace/src/tagger.js +1 -1
- package/packages/dd-trace/src/telemetry/index.js +1 -0
- package/packages/dd-trace/src/telemetry/logs/index.js +2 -2
- package/packages/dd-trace/src/telemetry/logs/log-collector.js +10 -2
- package/packages/dd-trace/src/telemetry/send-data.js +2 -2
- package/packages/dd-trace/src/util.js +5 -16
- package/packages/datadog-instrumentations/src/qs.js +0 -24
- package/packages/dd-trace/src/appsec/iast/iast-log.js +0 -86
- package/packages/dd-trace/src/appsec/passport.js +0 -110
- package/packages/dd-trace/src/telemetry/init-telemetry.js +0 -75
|
@@ -132,11 +132,11 @@ function checkIfBothOtelAndDdEnvVarSet () {
|
|
|
132
132
|
const fromEntries = Object.fromEntries || (entries =>
|
|
133
133
|
entries.reduce((obj, [k, v]) => Object.assign(obj, { [k]: v }), {}))
|
|
134
134
|
|
|
135
|
-
// eslint-disable-next-line max-len
|
|
135
|
+
// eslint-disable-next-line @stylistic/js/max-len
|
|
136
136
|
const qsRegex = '(?:p(?:ass)?w(?:or)?d|pass(?:_?phrase)?|secret|(?:api_?|private_?|public_?|access_?|secret_?)key(?:_?id)?|token|consumer_?(?:id|key|secret)|sign(?:ed|ature)?|auth(?:entication|orization)?)(?:(?:\\s|%20)*(?:=|%3D)[^&]+|(?:"|%22)(?:\\s|%20)*(?::|%3A)(?:\\s|%20)*(?:"|%22)(?:%2[^2]|%[^2]|[^"%])+(?:"|%22))|bearer(?:\\s|%20)+[a-z0-9\\._\\-]+|token(?::|%3A)[a-z0-9]{13}|gh[opsu]_[0-9a-zA-Z]{36}|ey[I-L](?:[\\w=-]|%3D)+\\.ey[I-L](?:[\\w=-]|%3D)+(?:\\.(?:[\\w.+\\/=-]|%3D|%2F|%2B)+)?|[\\-]{5}BEGIN(?:[a-z\\s]|%20)+PRIVATE(?:\\s|%20)KEY[\\-]{5}[^\\-]+[\\-]{5}END(?:[a-z\\s]|%20)+PRIVATE(?:\\s|%20)KEY|ssh-rsa(?:\\s|%20)*(?:[a-z0-9\\/\\.+]|%2F|%5C|%2B){100,}'
|
|
137
|
-
// eslint-disable-next-line max-len
|
|
137
|
+
// eslint-disable-next-line @stylistic/js/max-len
|
|
138
138
|
const defaultWafObfuscatorKeyRegex = '(?i)pass|pw(?:or)?d|secret|(?:api|private|public|access)[_-]?key|token|consumer[_-]?(?:id|key|secret)|sign(?:ed|ature)|bearer|authorization|jsessionid|phpsessid|asp\\.net[_-]sessionid|sid|jwt'
|
|
139
|
-
// eslint-disable-next-line max-len
|
|
139
|
+
// eslint-disable-next-line @stylistic/js/max-len
|
|
140
140
|
const defaultWafObfuscatorValueRegex = '(?i)(?:p(?:ass)?w(?:or)?d|pass(?:[_-]?phrase)?|secret(?:[_-]?key)?|(?:(?:api|private|public|access)[_-]?)key(?:[_-]?id)?|(?:(?:auth|access|id|refresh)[_-]?)?token|consumer[_-]?(?:id|key|secret)|sign(?:ed|ature)?|auth(?:entication|orization)?|jsessionid|phpsessid|asp\\.net(?:[_-]|-)sessionid|sid|jwt)(?:\\s*=[^;]|"\\s*:\\s*"[^"]+")|bearer\\s+[a-z0-9\\._\\-]+|token:[a-z0-9]{13}|gh[opsu]_[0-9a-zA-Z]{36}|ey[I-L][\\w=-]+\\.ey[I-L][\\w=-]+(?:\\.[\\w.+\\/=-]+)?|[\\-]{5}BEGIN[a-z\\s]+PRIVATE\\sKEY[\\-]{5}[^\\-]+[\\-]{5}END[a-z\\s]+PRIVATE\\sKEY|ssh-rsa\\s*[a-z0-9\\/\\.+]{100,}'
|
|
141
141
|
const runtimeId = uuid()
|
|
142
142
|
|
|
@@ -145,7 +145,7 @@ function maybeFile (filepath) {
|
|
|
145
145
|
try {
|
|
146
146
|
return fs.readFileSync(filepath, 'utf8')
|
|
147
147
|
} catch (e) {
|
|
148
|
-
log.error(e)
|
|
148
|
+
log.error('Error reading file %s', filepath, e)
|
|
149
149
|
return undefined
|
|
150
150
|
}
|
|
151
151
|
}
|
|
@@ -378,7 +378,7 @@ class Config {
|
|
|
378
378
|
} catch (e) {
|
|
379
379
|
// Only log error if the user has set a git.properties path
|
|
380
380
|
if (process.env.DD_GIT_PROPERTIES_FILE) {
|
|
381
|
-
log.error(e)
|
|
381
|
+
log.error('Error reading DD_GIT_PROPERTIES_FILE: %s', DD_GIT_PROPERTIES_FILE, e)
|
|
382
382
|
}
|
|
383
383
|
}
|
|
384
384
|
if (gitPropertiesString) {
|
|
@@ -449,8 +449,7 @@ class Config {
|
|
|
449
449
|
this._setValue(defaults, 'appsec.blockedTemplateHtml', undefined)
|
|
450
450
|
this._setValue(defaults, 'appsec.blockedTemplateJson', undefined)
|
|
451
451
|
this._setValue(defaults, 'appsec.enabled', undefined)
|
|
452
|
-
this._setValue(defaults, 'appsec.eventTracking.
|
|
453
|
-
this._setValue(defaults, 'appsec.eventTracking.mode', 'safe')
|
|
452
|
+
this._setValue(defaults, 'appsec.eventTracking.mode', 'identification')
|
|
454
453
|
this._setValue(defaults, 'appsec.obfuscatorKeyRegex', defaultWafObfuscatorKeyRegex)
|
|
455
454
|
this._setValue(defaults, 'appsec.obfuscatorValueRegex', defaultWafObfuscatorValueRegex)
|
|
456
455
|
this._setValue(defaults, 'appsec.rasp.enabled', true)
|
|
@@ -467,7 +466,7 @@ class Config {
|
|
|
467
466
|
this._setValue(defaults, 'ciVisibilityTestSessionName', '')
|
|
468
467
|
this._setValue(defaults, 'clientIpEnabled', false)
|
|
469
468
|
this._setValue(defaults, 'clientIpHeader', null)
|
|
470
|
-
this._setValue(defaults, 'crashtracking.enabled',
|
|
469
|
+
this._setValue(defaults, 'crashtracking.enabled', true)
|
|
471
470
|
this._setValue(defaults, 'codeOriginForSpans.enabled', false)
|
|
472
471
|
this._setValue(defaults, 'dbmPropagationMode', 'disabled')
|
|
473
472
|
this._setValue(defaults, 'dogstatsd.hostname', '127.0.0.1')
|
|
@@ -486,6 +485,7 @@ class Config {
|
|
|
486
485
|
this._setValue(defaults, 'headerTags', [])
|
|
487
486
|
this._setValue(defaults, 'hostname', '127.0.0.1')
|
|
488
487
|
this._setValue(defaults, 'iast.cookieFilterPattern', '.{32,}')
|
|
488
|
+
this._setValue(defaults, 'iast.dbRowsToTaint', 1)
|
|
489
489
|
this._setValue(defaults, 'iast.deduplicationEnabled', true)
|
|
490
490
|
this._setValue(defaults, 'iast.enabled', false)
|
|
491
491
|
this._setValue(defaults, 'iast.maxConcurrentRequests', 2)
|
|
@@ -553,7 +553,7 @@ class Config {
|
|
|
553
553
|
this._setValue(defaults, 'telemetry.dependencyCollection', true)
|
|
554
554
|
this._setValue(defaults, 'telemetry.enabled', true)
|
|
555
555
|
this._setValue(defaults, 'telemetry.heartbeatInterval', 60000)
|
|
556
|
-
this._setValue(defaults, 'telemetry.logCollection',
|
|
556
|
+
this._setValue(defaults, 'telemetry.logCollection', true)
|
|
557
557
|
this._setValue(defaults, 'telemetry.metrics', true)
|
|
558
558
|
this._setValue(defaults, 'traceEnabled', true)
|
|
559
559
|
this._setValue(defaults, 'traceId128BitGenerationEnabled', true)
|
|
@@ -566,6 +566,7 @@ class Config {
|
|
|
566
566
|
this._setValue(defaults, 'url', undefined)
|
|
567
567
|
this._setValue(defaults, 'version', pkg.version)
|
|
568
568
|
this._setValue(defaults, 'instrumentation_config_id', undefined)
|
|
569
|
+
this._setValue(defaults, 'aws.dynamoDb.tablePrimaryKeys', undefined)
|
|
569
570
|
}
|
|
570
571
|
|
|
571
572
|
_applyEnvironment () {
|
|
@@ -574,6 +575,7 @@ class Config {
|
|
|
574
575
|
DD_AGENT_HOST,
|
|
575
576
|
DD_API_SECURITY_ENABLED,
|
|
576
577
|
DD_API_SECURITY_SAMPLE_DELAY,
|
|
578
|
+
DD_APPSEC_AUTO_USER_INSTRUMENTATION_MODE,
|
|
577
579
|
DD_APPSEC_AUTOMATED_USER_EVENTS_TRACKING,
|
|
578
580
|
DD_APPSEC_ENABLED,
|
|
579
581
|
DD_APPSEC_GRAPHQL_BLOCKED_TEMPLATE_JSON,
|
|
@@ -589,11 +591,13 @@ class Config {
|
|
|
589
591
|
DD_APPSEC_RASP_ENABLED,
|
|
590
592
|
DD_APPSEC_TRACE_RATE_LIMIT,
|
|
591
593
|
DD_APPSEC_WAF_TIMEOUT,
|
|
594
|
+
DD_AWS_SDK_DYNAMODB_TABLE_PRIMARY_KEYS,
|
|
592
595
|
DD_CRASHTRACKING_ENABLED,
|
|
593
596
|
DD_CODE_ORIGIN_FOR_SPANS_ENABLED,
|
|
594
597
|
DD_DATA_STREAMS_ENABLED,
|
|
595
598
|
DD_DBM_PROPAGATION_MODE,
|
|
596
599
|
DD_DOGSTATSD_HOSTNAME,
|
|
600
|
+
DD_DOGSTATSD_HOST,
|
|
597
601
|
DD_DOGSTATSD_PORT,
|
|
598
602
|
DD_DYNAMIC_INSTRUMENTATION_ENABLED,
|
|
599
603
|
DD_ENV,
|
|
@@ -604,6 +608,7 @@ class Config {
|
|
|
604
608
|
DD_GRPC_SERVER_ERROR_STATUSES,
|
|
605
609
|
JEST_WORKER_ID,
|
|
606
610
|
DD_IAST_COOKIE_FILTER_PATTERN,
|
|
611
|
+
DD_IAST_DB_ROWS_TO_TAINT,
|
|
607
612
|
DD_IAST_DEDUPLICATION_ENABLED,
|
|
608
613
|
DD_IAST_ENABLED,
|
|
609
614
|
DD_IAST_MAX_CONCURRENT_REQUESTS,
|
|
@@ -711,11 +716,10 @@ class Config {
|
|
|
711
716
|
this._setValue(env, 'appsec.blockedTemplateJson', maybeFile(DD_APPSEC_HTTP_BLOCKED_TEMPLATE_JSON))
|
|
712
717
|
this._envUnprocessed['appsec.blockedTemplateJson'] = DD_APPSEC_HTTP_BLOCKED_TEMPLATE_JSON
|
|
713
718
|
this._setBoolean(env, 'appsec.enabled', DD_APPSEC_ENABLED)
|
|
714
|
-
|
|
715
|
-
|
|
716
|
-
|
|
717
|
-
|
|
718
|
-
}
|
|
719
|
+
this._setString(env, 'appsec.eventTracking.mode', coalesce(
|
|
720
|
+
DD_APPSEC_AUTO_USER_INSTRUMENTATION_MODE,
|
|
721
|
+
DD_APPSEC_AUTOMATED_USER_EVENTS_TRACKING // TODO: remove in next major
|
|
722
|
+
))
|
|
719
723
|
this._setString(env, 'appsec.obfuscatorKeyRegex', DD_APPSEC_OBFUSCATION_PARAMETER_KEY_REGEXP)
|
|
720
724
|
this._setString(env, 'appsec.obfuscatorValueRegex', DD_APPSEC_OBFUSCATION_PARAMETER_VALUE_REGEXP)
|
|
721
725
|
this._setBoolean(env, 'appsec.rasp.enabled', DD_APPSEC_RASP_ENABLED)
|
|
@@ -739,7 +743,7 @@ class Config {
|
|
|
739
743
|
this._setBoolean(env, 'crashtracking.enabled', DD_CRASHTRACKING_ENABLED)
|
|
740
744
|
this._setBoolean(env, 'codeOriginForSpans.enabled', DD_CODE_ORIGIN_FOR_SPANS_ENABLED)
|
|
741
745
|
this._setString(env, 'dbmPropagationMode', DD_DBM_PROPAGATION_MODE)
|
|
742
|
-
this._setString(env, 'dogstatsd.hostname', DD_DOGSTATSD_HOSTNAME)
|
|
746
|
+
this._setString(env, 'dogstatsd.hostname', DD_DOGSTATSD_HOST || DD_DOGSTATSD_HOSTNAME)
|
|
743
747
|
this._setString(env, 'dogstatsd.port', DD_DOGSTATSD_PORT)
|
|
744
748
|
this._setBoolean(env, 'dsmEnabled', DD_DATA_STREAMS_ENABLED)
|
|
745
749
|
this._setBoolean(env, 'dynamicInstrumentationEnabled', DD_DYNAMIC_INSTRUMENTATION_ENABLED)
|
|
@@ -757,6 +761,7 @@ class Config {
|
|
|
757
761
|
this._setArray(env, 'headerTags', DD_TRACE_HEADER_TAGS)
|
|
758
762
|
this._setString(env, 'hostname', coalesce(DD_AGENT_HOST, DD_TRACE_AGENT_HOSTNAME))
|
|
759
763
|
this._setString(env, 'iast.cookieFilterPattern', DD_IAST_COOKIE_FILTER_PATTERN)
|
|
764
|
+
this._setValue(env, 'iast.dbRowsToTaint', maybeInt(DD_IAST_DB_ROWS_TO_TAINT))
|
|
760
765
|
this._setBoolean(env, 'iast.deduplicationEnabled', DD_IAST_DEDUPLICATION_ENABLED)
|
|
761
766
|
this._setBoolean(env, 'iast.enabled', DD_IAST_ENABLED)
|
|
762
767
|
this._setValue(env, 'iast.maxConcurrentRequests', maybeInt(DD_IAST_MAX_CONCURRENT_REQUESTS))
|
|
@@ -876,6 +881,7 @@ class Config {
|
|
|
876
881
|
this._setBoolean(env, 'tracing', DD_TRACING_ENABLED)
|
|
877
882
|
this._setString(env, 'version', DD_VERSION || tags.version)
|
|
878
883
|
this._setBoolean(env, 'inferredProxyServicesEnabled', DD_TRACE_INFERRED_PROXY_SERVICES_ENABLED)
|
|
884
|
+
this._setString(env, 'aws.dynamoDb.tablePrimaryKeys', DD_AWS_SDK_DYNAMODB_TABLE_PRIMARY_KEYS)
|
|
879
885
|
}
|
|
880
886
|
|
|
881
887
|
_applyOptions (options) {
|
|
@@ -894,12 +900,7 @@ class Config {
|
|
|
894
900
|
this._setValue(opts, 'appsec.blockedTemplateJson', maybeFile(options.appsec.blockedTemplateJson))
|
|
895
901
|
this._optsUnprocessed['appsec.blockedTemplateJson'] = options.appsec.blockedTemplateJson
|
|
896
902
|
this._setBoolean(opts, 'appsec.enabled', options.appsec.enabled)
|
|
897
|
-
|
|
898
|
-
if (eventTracking) {
|
|
899
|
-
eventTracking = eventTracking.toLowerCase()
|
|
900
|
-
this._setValue(opts, 'appsec.eventTracking.enabled', ['extended', 'safe'].includes(eventTracking))
|
|
901
|
-
this._setValue(opts, 'appsec.eventTracking.mode', eventTracking)
|
|
902
|
-
}
|
|
903
|
+
this._setString(opts, 'appsec.eventTracking.mode', options.appsec.eventTracking?.mode)
|
|
903
904
|
this._setString(opts, 'appsec.obfuscatorKeyRegex', options.appsec.obfuscatorKeyRegex)
|
|
904
905
|
this._setString(opts, 'appsec.obfuscatorValueRegex', options.appsec.obfuscatorValueRegex)
|
|
905
906
|
this._setBoolean(opts, 'appsec.rasp.enabled', options.appsec.rasp?.enabled)
|
|
@@ -937,6 +938,7 @@ class Config {
|
|
|
937
938
|
this._setArray(opts, 'headerTags', options.headerTags)
|
|
938
939
|
this._setString(opts, 'hostname', options.hostname)
|
|
939
940
|
this._setString(opts, 'iast.cookieFilterPattern', options.iast?.cookieFilterPattern)
|
|
941
|
+
this._setValue(opts, 'iast.dbRowsToTaint', maybeInt(options.iast?.dbRowsToTaint))
|
|
940
942
|
this._setBoolean(opts, 'iast.deduplicationEnabled', options.iast && options.iast.deduplicationEnabled)
|
|
941
943
|
this._setBoolean(opts, 'iast.enabled',
|
|
942
944
|
options.iast && (options.iast === true || options.iast.enabled === true))
|
|
@@ -1141,16 +1143,6 @@ class Config {
|
|
|
1141
1143
|
calc['tracePropagationStyle.inject'] = calc['tracePropagationStyle.inject'] || defaultPropagationStyle
|
|
1142
1144
|
calc['tracePropagationStyle.extract'] = calc['tracePropagationStyle.extract'] || defaultPropagationStyle
|
|
1143
1145
|
}
|
|
1144
|
-
|
|
1145
|
-
const iastEnabled = coalesce(this._options['iast.enabled'], this._env['iast.enabled'])
|
|
1146
|
-
const profilingEnabled = coalesce(this._options['profiling.enabled'], this._env['profiling.enabled'])
|
|
1147
|
-
const injectionIncludesProfiler = (this._env.injectionEnabled || []).includes('profiler')
|
|
1148
|
-
if (iastEnabled || ['auto', 'true'].includes(profilingEnabled) || injectionIncludesProfiler) {
|
|
1149
|
-
this._setBoolean(calc, 'telemetry.logCollection', true)
|
|
1150
|
-
}
|
|
1151
|
-
if (this._env.injectionEnabled?.length > 0) {
|
|
1152
|
-
this._setBoolean(calc, 'crashtracking.enabled', true)
|
|
1153
|
-
}
|
|
1154
1146
|
}
|
|
1155
1147
|
|
|
1156
1148
|
_applyRemote (options) {
|
|
@@ -1288,7 +1280,7 @@ class Config {
|
|
|
1288
1280
|
// TODO: Deeply merge configurations.
|
|
1289
1281
|
// TODO: Move change tracking to telemetry.
|
|
1290
1282
|
// for telemetry reporting, `name`s in `containers` need to be keys from:
|
|
1291
|
-
// eslint-disable-next-line max-len
|
|
1283
|
+
// eslint-disable-next-line @stylistic/js/max-len
|
|
1292
1284
|
// https://github.com/DataDog/dd-go/blob/prod/trace/apps/tracer-telemetry-intake/telemetry-payload/static/config_norm_rules.json
|
|
1293
1285
|
_merge () {
|
|
1294
1286
|
const containers = [this._remote, this._options, this._env, this._calculated, this._defaults]
|
|
@@ -47,6 +47,7 @@ module.exports = {
|
|
|
47
47
|
SCHEMA_NAME: 'schema.name',
|
|
48
48
|
GRPC_CLIENT_ERROR_STATUSES: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16],
|
|
49
49
|
GRPC_SERVER_ERROR_STATUSES: [2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16],
|
|
50
|
+
DYNAMODB_PTR_KIND: 'aws.dynamodb.item',
|
|
50
51
|
S3_PTR_KIND: 'aws.s3.object',
|
|
51
52
|
SPAN_POINTER_DIRECTION: Object.freeze({
|
|
52
53
|
UPSTREAM: 'u',
|
|
@@ -20,7 +20,7 @@ class Crashtracker {
|
|
|
20
20
|
binding.updateConfig(this._getConfig(config))
|
|
21
21
|
binding.updateMetadata(this._getMetadata(config))
|
|
22
22
|
} catch (e) {
|
|
23
|
-
log.error(e)
|
|
23
|
+
log.error('Error configuring crashtracker', e)
|
|
24
24
|
}
|
|
25
25
|
}
|
|
26
26
|
|
|
@@ -36,7 +36,7 @@ class Crashtracker {
|
|
|
36
36
|
this._getMetadata(config)
|
|
37
37
|
)
|
|
38
38
|
} catch (e) {
|
|
39
|
-
log.error(e)
|
|
39
|
+
log.error('Error initialising crashtracker', e)
|
|
40
40
|
}
|
|
41
41
|
}
|
|
42
42
|
|
|
@@ -79,6 +79,7 @@ class Crashtracker {
|
|
|
79
79
|
'language:javascript',
|
|
80
80
|
`library_version:${pkg.version}`,
|
|
81
81
|
'runtime:nodejs',
|
|
82
|
+
`runtime_version:${process.versions.node}`,
|
|
82
83
|
'severity:crash'
|
|
83
84
|
]
|
|
84
85
|
}
|
|
@@ -1,7 +1,5 @@
|
|
|
1
1
|
const os = require('os')
|
|
2
2
|
const pkg = require('../../../../package.json')
|
|
3
|
-
// Message pack int encoding is done in big endian, but data streams uses little endian
|
|
4
|
-
const Uint64 = require('int64-buffer').Uint64BE
|
|
5
3
|
|
|
6
4
|
const { LogCollapsingLowestDenseDDSketch } = require('@datadog/sketches-js')
|
|
7
5
|
const { DsmPathwayCodec } = require('./pathway')
|
|
@@ -19,8 +17,8 @@ const HIGH_ACCURACY_DISTRIBUTION = 0.0075
|
|
|
19
17
|
|
|
20
18
|
class StatsPoint {
|
|
21
19
|
constructor (hash, parentHash, edgeTags) {
|
|
22
|
-
this.hash =
|
|
23
|
-
this.parentHash =
|
|
20
|
+
this.hash = hash.readBigUInt64BE()
|
|
21
|
+
this.parentHash = parentHash.readBigUInt64BE()
|
|
24
22
|
this.edgeTags = edgeTags
|
|
25
23
|
this.edgeLatency = new LogCollapsingLowestDenseDDSketch(HIGH_ACCURACY_DISTRIBUTION)
|
|
26
24
|
this.pathwayLatency = new LogCollapsingLowestDenseDDSketch(HIGH_ACCURACY_DISTRIBUTION)
|
|
@@ -344,8 +342,8 @@ class DataStreamsProcessor {
|
|
|
344
342
|
backlogs.push(backlog.encode())
|
|
345
343
|
}
|
|
346
344
|
serializedBuckets.push({
|
|
347
|
-
Start:
|
|
348
|
-
Duration:
|
|
345
|
+
Start: BigInt(timeNs),
|
|
346
|
+
Duration: BigInt(this.bucketSizeNs),
|
|
349
347
|
Stats: points,
|
|
350
348
|
Backlogs: backlogs
|
|
351
349
|
})
|
|
@@ -2,9 +2,10 @@ const pkg = require('../../../../package.json')
|
|
|
2
2
|
const log = require('../log')
|
|
3
3
|
const request = require('../exporters/common/request')
|
|
4
4
|
const { URL, format } = require('url')
|
|
5
|
-
const
|
|
5
|
+
const { MsgpackEncoder } = require('../msgpack')
|
|
6
6
|
const zlib = require('zlib')
|
|
7
|
-
|
|
7
|
+
|
|
8
|
+
const msgpack = new MsgpackEncoder()
|
|
8
9
|
|
|
9
10
|
function makeRequest (data, url, cb) {
|
|
10
11
|
const options = {
|
|
@@ -41,17 +42,17 @@ class DataStreamsWriter {
|
|
|
41
42
|
log.debug(() => `Maximum number of active requests reached. Payload discarded: ${JSON.stringify(payload)}`)
|
|
42
43
|
return
|
|
43
44
|
}
|
|
44
|
-
const encodedPayload = msgpack.encode(payload
|
|
45
|
+
const encodedPayload = msgpack.encode(payload)
|
|
45
46
|
|
|
46
47
|
zlib.gzip(encodedPayload, { level: 1 }, (err, compressedData) => {
|
|
47
48
|
if (err) {
|
|
48
|
-
log.error(err)
|
|
49
|
+
log.error('Error zipping datastream', err)
|
|
49
50
|
return
|
|
50
51
|
}
|
|
51
52
|
makeRequest(compressedData, this._url, (err, res) => {
|
|
52
53
|
log.debug(`Response from the agent: ${res}`)
|
|
53
54
|
if (err) {
|
|
54
|
-
log.error(err)
|
|
55
|
+
log.error('Error sending datastream', err)
|
|
55
56
|
}
|
|
56
57
|
})
|
|
57
58
|
})
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
'use strict'
|
|
2
|
+
|
|
3
|
+
const session = require('./session')
|
|
4
|
+
const { MAX_SNAPSHOTS_PER_SECOND_PER_PROBE, MAX_NON_SNAPSHOTS_PER_SECOND_PER_PROBE } = require('./defaults')
|
|
5
|
+
const { findScriptFromPartialPath, probes, breakpoints } = require('./state')
|
|
6
|
+
const log = require('../../log')
|
|
7
|
+
|
|
8
|
+
let sessionStarted = false
|
|
9
|
+
|
|
10
|
+
module.exports = {
|
|
11
|
+
addBreakpoint,
|
|
12
|
+
removeBreakpoint
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
async function addBreakpoint (probe) {
|
|
16
|
+
if (!sessionStarted) await start()
|
|
17
|
+
|
|
18
|
+
const file = probe.where.sourceFile
|
|
19
|
+
const line = Number(probe.where.lines[0]) // Tracer doesn't support multiple-line breakpoints
|
|
20
|
+
|
|
21
|
+
// Optimize for sending data to /debugger/v1/input endpoint
|
|
22
|
+
probe.location = { file, lines: [String(line)] }
|
|
23
|
+
delete probe.where
|
|
24
|
+
|
|
25
|
+
// Optimize for fast calculations when probe is hit
|
|
26
|
+
const snapshotsPerSecond = probe.sampling.snapshotsPerSecond ?? (probe.captureSnapshot
|
|
27
|
+
? MAX_SNAPSHOTS_PER_SECOND_PER_PROBE
|
|
28
|
+
: MAX_NON_SNAPSHOTS_PER_SECOND_PER_PROBE)
|
|
29
|
+
probe.sampling.nsBetweenSampling = BigInt(1 / snapshotsPerSecond * 1e9)
|
|
30
|
+
probe.lastCaptureNs = 0n
|
|
31
|
+
|
|
32
|
+
// TODO: Inbetween `await session.post('Debugger.enable')` and here, the scripts are parsed and cached.
|
|
33
|
+
// Maybe there's a race condition here or maybe we're guraenteed that `await session.post('Debugger.enable')` will
|
|
34
|
+
// not continue untill all scripts have been parsed?
|
|
35
|
+
const script = findScriptFromPartialPath(file)
|
|
36
|
+
if (!script) throw new Error(`No loaded script found for ${file} (probe: ${probe.id}, version: ${probe.version})`)
|
|
37
|
+
const [path, scriptId] = script
|
|
38
|
+
|
|
39
|
+
log.debug(
|
|
40
|
+
'[debugger:devtools_client] Adding breakpoint at %s:%d (probe: %s, version: %d)',
|
|
41
|
+
path, line, probe.id, probe.version
|
|
42
|
+
)
|
|
43
|
+
|
|
44
|
+
const { breakpointId } = await session.post('Debugger.setBreakpoint', {
|
|
45
|
+
location: {
|
|
46
|
+
scriptId,
|
|
47
|
+
lineNumber: line - 1 // Beware! lineNumber is zero-indexed
|
|
48
|
+
}
|
|
49
|
+
})
|
|
50
|
+
|
|
51
|
+
probes.set(probe.id, breakpointId)
|
|
52
|
+
breakpoints.set(breakpointId, probe)
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
async function removeBreakpoint ({ id }) {
|
|
56
|
+
if (!sessionStarted) {
|
|
57
|
+
// We should not get in this state, but abort if we do, so the code doesn't fail unexpected
|
|
58
|
+
throw Error(`Cannot remove probe ${id}: Debugger not started`)
|
|
59
|
+
}
|
|
60
|
+
if (!probes.has(id)) {
|
|
61
|
+
throw Error(`Unknown probe id: ${id}`)
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
const breakpointId = probes.get(id)
|
|
65
|
+
await session.post('Debugger.removeBreakpoint', { breakpointId })
|
|
66
|
+
probes.delete(id)
|
|
67
|
+
breakpoints.delete(breakpointId)
|
|
68
|
+
|
|
69
|
+
if (breakpoints.size === 0) await stop()
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
async function start () {
|
|
73
|
+
sessionStarted = true
|
|
74
|
+
return session.post('Debugger.enable') // return instead of await to reduce number of promises created
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
async function stop () {
|
|
78
|
+
sessionStarted = false
|
|
79
|
+
return session.post('Debugger.disable') // return instead of await to reduce number of promises created
|
|
80
|
+
}
|
|
@@ -15,7 +15,9 @@ const config = module.exports = {
|
|
|
15
15
|
updateUrl(parentConfig)
|
|
16
16
|
|
|
17
17
|
configPort.on('message', updateUrl)
|
|
18
|
-
configPort.on('messageerror', (err) =>
|
|
18
|
+
configPort.on('messageerror', (err) =>
|
|
19
|
+
log.error('[debugger:devtools_client] received "messageerror" on config port', err)
|
|
20
|
+
)
|
|
19
21
|
|
|
20
22
|
function updateUrl (updates) {
|
|
21
23
|
config.url = updates.url || format({
|
|
@@ -13,28 +13,59 @@ const { version } = require('../../../../../package.json')
|
|
|
13
13
|
|
|
14
14
|
require('./remote_config')
|
|
15
15
|
|
|
16
|
+
// Expression to run on a call frame of the paused thread to get its active trace and span id.
|
|
17
|
+
const expression = `
|
|
18
|
+
const context = global.require('dd-trace').scope().active()?.context();
|
|
19
|
+
({ trace_id: context?.toTraceId(), span_id: context?.toSpanId() })
|
|
20
|
+
`
|
|
21
|
+
|
|
16
22
|
// There doesn't seem to be an official standard for the content of these fields, so we're just populating them with
|
|
17
23
|
// something that should be useful to a Node.js developer.
|
|
18
24
|
const threadId = parentThreadId === 0 ? `pid:${process.pid}` : `pid:${process.pid};tid:${parentThreadId}`
|
|
19
25
|
const threadName = parentThreadId === 0 ? 'MainThread' : `WorkerThread:${parentThreadId}`
|
|
20
26
|
|
|
27
|
+
// WARNING: The code above the line `await session.post('Debugger.resume')` is highly optimized. Please edit with care!
|
|
21
28
|
session.on('Debugger.paused', async ({ params }) => {
|
|
22
29
|
const start = process.hrtime.bigint()
|
|
23
|
-
const timestamp = Date.now()
|
|
24
30
|
|
|
25
31
|
let captureSnapshotForProbe = null
|
|
26
32
|
let maxReferenceDepth, maxCollectionSize, maxFieldCount, maxLength
|
|
27
|
-
|
|
33
|
+
|
|
34
|
+
// V8 doesn't allow seting more than one breakpoint at a specific location, however, it's possible to set two
|
|
35
|
+
// breakpoints just next to eachother that will "snap" to the same logical location, which in turn will be hit at the
|
|
36
|
+
// same time. E.g. index.js:1:1 and index.js:1:2.
|
|
37
|
+
// TODO: Investigate if it will improve performance to create a fast-path for when there's only a single breakpoint
|
|
38
|
+
let sampled = false
|
|
39
|
+
const length = params.hitBreakpoints.length
|
|
40
|
+
let probes = new Array(length)
|
|
41
|
+
for (let i = 0; i < length; i++) {
|
|
42
|
+
const id = params.hitBreakpoints[i]
|
|
28
43
|
const probe = breakpoints.get(id)
|
|
29
|
-
|
|
44
|
+
|
|
45
|
+
if (start - probe.lastCaptureNs < probe.sampling.nsBetweenSampling) {
|
|
46
|
+
continue
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
sampled = true
|
|
50
|
+
probe.lastCaptureNs = start
|
|
51
|
+
|
|
52
|
+
if (probe.captureSnapshot === true) {
|
|
30
53
|
captureSnapshotForProbe = probe
|
|
31
54
|
maxReferenceDepth = highestOrUndefined(probe.capture.maxReferenceDepth, maxReferenceDepth)
|
|
32
55
|
maxCollectionSize = highestOrUndefined(probe.capture.maxCollectionSize, maxCollectionSize)
|
|
33
56
|
maxFieldCount = highestOrUndefined(probe.capture.maxFieldCount, maxFieldCount)
|
|
34
57
|
maxLength = highestOrUndefined(probe.capture.maxLength, maxLength)
|
|
35
58
|
}
|
|
36
|
-
|
|
37
|
-
|
|
59
|
+
|
|
60
|
+
probes[i] = probe
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
if (sampled === false) {
|
|
64
|
+
return session.post('Debugger.resume')
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
const timestamp = Date.now()
|
|
68
|
+
const dd = await getDD(params.callFrames[0].callFrameId)
|
|
38
69
|
|
|
39
70
|
let processLocalState
|
|
40
71
|
if (captureSnapshotForProbe !== null) {
|
|
@@ -54,7 +85,13 @@ session.on('Debugger.paused', async ({ params }) => {
|
|
|
54
85
|
await session.post('Debugger.resume')
|
|
55
86
|
const diff = process.hrtime.bigint() - start // TODO: Recored as telemetry (DEBUG-2858)
|
|
56
87
|
|
|
57
|
-
log.debug(
|
|
88
|
+
log.debug(
|
|
89
|
+
'[debugger:devtools_client] Finished processing breakpoints - main thread paused for: %d ms',
|
|
90
|
+
Number(diff) / 1000000
|
|
91
|
+
)
|
|
92
|
+
|
|
93
|
+
// Due to the highly optimized algorithm above, the `probes` array might have gaps
|
|
94
|
+
probes = probes.filter((probe) => !!probe)
|
|
58
95
|
|
|
59
96
|
const logger = {
|
|
60
97
|
// We can safely use `location.file` from the first probe in the array, since all probes hit by `hitBreakpoints`
|
|
@@ -92,8 +129,8 @@ session.on('Debugger.paused', async ({ params }) => {
|
|
|
92
129
|
}
|
|
93
130
|
|
|
94
131
|
// TODO: Process template (DEBUG-2628)
|
|
95
|
-
send(probe.template, logger, snapshot, (err) => {
|
|
96
|
-
if (err) log.error(err)
|
|
132
|
+
send(probe.template, logger, dd, snapshot, (err) => {
|
|
133
|
+
if (err) log.error('Debugger error', err)
|
|
97
134
|
else ackEmitting(probe)
|
|
98
135
|
})
|
|
99
136
|
}
|
|
@@ -102,3 +139,21 @@ session.on('Debugger.paused', async ({ params }) => {
|
|
|
102
139
|
function highestOrUndefined (num, max) {
|
|
103
140
|
return num === undefined ? max : Math.max(num, max ?? 0)
|
|
104
141
|
}
|
|
142
|
+
|
|
143
|
+
async function getDD (callFrameId) {
|
|
144
|
+
const { result } = await session.post('Debugger.evaluateOnCallFrame', {
|
|
145
|
+
callFrameId,
|
|
146
|
+
expression,
|
|
147
|
+
returnByValue: true,
|
|
148
|
+
includeCommandLineAPI: true
|
|
149
|
+
})
|
|
150
|
+
|
|
151
|
+
if (result?.value?.trace_id === undefined) {
|
|
152
|
+
if (result?.subtype === 'error') {
|
|
153
|
+
log.error('[debugger:devtools_client] Error getting trace/span id:', result.description)
|
|
154
|
+
}
|
|
155
|
+
return
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
return result.value
|
|
159
|
+
}
|
|
@@ -1,13 +1,10 @@
|
|
|
1
1
|
'use strict'
|
|
2
2
|
|
|
3
3
|
const { workerData: { rcPort } } = require('node:worker_threads')
|
|
4
|
-
const {
|
|
5
|
-
const session = require('./session')
|
|
4
|
+
const { addBreakpoint, removeBreakpoint } = require('./breakpoints')
|
|
6
5
|
const { ackReceived, ackInstalled, ackError } = require('./status')
|
|
7
6
|
const log = require('../../log')
|
|
8
7
|
|
|
9
|
-
let sessionStarted = false
|
|
10
|
-
|
|
11
8
|
// Example log line probe (simplified):
|
|
12
9
|
// {
|
|
13
10
|
// id: '100c9a5c-45ad-49dc-818b-c570d31e11d1',
|
|
@@ -44,20 +41,13 @@ rcPort.on('message', async ({ action, conf: probe, ackId }) => {
|
|
|
44
41
|
ackError(err, probe)
|
|
45
42
|
}
|
|
46
43
|
})
|
|
47
|
-
rcPort.on('messageerror', (err) => log.error(err))
|
|
48
|
-
|
|
49
|
-
async function start () {
|
|
50
|
-
sessionStarted = true
|
|
51
|
-
return session.post('Debugger.enable') // return instead of await to reduce number of promises created
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
async function stop () {
|
|
55
|
-
sessionStarted = false
|
|
56
|
-
return session.post('Debugger.disable') // return instead of await to reduce number of promises created
|
|
57
|
-
}
|
|
44
|
+
rcPort.on('messageerror', (err) => log.error('[debugger:devtools_client] received "messageerror" on RC port', err))
|
|
58
45
|
|
|
59
46
|
async function processMsg (action, probe) {
|
|
60
|
-
log.debug(
|
|
47
|
+
log.debug(
|
|
48
|
+
'[debugger:devtools_client] Received request to %s %s probe (id: %s, version: %d)',
|
|
49
|
+
action, probe.type, probe.id, probe.version
|
|
50
|
+
)
|
|
61
51
|
|
|
62
52
|
if (action !== 'unapply') ackReceived(probe)
|
|
63
53
|
|
|
@@ -66,7 +56,7 @@ async function processMsg (action, probe) {
|
|
|
66
56
|
}
|
|
67
57
|
if (!probe.where.sourceFile && !probe.where.lines) {
|
|
68
58
|
throw new Error(
|
|
69
|
-
// eslint-disable-next-line max-len
|
|
59
|
+
// eslint-disable-next-line @stylistic/js/max-len
|
|
70
60
|
`Unsupported probe insertion point! Only line-based probes are supported (id: ${probe.id}, version: ${probe.version})`
|
|
71
61
|
)
|
|
72
62
|
}
|
|
@@ -90,15 +80,17 @@ async function processMsg (action, probe) {
|
|
|
90
80
|
break
|
|
91
81
|
case 'apply':
|
|
92
82
|
await addBreakpoint(probe)
|
|
83
|
+
ackInstalled(probe)
|
|
93
84
|
break
|
|
94
85
|
case 'modify':
|
|
95
86
|
// TODO: Modify existing probe instead of removing it (DEBUG-2817)
|
|
96
87
|
await removeBreakpoint(probe)
|
|
97
88
|
await addBreakpoint(probe)
|
|
89
|
+
ackInstalled(probe) // TODO: Should we also send ackInstalled when modifying a probe?
|
|
98
90
|
break
|
|
99
91
|
default:
|
|
100
92
|
throw new Error(
|
|
101
|
-
// eslint-disable-next-line max-len
|
|
93
|
+
// eslint-disable-next-line @stylistic/js/max-len
|
|
102
94
|
`Cannot process probe ${probe.id} (version: ${probe.version}) - unknown remote configuration action: ${action}`
|
|
103
95
|
)
|
|
104
96
|
}
|
|
@@ -107,55 +99,6 @@ async function processMsg (action, probe) {
|
|
|
107
99
|
}
|
|
108
100
|
}
|
|
109
101
|
|
|
110
|
-
async function addBreakpoint (probe) {
|
|
111
|
-
if (!sessionStarted) await start()
|
|
112
|
-
|
|
113
|
-
const file = probe.where.sourceFile
|
|
114
|
-
const line = Number(probe.where.lines[0]) // Tracer doesn't support multiple-line breakpoints
|
|
115
|
-
|
|
116
|
-
// Optimize for sending data to /debugger/v1/input endpoint
|
|
117
|
-
probe.location = { file, lines: [String(line)] }
|
|
118
|
-
delete probe.where
|
|
119
|
-
|
|
120
|
-
// TODO: Inbetween `await session.post('Debugger.enable')` and here, the scripts are parsed and cached.
|
|
121
|
-
// Maybe there's a race condition here or maybe we're guraenteed that `await session.post('Debugger.enable')` will
|
|
122
|
-
// not continue untill all scripts have been parsed?
|
|
123
|
-
const script = findScriptFromPartialPath(file)
|
|
124
|
-
if (!script) throw new Error(`No loaded script found for ${file} (probe: ${probe.id}, version: ${probe.version})`)
|
|
125
|
-
const [path, scriptId] = script
|
|
126
|
-
|
|
127
|
-
log.debug(`Adding breakpoint at ${path}:${line} (probe: ${probe.id}, version: ${probe.version})`)
|
|
128
|
-
|
|
129
|
-
const { breakpointId } = await session.post('Debugger.setBreakpoint', {
|
|
130
|
-
location: {
|
|
131
|
-
scriptId,
|
|
132
|
-
lineNumber: line - 1 // Beware! lineNumber is zero-indexed
|
|
133
|
-
}
|
|
134
|
-
})
|
|
135
|
-
|
|
136
|
-
probes.set(probe.id, breakpointId)
|
|
137
|
-
breakpoints.set(breakpointId, probe)
|
|
138
|
-
|
|
139
|
-
ackInstalled(probe)
|
|
140
|
-
}
|
|
141
|
-
|
|
142
|
-
async function removeBreakpoint ({ id }) {
|
|
143
|
-
if (!sessionStarted) {
|
|
144
|
-
// We should not get in this state, but abort if we do, so the code doesn't fail unexpected
|
|
145
|
-
throw Error(`Cannot remove probe ${id}: Debugger not started`)
|
|
146
|
-
}
|
|
147
|
-
if (!probes.has(id)) {
|
|
148
|
-
throw Error(`Unknown probe id: ${id}`)
|
|
149
|
-
}
|
|
150
|
-
|
|
151
|
-
const breakpointId = probes.get(id)
|
|
152
|
-
await session.post('Debugger.removeBreakpoint', { breakpointId })
|
|
153
|
-
probes.delete(id)
|
|
154
|
-
breakpoints.delete(breakpointId)
|
|
155
|
-
|
|
156
|
-
if (breakpoints.size === 0) await stop()
|
|
157
|
-
}
|
|
158
|
-
|
|
159
102
|
async function lock () {
|
|
160
103
|
if (lock.p) await lock.p
|
|
161
104
|
let resolve
|
|
@@ -22,7 +22,7 @@ const ddtags = [
|
|
|
22
22
|
|
|
23
23
|
const path = `/debugger/v1/input?${stringify({ ddtags })}`
|
|
24
24
|
|
|
25
|
-
function send (message, logger, snapshot, cb) {
|
|
25
|
+
function send (message, logger, dd, snapshot, cb) {
|
|
26
26
|
const opts = {
|
|
27
27
|
method: 'POST',
|
|
28
28
|
url: config.url,
|
|
@@ -36,6 +36,7 @@ function send (message, logger, snapshot, cb) {
|
|
|
36
36
|
service,
|
|
37
37
|
message,
|
|
38
38
|
logger,
|
|
39
|
+
dd,
|
|
39
40
|
'debugger.snapshot': snapshot
|
|
40
41
|
}
|
|
41
42
|
|
|
@@ -57,6 +57,6 @@ module.exports = {
|
|
|
57
57
|
session.on('Debugger.scriptParsed', ({ params }) => {
|
|
58
58
|
scriptUrls.set(params.scriptId, params.url)
|
|
59
59
|
if (params.url.startsWith('file:')) {
|
|
60
|
-
scriptIds.push([params.url, params.scriptId])
|
|
60
|
+
scriptIds.push([params.url, params.scriptId, params.sourceMapURL])
|
|
61
61
|
}
|
|
62
62
|
})
|