dd-trace 5.0.0-pre-58d2e20 → 5.0.0-pre-efa6609

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 (48) hide show
  1. package/package.json +2 -2
  2. package/packages/datadog-instrumentations/src/aws-sdk.js +6 -2
  3. package/packages/datadog-instrumentations/src/couchbase.js +4 -4
  4. package/packages/datadog-instrumentations/src/fetch.js +24 -21
  5. package/packages/datadog-instrumentations/src/helpers/hooks.js +1 -0
  6. package/packages/datadog-instrumentations/src/http/client.js +41 -32
  7. package/packages/datadog-instrumentations/src/http2/client.js +1 -0
  8. package/packages/datadog-instrumentations/src/jest.js +26 -0
  9. package/packages/datadog-plugin-cassandra-driver/src/index.js +1 -1
  10. package/packages/datadog-plugin-elasticsearch/src/index.js +1 -1
  11. package/packages/datadog-plugin-fetch/src/index.js +7 -13
  12. package/packages/datadog-plugin-graphql/src/execute.js +6 -4
  13. package/packages/datadog-plugin-http/src/client.js +25 -20
  14. package/packages/datadog-plugin-memcached/src/index.js +1 -1
  15. package/packages/datadog-plugin-mongodb-core/src/index.js +1 -1
  16. package/packages/datadog-plugin-mysql/src/index.js +1 -1
  17. package/packages/datadog-plugin-openai/src/index.js +13 -7
  18. package/packages/datadog-plugin-openai/src/services.js +13 -9
  19. package/packages/datadog-plugin-oracledb/src/index.js +1 -1
  20. package/packages/datadog-plugin-pg/src/index.js +1 -1
  21. package/packages/datadog-plugin-redis/src/index.js +1 -1
  22. package/packages/datadog-plugin-tedious/src/index.js +1 -1
  23. package/packages/dd-trace/src/config.js +33 -15
  24. package/packages/dd-trace/src/external-logger/src/index.js +9 -1
  25. package/packages/dd-trace/src/external-logger/test/index.spec.js +1 -1
  26. package/packages/dd-trace/src/format.js +1 -1
  27. package/packages/dd-trace/src/opentelemetry/span.js +3 -1
  28. package/packages/dd-trace/src/opentracing/span_context.js +2 -1
  29. package/packages/dd-trace/src/plugins/index.js +1 -0
  30. package/packages/dd-trace/src/plugins/tracing.js +16 -9
  31. package/packages/dd-trace/src/plugins/util/ci.js +2 -1
  32. package/packages/dd-trace/src/profiling/exporters/agent.js +4 -1
  33. package/packages/dd-trace/src/proxy.js +2 -2
  34. package/packages/dd-trace/src/serverless.js +51 -7
  35. package/packages/dd-trace/src/service-naming/index.js +9 -13
  36. package/packages/dd-trace/src/service-naming/schemas/definition.js +4 -4
  37. package/packages/dd-trace/src/service-naming/schemas/util.js +2 -2
  38. package/packages/dd-trace/src/service-naming/schemas/v0/graphql.js +12 -0
  39. package/packages/dd-trace/src/service-naming/schemas/v0/index.js +2 -1
  40. package/packages/dd-trace/src/service-naming/schemas/v0/messaging.js +7 -7
  41. package/packages/dd-trace/src/service-naming/schemas/v0/storage.js +29 -23
  42. package/packages/dd-trace/src/service-naming/schemas/v1/graphql.js +12 -0
  43. package/packages/dd-trace/src/service-naming/schemas/v1/index.js +2 -1
  44. package/packages/dd-trace/src/service-naming/schemas/v1/storage.js +8 -9
  45. package/packages/dd-trace/src/span_sampler.js +1 -1
  46. package/packages/dd-trace/src/telemetry/metrics.js +11 -1
  47. package/packages/diagnostics_channel/src/index.js +1 -1
  48. package/scripts/install_plugin_modules.js +1 -0
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "dd-trace",
3
- "version": "5.0.0-pre-58d2e20",
3
+ "version": "5.0.0-pre-efa6609",
4
4
  "description": "Datadog APM tracing client for JavaScript",
