newrelic
Version:
New Relic agent
124 lines (114 loc) • 3.77 kB
JavaScript
/*
* Copyright 2021 New Relic Corporation. All rights reserved.
* SPDX-License-Identifier: Apache-2.0
*/
const { MiddlewareSpec } = require('../../shim/specs')
/**
* Retrieves the IncomingMessage from a Fastify request. Depending on the
* context of this function it either exists on `request.raw` or just `request`
*
* @param {WebFrameworkShim} shim
* @param {Function} fn middleware function executing
* @param {string} fnName name of middleware executing
* @param {args} args that are passed to middleware
* @returns {IncomingMessage}
*/
const getRequestFromFastify = (shim, fn, fnName, args) => {
const [request] = args
// request is Fastify request
// object, get IncomingMessage from .raw
if (request && request.raw) {
return request.raw
}
return request
}
/**
* Retrieves the params from the Fastify request.
*
* @param {WebFrameworkShim} shim
* @param {Function} fn middleware function executing
* @param {string} fnName name of middleware executing
* @param {args} args that are passed to middleware
* @returns {object} URL params on a Fastify request
*/
const getParamsFromFastifyRequest = (shim, fn, fnName, args) => {
const [req] = args
return req && req.params
}
/**
* Builds the recordMiddleware Spec for the route handler
*
* A spec is basically a specification -- or a list
* of instructions to the recordMiddleware function
* that provide it with the information it needs to
* do its job. You could also think of it as a
* mini-DSL
*
* @param {WebFrameworkShim} shim
* @param {string} path URL route being executed
* @returns {object} spec for Fastify route handler
*/
function buildMiddlewareSpecForRouteHandler(shim, path) {
return new MiddlewareSpec({
/**
* A function where we can wrap next, reply send, etc. methods
*
* This one is tricky. The `next` function will, same as
* the `req` function above, receives the fn, fnName,
* and args from the handler function. It _also_ receives
* a `wrap` function. This wrap function will allow us to
* to bind a segment for any next function/method, or any
* method that would finish the request handling (i.e.
* `reply`, `respond`, etc.)
*
* This is far more useful when instrumenting actual middleware vs.
* instrumenting a simple route handler. However, if the route
* handling API uses a method call for responding (vs. returning a value)
* then this method is required/useful again.
*
* The isFinal param determines whether or not a path is appended for
* this particular piece of middleware. (i.e. if this is the final handler
* that is actually handling the request, the path is actually left on)
*
* @param shim
* @param fn
* @param fnName
* @param args
* @param bindSegment
*/
next: function wrapNext(shim, fn, fnName, args, bindSegment) {
const reply = args[1]
if (!shim.isFunction(reply)) {
return
}
const isFinal = true
bindSegment(reply, 'send', isFinal)
},
params: getParamsFromFastifyRequest,
req: getRequestFromFastify,
route: path
})
}
/**
* Spec for all Fastify middleware(excluding route handlers)
*
* @param {WebFrameworkShim} shim
* @param {string} name metric name for middleware being executed
* @param route
* @returns {object} spec for Fastify middleware
*/
function buildMiddlewareSpecForMiddlewareFunction(shim, name, route) {
return new MiddlewareSpec({
name,
route,
next: shim.LAST,
params: getParamsFromFastifyRequest,
req: getRequestFromFastify,
type: shim.MIDDLEWARE
})
}
module.exports = {
buildMiddlewareSpecForRouteHandler,
buildMiddlewareSpecForMiddlewareFunction
}