dd-trace 4.4.0 → 4.5.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.
Files changed (41) hide show
  1. package/LICENSE-3rdparty.csv +4 -3
  2. package/package.json +4 -4
  3. package/packages/datadog-instrumentations/src/aws-sdk.js +5 -0
  4. package/packages/datadog-instrumentations/src/cassandra-driver.js +6 -3
  5. package/packages/datadog-instrumentations/src/elasticsearch.js +39 -1
  6. package/packages/datadog-instrumentations/src/helpers/hooks.js +1 -0
  7. package/packages/datadog-instrumentations/src/kafkajs.js +2 -2
  8. package/packages/datadog-instrumentations/src/opensearch.js +2 -1
  9. package/packages/datadog-plugin-aws-sdk/src/base.js +3 -3
  10. package/packages/datadog-plugin-aws-sdk/src/services/dynamodb.js +1 -0
  11. package/packages/datadog-plugin-aws-sdk/src/services/kinesis.js +1 -0
  12. package/packages/datadog-plugin-aws-sdk/src/services/s3.js +1 -0
  13. package/packages/datadog-plugin-aws-sdk/src/services/sns.js +1 -0
  14. package/packages/datadog-plugin-aws-sdk/src/services/sqs.js +1 -0
  15. package/packages/datadog-plugin-cassandra-driver/src/index.js +4 -4
  16. package/packages/datadog-plugin-grpc/src/client.js +8 -2
  17. package/packages/datadog-plugin-grpc/src/server.js +2 -2
  18. package/packages/datadog-plugin-kafkajs/src/consumer.js +6 -1
  19. package/packages/datadog-plugin-kafkajs/src/producer.js +8 -1
  20. package/packages/datadog-plugin-mongodb-core/src/index.js +13 -2
  21. package/packages/datadog-plugin-openai/src/index.js +9 -2
  22. package/packages/datadog-plugin-oracledb/src/index.js +1 -0
  23. package/packages/dd-trace/src/ci-visibility/exporters/git/git_metadata.js +6 -5
  24. package/packages/dd-trace/src/config.js +11 -0
  25. package/packages/dd-trace/src/data_streams_context.js +15 -0
  26. package/packages/dd-trace/src/datastreams/pathway.js +58 -0
  27. package/packages/dd-trace/src/datastreams/processor.js +194 -0
  28. package/packages/dd-trace/src/datastreams/writer.js +66 -0
  29. package/packages/dd-trace/src/plugin_manager.js +6 -1
  30. package/packages/dd-trace/src/plugins/database.js +2 -1
  31. package/packages/dd-trace/src/plugins/index.js +1 -0
  32. package/packages/dd-trace/src/plugins/outbound.js +2 -1
  33. package/packages/dd-trace/src/plugins/tracing.js +3 -0
  34. package/packages/dd-trace/src/plugins/util/git.js +37 -5
  35. package/packages/dd-trace/src/plugins/util/user-provided-git.js +36 -2
  36. package/packages/dd-trace/src/profiling/config.js +32 -5
  37. package/packages/dd-trace/src/service-naming/index.js +13 -1
  38. package/packages/dd-trace/src/service-naming/schemas/v0/web.js +9 -0
  39. package/packages/dd-trace/src/service-naming/schemas/v1/web.js +8 -0
  40. package/packages/dd-trace/src/telemetry/metrics.js +76 -20
  41. package/packages/dd-trace/src/tracer.js +19 -1
@@ -11,6 +11,7 @@ require,crypto-randomuuid,MIT,Copyright 2021 Node.js Foundation and contributors
11
11
  require,diagnostics_channel,MIT,Copyright 2021 Simon D.
12
12
  require,ignore,MIT,Copyright 2013 Kael Zhang and contributors
13
13
  require,import-in-the-middle,Apache license 2.0,Copyright 2021 Datadog Inc.
14
+ require,int64-buffer,MIT,Copyright 2015-2016 Yusuke Kawasaki
14
15
  require,ipaddr.js,MIT,Copyright 2011-2017 whitequark
15
16
  require,istanbul-lib-coverage,BSD-3-Clause,Copyright 2012-2015 Yahoo! Inc.
16
17
  require,koalas,MIT,Copyright 2013-2017 Brian Woodward
@@ -22,6 +23,7 @@ require,lodash.uniq,MIT,Copyright JS Foundation and other contributors
22
23
  require,lru-cache,ISC,Copyright (c) 2010-2022 Isaac Z. Schlueter and Contributors
23
24
  require,methods,MIT,Copyright 2013-2014 TJ Holowaychuk
24
25
  require,module-details-from-path,MIT,Copyright 2016 Thomas Watson Steen
