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

@instana/shared-metrics

Package Overview
Dependencies
Maintainers
3
Versions
190
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@instana/shared-metrics - npm Package Compare versions

Comparing version 1.130.1 to 1.131.0

src/util/CountDownLatch.js

10

package.json
{
"name": "@instana/shared-metrics",
"version": "1.130.1",
"version": "1.131.0",
"description": "Internal metrics plug-in package for Node.js monitoring with Instana",

@@ -29,3 +29,3 @@ "author": {

"test": "npm run test:mocha",
"test:mocha": "mocha --sort --reporter mocha-multi --reporter-options spec=-,xunit=../../test-results/shared-metris/results.xml $(find test -iname '*test.js')",
"test:mocha": "mocha --sort --reporter mocha-multi --reporter-options spec=-,xunit=../../test-results/shared-metris/results.xml $(find test -iname '*test.js' -not -path '*node_modules*')",
"test:debug": "WITH_STDOUT=true npm run test:mocha",

@@ -63,7 +63,7 @@ "lint": "eslint src test",

"dependencies": {
"@instana/core": "1.130.1",
"@instana/core": "1.131.0",
"detect-libc": "^1.0.3",
"event-loop-lag": "^1.4.0",
"recursive-copy": "^2.0.13",
"tar": "^5.0.7"
"tar": "^5.0.9"
},

@@ -83,3 +83,3 @@ "devDependencies": {

},
"gitHead": "6fe6e2f1d58b616bfb5ef408f13af2febe9ad19a"
"gitHead": "c143ddafc50f8305684638f5abff0ee847830408"
}

@@ -15,2 +15,5 @@ /*

const CountDownLatch = require('./util/CountDownLatch');
const { DependencyDistanceCalculator, MAX_DEPTH } = require('./util/DependencyDistanceCalculator');
/**

@@ -23,7 +26,16 @@ * @param {import('@instana/core/src/logger').GenericLogger} _logger

/** @type {number} */
exports.MAX_DEPENDENCIES = 750;
/** @type {string} */
exports.payloadPrefix = 'dependencies';
/** @type {Object.<string, *>} */
const preliminaryPayload = {};
/** @type {Object.<string, *>} */
exports.currentPayload = {};
const MAX_ATTEMPTS = 20;
exports.MAX_ATTEMPTS = 20;
const DELAY = 1000;

@@ -34,6 +46,8 @@ let attempts = 0;

attempts++;
const started = Date.now();
applicationUnderMonitoring.getMainPackageJsonPathStartingAtMainModule((err, packageJsonPath) => {
if (err) {
return logger.warn('Failed to determine main package.json. Reason: %s %s ', err.message, err.stack);
} else if (!packageJsonPath && attempts < MAX_ATTEMPTS) {
} else if (!packageJsonPath && attempts < exports.MAX_ATTEMPTS) {
logger.debug('Main package.json could not be found. Will try again later.');

@@ -54,3 +68,4 @@ setTimeout(exports.activate, DELAY).unref();

}
addDependenciesFromDir(path.join(nodeModulesFolder));
addAllDependencies(path.join(nodeModulesFolder), started, null);
});

@@ -66,3 +81,3 @@ return;

}
addDependenciesFromDir(dependencyDir);
addAllDependencies(dependencyDir, started, packageJsonPath);
});

@@ -72,35 +87,26 @@ };

