dd-trace 2.11.0 → 2.12.2
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/LICENSE-3rdparty.csv +0 -2
- package/ext/formats.js +3 -5
- package/index.d.ts +3 -3
- package/package.json +4 -6
- package/packages/datadog-core/src/storage/async_hooks.js +4 -4
- package/packages/datadog-core/src/storage/async_resource.js +14 -4
- package/packages/datadog-instrumentations/src/connect.js +5 -5
- package/packages/datadog-instrumentations/src/couchbase.js +166 -61
- package/packages/datadog-instrumentations/src/fastify.js +12 -25
- package/packages/datadog-instrumentations/src/graphql.js +17 -5
- package/packages/datadog-instrumentations/src/koa.js +5 -5
- package/packages/datadog-instrumentations/src/mocha.js +92 -19
- package/packages/datadog-instrumentations/src/restify.js +28 -10
- package/packages/datadog-instrumentations/src/router.js +5 -5
- package/packages/datadog-plugin-aws-sdk/src/base.js +1 -2
- package/packages/datadog-plugin-aws-sdk/src/services/sqs.js +1 -2
- package/packages/datadog-plugin-couchbase/src/index.js +8 -10
- package/packages/datadog-plugin-graphql/src/resolve.js +2 -0
- package/packages/datadog-plugin-http/src/server.js +3 -8
- package/packages/datadog-plugin-mocha/src/index.js +80 -3
- package/packages/datadog-plugin-next/src/index.js +1 -1
- package/packages/datadog-plugin-restify/src/index.js +7 -0
- package/packages/datadog-plugin-router/src/index.js +39 -10
- package/packages/dd-trace/src/encode/0.4.js +4 -0
- package/packages/dd-trace/src/encode/agentless-ci-visibility.js +111 -15
- package/packages/dd-trace/src/exporters/common/request.js +49 -34
- package/packages/dd-trace/src/exporters/common/writer.js +8 -1
- package/packages/dd-trace/src/noop/span.js +12 -12
- package/packages/dd-trace/src/noop/tracer.js +8 -5
- package/packages/dd-trace/src/opentracing/span.js +63 -49
- package/packages/dd-trace/src/opentracing/span_context.js +1 -5
- package/packages/dd-trace/src/opentracing/tracer.js +31 -36
- package/packages/dd-trace/src/plugin_manager.js +49 -33
- package/packages/dd-trace/src/plugins/util/test.js +32 -1
- package/packages/dd-trace/src/plugins/util/web.js +26 -18
- package/packages/dd-trace/src/profiling/config.js +10 -2
- package/packages/dd-trace/src/profiling/exporters/agent.js +1 -2
- package/packages/dd-trace/src/profiling/exporters/form-data.js +53 -0
- package/packages/dd-trace/src/profiling/index.js +2 -0
- package/packages/dd-trace/src/profiling/profiler.js +6 -1
- package/packages/dd-trace/src/profiling/profilers/cpu.js +126 -0
- package/packages/dd-trace/src/proxy.js +1 -4
|
@@ -3,13 +3,25 @@ const { truncateSpan, normalizeSpan } = require('./tags-processors')
|
|
|
3
3
|
const Chunk = require('./chunk')
|
|
4
4
|
const { AgentEncoder } = require('./0.4')
|
|
5
5
|
const { version: ddTraceVersion } = require('../../../../package.json')
|
|
6
|
+
const id = require('../../../dd-trace/src/id')
|
|
6
7
|
|
|
7
8
|
const ENCODING_VERSION = 1
|
|
8
9
|
|
|
10
|
+
const ALLOWED_CONTENT_TYPES = ['test_session_end', 'test_suite_end', 'test']
|
|
11
|
+
|
|
12
|
+
const TEST_SUITE_KEYS_LENGTH = 11
|
|
13
|
+
const TEST_SESSION_KEYS_LENGTH = 10
|
|
14
|
+
|
|
15
|
+
const CHUNK_SIZE = 4 * 1024 * 1024 // 4MB
|
|
16
|
+
|
|
9
17
|
function formatSpan (span) {
|
|
18
|
+
let encodingVersion = ENCODING_VERSION
|
|
19
|
+
if (span.type === 'test' && span.meta && span.meta.test_session_id) {
|
|
20
|
+
encodingVersion = 2
|
|
21
|
+
}
|
|
10
22
|
return {
|
|
11
|
-
type: span.type
|
|
12
|
-
version:
|
|
23
|
+
type: ALLOWED_CONTENT_TYPES.includes(span.type) ? span.type : 'span',
|
|
24
|
+
version: encodingVersion,
|
|
13
25
|
content: normalizeSpan(truncateSpan(span))
|
|
14
26
|
}
|
|
15
27
|
}
|
|
@@ -21,8 +33,8 @@ class AgentlessCiVisibilityEncoder extends AgentEncoder {
|
|
|
21
33
|
this.runtimeId = runtimeId
|
|
22
34
|
this.service = service
|
|
23
35
|
this.env = env
|
|
24
|
-
this._traceBytes = new Chunk()
|
|
25
|
-
this._stringBytes = new Chunk()
|
|
36
|
+
this._traceBytes = new Chunk(CHUNK_SIZE)
|
|
37
|
+
this._stringBytes = new Chunk(CHUNK_SIZE)
|
|
26
38
|
this._stringCount = 0
|
|
27
39
|
this._stringMap = {}
|
|
28
40
|
|
|
@@ -33,8 +45,69 @@ class AgentlessCiVisibilityEncoder extends AgentEncoder {
|
|
|
33
45
|
this.reset()
|
|
34
46
|
}
|
|
35
47
|
|
|
48
|
+
_encodeTestSuite (bytes, content) {
|
|
49
|
+
this._encodeMapPrefix(bytes, TEST_SUITE_KEYS_LENGTH)
|
|
50
|
+
this._encodeString(bytes, 'type')
|
|
51
|
+
this._encodeString(bytes, content.type)
|
|
52
|
+
|
|
53
|
+
this._encodeString(bytes, 'test_session_id')
|
|
54
|
+
this._encodeId(bytes, content.trace_id)
|
|
55
|
+
|
|
56
|
+
this._encodeString(bytes, 'test_suite_id')
|
|
57
|
+
this._encodeId(bytes, content.span_id)
|
|
58
|
+
|
|
59
|
+
this._encodeString(bytes, 'error')
|
|
60
|
+
this._encodeNumber(bytes, content.error)
|
|
61
|
+
this._encodeString(bytes, 'name')
|
|
62
|
+
this._encodeString(bytes, content.name)
|
|
63
|
+
this._encodeString(bytes, 'service')
|
|
64
|
+
this._encodeString(bytes, content.service)
|
|
65
|
+
this._encodeString(bytes, 'resource')
|
|
66
|
+
this._encodeString(bytes, content.resource)
|
|
67
|
+
this._encodeString(bytes, 'start')
|
|
68
|
+
this._encodeNumber(bytes, content.start)
|
|
69
|
+
this._encodeString(bytes, 'duration')
|
|
70
|
+
this._encodeNumber(bytes, content.duration)
|
|
71
|
+
this._encodeString(bytes, 'meta')
|
|
72
|
+
this._encodeMap(bytes, content.meta)
|
|
73
|
+
this._encodeString(bytes, 'metrics')
|
|
74
|
+
this._encodeMap(bytes, content.metrics)
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
_encodeTestSession (bytes, content) {
|
|
78
|
+
this._encodeMapPrefix(bytes, TEST_SESSION_KEYS_LENGTH)
|
|
79
|
+
this._encodeString(bytes, 'type')
|
|
80
|
+
this._encodeString(bytes, content.type)
|
|
81
|
+
|
|
82
|
+
this._encodeString(bytes, 'test_session_id')
|
|
83
|
+
this._encodeId(bytes, content.trace_id)
|
|
84
|
+
|
|
85
|
+
this._encodeString(bytes, 'error')
|
|
86
|
+
this._encodeNumber(bytes, content.error)
|
|
87
|
+
this._encodeString(bytes, 'name')
|
|
88
|
+
this._encodeString(bytes, content.name)
|
|
89
|
+
this._encodeString(bytes, 'service')
|
|
90
|
+
this._encodeString(bytes, content.service)
|
|
91
|
+
this._encodeString(bytes, 'resource')
|
|
92
|
+
this._encodeString(bytes, content.resource)
|
|
93
|
+
this._encodeString(bytes, 'start')
|
|
94
|
+
this._encodeNumber(bytes, content.start)
|
|
95
|
+
this._encodeString(bytes, 'duration')
|
|
96
|
+
this._encodeNumber(bytes, content.duration)
|
|
97
|
+
this._encodeString(bytes, 'meta')
|
|
98
|
+
this._encodeMap(bytes, content.meta)
|
|
99
|
+
this._encodeString(bytes, 'metrics')
|
|
100
|
+
this._encodeMap(bytes, content.metrics)
|
|
101
|
+
}
|
|
102
|
+
|
|
36
103
|
_encodeEventContent (bytes, content) {
|
|
37
|
-
|
|
104
|
+
const keysLength = Object.keys(content).length
|
|
105
|
+
if (content.meta.test_session_id) {
|
|
106
|
+
this._encodeMapPrefix(bytes, keysLength + 2)
|
|
107
|
+
} else {
|
|
108
|
+
this._encodeMapPrefix(bytes, keysLength)
|
|
109
|
+
}
|
|
110
|
+
|
|
38
111
|
if (content.type) {
|
|
39
112
|
this._encodeString(bytes, 'type')
|
|
40
113
|
this._encodeString(bytes, content.type)
|
|
@@ -57,6 +130,24 @@ class AgentlessCiVisibilityEncoder extends AgentEncoder {
|
|
|
57
130
|
this._encodeNumber(bytes, content.start)
|
|
58
131
|
this._encodeString(bytes, 'duration')
|
|
59
132
|
this._encodeNumber(bytes, content.duration)
|
|
133
|
+
/**
|
|
134
|
+
* We include `test_session_id` and `test_suite_id`
|
|
135
|
+
* in the root of the event by passing them via the `meta` dict.
|
|
136
|
+
* This is to avoid changing the span format in packages/dd-trace/src/format.js,
|
|
137
|
+
* which can have undesired side effects in other products.
|
|
138
|
+
* But `test_session_id` and `test_suite_id` are *not* supposed to be in `meta`,
|
|
139
|
+
* so we delete them before enconding the dictionary.
|
|
140
|
+
* TODO: find a better way to do this.
|
|
141
|
+
*/
|
|
142
|
+
if (content.meta.test_session_id) {
|
|
143
|
+
this._encodeString(bytes, 'test_session_id')
|
|
144
|
+
this._encodeId(bytes, id(content.meta.test_session_id))
|
|
145
|
+
delete content.meta.test_session_id
|
|
146
|
+
|
|
147
|
+
this._encodeString(bytes, 'test_suite_id')
|
|
148
|
+
this._encodeId(bytes, id(content.meta.test_suite_id))
|
|
149
|
+
delete content.meta.test_suite_id
|
|
150
|
+
}
|
|
60
151
|
this._encodeString(bytes, 'meta')
|
|
61
152
|
this._encodeMap(bytes, content.meta)
|
|
62
153
|
this._encodeString(bytes, 'metrics')
|
|
@@ -64,7 +155,7 @@ class AgentlessCiVisibilityEncoder extends AgentEncoder {
|
|
|
64
155
|
}
|
|
65
156
|
|
|
66
157
|
_encodeEvent (bytes, event) {
|
|
67
|
-
this._encodeMapPrefix(bytes, event)
|
|
158
|
+
this._encodeMapPrefix(bytes, Object.keys(event).length)
|
|
68
159
|
this._encodeString(bytes, 'type')
|
|
69
160
|
this._encodeString(bytes, event.type)
|
|
70
161
|
|
|
@@ -72,7 +163,13 @@ class AgentlessCiVisibilityEncoder extends AgentEncoder {
|
|
|
72
163
|
this._encodeNumber(bytes, event.version)
|
|
73
164
|
|
|
74
165
|
this._encodeString(bytes, 'content')
|
|
75
|
-
|
|
166
|
+
if (event.type === 'span' || event.type === 'test') {
|
|
167
|
+
this._encodeEventContent(bytes, event.content)
|
|
168
|
+
} else if (event.type === 'test_suite_end') {
|
|
169
|
+
this._encodeTestSuite(bytes, event.content)
|
|
170
|
+
} else if (event.type === 'test_session_end') {
|
|
171
|
+
this._encodeTestSession(bytes, event.content)
|
|
172
|
+
}
|
|
76
173
|
}
|
|
77
174
|
|
|
78
175
|
_encodeNumber (bytes, value) {
|
|
@@ -107,18 +204,17 @@ class AgentlessCiVisibilityEncoder extends AgentEncoder {
|
|
|
107
204
|
buffer[offset + 8] = lo
|
|
108
205
|
}
|
|
109
206
|
|
|
110
|
-
_encodeMapPrefix (bytes,
|
|
111
|
-
const keys = Object.keys(map)
|
|
207
|
+
_encodeMapPrefix (bytes, keysLength) {
|
|
112
208
|
const buffer = bytes.buffer
|
|
113
209
|
const offset = bytes.length
|
|
114
210
|
|
|
115
211
|
bytes.reserve(5)
|
|
116
212
|
bytes.length += 5
|
|
117
213
|
buffer[offset] = 0xdf
|
|
118
|
-
buffer[offset + 1] =
|
|
119
|
-
buffer[offset + 2] =
|
|
120
|
-
buffer[offset + 3] =
|
|
121
|
-
buffer[offset + 4] =
|
|
214
|
+
buffer[offset + 1] = keysLength >> 24
|
|
215
|
+
buffer[offset + 2] = keysLength >> 16
|
|
216
|
+
buffer[offset + 3] = keysLength >> 8
|
|
217
|
+
buffer[offset + 4] = keysLength
|
|
122
218
|
}
|
|
123
219
|
|
|
124
220
|
_encode (bytes, trace) {
|
|
@@ -171,11 +267,11 @@ class AgentlessCiVisibilityEncoder extends AgentEncoder {
|
|
|
171
267
|
payload.metadata['*']['runtime-id'] = this.runtimeId
|
|
172
268
|
}
|
|
173
269
|
|
|
174
|
-
this._encodeMapPrefix(bytes, payload)
|
|
270
|
+
this._encodeMapPrefix(bytes, Object.keys(payload).length)
|
|
175
271
|
this._encodeString(bytes, 'version')
|
|
176
272
|
this._encodeNumber(bytes, payload.version)
|
|
177
273
|
this._encodeString(bytes, 'metadata')
|
|
178
|
-
this._encodeMapPrefix(bytes, payload.metadata)
|
|
274
|
+
this._encodeMapPrefix(bytes, Object.keys(payload.metadata).length)
|
|
179
275
|
this._encodeString(bytes, '*')
|
|
180
276
|
this._encodeMap(bytes, payload.metadata['*'])
|
|
181
277
|
this._encodeString(bytes, 'events')
|
|
@@ -1,22 +1,33 @@
|
|
|
1
1
|
'use strict'
|
|
2
2
|
|
|
3
|
+
// TODO: Add test with slow or unresponsive agent.
|
|
4
|
+
// TODO: Add telemetry for things like dropped requests, errors, etc.
|
|
5
|
+
|
|
3
6
|
const http = require('http')
|
|
4
7
|
const https = require('https')
|
|
5
|
-
const log = require('../../log')
|
|
6
8
|
const docker = require('./docker')
|
|
7
9
|
const { storage } = require('../../../../datadog-core')
|
|
8
10
|
|
|
9
|
-
const
|
|
10
|
-
const
|
|
11
|
+
const keepAlive = true
|
|
12
|
+
const maxTotalSockets = 1
|
|
13
|
+
const maxActiveRequests = 8
|
|
14
|
+
const httpAgent = new http.Agent({ keepAlive, maxTotalSockets })
|
|
15
|
+
const httpsAgent = new https.Agent({ keepAlive, maxTotalSockets })
|
|
11
16
|
const containerId = docker.id()
|
|
12
17
|
|
|
18
|
+
let activeRequests = 0
|
|
19
|
+
|
|
13
20
|
function request (data, options, keepAlive, callback) {
|
|
14
21
|
if (!options.headers) {
|
|
15
22
|
options.headers = {}
|
|
16
23
|
}
|
|
24
|
+
|
|
25
|
+
// The timeout should be kept low to avoid excessive queueing.
|
|
26
|
+
const timeout = options.timeout || 2000
|
|
17
27
|
const isSecure = options.protocol === 'https:'
|
|
18
28
|
const client = isSecure ? https : http
|
|
19
29
|
const dataArray = [].concat(data)
|
|
30
|
+
|
|
20
31
|
options.headers['Content-Length'] = byteLength(dataArray)
|
|
21
32
|
|
|
22
33
|
if (containerId) {
|
|
@@ -27,39 +38,15 @@ function request (data, options, keepAlive, callback) {
|
|
|
27
38
|
options.agent = isSecure ? httpsAgent : httpAgent
|
|
28
39
|
}
|
|
29
40
|
|
|
30
|
-
const
|
|
31
|
-
dataArray.forEach(buffer => firstRequest.write(buffer))
|
|
32
|
-
|
|
33
|
-
// The first request will be retried
|
|
34
|
-
const firstRequestErrorHandler = () => {
|
|
35
|
-
log.debug('Retrying request to the intake')
|
|
36
|
-
const retriedReq = retriableRequest(options, client, callback)
|
|
37
|
-
dataArray.forEach(buffer => retriedReq.write(buffer))
|
|
38
|
-
// The retried request will fail normally
|
|
39
|
-
retriedReq.on('error', e => callback(new Error(`Network error trying to reach the intake: ${e.message}`)))
|
|
40
|
-
retriedReq.end()
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
firstRequest.on('error', firstRequestErrorHandler)
|
|
44
|
-
firstRequest.end()
|
|
45
|
-
|
|
46
|
-
return firstRequest
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
function retriableRequest (options, client, callback) {
|
|
50
|
-
const store = storage.getStore()
|
|
51
|
-
|
|
52
|
-
storage.enterWith({ noop: true })
|
|
53
|
-
|
|
54
|
-
const timeout = options.timeout || 15000
|
|
55
|
-
|
|
56
|
-
const request = client.request(options, res => {
|
|
41
|
+
const onResponse = res => {
|
|
57
42
|
let responseData = ''
|
|
58
43
|
|
|
59
44
|
res.setTimeout(timeout)
|
|
60
45
|
|
|
61
46
|
res.on('data', chunk => { responseData += chunk })
|
|
62
47
|
res.on('end', () => {
|
|
48
|
+
activeRequests--
|
|
49
|
+
|
|
63
50
|
if (res.statusCode >= 200 && res.statusCode <= 299) {
|
|
64
51
|
callback(null, responseData, res.statusCode)
|
|
65
52
|
} else {
|
|
@@ -69,15 +56,43 @@ function retriableRequest (options, client, callback) {
|
|
|
69
56
|
callback(error, null, res.statusCode)
|
|
70
57
|
}
|
|
71
58
|
})
|
|
72
|
-
}
|
|
73
|
-
request.setTimeout(timeout, request.abort)
|
|
74
|
-
storage.enterWith(store)
|
|
59
|
+
}
|
|
75
60
|
|
|
76
|
-
|
|
61
|
+
const makeRequest = onError => {
|
|
62
|
+
if (!request.writable) return callback(null)
|
|
63
|
+
|
|
64
|
+
activeRequests++
|
|
65
|
+
|
|
66
|
+
const store = storage.getStore()
|
|
67
|
+
|
|
68
|
+
storage.enterWith({ noop: true })
|
|
69
|
+
|
|
70
|
+
const req = client.request(options, onResponse)
|
|
71
|
+
|
|
72
|
+
req.once('error', err => {
|
|
73
|
+
activeRequests--
|
|
74
|
+
onError(err)
|
|
75
|
+
})
|
|
76
|
+
|
|
77
|
+
dataArray.forEach(buffer => req.write(buffer))
|
|
78
|
+
|
|
79
|
+
req.setTimeout(timeout, req.abort)
|
|
80
|
+
req.end()
|
|
81
|
+
|
|
82
|
+
storage.enterWith(store)
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
makeRequest(() => makeRequest(callback))
|
|
77
86
|
}
|
|
78
87
|
|
|
79
88
|
function byteLength (data) {
|
|
80
89
|
return data.length > 0 ? data.reduce((prev, next) => prev + next.length, 0) : 0
|
|
81
90
|
}
|
|
82
91
|
|
|
92
|
+
Object.defineProperty(request, 'writable', {
|
|
93
|
+
get () {
|
|
94
|
+
return activeRequests < maxActiveRequests
|
|
95
|
+
}
|
|
96
|
+
})
|
|
97
|
+
|
|
83
98
|
module.exports = request
|
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
'use strict'
|
|
2
|
+
|
|
3
|
+
const request = require('./request')
|
|
2
4
|
const log = require('../../log')
|
|
3
5
|
|
|
4
6
|
class Writer {
|
|
@@ -9,7 +11,10 @@ class Writer {
|
|
|
9
11
|
flush (done = () => {}) {
|
|
10
12
|
const count = this._encoder.count()
|
|
11
13
|
|
|
12
|
-
if (
|
|
14
|
+
if (!request.writable) {
|
|
15
|
+
this._encoder.reset()
|
|
16
|
+
done()
|
|
17
|
+
} else if (count > 0) {
|
|
13
18
|
const payload = this._encoder.makePayload()
|
|
14
19
|
|
|
15
20
|
this._sendPayload(payload, count, done)
|
|
@@ -19,6 +24,8 @@ class Writer {
|
|
|
19
24
|
}
|
|
20
25
|
|
|
21
26
|
append (spans) {
|
|
27
|
+
if (!request.writable) return
|
|
28
|
+
|
|
22
29
|
log.debug(() => `Encoding trace: ${JSON.stringify(spans)}`)
|
|
23
30
|
|
|
24
31
|
this._encode(spans)
|
|
@@ -1,26 +1,26 @@
|
|
|
1
1
|
'use strict'
|
|
2
2
|
|
|
3
|
-
const
|
|
4
|
-
const NoopSpanContext = require('../noop/span_context')
|
|
3
|
+
const NoopSpanContext = require('./span_context')
|
|
5
4
|
const id = require('../id')
|
|
6
5
|
const { storage } = require('../../../datadog-core') // TODO: noop storage?
|
|
7
6
|
|
|
8
|
-
class NoopSpan
|
|
7
|
+
class NoopSpan {
|
|
9
8
|
constructor (tracer, parent) {
|
|
10
|
-
super()
|
|
11
|
-
|
|
12
9
|
this._store = storage.getStore()
|
|
13
10
|
this._noopTracer = tracer
|
|
14
11
|
this._noopContext = this._createContext(parent)
|
|
15
12
|
}
|
|
16
13
|
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
}
|
|
14
|
+
context () { return this._noopContext }
|
|
15
|
+
tracer () { return this._noopTracer }
|
|
16
|
+
setOperationName (name) { return this }
|
|
17
|
+
setBaggageItem (key, value) { return this }
|
|
18
|
+
getBaggageItem (key) {}
|
|
19
|
+
setTag (key, value) { return this }
|
|
20
|
+
addTags (keyValueMap) { return this }
|
|
21
|
+
log () { return this }
|
|
22
|
+
logEvent () {}
|
|
23
|
+
finish (finishTime) {}
|
|
24
24
|
|
|
25
25
|
_createContext (parent) {
|
|
26
26
|
const spanId = id()
|
|
@@ -1,13 +1,10 @@
|
|
|
1
1
|
'use strict'
|
|
2
2
|
|
|
3
|
-
const Tracer = require('opentracing').Tracer
|
|
4
3
|
const Scope = require('../noop/scope')
|
|
5
4
|
const Span = require('./span')
|
|
6
5
|
|
|
7
|
-
class NoopTracer
|
|
6
|
+
class NoopTracer {
|
|
8
7
|
constructor (config) {
|
|
9
|
-
super(config)
|
|
10
|
-
|
|
11
8
|
this._scope = new Scope()
|
|
12
9
|
this._span = new Span(this)
|
|
13
10
|
}
|
|
@@ -35,10 +32,16 @@ class NoopTracer extends Tracer {
|
|
|
35
32
|
setUrl () {
|
|
36
33
|
}
|
|
37
34
|
|
|
38
|
-
|
|
35
|
+
startSpan (name, options) {
|
|
39
36
|
return this._span
|
|
40
37
|
}
|
|
41
38
|
|
|
39
|
+
inject (spanContext, format, carrier) {}
|
|
40
|
+
|
|
41
|
+
extract (format, carrier) {
|
|
42
|
+
return this._span.context()
|
|
43
|
+
}
|
|
44
|
+
|
|
42
45
|
setUser () {
|
|
43
46
|
return this
|
|
44
47
|
}
|
|
@@ -1,11 +1,9 @@
|
|
|
1
1
|
'use strict'
|
|
2
2
|
|
|
3
3
|
// TODO (new internal tracer): use DC events for lifecycle metrics and test them
|
|
4
|
-
|
|
5
|
-
const
|
|
6
|
-
const now = require('performance-now')
|
|
4
|
+
const now = require('perf_hooks').performance.now
|
|
5
|
+
const dateNow = Date.now
|
|
7
6
|
const semver = require('semver')
|
|
8
|
-
const Span = opentracing.Span
|
|
9
7
|
const SpanContext = require('./span_context')
|
|
10
8
|
const id = require('../id')
|
|
11
9
|
const tagger = require('../tagger')
|
|
@@ -21,10 +19,8 @@ const {
|
|
|
21
19
|
const unfinishedRegistry = createRegistry('unfinished')
|
|
22
20
|
const finishedRegistry = createRegistry('finished')
|
|
23
21
|
|
|
24
|
-
class DatadogSpan
|
|
22
|
+
class DatadogSpan {
|
|
25
23
|
constructor (tracer, processor, prioritySampler, fields, debug) {
|
|
26
|
-
super()
|
|
27
|
-
|
|
28
24
|
const operationName = fields.operationName
|
|
29
25
|
const parent = fields.parent || null
|
|
30
26
|
const tags = Object.assign({}, fields.tags)
|
|
@@ -70,66 +66,45 @@ class DatadogSpan extends Span {
|
|
|
70
66
|
return `Span${json}`
|
|
71
67
|
}
|
|
72
68
|
|
|
73
|
-
|
|
74
|
-
let spanContext
|
|
75
|
-
|
|
76
|
-
if (parent) {
|
|
77
|
-
spanContext = new SpanContext({
|
|
78
|
-
traceId: parent._traceId,
|
|
79
|
-
spanId: id(),
|
|
80
|
-
parentId: parent._spanId,
|
|
81
|
-
sampling: parent._sampling,
|
|
82
|
-
baggageItems: Object.assign({}, parent._baggageItems),
|
|
83
|
-
trace: parent._trace
|
|
84
|
-
})
|
|
85
|
-
} else {
|
|
86
|
-
const spanId = id()
|
|
87
|
-
spanContext = new SpanContext({
|
|
88
|
-
traceId: spanId,
|
|
89
|
-
spanId
|
|
90
|
-
})
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
spanContext._trace.started.push(this)
|
|
94
|
-
spanContext._trace.startTime = spanContext._trace.startTime || Date.now()
|
|
95
|
-
spanContext._trace.ticks = spanContext._trace.ticks || now()
|
|
96
|
-
|
|
97
|
-
return spanContext
|
|
98
|
-
}
|
|
99
|
-
|
|
100
|
-
_getTime () {
|
|
101
|
-
const { startTime, ticks } = this._spanContext._trace
|
|
102
|
-
|
|
103
|
-
return startTime + now() - ticks
|
|
104
|
-
}
|
|
105
|
-
|
|
106
|
-
_context () {
|
|
69
|
+
context () {
|
|
107
70
|
return this._spanContext
|
|
108
71
|
}
|
|
109
72
|
|
|
110
|
-
|
|
73
|
+
tracer () {
|
|
111
74
|
return this._parentTracer
|
|
112
75
|
}
|
|
113
76
|
|
|
114
|
-
|
|
77
|
+
setOperationName (name) {
|
|
115
78
|
this._spanContext._name = name
|
|
79
|
+
return this
|
|
116
80
|
}
|
|
117
81
|
|
|
118
|
-
|
|
82
|
+
setBaggageItem (key, value) {
|
|
119
83
|
this._spanContext._baggageItems[key] = value
|
|
84
|
+
return this
|
|
120
85
|
}
|
|
121
86
|
|
|
122
|
-
|
|
87
|
+
getBaggageItem (key) {
|
|
123
88
|
return this._spanContext._baggageItems[key]
|
|
124
89
|
}
|
|
125
90
|
|
|
126
|
-
|
|
127
|
-
|
|
91
|
+
setTag (key, value) {
|
|
92
|
+
this._addTags({ [key]: value })
|
|
93
|
+
return this
|
|
94
|
+
}
|
|
128
95
|
|
|
129
|
-
|
|
96
|
+
addTags (keyValueMap) {
|
|
97
|
+
this._addTags(keyValueMap)
|
|
98
|
+
return this
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
log () {
|
|
102
|
+
return this
|
|
130
103
|
}
|
|
131
104
|
|
|
132
|
-
|
|
105
|
+
logEvent () {}
|
|
106
|
+
|
|
107
|
+
finish (finishTime) {
|
|
133
108
|
if (this._duration !== undefined) {
|
|
134
109
|
return
|
|
135
110
|
}
|
|
@@ -157,6 +132,45 @@ class DatadogSpan extends Span {
|
|
|
157
132
|
this._spanContext._isFinished = true
|
|
158
133
|
this._processor.process(this)
|
|
159
134
|
}
|
|
135
|
+
|
|
136
|
+
_createContext (parent) {
|
|
137
|
+
let spanContext
|
|
138
|
+
|
|
139
|
+
if (parent) {
|
|
140
|
+
spanContext = new SpanContext({
|
|
141
|
+
traceId: parent._traceId,
|
|
142
|
+
spanId: id(),
|
|
143
|
+
parentId: parent._spanId,
|
|
144
|
+
sampling: parent._sampling,
|
|
145
|
+
baggageItems: Object.assign({}, parent._baggageItems),
|
|
146
|
+
trace: parent._trace
|
|
147
|
+
})
|
|
148
|
+
} else {
|
|
149
|
+
const spanId = id()
|
|
150
|
+
spanContext = new SpanContext({
|
|
151
|
+
traceId: spanId,
|
|
152
|
+
spanId
|
|
153
|
+
})
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
spanContext._trace.started.push(this)
|
|
157
|
+
spanContext._trace.startTime = spanContext._trace.startTime || dateNow()
|
|
158
|
+
spanContext._trace.ticks = spanContext._trace.ticks || now()
|
|
159
|
+
|
|
160
|
+
return spanContext
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
_getTime () {
|
|
164
|
+
const { startTime, ticks } = this._spanContext._trace
|
|
165
|
+
|
|
166
|
+
return startTime + now() - ticks
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
_addTags (keyValuePairs) {
|
|
170
|
+
tagger.add(this._spanContext._tags, keyValuePairs)
|
|
171
|
+
|
|
172
|
+
this._prioritySampler.sample(this, false)
|
|
173
|
+
}
|
|
160
174
|
}
|
|
161
175
|
|
|
162
176
|
function createRegistry (type) {
|