26
+ require,msgpack-lite,MIT,Copyright 2015 Yusuke Kawasaki
25
27
  require,node-abort-controller,MIT,Copyright (c) 2019 Steve Faulkner
26
28
  require,opentracing,MIT,Copyright 2016 Resonance Labs Inc
27
29
  require,path-to-regexp,MIT,Copyright 2014 Blake Embrey
@@ -51,13 +53,11 @@ dev,express,MIT,Copyright 2009-2014 TJ Holowaychuk 2013-2014 Roman Shtylman 2014
51
53
  dev,get-port,MIT,Copyright Sindre Sorhus
52
54
  dev,glob,ISC,Copyright Isaac Z. Schlueter and Contributors
53
55
  dev,graphql,MIT,Copyright 2015 Facebook Inc.
54
- dev,int64-buffer,MIT,Copyright 2015-2016 Yusuke Kawasaki
55
56
  dev,jszip,MIT,Copyright 2015-2016 Stuart Knightley and contributors
56
57
  dev,knex,MIT,Copyright (c) 2013-present Tim Griesser
57
58
  dev,mkdirp,MIT,Copyright 2010 James Halliday
58
59
  dev,mocha,MIT,Copyright 2011-2018 JS Foundation and contributors https://js.foundation
59
60
  dev,multer,MIT,Copyright 2014 Hage Yaapa
60
- dev,msgpack-lite,MIT,Copyright 2015 Yusuke Kawasaki
61
61
  dev,nock,MIT,Copyright 2017 Pedro Teixeira and other contributors
62
62
  dev,nyc,ISC,Copyright 2015 Contributors
63
63
  dev,pprof-format,MIT,Copyright 2022 Stephen Belanger
@@ -67,5 +67,6 @@ dev,sinon,BSD-3-Clause,Copyright 2010-2017 Christian Johansen
67
67
  dev,sinon-chai,WTFPL and BSD-2-Clause,Copyright 2004 Sam Hocevar 2012–2017 Domenic Denicola
68
68
  dev,tap,ISC,Copyright 2011-2022 Isaac Z. Schlueter and Contributors
69
69
  dev,tape,MIT,Copyright James Halliday
70
- file,aws-lambda-nodejs-runtime-interface-client,Apache 2.0,Copyright 2019 Amazon.com, Inc. or its affiliates. All Rights Reserved.
70
+ file,aws-lambda-nodejs-runtime-interface-client,Apache 2.0,Copyright 2019 Amazon.com Inc. or its affiliates. All Rights Reserved.
71
71
  file,profile.proto,Apache license 2.0,Copyright 2016 Google Inc.
72
+ file,is-git-url,MIT,Copyright (c) 2017 Jon Schlinkert.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "dd-trace",
3
- "version": "4.4.0",
3
+ "version": "4.5.0",
4
4
  "description": "Datadog APM tracing client for JavaScript",
5
5
  "main": "index.js",
6
6
  "typings": "index.d.ts",
@@ -19,7 +19,7 @@
19
19
  "test:appsec:ci": "nyc --no-clean --include \"packages/dd-trace/src/appsec/**/*.js\" --exclude \"packages/dd-trace/test/appsec/**/*.plugin.spec.js\" -- npm run test:appsec",
20
20
  "test:appsec:plugins": "mocha --colors --exit -r \"packages/dd-trace/test/setup/mocha.js\" \"packages/dd-trace/test/appsec/**/*.@($(echo $PLUGINS)).plugin.spec.js\"",
21
21
  "test:appsec:plugins:ci": "yarn services && nyc --no-clean --include \"packages/dd-trace/test/appsec/**/*.@($(echo $PLUGINS)).plugin.spec.js\" -- npm run test:appsec:plugins",
22
- "test:trace:core": "tap packages/dd-trace/test/*.spec.js \"packages/dd-trace/test/{ci-visibility,config,encode,exporters,opentelemetry,opentracing,plugins,telemetry}/**/*.spec.js\"",
22
+ "test:trace:core": "tap packages/dd-trace/test/*.spec.js \"packages/dd-trace/test/{ci-visibility,encode,exporters,opentelemetry,opentracing,plugins,service-naming,telemetry}/**/*.spec.js\"",
23
23
  "test:trace:core:ci": "npm run test:trace:core -- --coverage --nyc-arg=--include=\"packages/dd-trace/src/**/*.js\"",
24
24
  "test:instrumentations": "mocha --colors -r 'packages/dd-trace/test/setup/mocha.js' 'packages/datadog-instrumentations/test/**/*.spec.js'",
25
25
  "test:instrumentations:ci": "nyc --no-clean --include 'packages/datadog-instrumentations/src/**/*.js' -- npm run test:instrumentations",
