dd-trace 4.0.0-pre-e7fe5c1 → 4.0.0-pre-071951e

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.
Files changed (46) hide show
  1. package/package.json +2 -1
  2. package/packages/datadog-instrumentations/src/next.js +6 -1
  3. package/packages/datadog-instrumentations/src/playwright.js +11 -1
  4. package/packages/datadog-plugin-amqp10/src/consumer.js +3 -1
  5. package/packages/datadog-plugin-amqp10/src/producer.js +3 -1
  6. package/packages/datadog-plugin-amqplib/src/client.js +3 -4
  7. package/packages/datadog-plugin-amqplib/src/consumer.js +3 -1
  8. package/packages/datadog-plugin-amqplib/src/producer.js +3 -1
  9. package/packages/datadog-plugin-aws-sdk/src/base.js +3 -0
  10. package/packages/datadog-plugin-aws-sdk/src/services/cloudwatchlogs.js +2 -1
  11. package/packages/datadog-plugin-aws-sdk/src/services/dynamodb.js +4 -2
  12. package/packages/datadog-plugin-aws-sdk/src/services/eventbridge.js +4 -3
  13. package/packages/datadog-plugin-aws-sdk/src/services/kinesis.js +2 -1
  14. package/packages/datadog-plugin-aws-sdk/src/services/lambda.js +1 -0
  15. package/packages/datadog-plugin-aws-sdk/src/services/redshift.js +2 -1
  16. package/packages/datadog-plugin-aws-sdk/src/services/s3.js +2 -1
  17. package/packages/datadog-plugin-aws-sdk/src/services/sns.js +8 -1
  18. package/packages/datadog-plugin-aws-sdk/src/services/sqs.js +7 -1
  19. package/packages/datadog-plugin-google-cloud-pubsub/src/client.js +3 -4
  20. package/packages/datadog-plugin-google-cloud-pubsub/src/consumer.js +3 -1
  21. package/packages/datadog-plugin-google-cloud-pubsub/src/producer.js +3 -1
  22. package/packages/datadog-plugin-kafkajs/src/consumer.js +6 -1
  23. package/packages/datadog-plugin-kafkajs/src/producer.js +3 -1
  24. package/packages/datadog-plugin-rhea/src/consumer.js +3 -1
  25. package/packages/datadog-plugin-rhea/src/producer.js +5 -1
  26. package/packages/dd-trace/src/config.js +18 -23
  27. package/packages/dd-trace/src/encode/agentless-ci-visibility.js +14 -4
  28. package/packages/dd-trace/src/plugin_manager.js +0 -2
  29. package/packages/dd-trace/src/plugins/client.js +2 -3
  30. package/packages/dd-trace/src/plugins/consumer.js +2 -17
  31. package/packages/dd-trace/src/plugins/incoming.js +7 -0
  32. package/packages/dd-trace/src/plugins/{outbound.js → outgoing.js} +2 -2
  33. package/packages/dd-trace/src/plugins/producer.js +2 -17
  34. package/packages/dd-trace/src/plugins/server.js +2 -2
  35. package/packages/dd-trace/src/plugins/tracing.js +0 -11
  36. package/packages/dd-trace/src/profiling/constants.js +0 -1
  37. package/packages/dd-trace/src/profiling/profilers/space.js +1 -3
  38. package/packages/dd-trace/src/proxy.js +4 -0
  39. package/packages/dd-trace/src/serverless.js +25 -0
  40. package/version.js +9 -0
  41. package/packages/dd-trace/src/plugins/inbound.js +0 -7
  42. package/packages/dd-trace/src/service-naming/index.js +0 -41
  43. package/packages/dd-trace/src/service-naming/schemas/definition.js +0 -28
  44. package/packages/dd-trace/src/service-naming/schemas/index.js +0 -6
  45. package/packages/dd-trace/src/service-naming/schemas/v0.js +0 -66
  46. package/packages/dd-trace/src/service-naming/schemas/v1.js +0 -58
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "dd-trace",
3
- "version": "4.0.0-pre-e7fe5c1",
3
+ "version": "4.0.0-pre-071951e",
4
4
  "description": "Datadog APM tracing client for JavaScript",
5
5
  "main": "index.js",
6
6
  "typings": "index.d.ts",
@@ -36,6 +36,7 @@
36
36
  "test:integration:cucumber": "mocha --colors --timeout 30000 \"integration-tests/cucumber/*.spec.js\"",
37
37
  "test:integration:cypress": "mocha --colors --timeout 30000 \"integration-tests/cypress/*.spec.js\"",
38
38
  "test:integration:playwright": "mocha --colors --timeout 30000 \"integration-tests/playwright/*.spec.js\"",
39
+ "test:integration:serverless": "mocha --colors --timeout 30000 \"integration-tests/serverless/*.spec.js\"",
39
40
  "test:shimmer": "mocha --colors 'packages/datadog-shimmer/test/**/*.spec.js'",
40
41
  "test:shimmer:ci": "nyc --no-clean --include 'packages/datadog-shimmer/src/**/*.js' -- npm run test:shimmer",
41
42
  "leak:core": "node ./scripts/install_plugin_modules && (cd packages/memwatch && yarn) && NODE_PATH=./packages/memwatch/node_modules node --no-warnings ./node_modules/.bin/tape 'packages/dd-trace/test/leak/**/*.js'",
@@ -4,6 +4,7 @@
4
4
 
5
5
  const { channel, addHook, AsyncResource } = require('./helpers/instrument')
6
6
  const shimmer = require('../../datadog-shimmer')
7
+ const { MAJOR } = require('../../../version')
7
8
 
8
9
  const startChannel = channel('apm:next:request:start')
9
10
  const finishChannel = channel('apm:next:request:finish')
