forked from newrelic/node-newrelic
-
Notifications
You must be signed in to change notification settings - Fork 0
/
instrumentation-descriptor.js
215 lines (186 loc) · 5.83 KB
/
instrumentation-descriptor.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
/*
* 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 {string} shimName
* @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
/**
* Used when instrumenting a module to determine if a module has already
* been wrapped by a specific shim instance. It is used in conjunction with
* the `shim.id` value.
* @type {string}
*/
shimName
/**
* 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.shimName = params.shimName
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
// This export is for backward compatibility in the public API. The
// public API object simply re-exports this object that was originally
// in a `constants.js` file prior to the creation of the
// `InstrumentationDescriptor`.
module.exports.TYPES = {
GENERIC: InstrumentationDescriptor.TYPE_GENERIC,
DATASTORE: InstrumentationDescriptor.TYPE_DATASTORE,
MESSAGE: InstrumentationDescriptor.TYPE_MESSAGE,
PROMISE: InstrumentationDescriptor.TYPE_PROMISE,
WEB_FRAMEWORK: InstrumentationDescriptor.TYPE_WEB_FRAMEWORK,
TRACKING: InstrumentationDescriptor.TYPE_TRACKING,
/** @private */
CONGLOMERATE: InstrumentationDescriptor.TYPE_CONGLOMERATE,
/** @private */
TRANSACTION: InstrumentationDescriptor.TYPE_TRANSACTION
}