@@ -78,6 +78,7 @@
78
78
  "diagnostics_channel": "^1.1.0",
79
79
  "ignore": "^5.2.0",
80
80
  "import-in-the-middle": "^1.3.5",
81
+ "int64-buffer": "^0.1.9",
81
82
  "ipaddr.js": "^2.0.1",
82
83
  "istanbul-lib-coverage": "3.2.0",
83
84
  "koalas": "^1.0.2",
@@ -89,6 +90,7 @@
89
90
  "lru-cache": "^7.14.0",
90
91
  "methods": "^1.1.2",
91
92
  "module-details-from-path": "^1.0.3",
93
+ "msgpack-lite": "^0.1.26",
92
94
  "node-abort-controller": "^3.0.1",
93
95
  "opentracing": ">=0.12.1",
94
96
  "path-to-regexp": "^0.1.2",
@@ -120,12 +122,10 @@
120
122
  "get-port": "^3.2.0",
121
123
  "glob": "^7.1.6",
122
124
  "graphql": "0.13.2",
123
- "int64-buffer": "^0.1.9",
124
125
  "jszip": "^3.5.0",
125
126
  "knex": "^2.4.2",
126
127
  "mkdirp": "^0.5.1",
127
128
  "mocha": "8",
128
- "msgpack-lite": "^0.1.26",
129
129
  "multer": "^1.4.5-lts.1",
130
130
  "nock": "^11.3.3",
131
131
  "nyc": "^15.1.0",
@@ -166,6 +166,11 @@ function getChannelSuffix (name) {
166
166
  ].includes(name) ? name : 'default'
167
167
  }
168
168
 
