Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: Fixed instrumenting the same module installed in different locations #2104

Merged
merged 6 commits into from
Apr 3, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion api.js
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@
const LlmFeedbackMessage = require('./lib/llm-events/feedback-message')

const ATTR_DEST = require('./lib/config/attribute-filter').DESTINATIONS
const MODULE_TYPE = require('./lib/shim/constants').MODULE_TYPE
const MODULE_TYPE = require('./lib/instrumentation-descriptor').TYPES
const NAMES = require('./lib/metrics/names')
const obfuscate = require('./lib/util/sql/obfuscate')
const { DESTINATIONS } = require('./lib/config/attribute-filter')
Expand Down Expand Up @@ -1548,7 +1548,7 @@
* @param {string} params.traceId Identifier for the feedback event.
* Obtained from {@link getTraceMetadata}.
* @param {string} params.category A tag for the event.
* @param {string} params.rating A indicator of how useful the message was.

Check warning on line 1551 in api.js

View workflow job for this annotation

GitHub Actions / lint (lts/*)

The type 'getTraceMetadata' is undefined
* @param {string} [params.message] The message that triggered the event.
* @param {object} [params.metadata] Additional key-value pairs to associate
* with the recorded event.
Expand Down
26 changes: 0 additions & 26 deletions jsdoc-conf.json

This file was deleted.

38 changes: 38 additions & 0 deletions jsdoc-conf.jsonc
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
{
"opts": {
"destination": "out/",
"readme": "./README.md",
"template": "./node_modules/clean-jsdoc-theme",
"theme_opts": {
"search": false,
"shouldRemoveScrollbarStyle": true
},
"tutorials": "examples/shim",
"recurse": true
},
"source": {
"exclude": ["node_modules", "test"],
"includePattern": ".+\\.js(doc)?$",
// Note: we cannot add patterns to the "include" strings. They must be
jsumners-nr marked this conversation as resolved.
Show resolved Hide resolved
// explicit strings that point to either specific files or directories.
// Recursion is enabled for the `jsdoc` command, thus any directories
// specified here will be processed recursively. So make sure any files in
// these directories should be included in our public docs.
"include": [
"lib/shim/",
"lib/transaction/handle.js",
"lib/instrumentation-descriptor.js"
]
},
"plugins": [
"plugins/markdown"
],
"templates": {
"cleverLinks": true,
"showInheritedInNav": false
},
"markdown": {
"hardwrap": false,
"idInHeadings": true
}
}
29 changes: 29 additions & 0 deletions lib/instrumentation-descriptor.js
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ const idGen = new IdGen()
* @property {string} absolutePath
* @property {string} module
* @property {string} moduleName
* @property {string} shimName
* @property {InstrumentationOnError} onError
* @property {InstrumentationOnRequire} onRequire
* @property {string} resolvedName
Expand Down Expand Up @@ -117,6 +118,14 @@ class InstrumentationDescriptor {
*/
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`
Expand Down Expand Up @@ -163,6 +172,7 @@ class InstrumentationDescriptor {
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
Expand All @@ -184,3 +194,22 @@ class InstrumentationDescriptor {
}

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
}
60 changes: 30 additions & 30 deletions lib/instrumentations.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,44 +5,44 @@

'use strict'

const MODULE_TYPE = require('./shim/constants').MODULE_TYPE
const InstrumentationDescriptor = require('./instrumentation-descriptor')

// Return a new copy of this array every time we're called
module.exports = function instrumentations() {
return {
'aws-sdk': { module: '@newrelic/aws-sdk' },
'amqplib': { module: './instrumentation/amqplib' },
'cassandra-driver': { type: MODULE_TYPE.DATASTORE },
'connect': { type: MODULE_TYPE.WEB_FRAMEWORK },
'bluebird': { type: MODULE_TYPE.PROMISE },
'bunyan': { type: MODULE_TYPE.GENERIC },
'director': { type: MODULE_TYPE.WEB_FRAMEWORK },
'@elastic/elasticsearch': { type: MODULE_TYPE.DATASTORE },
'express': { type: MODULE_TYPE.WEB_FRAMEWORK },
'fastify': { type: MODULE_TYPE.WEB_FRAMEWORK },
'generic-pool': { type: MODULE_TYPE.GENERIC },
'cassandra-driver': { type: InstrumentationDescriptor.TYPE_DATASTORE },
'connect': { type: InstrumentationDescriptor.TYPE_WEB_FRAMEWORK },
'bluebird': { type: InstrumentationDescriptor.TYPE_PROMISE },
'bunyan': { type: InstrumentationDescriptor.TYPE_GENERIC },
'director': { type: InstrumentationDescriptor.TYPE_WEB_FRAMEWORK },
'@elastic/elasticsearch': { type: InstrumentationDescriptor.TYPE_DATASTORE },
'express': { type: InstrumentationDescriptor.TYPE_WEB_FRAMEWORK },
'fastify': { type: InstrumentationDescriptor.TYPE_WEB_FRAMEWORK },
'generic-pool': { type: InstrumentationDescriptor.TYPE_GENERIC },
'@grpc/grpc-js': { module: './instrumentation/grpc-js' },
'@hapi/hapi': { type: MODULE_TYPE.WEB_FRAMEWORK },
'ioredis': { type: MODULE_TYPE.DATASTORE },
'@hapi/hapi': { type: InstrumentationDescriptor.TYPE_WEB_FRAMEWORK },
'ioredis': { type: InstrumentationDescriptor.TYPE_DATASTORE },
'koa': { module: '@newrelic/koa' },
'langchain': { module: './instrumentation/langchain' },
'memcached': { type: MODULE_TYPE.DATASTORE },
'mongodb': { type: MODULE_TYPE.DATASTORE },
'memcached': { type: InstrumentationDescriptor.TYPE_DATASTORE },
'mongodb': { type: InstrumentationDescriptor.TYPE_DATASTORE },
'mysql': { module: './instrumentation/mysql' },
'openai': { type: MODULE_TYPE.GENERIC },
'@nestjs/core': { type: MODULE_TYPE.WEB_FRAMEWORK },
'@prisma/client': { type: MODULE_TYPE.DATASTORE },
'openai': { type: InstrumentationDescriptor.TYPE_GENERIC },
'@nestjs/core': { type: InstrumentationDescriptor.TYPE_WEB_FRAMEWORK },
'@prisma/client': { type: InstrumentationDescriptor.TYPE_DATASTORE },
'pino': { module: './instrumentation/pino' },
'pg': { type: MODULE_TYPE.DATASTORE },
'pg': { type: InstrumentationDescriptor.TYPE_DATASTORE },
'q': { type: null },
'redis': { type: MODULE_TYPE.DATASTORE },
'@node-redis/client': { type: MODULE_TYPE.DATASTORE },
'@redis/client': { type: MODULE_TYPE.DATASTORE },
'restify': { type: MODULE_TYPE.WEB_FRAMEWORK },
'redis': { type: InstrumentationDescriptor.TYPE_DATASTORE },
'@node-redis/client': { type: InstrumentationDescriptor.TYPE_DATASTORE },
'@redis/client': { type: InstrumentationDescriptor.TYPE_DATASTORE },
'restify': { type: InstrumentationDescriptor.TYPE_WEB_FRAMEWORK },
'superagent': { module: '@newrelic/superagent' },
'@hapi/vision': { type: MODULE_TYPE.WEB_FRAMEWORK },
'@hapi/vision': { type: InstrumentationDescriptor.TYPE_WEB_FRAMEWORK },
'when': { module: './instrumentation/when' },
'winston': { type: MODULE_TYPE.GENERIC },
'winston': { type: InstrumentationDescriptor.TYPE_GENERIC },
/**
* The modules below are listed here purely to take
* advantage of the Supportability/Features/onRequire/<module>
Expand All @@ -52,11 +52,11 @@ module.exports = function instrumentations() {
* Libraries that have OpenTelemetry instrumentation we want to register
* or have already registered.
*/
'loglevel': { type: MODULE_TYPE.TRACKING },
'npmlog': { type: MODULE_TYPE.TRACKING },
'fancy-log': { type: MODULE_TYPE.TRACKING },
'knex': { type: MODULE_TYPE.TRACKING },
'@azure/openai': { type: MODULE_TYPE.TRACKING },
'@langchain/community/llms/bedrock': { type: MODULE_TYPE.TRACKING }
'loglevel': { type: InstrumentationDescriptor.TYPE_TRACKING },
'npmlog': { type: InstrumentationDescriptor.TYPE_TRACKING },
'fancy-log': { type: InstrumentationDescriptor.TYPE_TRACKING },
'knex': { type: InstrumentationDescriptor.TYPE_TRACKING },
'@azure/openai': { type: InstrumentationDescriptor.TYPE_TRACKING },
'@langchain/community/llms/bedrock': { type: InstrumentationDescriptor.TYPE_TRACKING }
}
}
29 changes: 15 additions & 14 deletions lib/shim/conglomerate-shim.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,14 +8,14 @@
const logger = require('../logger').child({ component: 'ConglomerateShim' })
const Shim = require('./shim')

const { MODULE_TYPE } = require('./constants')
const InstrumentationDescriptor = require('../instrumentation-descriptor')
const SHIM_CLASSES = {
[MODULE_TYPE.GENERIC]: Shim,
[MODULE_TYPE.DATASTORE]: require('./datastore-shim'),
[MODULE_TYPE.MESSAGE]: require('./message-shim'),
[MODULE_TYPE.PROMISE]: require('./promise-shim'),
[MODULE_TYPE.TRANSACTION]: require('./transaction-shim'),
[MODULE_TYPE.WEB_FRAMEWORK]: require('./webframework-shim')
[InstrumentationDescriptor.TYPE_GENERIC]: Shim,
[InstrumentationDescriptor.TYPE_DATASTORE]: require('./datastore-shim'),
[InstrumentationDescriptor.TYPE_MESSAGE]: require('./message-shim'),
[InstrumentationDescriptor.TYPE_PROMISE]: require('./promise-shim'),
[InstrumentationDescriptor.TYPE_TRANSACTION]: require('./transaction-shim'),
[InstrumentationDescriptor.TYPE_WEB_FRAMEWORK]: require('./webframework-shim')
}

/**
Expand All @@ -37,29 +37,30 @@ class ConglomerateShim extends Shim {
}

get GENERIC() {
return MODULE_TYPE.GENERIC
return InstrumentationDescriptor.TYPE_GENERIC
}
get DATASTORE() {
return MODULE_TYPE.DATASTORE
return InstrumentationDescriptor.TYPE_DATASTORE
}
get MESSAGE() {
return MODULE_TYPE.MESSAGE
return InstrumentationDescriptor.TYPE_MESSAGE
}
get PROMISE() {
return MODULE_TYPE.PROMISE
return InstrumentationDescriptor.TYPE_PROMISE
}
get TRANSACTION() {
return MODULE_TYPE.TRANSACTION
return InstrumentationDescriptor.TYPE_TRANSACTION
}
get WEB_FRAMEWORK() {
return MODULE_TYPE.WEB_FRAMEWORK
return InstrumentationDescriptor.TYPE_WEB_FRAMEWORK
}

/**
* Constructs a new `Shim` of the specified type for instrumenting submodules
* of the conglomerate module.
*
* @param {MODULE_TYPE} type - The type of shim to construct.
* @param {string} type - The type of shim to construct. Utilize the static
* type fields on {@link InstrumentationDescriptor}.
* @param {string} submodule - The name of the submodule this will instrument.
* @returns {Shim} A new shim of the given type.
*/
Expand Down
42 changes: 0 additions & 42 deletions lib/shim/constants.js

This file was deleted.

18 changes: 8 additions & 10 deletions lib/shim/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,6 @@

'use strict'

const constants = require('./constants')

const Shim = require('./shim')
const ConglomerateShim = require('./conglomerate-shim')
const DatastoreShim = require('./datastore-shim')
Expand All @@ -15,14 +13,15 @@ const PromiseShim = require('./promise-shim')
const TransactionShim = require('./transaction-shim')
const WebFrameworkShim = require('./webframework-shim')
const properties = require('../util/properties')
const InstrumentationDescriptor = require('../instrumentation-descriptor')
const SHIM_TYPE_MAP = Object.create(null)
SHIM_TYPE_MAP[constants.MODULE_TYPE.GENERIC] = Shim
SHIM_TYPE_MAP[constants.MODULE_TYPE.CONGLOMERATE] = ConglomerateShim
SHIM_TYPE_MAP[constants.MODULE_TYPE.DATASTORE] = DatastoreShim
SHIM_TYPE_MAP[constants.MODULE_TYPE.MESSAGE] = MessageShim
SHIM_TYPE_MAP[constants.MODULE_TYPE.PROMISE] = PromiseShim
SHIM_TYPE_MAP[constants.MODULE_TYPE.TRANSACTION] = TransactionShim
SHIM_TYPE_MAP[constants.MODULE_TYPE.WEB_FRAMEWORK] = WebFrameworkShim
SHIM_TYPE_MAP[InstrumentationDescriptor.TYPE_GENERIC] = Shim
SHIM_TYPE_MAP[InstrumentationDescriptor.TYPE_CONGLOMERATE] = ConglomerateShim
SHIM_TYPE_MAP[InstrumentationDescriptor.TYPE_DATASTORE] = DatastoreShim
SHIM_TYPE_MAP[InstrumentationDescriptor.TYPE_MESSAGE] = MessageShim
SHIM_TYPE_MAP[InstrumentationDescriptor.TYPE_PROMISE] = PromiseShim
SHIM_TYPE_MAP[InstrumentationDescriptor.TYPE_TRANSACTION] = TransactionShim
SHIM_TYPE_MAP[InstrumentationDescriptor.TYPE_WEB_FRAMEWORK] = WebFrameworkShim

/**
*
Expand All @@ -46,7 +45,6 @@ function createShimFromType({ type, agent, moduleName, resolvedName, shimName, p
return shim
}

exports.constants = constants
exports.Shim = Shim
exports.ConglomerateShim = ConglomerateShim
exports.DatastoreShim = DatastoreShim
Expand Down
Loading
Loading