Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

elastic-apm-node

Package Overview
Dependencies
Maintainers
3
Versions
162
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

elastic-apm-node - npm Package Compare versions

Comparing version 4.0.0 to 4.1.0

lib/instrumentation/modules/@aws-sdk/client-dynamodb.js

1

index.d.ts

@@ -384,2 +384,3 @@ /*

interface PatchOptions {
name: string;
version: string | undefined;

@@ -386,0 +387,0 @@ enabled: boolean;

2

lib/agent.js

@@ -25,3 +25,3 @@ /*

const { InflightEventSet } = require('./InflightEventSet');
const Instrumentation = require('./instrumentation');
const { Instrumentation } = require('./instrumentation');
const { elasticApmAwsLambda } = require('./lambda');

@@ -28,0 +28,0 @@ const Metrics = require('./metrics');

@@ -8,5 +8,9 @@ /*

'use strict';
const URL = require('url').URL;
const JSONBigInt = require('json-bigint');
const { httpRequest } = require('../http-request');
const DEFAULT_BASE_URL = new URL('/', 'http://metadata.google.internal:80');
/**

@@ -48,2 +52,16 @@ * Checks for metadata server then fetches data

res.on('end', function (data) {
if (res.statusCode !== 200) {
logger.debug('gcp metadata: unexpected statusCode: %s', res.statusCode);
cb(
new Error(
'error fetching gcp metadata: unexpected statusCode: ' +
res.statusCode,
),
);
return;
}
// Note: We could also guard on the response having the
// 'Metadata-Flavor: Google' header as done by:
// https://github.com/googleapis/gcp-metadata/blob/v6.0.0/src/index.ts#L109-L112
let result;

@@ -53,3 +71,3 @@ try {

} catch (err) {
logger.trace(
logger.debug(
'gcp metadata server responded, but there was an ' +

@@ -84,72 +102,33 @@ 'error parsing the result: %o',

*
* Takes the response from a /computeMetadata/v1/?recursive=true
* service request and formats it into the cloud metadata object
* Convert a GCP Cloud Engine VM metadata response
* (https://cloud.google.com/compute/docs/metadata/default-metadata-values)
* to the APM intake cloud metadata object
* (https://github.com/elastic/apm/blob/main/specs/agents/metadata.md#gcp-metadata).
*
* See discussion about big int values here:
* https://github.com/googleapis/gcp-metadata#take-care-with-large-number-valued-properties
* This implementation is using the same 'json-bigint' library as 'gcp-metadata'.
*/
function formatMetadataStringIntoObject(string) {
const data = JSON.parse(string);
// cast string manipulation fields as strings "just in case"
if (data.instance) {
data.instance.machineType = String(data.instance.machineType);
data.instance.zone = String(data.instance.zone);
}
const data = JSONBigInt.parse(string);
// E.g., 'projects/513326162531/zones/us-west1-b' -> 'us-west1-b'
const az = data.instance.zone.split('/').pop();
const metadata = {
availability_zone: null,
region: null,
provider: 'gcp',
instance: {
id: null,
id: data.instance.id.toString(), // We expect this to be a BigInt.
name: data.instance.name,
},
project: {
id: data.project.projectId,
},
availability_zone: az,
region: az.slice(0, az.lastIndexOf('-')), // 'us-west1-b' -> 'us-west1'
machine: {
type: null,
type: data.instance.machineType.split('/').pop(),
},
provider: null,
project: {
id: null,
name: null,
},
};
metadata.availability_zone = null;
metadata.region = null;
if (data.instance && data.instance.zone) {
// `projects/513326162531/zones/us-west1-b` manipuated into
// `us-west1-b`, and then `us-west1`
const regionWithZone = data.instance.zone.split('/').pop();
const parts = regionWithZone.split('-');
parts.pop();
metadata.region = parts.join('-');
metadata.availability_zone = regionWithZone;
}
if (data.instance) {
metadata.instance = {
id: String(data.instance.id),
};
metadata.machine = {
type: String(data.instance.machineType.split('/').pop()),
};
} else {
metadata.instance = {
id: null,
};
metadata.machine = {
type: null,
};
}
metadata.provider = 'gcp';
if (data.project) {
metadata.project = {
id: String(data.project.numericProjectId),
name: String(data.project.projectId),
};
} else {
metadata.project = {
id: null,
name: null,
};
}
return metadata;

@@ -156,0 +135,0 @@ }

