dd-trace 5.61.1 → 5.63.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 +0 -5
- package/package.json +2 -2
- package/packages/datadog-instrumentations/src/ai.js +140 -0
- package/packages/datadog-instrumentations/src/apollo-server.js +50 -8
- package/packages/datadog-instrumentations/src/aws-sdk.js +49 -60
- package/packages/datadog-instrumentations/src/couchbase.js +102 -65
- package/packages/datadog-instrumentations/src/fastify.js +61 -55
- package/packages/datadog-instrumentations/src/graphql.js +90 -122
- package/packages/datadog-instrumentations/src/helpers/hooks.js +1 -0
- package/packages/datadog-instrumentations/src/helpers/register.js +2 -22
- package/packages/datadog-instrumentations/src/hono.js +11 -8
- package/packages/datadog-instrumentations/src/http2/server.js +14 -20
- package/packages/datadog-instrumentations/src/knex.js +15 -17
- package/packages/datadog-instrumentations/src/microgateway-core.js +16 -15
- package/packages/datadog-instrumentations/src/mongodb-core.js +35 -32
- package/packages/datadog-instrumentations/src/mongodb.js +9 -13
- package/packages/datadog-instrumentations/src/mongoose.js +25 -29
- package/packages/datadog-instrumentations/src/next.js +4 -8
- package/packages/datadog-instrumentations/src/openai.js +0 -2
- package/packages/datadog-instrumentations/src/oracledb.js +39 -33
- package/packages/datadog-instrumentations/src/pg.js +38 -48
- package/packages/datadog-plugin-aerospike/src/index.js +11 -11
- package/packages/datadog-plugin-ai/src/index.js +17 -0
- package/packages/datadog-plugin-ai/src/tracing.js +33 -0
- package/packages/datadog-plugin-ai/src/utils.js +28 -0
- package/packages/datadog-plugin-amqp10/src/consumer.js +2 -2
- package/packages/datadog-plugin-amqp10/src/index.js +1 -1
- package/packages/datadog-plugin-amqp10/src/producer.js +3 -3
- package/packages/datadog-plugin-amqplib/src/client.js +3 -3
- package/packages/datadog-plugin-amqplib/src/consumer.js +2 -2
- package/packages/datadog-plugin-amqplib/src/index.js +1 -1
- package/packages/datadog-plugin-amqplib/src/producer.js +2 -2
- package/packages/datadog-plugin-apollo/src/gateway/execute.js +2 -4
- package/packages/datadog-plugin-apollo/src/gateway/fetch.js +2 -4
- package/packages/datadog-plugin-apollo/src/gateway/index.js +1 -1
- package/packages/datadog-plugin-apollo/src/gateway/plan.js +2 -4
- package/packages/datadog-plugin-apollo/src/gateway/postprocessing.js +2 -4
- package/packages/datadog-plugin-apollo/src/gateway/request.js +2 -4
- package/packages/datadog-plugin-apollo/src/gateway/validate.js +2 -4
- package/packages/datadog-plugin-apollo/src/index.js +1 -1
- package/packages/datadog-plugin-avsc/src/index.js +2 -2
- package/packages/datadog-plugin-aws-sdk/src/base.js +70 -46
- package/packages/datadog-plugin-aws-sdk/src/index.js +1 -3
- package/packages/datadog-plugin-aws-sdk/src/services/bedrockruntime/index.js +1 -3
- package/packages/datadog-plugin-aws-sdk/src/services/bedrockruntime/tracing.js +1 -1
- package/packages/datadog-plugin-aws-sdk/src/services/cloudwatchlogs.js +1 -1
- package/packages/datadog-plugin-aws-sdk/src/services/dynamodb.js +3 -3
- package/packages/datadog-plugin-aws-sdk/src/services/eventbridge.js +2 -2
- package/packages/datadog-plugin-aws-sdk/src/services/kinesis.js +22 -20
- package/packages/datadog-plugin-aws-sdk/src/services/lambda.js +1 -1
- package/packages/datadog-plugin-aws-sdk/src/services/redshift.js +1 -1
- package/packages/datadog-plugin-aws-sdk/src/services/s3.js +3 -3
- package/packages/datadog-plugin-aws-sdk/src/services/sfn.js +1 -1
- package/packages/datadog-plugin-aws-sdk/src/services/sns.js +3 -3
- package/packages/datadog-plugin-aws-sdk/src/services/sqs.js +17 -15
- package/packages/datadog-plugin-aws-sdk/src/services/states.js +1 -1
- package/packages/datadog-plugin-aws-sdk/src/services/stepfunctions.js +1 -1
- package/packages/datadog-plugin-azure-functions/src/index.js +5 -5
- package/packages/datadog-plugin-azure-service-bus/src/index.js +1 -1
- package/packages/datadog-plugin-azure-service-bus/src/producer.js +2 -2
- package/packages/datadog-plugin-bunyan/src/index.js +3 -5
- package/packages/datadog-plugin-cassandra-driver/src/index.js +3 -3
- package/packages/datadog-plugin-child_process/src/index.js +2 -2
- package/packages/datadog-plugin-confluentinc-kafka-javascript/src/batch-consumer.js +1 -3
- package/packages/datadog-plugin-confluentinc-kafka-javascript/src/consumer.js +1 -3
- package/packages/datadog-plugin-confluentinc-kafka-javascript/src/index.js +1 -1
- package/packages/datadog-plugin-confluentinc-kafka-javascript/src/producer.js +1 -3
- package/packages/datadog-plugin-connect/src/index.js +1 -3
- package/packages/datadog-plugin-couchbase/src/index.js +39 -19
- package/packages/datadog-plugin-cucumber/src/index.js +1 -3
- package/packages/datadog-plugin-cypress/src/index.js +1 -3
- package/packages/datadog-plugin-dd-trace-api/src/index.js +1 -3
- package/packages/datadog-plugin-dns/src/index.js +1 -1
- package/packages/datadog-plugin-dns/src/lookup.js +2 -2
- package/packages/datadog-plugin-dns/src/lookup_service.js +2 -2
- package/packages/datadog-plugin-dns/src/resolve.js +2 -2
- package/packages/datadog-plugin-dns/src/reverse.js +2 -2
- package/packages/datadog-plugin-elasticsearch/src/index.js +1 -1
- package/packages/datadog-plugin-express/src/code_origin.js +1 -3
- package/packages/datadog-plugin-express/src/index.js +1 -1
- package/packages/datadog-plugin-express/src/tracing.js +1 -3
- package/packages/datadog-plugin-fastify/src/code_origin.js +1 -3
- package/packages/datadog-plugin-fastify/src/index.js +1 -1
- package/packages/datadog-plugin-fastify/src/tracing.js +18 -3
- package/packages/datadog-plugin-fetch/src/index.js +2 -2
- package/packages/datadog-plugin-find-my-way/src/index.js +1 -3
- package/packages/datadog-plugin-fs/src/index.js +2 -2
- package/packages/datadog-plugin-google-cloud-pubsub/src/client.js +3 -3
- package/packages/datadog-plugin-google-cloud-pubsub/src/consumer.js +2 -2
- package/packages/datadog-plugin-google-cloud-pubsub/src/index.js +1 -1
- package/packages/datadog-plugin-google-cloud-pubsub/src/producer.js +2 -2
- package/packages/datadog-plugin-google-cloud-vertexai/src/index.js +1 -1
- package/packages/datadog-plugin-google-cloud-vertexai/src/tracing.js +2 -4
- package/packages/datadog-plugin-graphql/src/execute.js +16 -9
- package/packages/datadog-plugin-graphql/src/index.js +1 -1
- package/packages/datadog-plugin-graphql/src/parse.js +12 -7
- package/packages/datadog-plugin-graphql/src/resolve.js +50 -16
- package/packages/datadog-plugin-graphql/src/validate.js +13 -7
- package/packages/datadog-plugin-grpc/src/client.js +4 -4
- package/packages/datadog-plugin-grpc/src/index.js +1 -1
- package/packages/datadog-plugin-grpc/src/server.js +3 -3
- package/packages/datadog-plugin-hapi/src/index.js +1 -3
- package/packages/datadog-plugin-hono/src/index.js +1 -3
- package/packages/datadog-plugin-http/src/client.js +2 -2
- package/packages/datadog-plugin-http/src/index.js +1 -1
- package/packages/datadog-plugin-http/src/server.js +3 -7
- package/packages/datadog-plugin-http2/src/client.js +2 -2
- package/packages/datadog-plugin-http2/src/index.js +1 -1
- package/packages/datadog-plugin-http2/src/server.js +22 -11
- package/packages/datadog-plugin-ioredis/src/index.js +1 -3
- package/packages/datadog-plugin-iovalkey/src/index.js +2 -4
- package/packages/datadog-plugin-jest/src/index.js +1 -3
- package/packages/datadog-plugin-kafkajs/src/batch-consumer.js +2 -2
- package/packages/datadog-plugin-kafkajs/src/consumer.js +2 -2
- package/packages/datadog-plugin-kafkajs/src/index.js +1 -1
- package/packages/datadog-plugin-kafkajs/src/producer.js +3 -3
- package/packages/datadog-plugin-koa/src/index.js +1 -3
- package/packages/datadog-plugin-langchain/src/index.js +2 -2
- package/packages/datadog-plugin-langchain/src/tracing.js +30 -48
- package/packages/datadog-plugin-mariadb/src/index.js +2 -2
- package/packages/datadog-plugin-memcached/src/index.js +1 -1
- package/packages/datadog-plugin-microgateway-core/src/index.js +4 -4
- package/packages/datadog-plugin-mocha/src/index.js +1 -3
- package/packages/datadog-plugin-moleculer/src/client.js +2 -2
- package/packages/datadog-plugin-moleculer/src/index.js +1 -1
- package/packages/datadog-plugin-moleculer/src/server.js +2 -2
- package/packages/datadog-plugin-mongodb-core/src/index.js +9 -5
- package/packages/datadog-plugin-mongoose/src/index.js +20 -0
- package/packages/datadog-plugin-mysql/src/index.js +2 -2
- package/packages/datadog-plugin-mysql2/src/index.js +1 -1
- package/packages/datadog-plugin-net/src/index.js +1 -1
- package/packages/datadog-plugin-net/src/ipc.js +2 -2
- package/packages/datadog-plugin-net/src/tcp.js +2 -2
- package/packages/datadog-plugin-next/src/index.js +1 -3
- package/packages/datadog-plugin-nyc/src/index.js +1 -3
- package/packages/datadog-plugin-openai/src/index.js +1 -1
- package/packages/datadog-plugin-openai/src/tracing.js +7 -411
- package/packages/datadog-plugin-opensearch/src/index.js +1 -3
- package/packages/datadog-plugin-oracledb/src/index.js +9 -5
- package/packages/datadog-plugin-pg/src/index.js +8 -5
- package/packages/datadog-plugin-pino/src/index.js +3 -5
- package/packages/datadog-plugin-playwright/src/index.js +1 -3
- package/packages/datadog-plugin-prisma/src/client.js +4 -6
- package/packages/datadog-plugin-prisma/src/engine.js +3 -3
- package/packages/datadog-plugin-prisma/src/index.js +1 -1
- package/packages/datadog-plugin-protobufjs/src/index.js +2 -6
- package/packages/datadog-plugin-redis/src/index.js +2 -2
- package/packages/datadog-plugin-restify/src/index.js +1 -3
- package/packages/datadog-plugin-rhea/src/consumer.js +1 -1
- package/packages/datadog-plugin-rhea/src/index.js +1 -1
- package/packages/datadog-plugin-rhea/src/producer.js +2 -2
- package/packages/datadog-plugin-router/src/index.js +1 -3
- package/packages/datadog-plugin-selenium/src/index.js +1 -3
- package/packages/datadog-plugin-sharedb/src/index.js +1 -1
- package/packages/datadog-plugin-tedious/src/index.js +3 -3
- package/packages/datadog-plugin-undici/src/index.js +2 -4
- package/packages/datadog-plugin-vitest/src/index.js +1 -3
- package/packages/datadog-plugin-web/src/index.js +1 -3
- package/packages/datadog-plugin-winston/src/index.js +3 -5
- package/packages/dd-trace/src/appsec/channels.js +1 -0
- package/packages/dd-trace/src/appsec/graphql.js +14 -12
- package/packages/dd-trace/src/appsec/iast/analyzers/sql-injection-analyzer.js +14 -7
- package/packages/dd-trace/src/appsec/iast/taint-tracking/plugin.js +4 -4
- package/packages/dd-trace/src/appsec/recommended.json +271 -2
- package/packages/dd-trace/src/appsec/waf/waf_manager.js +1 -1
- package/packages/dd-trace/src/ci-visibility/log-submission/log-submission-plugin.js +1 -3
- package/packages/dd-trace/src/ci-visibility/test-api-manual/test-api-manual-plugin.js +1 -3
- package/packages/dd-trace/src/config.js +1 -1
- package/packages/dd-trace/src/datastreams/checkpointer.js +23 -2
- package/packages/dd-trace/src/datastreams/processor.js +4 -3
- package/packages/dd-trace/src/guardrails/telemetry.js +18 -2
- package/packages/dd-trace/src/llmobs/plugins/ai/index.js +351 -0
- package/packages/dd-trace/src/llmobs/plugins/ai/util.js +179 -0
- package/packages/dd-trace/src/llmobs/plugins/langchain/index.js +30 -50
- package/packages/dd-trace/src/llmobs/plugins/openai.js +3 -5
- package/packages/dd-trace/src/llmobs/plugins/vertexai.js +3 -5
- package/packages/dd-trace/src/llmobs/writers/base.js +3 -2
- package/packages/dd-trace/src/opentracing/propagation/text_map.js +25 -2
- package/packages/dd-trace/src/opentracing/span_context.js +4 -0
- package/packages/dd-trace/src/plugin_manager.js +8 -4
- package/packages/dd-trace/src/plugins/apollo.js +3 -3
- package/packages/dd-trace/src/plugins/cache.js +1 -1
- package/packages/dd-trace/src/plugins/client.js +3 -3
- package/packages/dd-trace/src/plugins/consumer.js +3 -3
- package/packages/dd-trace/src/plugins/database.js +2 -2
- package/packages/dd-trace/src/plugins/index.js +2 -0
- package/packages/dd-trace/src/plugins/log_plugin.js +1 -5
- package/packages/dd-trace/src/plugins/outbound.js +1 -1
- package/packages/dd-trace/src/plugins/plugin.js +1 -1
- package/packages/dd-trace/src/plugins/producer.js +3 -3
- package/packages/dd-trace/src/plugins/server.js +3 -3
- package/packages/dd-trace/src/plugins/storage.js +1 -1
- package/packages/dd-trace/src/plugins/tracing.js +24 -6
- package/packages/dd-trace/src/plugins/util/ci.js +11 -7
- package/packages/dd-trace/src/plugins/util/inferred_proxy.js +15 -19
- package/packages/dd-trace/src/plugins/util/ip_extractor.js +44 -3
- package/packages/dd-trace/src/plugins/util/tags.js +2 -0
- package/packages/dd-trace/src/plugins/util/web.js +26 -7
- package/packages/dd-trace/src/profiling/config.js +2 -0
- package/packages/dd-trace/src/profiling/exporters/event_serializer.js +2 -21
- package/packages/dd-trace/src/profiling/libuv-size.js +49 -0
- package/packages/dd-trace/src/profiling/profilers/event_plugins/dns.js +2 -6
- package/packages/dd-trace/src/profiling/profilers/event_plugins/dns_lookup.js +1 -3
- package/packages/dd-trace/src/profiling/profilers/event_plugins/dns_lookupservice.js +1 -3
- package/packages/dd-trace/src/profiling/profilers/event_plugins/dns_resolve.js +1 -3
- package/packages/dd-trace/src/profiling/profilers/event_plugins/dns_reverse.js +1 -3
- package/packages/dd-trace/src/profiling/profilers/event_plugins/event.js +24 -23
- package/packages/dd-trace/src/profiling/profilers/event_plugins/fs.js +3 -9
- package/packages/dd-trace/src/profiling/profilers/event_plugins/net.js +3 -9
- package/packages/dd-trace/src/profiling/profilers/events.js +83 -64
- package/packages/dd-trace/src/profiling/profilers/poisson.js +105 -0
- package/packages/dd-trace/src/profiling/profilers/wall.js +3 -3
- package/packages/dd-trace/src/remote_config/manager.js +1 -1
- package/packages/dd-trace/src/supported-configurations.json +2 -0
- package/packages/dd-trace/src/tracer_metadata.js +1 -1
|
@@ -5,23 +5,7 @@
|
|
|
5
5
|
const os = require('os')
|
|
6
6
|
const perf = require('perf_hooks').performance
|
|
7
7
|
const version = require('../../../../../package.json').version
|
|
8
|
-
const {
|
|
9
|
-
|
|
10
|
-
const libuvThreadPoolSize = (() => {
|
|
11
|
-
const ss = getEnvironmentVariable('UV_THREADPOOL_SIZE')
|
|
12
|
-
if (ss === undefined) {
|
|
13
|
-
// Backend will apply the default size based on Node version.
|
|
14
|
-
return
|
|
15
|
-
}
|
|
16
|
-
// libuv uses atoi to parse the value, which is almost the same as parseInt, except that parseInt
|
|
17
|
-
// will return NaN on invalid input, while atoi will return 0. This is handled at return.
|
|
18
|
-
const s = Number.parseInt(ss)
|
|
19
|
-
// We don't interpret the value further here in the library. Backend will interpret the number
|
|
20
|
-
// based on Node version. In all currently known Node versions, 0 results in 1 worker thread,
|
|
21
|
-
// negative values (because they're assigned to an unsigned int) become very high positive values,
|
|
22
|
-
// and the value is finally capped at 1024.
|
|
23
|
-
return Number.isNaN(s) ? 0 : s
|
|
24
|
-
})()
|
|
8
|
+
const { availableParallelism, libuvThreadPoolSize } = require('../libuv-size')
|
|
25
9
|
|
|
26
10
|
class EventSerializer {
|
|
27
11
|
constructor ({ env, host, service, version, libraryInjected, activation } = {}) {
|
|
@@ -77,10 +61,7 @@ class EventSerializer {
|
|
|
77
61
|
version
|
|
78
62
|
},
|
|
79
63
|
runtime: {
|
|
80
|
-
|
|
81
|
-
available_processors: typeof os.availableParallelism === 'function'
|
|
82
|
-
? os.availableParallelism()
|
|
83
|
-
: os.cpus().length,
|
|
64
|
+
available_processors: availableParallelism(),
|
|
84
65
|
// Using `nodejs` for consistency with the existing `runtime` tag.
|
|
85
66
|
// Note that the event `family` property uses `node`, as that's what's
|
|
86
67
|
// proscribed by the Intake API, but that's an internal enum and is
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
'use strict'
|
|
2
|
+
|
|
3
|
+
const { getEnvironmentVariable } = require('../config-helper')
|
|
4
|
+
const os = require('node:os')
|
|
5
|
+
|
|
6
|
+
function getLibuvThreadPoolSize (envVar) {
|
|
7
|
+
if (envVar === undefined) {
|
|
8
|
+
return
|
|
9
|
+
}
|
|
10
|
+
// libuv uses atoi to parse the value, which is almost the same as parseInt, except that parseInt
|
|
11
|
+
// will return NaN on invalid input, while atoi will return 0. This is handled at return.
|
|
12
|
+
const s = Number.parseInt(envVar, 10)
|
|
13
|
+
// We don't interpret the value further here in the library. Backend will interpret the number
|
|
14
|
+
// based on Node version.
|
|
15
|
+
return Number.isNaN(s) ? 0 : s
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
const libuvThreadPoolSize = getLibuvThreadPoolSize(getEnvironmentVariable('UV_THREADPOOL_SIZE'))
|
|
19
|
+
|
|
20
|
+
function getEffectiveLibuvThreadCount (size) {
|
|
21
|
+
// In all currently known Node versions, 0 results in 1 worker thread, negative values (because
|
|
22
|
+
// they're assigned to an unsigned int) become very high positive values, and the value is finally
|
|
23
|
+
// capped at 1024.
|
|
24
|
+
if (size === undefined) {
|
|
25
|
+
return 4
|
|
26
|
+
} else if (size < 0 || size > 1024) {
|
|
27
|
+
return 1024
|
|
28
|
+
} else if (size === 0) {
|
|
29
|
+
return 1
|
|
30
|
+
}
|
|
31
|
+
return size
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
const effectiveLibuvThreadCount = getEffectiveLibuvThreadCount(libuvThreadPoolSize)
|
|
35
|
+
|
|
36
|
+
function availableParallelism () {
|
|
37
|
+
// os.availableParallelism only available in node 18.14.0/19.4.0 and above
|
|
38
|
+
// eslint-disable-next-line n/no-unsupported-features/node-builtins
|
|
39
|
+
return typeof os.availableParallelism === 'function' ? os.availableParallelism() : os.cpus().length
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
module.exports = {
|
|
43
|
+
availableParallelism,
|
|
44
|
+
effectiveLibuvThreadCount,
|
|
45
|
+
libuvThreadPoolSize,
|
|
46
|
+
// Only used for testing
|
|
47
|
+
getLibuvThreadPoolSize,
|
|
48
|
+
getEffectiveLibuvThreadCount
|
|
49
|
+
}
|
|
@@ -3,13 +3,9 @@
|
|
|
3
3
|
const EventPlugin = require('./event')
|
|
4
4
|
|
|
5
5
|
class DNSPlugin extends EventPlugin {
|
|
6
|
-
static
|
|
7
|
-
return 'dns'
|
|
8
|
-
}
|
|
6
|
+
static id = 'dns'
|
|
9
7
|
|
|
10
|
-
static
|
|
11
|
-
return 'dns'
|
|
12
|
-
}
|
|
8
|
+
static entryType = 'dns'
|
|
13
9
|
}
|
|
14
10
|
|
|
15
11
|
module.exports = DNSPlugin
|
|
@@ -5,9 +5,7 @@ const DNSPlugin = require('./dns')
|
|
|
5
5
|
const queryNames = new Map()
|
|
6
6
|
|
|
7
7
|
class DNSResolvePlugin extends DNSPlugin {
|
|
8
|
-
static
|
|
9
|
-
return 'resolve'
|
|
10
|
-
}
|
|
8
|
+
static operation = 'resolve'
|
|
11
9
|
|
|
12
10
|
extendEvent (event, startEvent) {
|
|
13
11
|
const rrtype = startEvent.args[1]
|
|
@@ -7,54 +7,55 @@ const { performance } = require('perf_hooks')
|
|
|
7
7
|
// start/error/finish methods to the appropriate diagnostic channels.
|
|
8
8
|
// TODO: Decouple this from TracingPlugin.
|
|
9
9
|
class EventPlugin extends TracingPlugin {
|
|
10
|
+
#eventHandler
|
|
11
|
+
#eventFilter
|
|
12
|
+
#dataSymbol
|
|
13
|
+
#entryType
|
|
14
|
+
|
|
10
15
|
constructor (eventHandler, eventFilter) {
|
|
11
16
|
super()
|
|
12
|
-
this
|
|
13
|
-
this
|
|
14
|
-
this
|
|
15
|
-
this
|
|
17
|
+
this.#eventHandler = eventHandler
|
|
18
|
+
this.#eventFilter = eventFilter
|
|
19
|
+
this.#entryType = this.constructor.entryType
|
|
20
|
+
this.#dataSymbol = Symbol(`dd-trace.profiling.event.${this.#entryType}.${this.constructor.operation}`)
|
|
16
21
|
}
|
|
17
22
|
|
|
18
23
|
start (ctx) {
|
|
19
|
-
this.
|
|
20
|
-
startEvent: ctx,
|
|
21
|
-
startTime: performance.now()
|
|
22
|
-
})
|
|
24
|
+
ctx[this.#dataSymbol] = performance.now()
|
|
23
25
|
}
|
|
24
26
|
|
|
25
27
|
error (ctx) {
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
data.error = true
|
|
29
|
-
}
|
|
28
|
+
// We don't emit perf events for failed operations
|
|
29
|
+
ctx[this.#dataSymbol] = undefined
|
|
30
30
|
}
|
|
31
31
|
|
|
32
32
|
finish (ctx) {
|
|
33
|
-
const
|
|
34
|
-
|
|
35
|
-
|
|
33
|
+
const startTime = ctx[this.#dataSymbol]
|
|
34
|
+
if (startTime === undefined) {
|
|
35
|
+
return
|
|
36
|
+
}
|
|
37
|
+
ctx[this.#dataSymbol] = undefined
|
|
36
38
|
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
return // don't emit perf events for failed operations or ignored events
|
|
39
|
+
if (this.ignoreEvent(ctx)) {
|
|
40
|
+
return // don't emit perf events for ignored events
|
|
40
41
|
}
|
|
41
42
|
|
|
42
43
|
const duration = performance.now() - startTime
|
|
43
44
|
const event = {
|
|
44
|
-
entryType: this
|
|
45
|
+
entryType: this.#entryType,
|
|
45
46
|
startTime,
|
|
46
47
|
duration
|
|
47
48
|
}
|
|
48
49
|
|
|
49
|
-
if (!this
|
|
50
|
+
if (!this.#eventFilter(event)) {
|
|
50
51
|
return
|
|
51
52
|
}
|
|
52
53
|
|
|
53
54
|
const context = (ctx.currentStore?.span || this.activeSpan)?.context()
|
|
54
|
-
event._ddSpanId = context?.
|
|
55
|
-
event._ddRootSpanId = context?._trace.started[0]?.context().
|
|
55
|
+
event._ddSpanId = context?.toBigIntSpanId()
|
|
56
|
+
event._ddRootSpanId = context?._trace.started[0]?.context().toBigIntSpanId() || event._ddSpanId
|
|
56
57
|
|
|
57
|
-
this
|
|
58
|
+
this.#eventHandler(this.extendEvent(event, ctx))
|
|
58
59
|
}
|
|
59
60
|
|
|
60
61
|
ignoreEvent () {
|
|
@@ -19,17 +19,11 @@ const allowedParams = new Set([
|
|
|
19
19
|
])
|
|
20
20
|
|
|
21
21
|
class FilesystemPlugin extends EventPlugin {
|
|
22
|
-
static
|
|
23
|
-
return 'fs'
|
|
24
|
-
}
|
|
22
|
+
static id = 'fs'
|
|
25
23
|
|
|
26
|
-
static
|
|
27
|
-
return 'operation'
|
|
28
|
-
}
|
|
24
|
+
static operation = 'operation'
|
|
29
25
|
|
|
30
|
-
static
|
|
31
|
-
return 'fs'
|
|
32
|
-
}
|
|
26
|
+
static entryType = 'fs'
|
|
33
27
|
|
|
34
28
|
ignoreEvent (event) {
|
|
35
29
|
// Don't care about sync events, they show up in the event loop samples anyway
|
|
@@ -3,17 +3,11 @@
|
|
|
3
3
|
const EventPlugin = require('./event')
|
|
4
4
|
|
|
5
5
|
class NetPlugin extends EventPlugin {
|
|
6
|
-
static
|
|
7
|
-
return 'net'
|
|
8
|
-
}
|
|
6
|
+
static id = 'net'
|
|
9
7
|
|
|
10
|
-
static
|
|
11
|
-
return 'tcp'
|
|
12
|
-
}
|
|
8
|
+
static operation = 'tcp'
|
|
13
9
|
|
|
14
|
-
static
|
|
15
|
-
return 'net'
|
|
16
|
-
}
|
|
10
|
+
static entryType = 'net'
|
|
17
11
|
|
|
18
12
|
extendEvent (event, { options }) {
|
|
19
13
|
event.name = 'connect'
|
|
@@ -3,9 +3,12 @@
|
|
|
3
3
|
const { performance, constants, PerformanceObserver } = require('perf_hooks')
|
|
4
4
|
const { END_TIMESTAMP_LABEL, SPAN_ID_LABEL, LOCAL_ROOT_SPAN_ID_LABEL, encodeProfileAsync } = require('./shared')
|
|
5
5
|
const { Function, Label, Line, Location, Profile, Sample, StringTable, ValueType } = require('pprof-format')
|
|
6
|
-
|
|
6
|
+
const PoissonProcessSamplingFilter = require('./poisson')
|
|
7
|
+
const { availableParallelism, effectiveLibuvThreadCount } = require('../libuv-size')
|
|
7
8
|
// perf_hooks uses millis, with fractional part representing nanos. We emit nanos into the pprof file.
|
|
8
9
|
const MS_TO_NS = 1_000_000
|
|
10
|
+
// The number of sampling intervals that need to pass before we reset the Poisson process sampling instant.
|
|
11
|
+
const POISSON_RESET_FACTOR = 2
|
|
9
12
|
|
|
10
13
|
// While this is an "events profiler", meaning it emits a pprof file based on events observed as
|
|
11
14
|
// perf_hooks events, the emitted pprof file uses the type "timeline".
|
|
@@ -38,6 +41,24 @@ function labelFromStrStr (stringTable, keyStr, valStr) {
|
|
|
38
41
|
return labelFromStr(stringTable, stringTable.dedup(keyStr), valStr)
|
|
39
42
|
}
|
|
40
43
|
|
|
44
|
+
function getSamplingIntervalMillis (options) {
|
|
45
|
+
return (options.samplingInterval || 1e3 / 99) // 99Hz
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
function getMaxSamples (options) {
|
|
49
|
+
const cpuSamplingInterval = getSamplingIntervalMillis(options)
|
|
50
|
+
const flushInterval = options.flushInterval || 65 * 1e3 // 60 seconds
|
|
51
|
+
const maxCpuSamples = flushInterval / cpuSamplingInterval
|
|
52
|
+
|
|
53
|
+
// The lesser of max parallelism and libuv thread pool size, plus one so we can detect
|
|
54
|
+
// oversubscription on libuv thread pool, plus another one for GC.
|
|
55
|
+
const factor = Math.max(1, Math.min(availableParallelism(), effectiveLibuvThreadCount)) + 2
|
|
56
|
+
|
|
57
|
+
// Let's not go overboard with too large limit and cap it at 100k. With current defaults, the
|
|
58
|
+
// value will be 65000/10.1*(4+2) = 38613.
|
|
59
|
+
return Math.min(100_000, Math.floor(maxCpuSamples * factor))
|
|
60
|
+
}
|
|
61
|
+
|
|
41
62
|
class GCDecorator {
|
|
42
63
|
constructor (stringTable) {
|
|
43
64
|
this.stringTable = stringTable
|
|
@@ -181,12 +202,15 @@ const decoratorTypes = {
|
|
|
181
202
|
|
|
182
203
|
// Translates performance entries into pprof samples.
|
|
183
204
|
class EventSerializer {
|
|
184
|
-
|
|
205
|
+
#sampleCount = 0
|
|
206
|
+
|
|
207
|
+
constructor (maxSamples) {
|
|
185
208
|
this.stringTable = new StringTable()
|
|
186
209
|
this.samples = []
|
|
187
210
|
this.locations = []
|
|
188
211
|
this.functions = []
|
|
189
212
|
this.decorators = {}
|
|
213
|
+
this.maxSamples = maxSamples
|
|
190
214
|
|
|
191
215
|
// A synthetic single-frame location to serve as the location for timeline
|
|
192
216
|
// samples. We need these as the profiling backend (mimicking official pprof
|
|
@@ -204,6 +228,31 @@ class EventSerializer {
|
|
|
204
228
|
}
|
|
205
229
|
|
|
206
230
|
addEvent (item) {
|
|
231
|
+
if (this.samples.length < this.maxSamples) {
|
|
232
|
+
const sample = this.#createSample(item)
|
|
233
|
+
if (sample !== undefined) {
|
|
234
|
+
this.samples.push(sample)
|
|
235
|
+
this.#sampleCount++
|
|
236
|
+
}
|
|
237
|
+
} else {
|
|
238
|
+
this.#sampleCount++
|
|
239
|
+
// Reservoir sampling
|
|
240
|
+
const replacementIndex = Math.floor(Math.random() * this.#sampleCount)
|
|
241
|
+
if (replacementIndex < this.maxSamples) {
|
|
242
|
+
const sample = this.#createSample(item)
|
|
243
|
+
if (sample === undefined) {
|
|
244
|
+
this.#sampleCount-- // unlikely
|
|
245
|
+
} else {
|
|
246
|
+
// This will cause the samples to no longer be sorted in their array
|
|
247
|
+
// by their end time. This is fine as the backend has no ordering
|
|
248
|
+
// expectations.
|
|
249
|
+
this.samples[replacementIndex] = sample
|
|
250
|
+
}
|
|
251
|
+
}
|
|
252
|
+
}
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
#createSample (item) {
|
|
207
256
|
const { entryType, startTime, duration, _ddSpanId, _ddRootSpanId } = item
|
|
208
257
|
let decorator = this.decorators[entryType]
|
|
209
258
|
if (!decorator) {
|
|
@@ -224,10 +273,11 @@ class EventSerializer {
|
|
|
224
273
|
new Label({ key: this.timestampLabelKey, num: dateOffset + BigInt(Math.round(endTime * MS_TO_NS)) })
|
|
225
274
|
]
|
|
226
275
|
if (_ddSpanId) {
|
|
227
|
-
label.push(
|
|
276
|
+
label.push(
|
|
277
|
+
new Label({ key: this.spanIdKey, num: _ddSpanId }))
|
|
228
278
|
}
|
|
229
279
|
if (_ddRootSpanId) {
|
|
230
|
-
label.push(
|
|
280
|
+
label.push(new Label({ key: this.rootSpanIdKey, num: _ddRootSpanId }))
|
|
231
281
|
}
|
|
232
282
|
|
|
233
283
|
const sampleInput = {
|
|
@@ -236,7 +286,7 @@ class EventSerializer {
|
|
|
236
286
|
label
|
|
237
287
|
}
|
|
238
288
|
decorator.decorateSample(sampleInput, item)
|
|
239
|
-
|
|
289
|
+
return new Sample(sampleInput)
|
|
240
290
|
}
|
|
241
291
|
|
|
242
292
|
createProfile (startDate, endDate) {
|
|
@@ -324,50 +374,13 @@ class DatadogInstrumentationEventSource {
|
|
|
324
374
|
}
|
|
325
375
|
}
|
|
326
376
|
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
}
|
|
335
|
-
|
|
336
|
-
stop () {
|
|
337
|
-
this.sources.forEach(s => s.stop())
|
|
338
|
-
}
|
|
339
|
-
}
|
|
340
|
-
|
|
341
|
-
function createPossionProcessSamplingFilter (samplingIntervalMillis) {
|
|
342
|
-
let nextSamplingInstant = performance.now()
|
|
343
|
-
let currentSamplingInstant = 0
|
|
344
|
-
setNextSamplingInstant()
|
|
345
|
-
|
|
346
|
-
return event => {
|
|
347
|
-
const endTime = event.startTime + event.duration
|
|
348
|
-
while (endTime >= nextSamplingInstant) {
|
|
349
|
-
setNextSamplingInstant()
|
|
350
|
-
}
|
|
351
|
-
// An event is sampled if it started before, and ended on or after a sampling instant. The above
|
|
352
|
-
// while loop will ensure that the ending invariant is always true for the current sampling
|
|
353
|
-
// instant so we don't have to test for it below. Across calls, the invariant also holds as long
|
|
354
|
-
// as the events arrive in endTime order. This is true for events coming from
|
|
355
|
-
// DatadogInstrumentationEventSource; they will be ordered by endTime by virtue of this method
|
|
356
|
-
// being invoked synchronously with the plugins' finish() handler which evaluates
|
|
357
|
-
// performance.now(). OTOH, events coming from NodeAPIEventSource (GC in typical setup) might be
|
|
358
|
-
// somewhat delayed as they are queued by Node, so they can arrive out of order with regard to
|
|
359
|
-
// events coming from the non-queued source. By omitting the endTime check, we will pass through
|
|
360
|
-
// some short events that started and ended before the current sampling instant. OTOH, if we
|
|
361
|
-
// were to check for this.currentSamplingInstant <= endTime, we would discard some long events
|
|
362
|
-
// that also ended before the current sampling instant. We'd rather err on the side of including
|
|
363
|
-
// some short events than excluding some long events.
|
|
364
|
-
return event.startTime < currentSamplingInstant
|
|
365
|
-
}
|
|
366
|
-
|
|
367
|
-
function setNextSamplingInstant () {
|
|
368
|
-
currentSamplingInstant = nextSamplingInstant
|
|
369
|
-
nextSamplingInstant -= Math.log(1 - Math.random()) * samplingIntervalMillis
|
|
370
|
-
}
|
|
377
|
+
function createPoissonProcessSamplingFilter (samplingIntervalMillis) {
|
|
378
|
+
const poissonFilter = new PoissonProcessSamplingFilter({
|
|
379
|
+
samplingInterval: samplingIntervalMillis,
|
|
380
|
+
resetInterval: samplingIntervalMillis * POISSON_RESET_FACTOR,
|
|
381
|
+
now: performance.now.bind(performance)
|
|
382
|
+
})
|
|
383
|
+
return poissonFilter.filter.bind(poissonFilter)
|
|
371
384
|
}
|
|
372
385
|
|
|
373
386
|
/**
|
|
@@ -376,45 +389,51 @@ function createPossionProcessSamplingFilter (samplingIntervalMillis) {
|
|
|
376
389
|
*/
|
|
377
390
|
class EventsProfiler {
|
|
378
391
|
type = 'events'
|
|
379
|
-
|
|
392
|
+
#maxSamples
|
|
393
|
+
#eventSerializer
|
|
394
|
+
#eventSources
|
|
380
395
|
|
|
381
396
|
constructor (options = {}) {
|
|
382
|
-
|
|
397
|
+
this.#maxSamples = getMaxSamples(options)
|
|
398
|
+
this.#eventSerializer = new EventSerializer(this.#maxSamples)
|
|
399
|
+
|
|
400
|
+
const eventHandler = event => this.#eventSerializer.addEvent(event)
|
|
383
401
|
const eventFilter = options.timelineSamplingEnabled
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
: _ => true
|
|
402
|
+
? createPoissonProcessSamplingFilter(getSamplingIntervalMillis(options))
|
|
403
|
+
: () => true
|
|
387
404
|
const filteringEventHandler = event => {
|
|
388
405
|
if (eventFilter(event)) {
|
|
389
406
|
eventHandler(event)
|
|
390
407
|
}
|
|
391
408
|
}
|
|
392
409
|
|
|
393
|
-
this
|
|
410
|
+
this.#eventSources = options.codeHotspotsEnabled
|
|
394
411
|
// Use Datadog instrumentation to collect events with span IDs. Still use
|
|
395
412
|
// Node API for GC events.
|
|
396
|
-
?
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
413
|
+
? [
|
|
414
|
+
new DatadogInstrumentationEventSource(eventHandler, eventFilter),
|
|
415
|
+
new NodeApiEventSource(filteringEventHandler, ['gc']),
|
|
416
|
+
]
|
|
400
417
|
// Use Node API instrumentation to collect events without span IDs
|
|
401
|
-
:
|
|
418
|
+
: [
|
|
419
|
+
new NodeApiEventSource(filteringEventHandler)
|
|
420
|
+
]
|
|
402
421
|
}
|
|
403
422
|
|
|
404
423
|
start () {
|
|
405
|
-
this.
|
|
424
|
+
this.#eventSources.forEach(s => s.start())
|
|
406
425
|
}
|
|
407
426
|
|
|
408
427
|
stop () {
|
|
409
|
-
this.
|
|
428
|
+
this.#eventSources.forEach(s => s.stop())
|
|
410
429
|
}
|
|
411
430
|
|
|
412
431
|
profile (restart, startDate, endDate) {
|
|
413
432
|
if (!restart) {
|
|
414
433
|
this.stop()
|
|
415
434
|
}
|
|
416
|
-
const thatEventSerializer = this
|
|
417
|
-
this
|
|
435
|
+
const thatEventSerializer = this.#eventSerializer
|
|
436
|
+
this.#eventSerializer = new EventSerializer(this.#maxSamples)
|
|
418
437
|
return () => thatEventSerializer.createProfile(startDate, endDate)
|
|
419
438
|
}
|
|
420
439
|
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
'use strict'
|
|
2
|
+
|
|
3
|
+
class PoissonProcessSamplingFilter {
|
|
4
|
+
#currentSamplingInstant = 0
|
|
5
|
+
#nextSamplingInstant
|
|
6
|
+
#samplingInterval
|
|
7
|
+
#resetInterval
|
|
8
|
+
#now
|
|
9
|
+
#lastNow = Number.NEGATIVE_INFINITY
|
|
10
|
+
#samplingInstantCount = 0
|
|
11
|
+
|
|
12
|
+
constructor ({ samplingInterval, now, resetInterval }) {
|
|
13
|
+
if (samplingInterval <= 0) {
|
|
14
|
+
throw new RangeError(`samplingInterval (${samplingInterval}) must be greater than 0`)
|
|
15
|
+
}
|
|
16
|
+
if (resetInterval < samplingInterval) {
|
|
17
|
+
throw new RangeError(
|
|
18
|
+
`resetInterval (${resetInterval}) must be greater than samplingInterval (${samplingInterval})`
|
|
19
|
+
)
|
|
20
|
+
}
|
|
21
|
+
if (typeof now !== 'function') {
|
|
22
|
+
throw new TypeError('now must be a function')
|
|
23
|
+
}
|
|
24
|
+
this.#samplingInterval = samplingInterval
|
|
25
|
+
this.#resetInterval = resetInterval
|
|
26
|
+
this.#now = now
|
|
27
|
+
this.#nextSamplingInstant = this.#callNow()
|
|
28
|
+
this.#setNextSamplingInstant()
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
get currentSamplingInstant () {
|
|
32
|
+
return this.#currentSamplingInstant
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
get nextSamplingInstant () {
|
|
36
|
+
return this.#nextSamplingInstant
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
get samplingInstantCount () {
|
|
40
|
+
return this.#samplingInstantCount
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
#callNow () {
|
|
44
|
+
const nowValue = this.#now()
|
|
45
|
+
if (typeof nowValue !== 'number') {
|
|
46
|
+
throw new TypeError('now() must return a number')
|
|
47
|
+
}
|
|
48
|
+
if (nowValue < this.#lastNow) {
|
|
49
|
+
throw new RangeError('now() must return a value greater than or equal to the last returned value')
|
|
50
|
+
}
|
|
51
|
+
this.#lastNow = nowValue
|
|
52
|
+
return nowValue
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
filter (event) {
|
|
56
|
+
const endTime = event.startTime + event.duration
|
|
57
|
+
// We're using the end times of events as an approximation of current time as events are
|
|
58
|
+
// expected to be reported close to where they ended. If the end time (and thus, presumably, the
|
|
59
|
+
// current time) is past the next sampling instant, we make it the current sampling instant and
|
|
60
|
+
// compute the next sampling instant in its future.
|
|
61
|
+
if (endTime >= this.#nextSamplingInstant) {
|
|
62
|
+
// All observed events are supposed to have happened in the past. For purposes of advancing
|
|
63
|
+
// the next sampling instant, we cap endTime to now(). This protects us from advancing it far
|
|
64
|
+
// into future if we receive an event with erroneously long duration, which would also take
|
|
65
|
+
// many iterations of the below "while" loop.
|
|
66
|
+
const cappedEndTime = Math.min(endTime, this.#callNow())
|
|
67
|
+
|
|
68
|
+
// If nextSamplingInstant is far in cappedEndTime's past, first advance it close to it. This
|
|
69
|
+
// can happen if we didn't receive any events for a while. Since a Poisson process has no
|
|
70
|
+
// memory, we can reset it anytime. This will ensure that the "while" loop below runs at most
|
|
71
|
+
// few iterations.
|
|
72
|
+
const earliestContinuousPast = cappedEndTime - this.#resetInterval
|
|
73
|
+
if (this.#nextSamplingInstant < earliestContinuousPast) {
|
|
74
|
+
this.#nextSamplingInstant = earliestContinuousPast
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
// Advance the next sampling instant until it is in cappedEndTime's future.
|
|
78
|
+
while (cappedEndTime >= this.#nextSamplingInstant) {
|
|
79
|
+
this.#setNextSamplingInstant()
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
// An event is sampled if it started before, and ended on or after a sampling instant. The above
|
|
83
|
+
// while loop will ensure that the ending invariant is always true for the current sampling
|
|
84
|
+
// instant so we don't have to test for it below. Across calls, the invariant also holds as long
|
|
85
|
+
// as the events arrive in endTime order. This is true for events coming from
|
|
86
|
+
// DatadogInstrumentationEventSource; they will be ordered by endTime by virtue of this method
|
|
87
|
+
// being invoked synchronously with the plugins' finish() handler which evaluates
|
|
88
|
+
// performance.now(). OTOH, events coming from NodeAPIEventSource (GC in typical setup) might be
|
|
89
|
+
// somewhat delayed as they are queued by Node, so they can arrive out of order with regard to
|
|
90
|
+
// events coming from the non-queued source. By omitting the endTime check, we will pass through
|
|
91
|
+
// some short events that started and ended before the current sampling instant. OTOH, if we
|
|
92
|
+
// were to check for this.currentSamplingInstant <= endTime, we would discard some long events
|
|
93
|
+
// that also ended before the current sampling instant. We'd rather err on the side of including
|
|
94
|
+
// some short events than excluding some long events.
|
|
95
|
+
return event.startTime < this.#currentSamplingInstant
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
#setNextSamplingInstant () {
|
|
99
|
+
this.#currentSamplingInstant = this.#nextSamplingInstant
|
|
100
|
+
this.#nextSamplingInstant -= Math.log(1 - Math.random()) * this.#samplingInterval
|
|
101
|
+
this.#samplingInstantCount++
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
module.exports = PoissonProcessSamplingFilter
|
|
@@ -75,7 +75,7 @@ class NativeWallProfiler {
|
|
|
75
75
|
_started = false
|
|
76
76
|
|
|
77
77
|
constructor (options = {}) {
|
|
78
|
-
this._samplingIntervalMicros = options.samplingInterval ||
|
|
78
|
+
this._samplingIntervalMicros = (options.samplingInterval || 1e3 / 99) * 1000 // 99hz
|
|
79
79
|
this._flushIntervalMillis = options.flushInterval || 60 * 1e3 // 60 seconds
|
|
80
80
|
this._codeHotspotsEnabled = !!options.codeHotspotsEnabled
|
|
81
81
|
this._endpointCollectionEnabled = !!options.endpointCollectionEnabled
|
|
@@ -215,10 +215,10 @@ class NativeWallProfiler {
|
|
|
215
215
|
|
|
216
216
|
_updateContext (context) {
|
|
217
217
|
if (context.spanId !== null && typeof context.spanId === 'object') {
|
|
218
|
-
context.spanId = context.spanId.
|
|
218
|
+
context.spanId = context.spanId.toBigInt()
|
|
219
219
|
}
|
|
220
220
|
if (context.rootSpanId !== null && typeof context.rootSpanId === 'object') {
|
|
221
|
-
context.rootSpanId = context.rootSpanId.
|
|
221
|
+
context.rootSpanId = context.rootSpanId.toBigInt()
|
|
222
222
|
}
|
|
223
223
|
if (context.webTags !== undefined && context.endpoint === undefined) {
|
|
224
224
|
// endpoint may not be determined yet, but keep it as fallback
|
|
@@ -22,7 +22,7 @@ const kSupportsAckCallback = Symbol('kSupportsAckCallback')
|
|
|
22
22
|
// There MUST NOT exist separate instances of RC clients in a tracer making separate ClientGetConfigsRequest
|
|
23
23
|
// with their own separated Client.ClientState.
|
|
24
24
|
class RemoteConfigManager extends EventEmitter {
|
|
25
|
-
static
|
|
25
|
+
static kPreUpdate = kPreUpdate
|
|
26
26
|
|
|
27
27
|
constructor (config) {
|
|
28
28
|
super()
|
|
@@ -129,6 +129,7 @@
|
|
|
129
129
|
"DD_PROFILING_HEAP_ENABLED": ["A"],
|
|
130
130
|
"DD_PROFILING_PROFILERS": ["A"],
|
|
131
131
|
"DD_PROFILING_SOURCE_MAP": ["A"],
|
|
132
|
+
"DD_PROFILING_TIMELINE_ENABLED": ["A"],
|
|
132
133
|
"DD_PROFILING_UPLOAD_PERIOD": ["A"],
|
|
133
134
|
"DD_PROFILING_V8_PROFILER_BUG_WORKAROUND": ["A"],
|
|
134
135
|
"DD_PROFILING_WALLTIME_ENABLED": ["A"],
|
|
@@ -160,6 +161,7 @@
|
|
|
160
161
|
"DD_TRACE_128_BIT_TRACEID_GENERATION_ENABLED": ["A"],
|
|
161
162
|
"DD_TRACE_128_BIT_TRACEID_LOGGING_ENABLED": ["A"],
|
|
162
163
|
"DD_TRACE_AEROSPIKE_ENABLED": ["A"],
|
|
164
|
+
"DD_TRACE_AI_ENABLED": ["A"],
|
|
163
165
|
"DD_TRACE_AGENT_PORT": ["A"],
|
|
164
166
|
"DD_TRACE_AGENT_PROTOCOL_VERSION": ["A"],
|
|
165
167
|
"DD_TRACE_AGENT_URL": ["A"],
|