dd-trace 5.82.0 → 5.83.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 +78 -79
- package/ci/init.js +6 -6
- package/index.d.ts +152 -3
- package/loader-hook.mjs +1 -1
- package/package.json +58 -55
- package/packages/datadog-core/src/storage.js +7 -7
- package/packages/datadog-esbuild/index.js +6 -0
- package/packages/datadog-instrumentations/src/ai.js +7 -3
- package/packages/datadog-instrumentations/src/child_process.js +1 -1
- package/packages/datadog-instrumentations/src/cucumber.js +1 -1
- package/packages/datadog-instrumentations/src/graphql.js +1 -1
- package/packages/datadog-instrumentations/src/helpers/instrumentations.js +4 -3
- package/packages/datadog-instrumentations/src/helpers/register.js +3 -7
- package/packages/datadog-instrumentations/src/helpers/rewriter/index.js +1 -1
- package/packages/datadog-instrumentations/src/http/client.js +2 -2
- package/packages/datadog-instrumentations/src/jest.js +35 -14
- package/packages/datadog-instrumentations/src/koa.js +2 -1
- package/packages/datadog-instrumentations/src/light-my-request.js +2 -2
- package/packages/datadog-instrumentations/src/mocha/main.js +2 -2
- package/packages/datadog-instrumentations/src/mocha/worker.js +1 -1
- package/packages/datadog-instrumentations/src/mocha.js +1 -1
- package/packages/datadog-instrumentations/src/mysql.js +1 -1
- package/packages/datadog-instrumentations/src/mysql2.js +2 -2
- package/packages/datadog-instrumentations/src/net.js +13 -5
- package/packages/datadog-instrumentations/src/nyc.js +1 -1
- package/packages/datadog-instrumentations/src/otel-sdk-trace.js +4 -4
- package/packages/datadog-instrumentations/src/pg.js +4 -2
- package/packages/datadog-instrumentations/src/playwright.js +3 -3
- package/packages/datadog-instrumentations/src/selenium.js +2 -2
- package/packages/datadog-instrumentations/src/undici.js +12 -1
- package/packages/datadog-plugin-aws-sdk/src/base.js +4 -4
- package/packages/datadog-plugin-azure-event-hubs/src/producer.js +2 -2
- package/packages/datadog-plugin-azure-service-bus/src/producer.js +2 -2
- package/packages/datadog-plugin-cucumber/src/index.js +2 -2
- package/packages/datadog-plugin-cypress/src/cypress-plugin.js +2 -2
- package/packages/datadog-plugin-dd-trace-api/src/index.js +2 -2
- package/packages/datadog-plugin-express/src/code_origin.js +21 -15
- package/packages/datadog-plugin-fastify/src/code_origin.js +17 -4
- package/packages/datadog-plugin-jest/src/index.js +2 -2
- package/packages/datadog-plugin-mocha/src/index.js +2 -2
- package/packages/datadog-plugin-mongodb-core/src/index.js +2 -2
- package/packages/datadog-plugin-playwright/src/index.js +3 -3
- package/packages/datadog-plugin-undici/src/index.js +305 -2
- package/packages/datadog-plugin-vitest/src/index.js +5 -5
- package/packages/dd-trace/index.js +19 -0
- package/packages/dd-trace/src/appsec/iast/taint-tracking/rewriter.js +1 -1
- package/packages/dd-trace/src/appsec/rasp/index.js +2 -4
- package/packages/dd-trace/src/azure_metadata.js +8 -3
- package/packages/dd-trace/src/baggage.js +36 -11
- package/packages/dd-trace/src/ci-visibility/dynamic-instrumentation/index.js +5 -1
- package/packages/dd-trace/src/ci-visibility/early-flake-detection/get-known-tests.js +2 -2
- package/packages/dd-trace/src/ci-visibility/exporters/agentless/coverage-writer.js +2 -2
- package/packages/dd-trace/src/ci-visibility/exporters/agentless/di-logs-writer.js +2 -2
- package/packages/dd-trace/src/ci-visibility/exporters/agentless/writer.js +2 -2
- package/packages/dd-trace/src/ci-visibility/exporters/ci-visibility-exporter.js +3 -2
- package/packages/dd-trace/src/ci-visibility/exporters/git/git_metadata.js +3 -3
- package/packages/dd-trace/src/ci-visibility/exporters/test-worker/index.js +4 -4
- package/packages/dd-trace/src/ci-visibility/exporters/test-worker/writer.js +1 -1
- package/packages/dd-trace/src/ci-visibility/intelligent-test-runner/get-skippable-suites.js +2 -2
- package/packages/dd-trace/src/ci-visibility/log-submission/log-submission-plugin.js +4 -4
- package/packages/dd-trace/src/ci-visibility/requests/get-library-configuration.js +4 -4
- package/packages/dd-trace/src/ci-visibility/test-management/get-test-management-tests.js +2 -2
- package/packages/dd-trace/src/{config_defaults.js → config/defaults.js} +3 -3
- package/packages/dd-trace/src/{config-helper.js → config/helper.js} +88 -15
- package/packages/dd-trace/src/{config.js → config/index.js} +92 -45
- package/packages/dd-trace/src/config/remote_config.js +187 -19
- package/packages/dd-trace/src/{config_stable.js → config/stable.js} +20 -32
- package/packages/dd-trace/src/{supported-configurations.json → config/supported-configurations.json} +2 -0
- package/packages/dd-trace/src/crashtracking/crashtracker.js +1 -1
- package/packages/dd-trace/src/datastreams/processor.js +1 -1
- package/packages/dd-trace/src/datastreams/writer.js +1 -1
- package/packages/dd-trace/src/debugger/devtools_client/condition.js +1 -1
- package/packages/dd-trace/src/debugger/devtools_client/config.js +1 -1
- package/packages/dd-trace/src/debugger/devtools_client/send.js +3 -3
- package/packages/dd-trace/src/debugger/devtools_client/snapshot/constants.js +1 -1
- package/packages/dd-trace/src/debugger/index.js +83 -15
- package/packages/dd-trace/src/dogstatsd.js +2 -2
- package/packages/dd-trace/src/encode/0.4.js +2 -2
- package/packages/dd-trace/src/exporter.js +1 -1
- package/packages/dd-trace/src/exporters/agent/index.js +2 -4
- package/packages/dd-trace/src/exporters/agent/writer.js +9 -14
- package/packages/dd-trace/src/exporters/common/agent-info-exporter.js +1 -1
- package/packages/dd-trace/src/exporters/common/docker.js +2 -2
- package/packages/dd-trace/src/exporters/common/request.js +1 -1
- package/packages/dd-trace/src/exporters/common/util.js +2 -2
- package/packages/dd-trace/src/exporters/span-stats/index.js +1 -1
- package/packages/dd-trace/src/flare/index.js +1 -1
- package/packages/dd-trace/src/guardrails/telemetry.js +1 -1
- package/packages/dd-trace/src/index.js +4 -4
- package/packages/dd-trace/src/lambda/handler.js +2 -2
- package/packages/dd-trace/src/lambda/index.js +2 -2
- package/packages/dd-trace/src/lambda/runtime/patch.js +2 -2
- package/packages/dd-trace/src/lambda/runtime/ritm.js +2 -2
- package/packages/dd-trace/src/llmobs/constants/tags.js +8 -1
- package/packages/dd-trace/src/llmobs/index.js +2 -2
- package/packages/dd-trace/src/llmobs/noop.js +2 -0
- package/packages/dd-trace/src/llmobs/plugins/openai/index.js +3 -4
- package/packages/dd-trace/src/llmobs/sdk.js +33 -6
- package/packages/dd-trace/src/llmobs/span_processor.js +17 -7
- package/packages/dd-trace/src/llmobs/tagger.js +175 -1
- package/packages/dd-trace/src/llmobs/writers/base.js +116 -37
- package/packages/dd-trace/src/llmobs/writers/spans.js +4 -3
- package/packages/dd-trace/src/log/index.js +5 -5
- package/packages/dd-trace/src/noop/proxy.js +3 -3
- package/packages/dd-trace/src/openfeature/writers/base.js +7 -8
- package/packages/dd-trace/src/opentelemetry/otlp/otlp_http_exporter_base.js +2 -2
- package/packages/dd-trace/src/opentelemetry/tracer.js +48 -6
- package/packages/dd-trace/src/opentracing/propagation/text_map.js +45 -21
- package/packages/dd-trace/src/opentracing/span.js +4 -4
- package/packages/dd-trace/src/plugin_manager.js +8 -6
- package/packages/dd-trace/src/plugins/util/ci.js +5 -8
- package/packages/dd-trace/src/plugins/util/git-cache.js +3 -3
- package/packages/dd-trace/src/plugins/util/test.js +1 -1
- package/packages/dd-trace/src/plugins/util/user-provided-git.js +41 -43
- package/packages/dd-trace/src/profiler.js +4 -39
- package/packages/dd-trace/src/profiling/config.js +74 -31
- package/packages/dd-trace/src/profiling/exporter_cli.js +5 -5
- package/packages/dd-trace/src/profiling/exporters/agent.js +1 -1
- package/packages/dd-trace/src/profiling/exporters/event_serializer.js +9 -2
- package/packages/dd-trace/src/profiling/index.js +1 -1
- package/packages/dd-trace/src/profiling/libuv-size.js +1 -1
- package/packages/dd-trace/src/profiling/profiler.js +57 -2
- package/packages/dd-trace/src/proxy.js +34 -5
- package/packages/dd-trace/src/remote_config/capabilities.js +3 -0
- package/packages/dd-trace/src/remote_config/index.js +1 -1
- package/packages/dd-trace/src/ritm.js +8 -4
- package/packages/dd-trace/src/runtime_metrics/runtime_metrics.js +2 -2
- package/packages/dd-trace/src/serverless.js +2 -2
- package/packages/dd-trace/src/span_processor.js +2 -2
- package/packages/dd-trace/src/startup-log.js +6 -15
- package/packages/dd-trace/src/telemetry/endpoints.js +67 -5
- package/packages/dd-trace/src/telemetry/send-data.js +103 -4
- package/packages/dd-trace/src/telemetry/telemetry.js +229 -110
- /package/packages/dd-trace/src/{git_properties.js → config/git_properties.js} +0 -0
|
@@ -7,8 +7,8 @@ const Module = require('module')
|
|
|
7
7
|
const dc = require('dc-polyfill')
|
|
8
8
|
|
|
9
9
|
const parse = require('../../../vendor/dist/module-details-from-path')
|
|
10
|
-
const { getEnvironmentVariable } = require('../../dd-trace/src/config-helper')
|
|
11
10
|
const { isRelativeRequire } = require('../../datadog-instrumentations/src/helpers/shared-utils')
|
|
11
|
+
const { getEnvironmentVariable, getValueFromEnvSources } = require('./config/helper')
|
|
12
12
|
|
|
13
13
|
const origRequire = Module.prototype.require
|
|
14
14
|
// derived from require-in-the-middle@3 with tweaks
|
|
@@ -63,6 +63,7 @@ function Hook (modules, options, onrequire) {
|
|
|
63
63
|
*/
|
|
64
64
|
let filename
|
|
65
65
|
try {
|
|
66
|
+
// @ts-expect-error Module._resolveFilename is not typed
|
|
66
67
|
filename = Module._resolveFilename(request, this)
|
|
67
68
|
} catch {
|
|
68
69
|
return _origRequire.apply(this, arguments)
|
|
@@ -71,9 +72,10 @@ function Hook (modules, options, onrequire) {
|
|
|
71
72
|
let name, basedir, hooks
|
|
72
73
|
// return known patched modules immediately
|
|
73
74
|
if (cache[filename]) {
|
|
75
|
+
const externalCacheEntry = require.cache[filename]
|
|
74
76
|
// require.cache was potentially altered externally
|
|
75
|
-
if (
|
|
76
|
-
return
|
|
77
|
+
if (externalCacheEntry && externalCacheEntry.exports !== cache[filename].original) {
|
|
78
|
+
return externalCacheEntry.exports
|
|
77
79
|
}
|
|
78
80
|
|
|
79
81
|
return cache[filename].exports
|
|
@@ -113,7 +115,7 @@ function Hook (modules, options, onrequire) {
|
|
|
113
115
|
name = filename
|
|
114
116
|
} else {
|
|
115
117
|
const inAWSLambda = getEnvironmentVariable('AWS_LAMBDA_FUNCTION_NAME') !== undefined
|
|
116
|
-
const hasLambdaHandler =
|
|
118
|
+
const hasLambdaHandler = getValueFromEnvSources('DD_LAMBDA_HANDLER') !== undefined
|
|
117
119
|
const segments = filename.split(path.sep)
|
|
118
120
|
const filenameFromNodeModule = segments.includes('node_modules')
|
|
119
121
|
// decide how to assign the stat
|
|
@@ -127,6 +129,7 @@ function Hook (modules, options, onrequire) {
|
|
|
127
129
|
hooks = moduleHooks[name]
|
|
128
130
|
if (!hooks) return exports // abort if module name isn't on whitelist
|
|
129
131
|
|
|
132
|
+
// @ts-expect-error Module._resolveLookupPaths is not typed
|
|
130
133
|
const paths = Module._resolveLookupPaths(name, this, true)
|
|
131
134
|
if (!paths) {
|
|
132
135
|
// abort if _resolveLookupPaths return null
|
|
@@ -135,6 +138,7 @@ function Hook (modules, options, onrequire) {
|
|
|
135
138
|
|
|
136
139
|
let res
|
|
137
140
|
try {
|
|
141
|
+
// @ts-expect-error Module._findPath is not typed
|
|
138
142
|
res = Module._findPath(name, [basedir, ...paths])
|
|
139
143
|
} catch {
|
|
140
144
|
// case where the file specified in package.json "main" doesn't exist
|
|
@@ -8,12 +8,12 @@ const process = require('process')
|
|
|
8
8
|
const { performance, PerformanceObserver, monitorEventLoopDelay } = require('perf_hooks')
|
|
9
9
|
const { DogStatsDClient, MetricsAggregationClient } = require('../dogstatsd')
|
|
10
10
|
const log = require('../log')
|
|
11
|
-
const {
|
|
11
|
+
const { getValueFromEnvSources } = require('../config/helper')
|
|
12
12
|
|
|
13
13
|
const { NODE_MAJOR } = require('../../../../version')
|
|
14
14
|
// TODO: This environment variable may not be changed, since the agent expects a flush every ten seconds.
|
|
15
15
|
// It is only a variable for testing. Think about alternatives.
|
|
16
|
-
const DD_RUNTIME_METRICS_FLUSH_INTERVAL =
|
|
16
|
+
const DD_RUNTIME_METRICS_FLUSH_INTERVAL = getValueFromEnvSources('DD_RUNTIME_METRICS_FLUSH_INTERVAL') ?? '10000'
|
|
17
17
|
const INTERVAL = Number.parseInt(DD_RUNTIME_METRICS_FLUSH_INTERVAL, 10)
|
|
18
18
|
|
|
19
19
|
const eventLoopDelayResolution = 4
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
'use strict'
|
|
2
2
|
|
|
3
|
-
const { getEnvironmentVariable } = require('./config
|
|
3
|
+
const { getEnvironmentVariable, getValueFromEnvSources } = require('./config/helper')
|
|
4
4
|
const { isFalse } = require('./util')
|
|
5
5
|
|
|
6
6
|
function getIsGCPFunction () {
|
|
@@ -19,7 +19,7 @@ function getIsGCPFunction () {
|
|
|
19
19
|
* PUSH: GCP sends HTTP POST requests to the service with message data in headers.
|
|
20
20
|
*/
|
|
21
21
|
function enableGCPPubSubPushSubscription () {
|
|
22
|
-
const isGCPPubSubPushSubscriptionEnabled =
|
|
22
|
+
const isGCPPubSubPushSubscriptionEnabled = getValueFromEnvSources('DD_TRACE_GCP_PUBSUB_PUSH_ENABLED')
|
|
23
23
|
return getEnvironmentVariable('K_SERVICE') !== undefined && !isFalse(isGCPPubSubPushSubscriptionEnabled)
|
|
24
24
|
}
|
|
25
25
|
|
|
@@ -4,8 +4,8 @@ const log = require('./log')
|
|
|
4
4
|
const spanFormat = require('./span_format')
|
|
5
5
|
const SpanSampler = require('./span_sampler')
|
|
6
6
|
const GitMetadataTagger = require('./git_metadata_tagger')
|
|
7
|
-
const { getEnvironmentVariable } = require('./config-helper')
|
|
8
7
|
const processTags = require('./process-tags')
|
|
8
|
+
const { getValueFromEnvSources } = require('./config/helper')
|
|
9
9
|
|
|
10
10
|
const startedSpans = new WeakSet()
|
|
11
11
|
const finishedSpans = new WeakSet()
|
|
@@ -88,7 +88,7 @@ class SpanProcessor {
|
|
|
88
88
|
}
|
|
89
89
|
|
|
90
90
|
_erase (trace, active) {
|
|
91
|
-
if (
|
|
91
|
+
if (getValueFromEnvSources('DD_TRACE_EXPERIMENTAL_STATE_TRACKING') === 'true') {
|
|
92
92
|
const started = new Set()
|
|
93
93
|
const startedIds = new Set()
|
|
94
94
|
const finished = new Set()
|
|
@@ -2,9 +2,8 @@
|
|
|
2
2
|
|
|
3
3
|
const os = require('os')
|
|
4
4
|
const { inspect } = require('util')
|
|
5
|
-
|
|
6
5
|
const tracerVersion = require('../../../package.json').version
|
|
7
|
-
const defaults = require('./
|
|
6
|
+
const defaults = require('./config/defaults')
|
|
8
7
|
const { info, warn } = require('./log/writer')
|
|
9
8
|
|
|
10
9
|
const errors = {}
|
|
@@ -15,23 +14,15 @@ let samplingRules = []
|
|
|
15
14
|
let alreadyRan = false
|
|
16
15
|
|
|
17
16
|
/**
|
|
18
|
-
* @param {{
|
|
17
|
+
* @param {{ status: number, message: string } } [agentError]
|
|
19
18
|
*/
|
|
20
|
-
function startupLog (
|
|
21
|
-
if (!config || !pluginManager) {
|
|
22
|
-
return
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
if (alreadyRan) {
|
|
19
|
+
function startupLog (agentError) {
|
|
20
|
+
if (alreadyRan || !config || !config.startupLogs || !pluginManager) {
|
|
26
21
|
return
|
|
27
22
|
}
|
|
28
23
|
|
|
29
24
|
alreadyRan = true
|
|
30
25
|
|
|
31
|
-
if (!config.startupLogs) {
|
|
32
|
-
return
|
|
33
|
-
}
|
|
34
|
-
|
|
35
26
|
const out = tracerInfo()
|
|
36
27
|
|
|
37
28
|
if (agentError) {
|
|
@@ -42,8 +33,8 @@ function startupLog ({ agentError } = {}) {
|
|
|
42
33
|
if (agentError) {
|
|
43
34
|
warn('DATADOG TRACER DIAGNOSTIC - Agent Error: ' + agentError.message)
|
|
44
35
|
errors.agentError = {
|
|
45
|
-
code: agentError.
|
|
46
|
-
message: `Agent Error
|
|
36
|
+
code: agentError.status,
|
|
37
|
+
message: `Agent Error: ${agentError.message}`
|
|
47
38
|
}
|
|
48
39
|
}
|
|
49
40
|
}
|
|
@@ -3,35 +3,75 @@
|
|
|
3
3
|
const dc = require('dc-polyfill')
|
|
4
4
|
const { sendData } = require('./send-data')
|
|
5
5
|
|
|
6
|
+
/**
|
|
7
|
+
* RetryData is information that `telemetry.js` keeps in-memory to be merged into the next payload.
|
|
8
|
+
*
|
|
9
|
+
* @callback GetRetryData
|
|
10
|
+
* @returns {{ payload: Record<string, unknown>, reqType: string } | null}
|
|
11
|
+
*/
|
|
12
|
+
/**
|
|
13
|
+
* @typedef {import('./send-data').TelemetryConfig & {
|
|
14
|
+
* appsec?: { apiSecurity?: { endpointCollectionEnabled?: boolean, endpointCollectionMessageLimit?: number } }
|
|
15
|
+
* }} TelemetryConfig
|
|
16
|
+
*/
|
|
17
|
+
|
|
6
18
|
const fastifyRouteCh = dc.channel('apm:fastify:route:added')
|
|
7
19
|
const expressRouteCh = dc.channel('apm:express:route:added')
|
|
8
20
|
const routerRouteCh = dc.channel('apm:router:route:added')
|
|
9
21
|
|
|
22
|
+
/** @type {TelemetryConfig} */
|
|
10
23
|
let config
|
|
24
|
+
|
|
25
|
+
/** @type {import('./send-data').TelemetryApplication} */
|
|
11
26
|
let application
|
|
27
|
+
|
|
28
|
+
/** @type {import('./send-data').TelemetryHost} */
|
|
12
29
|
let host
|
|
30
|
+
|
|
31
|
+
/** @type {GetRetryData} */
|
|
13
32
|
let getRetryData
|
|
33
|
+
|
|
34
|
+
/** @type {import('./send-data').SendDataCallback} */
|
|
14
35
|
let updateRetryData
|
|
15
36
|
|
|
16
37
|
/**
|
|
17
38
|
* Keep track of endpoints that still need to be sent.
|
|
18
39
|
* Map key is `${METHOD} ${PATH}`, value is { method, path, operationName }
|
|
19
40
|
*/
|
|
41
|
+
/** @type {Map<string, { method: string, path: string, operationName: string }>} */
|
|
20
42
|
const pendingEndpoints = new Map()
|
|
43
|
+
|
|
44
|
+
/** @type {Set<string>} */
|
|
21
45
|
const wildcardEndpoints = new Set()
|
|
22
46
|
let flushScheduled = false
|
|
23
47
|
let isFirstPayload = true
|
|
24
48
|
|
|
49
|
+
/**
|
|
50
|
+
* @param {string} method
|
|
51
|
+
* @param {string} path
|
|
52
|
+
* @returns {string}
|
|
53
|
+
*/
|
|
25
54
|
function endpointKey (method, path) {
|
|
26
55
|
return `${method.toUpperCase()} ${path}`
|
|
27
56
|
}
|
|
28
57
|
|
|
58
|
+
/**
|
|
59
|
+
* @returns {void}
|
|
60
|
+
*/
|
|
29
61
|
function scheduleFlush () {
|
|
30
62
|
if (flushScheduled) return
|
|
31
63
|
flushScheduled = true
|
|
32
|
-
setImmediate(
|
|
64
|
+
// this used to be setImmediate() instead, but it was making the system test flaky
|
|
65
|
+
// don't ask me why
|
|
66
|
+
setTimeout(flushAndSend).unref()
|
|
33
67
|
}
|
|
34
68
|
|
|
69
|
+
/**
|
|
70
|
+
* @param {string} method
|
|
71
|
+
* @param {string} path
|
|
72
|
+
* @param {string} operationName
|
|
73
|
+
* @returns {void}
|
|
74
|
+
*/
|
|
35
75
|
function recordEndpoint (method, path, operationName) {
|
|
36
76
|
const key = endpointKey(method, path)
|
|
37
77
|
if (pendingEndpoints.has(key)) return
|
|
@@ -40,6 +80,9 @@ function recordEndpoint (method, path, operationName) {
|
|
|
40
80
|
scheduleFlush()
|
|
41
81
|
}
|
|
42
82
|
|
|
83
|
+
/**
|
|
84
|
+
* @param {{ routeOptions?: { path?: string, method: string | string[] } } | null | undefined} routeData
|
|
85
|
+
*/
|
|
43
86
|
function onFastifyRoute (routeData) {
|
|
44
87
|
const routeOptions = routeData?.routeOptions
|
|
45
88
|
if (!routeOptions?.path) return
|
|
@@ -50,6 +93,9 @@ function onFastifyRoute (routeData) {
|
|
|
50
93
|
}
|
|
51
94
|
}
|
|
52
95
|
|
|
96
|
+
/**
|
|
97
|
+
* @param {{ method?: string, path?: string }} param0
|
|
98
|
+
*/
|
|
53
99
|
function onExpressRoute ({ method, path }) {
|
|
54
100
|
if (!method || !path) return
|
|
55
101
|
|
|
@@ -70,6 +116,9 @@ function onExpressRoute ({ method, path }) {
|
|
|
70
116
|
}
|
|
71
117
|
}
|
|
72
118
|
|
|
119
|
+
/**
|
|
120
|
+
* @param {{ method: string, path: string, operationName: string }[]} endpoints
|
|
121
|
+
*/
|
|
73
122
|
function buildEndpointObjects (endpoints) {
|
|
74
123
|
return endpoints.map(({ method, path, operationName }) => {
|
|
75
124
|
return {
|
|
@@ -82,6 +131,9 @@ function buildEndpointObjects (endpoints) {
|
|
|
82
131
|
})
|
|
83
132
|
}
|
|
84
133
|
|
|
134
|
+
/**
|
|
135
|
+
* @returns {void}
|
|
136
|
+
*/
|
|
85
137
|
function flushAndSend () {
|
|
86
138
|
flushScheduled = false
|
|
87
139
|
if (pendingEndpoints.size === 0) return
|
|
@@ -90,7 +142,8 @@ function flushAndSend () {
|
|
|
90
142
|
for (const [key, endpoint] of pendingEndpoints) {
|
|
91
143
|
batchEndpoints.push(endpoint)
|
|
92
144
|
pendingEndpoints.delete(key)
|
|
93
|
-
|
|
145
|
+
// Config is set when endpoint collection is enabled; message limit is optional
|
|
146
|
+
if (batchEndpoints.length >= (config.appsec?.apiSecurity?.endpointCollectionMessageLimit ?? 0)) break
|
|
94
147
|
}
|
|
95
148
|
|
|
96
149
|
const payloadObj = {
|
|
@@ -98,7 +151,10 @@ function flushAndSend () {
|
|
|
98
151
|
endpoints: buildEndpointObjects(batchEndpoints)
|
|
99
152
|
}
|
|
100
153
|
|
|
154
|
+
/** @type {import('./send-data').TelemetryRequestType} */
|
|
101
155
|
let reqType = 'app-endpoints'
|
|
156
|
+
|
|
157
|
+
/** @type {import('./send-data').TelemetryPayload} */
|
|
102
158
|
let payload = payloadObj
|
|
103
159
|
|
|
104
160
|
const retryData = getRetryData()
|
|
@@ -120,8 +176,15 @@ function flushAndSend () {
|
|
|
120
176
|
if (pendingEndpoints.size) scheduleFlush()
|
|
121
177
|
}
|
|
122
178
|
|
|
123
|
-
|
|
124
|
-
|
|
179
|
+
/**
|
|
180
|
+
* @param {TelemetryConfig} _config
|
|
181
|
+
* @param {import('./send-data').TelemetryApplication} _application
|
|
182
|
+
* @param {import('./send-data').TelemetryHost} _host
|
|
183
|
+
* @param {GetRetryData} getRetryDataFunction
|
|
184
|
+
* @param {import('./send-data').SendDataCallback} updateRetryDataFunction
|
|
185
|
+
*/
|
|
186
|
+
function start (_config, _application, _host, getRetryDataFunction, updateRetryDataFunction) {
|
|
187
|
+
if (!_config.appsec?.apiSecurity?.endpointCollectionEnabled) return
|
|
125
188
|
|
|
126
189
|
config = _config
|
|
127
190
|
application = _application
|
|
@@ -141,7 +204,6 @@ function stop () {
|
|
|
141
204
|
|
|
142
205
|
pendingEndpoints.clear()
|
|
143
206
|
flushScheduled = false
|
|
144
|
-
config = application = host = getRetryData = updateRetryData = null
|
|
145
207
|
}
|
|
146
208
|
|
|
147
209
|
module.exports = {
|
|
@@ -3,10 +3,93 @@
|
|
|
3
3
|
const request = require('../exporters/common/request')
|
|
4
4
|
const log = require('../log')
|
|
5
5
|
const { isTrue } = require('../util')
|
|
6
|
-
const {
|
|
6
|
+
const { getValueFromEnvSources } = require('../config/helper')
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* @typedef {Record<string, unknown>} TelemetryPayloadObject
|
|
10
|
+
*/
|
|
11
|
+
/**
|
|
12
|
+
* Telemetry "request_type" values sent by this library.
|
|
13
|
+
*
|
|
14
|
+
* @typedef {'app-started'
|
|
15
|
+
* | 'app-integrations-change'
|
|
16
|
+
* | 'app-heartbeat'
|
|
17
|
+
* | 'app-extended-heartbeat'
|
|
18
|
+
* | 'app-client-configuration-change'
|
|
19
|
+
* | 'app-closing'
|
|
20
|
+
* | 'app-dependencies-loaded'
|
|
21
|
+
* | 'app-endpoints'
|
|
22
|
+
* | 'generate-metrics'
|
|
23
|
+
* | 'distributions'
|
|
24
|
+
* | 'logs'
|
|
25
|
+
* | 'message-batch'} TelemetryRequestType
|
|
26
|
+
*/
|
|
27
|
+
/**
|
|
28
|
+
* @typedef {{ request_type: string, payload: TelemetryPayloadObject }} MessageBatchItem
|
|
29
|
+
*/
|
|
30
|
+
/**
|
|
31
|
+
* @typedef {MessageBatchItem[]} MessageBatchPayload
|
|
32
|
+
*/
|
|
33
|
+
/**
|
|
34
|
+
* Telemetry payloads are usually single objects, but some request types (e.g. `message-batch`)
|
|
35
|
+
* send arrays.
|
|
36
|
+
*
|
|
37
|
+
* @typedef {TelemetryPayloadObject | MessageBatchPayload} TelemetryPayload
|
|
38
|
+
*/
|
|
39
|
+
/**
|
|
40
|
+
* @typedef {{language_name: string, tracer_version: string} & Record<string, unknown>} TelemetryApplication
|
|
41
|
+
*/
|
|
42
|
+
/**
|
|
43
|
+
* @typedef {Exclude<TelemetryRequestType, 'message-batch'>} NonBatchTelemetryRequestType
|
|
44
|
+
*/
|
|
45
|
+
/**
|
|
46
|
+
* @typedef {{
|
|
47
|
+
* payload: TelemetryPayloadObject,
|
|
48
|
+
* reqType: NonBatchTelemetryRequestType
|
|
49
|
+
* } | {
|
|
50
|
+
* payload: MessageBatchPayload,
|
|
51
|
+
* reqType: 'message-batch'
|
|
52
|
+
* }} SendDataRetryObject
|
|
53
|
+
*/
|
|
54
|
+
/**
|
|
55
|
+
* @typedef {{
|
|
56
|
+
* hostname: string,
|
|
57
|
+
* os: string,
|
|
58
|
+
* architecture: string,
|
|
59
|
+
* os_version?: string,
|
|
60
|
+
* kernel_version?: string,
|
|
61
|
+
* kernel_release?: string,
|
|
62
|
+
* kernel_name?: string
|
|
63
|
+
* } & Record<string, unknown>} TelemetryHost
|
|
64
|
+
*/
|
|
65
|
+
/**
|
|
66
|
+
* @typedef {{
|
|
67
|
+
* hostname?: string,
|
|
68
|
+
* port?: string | number,
|
|
69
|
+
* url?: string | URL,
|
|
70
|
+
* site?: string,
|
|
71
|
+
* apiKey?: string,
|
|
72
|
+
* isCiVisibility?: boolean,
|
|
73
|
+
* spanAttributeSchema?: string,
|
|
74
|
+
* tags: Record<string, string>,
|
|
75
|
+
* telemetry?: { debug?: boolean }
|
|
76
|
+
* }} TelemetryConfig
|
|
77
|
+
*/
|
|
78
|
+
/**
|
|
79
|
+
* @callback SendDataCallback
|
|
80
|
+
* @param {Error | null | undefined} error
|
|
81
|
+
* @param {SendDataRetryObject} retryObj
|
|
82
|
+
* @returns {void}
|
|
83
|
+
*/
|
|
7
84
|
|
|
8
85
|
let agentTelemetry = true
|
|
9
86
|
|
|
87
|
+
/**
|
|
88
|
+
* @param {TelemetryConfig} config
|
|
89
|
+
* @param {TelemetryApplication} application
|
|
90
|
+
* @param {TelemetryRequestType} reqType
|
|
91
|
+
* @returns {Record<string, string>}
|
|
92
|
+
*/
|
|
10
93
|
function getHeaders (config, application, reqType) {
|
|
11
94
|
const headers = {
|
|
12
95
|
'content-type': 'application/json',
|
|
@@ -25,6 +108,9 @@ function getHeaders (config, application, reqType) {
|
|
|
25
108
|
return headers
|
|
26
109
|
}
|
|
27
110
|
|
|
111
|
+
/**
|
|
112
|
+
* @param {string | undefined} site
|
|
113
|
+
*/
|
|
28
114
|
function getAgentlessTelemetryEndpoint (site) {
|
|
29
115
|
if (site === 'datad0g.com') { // staging
|
|
30
116
|
return 'https://all-http-intake.logs.datad0g.com'
|
|
@@ -34,6 +120,10 @@ function getAgentlessTelemetryEndpoint (site) {
|
|
|
34
120
|
|
|
35
121
|
let seqId = 0
|
|
36
122
|
|
|
123
|
+
/**
|
|
124
|
+
* @param {TelemetryPayload} payload
|
|
125
|
+
* @returns {TelemetryPayload}
|
|
126
|
+
*/
|
|
37
127
|
function getPayload (payload) {
|
|
38
128
|
// Some telemetry endpoints payloads accept collections of elements such as the 'logs' endpoint.
|
|
39
129
|
// 'logs' request type payload is meant to send library logs to Datadog’s backend.
|
|
@@ -44,6 +134,15 @@ function getPayload (payload) {
|
|
|
44
134
|
return trimmedPayload
|
|
45
135
|
}
|
|
46
136
|
|
|
137
|
+
// TODO(BridgeAR): Simplify this code. A lot does not need to be recalculated on every call.
|
|
138
|
+
/**
|
|
139
|
+
* @param {TelemetryConfig} config
|
|
140
|
+
* @param {TelemetryApplication} application
|
|
141
|
+
* @param {TelemetryHost} host
|
|
142
|
+
* @param {TelemetryRequestType} reqType
|
|
143
|
+
* @param {TelemetryPayload} [payload]
|
|
144
|
+
* @param {SendDataCallback} [cb]
|
|
145
|
+
*/
|
|
47
146
|
function sendData (config, application, host, reqType, payload = {}, cb = () => {}) {
|
|
48
147
|
const {
|
|
49
148
|
hostname,
|
|
@@ -54,7 +153,7 @@ function sendData (config, application, host, reqType, payload = {}, cb = () =>
|
|
|
54
153
|
let url = config.url
|
|
55
154
|
|
|
56
155
|
const isCiVisibilityAgentlessMode = isCiVisibility &&
|
|
57
|
-
isTrue(
|
|
156
|
+
isTrue(getValueFromEnvSources('DD_CIVISIBILITY_AGENTLESS_ENABLED'))
|
|
58
157
|
|
|
59
158
|
if (isCiVisibilityAgentlessMode) {
|
|
60
159
|
try {
|
|
@@ -88,14 +187,14 @@ function sendData (config, application, host, reqType, payload = {}, cb = () =>
|
|
|
88
187
|
})
|
|
89
188
|
|
|
90
189
|
request(data, options, (error) => {
|
|
91
|
-
if (error &&
|
|
190
|
+
if (error && getValueFromEnvSources('DD_API_KEY') && config.site) {
|
|
92
191
|
if (agentTelemetry) {
|
|
93
192
|
log.warn('Agent telemetry failed, started agentless telemetry')
|
|
94
193
|
agentTelemetry = false
|
|
95
194
|
}
|
|
96
195
|
// figure out which data center to send to
|
|
97
196
|
const backendUrl = getAgentlessTelemetryEndpoint(config.site)
|
|
98
|
-
const backendHeader = { ...options.headers, 'DD-API-KEY':
|
|
197
|
+
const backendHeader = { ...options.headers, 'DD-API-KEY': getValueFromEnvSources('DD_API_KEY') }
|
|
99
198
|
const backendOptions = {
|
|
100
199
|
...options,
|
|
101
200
|
url: backendUrl,
|