@@ -21,3 +21,2 @@ /*

var { Ids } = require('./ids');
var NamedArray = require('./named-array');
var Transaction = require('./transaction');

@@ -41,51 +40,71 @@ var { NoopTransaction } = require('./noop-transaction');

var MODULES = [
'@apollo/server',
['@smithy/smithy-client', '@aws-sdk/smithy-client'], // Instrument the base client which all AWS-SDK v3 clients extends.
['@elastic/elasticsearch', '@elastic/elasticsearch-canary'],
'@opentelemetry/api',
'@opentelemetry/sdk-metrics',
'@node-redis/client/dist/lib/client',
'@node-redis/client/dist/lib/client/commands-queue',
'@redis/client/dist/lib/client',
'@redis/client/dist/lib/client/commands-queue',
'apollo-server-core',
'aws-sdk',
'bluebird',
'cassandra-driver',
'elasticsearch',
'express',
'express-graphql',
'express-queue',
'fastify',
'finalhandler',
'generic-pool',
'graphql',
'handlebars',
'@hapi/hapi',
'http',
'https',
'http2',
'ioredis',
'jade',
'knex',
'koa',
['koa-router', '@koa/router'],
'memcached',
'mimic-response',
'mongodb-core',
'mongodb',
'mysql',
'mysql2',
'next/dist/server/api-utils/node',
'next/dist/server/dev/next-dev-server',
'next/dist/server/next',
'next/dist/server/next-server',
'pg',
'pug',
'redis',
'restify',
'tedious',
'undici',
'ws',
var MODULE_PATCHERS = [
{ modPath: '@apollo/server' },
{ modPath: '@smithy/smithy-client' }, // Instrument the base client which all AWS-SDK v3 clients extend.
{
modPath: '@aws-sdk/smithy-client',
patcher: './modules/@smithy/smithy-client.js',
},
{ modPath: '@elastic/elasticsearch' },
{
modPath: '@elastic/elasticsearch-canary',
patcher: './modules/@elastic/elasticsearch.js',
},
{ modPath: '@opentelemetry/api' },
{ modPath: '@opentelemetry/sdk-metrics' },
{ modPath: '@redis/client/dist/lib/client/index.js', diKey: 'redis' },
{
modPath: '@redis/client/dist/lib/client/commands-queue.js',
diKey: 'redis',
},
{
modPath: '@node-redis/client/dist/lib/client/index.js',
patcher: './modules/@redis/client/dist/lib/client/index.js',
diKey: 'redis',
},
{
modPath: '@node-redis/client/dist/lib/client/commands-queue.js',
patcher: './modules/@redis/client/dist/lib/client/commands-queue.js',
diKey: 'redis',
},
{ modPath: 'apollo-server-core' },
{ modPath: 'aws-sdk' },
{ modPath: 'bluebird' },
{ modPath: 'cassandra-driver' },
{ modPath: 'elasticsearch' },
{ modPath: 'express' },
{ modPath: 'express-graphql' },
{ modPath: 'express-queue' },
{ modPath: 'fastify' },
{ modPath: 'finalhandler' },
{ modPath: 'generic-pool' },
{ modPath: 'graphql' },
{ modPath: 'handlebars' },
{ modPath: '@hapi/hapi' },
{ modPath: 'http' },
{ modPath: 'https' },
{ modPath: 'http2' },
{ modPath: 'ioredis' },
{ modPath: 'jade' },
{ modPath: 'knex' },
{ modPath: 'koa' },
{ modPath: 'koa-router' },
{ modPath: '@koa/router', patcher: './modules/koa-router.js' },
{ modPath: 'memcached' },
{ modPath: 'mimic-response' },
{ modPath: 'mongodb-core' },
{ modPath: 'mongodb' },
{ modPath: 'mysql' },
{ modPath: 'mysql2' },
{ modPath: 'next' },
{ modPath: 'next/dist/server/api-utils/node.js' },
{ modPath: 'next/dist/server/dev/next-dev-server.js' },
{ modPath: 'next/dist/server/next-server.js' },
{ modPath: 'pg' },
{ modPath: 'pug' },
{ modPath: 'redis' },
{ modPath: 'restify' },
{ modPath: 'tedious' },
{ modPath: 'undici' },
{ modPath: 'ws' },
];

@@ -113,2 +132,3 @@

// '@aws-sdk/smithy-client': { instrumentImportMod: false },
'cassandra-driver': { instrumentImportMod: false },
express: { instrumentImportMod: false },

@@ -123,4 +143,155 @@ fastify: { instrumentImportMod: true },

module.exports = Instrumentation;
/**
* modPath modName
* ------- ---------
* mongodb mongodb
* mongodb/lib/foo.js mongodb
* @elastic/elasticsearch @elastic/elasticsearch
* @redis/client/dist/lib/client.js @redis/client
* /var/task/index.js /var/task/index.js
*/
function modNameFromModPath(modPath) {
if (modPath.startsWith('/')) {
return modPath;
} else if (modPath.startsWith('@')) {
return modPath.split('/', 2).join('/');
} else {
return modPath.split('/', 1)[0];
}
}
/**
* Holds the registered set of "patchers" (functions that monkey patch imported
* modules) for a module path (`modPath`).
*/
class PatcherRegistry {
constructor() {
this.reset();
}
reset() {
this._infoFromModPath = {};
}
/**
* Add a patcher for the given module path.
*
* @param {string} modPath - Identifies a module that RITM can hook: a
* module name (http, @smithy/client), a module-relative path
* (mongodb/lib/cmap/connection_pool.js), an absolute path
* (/var/task/index.js; Windows paths are not supported), a sub-module
* (react-dom/server).
* @param {import('../..').PatchHandler | string} patcher - A patcher function
* or a path to a CommonJS module that exports one as the default export.
* @param {string} [diKey] - An optional key in the `disableInstrumentations`
* config var that is used to determine if this patcher is
* disabled. All patchers for the same modPath must share the same `diKey`.
* This throws if a conflicting `diKey` is given.
* It defaults to the `modName` (derived from the `modPath`).
*/
add(modPath, patcher, diKey = null) {
if (!(modPath in this._infoFromModPath)) {
this._infoFromModPath[modPath] = {
patchers: [patcher],
diKey: diKey || modNameFromModPath(modPath),
};
} else {
const entry = this._infoFromModPath[modPath];
// The `diKey`, if provided, must be the same for all patchers for a modPath.
if (diKey && diKey !== entry.diKey) {
throw new Error(
`invalid "diKey", ${diKey}, for module "${modPath}" patcher: it conflicts with existing diKey=${entry.diKey}`,
);
}
entry.patchers.push(patcher);
}
}
/**
* Remove the given patcher for the given module path.
*/
remove(modPath, patcher) {
const entry = this._infoFromModPath[modPath];
if (!entry) {
return;
}
const idx = entry.patchers.indexOf(patcher);
if (idx !== -1) {
entry.patchers.splice(idx, 1);
}
if (entry.patchers.length === 0) {
delete this._infoFromModPath[modPath];
}
}
/**
* Remove all patchers for the given module path.
*/
clear(modPath) {
delete this._infoFromModPath[modPath];
}
has(modPath) {
return modPath in this._infoFromModPath;
}
getPatchers(modPath) {
return this._infoFromModPath[modPath]?.patchers;
}
/**
* Returns the appropriate RITM `modules` argument so that all registered
* `modPath`s will be hooked. This assumes `{internals: true}` RITM options
* are used.
*
* @returns {Array<string>}
*/
ritmModulesArg() {
// RITM hooks:
// 1. `require('mongodb')` if 'mongodb' is in the modules arg;
// 2. `require('mongodb/lib/foo.js')`, a module-relative path, if 'mongodb'
// is in the modules arg and `{internals: true}` option is given;
// 3. `require('/var/task/index.js')` if the exact resolved absolute path
// is in the modules arg; and
// 4. `require('react-dom/server')`, a "sub-module", if 'react-dom/server'
// is in the modules arg.
//
// The wrinkle is that the modPath "mongodb/lib/foo.js" need not be in the
// `modules` argument to RITM, but the similar-looking "react-dom/server"
// must be.
const modules = new Set();
const hasModExt = /\.(js|cjs|mjs|json)$/;
Object.keys(this._infoFromModPath).forEach((modPath) => {
const modName = modNameFromModPath(modPath);
if (modPath === modName) {
modules.add(modPath);
} else {
if (hasModExt.test(modPath)) {
modules.add(modName); // case 2
} else {
// Beware the RITM bug: passing both 'foo' and 'foo/subpath' results
// in 'foo/subpath' not being hooked.
// TODO: link to issue for this
modules.add(modPath); // case 4
}
}
});
return Array.from(modules);
}
/**
* Get the string on the `disableInstrumentations` config var that indicates
* if this module path should be disabled.
*
* Typically this is the module name -- e.g. "@redis/client" -- but might be
* a custom value -- e.g. "lambda" for a Lambda handler path.
*
* @returns {string | undefined}
*/
diKey(modPath) {
return this._infoFromModPath[modPath]?.diKey;
}
}
function Instrumentation(agent) {

@@ -134,32 +305,4 @@ this._agent = agent;

this._log = agent.logger;
// NOTE: we need to track module names for patches
// in a separate array rather than using Object.keys()
// because the array is given to the hook(...) call.
this._patches = new NamedArray();
for (let modName of MODULES) {
if (!Array.isArray(modName)) modName = [modName];
const pathName = modName[0];
this.addPatch(modName, (...args) => {
// Lazy require so that we don't have to use `require.resolve` which
// would fail in combination with Webpack. For more info see:
// https://github.com/elastic/apm-agent-nodejs/pull/957
return require(`./modules/${pathName}.js`)(...args);
});
}
// patch for lambda handler needs special handling since its
// module name will always be different than its handler name
this._lambdaHandlerInfo = getLambdaHandlerInfo(
process.env,
MODULES,
this._log,
);
if (this._lambdaHandlerInfo) {
this.addPatch(this._lambdaHandlerInfo.filePath, (...args) => {
return require('./modules/_lambda-handler')(...args);
});
}
this._patcherReg = new PatcherRegistry();
this._cachedVerFromModBaseDir = new Map();
}

