dd-trace 4.30.0 → 4.32.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.
- package/index.d.ts +39 -0
- package/package.json +2 -2
- package/packages/datadog-instrumentations/src/apollo.js +101 -0
- package/packages/datadog-instrumentations/src/helpers/hooks.js +1 -0
- package/packages/datadog-instrumentations/src/mongodb-core.js +1 -3
- package/packages/datadog-instrumentations/src/playwright.js +151 -6
- package/packages/datadog-plugin-apollo/src/gateway/execute.js +12 -0
- package/packages/datadog-plugin-apollo/src/gateway/fetch.js +36 -0
- package/packages/datadog-plugin-apollo/src/gateway/index.js +36 -0
- package/packages/datadog-plugin-apollo/src/gateway/plan.js +13 -0
- package/packages/datadog-plugin-apollo/src/gateway/postprocessing.js +12 -0
- package/packages/datadog-plugin-apollo/src/gateway/request.js +139 -0
- package/packages/datadog-plugin-apollo/src/gateway/validate.js +21 -0
- package/packages/datadog-plugin-apollo/src/index.js +15 -0
- package/packages/datadog-plugin-cucumber/src/index.js +2 -2
- package/packages/datadog-plugin-cypress/src/cypress-plugin.js +2 -2
- package/packages/datadog-plugin-jest/src/index.js +2 -2
- package/packages/datadog-plugin-mocha/src/index.js +2 -2
- package/packages/datadog-plugin-playwright/src/index.js +10 -2
- package/packages/dd-trace/src/appsec/iast/iast-plugin.js +23 -12
- package/packages/dd-trace/src/appsec/iast/path-line.js +9 -6
- package/packages/dd-trace/src/appsec/iast/taint-tracking/operations.js +1 -1
- package/packages/dd-trace/src/appsec/iast/taint-tracking/plugin.js +6 -2
- package/packages/dd-trace/src/appsec/iast/taint-tracking/rewriter-telemetry.js +1 -1
- package/packages/dd-trace/src/appsec/iast/taint-tracking/rewriter.js +6 -7
- package/packages/dd-trace/src/appsec/iast/taint-tracking/taint-tracking-impl.js +1 -1
- package/packages/dd-trace/src/appsec/iast/telemetry/iast-metric.js +34 -27
- package/packages/dd-trace/src/appsec/iast/telemetry/namespaces.js +39 -11
- package/packages/dd-trace/src/appsec/iast/telemetry/span-tags.js +7 -6
- package/packages/dd-trace/src/appsec/reporter.js +24 -11
- package/packages/dd-trace/src/ci-visibility/exporters/agent-proxy/index.js +6 -1
- package/packages/dd-trace/src/lambda/runtime/ritm.js +1 -1
- package/packages/dd-trace/src/opentracing/propagation/text_map.js +21 -2
- package/packages/dd-trace/src/opentracing/span.js +2 -0
- package/packages/dd-trace/src/opentracing/span_context.js +1 -0
- package/packages/dd-trace/src/plugin_manager.js +1 -2
- package/packages/dd-trace/src/plugins/apollo.js +50 -0
- package/packages/dd-trace/src/plugins/composite.js +1 -0
- package/packages/dd-trace/src/plugins/index.js +1 -0
- package/packages/dd-trace/src/plugins/tracing.js +8 -5
- package/packages/dd-trace/src/plugins/util/test.js +2 -2
- package/packages/dd-trace/src/priority_sampler.js +11 -6
- package/packages/dd-trace/src/profiling/profilers/events.js +79 -82
- package/packages/dd-trace/src/proxy.js +2 -0
- package/packages/dd-trace/src/service-naming/schemas/v0/web.js +24 -0
- package/packages/dd-trace/src/service-naming/schemas/v1/web.js +24 -0
- package/packages/dd-trace/src/telemetry/index.js +15 -4
- package/CONTRIBUTING.md +0 -171
- package/MIGRATING.md +0 -224
- package/packages/dd-trace/src/external-logger/test/index.spec.js +0 -147
- package/scripts/check-proposal-labels.js +0 -71
- package/scripts/check_licenses.js +0 -69
- package/scripts/helpers/color.js +0 -8
- package/scripts/helpers/exec.js +0 -22
- package/scripts/helpers/title.js +0 -15
- package/scripts/install_plugin_modules.js +0 -248
- package/scripts/publish_docs.js +0 -21
- package/scripts/st.js +0 -105
|
@@ -171,6 +171,14 @@ class TextMapPropagator {
|
|
|
171
171
|
carrier[traceparentKey] = spanContext.toTraceparent()
|
|
172
172
|
|
|
173
173
|
ts.forVendor('dd', state => {
|
|
174
|
+
if (!spanContext._isRemote) {
|
|
175
|
+
// SpanContext was created by a ddtrace span.
|
|
176
|
+
// Last datadog span id should be set to the current span.
|
|
177
|
+
state.set('p', spanContext._spanId)
|
|
178
|
+
} else if (spanContext._trace.tags['_dd.parent_id']) {
|
|
179
|
+
// Propagate the last Datadog span id set on the remote span.
|
|
180
|
+
state.set('p', spanContext._trace.tags['_dd.parent_id'])
|
|
181
|
+
}
|
|
174
182
|
state.set('s', priority)
|
|
175
183
|
if (mechanism) {
|
|
176
184
|
state.set('t.dm', `-${mechanism}`)
|
|
@@ -279,7 +287,8 @@ class TextMapPropagator {
|
|
|
279
287
|
return new DatadogSpanContext({
|
|
280
288
|
traceId: id(),
|
|
281
289
|
spanId: null,
|
|
282
|
-
sampling: { priority }
|
|
290
|
+
sampling: { priority },
|
|
291
|
+
isRemote: true
|
|
283
292
|
})
|
|
284
293
|
}
|
|
285
294
|
|
|
@@ -327,6 +336,7 @@ class TextMapPropagator {
|
|
|
327
336
|
const spanContext = new DatadogSpanContext({
|
|
328
337
|
traceId: id(traceId, 16),
|
|
329
338
|
spanId: id(spanId, 16),
|
|
339
|
+
isRemote: true,
|
|
330
340
|
sampling: { priority: parseInt(flags, 10) & 1 ? 1 : 0 },
|
|
331
341
|
traceparent,
|
|
332
342
|
tracestate
|
|
@@ -337,6 +347,10 @@ class TextMapPropagator {
|
|
|
337
347
|
tracestate.forVendor('dd', state => {
|
|
338
348
|
for (const [key, value] of state.entries()) {
|
|
339
349
|
switch (key) {
|
|
350
|
+
case 'p': {
|
|
351
|
+
spanContext._trace.tags['_dd.parent_id'] = value
|
|
352
|
+
break
|
|
353
|
+
}
|
|
340
354
|
case 's': {
|
|
341
355
|
const priority = parseInt(value, 10)
|
|
342
356
|
if (!Number.isInteger(priority)) continue
|
|
@@ -367,6 +381,10 @@ class TextMapPropagator {
|
|
|
367
381
|
}
|
|
368
382
|
})
|
|
369
383
|
|
|
384
|
+
if (!spanContext._trace.tags['_dd.parent_id']) {
|
|
385
|
+
spanContext._trace.tags['_dd.parent_id'] = '0000000000000000'
|
|
386
|
+
}
|
|
387
|
+
|
|
370
388
|
this._extractBaggageItems(carrier, spanContext)
|
|
371
389
|
return spanContext
|
|
372
390
|
}
|
|
@@ -379,7 +397,8 @@ class TextMapPropagator {
|
|
|
379
397
|
|
|
380
398
|
return new DatadogSpanContext({
|
|
381
399
|
traceId: id(carrier[traceKey], radix),
|
|
382
|
-
spanId: id(carrier[spanKey], radix)
|
|
400
|
+
spanId: id(carrier[spanKey], radix),
|
|
401
|
+
isRemote: true
|
|
383
402
|
})
|
|
384
403
|
}
|
|
385
404
|
|
|
@@ -4,7 +4,6 @@ const { channel } = require('dc-polyfill')
|
|
|
4
4
|
const { isFalse } = require('./util')
|
|
5
5
|
const plugins = require('./plugins')
|
|
6
6
|
const log = require('./log')
|
|
7
|
-
const Nomenclature = require('./service-naming')
|
|
8
7
|
|
|
9
8
|
const loadChannel = channel('dd-trace:instrumentation:load')
|
|
10
9
|
|
|
@@ -102,7 +101,7 @@ module.exports = class PluginManager {
|
|
|
102
101
|
// like instrumenter.enable()
|
|
103
102
|
configure (config = {}) {
|
|
104
103
|
this._tracerConfig = config
|
|
105
|
-
|
|
104
|
+
this._tracer._nomenclature.configure(config)
|
|
106
105
|
|
|
107
106
|
for (const name in pluginClasses) {
|
|
108
107
|
this.loadPlugin(name)
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
const TracingPlugin = require('./tracing')
|
|
2
|
+
const { storage } = require('../../../datadog-core')
|
|
3
|
+
|
|
4
|
+
class ApolloBasePlugin extends TracingPlugin {
|
|
5
|
+
static get id () { return 'apollo.gateway' }
|
|
6
|
+
static get type () { return 'web' }
|
|
7
|
+
static get kind () { return 'server' }
|
|
8
|
+
|
|
9
|
+
bindStart (ctx) {
|
|
10
|
+
const store = storage.getStore()
|
|
11
|
+
const childOf = store ? store.span : null
|
|
12
|
+
|
|
13
|
+
const span = this.startSpan(this.getOperationName(), {
|
|
14
|
+
childOf,
|
|
15
|
+
service: this.getServiceName(),
|
|
16
|
+
type: this.constructor.type,
|
|
17
|
+
kind: this.constructor.kind,
|
|
18
|
+
meta: {}
|
|
19
|
+
}, false)
|
|
20
|
+
|
|
21
|
+
ctx.parentStore = store
|
|
22
|
+
ctx.currentStore = { ...store, span }
|
|
23
|
+
|
|
24
|
+
return ctx.currentStore
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
end (ctx) {
|
|
28
|
+
ctx?.currentStore?.span.finish()
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
asyncStart (ctx) {
|
|
32
|
+
ctx?.currentStore?.span.finish()
|
|
33
|
+
return ctx.parentStore
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
getServiceName () {
|
|
37
|
+
return this.serviceName({
|
|
38
|
+
id: `${this.constructor.id}.${this.constructor.operation}`,
|
|
39
|
+
pluginConfig: this.config
|
|
40
|
+
})
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
getOperationName () {
|
|
44
|
+
return this.operationName({
|
|
45
|
+
id: `${this.constructor.id}.${this.constructor.operation}`
|
|
46
|
+
})
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
module.exports = ApolloBasePlugin
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
'use strict'
|
|
2
2
|
|
|
3
3
|
module.exports = {
|
|
4
|
+
get '@apollo/gateway' () { return require('../../../datadog-plugin-apollo/src') },
|
|
4
5
|
get '@aws-sdk/smithy-client' () { return require('../../../datadog-plugin-aws-sdk/src') },
|
|
5
6
|
get '@cucumber/cucumber' () { return require('../../../datadog-plugin-cucumber/src') },
|
|
6
7
|
get '@playwright/test' () { return require('../../../datadog-plugin-playwright/src') },
|
|
@@ -4,7 +4,6 @@ const Plugin = require('./plugin')
|
|
|
4
4
|
const { storage } = require('../../../datadog-core')
|
|
5
5
|
const analyticsSampler = require('../analytics_sampler')
|
|
6
6
|
const { COMPONENT } = require('../constants')
|
|
7
|
-
const Nomenclature = require('../service-naming')
|
|
8
7
|
|
|
9
8
|
class TracingPlugin extends Plugin {
|
|
10
9
|
constructor (...args) {
|
|
@@ -29,7 +28,7 @@ class TracingPlugin extends Plugin {
|
|
|
29
28
|
kind = this.constructor.kind
|
|
30
29
|
} = opts
|
|
31
30
|
|
|
32
|
-
return
|
|
31
|
+
return this._tracer._nomenclature.serviceName(type, kind, id, opts)
|
|
33
32
|
}
|
|
34
33
|
|
|
35
34
|
operationName (opts = {}) {
|
|
@@ -39,7 +38,7 @@ class TracingPlugin extends Plugin {
|
|
|
39
38
|
kind = this.constructor.kind
|
|
40
39
|
} = opts
|
|
41
40
|
|
|
42
|
-
return
|
|
41
|
+
return this._tracer._nomenclature.opName(type, kind, id, opts)
|
|
43
42
|
}
|
|
44
43
|
|
|
45
44
|
configure (config) {
|
|
@@ -58,8 +57,12 @@ class TracingPlugin extends Plugin {
|
|
|
58
57
|
this.activeSpan?.finish()
|
|
59
58
|
}
|
|
60
59
|
|
|
61
|
-
error (
|
|
62
|
-
|
|
60
|
+
error (ctxOrError) {
|
|
61
|
+
if (ctxOrError?.currentStore) {
|
|
62
|
+
ctxOrError.currentStore?.span.setTag('error', ctxOrError?.error)
|
|
63
|
+
return
|
|
64
|
+
}
|
|
65
|
+
this.addError(ctxOrError)
|
|
63
66
|
}
|
|
64
67
|
|
|
65
68
|
addTraceSubs () {
|
|
@@ -52,7 +52,7 @@ const TEST_SKIPPED_BY_ITR = 'test.skipped_by_itr'
|
|
|
52
52
|
const TEST_CONFIGURATION_BROWSER_NAME = 'test.configuration.browser_name'
|
|
53
53
|
// Early flake detection
|
|
54
54
|
const TEST_IS_NEW = 'test.is_new'
|
|
55
|
-
const
|
|
55
|
+
const TEST_IS_RETRY = 'test.is_retry'
|
|
56
56
|
const TEST_EARLY_FLAKE_IS_ENABLED = 'test.early_flake.is_enabled'
|
|
57
57
|
|
|
58
58
|
const CI_APP_ORIGIN = 'ciapp-test'
|
|
@@ -101,7 +101,7 @@ module.exports = {
|
|
|
101
101
|
TEST_SKIPPED_BY_ITR,
|
|
102
102
|
TEST_CONFIGURATION_BROWSER_NAME,
|
|
103
103
|
TEST_IS_NEW,
|
|
104
|
-
|
|
104
|
+
TEST_IS_RETRY,
|
|
105
105
|
TEST_EARLY_FLAKE_IS_ENABLED,
|
|
106
106
|
getTestEnvironmentMetadata,
|
|
107
107
|
getTestParametersString,
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
'use strict'
|
|
2
2
|
|
|
3
|
+
const RateLimiter = require('./rate_limiter')
|
|
3
4
|
const Sampler = require('./sampler')
|
|
4
5
|
const { setSamplingRules } = require('./startup-log')
|
|
5
6
|
const SamplingRule = require('./sampling_rule')
|
|
@@ -43,6 +44,7 @@ class PrioritySampler {
|
|
|
43
44
|
configure (env, { sampleRate, rateLimit = 100, rules = [] } = {}) {
|
|
44
45
|
this._env = env
|
|
45
46
|
this._rules = this._normalizeRules(rules, sampleRate, rateLimit)
|
|
47
|
+
this._limiter = new RateLimiter(rateLimit)
|
|
46
48
|
|
|
47
49
|
setSamplingRules(this._rules)
|
|
48
50
|
}
|
|
@@ -136,14 +138,17 @@ class PrioritySampler {
|
|
|
136
138
|
context._trace[SAMPLING_RULE_DECISION] = rule.sampleRate
|
|
137
139
|
context._sampling.mechanism = SAMPLING_MECHANISM_RULE
|
|
138
140
|
|
|
139
|
-
|
|
140
|
-
|
|
141
|
+
return rule.sample() && this._isSampledByRateLimit(context)
|
|
142
|
+
? USER_KEEP
|
|
143
|
+
: USER_REJECT
|
|
144
|
+
}
|
|
141
145
|
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
146
|
+
_isSampledByRateLimit (context) {
|
|
147
|
+
const allowed = this._limiter.isAllowed()
|
|
148
|
+
|
|
149
|
+
context._trace[SAMPLING_LIMIT_DECISION] = this._limiter.effectiveRate()
|
|
145
150
|
|
|
146
|
-
return
|
|
151
|
+
return allowed
|
|
147
152
|
}
|
|
148
153
|
|
|
149
154
|
_getPriorityByAgent (context) {
|
|
@@ -15,6 +15,8 @@ const MS_TO_NS = 1000000
|
|
|
15
15
|
const pprofValueType = 'timeline'
|
|
16
16
|
const pprofValueUnit = 'nanoseconds'
|
|
17
17
|
|
|
18
|
+
const dateOffset = BigInt(Math.round(performance.timeOrigin * MS_TO_NS))
|
|
19
|
+
|
|
18
20
|
function labelFromStr (stringTable, key, valStr) {
|
|
19
21
|
return new Label({ key, str: stringTable.dedup(valStr) })
|
|
20
22
|
}
|
|
@@ -146,6 +148,76 @@ if (node16) {
|
|
|
146
148
|
decoratorTypes.net = NetDecorator
|
|
147
149
|
}
|
|
148
150
|
|
|
151
|
+
// Translates performance entries into pprof samples.
|
|
152
|
+
class EventSerializer {
|
|
153
|
+
constructor () {
|
|
154
|
+
this.stringTable = new StringTable()
|
|
155
|
+
this.samples = []
|
|
156
|
+
this.locations = []
|
|
157
|
+
this.functions = []
|
|
158
|
+
this.decorators = {}
|
|
159
|
+
|
|
160
|
+
// A synthetic single-frame location to serve as the location for timeline
|
|
161
|
+
// samples. We need these as the profiling backend (mimicking official pprof
|
|
162
|
+
// tool's behavior) ignores these.
|
|
163
|
+
const fn = new Function({ id: this.functions.length + 1, name: this.stringTable.dedup('') })
|
|
164
|
+
this.functions.push(fn)
|
|
165
|
+
const line = new Line({ functionId: fn.id })
|
|
166
|
+
const location = new Location({ id: this.locations.length + 1, line: [line] })
|
|
167
|
+
this.locations.push(location)
|
|
168
|
+
this.locationId = [location.id]
|
|
169
|
+
|
|
170
|
+
this.timestampLabelKey = this.stringTable.dedup(END_TIMESTAMP_LABEL)
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
addEvent (item) {
|
|
174
|
+
const { entryType, startTime, duration } = item
|
|
175
|
+
let decorator = this.decorators[entryType]
|
|
176
|
+
if (!decorator) {
|
|
177
|
+
const DecoratorCtor = decoratorTypes[entryType]
|
|
178
|
+
if (DecoratorCtor) {
|
|
179
|
+
decorator = new DecoratorCtor(this.stringTable)
|
|
180
|
+
decorator.eventTypeLabel = labelFromStrStr(this.stringTable, 'event', entryType)
|
|
181
|
+
this.decorators[entryType] = decorator
|
|
182
|
+
} else {
|
|
183
|
+
// Shouldn't happen but it's better to not rely on observer only getting
|
|
184
|
+
// requested event types.
|
|
185
|
+
return
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
const endTime = startTime + duration
|
|
189
|
+
const sampleInput = {
|
|
190
|
+
value: [Math.round(duration * MS_TO_NS)],
|
|
191
|
+
locationId: this.locationId,
|
|
192
|
+
label: [
|
|
193
|
+
decorator.eventTypeLabel,
|
|
194
|
+
new Label({ key: this.timestampLabelKey, num: dateOffset + BigInt(Math.round(endTime * MS_TO_NS)) })
|
|
195
|
+
]
|
|
196
|
+
}
|
|
197
|
+
decorator.decorateSample(sampleInput, item)
|
|
198
|
+
this.samples.push(new Sample(sampleInput))
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
createProfile (startDate, endDate) {
|
|
202
|
+
const timeValueType = new ValueType({
|
|
203
|
+
type: this.stringTable.dedup(pprofValueType),
|
|
204
|
+
unit: this.stringTable.dedup(pprofValueUnit)
|
|
205
|
+
})
|
|
206
|
+
|
|
207
|
+
return new Profile({
|
|
208
|
+
sampleType: [timeValueType],
|
|
209
|
+
timeNanos: endDate.getTime() * MS_TO_NS,
|
|
210
|
+
periodType: timeValueType,
|
|
211
|
+
period: 1,
|
|
212
|
+
durationNanos: (endDate.getTime() - startDate.getTime()) * MS_TO_NS,
|
|
213
|
+
sample: this.samples,
|
|
214
|
+
location: this.locations,
|
|
215
|
+
function: this.functions,
|
|
216
|
+
stringTable: this.stringTable
|
|
217
|
+
})
|
|
218
|
+
}
|
|
219
|
+
}
|
|
220
|
+
|
|
149
221
|
/**
|
|
150
222
|
* This class generates pprof files with timeline events sourced from Node.js
|
|
151
223
|
* performance measurement APIs.
|
|
@@ -155,7 +227,7 @@ class EventsProfiler {
|
|
|
155
227
|
this.type = 'events'
|
|
156
228
|
this._flushIntervalNanos = (options.flushInterval || 60000) * 1e6 // 60 sec
|
|
157
229
|
this._observer = undefined
|
|
158
|
-
this.
|
|
230
|
+
this.eventSerializer = new EventSerializer()
|
|
159
231
|
}
|
|
160
232
|
|
|
161
233
|
start () {
|
|
@@ -163,7 +235,9 @@ class EventsProfiler {
|
|
|
163
235
|
if (this._observer) return
|
|
164
236
|
|
|
165
237
|
function add (items) {
|
|
166
|
-
|
|
238
|
+
for (const item of items.getEntries()) {
|
|
239
|
+
this.eventSerializer.addEvent(item)
|
|
240
|
+
}
|
|
167
241
|
}
|
|
168
242
|
this._observer = new PerformanceObserver(add.bind(this))
|
|
169
243
|
this._observer.observe({ entryTypes: Object.keys(decoratorTypes) })
|
|
@@ -177,89 +251,12 @@ class EventsProfiler {
|
|
|
177
251
|
}
|
|
178
252
|
|
|
179
253
|
profile (restart, startDate, endDate) {
|
|
180
|
-
if (this.entries.length === 0) {
|
|
181
|
-
// No events in the period; don't produce a profile
|
|
182
|
-
return null
|
|
183
|
-
}
|
|
184
|
-
|
|
185
|
-
const stringTable = new StringTable()
|
|
186
|
-
const locations = []
|
|
187
|
-
const functions = []
|
|
188
|
-
|
|
189
|
-
// A synthetic single-frame location to serve as the location for timeline
|
|
190
|
-
// samples. We need these as the profiling backend (mimicking official pprof
|
|
191
|
-
// tool's behavior) ignores these.
|
|
192
|
-
const locationId = (() => {
|
|
193
|
-
const fn = new Function({ id: functions.length + 1, name: stringTable.dedup('') })
|
|
194
|
-
functions.push(fn)
|
|
195
|
-
const line = new Line({ functionId: fn.id })
|
|
196
|
-
const location = new Location({ id: locations.length + 1, line: [line] })
|
|
197
|
-
locations.push(location)
|
|
198
|
-
return [location.id]
|
|
199
|
-
})()
|
|
200
|
-
|
|
201
|
-
const decorators = {}
|
|
202
|
-
for (const [eventType, DecoratorCtor] of Object.entries(decoratorTypes)) {
|
|
203
|
-
const decorator = new DecoratorCtor(stringTable)
|
|
204
|
-
decorator.eventTypeLabel = labelFromStrStr(stringTable, 'event', eventType)
|
|
205
|
-
decorators[eventType] = decorator
|
|
206
|
-
}
|
|
207
|
-
const timestampLabelKey = stringTable.dedup(END_TIMESTAMP_LABEL)
|
|
208
|
-
|
|
209
|
-
const dateOffset = BigInt(Math.round(performance.timeOrigin * MS_TO_NS))
|
|
210
|
-
const lateEntries = []
|
|
211
|
-
const perfEndDate = endDate.getTime() - performance.timeOrigin
|
|
212
|
-
const samples = this.entries.map((item) => {
|
|
213
|
-
const decorator = decorators[item.entryType]
|
|
214
|
-
if (!decorator) {
|
|
215
|
-
// Shouldn't happen but it's better to not rely on observer only getting
|
|
216
|
-
// requested event types.
|
|
217
|
-
return null
|
|
218
|
-
}
|
|
219
|
-
const { startTime, duration } = item
|
|
220
|
-
if (startTime >= perfEndDate) {
|
|
221
|
-
// An event past the current recording end date; save it for the next
|
|
222
|
-
// profile. Not supposed to happen as long as there's no async activity
|
|
223
|
-
// between capture of the endDate value in profiler.js _collect() and
|
|
224
|
-
// here, but better be safe than sorry.
|
|
225
|
-
lateEntries.push(item)
|
|
226
|
-
return null
|
|
227
|
-
}
|
|
228
|
-
const endTime = startTime + duration
|
|
229
|
-
const sampleInput = {
|
|
230
|
-
value: [Math.round(duration * MS_TO_NS)],
|
|
231
|
-
locationId,
|
|
232
|
-
label: [
|
|
233
|
-
decorator.eventTypeLabel,
|
|
234
|
-
new Label({ key: timestampLabelKey, num: dateOffset + BigInt(Math.round(endTime * MS_TO_NS)) })
|
|
235
|
-
]
|
|
236
|
-
}
|
|
237
|
-
decorator.decorateSample(sampleInput, item)
|
|
238
|
-
return new Sample(sampleInput)
|
|
239
|
-
}).filter(v => v)
|
|
240
|
-
|
|
241
|
-
this.entries = lateEntries
|
|
242
|
-
|
|
243
|
-
const timeValueType = new ValueType({
|
|
244
|
-
type: stringTable.dedup(pprofValueType),
|
|
245
|
-
unit: stringTable.dedup(pprofValueUnit)
|
|
246
|
-
})
|
|
247
|
-
|
|
248
254
|
if (!restart) {
|
|
249
255
|
this.stop()
|
|
250
256
|
}
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
timeNanos: endDate.getTime() * MS_TO_NS,
|
|
255
|
-
periodType: timeValueType,
|
|
256
|
-
period: 1,
|
|
257
|
-
durationNanos: (endDate.getTime() - startDate.getTime()) * MS_TO_NS,
|
|
258
|
-
sample: samples,
|
|
259
|
-
location: locations,
|
|
260
|
-
function: functions,
|
|
261
|
-
stringTable: stringTable
|
|
262
|
-
})
|
|
257
|
+
const profile = this.eventSerializer.createProfile(startDate, endDate)
|
|
258
|
+
this.eventSerializer = new EventSerializer()
|
|
259
|
+
return profile
|
|
263
260
|
}
|
|
264
261
|
|
|
265
262
|
encode (profile) {
|
|
@@ -6,6 +6,7 @@ const runtimeMetrics = require('./runtime_metrics')
|
|
|
6
6
|
const log = require('./log')
|
|
7
7
|
const { setStartupLogPluginManager } = require('./startup-log')
|
|
8
8
|
const telemetry = require('./telemetry')
|
|
9
|
+
const nomenclature = require('./service-naming')
|
|
9
10
|
const PluginManager = require('./plugin_manager')
|
|
10
11
|
const remoteConfig = require('./appsec/remote_config')
|
|
11
12
|
const AppsecSdk = require('./appsec/sdk')
|
|
@@ -17,6 +18,7 @@ class Tracer extends NoopProxy {
|
|
|
17
18
|
super()
|
|
18
19
|
|
|
19
20
|
this._initialized = false
|
|
21
|
+
this._nomenclature = nomenclature
|
|
20
22
|
this._pluginManager = new PluginManager(this)
|
|
21
23
|
this.dogstatsd = new dogstatsd.NoopDogStatsDClient()
|
|
22
24
|
this._tracingInitialized = false
|
|
@@ -33,6 +33,30 @@ const web = {
|
|
|
33
33
|
}
|
|
34
34
|
},
|
|
35
35
|
server: {
|
|
36
|
+
'apollo.gateway.request': {
|
|
37
|
+
opName: () => 'apollo.gateway.request',
|
|
38
|
+
serviceName: ({ pluginConfig, tracerService }) => pluginConfig.service || tracerService
|
|
39
|
+
},
|
|
40
|
+
'apollo.gateway.plan': {
|
|
41
|
+
opName: () => 'apollo.gateway.plan',
|
|
42
|
+
serviceName: ({ pluginConfig, tracerService }) => pluginConfig.service || tracerService
|
|
43
|
+
},
|
|
44
|
+
'apollo.gateway.validate': {
|
|
45
|
+
opName: () => 'apollo.gateway.validate',
|
|
46
|
+
serviceName: ({ pluginConfig, tracerService }) => pluginConfig.service || tracerService
|
|
47
|
+
},
|
|
48
|
+
'apollo.gateway.execute': {
|
|
49
|
+
opName: () => 'apollo.gateway.execute',
|
|
50
|
+
serviceName: ({ pluginConfig, tracerService }) => pluginConfig.service || tracerService
|
|
51
|
+
},
|
|
52
|
+
'apollo.gateway.fetch': {
|
|
53
|
+
opName: () => 'apollo.gateway.fetch',
|
|
54
|
+
serviceName: ({ pluginConfig, tracerService }) => pluginConfig.service || tracerService
|
|
55
|
+
},
|
|
56
|
+
'apollo.gateway.postprocessing': {
|
|
57
|
+
opName: () => 'apollo.gateway.postprocessing',
|
|
58
|
+
serviceName: ({ pluginConfig, tracerService }) => pluginConfig.service || tracerService
|
|
59
|
+
},
|
|
36
60
|
grpc: {
|
|
37
61
|
opName: () => DD_MAJOR <= 2 ? 'grpc.request' : 'grpc.server',
|
|
38
62
|
serviceName: identityService
|
|
@@ -32,6 +32,30 @@ const web = {
|
|
|
32
32
|
}
|
|
33
33
|
},
|
|
34
34
|
server: {
|
|
35
|
+
'apollo.gateway.request': {
|
|
36
|
+
opName: () => 'apollo.gateway.request',
|
|
37
|
+
serviceName: ({ pluginConfig, tracerService }) => pluginConfig.service || tracerService
|
|
38
|
+
},
|
|
39
|
+
'apollo.gateway.plan': {
|
|
40
|
+
opName: () => 'apollo.gateway.plan',
|
|
41
|
+
serviceName: ({ pluginConfig, tracerService }) => pluginConfig.service || tracerService
|
|
42
|
+
},
|
|
43
|
+
'apollo.gateway.validate': {
|
|
44
|
+
opName: () => 'apollo.gateway.validate',
|
|
45
|
+
serviceName: ({ pluginConfig, tracerService }) => pluginConfig.service || tracerService
|
|
46
|
+
},
|
|
47
|
+
'apollo.gateway.execute': {
|
|
48
|
+
opName: () => 'apollo.gateway.execute',
|
|
49
|
+
serviceName: ({ pluginConfig, tracerService }) => pluginConfig.service || tracerService
|
|
50
|
+
},
|
|
51
|
+
'apollo.gateway.fetch': {
|
|
52
|
+
opName: () => 'apollo.gateway.fetch',
|
|
53
|
+
serviceName: ({ pluginConfig, tracerService }) => pluginConfig.service || tracerService
|
|
54
|
+
},
|
|
55
|
+
'apollo.gateway.postprocessing': {
|
|
56
|
+
opName: () => 'apollo.gateway.postprocessing',
|
|
57
|
+
serviceName: ({ pluginConfig, tracerService }) => pluginConfig.service || tracerService
|
|
58
|
+
},
|
|
35
59
|
grpc: {
|
|
36
60
|
opName: () => 'grpc.server.request',
|
|
37
61
|
serviceName: identityService
|
|
@@ -304,30 +304,41 @@ function updateConfig (changes, config) {
|
|
|
304
304
|
const application = createAppObject(config)
|
|
305
305
|
const host = createHostObject()
|
|
306
306
|
|
|
307
|
-
const
|
|
307
|
+
const nameMapping = {
|
|
308
308
|
sampleRate: 'DD_TRACE_SAMPLE_RATE',
|
|
309
309
|
logInjection: 'DD_LOG_INJECTION',
|
|
310
310
|
headerTags: 'DD_TRACE_HEADER_TAGS',
|
|
311
311
|
tags: 'DD_TAGS'
|
|
312
312
|
}
|
|
313
313
|
|
|
314
|
+
const namesNeedFormatting = new Set(['DD_TAGS', 'peerServiceMapping'])
|
|
315
|
+
|
|
314
316
|
const configuration = []
|
|
317
|
+
const names = [] // list of config names whose values have been changed
|
|
315
318
|
|
|
316
319
|
for (const change of changes) {
|
|
317
|
-
const name =
|
|
320
|
+
const name = nameMapping[change.name] || change.name
|
|
321
|
+
names.push(name)
|
|
318
322
|
const { origin, value } = change
|
|
319
323
|
const entry = { name, value, origin }
|
|
320
324
|
|
|
321
325
|
if (Array.isArray(value)) entry.value = value.join(',')
|
|
322
|
-
if (entry.name
|
|
326
|
+
if (namesNeedFormatting.has(entry.name)) entry.value = formatMapForTelemetry(entry.value)
|
|
323
327
|
if (entry.name === 'url' && entry.value) entry.value = entry.value.toString()
|
|
324
|
-
if (entry.name === 'peerServiceMapping' || entry.name === 'tags') entry.value = formatMapForTelemetry(entry.value)
|
|
325
328
|
|
|
326
329
|
configuration.push(entry)
|
|
327
330
|
}
|
|
331
|
+
|
|
332
|
+
function isNotModified (entry) {
|
|
333
|
+
return !names.includes(entry.name)
|
|
334
|
+
}
|
|
335
|
+
|
|
328
336
|
if (!configWithOrigin.length) {
|
|
329
337
|
configWithOrigin = configuration
|
|
330
338
|
} else {
|
|
339
|
+
// update configWithOrigin to contain up-to-date full list of config values for app-extended-heartbeat
|
|
340
|
+
configWithOrigin = configWithOrigin.filter(isNotModified)
|
|
341
|
+
configWithOrigin = configWithOrigin.concat(configuration)
|
|
331
342
|
const { reqType, payload } = createPayload('app-client-configuration-change', { configuration })
|
|
332
343
|
sendData(config, application, host, reqType, payload, updateRetryData)
|
|
333
344
|
}
|