dd-trace 3.24.0 → 3.26.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
@@ -0,0 +1,194 @@
1
+ const os = require('os')
2
+ const pkg = require('../../../../package.json')
3
+ // Message pack int encoding is done in big endian, but data streams uses little endian
4
+ const Uint64 = require('int64-buffer').Uint64BE
5
+
6
+ const { LogCollapsingLowestDenseDDSketch } = require('@datadog/sketches-js')
7
+
8
+ const { DataStreamsWriter } = require('./writer')
9
+ const { computePathwayHash } = require('./pathway')
10
+ const ENTRY_PARENT_HASH = Buffer.from('0000000000000000', 'hex')
11
+
12
+ const HIGH_ACCURACY_DISTRIBUTION = 0.0075
13
+
14
+ class StatsPoint {
15
+ constructor (hash, parentHash, edgeTags) {
16
+ this.hash = new Uint64(hash)
17
+ this.parentHash = new Uint64(parentHash)
18
+ this.edgeTags = edgeTags
19
+ this.edgeLatency = new LogCollapsingLowestDenseDDSketch(HIGH_ACCURACY_DISTRIBUTION)
20
+ this.pathwayLatency = new LogCollapsingLowestDenseDDSketch(HIGH_ACCURACY_DISTRIBUTION)
21
+ }
22
+
23
+ addLatencies (checkpoint) {
24
+ const edgeLatencySec = checkpoint.edgeLatencyNs / 1e9
25
+ const pathwayLatencySec = checkpoint.pathwayLatencyNs / 1e9
26
+ this.edgeLatency.accept(edgeLatencySec)
27
+ this.pathwayLatency.accept(pathwayLatencySec)
28
+ }
29
+
30
+ encode () {
31
+ return {
32
+ Hash: this.hash,
33
+ ParentHash: this.parentHash,
34
+ EdgeTags: this.edgeTags,
35
+ EdgeLatency: this.edgeLatency.toProto(),
36
+ PathwayLatency: this.pathwayLatency.toProto()
37
+ }
38
+ }
39
+ }
40
+
41
+ class StatsBucket extends Map {
42
+ forCheckpoint (checkpoint) {
43
+ const key = checkpoint.hash
44
+ if (!this.has(key)) {
45
+ this.set(key, new StatsPoint(checkpoint.hash, checkpoint.parentHash, checkpoint.edgeTags)) // StatsPoint
46
+ }
47
+
48
+ return this.get(key)
49
+ }
50
+ }
51
+
52
+ class TimeBuckets extends Map {
53
+ forTime (time) {
54
+ if (!this.has(time)) {
55
+ this.set(time, new StatsBucket())
56
+ }
57
+
58
+ return this.get(time)
59
+ }
60
+ }
61
+
62
+ class DataStreamsProcessor {
63
+ constructor ({
64
+ dsmEnabled,
65
+ hostname,
66
+ port,
67
+ url,
68
+ env,
69
+ tags
70
+ } = {}) {
71
+ this.writer = new DataStreamsWriter({
72
+ hostname,
73
+ port,
74
+ url
75
+ })
76
+ this.bucketSizeNs = 1e10
77
+ this.buckets = new TimeBuckets()
78
+ this.hostname = os.hostname()
79
+ this.enabled = dsmEnabled
80
+ this.env = env
81
+ this.tags = tags || {}
82
+ this.service = this.tags.service || 'unnamed-nodejs-service'
83
+ this.sequence = 0
84
+
85
+ if (this.enabled) {
86
+ this.timer = setInterval(this.onInterval.bind(this), 10000)
87
+ this.timer.unref()
88
+ }
89
+ }
90
+
91
+ onInterval () {
92
+ const serialized = this._serializeBuckets()
93
+ if (!serialized) return
94
+ const payload = {
95
+ Env: this.env,
96
+ Service: this.service,
97
+ Stats: serialized,
98
+ TracerVersion: pkg.version,
99
+ Lang: 'javascript'
100
+ }
101
+ this.writer.flush(payload)
102
+ }
103
+
104
+ recordCheckpoint (checkpoint) {
105
+ if (!this.enabled) return
106
+ const bucketTime = Math.round(checkpoint.currentTimestamp - (checkpoint.currentTimestamp % this.bucketSizeNs))
107
+ this.buckets.forTime(bucketTime)
108
+ .forCheckpoint(checkpoint)
109
+ .addLatencies(checkpoint)
110
+ }
111
+
112
+ setCheckpoint (edgeTags, ctx = null) {
113
+ if (!this.enabled) return null
114
+ const nowNs = Date.now() * 1e6
115
+ const direction = edgeTags.find(t => t.startsWith('direction:'))
116
+ let pathwayStartNs = nowNs
117
+ let edgeStartNs = nowNs
118
+ let parentHash = ENTRY_PARENT_HASH
119
+ let closestOppositeDirectionHash = ENTRY_PARENT_HASH
120
+ let closestOppositeDirectionEdgeStart = nowNs
121
+ if (ctx != null) {
122
+ pathwayStartNs = ctx.pathwayStartNs
123
+ edgeStartNs = ctx.edgeStartNs
124
+ parentHash = ctx.hash
125
+ closestOppositeDirectionHash = ctx.closestOppositeDirectionHash || ENTRY_PARENT_HASH
126
+ closestOppositeDirectionEdgeStart = ctx.closestOppositeDirectionEdgeStart || nowNs
127
+ if (direction === ctx.previousDirection) {
128
+ parentHash = ctx.closestOppositeDirectionHash
129
+ if (parentHash === ENTRY_PARENT_HASH) {
130
+ // if the closest hash from opposite direction is the entry hash, that means
131
+ // we produce in a loop, without consuming
132
+ // in that case, we don't want the pathway to be longer and longer, but we want to restart a new pathway.
133
+ edgeStartNs = nowNs
134
+ pathwayStartNs = nowNs
135
+ } else {
136
+ edgeStartNs = ctx.closestOppositeDirectionEdgeStart
137
+ }
138
+ } else {
139
+ closestOppositeDirectionHash = parentHash
140
+ closestOppositeDirectionEdgeStart = edgeStartNs
141
+ }
142
+ }
143
+ const hash = computePathwayHash(this.service, this.env, edgeTags, parentHash)
144
+ const edgeLatencyNs = nowNs - edgeStartNs
145
+ const pathwayLatencyNs = nowNs - pathwayStartNs
146
+ const checkpoint = {
147
+ currentTimestamp: nowNs,
148
+ parentHash: parentHash,
149
+ hash: hash,
150
+ edgeTags: edgeTags,
151
+ edgeLatencyNs: edgeLatencyNs,
152
+ pathwayLatencyNs: pathwayLatencyNs
153
+ }
154
+ this.recordCheckpoint(checkpoint)
155
+ return {
156
+ hash: hash,
157
+ edgeStartNs: edgeStartNs,
158
+ pathwayStartNs: pathwayStartNs,
159
+ previousDirection: direction,
160
+ closestOppositeDirectionHash: closestOppositeDirectionHash,
161
+ closestOppositeDirectionEdgeStart: closestOppositeDirectionEdgeStart
162
+ }
163
+ }
164
+
165
+ _serializeBuckets () {
166
+ const serializedBuckets = []
167
+
168
+ for (const [ timeNs, bucket ] of this.buckets.entries()) {
169
+ const points = []
170
+
171
+ for (const stats of bucket.values()) {
172
+ points.push(stats.encode())
173
+ }
174
+
175
+ serializedBuckets.push({
176
+ Start: new Uint64(timeNs),
177
+ Duration: new Uint64(this.bucketSizeNs),
178
+ Stats: points
179
+ })
180
+ }
181
+
182
+ this.buckets.clear()
183
+
184
+ return serializedBuckets
185
+ }
186
+ }
187
+
188
+ module.exports = {
189
+ DataStreamsProcessor: DataStreamsProcessor,
190
+ StatsPoint: StatsPoint,
191
+ StatsBucket: StatsBucket,
192
+ TimeBuckets,
193
+ ENTRY_PARENT_HASH
194
+ }
@@ -0,0 +1,66 @@
1
+ const pkg = require('../../../../package.json')
2
+ const log = require('../log')
3
+ const request = require('../exporters/common/request')
4
+ const { URL, format } = require('url')
5
+ const msgpack = require('msgpack-lite')
6
+ const zlib = require('zlib')
7
+ const codec = msgpack.createCodec({ int64: true })
8
+
9
+ function makeRequest (data, url, cb) {
10
+ const options = {
11
+ path: '/v0.1/pipeline_stats',
12
+ method: 'POST',
13
+ headers: {
14
+ 'Datadog-Meta-Lang': 'javascript',
15
+ 'Datadog-Meta-Tracer-Version': pkg.version,
16
+ 'Content-Type': 'application/msgpack',
17
+ 'Content-Encoding': 'gzip'
18
+ }
19
+ }
20
+
21
+ options.protocol = url.protocol
22
+ options.hostname = url.hostname
23
+ options.port = url.port
24
+
25
+ log.debug(() => `Request to the intake: ${JSON.stringify(options)}`)
26
+
27
+ request(data, options, (err, res) => {
28
+ cb(err, res)
29
+ })
30
+ }
31
+
32
+ class DataStreamsWriter {
33
+ constructor (config) {
34
+ const { hostname = '127.0.0.1', port = 8126, url } = config
35
+ this._url = url || new URL(format({
36
+ protocol: 'http:',
37
+ hostname: hostname || 'localhost',
38
+ port
39
+ }))
40
+ }
41
+
42
+ flush (payload) {
43
+ if (!request.writable) {
44
+ log.debug(() => `Maximum number of active requests reached. Payload discarded: ${JSON.stringify(payload)}`)
45
+ return
46
+ }
47
+ const encodedPayload = msgpack.encode(payload, { codec })
48
+
49
+ zlib.gzip(encodedPayload, { level: 1 }, (err, compressedData) => {
50
+ if (err) {
51
+ log.error(err)
52
+ return
53
+ }
54
+ makeRequest(compressedData, this._url, (err, res) => {
55
+ log.debug(`Response from the agent: ${res}`)
56
+ if (err) {
57
+ log.error(err)
58
+ }
59
+ })
60
+ })
61
+ }
62
+ }
63
+
64
+ module.exports = {
65
+ DataStreamsWriter
66
+ }
@@ -8,7 +8,11 @@ const log = require('./log')
8
8
 