@@ -197,4 +340,3 @@

}
for (const modName of modules) {
for (const modPath of modules) {
const type = typeof handler;

@@ -205,7 +347,5 @@ if (type !== 'function' && type !== 'string') {

}
this._patches.add(modName, handler);
this._patcherReg.add(modPath, handler);
}
this._startHook();
this._restartHooks();
};

@@ -216,7 +356,7 @@

for (const modName of modules) {
this._patches.delete(modName, handler);
for (const modPath of modules) {
this._patcherReg.remove(modPath, handler);
}
this._startHook();
this._restartHooks();
};

@@ -227,11 +367,33 @@

for (const modName of modules) {
this._patches.clear(modName);
for (const modPath of modules) {
this._patcherReg.clear(modPath);
}
this._startHook();
this._restartHooks();
};
Instrumentation.modules = Object.freeze(MODULES);
// If in a Lambda environment, find its handler and add a patcher for it.
Instrumentation.prototype._maybeLoadLambdaPatcher = function () {
let lambdaHandlerInfo = getLambdaHandlerInfo(process.env);
if (lambdaHandlerInfo && this._patcherReg.has(lambdaHandlerInfo.modName)) {
this._log.warn(
'Unable to instrument Lambda handler "%s" due to name conflict with "%s", please choose a different Lambda handler name',
process.env._HANDLER,
lambdaHandlerInfo.modName,
);
lambdaHandlerInfo = null;
}
if (lambdaHandlerInfo) {
const { createLambdaPatcher } = require('./modules/_lambda-handler');
this._lambdaHandlerInfo = lambdaHandlerInfo;
this._patcherReg.add(
this._lambdaHandlerInfo.filePath,
createLambdaPatcher(lambdaHandlerInfo.propPath),
'lambda', // diKey
);
}
};
// Start the instrumentation system.

