77// eslint-disable-next-line n/no-unsupported-features/node-builtins
88const { tracingChannel } = require ( 'node:diagnostics_channel' )
99const cat = require ( '#agentlib/util/cat.js' )
10+ const recordSupportabilityMetric = require ( './record-supportability-metric.js' )
11+
1012// Used for the `traceCallback` work.
1113// This can be removed when we add true support into orchestrion
1214const makeCall = ( fn ) => ( ...args ) => fn . call ( ...args )
@@ -28,38 +30,45 @@ const ArrayPrototypeSplice = makeCall(Array.prototype.splice)
2830
2931/**
3032 * @property {object } agent A New Relic Node.js agent instance.
31- * @property {object } logger An agent logger instance.
33+ * @property {TracingChannel } channel The tracing channel instance this subscriber will be monitoring.
34+ * @property {string } channelName A unique name for the diagnostics channel
35+ * that will be registered.
3236 * @property {object } config The agent configuration object.
37+ * @property {string } id A unique identifier for the subscriber, combining the prefix, package
38+ * name, and channel name.
39+ * @property {object } logger An agent logger instance.
3340 * @property {string } packageName The name of the module being instrumented.
3441 * This is the same string one would pass to the `require` function.
35- * @property {string } channelName A unique name for the diagnostics channel
36- * that will be registered.
42+ * @property {AsyncLocalStorage } store The async local storage instance used for context management.
43+ * @property {number } [callback=null] Position of callback if it needs to be wrapped for instrumentation.
44+ * -1 means last argument.
3745 * @property {string[] } [events=[]] Set of tracing channel event names to
3846 * register handlers for. For any name in the set, a corresponding method
3947 * must exist on the subscriber instance. The method will be passed the
4048 * event object. Possible event names are `start`, `end`, `asyncStart`,
4149 * `asyncEnd`, and `error`.
42- *
43- * See {@link https://nodejs.org/api/diagnostics_channel.html#class-tracingchannel}
44- * @property {boolean } [opaque=false] If true, any children segments will not be created.
50+ * See {@link https://nodejs.org/api/diagnostics_channel.html#class-tracingchannel}
4551 * @property {boolean } [internal=false] If true, any children segments from the same library
4652 * will not be created.
53+ * @property {boolean } [opaque=false] If true, any children segments will not be created.
4754 * @property {string } [prefix='orchestrion:'] String to prepend to diagnostics
4855 * channel event names. This provides a namespace for the events we are
4956 * injecting into a module.
50- * @property {boolean } [requireActiveTx=true] If true, the subscriber will only handle events
51- * when there is an active transaction.
5257 * @property {boolean } [propagateContext=false] If true, it will bind `asyncStart` to the store
5358 * and re-propagate the active context. It will also attach the `transaction` to the event in
5459 * `start.bindStore`. This is used for functions that queue async code and context is lost.
55- * @property {string } id A unique identifier for the subscriber, combining the prefix, package
56- * name, and channel name.
57- * @property {TracingChannel } channel The tracing channel instance this subscriber will be monitoring.
58- * @property {AsyncLocalStorage } store The async local storage instance used for context management.
59- * @property {number } [callback=null] Position of callback if it needs to be wrapped for instrumentation.
60- * -1 means last argument.
60+ * @property {boolean } [requireActiveTx=true] If true, the subscriber will only handle events
61+ * when there is an active transaction.
62+ * @property {object } [targetModuleMeta] Defines the target module's name and
63+ * version string, i.e. is an object `{ name, version }`. This is only necessary
64+ * when target instrumentation can surface an unexpected name for the
65+ * `packageName` property. For example, `express` uses multiple modules to
66+ * compose its core functionality. We want to track things under the `express`
67+ * name, but `packageName` will be set to `router` is most cases.
6168 */
6269class Subscriber {
70+ #usageMetricRecorded = false
71+
6372 /**
6473 * @param {SubscriberParams } params the subscriber constructor params
6574 */
@@ -234,6 +243,15 @@ class Subscriber {
234243 * @returns {Context } The context after processing the event
235244 */
236245 const handler = ( data ) => {
246+ if ( this . #usageMetricRecorded === false ) {
247+ recordSupportabilityMetric ( {
248+ agent : this . agent ,
249+ moduleName : this . packageName ,
250+ moduleVersion : data . moduleVersion
251+ } )
252+ this . #usageMetricRecorded = true
253+ }
254+
237255 // only wrap the callback if a subscriber has a callback property defined
238256 if ( this . callback !== null ) {
239257 this . traceCallback ( this . callback , data )
0 commit comments