dd-trace 2.12.0 → 3.0.0-pre.1

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.
@@ -1,548 +0,0 @@
1
- 'use strict'
2
-
3
- const { storage } = require('../../datadog-core')
4
-
5
- let kDirReadPromisified
6
- let kDirClosePromisified
7
- let kHandle
8
-
9
- const ddFhSym = Symbol('ddFileHandle')
10
-
11
- const tagMakers = {
12
- open: createOpenTags,
13
- close: createCloseTags,
14
- readFile: createReadFileTags,
15
- writeFile: createWriteFileTags,
16
- appendFile: createAppendFileTags,
17
- access: createPathTags,
18
- copyFile: createCopyFileTags,
19
- stat: createPathTags,
20
- lstat: createPathTags,
21
- fstat: createFDTags,
22
- readdir: createPathTags,
23
- opendir: createPathTags,
24
- read: createFDTags,
25
- write: createFDTags,
26
- writev: createFDTags,
27
- chmod: createChmodTags,
28
- lchmod: createChmodTags,
29
- fchmod: createFchmodTags,
30
- chown: createChownTags,
31
- lchown: createChownTags,
32
- fchown: createFchownTags,
33
- realpath: createPathTags,
34
- readlink: createPathTags,
35
- unlink: createPathTags,
36
- symlink: createCopyFileTags,
37
- link: createCopyFileTags,
38
- rmdir: createPathTags,
39
- rename: createCopyFileTags,
40
- fsync: createFDTags,
41
- fdatasync: createFDTags,
42
- mkdir: createPathTags,
43
- truncate: createPathTags,
44
- ftruncate: createFDTags,
45
- utimes: createPathTags,
46
- futimes: createFDTags,
47
- mkdtemp: createPathTags
48
- }
49
-
50
- const promisifiable = ['read', 'readv', 'write', 'writev']
51
-
52
- const orphanable = false
53
-
54
- function createWrapCreateReadStream (config, tracer) {
55
- return function wrapCreateReadStream (createReadStream) {
56
- return function createReadStreamWithTrace (path, options) {
57
- if (!hasParent()) {
58
- return createReadStream.apply(this, arguments)
59
- }
60
- const tags = makeFSFlagTags('ReadStream', path, options, 'r', config, tracer)
61
- return tracer.trace('fs.operation', { tags, orphanable }, (span, done) => {
62
- const stream = createReadStream.apply(this, arguments)
63
- stream.once('close', done)
64
- stream.once('end', done)
65
- stream.once('error', done)
66
- return stream
67
- })
68
- }
69
- }
70
- }
71
-
72
- function createWrapCreateWriteStream (config, tracer) {
73
- return function wrapCreateWriteStream (createWriteStream) {
74
- return function createWriteStreamWithTrace (path, options) {
75
- const tags = makeFSFlagTags('WriteStream', path, options, 'w', config, tracer)
76
- return tracer.trace('fs.operation', { tags, orphanable }, (span, done) => {
77
- const stream = createWriteStream.apply(this, arguments)
78
- stream.once('close', done)
79
- stream.once('finish', done)
80
- stream.once('error', done)
81
- return stream
82
- })
83
- }
84
- }
85
- }
86
-
87
- function createWrapExists (config, tracer) {
88
- return function wrapExists (exists) {
89
- const existsWithTrace = function existsWithTrace (path, cb) {
90
- if (typeof cb !== 'function') {
91
- return exists.apply(this, arguments)
92
- }
93
- const tags = makeFSTags('exists', path, null, config, tracer)
94
- return tracer.trace('fs.operation', { tags, orphanable }, (span, done) => {
95
- arguments[1] = function (result) {
96
- done()
97
- cb.apply(this, arguments)
98
- }
99
- return exists.apply(this, arguments)
100
- })
101
- }
102
-
103
- copySymbols(exists, existsWithTrace)
104
-
105
- return existsWithTrace
106
- }
107
- }
108
-
109
- function createWrapDirRead (config, tracer, sync) {
110
- const name = sync ? 'dir.readSync' : 'dir.read'
111
- return function wrapDirRead (read) {
112
- function options () {
113
- const tags = makeFSTags(name, this.path, null, config, tracer)
114
- return { tags, orphanable }
115
- }
116
- return tracer.wrap('fs.operation', options, read, true)
117
- }
118
- }
119
-
120
- function createWrapDirClose (config, tracer, sync) {
121
- const name = sync ? 'dir.closeSync' : 'dir.close'
122
- return function wrapDirClose (close) {
123
- function options () {
124
- const tags = makeFSTags(name, this.path, null, config, tracer)
125
- return { tags, orphanable }
126
- }
127
- return tracer.wrap('fs.operation', options, close, true)
128
- }
129
- }
130
-
131
- function createWrapDirAsyncIterator (config, tracer, instrumenter) {
132
- return function wrapDirAsyncIterator (asyncIterator) {
133
- return function asyncIteratorWithTrace () {
134
- if (!kDirReadPromisified) {
135
- const keys = Reflect.ownKeys(this)
136
- for (const key of keys) {
137
- if (kDirReadPromisified && kDirClosePromisified) break
138
- if (typeof key !== 'symbol') continue
139
- if (!kDirReadPromisified && getSymbolName(key).includes('kDirReadPromisified')) {
140
- kDirReadPromisified = key
141
- }
142
- if (!kDirClosePromisified && getSymbolName(key).includes('kDirClosePromisified')) {
143
- kDirClosePromisified = key
144
- }
145
- }
146
- }
147
- instrumenter.wrap(this, kDirReadPromisified, createWrapDirRead(config, tracer))
148
- instrumenter.wrap(this, kDirClosePromisified, createWrapKDirClose(config, tracer, instrumenter))
149
- return asyncIterator.apply(this, arguments)
150
- }
151
- }
152
- }
153
-
154
- function createWrapKDirClose (config, tracer, instrumenter) {
155
- return function wrapKDirClose (kDirClose) {
156
- return function kDirCloseWithTrace () {
157
- const tags = makeFSTags('dir.close', this.path, null, config, tracer)
158
- return tracer.trace('fs.operation', { tags, orphanable }, (span) => {
159
- const p = kDirClose.apply(this, arguments)
160
- const unwrapBoth = () => {
161
- instrumenter.unwrap(this, kDirReadPromisified)
162
- instrumenter.unwrap(this, kDirClosePromisified)
163
- }
164
- p.then(unwrapBoth, unwrapBoth)
165
- return p
166
- })
167
- }
168
- }
169
- }
170
-
171
- function createOpenTags (resourceName, config, tracer) {
172
- return function openTags (path, flag, mode) {
173
- if (!flag || typeof flag === 'function') {
174
- flag = null
175
- }
176
- return makeFSFlagTags(resourceName, path, { flag }, 'r', config, tracer)
177
- }
178
- }
179
-
180
- function createCloseTags (resourceName, config, tracer) {
181
- return function closeTags (fd) {
182
- if (typeof fd === 'undefined' && this && this[ddFhSym]) {
183
- fd = this[ddFhSym].fd
184
- }
185
- if (typeof fd !== 'number' || !Number.isInteger(fd)) {
186
- return
187
- }
188
- return makeFSTags(resourceName, fd, null, config, tracer)
189
- }
190
- }
191
-
192
- function createReadFileTags (resourceName, config, tracer) {
193
- return function readFileTags (path, options) {
194
- return makeFSFlagTags(resourceName, path, options, 'r', config, tracer)
195
- }
196
- }
197
-
198
- function createWriteFileTags (resourceName, config, tracer) {
199
- return function writeFileTags (path, data, options) {
200
- return makeFSFlagTags(resourceName, path, options, 'w', config, tracer)
201
- }
202
- }
203
-
204
- function createAppendFileTags (resourceName, config, tracer) {
205
- return function appendFileTags (path, data, options) {
206
- return makeFSFlagTags(resourceName, path, options, 'a', config, tracer)
207
- }
208
- }
209
-
210
- function createCopyFileTags (resourceName, config, tracer) {
211
- return function copyFileTags (src, dest, flag) {
212
- return makeFSTags(resourceName, { src, dest }, null, config, tracer)
213
- }
214
- }
215
-
216
- function createChmodTags (resourceName, config, tracer) {
217
- return function chmodTags (fd, mode) {
218
- const tags = makeFSTags(resourceName, fd, null, config, tracer)
219
- tags['file.mode'] = mode.toString(8)
220
- return tags
221
- }
222
- }
223
-
224
- function createFchmodTags (resourceName, config, tracer) {
225
- return function fchmodTags (fd, mode) {
226
- if (typeof this === 'object' && this !== null && this.fd) {
227
- mode = fd
228
- fd = this.fd
229
- }
230
-
231
- const tags = makeFSTags(resourceName, fd, null, config, tracer)
232
- if (mode) {
233
- tags['file.mode'] = mode.toString(8)
234
- }
235
- return tags
236
- }
237
- }
238
-
239
- function createPathTags (resourceName, config, tracer) {
240
- return function pathTags (path) {
241
- return makeFSTags(resourceName, path, null, config, tracer)
242
- }
243
- }
244
-
245
- function createFDTags (resourceName, config, tracer) {
246
- return function fdTags (fd) {
247
- if (typeof this === 'object' && this !== null && this.fd) {
248
- fd = this.fd
249
- }
250
- return makeFSTags(resourceName, fd, null, config, tracer)
251
- }
252
- }
253
-
254
- function createChownTags (resourceName, config, tracer) {
255
- return function chownTags (fd, uid, gid) {
256
- const tags = makeFSTags(resourceName, fd, null, config, tracer)
257
- if (typeof uid === 'number') {
258
- tags['file.uid'] = uid.toString()
259
- }
260
- if (typeof gid === 'number') {
261
- tags['file.gid'] = gid.toString()
262
- }
263
- return tags
264
- }
265
- }
266
-
267
- function createFchownTags (resourceName, config, tracer) {
268
- return function fchownTags (fd, uid, gid) {
269
- if (typeof this === 'object' && this !== null && this.fd) {
270
- gid = uid
271
- uid = fd
272
- fd = this.fd
273
- }
274
- const tags = makeFSTags(resourceName, fd, null, config, tracer)
275
- if (typeof uid === 'number') {
276
- tags['file.uid'] = uid.toString()
277
- }
278
- if (typeof gid === 'number') {
279
- tags['file.gid'] = gid.toString()
280
- }
281
- return tags
282
- }
283
- }
284
-
285
- function getSymbolName (sym) {
286
- return sym.description || sym.toString()
287
- }
288
-
289
- function hasParent () {
290
- const store = storage.getStore()
291
-
292
- return store && store.span && !store.noop
293
- }
294
-
295
- function createWrapCb (tracer, config, name, tagMaker) {
296
- const makeTags = tagMaker(name, config, tracer)
297
- return function wrapFunction (fn) {
298
- return tracer.wrap('fs.operation', function () {
299
- if (typeof arguments[arguments.length - 1] !== 'function') {
300
- return
301
- }
302
- const tags = makeTags.apply(this, arguments)
303
- return tags ? { tags, orphanable } : { orphanable }
304
- }, fn, true)
305
- }
306
- }
307
-
308
- function createWrap (tracer, config, name, tagMaker) {
309
- const makeTags = tagMaker(name, config, tracer)
310
-
311
- return function wrapSyncFunction (fn) {
312
- return tracer.wrap('fs.operation', function () {
313
- const tags = makeTags.apply(this, arguments)
314
- return tags ? { tags, orphanable } : { orphanable }
315
- }, fn, true)
316
- }
317
- }
318
-
319
- function makeFSFlagTags (resourceName, path, options, defaultFlag, config, tracer) {
320
- const tags = makeFSTags(resourceName, path, options, config, tracer)
321
-
322
- if (tags) {
323
- let flag = defaultFlag
324
- if (typeof options === 'object' && options !== null) {
325
- if (options.flag) {
326
- flag = options.flag
327
- } else if (options.flags) {
328
- flag = options.flags
329
- }
330
- }
331
- tags['file.flag'] = flag
332
- return tags
333
- }
334
- }
335
-
336
- function makeFSTags (resourceName, path, options, config, tracer) {
337
- path = options && typeof options === 'object' && 'fd' in options ? options.fd : path
338
- const tags = {
339
- 'component': 'fs',
340
- 'span.kind': 'internal',
341
- 'resource.name': resourceName,
342
- 'service.name': config.service || tracer._service
343
- }
344
-
345
- switch (typeof path) {
346
- case 'object': {
347
- if (path === null) return tags
348
- const src = 'src' in path ? path.src : null
349
- const dest = 'dest' in path ? path.dest : null
350
- if (src || dest) {
351
- tags['file.src'] = src
352
- tags['file.dest'] = dest
353
- } else {
354
- tags['file.path'] = path
355
- }
356
- break
357
- }
358
- case 'string': {
359
- tags['file.path'] = path
360
- break
361
- }
362
- case 'number': {
363
- tags['file.descriptor'] = path.toString()
364
- break
365
- }
366
- }
367
-
368
- return tags
369
- }
370
-
371
- function copySymbols (from, to) {
372
- const props = Object.getOwnPropertyDescriptors(from)
373
- const keys = Reflect.ownKeys(props)
374
-
375
- for (const key of keys) {
376
- if (typeof key !== 'symbol' || to.hasOwnProperty(key)) continue
377
-
378
- Object.defineProperty(to, key, props[key])
379
- }
380
- }
381
-
382
- function getFileHandlePrototype (fs) {
383
- return fs.promises.open(__filename, 'r')
384
- .then(fh => {
385
- if (!kHandle) {
386
- kHandle = Reflect.ownKeys(fh).find(key => typeof key === 'symbol' && key.toString().includes('kHandle'))
387
- }
388
- fh.close()
389
-
390
- return Object.getPrototypeOf(fh)
391
- })
392
- }
393
-
394
- function patchClassicFunctions (fs, tracer, config) {
395
- for (const name in fs) {
396
- if (!fs[name]) continue
397
- const tagMakerName = name.endsWith('Sync') ? name.substr(0, name.length - 4) : name
398
- const original = fs[name]
399
- if (tagMakerName in tagMakers) {
400
- const tagMaker = tagMakers[tagMakerName]
401
- if (name.endsWith('Sync')) {
402
- this.wrap(fs, name, createWrap(tracer, config, name, tagMaker))
403
- } else {
404
- this.wrap(fs, name, createWrapCb(tracer, config, name, tagMaker))
405
- }
406
- if (name in promisifiable) {
407
- copySymbols(original, fs[name])
408
- }
409
- }
410
- }
411
- }
412
-
413
- function patchFileHandle (fs, tracer, config) {
414
- getFileHandlePrototype(fs).then((fileHandlePrototype) => {
415
- for (const name of Reflect.ownKeys(fileHandlePrototype)) {
416
- if (typeof name !== 'string' || name === 'constructor' || name === 'fd' || name === 'getAsyncId') {
417
- continue
418
- }
419
- let tagMaker
420
- const fName = 'f' + name
421
- if (fName in tagMakers) {
422
- tagMaker = tagMakers[fName]
423
- } else {
424
- tagMaker = createFDTags
425
- }
426
-
427
- const instrumenter = this
428
-
429
- const desc = Reflect.getOwnPropertyDescriptor(fileHandlePrototype, kHandle)
430
- if (!desc || !desc.get) {
431
- Reflect.defineProperty(fileHandlePrototype, kHandle, {
432
- get () {
433
- return this[ddFhSym]
434
- },
435
- set (h) {
436
- this[ddFhSym] = h
437
- instrumenter.wrap(this, 'close', createWrap(tracer, config, 'filehandle.close', tagMakers.close))
438
- },
439
- configurable: true
440
- })
441
- }
442
-
443
- this.wrap(fileHandlePrototype, name, createWrap(tracer, config, 'filehandle.' + name, tagMaker))
444
- }
445
- })
446
- }
447
-
448
- function patchPromiseFunctions (fs, tracer, config) {
449
- for (const name in fs.promises) {
450
- if (name in tagMakers) {
451
- const tagMaker = tagMakers[name]
452
- this.wrap(fs.promises, name, createWrap(tracer, config, 'promises.' + name, tagMaker))
453
- }
454
- }
455
- }
456
-
457
- function patchDirFunctions (fs, tracer, config) {
458
- this.wrap(fs.Dir.prototype, 'close', createWrapDirClose(config, tracer))
459
- this.wrap(fs.Dir.prototype, 'closeSync', createWrapDirClose(config, tracer, true))
460
- this.wrap(fs.Dir.prototype, 'read', createWrapDirRead(config, tracer))
461
- this.wrap(fs.Dir.prototype, 'readSync', createWrapDirRead(config, tracer, true))
462
- this.wrap(fs.Dir.prototype, Symbol.asyncIterator, createWrapDirAsyncIterator(config, tracer, this))
463
- }
464
-
465
- function unpatchClassicFunctions (fs) {
466
- for (const name in fs) {
467
- if (!fs[name]) continue
468
- const tagMakerName = name.endsWith('Sync') ? name.substr(0, name.length - 4) : name
469
- if (tagMakerName in tagMakers) {
470
- this.unwrap(fs, name)
471
- }
472
- }
473
- }
474
-
475
- function unpatchFileHandle (fs) {
476
- getFileHandlePrototype(fs).then(fileHandlePrototype => {
477
- for (const name of Reflect.ownKeys(fileHandlePrototype)) {
478
- if (typeof name !== 'string' || name === 'constructor' || name === 'fd' || name === 'getAsyncId') {
479
- continue
480
- }
481
- this.unwrap(fileHandlePrototype, name)
482
- }
483
- delete fileHandlePrototype[kHandle]
484
- })
485
- }
486
-
487
- function unpatchPromiseFunctions (fs) {
488
- for (const name in fs.promises) {
489
- if (name in tagMakers) {
490
- this.unwrap(fs.promises, name)
491
- }
492
- }
493
- }
494
-
495
- function unpatchDirFunctions (fs) {
496
- this.unwrap(fs.Dir.prototype, 'close')
497
- this.unwrap(fs.Dir.prototype, 'closeSync')
498
- this.unwrap(fs.Dir.prototype, 'read')
499
- this.unwrap(fs.Dir.prototype, 'readSync')
500
- this.unwrap(fs.Dir.prototype, Symbol.asyncIterator)
501
- }
502
-
503
- module.exports = {
504
- name: 'fs',
505
- patch (fs, tracer, config) {
506
- const realpathNative = fs.realpath.native
507
- const realpathSyncNative = fs.realpathSync.native
508
- patchClassicFunctions.call(this, fs, tracer, config)
509
- if (fs.promises) {
510
- patchFileHandle.call(this, fs, tracer, config)
511
- patchPromiseFunctions.call(this, fs, tracer, config)
512
- }
513
- if (fs.Dir) {
514
- patchDirFunctions.call(this, fs, tracer, config)
515
- }
516
- this.wrap(fs, 'createReadStream', createWrapCreateReadStream(config, tracer))
517
- this.wrap(fs, 'createWriteStream', createWrapCreateWriteStream(config, tracer))
518
- this.wrap(fs, 'existsSync', createWrap(tracer, config, 'existsSync', createPathTags))
519
- this.wrap(fs, 'exists', createWrapExists(config, tracer))
520
- if (realpathNative) {
521
- fs.realpath.native = createWrapCb(tracer, config, 'realpath.native', createPathTags)(realpathNative)
522
- }
523
- if (realpathSyncNative) {
524
- fs.realpathSync.native = createWrap(tracer, config, 'realpath.native', createPathTags)(realpathSyncNative)
525
- }
526
- },
527
- unpatch (fs) {
528
- unpatchClassicFunctions.call(this, fs)
529
- if (fs.promises) {
530
- unpatchFileHandle.call(this, fs)
531
- unpatchPromiseFunctions.call(this, fs)
532
- }
533
- if (fs.Dir) {
534
- unpatchDirFunctions.call(this, fs)
535
- }
536
- this.unwrap(fs, 'createReadStream')
537
- this.unwrap(fs, 'createWriteStream')
538
- this.unwrap(fs, 'existsSync')
539
- this.unwrap(fs, 'exists')
540
- }
541
- }
542
-
543
- /** TODO fs functions:
544
-
545
- unwatchFile
546
- watch
547
- watchFile
548
- */