Skip to content

Commit

Permalink
feat: Added instrumentation for fetch. (#1776)
Browse files Browse the repository at this point in the history
  • Loading branch information
bizob2828 committed Sep 7, 2023
1 parent 683b254 commit 980b4dc
Show file tree
Hide file tree
Showing 12 changed files with 3,256 additions and 3,752 deletions.
2 changes: 1 addition & 1 deletion THIRD_PARTY_NOTICES.md
Expand Up @@ -2218,7 +2218,7 @@ THE SOFTWARE.

### c8

This product includes source derived from [c8](https://github.com/bcoe/c8) ([v7.14.0](https://github.com/bcoe/c8/tree/v7.14.0)), distributed under the [ISC License](https://github.com/bcoe/c8/blob/v7.14.0/LICENSE.txt):
This product includes source derived from [c8](https://github.com/bcoe/c8) ([v8.0.1](https://github.com/bcoe/c8/tree/v8.0.1)), distributed under the [ISC License](https://github.com/bcoe/c8/blob/v8.0.1/LICENSE.txt):

```
Copyright (c) 2017, Contributors
Expand Down
40 changes: 27 additions & 13 deletions lib/instrumentation/undici.js
Expand Up @@ -14,25 +14,36 @@ const symbols = require('../symbols')
const { executionAsyncResource } = require('async_hooks')
const diagnosticsChannel = require('diagnostics_channel')

module.exports = function addUndiciChannels(agent, _undici, _modName, shim) {
registerHookPoints(shim)
}
const channels = [
{ channel: diagnosticsChannel.channel('undici:request:create'), hook: requestCreateHook },
{ channel: diagnosticsChannel.channel('undici:request:headers'), hook: requestHeadersHook },
{ channel: diagnosticsChannel.channel('undici:request:trailers'), hook: endAndRestoreSegment },
{ channel: diagnosticsChannel.channel('undici:request:error'), hook: endAndRestoreSegment }
]

/**
* Subscribes to all relevant undici hook points
* See: https://github.com/nodejs/undici/blob/main/docs/api/DiagnosticsChannel.md
*
* @param {Shim} shim instance of shim
* @param agent
* @param _undici
* @param _modName
* @param shim
*/
function registerHookPoints(shim) {
const requestCreate = diagnosticsChannel.channel('undici:request:create')
requestCreate.subscribe(requestCreateHook.bind(null, shim))
const requestHeaders = diagnosticsChannel.channel('undici:request:headers')
requestHeaders.subscribe(requestHeadersHook.bind(null, shim))
const requestTrailers = diagnosticsChannel.channel('undici:request:trailers')
requestTrailers.subscribe(endAndRestoreSegment.bind(null, shim))
const requestError = diagnosticsChannel.channel('undici:request:error')
requestError.subscribe(endAndRestoreSegment.bind(null, shim))
module.exports = function addUndiciChannels(agent, _undici, _modName, shim) {
channels.forEach(({ channel, hook }) => {
if (!channel.hasSubscribers) {
channel.subscribe(hook.bind(null, shim))
}
})
}

module.exports.unsubscribe = function unsubscribe() {
channels.forEach(({ channel, hook }) => {
if (channel.hasSubscribers) {
channel.unsubscribe(hook)
}
})
}

/**
Expand Down Expand Up @@ -107,6 +118,9 @@ function addDTHeaders({ transaction, config, request }) {
function createExternalSegment({ shim, request, parentSegment }) {
const url = new URL(request.origin + request.path)
const name = NAMES.EXTERNAL.PREFIX + url.host + url.pathname
// Metrics for `External/<host>` will have a suffix of undici
// We will have to see if this matters for people only using fetch
// It's undici under the hood so ¯\_(ツ)_/¯
const segment = shim.createSegment(name, recordExternal(url.host, 'undici'), parentSegment)
if (segment) {
segment.start()
Expand Down
1 change: 0 additions & 1 deletion lib/instrumentations.js
Expand Up @@ -36,7 +36,6 @@ module.exports = function instrumentations() {
'@redis/client': { type: MODULE_TYPE.DATASTORE },
'restify': { type: MODULE_TYPE.WEB_FRAMEWORK },
'superagent': { module: '@newrelic/superagent' },
'undici': { type: MODULE_TYPE.TRANSACTION },
'@hapi/vision': { type: MODULE_TYPE.WEB_FRAMEWORK },
'when': { module: './instrumentation/when' },
'winston': { type: MODULE_TYPE.GENERIC },
Expand Down
8 changes: 8 additions & 0 deletions lib/shimmer.js
Expand Up @@ -18,6 +18,7 @@ let pkgsToHook = []

const NAMES = require('./metrics/names')
const symbols = require('./symbols')
const { unsubscribe } = require('./instrumentation/undici')

const MODULE_TYPE = shims.constants.MODULE_TYPE

Expand Down Expand Up @@ -328,6 +329,12 @@ const shimmer = (module.exports = {
const globalsFilepath = path.join(__dirname, 'instrumentation', 'core', 'globals.js')
_firstPartyInstrumentation(agent, globalsFilepath, globalShim, global, 'globals')

// Since this just registers subscriptions to diagnostics_channel events from undici
// We register this as core and it'll work for both fetch and undici
const undiciPath = path.join(__dirname, 'instrumentation', 'undici.js')
const undiciShim = shims.createShimFromType(MODULE_TYPE.TRANSACTION, agent, 'undici', 'undici')
_firstPartyInstrumentation(agent, undiciPath, undiciShim)

// Instrument each of the core modules.
for (const [mojule, core] of Object.entries(CORE_INSTRUMENTATION)) {
const filePath = path.join(__dirname, 'instrumentation', 'core', core.file)
Expand Down Expand Up @@ -364,6 +371,7 @@ const shimmer = (module.exports = {
}

pkgsToHook = []
unsubscribe()
},

bootstrapInstrumentation: function bootstrapInstrumentation(agent) {
Expand Down

0 comments on commit 980b4dc

Please sign in to comment.