169
+ addHook({ name: '@smithy/smithy-client', versions: ['>=1.0.3'] }, smithy => {
170
+ shimmer.wrap(smithy.Client.prototype, 'send', wrapSmithySend)
171
+ return smithy
172
+ })
173
+
169
174
  addHook({ name: '@aws-sdk/smithy-client', versions: ['>=3'] }, smithy => {
170
175
  shimmer.wrap(smithy.Client.prototype, 'send', wrapSmithySend)
171
176
  return smithy
@@ -28,7 +28,8 @@ addHook({ name: 'cassandra-driver', versions: ['>=3.0.0'] }, cassandra => {
28
28
  }
29
29
 
30
30
  return asyncResource.runInAsyncScope(() => {
31
- startCh.publish({ keyspace: this.keyspace, query: queries })
31
+ const contactPoints = this.options && this.options.contactPoints
32
+ startCh.publish({ keyspace: this.keyspace, query: queries, contactPoints })
32
33
  try {
33
34
  const res = batch.apply(this, arguments)
34
35
  if (typeof res === 'function' || !res) {
@@ -56,7 +57,8 @@ addHook({ name: 'cassandra-driver', versions: ['>=4.4'] }, cassandra => {
56
57
  }
57
58
  const asyncResource = new AsyncResource('bound-anonymous-fn')
58
59
  return asyncResource.runInAsyncScope(() => {
59
- startCh.publish({ keyspace: this.keyspace, query })
60
+ const contactPoints = this.options && this.options.contactPoints
61
+ startCh.publish({ keyspace: this.keyspace, query, contactPoints })
60
62
  const promise = _execute.apply(this, arguments)
61
63
 
62
64
  const promiseAsyncResource = new AsyncResource('bound-anonymous-fn')
@@ -88,7 +90,8 @@ addHook({ name: 'cassandra-driver', versions: ['3 - 4.3'] }, cassandra => {
88
90
  }
89
91
 
90
92
  return asyncResource.runInAsyncScope(() => {
91
- startCh.publish({ keyspace: this.keyspace, query })
93
+ const contactPoints = this.options && this.options.contactPoints
94
+ startCh.publish({ keyspace: this.keyspace, query, contactPoints })
92
95
 
93
96
  const lastIndex = arguments.length - 1
94
97
  let cb = arguments[lastIndex]
@@ -9,11 +9,13 @@ const shimmer = require('../../datadog-shimmer')
9
9
 
10
10
  addHook({ name: '@elastic/transport', file: 'lib/Transport.js', versions: ['>=8'] }, (exports) => {
11
11
  shimmer.wrap(exports.default.prototype, 'request', createWrapRequest('elasticsearch'))
12
+ shimmer.wrap(exports.default.prototype, 'getConnection', createWrapGetConnection('elasticsearch'))
12
13
  return exports
13
14
  })
14
15
 
15
16
  addHook({ name: '@elastic/elasticsearch', file: 'lib/Transport.js', versions: ['>=5.6.16 <8', '>=8'] }, Transport => {
16
17
  shimmer.wrap(Transport.prototype, 'request', createWrapRequest('elasticsearch'))
18
+ shimmer.wrap(Transport.prototype, 'getConnection', createWrapGetConnection('elasticsearch'))
17
19
  return Transport
18
20
  })
19
21
 
@@ -22,6 +24,42 @@ addHook({ name: 'elasticsearch', file: 'src/lib/transport.js', versions: ['>=10'
22
24
  return Transport
23
25
  })
24
26
 
27
+ addHook({ name: 'elasticsearch', file: 'src/lib/connection_pool.js', versions: ['>=10'] }, ConnectionPool => {
28
+ shimmer.wrap(ConnectionPool.prototype, 'select', createWrapSelect('elasticsearch'))
29
+ return ConnectionPool
30
+ })
31
+
32
+ function createWrapGetConnection (name) {
33
+ const connectCh = channel(`apm:${name}:query:connect`)
34
+ return function wrapRequest (request) {
35
+ return function () {
36
+ const connection = request.apply(this, arguments)
37
+ if (connectCh.hasSubscribers && connection && connection.url) {
38
+ connectCh.publish(connection.url)
39
+ }
40
+ return connection
41
+ }
42
+ }
43
+ }
44
+
45
+ function createWrapSelect () {
46
+ const connectCh = channel('apm:elasticsearch:query:connect')
47
+ return function wrapRequest (request) {
48
+ return function () {
49
+ if (arguments.length === 1) {
50
+ const cb = arguments[0]
51
+ arguments[0] = function (err, connection) {
52
+ if (connectCh.hasSubscribers && connection && connection.host) {
53
+ connectCh.publish({ hostname: connection.host.host, port: connection.host.port })
54
+ }
55
+ cb(err, connection)
56
+ }
57
+ }
58
+ return request.apply(this, arguments)
59
+ }
60
+ }
61
+ }
62
+
25
63
  function createWrapRequest (name) {
26
64
  const startCh = channel(`apm:${name}:query:start`)
27
65
  const finishCh = channel(`apm:${name}:query:finish`)
@@ -83,4 +121,4 @@ function createWrapRequest (name) {
83
121
  }
84
122
  }
85
123
 
86
- module.exports = { createWrapRequest }
124
+ module.exports = { createWrapRequest, createWrapGetConnection }
@@ -16,6 +16,7 @@ module.exports = {
16
16
  '@opensearch-project/opensearch': () => require('../opensearch'),
17
17
  '@opentelemetry/sdk-trace-node': () => require('../otel-sdk-trace'),
18
18
  '@redis/client': () => require('../redis'),
19
+ '@smithy/smithy-client': () => require('../aws-sdk'),
19
20
  'amqp10': () => require('../amqp10'),
20
21
  'amqplib': () => require('../amqplib'),
21
22
  'aws-sdk': () => require('../aws-sdk'),
@@ -69,6 +69,7 @@ addHook({ name: 'kafkajs', versions: ['>=1.4'] }, (obj) => {
69
69
  const consumer = createConsumer.apply(this, arguments)
70
70
  const run = consumer.run
71
71
 
72
+ const groupId = arguments[0].groupId
72
73
  consumer.run = function ({ eachMessage, ...runArgs }) {
73
74
  if (typeof eachMessage !== 'function') return run({ eachMessage, ...runArgs })
74
75
 
@@ -77,10 +78,9 @@ addHook({ name: 'kafkajs', versions: ['>=1.4'] }, (obj) => {
77
78
  const innerAsyncResource = new AsyncResource('bound-anonymous-fn')
78
79
  return innerAsyncResource.runInAsyncScope(() => {
79
80
  const { topic, partition, message } = eachMessageArgs[0]
80
- consumerStartCh.publish({ topic, partition, message })
81
+ consumerStartCh.publish({ topic, partition, message, groupId })
81
82
  try {
82
83
  const result = eachMessage.apply(this, eachMessageArgs)
83
-
84
84
  if (result && typeof result.then === 'function') {
85
85
  result.then(
86
86
  innerAsyncResource.bind(() => consumerFinishCh.publish(undefined)),
@@ -2,9 +2,10 @@
2
2
 
3
3
  const { addHook } = require('./helpers/instrument')
4
4
  const shimmer = require('../../datadog-shimmer')
5
- const { createWrapRequest } = require('./elasticsearch')
5
+ const { createWrapRequest, createWrapGetConnection } = require('./elasticsearch')
6
6
 
7
7
  addHook({ name: '@opensearch-project/opensearch', file: 'lib/Transport.js', versions: ['>=1'] }, Transport => {
8
8
  shimmer.wrap(Transport.prototype, 'request', createWrapRequest('opensearch'))
9
+ shimmer.wrap(Transport.prototype, 'getConnection', createWrapGetConnection('opensearch'))
9
10
  return Transport
10
11
  })
@@ -1,11 +1,11 @@
1
1
  'use strict'
2
2
 
3
3
  const analyticsSampler = require('../../dd-trace/src/analytics_sampler')
4
- const Plugin = require('../../dd-trace/src/plugins/plugin')
4
+ const ClientPlugin = require('../../dd-trace/src/plugins/client')
5
5
  const { storage } = require('../../datadog-core')
6
6
  const { isTrue } = require('../../dd-trace/src/util')
7
7
 
8
- class BaseAwsSdkPlugin extends Plugin {
8
+ class BaseAwsSdkPlugin extends ClientPlugin {
9
9
  static get id () { return 'aws' }
10
10
 
11
11
  get serviceIdentifier () {
@@ -116,7 +116,7 @@ class BaseAwsSdkPlugin extends Plugin {
116
116
  this.config.hooks.request(span, response)
117
117
  }
118
118
 
119
- span.finish()
119
+ super.finish()
120
120
  }
121
121
 
122
122
  configure (config) {
@@ -4,6 +4,7 @@ const BaseAwsSdkPlugin = require('../base')
4
4
 
5
5
  class DynamoDb extends BaseAwsSdkPlugin {
6
6
  static get id () { return 'dynamodb' }
7
+ static get peerServicePrecursors () { return ['tablename'] }
7
8
 
8
9
  generateTags (params, operation, response) {
9
10
  const tags = {}
@@ -3,6 +3,7 @@ const log = require('../../../dd-trace/src/log')
3
3
  const BaseAwsSdkPlugin = require('../base')
4
4
  class Kinesis extends BaseAwsSdkPlugin {
5
5
  static get id () { return 'kinesis' }
6
+ static get peerServicePrecursors () { return ['streamname'] }
6
7
 
7
8
  generateTags (params, operation, response) {
8
9
  if (!params || !params.StreamName) return {}
@@ -4,6 +4,7 @@ const BaseAwsSdkPlugin = require('../base')
4
4
 
5
5
  class S3 extends BaseAwsSdkPlugin {
6
6
  static get id () { return 's3' }
7
+ static get peerServicePrecursors () { return ['bucketname'] }
7
8
 
8
9
  generateTags (params, operation, response) {
9
10
  const tags = {}
@@ -4,6 +4,7 @@ const BaseAwsSdkPlugin = require('../base')
4
4
 
5
5
  class Sns extends BaseAwsSdkPlugin {
6
6
  static get id () { return 'sns' }
7
+ static get peerServicePrecursors () { return ['topicname'] }
7
8
 
8
9
  generateTags (params, operation, response) {
9
10
  if (!params) return {}
@@ -6,6 +6,7 @@ const { storage } = require('../../../datadog-core')
6
6
 
7
7
  class Sqs extends BaseAwsSdkPlugin {
8
8
  static get id () { return 'sqs' }
9
+ static get peerServicePrecursors () { return ['queuename'] }
9
10
 
10
11
  constructor (...args) {
11
12
  super(...args)
@@ -1,13 +1,14 @@
1
1
  'use strict'
2
2
 
3
- const { CLIENT_PORT_KEY } = require('../../dd-trace/src/constants')
4
3
  const DatabasePlugin = require('../../dd-trace/src/plugins/database')
4
+ const CASSANDRA_CONTACT_POINTS_KEY = 'db.cassandra.contact.points'
5
5
 
6
6
  class CassandraDriverPlugin extends DatabasePlugin {
7
7
  static get id () { return 'cassandra-driver' }
8
8
  static get system () { return 'cassandra' }
9
+ static get peerServicePrecursors () { return [CASSANDRA_CONTACT_POINTS_KEY] }
9
10
 
10
- start ({ keyspace, query, connectionOptions = {} }) {
11
+ start ({ keyspace, query, contactPoints = {} }) {
11
12
  if (Array.isArray(query)) {
12
13
  query = combine(query)
13
14
  }
@@ -21,8 +22,7 @@ class CassandraDriverPlugin extends DatabasePlugin {
21
22
  'db.type': 'cassandra',
22
23
  'cassandra.query': query,
23
24
  'cassandra.keyspace': keyspace,
24
- 'out.host': connectionOptions.host,
25
- [CLIENT_PORT_KEY]: connectionOptions.port
25
+ [CASSANDRA_CONTACT_POINTS_KEY]: contactPoints.join(',') || null
26
26
  }
27
27
  })
28
28
  }
@@ -7,12 +7,13 @@ const { addMetadataTags, getFilter, getMethodMetadata } = require('./util')
7
7
  class GrpcClientPlugin extends ClientPlugin {
8
8
  static get id () { return 'grpc' }
9
9
  static get operation () { return 'client:request' }
10
+ static get peerServicePrecursors () { return ['rpc.service'] }
10
11
 
11
12
  start ({ metadata, path, type }) {
12
13
  const metadataFilter = this.config.metadataFilter
13
14
  const method = getMethodMetadata(path, type)
14
- const span = this.startSpan('grpc.client', {
15
- service: this.config.service,
15
+ const span = this.startSpan(this.operationName(), {
16
+ service: this.config.service || this.serviceName(),
16
17
  resource: path,
17
18
  kind: 'client',
18
19
  type: 'http',
@@ -29,6 +30,11 @@ class GrpcClientPlugin extends ClientPlugin {
29
30
  }
30
31
  })
31
32
 
33
+ // needed as precursor for peer.service
34
+ if (method.service && method.package) {
35
+ span.setTag('rpc.service', method.package + '.' + method.service)
36
+ }
37
+
32
38
  if (metadata) {
33
39
  addMetadataTags(span, metadata, metadataFilter, 'request')
34
40
  inject(this.tracer, span, metadata)
@@ -24,9 +24,9 @@ class GrpcServerPlugin extends ServerPlugin {
24
24
  const metadataFilter = this.config.metadataFilter
25
25
  const childOf = extract(this.tracer, metadata)
26
26
  const method = getMethodMetadata(name, type)
27
- const span = this.startSpan('grpc.server', {
27
+ const span = this.startSpan(this.operationName(), {
28
28
  childOf,
29
- service: this.config.service,
29
+ service: this.config.service || this.serviceName(),
30
30
  resource: name,
31
31
  kind: 'server',
32
32
  type: 'web',
@@ -6,7 +6,12 @@ class KafkajsConsumerPlugin extends ConsumerPlugin {
6
6
  static get id () { return 'kafkajs' }
7
7
  static get operation () { return 'consume' }
8
8
 
9
- start ({ topic, partition, message }) {
9
+ start ({ topic, partition, message, groupId }) {
10
+ if (this.config.dsmEnabled) {
11
+ this.tracer.decodeDataStreamsContext(message.headers['dd-pathway-ctx'])
12
+ this.tracer
13
+ .setCheckpoint(['direction:in', `group:${groupId}`, `topic:${topic}`, 'type:kafka'])
14
+ }
10
15
  const childOf = extract(this.tracer, message.headers)
11
16
  this.startSpan({
12
17
  childOf,
@@ -1,12 +1,19 @@
1
1
  'use strict'
2
2
 
3
3
  const ProducerPlugin = require('../../dd-trace/src/plugins/producer')
4
+ const { encodePathwayContext } = require('../../dd-trace/src/datastreams/pathway')
4
5
 
5
6
  class KafkajsProducerPlugin extends ProducerPlugin {
6
7
  static get id () { return 'kafkajs' }
7
8
  static get operation () { return 'produce' }
8
9
 
9
10
  start ({ topic, messages }) {
11
+ let pathwayCtx
12
+ if (this.config.dsmEnabled) {
13
+ const dataStreamsContext = this.tracer
14
+ .setCheckpoint(['direction:out', `topic:${topic}`, 'type:kafka'])
15
+ pathwayCtx = encodePathwayContext(dataStreamsContext)
16
+ }
10
17
  const span = this.startSpan({
11
18
  resource: topic,
12
19
  meta: {
@@ -17,9 +24,9 @@ class KafkajsProducerPlugin extends ProducerPlugin {
17
24
  'kafka.batch_size': messages.length
18
25
  }
19
26
  })
20
-
21
27
  for (const message of messages) {
22
28
  if (typeof message === 'object') {
29
+ if (this.config.dsmEnabled) message.headers['dd-pathway-ctx'] = pathwayCtx
23
30
  this.tracer.inject(span, 'text_map', message.headers)
24
31
  }
25
32
  }
@@ -5,17 +5,19 @@ const DatabasePlugin = require('../../dd-trace/src/plugins/database')
5
5
  class MongodbCorePlugin extends DatabasePlugin {
6
6
  static get id () { return 'mongodb-core' }
7
7
  static get component () { return 'mongodb' }
8
-
8
+ // avoid using db.name for peer.service since it includes the collection name
9
+ // should be removed if one day this will be fixed
10
+ static get peerServicePrecursors () { return [] }
9
11
  start ({ ns, ops, options = {}, name }) {
10
12
  const query = getQuery(ops)
11
13
  const resource = truncate(getResource(this, ns, query, name))
12
-
13
14
  this.startSpan(this.operationName(), {
14
15
  service: this.serviceName(this.config),
15
16
  resource,
16
17
  type: 'mongodb',
17
18
  kind: 'client',
18
19
  meta: {
20
+ // this is not technically correct since it includes the collection but we changing will break customer stuff
19
21
  'db.name': ns,
20
22
  'mongodb.query': query,
21
23
  'out.host': options.host,
@@ -23,6 +25,15 @@ class MongodbCorePlugin extends DatabasePlugin {
23
25
  }
24
26
  })
25
27
  }
28
+
29
+ getPeerService (tags) {
30
+ const ns = tags['db.name']
31
+ if (ns && tags['peer.service'] === undefined) {
32
+ // the mongo ns is either dbName either dbName.collection. So we keep the first part
33
+ tags['peer.service'] = ns.split('.', 1)[0]
34
+ }
35
+ return super.getPeerService(tags)
36
+ }
26
37
  }
27
38
 
28
39
  function getQuery (cmd) {
@@ -100,7 +100,7 @@ class OpenApiPlugin extends TracingPlugin {
100
100
  }
101
101
 
102
102
  // createChatCompletion, createCompletion
103
- if ('logit_bias' in payload) {
103
+ if (typeof payload.logit_bias === 'object' && payload.logit_bias) {
104
104
  for (const [tokenId, bias] of Object.entries(payload.logit_bias)) {
105
105
  tags[`openai.request.logit_bias.${tokenId}`] = bias
106
106
  }
@@ -264,6 +264,8 @@ function retrieveModelRequestExtraction (tags, payload) {
264
264
  }
265
265
 
266
266
  function createChatCompletionRequestExtraction (tags, payload, store) {
267
+ if (!defensiveArrayLength(payload.messages)) return
268
+
267
269
  store.messages = payload.messages
268
270
  for (let i = 0; i < payload.messages.length; i++) {
269
271
  const message = payload.messages[i]
@@ -411,7 +413,7 @@ function createFineTuneRequestExtraction (tags, body) {
411
413
  tags['openai.request.compute_classification_metrics'] = body.compute_classification_metrics
412
414
  tags['openai.request.classification_n_classes'] = body.classification_n_classes
413
415
  tags['openai.request.classification_positive_class'] = body.classification_positive_class
414
- tags['openai.request.classification_betas_count'] = body.classification_betas.length
416
+ tags['openai.request.classification_betas_count'] = defensiveArrayLength(body.classification_betas)
415
417
  }
416
418
 
417
419
  function commonFineTuneResponseExtraction (tags, body) {
@@ -521,6 +523,7 @@ function commonCreateResponseExtraction (tags, body, store) {
521
523
 
522
524
  // createCompletion, createChatCompletion, createEdit, createEmbedding
523
525
  function usageExtraction (tags, body) {
526
+ if (typeof body.usage !== 'object' || !body.usage) return
524
527
  tags['openai.response.usage.prompt_tokens'] = body.usage.prompt_tokens
525
528
  tags['openai.response.usage.completion_tokens'] = body.usage.completion_tokens
526
529
  tags['openai.response.usage.total_tokens'] = body.usage.total_tokens
@@ -675,4 +678,8 @@ function normalizeStringOrTokenArray (input, truncate = true) {
675
678
  return truncate ? truncateText(normalized) : normalized
676
679
  }
677
680
 
681
+ function defensiveArrayLength (maybeArray) {
682
+ return Array.isArray(maybeArray) ? maybeArray.length : undefined
683
+ }
684
+
678
685
  module.exports = OpenApiPlugin
@@ -7,6 +7,7 @@ const log = require('../../dd-trace/src/log')
7
7
  class OracledbPlugin extends DatabasePlugin {
8
8
  static get id () { return 'oracledb' }
9
9
  static get system () { return 'oracle' }
10
+ static get peerServicePrecursors () { return ['db.instance', 'db.hostname'] }
10
11
 
11
12
  start ({ query, connAttrs }) {
12
13
  const service = this.serviceName(this.config, connAttrs)
@@ -51,8 +51,6 @@ function getCommitsToExclude ({ url, isEvpProxy, repositoryUrl }, callback) {
51
51
 
52
52
  log.debug(`There were ${latestCommits.length} commits since last month.`)
53
53
 
54
- const [headCommit] = latestCommits
55
-
56
54
  const commonOptions = getCommonRequestOptions(url)
57
55
 
58
56
  const options = {
@@ -91,7 +89,7 @@ function getCommitsToExclude ({ url, isEvpProxy, repositoryUrl }, callback) {
91
89
  } catch (e) {
92
90
  return callback(new Error(`Can't parse commits to exclude response: ${e.message}`))
93
91
  }
94
- callback(null, commitsToExclude, headCommit)
92
+ callback(null, commitsToExclude, latestCommits)
95
93
  })
96
94
  }
97
95
 
@@ -172,13 +170,16 @@ function sendGitMetadata (url, isEvpProxy, configRepositoryUrl, callback) {
172
170
  unshallowRepository()
173
171
  }
174
172
 
175
- getCommitsToExclude({ url, repositoryUrl, isEvpProxy }, (err, commitsToExclude, headCommit) => {
173
+ getCommitsToExclude({ url, repositoryUrl, isEvpProxy }, (err, commitsToExclude, latestCommits) => {
176
174
  if (err) {
177
175
  return callback(err)
178
176
  }
179
177
  log.debug(`There are ${commitsToExclude.length} commits to exclude.`)
178
+ const [headCommit] = latestCommits
179
+ const commitsToInclude = latestCommits.filter((commit) => !commitsToExclude.includes(commit))
180
+ log.debug(`There are ${commitsToInclude.length} commits to include.`)
180
181
 
181
- const commitsToUpload = getCommitsToUpload(commitsToExclude)
182
+ const commitsToUpload = getCommitsToUpload(commitsToExclude, commitsToInclude)
182
183
 
183
184
  if (!commitsToUpload.length) {
184
185
  log.debug('No commits to upload')
@@ -144,6 +144,11 @@ class Config {
144
144
  process.env.DD_DBM_PROPAGATION_MODE,
145
145
  'disabled'
146
146
  )
147
+ const DD_DATA_STREAMS_ENABLED = coalesce(
148
+ options.dsmEnabled,
149
+ process.env.DD_DATA_STREAMS_ENABLED,
150
+ false
151
+ )
147
152
  const DD_AGENT_HOST = coalesce(
148
153
  options.hostname,
149
154
  process.env.DD_AGENT_HOST,
@@ -316,6 +321,10 @@ class Config {
316
321
  )
317
322
  const DD_TRACE_PEER_SERVICE_DEFAULTS_ENABLED = process.env.DD_TRACE_PEER_SERVICE_DEFAULTS_ENABLED
318
323
 
324
+ const DD_TRACE_REMOVE_INTEGRATION_SERVICE_NAMES_ENABLED = coalesce(
325
+ isTrue(process.env.DD_TRACE_REMOVE_INTEGRATION_SERVICE_NAMES_ENABLED),
326
+ false
327
+ )
319
328
  const DD_TRACE_X_DATADOG_TAGS_MAX_LENGTH = coalesce(
320
329
  process.env.DD_TRACE_X_DATADOG_TAGS_MAX_LENGTH,
321
330
  '512'
@@ -497,6 +506,7 @@ ken|consumer_?(?:id|key|secret)|sign(?:ed|ature)?|auth(?:entication|orization)?)
497
506
 
498
507
  this.tracing = !isFalse(DD_TRACING_ENABLED)
499
508
  this.dbmPropagationMode = DD_DBM_PROPAGATION_MODE
509
+ this.dsmEnabled = isTrue(DD_DATA_STREAMS_ENABLED)
500
510
  this.openAiLogsEnabled = DD_OPENAI_LOGS_ENABLED
501
511
  this.apiKey = DD_API_KEY
502
512
  this.logInjection = isTrue(DD_LOGS_INJECTION)
@@ -543,6 +553,7 @@ ken|consumer_?(?:id|key|secret)|sign(?:ed|ature)?|auth(?:entication|orization)?)
543
553
  ? isTrue(DD_TRACE_PEER_SERVICE_DEFAULTS_ENABLED)
544
554
  : true
545
555
  )
556
+ this.traceRemoveIntegrationServiceNamesEnabled = DD_TRACE_REMOVE_INTEGRATION_SERVICE_NAMES_ENABLED
546
557
  this.lookup = options.lookup
547
558
  this.startupLogs = isTrue(DD_TRACE_STARTUP_LOGS)
548
559
  // Disabled for CI Visibility's agentless
@@ -0,0 +1,15 @@
1
+ const { storage } = require('../../datadog-core')
2
+
3
+ function getDataStreamsContext () {
4
+ const store = storage.getStore()
5
+ return (store && store.dataStreamsContext) || null
6
+ }
7
+
8
+ function setDataStreamsContext (dataStreamsContext) {
9
+ storage.enterWith({ ...(storage.getStore()), dataStreamsContext })
10
+ }
11
+
12
+ module.exports = {
13
+ getDataStreamsContext,
14
+ setDataStreamsContext
15
+ }