forked from newrelic/node-newrelic
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
chore: Added instrumentation tracking to support issue 2033
- Loading branch information
1 parent
f4586d7
commit c7e3602
Showing
5 changed files
with
606 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,186 @@ | ||
/* | ||
* Copyright 2024 New Relic Corporation. All rights reserved. | ||
* SPDX-License-Identifier: Apache-2.0 | ||
*/ | ||
|
||
'use strict' | ||
|
||
const IdGen = require('./util/idgen') | ||
const idGen = new IdGen() | ||
|
||
/** | ||
* @typedef {function} InstrumentationOnRequire | ||
* @param {Shim} shim The shim instance to use for the instrumentation. | ||
* @param {object} resolvedNodule The module being instrumented as returned by | ||
* Node's `require` function. | ||
* @param {string} moduleName The simple name of the module, i.e. the value | ||
* passed to the `require` function. | ||
* @throws {Error|object} | ||
*/ | ||
|
||
/** | ||
* @typedef {function} InstrumentationOnError | ||
* @param {Error|object} error The error thrown by `onRequire` when there was | ||
* an issue registering the instrumentation. | ||
*/ | ||
|
||
/* eslint-disable jsdoc/require-property-description */ | ||
/** | ||
* @typedef {object} InstrumentationDescriptorParams | ||
* @property {string} absolutePath | ||
* @property {string} module | ||
* @property {string} moduleName | ||
* @property {InstrumentationOnError} onError | ||
* @property {InstrumentationOnRequire} onRequire | ||
* @property {string} resolvedName | ||
* @property {string} type | ||
*/ | ||
|
||
/** | ||
* Describes the configuration for an instrumentation. An instrumentation | ||
* is what `newrelic` uses to wrap Node.js modules. In particular, a description | ||
* details the name of the module, the path on disk to the module, and the | ||
* hooks (`onRequire` and `onError`) to apply to the module. | ||
*/ | ||
class InstrumentationDescriptor { | ||
/** | ||
* Utility/generic module. | ||
* @type {string} | ||
*/ | ||
static TYPE_GENERIC = 'generic' | ||
|
||
/** | ||
* @private | ||
* @type {string} | ||
*/ | ||
static TYPE_CONGLOMERATE = 'conglomerate' | ||
|
||
/** | ||
* Database module, such as the MongoDB or MySQL drivers. | ||
* @type {string} | ||
*/ | ||
static TYPE_DATASTORE = 'datastore' | ||
|
||
/** | ||
* Messaging module, such as AMQP. | ||
* @type {string} | ||
*/ | ||
static TYPE_MESSAGE = 'message' | ||
|
||
/** | ||
* Promise module, such as Bluebird. | ||
* @type {string} | ||
*/ | ||
static TYPE_PROMISE = 'promise' | ||
|
||
/** | ||
* @private | ||
* @type {string} | ||
*/ | ||
static TYPE_TRANSACTION = 'transaction' | ||
|
||
/** | ||
* Web server framework module, such as Express or Fastify. | ||
* @type {string} | ||
*/ | ||
static TYPE_WEB_FRAMEWORK = 'web-framework' | ||
|
||
/** | ||
* Used to load supportability metrics on installed versions of packages | ||
* that the Node.js agent does not instrument (e.g. OTEL instrumentation or | ||
* top logging libraries). | ||
* @type {string} | ||
*/ | ||
static TYPE_TRACKING = 'tracking' | ||
|
||
/** | ||
* The type of the module being instrumented. See the static `TYPE_` fields. | ||
* @type {string|null} | ||
*/ | ||
type | ||
|
||
/** | ||
* The name of the module being instrumented, i.e. the string used to require | ||
* the module. This must map to a directory in `lib/instrumentations` which | ||
* contains an `nr-hooks.js` file. | ||
* | ||
* This takes precedence over `moduleName`. | ||
* @type {string} | ||
*/ | ||
module | ||
|
||
/** | ||
* The name of the module being instrumented, i.e. the string used to require | ||
* the module. This must map to a JavaScript file of the same name in the | ||
* `lib/instrumentations` directory. | ||
* @type {string} | ||
*/ | ||
moduleName | ||
|
||
/** | ||
* The absolute path to the module to instrument. This should only be set | ||
* when the module being instrumented does not reside in a `node_modules` | ||
* directory; for example, when someone is instrumenting a module of their | ||
* own through the public API. | ||
* | ||
* The `moduleName` property still needs to be set to the simple name, i.e. | ||
* the string passed to `require`, for instrumentation tracking purposes. | ||
* | ||
* Note: this value takes precedence over `moduleName`. | ||
*/ | ||
absolutePath | ||
|
||
/** | ||
* The fully resolved path to the module, e.g. `/opt/app/node_modules/foo`. | ||
* If the module is a core module, the special value `.` should be used. | ||
* @type {string} | ||
*/ | ||
resolvedName | ||
|
||
/** | ||
* Hook to invoke when the module is required. This is the actual | ||
* implementation of the instrumentation. | ||
* @type {InstrumentationOnRequire} | ||
*/ | ||
onRequire | ||
|
||
/** | ||
* Hook to invoke when the `onRequire` hook throws an error. | ||
* @type {InstrumentationOnError} | ||
*/ | ||
onError | ||
|
||
/** | ||
* @type {number} | ||
*/ | ||
#id | ||
|
||
/* eslint-disable jsdoc/require-param-description */ | ||
/** | ||
* @param {InstrumentationDescriptorParams} params | ||
*/ | ||
constructor(params) { | ||
this.absolutePath = params.absolutePath | ||
this.module = params.module | ||
this.moduleName = params.moduleName | ||
this.onError = params.onError | ||
this.onRequire = params.onRequire | ||
this.resolvedName = params.resolvedName | ||
this.type = params.type | ||
|
||
this.#id = idGen.idFor(this.moduleName) | ||
} | ||
|
||
/** | ||
* Identifier for the instrumentation. Used by the internal instrumentation | ||
* tracker to distinguish between different instrumentations targeting the | ||
* same module. | ||
* | ||
* @returns {number} The identifier. | ||
*/ | ||
get instrumentationId() { | ||
return this.#id | ||
} | ||
} | ||
|
||
module.exports = InstrumentationDescriptor |
Oops, something went wrong.