Skip to content

Commit e66380a

Browse files
rochdevnsavoire
authored andcommitted
add support for global fetch (#3258)
1 parent 212fe3f commit e66380a

File tree

10 files changed

+864
-11
lines changed

10 files changed

+864
-11
lines changed

.github/workflows/plugins.yml

+18-1
Original file line numberDiff line numberDiff line change
@@ -350,6 +350,23 @@ jobs:
350350
uses: ./.github/actions/testagent/logs
351351
- uses: codecov/codecov-action@v2
352352

353+
fetch:
354+
runs-on: ubuntu-latest
355+
env:
356+
PLUGINS: fetch
357+
steps:
358+
- uses: actions/checkout@v2
359+
- uses: ./.github/actions/testagent/start
360+
- uses: ./.github/actions/node/setup
361+
- run: yarn install
362+
- uses: ./.github/actions/node/oldest
363+
- run: yarn test:plugins:ci
364+
- uses: ./.github/actions/node/latest
365+
- run: yarn test:plugins:ci
366+
- if: always()
367+
uses: ./.github/actions/testagent/logs
368+
- uses: codecov/codecov-action@v2
369+
353370
generic-pool:
354371
runs-on: ubuntu-latest
355372
env:
@@ -829,7 +846,7 @@ jobs:
829846
- 5500:5500
830847
testagent:
831848
image: ghcr.io/datadog/dd-apm-test-agent/ddapm-test-agent:latest
832-
env:
849+
env:
833850
LOG_LEVEL: DEBUG
834851
TRACE_LANGUAGE: javascript
835852
DISABLED_CHECKS: trace_content_length

docs/API.md

+5
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ tracer.use("pg", {
4040
<h5 id="generic-pool"></h5>
4141
<h5 id="google-cloud-pubsub"></h5>
4242
<h5 id="fastify"></h5>
43+
<h5 id="fetch"></h5>
4344
<h5 id="fs"></h5>
4445
<h5 id="graphql"></h5>
4546
<h5 id="graphql-tags"></h5>
@@ -111,7 +112,11 @@ tracer.use("pg", {
111112
* [elasticsearch](./interfaces/plugins.elasticsearch.html)
112113
* [express](./interfaces/plugins.express.html)
113114
* [fastify](./interfaces/plugins.fastify.html)
115+
<<<<<<< HEAD
114116
- [fs](./interfaces/plugins.fs.html)
117+
=======
118+
* [fetch](./interfaces/plugins.fetch.html)
119+
>>>>>>> a9f082345 (add support for global fetch (#3258))
115120
* [generic-pool](./interfaces/plugins.generic_pool.html)
116121
* [google-cloud-pubsub](./interfaces/plugins.google_cloud_pubsub.html)
117122
* [graphql](./interfaces/plugins.graphql.html)

docs/test.ts

+2
Original file line numberDiff line numberDiff line change
@@ -248,6 +248,8 @@ tracer.use('express');
248248
tracer.use('express', httpServerOptions);
249249
tracer.use('fastify');
250250
tracer.use('fastify', httpServerOptions);
251+
tracer.use('fetch');
252+
tracer.use('fetch', httpClientOptions);
251253
tracer.use('fs');
252254
tracer.use('generic-pool');
253255
tracer.use('google-cloud-pubsub');

index.d.ts

+7
Original file line numberDiff line numberDiff line change
@@ -759,6 +759,7 @@ interface Plugins {
759759
"elasticsearch": plugins.elasticsearch;
760760
"express": plugins.express;
761761
"fastify": plugins.fastify;
762+
"fetch": plugins.fetch;
762763
"fs": plugins.fs;
763764
"generic-pool": plugins.generic_pool;
764765
"google-cloud-pubsub": plugins.google_cloud_pubsub;
@@ -1103,6 +1104,12 @@ declare namespace plugins {
11031104
*/
11041105
interface fastify extends HttpServer {}
11051106

1107+
/**
1108+
* This plugin automatically instruments the
1109+
* [fetch](https://nodejs.org/api/globals.html#fetch) global.
1110+
*/
1111+
interface fetch extends HttpClient {}
1112+
11061113
/**
11071114
* This plugin automatically instruments the
11081115
* [fs](https://nodejs.org/api/fs.html) module.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
'use strict'
2+
3+
const shimmer = require('../../datadog-shimmer')
4+
const { channel } = require('./helpers/instrument')
5+
6+
const startChannel = channel('apm:fetch:request:start')
7+
const finishChannel = channel('apm:fetch:request:finish')
8+
const errorChannel = channel('apm:fetch:request:error')
9+
10+
function wrapFetch (fetch, Request) {
11+
if (typeof fetch !== 'function') return fetch
12+
13+
return function (input, init) {
14+
if (!startChannel.hasSubscribers) return fetch.apply(this, arguments)
15+
16+
const req = new Request(input, init)
17+
const headers = req.headers
18+
const message = { req, headers }
19+
20+
startChannel.publish(message)
21+
22+
// Request object is read-only so we need new objects to change headers.
23+
arguments[0] = message.req
24+
arguments[1] = { headers: message.headers }
25+
26+
return fetch.apply(this, arguments)
27+
.then(
28+
res => {
29+
finishChannel.publish({ req, res })
30+
31+
return res
32+
},
33+
err => {
34+
if (err.name !== 'AbortError') {
35+
errorChannel.publish(err)
36+
}
37+
38+
finishChannel.publish({ req })
39+
40+
throw err
41+
}
42+
)
43+
}
44+
}
45+
46+
if (globalThis.fetch) {
47+
globalThis.fetch = shimmer.wrap(fetch, wrapFetch(fetch, globalThis.Request))
48+
}

packages/datadog-instrumentations/src/helpers/register.js

+3
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,9 @@ const disabledInstrumentations = new Set(
1919

2020
const loadChannel = channel('dd-trace:instrumentation:load')
2121

22+
// Globals
23+
require('../fetch')
24+
2225
// TODO: make this more efficient
2326

2427
for (const packageName of names) {
+36
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
'use strict'
2+
3+
const HttpClientPlugin = require('../../datadog-plugin-http/src/client')
4+
const { HTTP_HEADERS } = require('../../../ext/formats')
5+
6+
class FetchPlugin extends HttpClientPlugin {
7+
static get id () { return 'fetch' }
8+
9+
addTraceSub (eventName, handler) {
10+
this.addSub(`apm:${this.constructor.id}:${this.operation}:${eventName}`, handler)
11+
}
12+
13+
start (message) {
14+
const req = message.req
15+
const options = new URL(req.url)
16+
const headers = options.headers = Object.fromEntries(req.headers.entries())
17+
18+
const args = { options }
19+
20+
super.start({ args })
21+
22+
message.req = new globalThis.Request(req, { headers })
23+
}
24+
25+
_inject (span, headers) {
26+
const carrier = {}
27+
28+
this.tracer.inject(span, HTTP_HEADERS, carrier)
29+
30+
for (const name in carrier) {
31+
headers.append(name, carrier[name])
32+
}
33+
}
34+
}
35+
36+
module.exports = FetchPlugin

0 commit comments

Comments
 (0)