dd-trace 4.3.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 (88) hide show
  1. package/LICENSE-3rdparty.csv +4 -3
  2. package/index.d.ts +27 -0
  3. package/package.json +4 -4
  4. package/packages/datadog-instrumentations/src/aws-sdk.js +5 -0
  5. package/packages/datadog-instrumentations/src/cassandra-driver.js +6 -3
  6. package/packages/datadog-instrumentations/src/elasticsearch.js +39 -1
  7. package/packages/datadog-instrumentations/src/express.js +23 -0
  8. package/packages/datadog-instrumentations/src/helpers/hooks.js +4 -0
  9. package/packages/datadog-instrumentations/src/kafkajs.js +2 -2
  10. package/packages/datadog-instrumentations/src/openai.js +50 -0
  11. package/packages/datadog-instrumentations/src/opensearch.js +2 -1
  12. package/packages/datadog-instrumentations/src/passport-http.js +22 -0
  13. package/packages/datadog-instrumentations/src/passport-local.js +22 -0
  14. package/packages/datadog-instrumentations/src/passport-utils.js +36 -0
  15. package/packages/datadog-instrumentations/src/pg.js +17 -4
  16. package/packages/datadog-plugin-aws-sdk/src/base.js +3 -3
  17. package/packages/datadog-plugin-aws-sdk/src/services/dynamodb.js +1 -0
  18. package/packages/datadog-plugin-aws-sdk/src/services/kinesis.js +1 -0
  19. package/packages/datadog-plugin-aws-sdk/src/services/s3.js +1 -0
  20. package/packages/datadog-plugin-aws-sdk/src/services/sns.js +1 -0
  21. package/packages/datadog-plugin-aws-sdk/src/services/sqs.js +1 -0
  22. package/packages/datadog-plugin-cassandra-driver/src/index.js +6 -6
  23. package/packages/datadog-plugin-dns/src/lookup.js +1 -1
  24. package/packages/datadog-plugin-elasticsearch/src/index.js +2 -2
  25. package/packages/datadog-plugin-google-cloud-pubsub/src/consumer.js +1 -1
  26. package/packages/datadog-plugin-graphql/src/execute.js +1 -1
  27. package/packages/datadog-plugin-graphql/src/parse.js +1 -1
  28. package/packages/datadog-plugin-graphql/src/resolve.js +0 -5
  29. package/packages/datadog-plugin-graphql/src/validate.js +1 -1
  30. package/packages/datadog-plugin-grpc/src/client.js +9 -3
  31. package/packages/datadog-plugin-grpc/src/server.js +3 -3
  32. package/packages/datadog-plugin-http/src/client.js +1 -1
  33. package/packages/datadog-plugin-http/src/server.js +38 -34
  34. package/packages/datadog-plugin-http2/src/client.js +0 -5
  35. package/packages/datadog-plugin-http2/src/server.js +23 -23
  36. package/packages/datadog-plugin-kafkajs/src/consumer.js +6 -1
  37. package/packages/datadog-plugin-kafkajs/src/producer.js +8 -1
  38. package/packages/datadog-plugin-mocha/src/index.js +3 -3
  39. package/packages/datadog-plugin-moleculer/src/client.js +3 -3
  40. package/packages/datadog-plugin-moleculer/src/server.js +2 -2
  41. package/packages/datadog-plugin-mongodb-core/src/index.js +15 -4
  42. package/packages/datadog-plugin-next/src/index.js +50 -52
  43. package/packages/datadog-plugin-openai/src/index.js +685 -0
  44. package/packages/datadog-plugin-openai/src/services.js +43 -0
  45. package/packages/datadog-plugin-oracledb/src/index.js +3 -10
  46. package/packages/datadog-plugin-pg/src/index.js +3 -11
  47. package/packages/datadog-plugin-sharedb/src/index.js +1 -1
  48. package/packages/dd-trace/src/appsec/channels.js +1 -0
  49. package/packages/dd-trace/src/appsec/iast/taint-tracking/origin-types.js +3 -2
  50. package/packages/dd-trace/src/appsec/iast/taint-tracking/plugin.js +12 -2
  51. package/packages/dd-trace/src/appsec/index.js +20 -0
  52. package/packages/dd-trace/src/appsec/passport.js +110 -0
  53. package/packages/dd-trace/src/appsec/sdk/track_event.js +14 -5
  54. package/packages/dd-trace/src/ci-visibility/exporters/git/git_metadata.js +17 -4
  55. package/packages/dd-trace/src/ci-visibility/test-api-manual/test-api-manual-plugin.js +45 -0
  56. package/packages/dd-trace/src/config.js +38 -1
  57. package/packages/dd-trace/src/constants.js +2 -0
  58. package/packages/dd-trace/src/data_streams_context.js +15 -0
  59. package/packages/dd-trace/src/datastreams/pathway.js +58 -0
  60. package/packages/dd-trace/src/datastreams/processor.js +194 -0
  61. package/packages/dd-trace/src/datastreams/writer.js +66 -0
  62. package/packages/dd-trace/src/dogstatsd.js +12 -4
  63. package/packages/dd-trace/src/external-logger/src/index.js +4 -0
  64. package/packages/dd-trace/src/opentelemetry/span.js +1 -0
  65. package/packages/dd-trace/src/opentracing/span.js +32 -0
  66. package/packages/dd-trace/src/opentracing/tracer.js +3 -1
  67. package/packages/dd-trace/src/plugin_manager.js +7 -2
  68. package/packages/dd-trace/src/plugins/client.js +1 -0
  69. package/packages/dd-trace/src/plugins/database.js +2 -1
  70. package/packages/dd-trace/src/plugins/index.js +2 -0
  71. package/packages/dd-trace/src/plugins/outbound.js +59 -1
  72. package/packages/dd-trace/src/plugins/server.js +2 -0
  73. package/packages/dd-trace/src/plugins/tracing.js +5 -1
  74. package/packages/dd-trace/src/plugins/util/exec.js +2 -0
  75. package/packages/dd-trace/src/plugins/util/git.js +38 -10
  76. package/packages/dd-trace/src/plugins/util/user-provided-git.js +36 -2
  77. package/packages/dd-trace/src/profiling/config.js +34 -7
  78. package/packages/dd-trace/src/proxy.js +6 -0
  79. package/packages/dd-trace/src/service-naming/index.js +13 -1
  80. package/packages/dd-trace/src/service-naming/schemas/v0/index.js +2 -1
  81. package/packages/dd-trace/src/service-naming/schemas/v0/storage.js +34 -1
  82. package/packages/dd-trace/src/service-naming/schemas/v0/web.js +27 -0
  83. package/packages/dd-trace/src/service-naming/schemas/v1/index.js +2 -1
  84. package/packages/dd-trace/src/service-naming/schemas/v1/storage.js +31 -0
  85. package/packages/dd-trace/src/service-naming/schemas/v1/web.js +26 -0
  86. package/packages/dd-trace/src/telemetry/index.js +3 -0
  87. package/packages/dd-trace/src/telemetry/metrics.js +281 -0
  88. 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/index.d.ts CHANGED
@@ -556,6 +556,19 @@ export declare interface TracerOptions {
556
556
  * Specifies a path to a custom blocking template json file.
557
557
  */
558
558
  blockedTemplateJson?: string,
559
+
560
+ /**
561
+ * Controls the automated user event tracking configuration
562
+ */
563
+ eventTracking?: {
564
+ /**
565
+ * Controls the automated user event tracking mode. Possible values are disabled, safe and extended.
566
+ * On safe mode, any detected Personally Identifiable Information (PII) about the user will be redacted from the event.
567
+ * On extended mode, no redaction will take place.
568
+ * @default 'safe'
569
+ */
570
+ mode?: 'safe' | 'extended' | 'disabled'
571
+ }
559
572
  };
560
573
 
561
574
  /**
@@ -1450,6 +1463,20 @@ declare namespace plugins {
1450
1463
  };
1451
1464
  }
1452
1465
 
1466
+ /**
1467
+ * This plugin automatically instruments the
1468
+ * [openai](https://platform.openai.com/docs/api-reference?lang=node.js) module.
1469
+ *
1470
+ * Note that for logs to work you'll need to set the `DD_API_KEY` environment variable.
1471
+ * You'll also need to adjust any firewall settings to allow the tracer to communicate
1472
+ * with `http-intake.logs.datadoghq.com`.
1473
+ *
1474
+ * Note that for metrics to work you'll need to enable
1475
+ * [DogStatsD](https://docs.datadoghq.com/developers/dogstatsd/?tab=hostagent#setup)
1476
+ * in the agent.
1477
+ */
1478
+ interface openai extends Instrumentation {}
1479
+
1453
1480
  /**
1454
1481
  * This plugin automatically instruments the
1455
1482
  * [opensearch](https://github.com/opensearch-project/opensearch-js) module.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "dd-trace",
3
- "version": "4.3.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 }
@@ -57,3 +57,26 @@ addHook({
57
57
  })
58
58
  })
59
59
  })
60
+
61
+ const processParamsStartCh = channel('datadog:express:process_params:start')
62
+ const wrapProcessParamsMethod = (requestPositionInArguments) => {
63
+ return (original) => {
64
+ return function () {
65
+ if (processParamsStartCh.hasSubscribers) {
66
+ processParamsStartCh.publish({ req: arguments[requestPositionInArguments] })
67
+ }
68
+
69
+ return original.apply(this, arguments)
70
+ }
71
+ }
72
+ }
73
+
74
+ addHook({ name: 'express', versions: ['>=4.0.0 <4.3.0'] }, express => {
75
+ shimmer.wrap(express.Router, 'process_params', wrapProcessParamsMethod(1))
76
+ return express
77
+ })
78
+
79
+ addHook({ name: 'express', versions: ['>=4.3.0'] }, express => {
80
+ shimmer.wrap(express.Router, 'process_params', wrapProcessParamsMethod(2))
81
+ return express
82
+ })
@@ -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,7 +70,10 @@ module.exports = {
69
70
  'net': () => require('../net'),
70
71
  'next': () => require('../next'),
71
72
  'oracledb': () => require('../oracledb'),
73
+ 'openai': () => require('../openai'),
72
74
  'paperplane': () => require('../paperplane'),
75
+ 'passport-http': () => require('../passport-http'),
76
+ 'passport-local': () => require('../passport-local'),
73
77
  'pg': () => require('../pg'),
74
78
  'pino': () => require('../pino'),
75
79
  'pino-pretty': () => require('../pino'),
@@ -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)),
@@ -0,0 +1,50 @@
1
+ 'use strict'
2
+
3
+ const {
4
+ channel,
5
+ addHook
6
+ } = require('./helpers/instrument')
7
+ const shimmer = require('../../datadog-shimmer')
8
+
9
+ const startCh = channel('apm:openai:request:start')
10
+ const finishCh = channel('apm:openai:request:finish')
11
+ const errorCh = channel('apm:openai:request:error')
12
+
13
+ addHook({ name: 'openai', file: 'dist/api.js', versions: ['>=3.0.0'] }, exports => {
14
+ const methodNames = Object.getOwnPropertyNames(exports.OpenAIApi.prototype)
15
+ methodNames.shift() // remove leading 'constructor' method
16
+
17
+ for (const methodName of methodNames) {
18
+ shimmer.wrap(exports.OpenAIApi.prototype, methodName, fn => function () {
19
+ if (!startCh.hasSubscribers) {
20
+ return fn.apply(this, arguments)
21
+ }
22
+
23
+ startCh.publish({
24
+ methodName,
25
+ args: arguments,
26
+ basePath: this.basePath,
27
+ apiKey: this.configuration.apiKey
28
+ })
29
+
30
+ return fn.apply(this, arguments)
31
+ .then((response) => {
32
+ finishCh.publish({
33
+ headers: response.headers,
34
+ body: response.data,
35
+ path: response.request.path,
36
+ method: response.request.method
37
+ })
38
+
39
+ return response
40
+ })
41
+ .catch((err) => {
42
+ errorCh.publish({ err })
43
+
44
+ throw err
45
+ })
46
+ })
47
+ }
48
+
49
+ return exports
50
+ })
@@ -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
  })
@@ -0,0 +1,22 @@
1
+ 'use strict'
2
+
3
+ const shimmer = require('../../datadog-shimmer')
4
+ const { addHook } = require('./helpers/instrument')
5
+ const { wrapVerify } = require('./passport-utils')
6
+
7
+ addHook({
8
+ name: 'passport-http',
9
+ file: 'lib/passport-http/strategies/basic.js',
10
+ versions: ['>=0.3.0']
11
+ }, BasicStrategy => {
12
+ return shimmer.wrap(BasicStrategy, function () {
13
+ const type = 'http'
14
+
15
+ if (typeof arguments[0] === 'function') {
16
+ arguments[0] = wrapVerify(arguments[0], false, type)
17
+ } else {
18
+ arguments[1] = wrapVerify(arguments[1], (arguments[0] && arguments[0].passReqToCallback), type)
19
+ }
20
+ return BasicStrategy.apply(this, arguments)
21
+ })
22
+ })
@@ -0,0 +1,22 @@
1
+ 'use strict'
2
+
3
+ const shimmer = require('../../datadog-shimmer')
4
+ const { addHook } = require('./helpers/instrument')
5
+ const { wrapVerify } = require('./passport-utils')
6
+
7
+ addHook({
8
+ name: 'passport-local',
9
+ file: 'lib/strategy.js',
10
+ versions: ['>=1.0.0']
11
+ }, Strategy => {
12
+ return shimmer.wrap(Strategy, function () {
13
+ const type = 'local'
14
+
15
+ if (typeof arguments[0] === 'function') {
16
+ arguments[0] = wrapVerify(arguments[0], false, type)
17
+ } else {
18
+ arguments[1] = wrapVerify(arguments[1], (arguments[0] && arguments[0].passReqToCallback), type)
19
+ }
20
+ return Strategy.apply(this, arguments)
21
+ })
22
+ })
@@ -0,0 +1,36 @@
1
+ 'use strict'
2
+
3
+ const shimmer = require('../../datadog-shimmer')
4
+ const { channel } = require('./helpers/instrument')
5
+
6
+ const passportVerifyChannel = channel('datadog:passport:verify:finish')
7
+
8
+ function wrapVerifiedAndPublish (username, password, verified, type) {
9
+ if (!passportVerifyChannel.hasSubscribers) {
10
+ return verified
11
+ }
12
+
13
+ return shimmer.wrap(verified, function (err, user, info) {
14
+ const credentials = { type, username }
15
+ passportVerifyChannel.publish({ credentials, user })
16
+ return verified.apply(this, arguments)
17
+ })
18
+ }
19
+
20
+ function wrapVerify (verify, passReq, type) {
21
+ if (passReq) {
22
+ return function (req, username, password, verified) {
23
+ arguments[3] = wrapVerifiedAndPublish(username, password, verified, type)
24
+ return verify.apply(this, arguments)
25
+ }
26
+ } else {
27
+ return function (username, password, verified) {
28
+ arguments[2] = wrapVerifiedAndPublish(username, password, verified, type)
29
+ return verify.apply(this, arguments)
30
+ }
31
+ }
32
+ }
33
+
34
+ module.exports = {
35
+ wrapVerify
36
+ }
@@ -31,10 +31,23 @@ function wrapQuery (query) {
31
31
  const asyncResource = new AsyncResource('bound-anonymous-fn')
32
32
  const processId = this.processID
33
33
 
34
- const pgQuery = arguments[0] && typeof arguments[0] === 'object' ? arguments[0] : { text: arguments[0] }
35
-
36
- // shallow clone the existing query to swap out .text field
37
- let newQuery = { ...pgQuery }
34
+ const pgQuery = arguments[0] && typeof arguments[0] === 'object'
35
+ ? arguments[0]
36
+ : { text: arguments[0] }
37
+
38
+ // The query objects passed in can be pretty complex. They can be instances of EventEmitter.
39
+ // For this reason we can't make a shallow clone of the object.
40
+ // Some libraries, such as sql-template-tags, can provide a getter .text property.
41
+ // For this reason we can't replace the .text property.
42
+ // Instead, we create a new object, and set the original query as the prototype.
43
+ // This allows any existing methods to still work and lets us easily provide a new query.
44
+ let newQuery = {
45
+ __ddInjectableQuery: '',
46
+ get text () {
47
+ return this.__ddInjectableQuery || Object.getPrototypeOf(this).text
48
+ }
49
+ }
50
+ Object.setPrototypeOf(newQuery, pgQuery)
38
51
 
39
52
  return asyncResource.runInAsyncScope(() => {
40
53
  startCh.publish({
@@ -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,19 +1,20 @@
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
  }
14
15
 
15
- this.startSpan('cassandra.query', {
16
- service: this.config.service,
16
+ this.startSpan(this.operationName(), {
17
+ service: this.serviceName(this.config, this.system),
17
18
  resource: trim(query, 5000),
18
19
  type: 'cassandra',
19
20
  kind: 'client',
@@ -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
  }
@@ -33,7 +33,7 @@ class DNSLookupPlugin extends ClientPlugin {
33
33
  span.setTag('dns.address', result)
34
34
  }
35
35
 
36
- span.finish()
36
+ super.finish()
37
37
  }
38
38
  }
39
39
 
@@ -8,8 +8,8 @@ class ElasticsearchPlugin extends DatabasePlugin {
8
8
  start ({ params }) {
9
9
  const body = getBody(params.body || params.bulkBody)
10
10
 
11
- this.startSpan(`${this.system}.query`, {
12
- service: this.config.service,
11
+ this.startSpan(this.operationName(), {
12
+ service: this.serviceName(this.config),
13
13
  resource: `${params.method} ${quantizePath(params.path)}`,
14
14
  type: 'elasticsearch',
15
15
  kind: 'client',
@@ -32,7 +32,7 @@ class GoogleCloudPubsubConsumerPlugin extends ConsumerPlugin {
32
32
  span.setTag('pubsub.ack', 1)
33
33
  }
34
34
 
35
- span.finish()
35
+ super.finish()
36
36
  }
37
37
  }
38
38
 
@@ -32,7 +32,7 @@ class GraphQLExecutePlugin extends TracingPlugin {
32
32
  finish ({ res, args }) {
33
33
  const span = this.activeSpan
34
34
  this.config.hooks.execute(span, args, res)
35
- span.finish()
35
+ super.finish()
36
36
  }
37
37
  }
38
38
 
@@ -25,7 +25,7 @@ class GraphQLParsePlugin extends TracingPlugin {
25
25
 
26
26
  this.config.hooks.parse(span, source, document)
27
27
 
28
- span.finish()
28
+ super.finish()
29
29
  }
30
30
  }
31
31
 
@@ -56,11 +56,6 @@ class GraphQLResolvePlugin extends TracingPlugin {
56
56
  }
57
57
  }
58
58
 
59
- finish (finishTime) {
60
- const span = this.activeSpan
61
- span.finish(finishTime)
62
- }
63
-
64
59
  constructor (...args) {
65
60
  super(...args)
66
61
 
@@ -21,7 +21,7 @@ class GraphQLValidatePlugin extends TracingPlugin {
21
21
  finish ({ document, errors }) {
22
22
  const span = this.activeSpan
23
23
  this.config.hooks.validate(span, document, errors)
24
- span.finish()
24
+ super.finish()
25
25
  }
26
26
  }
27
27