/**
* Finds all installed modules in the given dependencyDir (say, /path/to/app/node_modules) and saves the dependency with
* the associated version into preliminaryPayload.
*
* @param {string} dependencyDir
* @param {number} started
* @param {string} packageJsonPath
*/
function addDependenciesFromDir(dependencyDir) {
fs.readdir(dependencyDir, (readDirErr, dependencies) => {
if (readDirErr) {
return logger.warn('Cannot analyse dependencies due to %s', readDirErr.message);
function addAllDependencies(dependencyDir, started, packageJsonPath) {
addDependenciesFromDir(dependencyDir, () => {
if (Object.keys(preliminaryPayload).length <= exports.MAX_DEPENDENCIES) {
exports.currentPayload = preliminaryPayload;
logger.debug(`Collection of dependencies took ${Date.now() - started} ms.`);
return;
}
dependencies
.filter(
(
dependency // exclude the .bin directory
) => dependency !== '.bin'
)
.forEach(dependency => {
if (dependency.indexOf('@') === 0) {
addDependenciesFromDir(path.join(dependencyDir, dependency));
} else {
const fullDirPath = path.join(dependencyDir, dependency);
// Only check directories. For example, yarn adds a .yarn-integrity file to /node_modules/ which we need to
// exclude, otherwise we get a confusing "Failed to identify version of .yarn-integrity dependency due to:
// ENOTDIR: not a directory, open '.../node_modules/.yarn-integrity/package.json'." in the logs.
fs.stat(fullDirPath, (statErr, stats) => {
if (statErr) {
return logger.warn('Cannot analyse dependency %s due to %s', fullDirPath, statErr.message);
}
if (stats.isDirectory()) {
const fullPackageJsonPath = path.join(fullDirPath, 'package.json');
addDependency(dependency, fullPackageJsonPath);
}
});
}
if (packageJsonPath) {
new DependencyDistanceCalculator().calculateDistancesFrom(packageJsonPath, distancesFromRoot => {
logger.debug(`Collection of dependencies took ${Date.now() - started} ms.`);
limitAndSet(distancesFromRoot);
});
} else {
logger.debug(`Collection of dependencies took ${Date.now() - started} ms.`);
limitAndSet();
}
});

@@ -110,6 +116,70 @@ }

/**
* @param {*} dependency
* @param {string} packageJsonPath
* Finds all installed modules in dependencyDir (say, /path/to/app/node_modules) and saves the dependency with the
* associated version into preliminaryPayload.
*
* @param {string} dependencyDir
* @param {() => void} callback
*/
function addDependency(dependency, packageJsonPath) {
function addDependenciesFromDir(dependencyDir, callback) {
fs.readdir(dependencyDir, (readDirErr, dependencies) => {
if (readDirErr || !dependencies) {
logger.warn('Cannot analyse dependencies due to %s', readDirErr.message);
callback();
return;
}
const filteredDependendencies = dependencies.filter(
(
dependency // exclude the .bin directory
) => dependency !== '.bin'
);
if (filteredDependendencies.length === 0) {
callback();
return;
}
// This latch fires once all dependencies of the current directory in the node_modules tree have been analysed.
const countDownLatch = new CountDownLatch(filteredDependendencies.length);
countDownLatch.once('done', () => {
callback();
});
filteredDependendencies.forEach(dependency => {
if (dependency.indexOf('@') === 0) {
addDependenciesFromDir(path.join(dependencyDir, dependency), () => {
countDownLatch.countDown();
});
} else {
const fullDirPath = path.join(dependencyDir, dependency);
// Only check directories. For example, yarn adds a .yarn-integrity file to /node_modules/ which we need to
// exclude, otherwise we get a confusing "Failed to identify version of .yarn-integrity dependency due to:
// ENOTDIR: not a directory, open '.../node_modules/.yarn-integrity/package.json'." in the logs.
fs.stat(fullDirPath, (statErr, stats) => {
if (statErr) {
countDownLatch.countDown();
logger.warn('Cannot analyse dependency %s due to %s', fullDirPath, statErr.message);
return;
}
if (!stats.isDirectory()) {
countDownLatch.countDown();
return;
}
addDependency(dependency, fullDirPath, countDownLatch);
});
}
});
});
}
/**
* Parses the package.json file in the given directory and then adds the given dependency (with its version) to
* preliminaryPayload.
*
* @param {string} dependency
* @param {string} dependencyDirPath
* @param {import('./util/CountDownLatch')} countDownLatch
*/
function addDependency(dependency, dependencyDirPath, countDownLatch) {
const packageJsonPath = path.join(dependencyDirPath, 'package.json');
fs.readFile(packageJsonPath, { encoding: 'utf8' }, (err, contents) => {

@@ -119,5 +189,8 @@ if (err && err.code === 'ENOENT') {

// We can simply ignore this.
return logger.debug(`No package.json at ${packageJsonPath}, ignoring this directory.`);
countDownLatch.countDown();
logger.debug(`No package.json at ${packageJsonPath}, ignoring this directory.`);
return;
} else if (err) {
return logger.info(
countDownLatch.countDown();
logger.info(
'Failed to identify version of %s dependency due to: %s. This means that you will not be ' +

@@ -128,8 +201,11 @@ 'able to see details about this dependency within Instana.',

);
return;
}
try {
const pckg = JSON.parse(contents);
exports.currentPayload[pckg.name] = pckg.version;
} catch (subErr) {
const parsedPackageJson = JSON.parse(contents);
if (!preliminaryPayload[parsedPackageJson.name]) {
preliminaryPayload[parsedPackageJson.name] = parsedPackageJson.version;
}
} catch (parseErr) {
return logger.info(

@@ -139,6 +215,67 @@ 'Failed to identify version of %s dependency due to: %s. This means that you will not be ' +

dependency,
subErr.message
parseErr.message
);
}
const potentialNestedNodeModulesFolder = path.join(dependencyDirPath, 'node_modules');
fs.stat(potentialNestedNodeModulesFolder, (statErr, stats) => {
if (statErr || !stats.isDirectory()) {
countDownLatch.countDown();
return;
}
addDependenciesFromDir(potentialNestedNodeModulesFolder, () => {
countDownLatch.countDown();
});
});
});
}
/**
* Limits the collected dependencies to exports.MAX_DEPENDENCIES entries and commits them to exports.currentPayload.
*
* @param {Object<string, any>} distances
*/
function limitAndSet(distances = {}) {
const keys = Object.keys(preliminaryPayload);
keys.sort(sortByDistance.bind(null, distances));
// After sorting, the most distant (and therefore, most uninteresting) packages are a the start of the array. For
// packages with the same distance, we sort in a reverse lexicographic order. That means, that if no distances are
// available at all, packages will be in reverse lexicographical order.
//
// At any rate, we start deleting collected depenencies from the payload at index 0, that is, we either remove the
// most distant ones or the ones that are at the end of the lexicographic order.
for (let i = 0; i < keys.length - exports.MAX_DEPENDENCIES; i++) {
delete preliminaryPayload[keys[i]];
}
exports.currentPayload = preliminaryPayload;
}
/**
* Compares the given dependencies by their distance.
*
* @param {Object<string, any>} distances
* @param {string} dependency1
* @param {string} dependency2
*/
function sortByDistance(distances, dependency1, dependency2) {
// To make troubleshooting easier, we always want to include the Instana dependencies, therefore they will be sorted
// to the end of the array.
const isInstana1 = dependency1.indexOf('instana') >= 0;
const isInstana2 = dependency2.indexOf('instana') >= 0;
if (isInstana1 && isInstana2) {
return dependency2.localeCompare(dependency1);
} else if (isInstana1) {
return 1;
} else if (isInstana2) {
return -1;
}
const d1 = distances[dependency1] || MAX_DEPTH + 1;
const d2 = distances[dependency2] || MAX_DEPTH + 1;
if (d1 === d2) {
// for the same distance, sort lexicographically
return dependency2.localeCompare(dependency1);
}
return d2 - d1;
}

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

function addDirectDependenciesFromMainPackageJson(packageJsonPath) {
const started = Date.now();
fs.readFile(packageJsonPath, { encoding: 'utf8' }, (err, contents) => {

@@ -71,3 +72,5 @@ if (err) {

exports.currentPayload[pckg.name] = pckg.version;
logger.debug(`Collection of direct dependencies took ${Date.now() - started} ms.`);
} catch (subErr) {
logger.debug(`Collection of direct dependencies took ${Date.now() - started} ms.`);
return logger.debug('Failed to parse package.json %s dependency due to: %s', packageJsonPath, subErr.message);

@@ -74,0 +77,0 @@ }

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