@@ -168,7 +169,11 @@ addHook({ name: 'next', versions: ['>=11.1 <13.2'], file: 'dist/server/next-serv
168
169
  return nextServer
169
170
  })
170
171
 
171
- addHook({ name: 'next', versions: ['>=9.5 <11.1'], file: 'dist/next-server/server/next-server.js' }, nextServer => {
172
+ addHook({
173
+ name: 'next',
174
+ versions: MAJOR >= 4 ? ['>=10.2 <11.1'] : ['>=9.5 <11.1'],
175
+ file: 'dist/next-server/server/next-server.js'
176
+ }, nextServer => {
172
177
  const Server = nextServer.default
173
178
 
174
179
  shimmer.wrap(Server.prototype, 'handleRequest', wrapHandleRequest)
@@ -214,10 +214,20 @@ function runnerHook (runnerExport, playwrightVersion) {
214
214
  })
215
215
 
216
216
  const runAllTestsReturn = await runAllTests.apply(this, arguments)
217
+
218
+ Object.values(remainingTestsByFile).forEach(tests => {
219
+ // `tests` should normally be empty, but if it isn't,
220
+ // there were tests that did not go through `testBegin` or `testEnd`,
221
+ // because they were skipped
222
+ tests.forEach(test => {
223
+ testBeginHandler(test)
224
+ testEndHandler(test, 'skip')
225
+ })
226
+ })
227
+
217
228
  const sessionStatus = runAllTestsReturn.status || runAllTestsReturn
218
229
 
219
230
  let onDone
220
-
221
231
  const flushWait = new Promise(resolve => {
222
232
  onDone = resolve
223
233
  })
@@ -11,9 +11,11 @@ class Amqp10ConsumerPlugin extends ConsumerPlugin {
11
11
  const source = getShortName(link)
12
12
  const address = getAddress(link)
13
13
 
14
- this.startSpan({
14
+ this.startSpan('amqp.receive', {
15
+ service: this.config.service || `${this.tracer._service}-amqp`,
15
16
  resource: ['receive', source].filter(v => v).join(' '),
16
17
  type: 'worker',
18
+ kind: 'consumer',
17
19
  meta: {
18
20
  'amqp.link.source.address': source,
19
21
  'amqp.link.role': 'receiver',
@@ -13,8 +13,10 @@ class Amqp10ProducerPlugin extends ProducerPlugin {
13
13
  const address = getAddress(link)
14
14
  const target = getShortName(link)
15
15
 
16
- this.startSpan({
16
+ this.startSpan('amqp.send', {
17
+ service: this.config.service || `${this.tracer._service}-amqp`,
17
18
  resource: ['send', target].filter(v => v).join(' '),
19
+ kind: 'producer',
18
20
  meta: {
19
21
  'amqp.link.target.address': target,
20
22
  'amqp.link.role': 'sender',
@@ -7,7 +7,6 @@ const { getResourceName } = require('./util')
7
7
 
8
8
  class AmqplibClientPlugin extends ClientPlugin {
9
9
  static get id () { return 'amqplib' }
10
- static get type () { return 'messaging' }
11
10
  static get operation () { return 'command' }
12
11
 
13
12
  start ({ channel = {}, method, fields }) {
@@ -15,10 +14,10 @@ class AmqplibClientPlugin extends ClientPlugin {
15
14
  if (method === 'basic.publish') return
16
15
 
17
16
  const stream = (channel.connection && channel.connection.stream) || {}
18
- const span = this.startSpan(this.operationName(), {
19
- service: this.config.service || this.serviceName(),
17
+ const span = this.startSpan('amqp.command', {
18
+ service: this.config.service || `${this.tracer._service}-amqp`,
20
19
  resource: getResourceName(method, fields),
21
- kind: this.constructor.kind,
20
+ kind: 'client',
22
21
  meta: {
23
22
  'out.host': stream._host,
24
23
  [CLIENT_PORT_KEY]: stream.remotePort,
@@ -13,9 +13,11 @@ class AmqplibConsumerPlugin extends ConsumerPlugin {
13
13
 
14
14
  const childOf = extract(this.tracer, message)
15
15
 
16
- this.startSpan({
16
+ this.startSpan('amqp.command', {
17
17
  childOf,
18
+ service: this.config.service || `${this.tracer._service}-amqp`,
18
19
  resource: getResourceName(method, fields),
20
+ kind: 'consumer',
19
21
  type: 'worker',
20
22
  meta: {
21
23
  'amqp.queue': fields.queue,
@@ -13,8 +13,10 @@ class AmqplibProducerPlugin extends ProducerPlugin {
13
13
  if (method !== 'basic.publish') return
14
14
 
15
15
  const stream = (channel.connection && channel.connection.stream) || {}
16
- const span = this.startSpan({
16
+ const span = this.startSpan('amqp.command', {
17
+ service: this.config.service || `${this.tracer._service}-amqp`,
17
18
  resource: getResourceName(method, fields),
19
+ kind: 'producer',
18
20
  meta: {
19
21
  'out.host': stream._host,
20
22
  [CLIENT_PORT_KEY]: stream.remotePort,
@@ -38,6 +38,8 @@ class BaseAwsSdkPlugin extends Plugin {
38
38
  'service.name': serviceName,
39
39
  'aws.operation': operation,
40
40
  'aws.region': awsRegion,
41
+ 'region': awsRegion,
42
+ 'aws_service': awsService,
41
43
  'aws.service': awsService,
42
44
  'component': 'aws-sdk'
43
45
  }
@@ -60,6 +62,7 @@ class BaseAwsSdkPlugin extends Plugin {
60
62
  const { span } = store
61
63
  if (!span) return
62
64
  span.setTag('aws.region', region)
65
+ span.setTag('region', region)
63
66
  })
64
67
 
65
68
  this.addSub(`apm:aws:request:complete:${this.serviceIdentifier}`, ({ response }) => {
@@ -12,7 +12,8 @@ class CloudwatchLogs extends BaseAwsSdkPlugin {
12
12
 
13
13
  return Object.assign(tags, {
14
14
  'resource.name': `${operation} ${params.logGroupName}`,
15
- 'aws.cloudwatch.logs.log_group_name': params.logGroupName
15
+ 'aws.cloudwatch.logs.log_group_name': params.logGroupName,
16
+ 'loggroupname': params.logGroupName
16
17
  })
17
18
  }
18
19
  }
@@ -12,7 +12,8 @@ class DynamoDb extends BaseAwsSdkPlugin {
12
12
  if (params.TableName) {
13
13
  Object.assign(tags, {
14
14
  'resource.name': `${operation} ${params.TableName}`,
15
- 'aws.dynamodb.table_name': params.TableName
15
+ 'aws.dynamodb.table_name': params.TableName,
16
+ 'tablename': params.TableName
16
17
  })
17
18
  }
18
19
 
@@ -27,7 +28,8 @@ class DynamoDb extends BaseAwsSdkPlugin {
27
28
  // also add span type to match serverless convention
28
29
  Object.assign(tags, {
29
30
  'resource.name': `${operation} ${tableName}`,
30
- 'aws.dynamodb.table_name': tableName
31
+ 'aws.dynamodb.table_name': tableName,
32
+ 'tablename': tableName
31
33
  })
32
34
  }
33
35
  }
@@ -7,10 +7,11 @@ class EventBridge extends BaseAwsSdkPlugin {
7
7
 
8
8
  generateTags (params, operation, response) {
9
9
  if (!params || !params.source) return {}
10
-
10
+ const rulename = params.Name ? params.Name : ''
11
11
  return {
12
- 'resource.name': `${operation} ${params.source}`,
13
- 'aws.eventbridge.source': params.source
12
+ 'resource.name': operation ? `${operation} ${params.source}` : params.source,
13
+ 'aws.eventbridge.source': `${params.source}`,
14
+ 'rulename': `${rulename}`
14
15
  }
15
16
  }
16
17
 
@@ -9,7 +9,8 @@ class Kinesis extends BaseAwsSdkPlugin {
9
9
 
10
10
  return {
11
11
  'resource.name': `${operation} ${params.StreamName}`,
12
- 'aws.kinesis.stream_name': params.StreamName
12
+ 'aws.kinesis.stream_name': params.StreamName,
13
+ 'streamname': params.StreamName
13
14
  }
14
15
  }
15
16
 
@@ -13,6 +13,7 @@ class Lambda extends BaseAwsSdkPlugin {
13
13
 
14
14
  return Object.assign(tags, {
15
15
  'resource.name': `${operation} ${params.FunctionName}`,
16
+ 'functionname': params.FunctionName,
16
17
  'aws.lambda': params.FunctionName
17
18
  })
18
19
  }
@@ -12,7 +12,8 @@ class Redshift extends BaseAwsSdkPlugin {
12
12
 
13
13
  return Object.assign(tags, {
14
14
  'resource.name': `${operation} ${params.ClusterIdentifier}`,
15
- 'aws.redshift.cluster_identifier': params.ClusterIdentifier
15
+ 'aws.redshift.cluster_identifier': params.ClusterIdentifier,
16
+ 'clusteridentifier': params.ClusterIdentifier
16
17
  })
17
18
  }
18
19
  }
@@ -12,7 +12,8 @@ class S3 extends BaseAwsSdkPlugin {
12
12
 
13
13
  return Object.assign(tags, {
14
14
  'resource.name': `${operation} ${params.Bucket}`,
15
- 'aws.s3.bucket_name': params.Bucket
15
+ 'aws.s3.bucket_name': params.Bucket,
16
+ 'bucketname': params.Bucket
16
17
  })
17
18
  }
18
19
  }
@@ -9,10 +9,17 @@ class Sns extends BaseAwsSdkPlugin {
9
9
  if (!params) return {}
10
10
 
11
11
  if (!params.TopicArn && !(response.data && response.data.TopicArn)) return {}
12
+ const TopicArn = params.TopicArn || response.data.TopicArn
13
+ // Split the ARN into its parts
14
+ // ex.'arn:aws:sns:us-east-1:123456789012:my-topic'
15
+ const arnParts = TopicArn.split(':')
12
16
 
17
+ // Get the topic name from the last part of the ARN
18
+ const topicName = arnParts[arnParts.length - 1]
13
19
  return {
14
20
  'resource.name': `${operation} ${params.TopicArn || response.data.TopicArn}`,
15
- 'aws.sns.topic_arn': params.TopicArn || response.data.TopicArn
21
+ 'aws.sns.topic_arn': TopicArn,
22
+ 'topicname': topicName
16
23
  }
17
24
 
18
25
  // TODO: should arn be sanitized or quantized in some way here,
@@ -59,10 +59,16 @@ class Sqs extends BaseAwsSdkPlugin {
59
59
  const tags = {}
60
60
 
61
61
  if (!params || (!params.QueueName && !params.QueueUrl)) return tags
62
+ // 'https://sqs.us-east-1.amazonaws.com/123456789012/my-queue';
63
+ let queueName = params.QueueName
64
+ if (params.QueueUrl) {
65
+ queueName = params.QueueUrl.split('/')[params.QueueUrl.split('/').length - 1]
66
+ }
62
67
 
63
68
  Object.assign(tags, {
64
69
  'resource.name': `${operation} ${params.QueueName || params.QueueUrl}`,
65
- 'aws.sqs.queue_name': params.QueueName || params.QueueUrl
70
+ 'aws.sqs.queue_name': params.QueueName || params.QueueUrl,
71
+ 'queuename': queueName
66
72
  })
67
73
 
68
74
  switch (operation) {
@@ -4,16 +4,15 @@ const ClientPlugin = require('../../dd-trace/src/plugins/client')
4
4
 
5
5
  class GoogleCloudPubsubClientPlugin extends ClientPlugin {
6
6
  static get id () { return 'google-cloud-pubsub' }
7
- static get type () { return 'messaging' }
8
7
  static get operation () { return 'request' }
9
8
 
10
9
  start ({ request, api, projectId }) {
11
10
  if (api === 'publish') return
12
11
 
13
- this.startSpan(this.operationName(), {
14
- service: this.config.service || this.serviceName(),
12
+ this.startSpan('pubsub.request', {
13
+ service: this.config.service || `${this.tracer._service}-pubsub`,
15
14
  resource: [api, request.name].filter(x => x).join(' '),
16
- kind: this.constructor.kind,
15
+ kind: 'client',
17
16
  meta: {
18
17
  'pubsub.method': api,
19
18
  'gcloud.project_id': projectId
@@ -11,9 +11,11 @@ class GoogleCloudPubsubConsumerPlugin extends ConsumerPlugin {
11
11
  const topic = subscription.metadata && subscription.metadata.topic
12
12
  const childOf = this.tracer.extract('text_map', message.attributes) || null
13
13
 
14
- this.startSpan({
14
+ this.startSpan('pubsub.receive', {
15
15
  childOf,
16
+ service: this.config.service,
16
17
  resource: topic,
18
+ kind: 'consumer',
17
19
  type: 'worker',
18
20
  meta: {
19
21
  'gcloud.project_id': subscription.pubsub.projectId,
@@ -11,8 +11,10 @@ class GoogleCloudPubsubProducerPlugin extends ProducerPlugin {
11
11
 
12
12
  const messages = request.messages || []
13
13
  const topic = request.topic
14
- const span = this.startSpan({ // TODO: rename
14
+ const span = this.startSpan('pubsub.request', { // TODO: rename
15
+ service: this.config.service || `${this.tracer._service}-pubsub`,
15
16
  resource: `${api} ${topic}`,
17
+ kind: 'producer',
16
18
  meta: {
17
19
  'gcloud.project_id': projectId,
18
20
  'pubsub.method': api, // TODO: remove
@@ -8,9 +8,12 @@ class KafkajsConsumerPlugin extends ConsumerPlugin {
8
8
 
9
9
  start ({ topic, partition, message }) {
10
10
  const childOf = extract(this.tracer, message.headers)
11
- this.startSpan({
11
+
12
+ this.startSpan('kafka.consume', {
12
13
  childOf,
14
+ service: this.config.service || `${this.tracer._service}-kafka`,
13
15
  resource: topic,
16
+ kind: 'consumer',
14
17
  type: 'worker',
15
18
  meta: {
16
19
  'component': 'kafkajs',
@@ -30,6 +33,8 @@ function extract (tracer, bufferMap) {
30
33
  const textMap = {}
31
34
 
32
35
  for (const key of Object.keys(bufferMap)) {
36
+ if (bufferMap[key] === null || bufferMap[key] === undefined) continue
37
+
33
38
  textMap[key] = bufferMap[key].toString()
34
39
  }
35
40
 
@@ -7,8 +7,10 @@ class KafkajsProducerPlugin extends ProducerPlugin {
7
7
  static get operation () { return 'produce' }
8
8
 
9
9
  start ({ topic, messages }) {
10
- const span = this.startSpan({
10
+ const span = this.startSpan('kafka.produce', {
11
+ service: this.config.service || `${this.tracer._service}-kafka`,
11
12
  resource: topic,
13
+ kind: 'producer',
12
14
  meta: {
13
15
  'component': 'kafkajs',
14
16
  'kafka.topic': topic
@@ -19,10 +19,12 @@ class RheaConsumerPlugin extends ConsumerPlugin {
19
19
  const name = getResourceNameFromMessage(msgObj)
20
20
  const childOf = extractTextMap(msgObj, this.tracer)
21
21
 
22
- this.startSpan({
22
+ this.startSpan('amqp.receive', {
23
23
  childOf,
24
+ service: this.config.service,
24
25
  resource: name,
25
26
  type: 'worker',
27
+ kind: 'consumer',
26
28
  meta: {
27
29
  'component': 'rhea',
28
30
  'amqp.link.source.address': name,
@@ -9,13 +9,17 @@ class RheaProducerPlugin extends ProducerPlugin {
9
9
 
10
10
  constructor (...args) {
11
11
  super(...args)
12
+
12
13
  this.addTraceSub('encode', this.encode.bind(this))
13
14
  }
14
15
 
15
16
  start ({ targetAddress, host, port }) {
16
17
  const name = targetAddress || 'amq.topic'
17
- this.startSpan({
18
+
19
+ this.startSpan('amqp.send', {
20
+ service: this.config.service || `${this.tracer._service}-amqp-producer`,
18
21
  resource: name,
22
+ kind: 'producer',
19
23
  meta: {
20
24
  'component': 'rhea',
21
25
  'amqp.link.target.address': name,
@@ -34,19 +34,6 @@ function safeJsonParse (input) {
34
34
  }
35
35
  }
36
36
 
37
- const namingVersions = ['v0', 'v1']
38
- const defaultVersion = 'v0'
39
-
40
- function validateNamingVersion (versionString) {
41
- if (!namingVersions.includes(versionString)) {
42
- log.warn(
43
- `Unexpected input for config.spanAttributeSchema, picked default ${defaultVersion}`
44
- )
45
- return defaultVersion
46
- }
47
- return versionString
48
- }
49
-
50
37
  // Shallow clone with property name remapping
51
38
  function remapify (input, mappings) {
52
39
  if (!input) return
@@ -172,6 +159,8 @@ class Config {
172
159
  process.env.DD_SERVICE_NAME ||
173
160
  this.tags.service ||
174
161
  process.env.AWS_LAMBDA_FUNCTION_NAME ||
162
+ process.env.FUNCTION_NAME || // Google Cloud Function Name set by deprecated runtimes
163
+ process.env.K_SERVICE || // Google Cloud Function Name set by newer runtimes
175
164
  pkg.name ||
176
165
  'node'
177
166
  const DD_SERVICE_MAPPING = coalesce(
@@ -196,9 +185,18 @@ class Config {
196
185
  process.env.DD_TRACE_STARTUP_LOGS,
197
186
  false
198
187
  )
188
+
189
+ const inAWSLambda = process.env.AWS_LAMBDA_FUNCTION_NAME !== undefined
190
+
191
+ const isDeprecatedGCPFunction = process.env.FUNCTION_NAME !== undefined && process.env.GCP_PROJECT !== undefined
192
+ const isNewerGCPFunction = process.env.K_SERVICE !== undefined && process.env.FUNCTION_TARGET !== undefined
193
+ const isGCPFunction = isDeprecatedGCPFunction || isNewerGCPFunction
194
+
195
+ const inServerlessEnvironment = inAWSLambda || isGCPFunction
196
+
199
197
  const DD_TRACE_TELEMETRY_ENABLED = coalesce(
200
198
  process.env.DD_TRACE_TELEMETRY_ENABLED,
201
- !process.env.AWS_LAMBDA_FUNCTION_NAME
199
+ !inServerlessEnvironment
202
200
  )
203
201
  const DD_TELEMETRY_DEBUG_ENABLED = coalesce(
204
202
  process.env.DD_TELEMETRY_DEBUG_ENABLED,
@@ -273,9 +271,7 @@ class Config {
273
271
  process.env.DD_TRACE_EXPERIMENTAL_GET_RUM_DATA_ENABLED,
274
272
  false
275
273
  )
276
- const DD_TRACE_SPAN_ATTRIBUTE_SCHEMA = validateNamingVersion(
277
- process.env.DD_TRACE_SPAN_ATTRIBUTE_SCHEMA
278
- )
274
+
279
275
  const DD_TRACE_X_DATADOG_TAGS_MAX_LENGTH = coalesce(
280
276
  process.env.DD_TRACE_X_DATADOG_TAGS_MAX_LENGTH,
281
277
  '512'
@@ -284,7 +280,7 @@ class Config {
284
280
  const DD_TRACE_STATS_COMPUTATION_ENABLED = coalesce(
285
281
  options.stats,
286
282
  process.env.DD_TRACE_STATS_COMPUTATION_ENABLED,
287
- false
283
+ isGCPFunction
288
284
  )
289
285
 
290
286
  const DD_TRACE_128_BIT_TRACEID_GENERATION_ENABLED = coalesce(
@@ -351,12 +347,10 @@ ken|consumer_?(?:id|key|secret)|sign(?:ed|ature)?|auth(?:entication|orization)?)
351
347
  maybeFile(process.env.DD_APPSEC_HTTP_BLOCKED_TEMPLATE_JSON)
352
348
  )
353
349
 
354
- const inAWSLambda = process.env.AWS_LAMBDA_FUNCTION_NAME !== undefined
355
-
356
350
  const remoteConfigOptions = options.remoteConfig || {}
357
351
  const DD_REMOTE_CONFIGURATION_ENABLED = coalesce(
358
352
  process.env.DD_REMOTE_CONFIGURATION_ENABLED && isTrue(process.env.DD_REMOTE_CONFIGURATION_ENABLED),
359
- !inAWSLambda
353
+ !inServerlessEnvironment
360
354
  )
361
355
  const DD_REMOTE_CONFIG_POLL_INTERVAL_SECONDS = coalesce(
362
356
  parseInt(remoteConfigOptions.pollInterval),
@@ -439,7 +433,7 @@ ken|consumer_?(?:id|key|secret)|sign(?:ed|ature)?|auth(?:entication|orization)?)
439
433
  })
440
434
  }
441
435
 
442
- const defaultFlushInterval = inAWSLambda ? 0 : 2000
436
+ const defaultFlushInterval = inServerlessEnvironment ? 0 : 2000
443
437
 
444
438
  this.tracing = !isFalse(DD_TRACING_ENABLED)
445
439
  this.dbmPropagationMode = DD_DBM_PROPAGATION_MODE
@@ -482,7 +476,6 @@ ken|consumer_?(?:id|key|secret)|sign(?:ed|ature)?|auth(?:entication|orization)?)
482
476
  sourceMap: !isFalse(DD_PROFILING_SOURCE_MAP),
483
477
  exporters: DD_PROFILING_EXPORTERS
484
478
  }
485
- this.spanAttributeSchema = DD_TRACE_SPAN_ATTRIBUTE_SCHEMA
486
479
  this.lookup = options.lookup
487
480
  this.startupLogs = isTrue(DD_TRACE_STARTUP_LOGS)
488
481
  // Disabled for CI Visibility's agentless
@@ -529,6 +522,8 @@ ken|consumer_?(?:id|key|secret)|sign(?:ed|ature)?|auth(?:entication|orization)?)
529
522
  this.traceId128BitGenerationEnabled = isTrue(DD_TRACE_128_BIT_TRACEID_GENERATION_ENABLED)
530
523
  this.traceId128BitLoggingEnabled = isTrue(DD_TRACE_128_BIT_TRACEID_LOGGING_ENABLED)
531
524
 
525
+ this.isGCPFunction = isGCPFunction
526
+
532
527
  tagger.add(this.tags, {
533
528
  service: this.service,
534
529
  env: this.env,
@@ -129,12 +129,17 @@ class AgentlessCiVisibilityEncoder extends AgentEncoder {
129
129
  _encodeEventContent (bytes, content) {
130
130
  const keysLength = Object.keys(content).length
131
131
 
132
+ let totalKeysLength = keysLength
132
133
  if (content.meta.test_session_id) {
133
- this._encodeMapPrefix(bytes, keysLength + 3)
134
- } else {
135
- this._encodeMapPrefix(bytes, keysLength)
134
+ totalKeysLength = totalKeysLength + 1
136
135
  }
137
-
136
+ if (content.meta.test_module_id) {
137
+ totalKeysLength = totalKeysLength + 1
138
+ }
139
+ if (content.meta.test_suite_id) {
140
+ totalKeysLength = totalKeysLength + 1
141
+ }
142
+ this._encodeMapPrefix(bytes, totalKeysLength)
138
143
  if (content.type) {
139
144
  this._encodeString(bytes, 'type')
140
145
  this._encodeString(bytes, content.type)
@@ -170,15 +175,20 @@ class AgentlessCiVisibilityEncoder extends AgentEncoder {
170
175
  this._encodeString(bytes, 'test_session_id')
171
176
  this._encodeId(bytes, id(content.meta.test_session_id, 10))
172
177
  delete content.meta.test_session_id
178
+ }
173
179
 
180
+ if (content.meta.test_module_id) {
174
181
  this._encodeString(bytes, 'test_module_id')
175
182
  this._encodeId(bytes, id(content.meta.test_module_id, 10))
176
183
  delete content.meta.test_module_id
184
+ }
177
185
 
186
+ if (content.meta.test_suite_id) {
178
187
  this._encodeString(bytes, 'test_suite_id')
179
188
  this._encodeId(bytes, id(content.meta.test_suite_id, 10))
180
189
  delete content.meta.test_suite_id
181
190
  }
191
+
182
192
  this._encodeString(bytes, 'meta')
183
193
  this._encodeMap(bytes, content.meta)
184
194
  this._encodeString(bytes, 'metrics')
@@ -4,7 +4,6 @@ const { channel } = require('../../diagnostics_channel')
4
4
  const { isFalse } = require('./util')
5
5
  const plugins = require('./plugins')
6
6
  const log = require('./log')
7
- const Nomenclature = require('./service-naming')
8
7
 
9
8
  const loadChannel = channel('dd-trace:instrumentation:load')
10
9
 
@@ -97,7 +96,6 @@ module.exports = class PluginManager {
97
96
  // like instrumenter.enable()
98
97
  configure (config = {}) {
99
98
  this._tracerConfig = config
100
- Nomenclature.configure(config)
101
99
 
102
100
  for (const name in pluginClasses) {
103
101
  this.loadPlugin(name)
@@ -1,10 +1,9 @@
1
1
  'use strict'
2
2
 
3
- const OutboundPlugin = require('./outbound')
3
+ const OutgoingPlugin = require('./outgoing')
4
4
 
5
- class ClientPlugin extends OutboundPlugin {
5
+ class ClientPlugin extends OutgoingPlugin {
6
6
  static get operation () { return 'request' }
7
- static get kind () { return 'client' }
8
7
  }
9
8
 
10
9
  module.exports = ClientPlugin
@@ -1,24 +1,9 @@
1
1
  'use strict'
2
2
 
3
- const InboundPlugin = require('./inbound')
3
+ const IncomingPlugin = require('./incoming')
4
4
 
5
- class ConsumerPlugin extends InboundPlugin {
5
+ class ConsumerPlugin extends IncomingPlugin {
6
6
  static get operation () { return 'receive' }
7
- static get kind () { return 'consumer' }
8
- static get type () { return 'messaging' }
9
-
10
- startSpan (options) {
11
- const spanDefaults = {
12
- service: this.config.service || this.serviceName(),
13
- kind: this.constructor.kind
14
- }
15
- Object.keys(spanDefaults).forEach(
16
- key => {
17
- if (!options[key]) options[key] = spanDefaults[key]
18
- }
19
- )
20
- return super.startSpan(this.operationName(), options)
21
- }
22
7
  }
23
8
 
24
9
  module.exports = ConsumerPlugin
@@ -0,0 +1,7 @@
1
+ 'use strict'
2
+
3
+ const TracingPlugin = require('./tracing')
4
+
5
+ class IncomingPlugin extends TracingPlugin {}
6
+
7
+ module.exports = IncomingPlugin
@@ -4,7 +4,7 @@ const { CLIENT_PORT_KEY } = require('../constants')
4
4
  const TracingPlugin = require('./tracing')
5
5
 
6
6
  // TODO: Exit span on finish when AsyncResource instances are removed.
7
- class OutboundPlugin extends TracingPlugin {
7
+ class OutgoingPlugin extends TracingPlugin {
8
8
  constructor (...args) {
9
9
  super(...args)
10
10
 
@@ -29,4 +29,4 @@ class OutboundPlugin extends TracingPlugin {
29
29
  }
30
30
  }
31
31
 
32
- module.exports = OutboundPlugin
32
+ module.exports = OutgoingPlugin
@@ -1,24 +1,9 @@
1
1
  'use strict'
2
2
 
3
- const OutboundPlugin = require('./outbound')
3
+ const OutgoingPlugin = require('./outgoing')
4
4
 
5
- class ProducerPlugin extends OutboundPlugin {
5
+ class ProducerPlugin extends OutgoingPlugin {
6
6
  static get operation () { return 'publish' }
7
- static get kind () { return 'producer' }
8
- static get type () { return 'messaging' }
9
-
10
- startSpan (options) {
11
- const spanDefaults = {
12
- service: this.config.service || this.serviceName(),
13
- kind: this.constructor.kind
14
- }
15
- Object.keys(spanDefaults).forEach(
16
- key => {
17
- if (!options[key]) options[key] = spanDefaults[key]
18
- }
19
- )
20
- return super.startSpan(this.operationName(), options)
21
- }
22
7
  }
23
8
 
24
9
  module.exports = ProducerPlugin
@@ -1,8 +1,8 @@
1
1
  'use strict'
2
2
 
3
- const InboundPlugin = require('./inbound')
3
+ const IncomingPlugin = require('./incoming')
4
4
 
5
- class ServerPlugin extends InboundPlugin {
5
+ class ServerPlugin extends IncomingPlugin {
6
6
  static get operation () { return 'request' }
7
7
  }
8
8
 
@@ -4,7 +4,6 @@ const Plugin = require('./plugin')
4
4
  const { storage } = require('../../../datadog-core')
5
5
  const analyticsSampler = require('../analytics_sampler')
6
6
  const { COMPONENT } = require('../constants')
7
- const Nomenclature = require('../service-naming')
8
7
 
9
8
  class TracingPlugin extends Plugin {
10
9
  constructor (...args) {
@@ -32,16 +31,6 @@ class TracingPlugin extends Plugin {
32
31
  return store && store.span
33
32
  }
34
33
 
35
- serviceName (serviceArgs) {
36
- const { type, id, kind } = this.constructor
37
- return Nomenclature.serviceName(type, kind, id, serviceArgs)
38
- }
39
-
40
- operationName (opNameArgs) {
41
- const { type, id, kind } = this.constructor
42
- return Nomenclature.opName(type, kind, id, opNameArgs)
43
- }
44
-
45
34
  configure (config) {
46
35
  return super.configure({
47
36
  ...config,
@@ -9,7 +9,6 @@ const snapshotKinds = Object.freeze({
9
9
  const oomExportStrategies = Object.freeze({
10
10
  PROCESS: 'process',
11
11
  ASYNC_CALLBACK: 'async',
12
- INTERRUPT_CALLBACK: 'interrupt',
13
12
  LOGS: 'logs'
14
13
  })
15
14
 
@@ -3,9 +3,7 @@
3
3
  const { oomExportStrategies } = require('../constants')
4
4
 
5
5
  function strategiesToCallbackMode (strategies, callbackMode) {
6
- const hasInterrupt = strategies.includes(oomExportStrategies.INTERRUPT_CALLBACK) ? callbackMode.Interrupt : 0
7
- const hasCallback = strategies.includes(oomExportStrategies.ASYNC_CALLBACK) ? callbackMode.Async : 0
8
- return hasInterrupt | hasCallback
6
+ return strategies.includes(oomExportStrategies.ASYNC_CALLBACK) ? callbackMode.Async : 0
9
7
  }
10
8
 
11
9
  class NativeSpaceProfiler {
@@ -30,6 +30,10 @@ class Tracer extends NoopProxy {
30
30
  remoteConfig.enable(config)
31
31
  }
32
32
 
33
+ if (config.isGCPFunction) {
34
+ require('./serverless').maybeStartServerlessMiniAgent()
35
+ }
36
+
33
37
  if (config.profiling.enabled) {
34
38
  // do not stop tracer initialization if the profiler fails to be imported
35
39
  try {
@@ -0,0 +1,25 @@
1
+ 'use strict'
2
+
3
+ function maybeStartServerlessMiniAgent () {
4
+ let rustBinaryPath =
5
+ '/workspace/node_modules/@datadog/sma/datadog-serverless-agent-linux-amd64/datadog-serverless-trace-mini-agent'
6
+ if (process.env.DD_MINI_AGENT_PATH !== undefined) {
7
+ rustBinaryPath = process.env.DD_MINI_AGENT_PATH
8
+ }
9
+ const log = require('./log')
10
+ const fs = require('fs')
11
+
12
+ // trying to spawn with an invalid path will return a non-descriptive error, so we want to catch
13
+ // invalid paths and log our own error.
14
+ if (!fs.existsSync(rustBinaryPath)) {
15
+ log.error('Serverless Mini Agent did not start. Could not find mini agent binary.')
16
+ return
17
+ }
18
+ try {
19
+ require('child_process').spawn(rustBinaryPath, { stdio: 'inherit' })
20
+ } catch (err) {
21
+ log.error(`Error spawning mini agent process: ${err}`)
22
+ }
23
+ }
24
+
25
+ module.exports = { maybeStartServerlessMiniAgent }
package/version.js ADDED
@@ -0,0 +1,9 @@
1
+ 'use strict'
2
+
3
+ const matches = require('./package.json').version.match(/^(\d+)\.(\d+)\.(\d+)/)
4
+
5
+ module.exports = {
6
+ MAJOR: parseInt(matches[1]),
7
+ MINOR: parseInt(matches[2]),
8
+ PATCH: parseInt(matches[3])
9
+ }
@@ -1,7 +0,0 @@
1
- 'use strict'
2
-
3
- const TracingPlugin = require('./tracing')
4
-
5
- class InboundPlugin extends TracingPlugin {}
6
-
7
- module.exports = InboundPlugin
@@ -1,41 +0,0 @@
1
- const { schemaDefinitions } = require('./schemas')
2
-
3
- const kindMap = {
4
- messaging: {
5
- client: 'controlPlane',
6
- consumer: 'inbound',
7
- producer: 'outbound'
8
- }
9
- }
10
-
11
- class SchemaManager {
12
- constructor () {
13
- this.schemas = schemaDefinitions
14
- this.config = { spanAttributeSchema: 'v0' }
15
- }
16
-
17
- get schema () {
18
- return this.schemas[this.version]
19
- }
20
-
21
- get version () {
22
- return this.config.spanAttributeSchema
23
- }
24
-
25
- opName (type, kind, plugin, opNameArgs) {
26
- return this.schema.getOpName(type, kindMap[type][kind], plugin, opNameArgs)
27
- }
28
-
29
- serviceName (type, kind, plugin, serviceNameArgs) {
30
- return this.schema.getServiceName(type, kindMap[type][kind], plugin, serviceNameArgs)
31
- }
32
-
33
- configure (config = {}) {
34
- this.config = config
35
- Object.values(this.schemas).forEach(schemaDef => {
36
- schemaDef.configure(config)
37
- })
38
- }
39
- }
40
-
41
- module.exports = new SchemaManager()
@@ -1,28 +0,0 @@
1
- class SchemaDefinition {
2
- constructor (schema) {
3
- this.schema = schema
4
- }
5
-
6
- getSchemaItem (type, subType, plugin) {
7
- const schema = this.schema
8
- if (schema && schema[type] && schema[type][subType] && schema[type][subType][plugin]) {
9
- return schema[type][subType][plugin]
10
- }
11
- }
12
-
13
- getOpName (type, subType, plugin, opNameArgs) {
14
- const item = this.getSchemaItem(type, subType, plugin)
15
- return item.opName(opNameArgs)
16
- }
17
-
18
- getServiceName (type, subType, plugin, serviceNameArgs) {
19
- const item = this.getSchemaItem(type, subType, plugin)
20
- return item.serviceName(this.service, serviceNameArgs)
21
- }
22
-
23
- configure ({ service }) {
24
- this.service = service
25
- }
26
- }
27
-
28
- module.exports = SchemaDefinition
@@ -1,6 +0,0 @@
1
- const v0 = require('./v0')
2
- const v1 = require('./v1')
3
-
4
- module.exports = {
5
- schemaDefinitions: { v0, v1 }
6
- }
@@ -1,66 +0,0 @@
1
- const SchemaDefinition = require('./definition')
2
-
3
- function amqpServiceName (service) {
4
- return `${service}-amqp`
5
- }
6
-
7
- const schema = {
8
- messaging: {
9
- outbound: {
10
- amqplib: {
11
- opName: () => 'amqp.command',
12
- serviceName: amqpServiceName
13
- },
14
- amqp10: {
15
- opName: () => 'amqp.send',
16
- serviceName: amqpServiceName
17
- },
18
- 'google-cloud-pubsub': {
19
- opName: () => 'pubsub.request',
20
- serviceName: service => `${service}-pubsub`
21
- },
22
- kafkajs: {
23
- opName: () => 'kafka.produce',
24
- serviceName: service => `${service}-kafka`
25
- },
26
- rhea: {
27
- opName: () => 'amqp.send',
28
- serviceName: service => `${service}-amqp-producer`
29
- }
30
- },
31
- inbound: {
32
- amqplib: {
33
- opName: () => 'amqp.command',
34
- serviceName: amqpServiceName
35
- },
36
- amqp10: {
37
- opName: () => 'amqp.receive',
38
- serviceName: amqpServiceName
39
- },
40
- 'google-cloud-pubsub': {
41
- opName: () => 'pubsub.receive',
42
- serviceName: service => service
43
- },
44
- kafkajs: {
45
- opName: () => 'kafka.consume',
46
- serviceName: service => `${service}-kafka`
47
- },
48
- rhea: {
49
- opName: () => 'amqp.receive',
50
- serviceName: service => service
51
- }
52
- },
53
- controlPlane: {
54
- amqplib: {
55
- opName: () => 'amqp.command',
56
- serviceName: amqpServiceName
57
- },
58
- 'google-cloud-pubsub': {
59
- opName: () => 'pubsub.request',
60
- serviceName: service => `${service}-pubsub`
61
- }
62
- }
63
- }
64
- }
65
-
66
- module.exports = new SchemaDefinition(schema)
@@ -1,58 +0,0 @@
1
- const SchemaDefinition = require('./definition')
2
-
3
- function identityService (service) {
4
- return service
5
- }
6
-
7
- const amqpInbound = {
8
- opName: () => 'amqp.process',
9
- serviceName: identityService
10
- }
11
-
12
- const amqpOutbound = {
13
- opName: () => 'amqp.send',
14
- serviceName: identityService
15
- }
16
-
17
- const schema = {
18
- messaging: {
19
- outbound: {
20
- amqplib: amqpOutbound,
21
- amqp10: amqpOutbound,
22
- 'google-cloud-pubsub': {
23
- opName: () => 'gcp.pubsub.send',
24
- serviceName: identityService
25
- },
26
- kafkajs: {
27
- opName: () => 'kafka.send',
28
- serviceName: identityService
29
- },
30
- rhea: amqpOutbound
31
- },
32
- inbound: {
33
- amqplib: amqpInbound,
34
- amqp10: amqpInbound,
35
- 'google-cloud-pubsub': {
36
- opName: () => 'gcp.pubsub.process',
37
- serviceName: identityService
38
- },
39
- kafkajs: {
40
- opName: () => 'kafka.process',
41
- serviceName: identityService
42
- },
43
- rhea: amqpInbound
44
- },
45
- controlPlane: {
46
- amqplib: {
47
- opName: () => 'amqp.command',
48
- serviceName: identityService
49
- },
50
- 'google-cloud-pubsub': {
51
- opName: () => 'gcp.pubsub.request',
52
- serviceName: identityService
53
- }
54
- }
55
- }
56
- }
57
-
58
- module.exports = new SchemaDefinition(schema)