Application Performance Monitoring (APM) agent for Node.js applications with transaction tracing, error tracking, custom metrics, and distributed tracing capabilities.
—
Pending
Does it follow best practices?
Impact
Pending
No eval scenarios have been run
Pending
The risk profile of this skill
Register custom instrumentation for third-party modules and application-specific code patterns.
Register generic instrumentation for any module.
/**
* Register generic instrumentation for a module
* @param {string|object} moduleName - Module name or instrumentation options
* @param {Function} onRequire - Function called when module is loaded
* @param {Function} [onError] - Error handler for instrumentation failures
*/
function instrument(moduleName, onRequire, onError);/**
* Register datastore-specific instrumentation
*/
function instrumentDatastore(moduleName, onRequire, onError);
/**
* Register web framework instrumentation
*/
function instrumentWebframework(moduleName, onRequire, onError);
/**
* Register message broker instrumentation
*/
function instrumentMessages(moduleName, onRequire, onError);
/**
* Register conglomerate (multi-module) instrumentation
*/
function instrumentConglomerate(moduleName, onRequire, onError);
/**
* Apply instrumentation to already loaded modules
* @param {string} moduleName - Module name
* @param {object} module - Already loaded module
* @returns {boolean} Success status
*/
function instrumentLoadedModule(moduleName, module);For advanced instrumentation scenarios, pass an object instead of a string:
interface InstrumentationSpec {
/** Module name to instrument */
moduleName: string;
/** Absolute path for specific module location */
absolutePath?: string;
/** Function called when module loads */
onRequire: Function;
/** Error handler for instrumentation failures */
onError?: Function;
/** Mark as ESM module (for ES Modules) */
isEsm?: boolean;
}The shim object provides different recording methods based on the instrumentation type:
// Record a function call with timing
shim.record(target, methodName, recordSpec);
// Wrap a function with custom logic
shim.wrap(target, methodName, wrapperFunction);
// Segment timing without recording
shim.createSegment(name, recorder, parentSegment);// Record database operations
shim.recordOperation(target, methodNames, operationSpec);
// Record query operations with SQL
shim.recordQuery(target, methodNames, querySpec);
// Record batch operations
shim.recordBatchQuery(target, methodNames, batchSpec);// Record middleware functions
shim.recordMiddleware(target, methodName, middlewareSpec);
// Record route handlers
shim.recordRender(target, methodName, renderSpec);
// Wrap request/response handling
shim.wrapMiddlewareMounter(target, methodName, spec);// Record message producer operations
shim.recordProduce(target, methodName, produceSpec);
// Record message consumer operations
shim.recordConsume(target, methodName, consumeSpec);
// Record subscription operations
shim.recordSubscribedConsume(target, methodName, subscribeSpec);Usage Examples:
const newrelic = require('newrelic');
// Basic instrumentation with error handling
newrelic.instrument('my-custom-db', function(shim, module, moduleName) {
// Record all query methods
shim.record(module.prototype, ['query', 'find', 'update'], function(shim, fn, name, args) {
return {
name: `Database/${moduleName}/${name}`,
callback: shim.LAST,
parameters: {
query: args[0]
}
};
});
// Wrap connection method for additional context
shim.wrap(module.prototype, 'connect', function(shim, original) {
return function wrappedConnect() {
const result = original.apply(this, arguments);
shim.logger.debug('Database connection established');
return result;
};
});
}, function onError(error) {
console.error('Failed to instrument my-custom-db:', error);
});
// Advanced datastore instrumentation
newrelic.instrumentDatastore('redis-custom', function(shim, redis, moduleName) {
// Record standard operations
shim.recordOperation(redis.RedisClient.prototype, ['get', 'set', 'del'], {
name: function(shim, fn, fnName, args) {
return fnName.toUpperCase(); // GET, SET, DEL
},
parameters: {
key: shim.FIRST,
database_name: function(shim, fn, fnName, args, client) {
return client.selectedDb || 0;
}
},
callback: function(shim, fn, fnName, args) {
// Find callback in arguments
for (let i = args.length - 1; i >= 0; i--) {
if (typeof args[i] === 'function') {
return i;
}
}
return null;
}
});
// Record complex query operations
shim.recordQuery(redis.RedisClient.prototype, ['eval', 'evalsha'], {
name: 'EVAL',
parameters: {
script: shim.FIRST,
key_count: function(shim, fn, fnName, args) {
return args[1] || 0;
}
},
callback: shim.LAST
});
});
// Web framework instrumentation
newrelic.instrumentWebframework('my-web-framework', function(shim, framework, moduleName) {
// Record middleware registration
shim.recordMiddleware(framework.prototype, 'use', {
name: function(shim, fn, fnName, args) {
if (typeof args[0] === 'string') {
return `Middleware/${args[0]}`;
}
return 'Middleware/anonymous';
},
type: shim.MIDDLEWARE,
route: function(shim, fn, fnName, args) {
return typeof args[0] === 'string' ? args[0] : null;
},
wrapper: function(shim, middleware, name) {
return shim.recordMiddleware(middleware, {
name: name,
type: shim.MIDDLEWARE
});
}
});
// Record route handlers
shim.recordRender(framework.prototype, ['get', 'post', 'put', 'delete'], {
name: function(shim, fn, fnName, args) {
const route = args[0] || '/';
return `Route/${fnName.toUpperCase()} ${route}`;
},
callback: function(shim, fn, fnName, args) {
// Last argument is typically the handler
return args.length - 1;
}
});
});
// Message queue instrumentation
newrelic.instrumentMessages('my-queue-lib', function(shim, queueLib, moduleName) {
// Record message publishing
shim.recordProduce(queueLib.prototype, 'publish', {
name: function(shim, fn, fnName, args) {
const queueName = args[0] || 'unknown';
return `MessageBroker/${moduleName}/Queue/Produce/Named/${queueName}`;
},
parameters: {
routing_key: shim.FIRST,
reply_to: function(shim, fn, fnName, args) {
return args[1] && args[1].replyTo;
}
},
callback: shim.LAST
});
// Record message consumption
shim.recordConsume(queueLib.prototype, 'subscribe', {
name: function(shim, fn, fnName, args) {
const queueName = args[0] || 'unknown';
return `MessageBroker/${moduleName}/Queue/Consume/Named/${queueName}`;
},
parameters: {
routing_key: shim.FIRST
},
messageHandler: function(shim, fn, fnName, args) {
// Find the message handler function
for (let i = 1; i < args.length; i++) {
if (typeof args[i] === 'function') {
return i;
}
}
return null;
}
});
});
// Already loaded module instrumentation
const customModule = require('my-module');
const success = newrelic.instrumentLoadedModule('my-module', customModule);
if (success) {
console.log('Successfully instrumented already-loaded module');
} else {
console.warn('Failed to instrument already-loaded module');
}
// ESM module instrumentation
newrelic.instrument({
moduleName: 'esm-module',
isEsm: true,
onRequire: function(shim, module, moduleName) {
shim.record(module.default, 'process', {
name: `Custom/${moduleName}/process`,
callback: shim.LAST
});
},
onError: function(error) {
console.error('ESM instrumentation failed:', error);
}
});interface RecordSpec {
/** Segment/metric name (string or function) */
name: string | Function;
/** Callback argument index or function to find it */
callback?: number | Function;
/** Additional parameters to capture */
parameters?: object;
/** Whether to record as a metric */
record?: boolean;
/** Segment recorder function */
recorder?: Function;
}interface DatastoreOperationSpec {
/** Operation name */
name: string | Function;
/** Callback position */
callback?: number | Function;
/** Parameters to capture (database_name, collection_name, etc.) */
parameters?: object;
/** Promise handling */
promise?: boolean;
/** Query/command to capture */
query?: Function;
}interface MiddlewareSpec {
/** Middleware name */
name: string | Function;
/** Middleware type (shim.MIDDLEWARE, shim.ROUTER, etc.) */
type: string;
/** Route pattern */
route?: string | Function;
/** Request object position */
req?: number | Function;
/** Response object position */
res?: number | Function;
/** Next function position */
next?: number | Function;
/** Wrapper function for the middleware */
wrapper?: Function;
}newrelic.instrument('unreliable-module', function(shim, module) {
try {
shim.record(module, 'riskyMethod', {
name: 'RiskyOperation',
callback: shim.LAST
});
} catch (error) {
shim.logger.warn('Could not instrument riskyMethod:', error);
}
}, function onError(error) {
console.error('Module instrumentation failed completely:', error);
});newrelic.instrument('optional-module', function(shim, module) {
if (module.version && parseFloat(module.version) >= 2.0) {
// Use v2+ API
shim.record(module, 'newMethod', {
name: 'NewAPI/newMethod',
callback: shim.LAST
});
} else {
// Use legacy API
shim.record(module, 'oldMethod', {
name: 'LegacyAPI/oldMethod',
callback: shim.LAST
});
}
});newrelic.instrument('promise-based-lib', function(shim, lib) {
shim.record(lib.prototype, 'asyncOperation', {
name: 'AsyncOperation',
promise: true, // Handle promise-based methods
parameters: {
input: shim.FIRST
}
});
});newrelic.instrument('class-based-lib', function(shim, lib) {
// Instrument instance methods
shim.record(lib.MyClass.prototype, ['method1', 'method2'], {
name: function(shim, fn, fnName) {
return `MyClass/${fnName}`;
},
callback: shim.LAST
});
// Instrument static methods
shim.record(lib.MyClass, 'staticMethod', {
name: 'MyClass/staticMethod',
callback: shim.LAST
});
});isEsm: true and ensure proper import handlinginstrumentLoadedModule for modules loaded before instrumentationnewrelic.instrument('debug-module', function(shim, module, moduleName) {
shim.logger.debug('Instrumenting module:', moduleName);
shim.logger.debug('Module methods:', Object.getOwnPropertyNames(module));
shim.record(module, 'targetMethod', {
name: 'DebugOperation',
callback: function(shim, fn, fnName, args) {
shim.logger.debug('Callback search in args:', args.map(arg => typeof arg));
return shim.LAST;
}
});
});