Skip to content

Commit

Permalink
fix: Fixed instrumenting the same module installed in different locat…
Browse files Browse the repository at this point in the history
…ions (#2104)
  • Loading branch information
jsumners-nr committed Apr 3, 2024
1 parent 7b5bdaa commit 88bdace
Show file tree
Hide file tree
Showing 27 changed files with 373 additions and 312 deletions.
2 changes: 1 addition & 1 deletion api.js
Expand Up @@ -26,7 +26,7 @@ const {
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
26 changes: 0 additions & 26 deletions jsdoc-conf.json

This file was deleted.

38 changes: 38 additions & 0 deletions jsdoc-conf.jsonc
@@ -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
// 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
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
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
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
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

0 comments on commit 88bdace

Please sign in to comment.