5
5
  "main": "index.js",
6
6
  "typings": "index.d.ts",
@@ -68,7 +68,7 @@
68
68
  "dependencies": {
69
69
  "@datadog/native-appsec": "^3.2.0",
70
70
  "@datadog/native-iast-rewriter": "2.0.1",
71
- "@datadog/native-iast-taint-tracking": "^1.5.0",
71
+ "@datadog/native-iast-taint-tracking": "1.5.0",
72
72
  "@datadog/native-metrics": "^2.0.0",
73
73
  "@datadog/pprof": "3.1.0",
74
74
  "@datadog/sketches-js": "^2.1.0",
@@ -177,7 +177,6 @@ addHook({ name: '@aws-sdk/smithy-client', versions: ['>=3'] }, smithy => {
177
177
  })
178
178
 
179
179
  addHook({ name: 'aws-sdk', versions: ['>=2.3.0'] }, AWS => {
180
- shimmer.wrap(AWS.Request.prototype, 'promise', wrapRequest)
181
180
  shimmer.wrap(AWS.config, 'setPromisesDependency', setPromisesDependency => {
182
181
  return function wrappedSetPromisesDependency (dep) {
183
182
  const result = setPromisesDependency.apply(this, arguments)
@@ -188,9 +187,14 @@ addHook({ name: 'aws-sdk', versions: ['>=2.3.0'] }, AWS => {
188
187
  return AWS
189
188
  })
190
189
 
190
+ addHook({ name: 'aws-sdk', file: 'lib/core.js', versions: ['>=2.3.0'] }, AWS => {
191
+ shimmer.wrap(AWS.Request.prototype, 'promise', wrapRequest)
192
+ return AWS
193
+ })
194
+
191
195
  // <2.1.35 has breaking changes for instrumentation
192
196
  // https://github.com/aws/aws-sdk-js/pull/629
193
- addHook({ name: 'aws-sdk', versions: ['>=2.1.35'] }, AWS => {
197
+ addHook({ name: 'aws-sdk', file: 'lib/core.js', versions: ['>=2.1.35'] }, AWS => {
194
198
  shimmer.wrap(AWS.Request.prototype, 'send', wrapRequest)
195
199
  return AWS
196
200
  })
@@ -160,7 +160,7 @@ function wrapV3Query (query) {
160
160
  }
161
161
 
162
162
  // semver >=2 <3
163
- addHook({ name: 'couchbase', file: 'lib/bucket.js', versions: ['^2.6.5'] }, Bucket => {
163
+ addHook({ name: 'couchbase', file: 'lib/bucket.js', versions: ['^2.6.12'] }, Bucket => {
164
164
  const startCh = channel('apm:couchbase:query:start')
165
165
  const finishCh = channel('apm:couchbase:query:finish')
166
166
  const errorCh = channel('apm:couchbase:query:error')
@@ -208,7 +208,7 @@ addHook({ name: 'couchbase', file: 'lib/bucket.js', versions: ['^2.6.5'] }, Buck
208
208
  return Bucket
209
209
  })
210
210
 
211
- addHook({ name: 'couchbase', file: 'lib/cluster.js', versions: ['^2.6.5'] }, Cluster => {
211
+ addHook({ name: 'couchbase', file: 'lib/cluster.js', versions: ['^2.6.12'] }, Cluster => {
212
212
  Cluster.prototype._maybeInvoke = wrapMaybeInvoke(Cluster.prototype._maybeInvoke)
213
213
  Cluster.prototype.query = wrapQuery(Cluster.prototype.query)
214
214
 
@@ -217,7 +217,7 @@ addHook({ name: 'couchbase', file: 'lib/cluster.js', versions: ['^2.6.5'] }, Clu
217
217
 
218
218
  // semver >=3 <3.2.0
219
219
 
220
- addHook({ name: 'couchbase', file: 'lib/collection.js', versions: ['>=3.0.0 <3.2.0'] }, Collection => {
220
+ addHook({ name: 'couchbase', file: 'lib/collection.js', versions: ['^3.0.7', '^3.1.3'] }, Collection => {
221
221
  wrapAllNames(['upsert', 'insert', 'replace'], name => {
222
222
  shimmer.wrap(Collection.prototype, name, wrapWithName(name))
223
223
  })
@@ -225,7 +225,7 @@ addHook({ name: 'couchbase', file: 'lib/collection.js', versions: ['>=3.0.0 <3.2
225
225
  return Collection
226
226
  })
227
227
 
228
- addHook({ name: 'couchbase', file: 'lib/cluster.js', versions: ['>=3.0.0 <3.2.0'] }, Cluster => {
228
+ addHook({ name: 'couchbase', file: 'lib/cluster.js', versions: ['^3.0.7', '^3.1.3'] }, Cluster => {
229
229
  shimmer.wrap(Cluster.prototype, 'query', wrapV3Query)
230
230
  return Cluster
231
231
  })
@@ -17,29 +17,32 @@ function wrapFetch (fetch, Request) {
17
17
  const headers = req.headers
18
18
  const message = { req, headers }
19
19
 
20
- startChannel.publish(message)
21
-
22
- // Request object is read-only so we need new objects to change headers.
23
- arguments[0] = message.req
24
- arguments[1] = { headers: message.headers }
25
-
26
- return fetch.apply(this, arguments)
27
- .then(
28
- res => {
29
- finishChannel.publish({ req, res })
30
-
31
- return res
32
- },
33
- err => {
34
- if (err.name !== 'AbortError') {
35
- errorChannel.publish(err)
36
- }
20
+ return startChannel.runStores(message, () => {
21
+ // Request object is read-only so we need new objects to change headers.
22
+ arguments[0] = message.req
23
+ arguments[1] = { headers: message.headers }
24
+
25
+ return fetch.apply(this, arguments)
26
+ .then(
27
+ res => {
28
+ message.res = res
29
+
30
+ finishChannel.publish(message)
37
31
 
38
- finishChannel.publish({ req })
32
+ return res
33
+ },
34
+ err => {
35
+ if (err.name !== 'AbortError') {
36
+ message.error = err
37
+ errorChannel.publish(message)
38
+ }
39
39
 
40
- throw err
41
- }
42
- )
40
+ finishChannel.publish(message)
41
+
42
+ throw err
43
+ }
44
+ )
45
+ })
43
46
  }
44
47
  }
45
48
 
@@ -10,6 +10,7 @@ module.exports = {
10
10
  '@grpc/grpc-js': () => require('../grpc'),
11
11
  '@hapi/hapi': () => require('../hapi'),
12
12
  '@jest/core': () => require('../jest'),
13
+ '@jest/transform': () => require('../jest'),
13
14
  '@jest/reporters': () => require('../jest'),
14
15
  '@koa/router': () => require('../koa'),
15
16
  '@node-redis/client': () => require('../redis'),
@@ -3,18 +3,16 @@
3
3
  /* eslint-disable no-fallthrough */
4
4
 
5
5
  const url = require('url')
6
- const {
7
- channel,
8
- addHook,
9
- AsyncResource
10
- } = require('../helpers/instrument')
6
+ const { channel, addHook } = require('../helpers/instrument')
11
7
  const shimmer = require('../../../datadog-shimmer')
12
8
 
13
9
  const log = require('../../../dd-trace/src/log')
14
10
 
15
- const startClientCh = channel('apm:http:client:request:start')
16
- const finishClientCh = channel('apm:http:client:request:finish')
17
- const errorClientCh = channel('apm:http:client:request:error')
11
+ const startChannel = channel('apm:http:client:request:start')
12
+ const finishChannel = channel('apm:http:client:request:finish')
13
+ const endChannel = channel('apm:http:client:request:end')
14
+ const asyncStartChannel = channel('apm:http:client:request:asyncStart')
15
+ const errorChannel = channel('apm:http:client:request:error')
18
16
 
19
17
  addHook({ name: 'https' }, hookFn)
20
18
 
@@ -32,7 +30,7 @@ function patch (http, methodName) {
32
30
 
33
31
  function instrumentRequest (request) {
34
32
  return function () {
35
- if (!startClientCh.hasSubscribers) {
33
+ if (!startChannel.hasSubscribers) {
36
34
  return request.apply(this, arguments)
37
35
  }
38
36
 
@@ -45,57 +43,68 @@ function patch (http, methodName) {
45
43
  return request.apply(this, arguments)
46
44
  }
47
45
 
48
- const callbackResource = new AsyncResource('bound-anonymous-fn')
49
- const asyncResource = new AsyncResource('bound-anonymous-fn')
50
-
51
- return asyncResource.runInAsyncScope(() => {
52
- startClientCh.publish({ args, http })
46
+ const ctx = { args, http }
53
47
 
48
+ return startChannel.runStores(ctx, () => {
54
49
  let finished = false
55
50
  let callback = args.callback
56
51
 
57
52
  if (callback) {
58
- callback = callbackResource.bind(callback)
53
+ callback = function () {
54
+ return asyncStartChannel.runStores(ctx, () => {
55
+ return args.callback.apply(this, arguments)
56
+ })
57
+ }
59
58
  }
60
59
 
61
60
  const options = args.options
62
- const req = request.call(this, options, callback)
63
- const emit = req.emit
64
-
65
- const finish = (req, res) => {
61
+ const finish = () => {
66
62
  if (!finished) {
67
63
  finished = true
68
- finishClientCh.publish({ req, res })
64
+ finishChannel.publish(ctx)
69
65
  }
70
66
  }
71
67
 
72
- req.emit = function (eventName, arg) {
73
- asyncResource.runInAsyncScope(() => {
68
+ try {
69
+ const req = request.call(this, options, callback)
70
+ const emit = req.emit
71
+
72
+ ctx.req = req
73
+
74
+ req.emit = function (eventName, arg) {
74
75
  switch (eventName) {
75
76
  case 'response': {
76
77
  const res = arg
77
- const listener = asyncResource.bind(() => finish(req, res))
78
- res.on('end', listener)
79
- res.on('error', listener)
78
+ ctx.res = res
79
+ res.on('end', finish)
80
+ res.on('error', finish)
80
81
  break
81
82
  }
82
83
  case 'connect':
83
84
  case 'upgrade':
84
- finish(req, arg)
85
+ ctx.res = arg
86
+ finish()
85
87
  break
86
88
  case 'error':
87
89
  case 'timeout':
88
- errorClientCh.publish(arg)
90
+ ctx.error = arg
91
+ errorChannel.publish(ctx)
89
92
  case 'abort': // deprecated and replaced by `close` in node 17
90
93
  case 'close':
91
- finish(req)
94
+ finish()
92
95
  }
93
- })
94
96
 
95
- return emit.apply(this, arguments)
96
- }
97
+ return emit.apply(this, arguments)
98
+ }
97
99
 
98
- return req
100
+ return req
101
+ } catch (e) {
102
+ ctx.error = e
103
+ errorChannel.publish(ctx)
104
+ throw e
105
+ } finally {
106
+ endChannel.publish(ctx)
107
+ }
99
108
  })
100
109
  }
101
110
  }
@@ -42,6 +42,7 @@ function createWrapRequest (authority, options) {
42
42
  } catch (e) {
43
43
  ctx.error = e
44
44
  errorChannel.publish(ctx)
45
+ throw e
45
46
  } finally {
46
47
  endChannel.publish(ctx)
47
48
  }
@@ -410,6 +410,32 @@ function jestConfigSyncWrapper (jestConfig) {
410
410
  return jestConfig
411
411
  }
412
412
 
413
+ addHook({
414
+ name: '@jest/transform',
415
+ versions: ['>=24.8.0'],
416
+ file: 'build/ScriptTransformer.js'
417
+ }, transformPackage => {
418
+ const originalCreateScriptTransformer = transformPackage.createScriptTransformer
419
+
420
+ transformPackage.createScriptTransformer = async function (config) {
421
+ const { testEnvironmentOptions, ...restOfConfig } = config
422
+ const {
423
+ _ddTestModuleId,
424
+ _ddTestSessionId,
425
+ _ddTestCommand,
426
+ ...restOfTestEnvironmentOptions
427
+ } = testEnvironmentOptions
428
+
429
+ restOfConfig.testEnvironmentOptions = restOfTestEnvironmentOptions
430
+
431
+ arguments[0] = restOfConfig
432
+
433
+ return originalCreateScriptTransformer.apply(this, arguments)
434
+ }
435
+
436
+ return transformPackage
437
+ })
438
+
413
439
  /**
414
440
  * Hook to remove the test paths (test suite) that are part of `skippableSuites`
415
441
  */
@@ -14,7 +14,7 @@ class CassandraDriverPlugin extends DatabasePlugin {
14
14
  }
15
15
 
16
16
  this.startSpan(this.operationName(), {
17
- service: this.serviceName(this.config, this.system),
17
+ service: this.serviceName({ pluginConfig: this.config, system: this.system }),
18
18
  resource: trim(query, 5000),
19
19
  type: 'cassandra',
20
20
  kind: 'client',
@@ -9,7 +9,7 @@ class ElasticsearchPlugin extends DatabasePlugin {
9
9
  const body = getBody(params.body || params.bulkBody)
10
10
 
11
11
  this.startSpan(this.operationName(), {
12
- service: this.serviceName(this.config),
12
+ service: this.serviceName({ pluginConfig: this.config }),
13
13
  resource: `${params.method} ${quantizePath(params.path)}`,
14
14
  type: 'elasticsearch',
15
15
  kind: 'client',
@@ -1,35 +1,29 @@
1
1
  'use strict'
2
2
 
3
3
  const HttpClientPlugin = require('../../datadog-plugin-http/src/client')
4
- const { HTTP_HEADERS } = require('../../../ext/formats')
5
4
 
6
5
  class FetchPlugin extends HttpClientPlugin {
7
6
  static get id () { return 'fetch' }
7
+ static get prefix () { return `apm:fetch:request` }
8
8
 
9
9
  addTraceSub (eventName, handler) {
10
10
  this.addSub(`apm:${this.constructor.id}:${this.operation}:${eventName}`, handler)
11
11
  }
12
12
 
13
- start (message) {
13
+ bindStart (message) {
14
14
  const req = message.req
15
15
  const options = new URL(req.url)
16
16
  const headers = options.headers = Object.fromEntries(req.headers.entries())
17
17
 
18
- const args = { options }
18
+ options.method = req.method
19
19
 
20
- super.start({ args })
20
+ message.args = { options }
21
21
 
22
- message.req = new globalThis.Request(req, { headers })
23
- }
22
+ const store = super.bindStart(message)
24
23
 
25
- _inject (span, headers) {
26
- const carrier = {}
27
-
28
- this.tracer.inject(span, HTTP_HEADERS, carrier)
24
+ message.req = new globalThis.Request(req, { headers })
29
25
 
30
- for (const name in carrier) {
31
- headers.append(name, carrier[name])
32
- }
26
+ return store
33
27
  }
34
28
  }
35
29
 
@@ -7,6 +7,8 @@ let tools
7
7
  class GraphQLExecutePlugin extends TracingPlugin {
8
8
  static get id () { return 'graphql' }
9
9
  static get operation () { return 'execute' }
10
+ static get type () { return 'graphql' }
11
+ static get kind () { return 'server' }
10
12
 
11
13
  start ({ operation, args, docSource }) {
12
14
  const type = operation && operation.operation
@@ -14,11 +16,11 @@ class GraphQLExecutePlugin extends TracingPlugin {
14
16
  const document = args.document
15
17
  const source = this.config.source && document && docSource
16
18
 
17
- const span = this.startSpan('graphql.execute', {
18
- service: this.config.service,
19
+ const span = this.startSpan(this.operationName(), {
20
+ service: this.config.service || this.serviceName(),
19
21
  resource: getSignature(document, name, type, this.config.signature),
20
- kind: 'server',
21
- type: 'graphql',
22
+ kind: this.constructor.kind,
23
+ type: this.constructor.type,
22
24
  meta: {
23
25
  'graphql.operation.type': type,
24
26
  'graphql.operation.name': name,
@@ -16,15 +16,11 @@ const HTTP_REQUEST_HEADERS = tags.HTTP_REQUEST_HEADERS
16
16
  const HTTP_RESPONSE_HEADERS = tags.HTTP_RESPONSE_HEADERS
17
17
 
18
18
  class HttpClientPlugin extends ClientPlugin {
19
- static get id () {
20
- return 'http'
21
- }
22
-
23
- addTraceSub (eventName, handler) {
24
- this.addSub(`apm:${this.constructor.id}:client:${this.operation}:${eventName}`, handler)
25
- }
19
+ static get id () { return 'http' }
20
+ static get prefix () { return `apm:http:client:request` }
26
21
 
27
- start ({ args, http = {} }) {
22
+ bindStart (message) {
23
+ const { args, http = {} } = message
28
24
  const store = storage.getStore()
29
25
  const options = args.options
30
26
  const agent = options.agent || options._defaultAgent || http.globalAgent || {}
@@ -55,7 +51,7 @@ class HttpClientPlugin extends ClientPlugin {
55
51
  metrics: {
56
52
  [CLIENT_PORT_KEY]: parseInt(options.port)
57
53
  }
58
- })
54
+ }, false)
59
55
 
60
56
  // TODO: Figure out a better way to do this for any span.
61
57
  if (!allowed) {
@@ -67,11 +63,19 @@ class HttpClientPlugin extends ClientPlugin {
67
63
  }
68
64
 
69
65
  analyticsSampler.sample(span, this.config.measured)
70
- this.enter(span, store)
66
+
67
+ message.span = span
68
+ message.parentStore = store
69
+ message.currentStore = { ...store, span }
70
+
71
+ return message.currentStore
71
72
  }
72
73
 
73
- finish ({ req, res }) {
74
- const span = storage.getStore().span
74
+ bindAsyncStart ({ parentStore }) {
75
+ return parentStore
76
+ }
77
+
78
+ finish ({ req, res, span }) {
75
79
  if (res) {
76
80
  const status = res.status || res.statusCode
77
81
 
@@ -87,17 +91,18 @@ class HttpClientPlugin extends ClientPlugin {
87
91
  addRequestHeaders(req, span, this.config)
88
92
 
89
93
  this.config.hooks.request(span, req, res)
90
- super.finish()
91
- }
92
94
 
93
- error (err) {
94
- const span = storage.getStore().span
95
+ this.tagPeerService(span)
96
+
97
+ span.finish()
98
+ }
95
99
 
96
- if (err) {
100
+ error ({ span, error }) {
101
+ if (error) {
97
102
  span.addTags({
98
- [ERROR_TYPE]: err.name,
99
- [ERROR_MESSAGE]: err.message || err.code,
100
- [ERROR_STACK]: err.stack
103
+ [ERROR_TYPE]: error.name,
104
+ [ERROR_MESSAGE]: error.message || error.code,
105
+ [ERROR_STACK]: error.stack
101
106
  })
102
107
  } else {
103
108
  span.setTag('error', 1)
@@ -10,7 +10,7 @@ class MemcachedPlugin extends CachePlugin {
10
10
  const address = getAddress(client, server, query)
11
11
 
12
12
  this.startSpan({
13
- service: this.serviceName(this.config, this.system),
13
+ service: this.serviceName({ pluginConfig: this.config, system: this.system }),
14
14
  resource: query.type,
15
15
  type: 'memcached',
16
16
  meta: {
@@ -12,7 +12,7 @@ class MongodbCorePlugin extends DatabasePlugin {
12
12
  const query = getQuery(ops)
13
13
  const resource = truncate(getResource(this, ns, query, name))
14
14
  this.startSpan(this.operationName(), {
15
- service: this.serviceName(this.config),
15
+ service: this.serviceName({ pluginConfig: this.config }),
16
16
  resource,
17
17
  type: 'mongodb',
18
18
  kind: 'client',
@@ -8,7 +8,7 @@ class MySQLPlugin extends DatabasePlugin {
8
8
  static get system () { return 'mysql' }
9
9
 
10
10
  start (payload) {
11
- const service = this.serviceName(this.config, payload.conf, this.system)
11
+ const service = this.serviceName({ pluginConfig: this.config, dbConfig: payload.conf, system: this.system })
12
12
  this.startSpan(this.operationName(), {
13
13
  service,
14
14
  resource: payload.sql,
@@ -8,6 +8,10 @@ const services = require('./services')
8
8
  const Sampler = require('../../dd-trace/src/sampler')
9
9
  const { MEASURED } = require('../../../ext/tags')
10
10
 
11
+ // String#replaceAll unavailable on Node.js@v14 (dd-trace@<=v3)
12
+ const RE_NEWLINE = /\n/g
13
+ const RE_TAB = /\t/g
14
+
11
15
  // TODO: In the future we should refactor config.js to make it requirable
12
16
  let MAX_TEXT_LEN = 128
13
17
 
@@ -26,7 +30,9 @@ class OpenApiPlugin extends TracingPlugin {
26
30
  this.sampler = new Sampler(0.1) // default 10% log sampling
27
31
 
28
32
  // hoist the max length env var to avoid making all of these functions a class method
29
- MAX_TEXT_LEN = this._tracerConfig.openaiSpanCharLimit
33
+ if (this._tracerConfig) {
34
+ MAX_TEXT_LEN = this._tracerConfig.openaiSpanCharLimit
35
+ }
30
36
  }
31
37
 
32
38
  configure (config) {
@@ -83,11 +89,11 @@ class OpenApiPlugin extends TracingPlugin {
83
89
  store.prompt = prompt
84
90
  if (typeof prompt === 'string' || (Array.isArray(prompt) && typeof prompt[0] === 'number')) {
85
91
  // This is a single prompt, either String or [Number]
86
- tags[`openai.request.prompt`] = normalizeStringOrTokenArray(prompt)
92
+ tags[`openai.request.prompt`] = normalizeStringOrTokenArray(prompt, true)
87
93
  } else if (Array.isArray(prompt)) {
88
94
  // This is multiple prompts, either [String] or [[Number]]
89
95
  for (let i = 0; i < prompt.length; i++) {
90
- tags[`openai.request.prompt.${i}`] = normalizeStringOrTokenArray(prompt[i])
96
+ tags[`openai.request.prompt.${i}`] = normalizeStringOrTokenArray(prompt[i], true)
91
97
  }
92
98
  }
93
99
  }
@@ -547,7 +553,7 @@ function usageExtraction (tags, body) {
547
553
  }
548
554
 
549
555
  function truncateApiKey (apiKey) {
550
- return `sk-...${apiKey.substr(apiKey.length - 4)}`
556
+ return apiKey && `sk-...${apiKey.substr(apiKey.length - 4)}`
551
557
  }
552
558
 
553
559
  /**
@@ -557,8 +563,8 @@ function truncateText (text) {
557
563
  if (!text) return
558
564
 
559
565
  text = text
560
- .replaceAll('\n', '\\n')
561
- .replaceAll('\t', '\\t')
566
+ .replace(RE_NEWLINE, '\\n')
567
+ .replace(RE_TAB, '\\t')
562
568
 
563
569
  if (text.length > MAX_TEXT_LEN) {
564
570
  return text.substring(0, MAX_TEXT_LEN) + '...'
@@ -688,7 +694,7 @@ function normalizeRequestPayload (methodName, args) {
688
694
  * "foo" -> "foo"
689
695
  * [1,2,3] -> "[1, 2, 3]"
690
696
  */
691
- function normalizeStringOrTokenArray (input, truncate = true) {
697
+ function normalizeStringOrTokenArray (input, truncate) {
692
698
  const normalized = Array.isArray(input)
693
699
  ? `[${input.join(', ')}]` // "[1, 2, 999]"
694
700
  : input // "foo"
@@ -1,7 +1,7 @@
1
1
  'use strict'
2
2
 
3
3
  const { DogStatsDClient, NoopDogStatsDClient } = require('../../dd-trace/src/dogstatsd')
4
- const ExternalLogger = require('../../dd-trace/src/external-logger/src')
4
+ const { ExternalLogger, NoopExternalLogger } = require('../../dd-trace/src/external-logger/src')
5
5
 
6
6
  const FLUSH_INTERVAL = 10 * 1000
7
7
 
@@ -10,7 +10,7 @@ let logger = null
10
10
  let interval = null
11
11
 
12
12
  module.exports.init = function (tracerConfig) {
13
- if (tracerConfig.dogstatsd) {
13
+ if (tracerConfig && tracerConfig.dogstatsd) {
14
14
  metrics = new DogStatsDClient({
15
15
  host: tracerConfig.dogstatsd.hostname,
16
16
  port: tracerConfig.dogstatsd.port,
@@ -24,13 +24,17 @@ module.exports.init = function (tracerConfig) {
24
24
  metrics = new NoopDogStatsDClient()
25
25
  }
26
26
 
27
- logger = new ExternalLogger({
28
- ddsource: 'openai',
29
- hostname: tracerConfig.hostname,
30
- service: tracerConfig.service,
31
- apiKey: tracerConfig.apiKey,
32
- interval: FLUSH_INTERVAL
33
- })
27
+ if (tracerConfig && tracerConfig.apiKey) {
28
+ logger = new ExternalLogger({
29
+ ddsource: 'openai',
30
+ hostname: tracerConfig.hostname,
31
+ service: tracerConfig.service,
32
+ apiKey: tracerConfig.apiKey,
33
+ interval: FLUSH_INTERVAL
34
+ })
35
+ } else {
36
+ logger = new NoopExternalLogger()
37
+ }
34
38
 
35
39
  interval = setInterval(() => {
36
40
  metrics.flush()
@@ -10,7 +10,7 @@ class OracledbPlugin extends DatabasePlugin {
10
10
  static get peerServicePrecursors () { return ['db.instance', 'db.hostname'] }
11
11
 
12
12
  start ({ query, connAttrs }) {
13
- const service = this.serviceName(this.config, connAttrs)
13
+ const service = this.serviceName({ pluginConfig: this.config, params: connAttrs })
14
14
  const url = getUrl(connAttrs.connectString)
15
15
 
16
16
  this.startSpan(this.operationName(), {
@@ -9,7 +9,7 @@ class PGPlugin extends DatabasePlugin {
9
9
  static get system () { return 'postgres' }
10
10
 
11
11
  start ({ params = {}, query, processId }) {
12
- const service = this.serviceName(this.config, params)
12
+ const service = this.serviceName({ pluginConfig: this.config, params })
13
13
  const originalStatement = query.text
14
14
 
15
15
  this.startSpan(this.operationName(), {
@@ -15,7 +15,7 @@ class RedisPlugin extends CachePlugin {
15
15
 
16
16
  this.startSpan({
17
17
  resource,
18
- service: this.serviceName(this.config, this.system, connectionName),
18
+ service: this.serviceName({ pluginConfig: this.config, system: this.system, connectionName }),
19
19
  type: 'redis',
20
20
  meta: {
21
21
  'db.type': 'redis',
@@ -10,7 +10,7 @@ class TediousPlugin extends DatabasePlugin {
10
10
 
11
11
  start ({ queryOrProcedure, connectionConfig }) {
12
12
  this.startSpan(this.operationName(), {
13
- service: this.serviceName(this.config, this.system),
13
+ service: this.serviceName({ pluginConfig: this.config, system: this.system }),
14
14
  resource: queryOrProcedure,
15
15
  type: 'sql',
16
16
  kind: 'client',