9
9
  const MAX_BUFFER_SIZE = 1024 // limit from the agent
10
10
 
11
- class Client {
11
+ const TYPE_COUNTER = 'c'
12
+ const TYPE_GAUGE = 'g'
13
+ const TYPE_DISTRIBUTION = 'd'
14
+
15
+ class DogStatsDClient {
12
16
  constructor (options) {
13
17
  options = options || {}
14
18
 
@@ -32,11 +36,15 @@ class Client {
32
36
  }
33
37
 
34
38
  gauge (stat, value, tags) {
35
- this._add(stat, value, 'g', tags)
39
+ this._add(stat, value, TYPE_GAUGE, tags)
36
40
  }
37
41
 
38
42
  increment (stat, value, tags) {
39
- this._add(stat, value, 'c', tags)
43
+ this._add(stat, value, TYPE_COUNTER, tags)
44
+ }
45
+
46
+ distribution (stat, value, tags) {
47
+ this._add(stat, value, TYPE_DISTRIBUTION, tags)
40
48
  }
41
49
 
42
50
  flush () {
@@ -135,4 +143,4 @@ class Client {
135
143
  }
136
144
  }
137
145
 
138
- module.exports = Client
146
+ module.exports = DogStatsDClient
@@ -7,6 +7,8 @@ class ExternalLogger {
7
7
  constructor ({
8
8
  ddsource, hostname, service, apiKey, site = 'datadoghq.com', interval = 10000, timeout = 2000, limit = 1000
9
9
  }) {
10
+ this.enabled = !!apiKey
11
+
10
12
  this.ddsource = ddsource
11
13
  this.hostname = hostname
12
14
  this.service = service
@@ -38,6 +40,8 @@ class ExternalLogger {
38
40
 
39
41
  // Parses and enqueues a log
40
42
  log (log, span, tags) {
43
+ if (!this.enabled) return
44
+
41
45
  const logTags = ExternalLogger.tagString(tags)
42
46
 
43
47
  if (span) {
@@ -38,6 +38,7 @@ class Span {
38
38
  context: spanContext._ddContext,
39
39
  startTime,
40
40
  hostname: _tracer._hostname,
41
+ integrationName: 'otel',
41
42
  tags: {
42
43
  'service.name': _tracer._service
43
44
  }
@@ -11,6 +11,9 @@ const tagger = require('../tagger')
11
11
  const metrics = require('../metrics')
12
12
  const log = require('../log')
13
13
  const { storage } = require('../../../datadog-core')
14
+ const telemetryMetrics = require('../telemetry/metrics')
15
+
16
+ const tracerMetrics = telemetryMetrics.manager.namespace('tracers')
14
17
 
15
18
  const {
16
19
  DD_TRACE_EXPERIMENTAL_STATE_TRACKING,
@@ -20,6 +23,30 @@ const {
20
23
  const unfinishedRegistry = createRegistry('unfinished')
21
24
  const finishedRegistry = createRegistry('finished')
22
25
 
26
+ const OTEL_ENABLED = !!process.env.DD_TRACE_OTEL_ENABLED
27
+
28
+ const integrationCounters = {
29
+ span_created: {},
30
+ span_finished: {}
31
+ }
32
+
33
+ function getIntegrationCounter (event, integration) {
34
+ const counters = integrationCounters[event]
35
+
36
+ if (integration in counters) {
37
+ return counters[integration]
38
+ }
39
+
40
+ const counter = tracerMetrics.count(event, [
41
+ `integration_name:${integration.toLowerCase()}`,
42
+ `otel_enabled:${OTEL_ENABLED}`
43
+ ])
44
+
45
+ integrationCounters[event][integration] = counter
46
+
47
+ return counter
48
+ }
49
+
23
50
  class DatadogSpan {
24
51
  constructor (tracer, processor, prioritySampler, fields, debug) {
25
52
  const operationName = fields.operationName
@@ -38,6 +65,9 @@ class DatadogSpan {
38
65
  // This name property is not updated when the span name changes.
39
66
  // This is necessary for span count metrics.
40
67
  this._name = operationName
68
+ this._integrationName = fields.integrationName || 'opentracing'
69
+
70
+ getIntegrationCounter('span_created', this._integrationName).inc()
41
71
 
42
72
  this._spanContext = this._createContext(parent, fields)
43
73
  this._spanContext._name = operationName
@@ -126,6 +156,8 @@ class DatadogSpan {
126
156
  }
127
157
  }
128
158
 
159
+ getIntegrationCounter('span_finished', this._integrationName).inc()
160
+
129
161
  if (DD_TRACE_EXPERIMENTAL_SPAN_COUNTS && finishedRegistry) {
130
162
  metrics.decrement('runtime.node.spans.unfinished')
131
163
  metrics.decrement('runtime.node.spans.unfinished.by.name', `span_name:${this._name}`)
@@ -26,6 +26,7 @@ class DatadogTracer {
26
26
  this._version = config.version
27
27
  this._env = config.env
28
28
  this._tags = config.tags
29
+ this._computePeerService = config.spanComputePeerService
29
30
  this._logInjection = config.logInjection
30
31
  this._debug = config.debug
31
32
  this._prioritySampler = new PrioritySampler(config.env, config.sampler)
@@ -60,7 +61,8 @@ class DatadogTracer {
60
61
  tags,
61
62
  startTime: options.startTime,
62
63
  hostname: this._hostname,
63
- traceId128BitGenerationEnabled: this._traceId128BitGenerationEnabled
64
+ traceId128BitGenerationEnabled: this._traceId128BitGenerationEnabled,
65
+ integrationName: options.integrationName
64
66
  }, this._debug)
65
67
 
66
68
  span.addTags(this._tags)
@@ -21,7 +21,7 @@ const disabledPlugins = new Set(
21
21
  DD_TRACE_DISABLED_PLUGINS && DD_TRACE_DISABLED_PLUGINS.split(',').map(plugin => plugin.trim())
22
22
  )
23
23
 
24
- // TODO actually ... should we be looking at envrionment variables this deep down in the code?
24
+ // TODO actually ... should we be looking at environment variables this deep down in the code?
25
25
 
26
26
  const pluginClasses = {}
27
27
 
@@ -133,7 +133,9 @@ module.exports = class PluginManager {
133
133
  serviceMapping,
134
134
  queryStringObfuscation,
135
135
  site,
136
- url
136
+ url,
137
+ dbmPropagationMode,
138
+ dsmEnabled
137
139
  } = this._tracerConfig
138
140
 
139
141
  const sharedConfig = {}
@@ -146,6 +148,9 @@ module.exports = class PluginManager {
146
148
  sharedConfig.queryStringObfuscation = queryStringObfuscation
147
149
  }
148
150
 
151
+ sharedConfig.dbmPropagationMode = dbmPropagationMode
152
+ sharedConfig.dsmEnabled = dsmEnabled
153
+
149
154
  if (serviceMapping && serviceMapping[name]) {
150
155
  sharedConfig.service = serviceMapping[name]
151
156
  }
@@ -5,6 +5,7 @@ const OutboundPlugin = require('./outbound')
5
5
  class ClientPlugin extends OutboundPlugin {
6
6
  static get operation () { return 'request' }
7
7
  static get kind () { return 'client' }
8
+ static get type () { return 'web' } // overridden by storage and other client type plugins
8
9
  }
9
10
 
10
11
  module.exports = ClientPlugin
@@ -4,6 +4,7 @@ const StoragePlugin = require('./storage')
4
4
 
5
5
  class DatabasePlugin extends StoragePlugin {
6
6
  static get operation () { return 'query' }
7
+ static get peerServicePrecursors () { return ['db.name'] }
7
8
 
8
9
  constructor (...args) {
9
10
  super(...args)
@@ -38,7 +39,7 @@ class DatabasePlugin extends StoragePlugin {
38
39
  }
39
40
 
40
41
  injectDbmQuery (query, serviceName, isPreparedStatement = false) {
41
- const mode = this.config.dbmPropagationMode || this._tracerConfig.dbmPropagationMode
42
+ const mode = this.config.dbmPropagationMode
42
43
 
43
44
  if (mode === 'disabled') {
44
45
  return query
@@ -14,6 +14,7 @@ module.exports = {
14
14
  get '@node-redis/client' () { return require('../../../datadog-plugin-redis/src') },
15
15
  get '@opensearch-project/opensearch' () { return require('../../../datadog-plugin-opensearch/src') },
16
16
  get '@redis/client' () { return require('../../../datadog-plugin-redis/src') },
17
+ get '@smithy/smithy-client' () { return require('../../../datadog-plugin-aws-sdk/src') },
17
18
  get 'amqp10' () { return require('../../../datadog-plugin-amqp10/src') },
18
19
  get 'amqplib' () { return require('../../../datadog-plugin-amqplib/src') },
19
20
  get 'aws-sdk' () { return require('../../../datadog-plugin-aws-sdk/src') },
@@ -56,6 +57,7 @@ module.exports = {
56
57
  get 'net' () { return require('../../../datadog-plugin-net/src') },
57
58
  get 'next' () { return require('../../../datadog-plugin-next/src') },
58
59
  get 'oracledb' () { return require('../../../datadog-plugin-oracledb/src') },
60
+ get 'openai' () { return require('../../../datadog-plugin-openai/src') },
59
61
  get 'paperplane' () { return require('../../../datadog-plugin-paperplane/src') },
60
62
  get 'pg' () { return require('../../../datadog-plugin-pg/src') },
61
63
  get 'pino' () { return require('../../../datadog-plugin-pino/src') },
@@ -1,10 +1,21 @@
1
1
  'use strict'
2
2
 
3
- const { CLIENT_PORT_KEY } = require('../constants')
3
+ const {
4
+ CLIENT_PORT_KEY,
5
+ PEER_SERVICE_KEY,
6
+ PEER_SERVICE_SOURCE_KEY
7
+ } = require('../constants')
4
8
  const TracingPlugin = require('./tracing')
5
9
 
10
+ const COMMON_PEER_SVC_SOURCE_TAGS = [
11
+ 'net.peer.name',
12
+ 'out.host'
13
+ ]
14
+
6
15
  // TODO: Exit span on finish when AsyncResource instances are removed.
7
16
  class OutboundPlugin extends TracingPlugin {
17
+ static get peerServicePrecursors () { return [] }
18
+
8
19
  constructor (...args) {
9
20
  super(...args)
10
21
 
@@ -13,6 +24,53 @@ class OutboundPlugin extends TracingPlugin {
13
24
  })
14
25
  }
15
26
 
27
+ getPeerService (tags) {
28
+ /**
29
+ * Compute `peer.service` and associated metadata from available tags, based
30
+ * on defined precursor tags names.
31
+ *
32
+ * - The `peer.service` tag is set from the first precursor available (based on list ordering)
33
+ * - The `_dd.peer.service.source` tag is set from the precursor's name
34
+ * - If `peer.service` was defined _before_ we compute it (for example in custom instrumentation),
35
+ * `_dd.peer.service.source`'s value is `peer.service`
36
+ */
37
+
38
+ if (tags['peer.service'] !== undefined) {
39
+ return { [PEER_SERVICE_SOURCE_KEY]: 'peer.service' }
40
+ }
41
+
42
+ const sourceTags = [
43
+ ...this.constructor.peerServicePrecursors,
44
+ ...COMMON_PEER_SVC_SOURCE_TAGS
45
+ ]
46
+
47
+ for (const sourceTag of sourceTags) {
48
+ if (tags[sourceTag]) {
49
+ return {
50
+ [PEER_SERVICE_KEY]: tags[sourceTag],
51
+ [PEER_SERVICE_SOURCE_KEY]: sourceTag
52
+ }
53
+ }
54
+ }
55
+ return {}
56
+ }
57
+
58
+ startSpan (name, options) {
59
+ const span = super.startSpan(name, options)
60
+ return span
61
+ }
62
+
63
+ finish () {
64
+ const span = this.activeSpan
65
+ if (this.tracer._computePeerService) {
66
+ const peerData = this.getPeerService(span.context()._tags)
67
+ if (peerData) {
68
+ span.addTags(peerData)
69
+ }
70
+ }
71
+ super.finish(...arguments)
72
+ }
73
+
16
74
  connect (url) {
17
75
  this.addHost(url.hostname, url.port)
18
76
  }
@@ -4,6 +4,8 @@ const InboundPlugin = require('./inbound')
4
4
 
5
5
  class ServerPlugin extends InboundPlugin {
6
6
  static get operation () { return 'request' }
7
+ static get kind () { return 'server' }
8
+ static get type () { return 'web' } // a default that may eventually be overriden by nonweb servers
7
9
  }
8
10
 
9
11
  module.exports = ServerPlugin
@@ -33,6 +33,9 @@ class TracingPlugin extends Plugin {
33
33
  }
34
34
 
35
35
  serviceName (...serviceArgs) {
36
+ if (Nomenclature.shouldUseConsistentServiceNaming) {
37
+ return Nomenclature.shortCircuitServiceName(this.config, ...serviceArgs)
38
+ }
36
39
  const { type, id, kind } = this.constructor
37
40
  return Nomenclature.serviceName(type, kind, id, ...serviceArgs)
38
41
  }
@@ -91,7 +94,8 @@ class TracingPlugin extends Plugin {
91
94
  'span.type': type,
92
95
  ...meta,
93
96
  ...metrics
94
- }
97
+ },
98
+ integrationName: type
95
99
  })
96
100
 
97
101
  analyticsSampler.sample(span, this.config.measured)
@@ -1,9 +1,11 @@
1
1
  const cp = require('child_process')
2
+ const log = require('../../log')
2
3
 
3
4
  const sanitizedExec = (cmd, flags, options = { stdio: 'pipe' }) => {
4
5
  try {
5
6
  return cp.execFileSync(cmd, flags, options).toString().replace(/(\r\n|\n|\r)/gm, '')
6
7
  } catch (e) {
8
+ log.error(e)
7
9
  return ''
8
10
  }
9
11
  }
@@ -35,13 +35,41 @@ function isShallowRepository () {
35
35
  return sanitizedExec('git', ['rev-parse', '--is-shallow-repository']) === 'true'
36
36
  }
37
37
 
38
- function unshallowRepository () {
38
+ function getGitVersion () {
39
+ const gitVersionString = sanitizedExec('git', ['version'])
40
+ const gitVersionMatches = gitVersionString.match(/git version (\d+)\.(\d+)\.(\d+)/)
39
41
  try {
40
- sanitizedExec('git', ['config', 'remote.origin.partialclonefilter', '"blob:none"'])
41
- sanitizedExec('git', ['fetch', '--shallow-since="1 month ago"', '--update-shallow', '--refetch'])
42
- } catch (err) {
43
- log.error(err)
42
+ return {
43
+ major: parseInt(gitVersionMatches[1]),
44
+ minor: parseInt(gitVersionMatches[2]),
45
+ patch: parseInt(gitVersionMatches[3])
46
+ }
47
+ } catch (e) {
48
+ return null
49
+ }
50
+ }
51
+
52
+ function unshallowRepository () {
53
+ const gitVersion = getGitVersion()
54
+ if (!gitVersion) {
55
+ log.warn('Git version could not be extracted, so git unshallow will not proceed')
56
+ return
44
57
  }
58
+ if (gitVersion.major < 2 || (gitVersion.major === 2 && gitVersion.minor < 27)) {
59
+ log.warn('Git version is <2.27, so git unshallow will not proceed')
60
+ return
61
+ }
62
+ const defaultRemoteName = sanitizedExec('git', ['config', '--default', 'origin', '--get', 'clone.defaultRemoteName'])
63
+ const revParseHead = sanitizedExec('git', ['rev-parse', 'HEAD'])
64
+ sanitizedExec('git', [
65
+ 'fetch',
66
+ '--shallow-since="1 month ago"',
67
+ '--update-shallow',
68
+ '--filter=blob:none',
69
+ '--recurse-submodules=no',
70
+ defaultRemoteName,
71
+ revParseHead
72
+ ])
45
73
  }
46
74
 
47
75
  function getRepositoryUrl () {
@@ -55,12 +83,12 @@ function getLatestCommits () {
55
83
  .split('\n')
56
84
  .filter(commit => commit)
57
85
  } catch (err) {
58
- log.error(err)
86
+ log.error(`Get latest commits failed: ${err.message}`)
59
87
  return []
60
88
  }
61
89
  }
62
90
 
63
- function getCommitsToUpload (commitsToExclude) {
91
+ function getCommitsToUpload (commitsToExclude, commitsToInclude) {
64
92
  const commitsToExcludeString = commitsToExclude.map(commit => `^${commit}`)
65
93
 
66
94
  try {
@@ -72,15 +100,15 @@ function getCommitsToUpload (commitsToExclude) {
72
100
  '--no-object-names',
73
101
  '--filter=blob:none',
74
102
  '--since="1 month ago"',
75
- 'HEAD',
76
- ...commitsToExcludeString
103
+ ...commitsToExcludeString,
104
+ ...commitsToInclude
77
105
  ],
78
106
  { stdio: 'pipe', maxBuffer: GIT_REV_LIST_MAX_BUFFER })
79
107
  .toString()
80
108
  .split('\n')
81
109
  .filter(commit => commit)
82
110
  } catch (err) {
83
- log.error(err)
111
+ log.error(`Get commits to upload failed: ${err.message}`)
84
112
  return []
85
113
  }
86
114
  }