@@ -275,6 +437,27 @@ //

// Load module patchers: from MODULE_PATCHERS, for Lambda, and from
// config.addPatch.
for (let info of MODULE_PATCHERS) {
let patcher;
if (info.patcher) {
patcher = path.resolve(__dirname, info.patcher);
} else {
// Typically the patcher module for the APM agent's included
// instrumentations is "./modules/${modPath}[.js]".
patcher = path.resolve(
__dirname,
'modules',
info.modPath + (info.modPath.endsWith('.js') ? '' : '.js'),
);
}
this._patcherReg.add(info.modPath, patcher, info.diKey);
}
this._maybeLoadLambdaPatcher();
const patches = this._agent._conf.addPatch;
if (Array.isArray(patches)) {
for (const [modName, path] of patches) {
this.addPatch(modName, path);
for (const [modPath, patcher] of patches) {
this._patcherReg.add(modPath, patcher);
}

@@ -284,3 +467,3 @@ }

this._runCtxMgr.enable();
this._startHook();
this._restartHooks();

@@ -321,3 +504,4 @@ if (nodeHasInstrumentableFetch && this._isModuleEnabled('undici')) {

}
this._patcherReg.reset();
this._lambdaHandlerInfo = null;
if (nodeHasInstrumentableFetch) {

@@ -354,3 +538,3 @@ undiciInstr.uninstrumentUndici();

Instrumentation.prototype._startHook = function () {
Instrumentation.prototype._restartHooks = function () {
if (!this._started) {

@@ -371,35 +555,48 @@ return;

this._agent.logger.debug('adding hooks to Node.js module loader');
this._log.debug('adding Node.js module loader hooks');
this._ritmHook = new RitmHook(this._patches.keys, function (
exports,
name,
basedir,
) {
const enabled = self._isModuleEnabled(name);
var pkg, version;
this._ritmHook = new RitmHook(
this._patcherReg.ritmModulesArg(),
{ internals: true },
function (exports, modPath, basedir) {
let version = undefined;
const isHandlingLambda =
self._lambdaHandlerInfo && self._lambdaHandlerInfo.module === name;
// An *absolute path* given to RITM results in the file *basename* being
// used as `modPath` in this callback. We need the absolute path back to
// look up the patcher in our registry. We know the only absolute path
// we use is for our Lambda handler.
if (self._lambdaHandlerInfo?.modName === modPath) {
modPath = self._lambdaHandlerInfo.filePath;
version = process.env.AWS_LAMBDA_FUNCTION_VERSION || '';
}
if (!isHandlingLambda && basedir) {
pkg = path.join(basedir, 'package.json');
try {
version = JSON.parse(fs.readFileSync(pkg)).version;
} catch (e) {
self._agent.logger.debug(
'could not shim %s module: %s',
name,
e.message,
);
if (!self._patcherReg.has(modPath)) {
// Skip out if there are no patchers for this hooked module name.
return exports;
}
} else {
version = process.versions.node;
}
return self._patchModule(exports, name, version, enabled, false);
});
// Find an appropriate version for this modPath.
if (version !== undefined) {
// Lambda version already handled above.
} else if (!basedir) {
// This is a core module.
version = process.versions.node;
} else {
// This is a module (e.g. 'mongodb') or a module internal path
// ('mongodb/lib/cmap/connection_pool.js').
version = self._getPackageVersion(modPath, basedir);
if (version === undefined) {
self._log.debug('could not patch %s module', modPath);
return exports;
}
}
const diKey = self._patcherReg.diKey(modPath);
const enabled = self._isModuleEnabled(diKey);
return self._patchModule(exports, modPath, version, enabled, false);
},
);
this._iitmHook = IitmHook(
// TODO: Eventually derive this from `_patcherRegistry`.
Object.keys(IITM_MODULES),

@@ -428,2 +625,7 @@ function (modExports, modName, modBaseDir) {

Instrumentation.prototype._getPackageVersion = function (modName, modBaseDir) {
if (this._cachedVerFromModBaseDir.has(modBaseDir)) {
return this._cachedVerFromModBaseDir.get(modBaseDir);
}
let ver = undefined;
try {

@@ -434,5 +636,3 @@ const version = JSON.parse(

if (typeof version === 'string') {
return version;
} else {
return undefined;
ver = version;
}

@@ -444,4 +644,6 @@ } catch (err) {

);
return undefined;
}
this._cachedVerFromModBaseDir.set(modBaseDir, ver);
return ver;
};

@@ -457,3 +659,3 @@

* `module.exports`) if `isImportMod=false`.
* @param {string} name
* @param {string} modPath
* @param {string} version

@@ -471,3 +673,3 @@ * @param {boolean} enabled Whether instrumentation is enabled for this module

modExports,
name,
modPath,
version,

@@ -477,5 +679,5 @@ enabled,

) {
this._agent.logger.debug(
this._log.debug(
'instrumenting %s@%s module (enabled=%s, isImportMod=%s)',
name,
modPath,
version,

@@ -485,21 +687,13 @@ enabled,

);
const isHandlingLambda =
this._lambdaHandlerInfo && this._lambdaHandlerInfo.module === name;
let patches;
if (!isHandlingLambda) {
patches = this._patches.get(name);
} else if (name === this._lambdaHandlerInfo.module) {
patches = this._patches.get(this._lambdaHandlerInfo.filePath);
}
if (patches) {
for (let patch of patches) {
if (typeof patch === 'string') {
if (patch[0] === '.') {
patch = path.resolve(process.cwd(), patch);
const patchers = this._patcherReg.getPatchers(modPath);
if (patchers) {
for (let patcher of patchers) {
if (typeof patcher === 'string') {
if (patcher[0] === '.') {
patcher = path.resolve(process.cwd(), patcher);
}
patch = require(patch);
patcher = require(patcher);
}
const type = typeof patch;
const type = typeof patcher;
if (type !== 'function') {

@@ -509,3 +703,3 @@ this._agent.logger.error(

type,
name,
modPath,
);

@@ -515,4 +709,4 @@ continue;

modExports = patch(modExports, this._agent, {
name,
modExports = patcher(modExports, this._agent, {
name: modPath,
version,

@@ -940,1 +1134,5 @@ enabled,

};
module.exports = {
Instrumentation,
};

@@ -9,25 +9,33 @@ /*

const Instrumentation = require('../index');
const { getLambdaHandlerInfo } = require('../../lambda');
const propwrap = require('../../propwrap');
module.exports = function (module, agent, { version, enabled }) {
if (!enabled) {
return module;
}
/**
* Return a patch handler, `function (module, agent, options)`, that will patch
* the Lambda handler function at the given property path.
*
* For example, a Lambda _HANDLER=index.handler indicates that a file "index.js"
* has a `handler` export that is the Lambda handler function. In this case
* `module` will be the imported "index.js" module and `propPath` will be
* "handler".
*/
function createLambdaPatcher(propPath) {
return function lambdaHandlerPatcher(module, agent, { enabled }) {
if (!enabled) {
return module;
}
const { field } = getLambdaHandlerInfo(
process.env,
Instrumentation.modules,
agent.logger,
);
try {
const newMod = propwrap.wrap(module, field, (orig) => {
return agent.lambda(orig);
});
return newMod;
} catch (wrapErr) {
agent.logger.warn('could not wrap lambda handler: %s', wrapErr);
return module;
}
try {
const newMod = propwrap.wrap(module, propPath, (orig) => {
return agent.lambda(orig);
});
return newMod;
} catch (wrapErr) {
agent.logger.warn('could not wrap lambda handler: %s', wrapErr);
return module;
}
};
}
module.exports = {
createLambdaPatcher,
};

@@ -214,2 +214,12 @@ /*

/**
* Tells if the command needs to be ingored
* @param {import('@aws-sdk/types').Command} command the command sent by the SNS client
* @param {any} config the agent configuration
* @returns {boolean} false if the command should create a span
*/
function s3ShouldIgnoreCommand(command, config) {
return false;
}
module.exports = {

@@ -220,2 +230,3 @@ S3_NAME: NAME,

s3MiddlewareFactory,
s3ShouldIgnoreCommand,
};

@@ -13,2 +13,9 @@ /*

const {
DYNAMODB_NAME,
DYNAMODB_TYPE,
DYNAMODB_SUBTYPE,
dynamoDBMiddlewareFactory,
dynamoDBShouldIgnoreCommand,
} = require('../@aws-sdk/client-dynamodb');
const {
S3_NAME,

@@ -18,4 +25,20 @@ S3_TYPE,

s3MiddlewareFactory,
s3ShouldIgnoreCommand,
} = require('../@aws-sdk/client-s3');
const {
SNS_NAME,
SNS_TYPE,
SNS_SUBTYPE,
snsMiddlewareFactory,
snsShouldIgnoreCommand,
} = require('../@aws-sdk/client-sns');
const {
SQS_NAME,
SQS_TYPE,
SQS_SUBTYPE,
sqsMiddlewareFactory,
sqsShouldIgnoreCommand,
} = require('../@aws-sdk/client-sqs');
/**

@@ -55,2 +78,9 @@ * We do alias them to a local type

const clientsConfig = {
DynamoDBClient: {
NAME: DYNAMODB_NAME,
TYPE: DYNAMODB_TYPE,
SUBTYPE: DYNAMODB_SUBTYPE,
factory: dynamoDBMiddlewareFactory,
shouldIgnoreCommand: dynamoDBShouldIgnoreCommand,
},
S3Client: {

@@ -61,3 +91,18 @@ NAME: S3_NAME,

factory: s3MiddlewareFactory,
shouldIgnoreCommand: s3ShouldIgnoreCommand,
},
SNSClient: {
NAME: SNS_NAME,
TYPE: SNS_TYPE,
SUBTYPE: SNS_SUBTYPE,
factory: snsMiddlewareFactory,
shouldIgnoreCommand: snsShouldIgnoreCommand,
},
SQSClient: {
NAME: SQS_NAME,
TYPE: SQS_TYPE,
SUBTYPE: SQS_SUBTYPE,
factory: sqsMiddlewareFactory,
shouldIgnoreCommand: sqsShouldIgnoreCommand,
},
};

@@ -115,2 +160,7 @@

const command = arguments[0];
if (clientConfig.shouldIgnoreCommand(command, agent._conf)) {
return orig.apply(this, arguments);
}
const opName = opNameFromCommandName(command.constructor.name);

@@ -117,0 +167,0 @@ const name = clientConfig.NAME + ' ' + opName;

@@ -26,3 +26,4 @@ /*

if (!semver.satisfies(version, '>=2.0.0 <4.0.0')) {
agent.logger.debug('redis version %s not supported - aborting...', version);
// Explicitly do not log.debug here, because the message is misleading for
// redis@4 and later that is being handled by @redis/client instrumentation.
return redis;

@@ -29,0 +30,0 @@ }

@@ -811,17 +811,2 @@ /*

function isHandlerNameInModules(handlerModule, modules) {
for (let instrumentedModules of modules) {
// array.flat didn't come around until Node 11
if (!Array.isArray(instrumentedModules)) {
instrumentedModules = [instrumentedModules];
}
for (const instrumentedModule of instrumentedModules) {
if (handlerModule === instrumentedModule) {
return true;
}
}
}
return false;
}
// Returns the full file path to the user's handler handler module

@@ -847,3 +832,3 @@ //

function getLambdaHandlerInfo(env, modules, logger) {
function getLambdaHandlerInfo(env) {
if (

@@ -854,3 +839,3 @@ !isLambdaExecutionEnvironment() ||

) {
return;
return null;
}

@@ -863,18 +848,6 @@

if (!match || match.length !== 3) {
return;
return null;
}
const handlerModule = match[1].split('/').pop();
const handlerFunctionPath = match[2];
// if there's a name conflict with an already instrumented module, skip the
// instrumentation of the lambda handle and log a message.
if (isHandlerNameInModules(handlerModule, modules)) {
logger.warn(
'Unable to instrument Lambda handler "%s" due to name conflict with "%s", please choose a different Lambda handler name',
env._HANDLER,
handlerModule,
);
return;
}
const handlerFilePath = getFilePath(env.LAMBDA_TASK_ROOT, match[1]);

@@ -884,4 +857,4 @@

filePath: handlerFilePath,
module: handlerModule,
field: handlerFunctionPath,
modName: handlerModule,
propPath: handlerFunctionPath,
};

@@ -888,0 +861,0 @@ }

@@ -116,4 +116,4 @@ /*

*
* @param {Object} res - Typically `res` is a Node.js `http.OutgoingMessage`
* (https://nodejs.org/api/http.html#class-httpoutgoingmessage).
* @param {Object} res - Typically `res` is a Node.js `http.ServerResponse`
* (https://nodejs.org/api/http.html#class-httpserverresponse).
* However, some cases (e.g. Lambda and Azure Functions instrumentation)

@@ -120,0 +120,0 @@ * create a pseudo-res object that matches well enough for this function.

{
"name": "elastic-apm-node",
"version": "4.0.0",
"version": "4.1.0",
"description": "The official Elastic APM agent for Node.js",

@@ -8,3 +8,2 @@ "main": "index.js",

"scripts": {
"backport": "backport",
"docs:open": "PREVIEW=1 npm run docs:build",

@@ -110,2 +109,3 @@ "docs:build": "./docs/scripts/build_docs.sh apm-agent-nodejs ./docs ./build",

"import-in-the-middle": "1.4.2",
"json-bigint": "^1.0.0",
"lru-cache": "^10.0.1",

@@ -131,3 +131,6 @@ "measured-reporting": "^1.51.1",

"@apollo/server": "^4.2.2",
"@aws-sdk/client-dynamodb": "^3.379.1",
"@aws-sdk/client-s3": "^3.379.1",
"@aws-sdk/client-sns": "^3.379.1",
"@aws-sdk/client-sqs": "^3.379.1",
"@aws-sdk/s3-request-presigner": "^3.379.1",

@@ -147,3 +150,2 @@ "@babel/cli": "^7.8.4",

"aws-sdk": "^2.1400.0",
"backport": "^5.1.2",
"benchmark": "^2.1.4",

@@ -150,0 +152,0 @@ "bluebird": "^3.7.2",

@@ -87,2 +87,3 @@ # Elastic APM Node.js Agent

- [Release notes](https://www.elastic.co/guide/en/apm/agent/nodejs/current/release-notes.html)
- [Supported Technologies](https://www.elastic.co/guide/en/apm/agent/nodejs/current/supported-technologies.html) describes the supported Node.js versions, which modules (and version ranges) are automatically traced, and other technologies.

@@ -102,5 +103,4 @@ - [Configuring the agent](https://www.elastic.co/guide/en/apm/agent/nodejs/current/configuring-the-agent.html) describes the different ways to configure the APM agent (via options to `apm.start(...)`, environment variables, or other mechanisms).

- The ["main" branch](https://github.com/elastic/apm-agent-nodejs/tree/main) is being used for **4.x releases**.
- The ["3.x" branch](https://github.com/elastic/apm-agent-nodejs/tree/3.x) is being used for **3.x maintenance releases**. The 3.x line will be [supported for 6 months](https://www.elastic.co/support/eol) after the release of v4.0.0.
- The ["3.x" branch](https://github.com/elastic/apm-agent-nodejs/tree/3.x) is being used for **3.x maintenance releases**. The 3.x line will be [supported until 2024-03-07](https://www.elastic.co/support/eol) -- for 6 months after the release of v4.0.0.
## Contributing

@@ -107,0 +107,0 @@

Sorry, the diff of this file is too big to display

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc