UNPKG

apminsight

Version:

monitor nodejs applications

338 lines (304 loc) 9.9 kB
var fs = require("fs"); var path = require("path"); var constants = require("../constants"); var crypto = require("crypto"); const ini = require('ini'); var algorithm = "aes-256-cbc"; //For encryption and decryption const os = require("os"); function isEmpty(string) { return string === undefined || string === null || string === ""; } function isNonEmptyString(str) { return typeof str === "string" && !isEmpty(str) && /\S/.test(str); } function isPositiveNumber(num) { // Use the existing isNumber function to check validity if (!isNumber(num)) { return false; } // If it's a valid number, just check if it's >= 0 return num >= 0; } function isNumber(value) { if (value === null || value === undefined || value === '') { return false; } // If it's already a number, just check for NaN if (typeof value === 'number') { return !isNaN(value); } if (typeof value === 'string') { const trimmed = value.trim(); if (trimmed === '') { return false; } // Match valid integer or float, positive/negative return /^-?\d+(\.\d+)?$/.test(trimmed); } return false; } function isTypeNumber(num) { if (typeof num === "number") { return true; } return false; } function isLetter(str) { return str.length === 1 && str.match(/[a-z]/i) != null; } function isFunction(fn) { return typeof fn === "function"; } function isObject(obj) { return typeof obj === "object"; } function isBoolean(boolean) { return typeof boolean === "boolean"; } function isEmptyObject(obj) { return Object.keys(obj).length === 0; } function convertToString(value) { if (value && typeof value !== "string") { return String(value); } return value; } /*eslint no-empty: "error"*/ function loadInfoFileSync(configInstance) { if (isEmpty(configInstance.getBaseDir())) { return {}; } try { var baseDirectory = configInstance.getBaseDir(); var appDirectoryName = configInstance.getApplicationName() + "_" + configInstance.getApplicationPort(); var appDirectoryPath = path.join(baseDirectory, appDirectoryName); var newFilePath = path.join(appDirectoryPath, "apminsight.json"); if (!fs.existsSync(newFilePath)) { return {}; } return JSON.parse(fs.readFileSync(newFilePath)); } catch (e) { console.error("[APM] Error while reading apminsight.json file: ", e); } return {}; } function createInfoFileFolder() { try { var configDetails = apmInsightAgentInstance.getConfig(); var baseDirectory = configDetails.getBaseDir(); if (isEmpty(baseDirectory)) { console.log("[APM] Base directory is empty, cannot create info file folder"); return; } var appDirectoryName = configDetails.getApplicationName() + "_" + configDetails.getApplicationPort(); var appDirectoryPath = path.join(baseDirectory, appDirectoryName); if (!fs.existsSync(appDirectoryPath)) { fs.mkdir(appDirectoryPath, { recursive: true }, (err) => { if (err) { console.log('[APM] Error creating app directory:', err); return; } }) } } catch (err) { console.error("[APM] Error while creating app directory : ", err); } } function writeStream() { return process.stdout; } function checkAndCreateBaseDir(options) { var agentDataPath; if ( isNonEmptyString(options.logsDir) && isNonEmptyString(options.appName) ) { var dirName = "apminsightdata_" + options.appName + "_" + options.port; agentDataPath = path.join(options.logsDir, dirName); } else if (isNonEmptyString(process.env.APMINSIGHT_AGENT_HOMEPATH)) { // One agent requirement agentDataPath = path.join(process.env.APMINSIGHT_AGENT_HOMEPATH, constants.oneAgentNodeSpecificDir); } else { agentDataPath = path.join(process.cwd(), "apminsightdata"); } try { if (!fs.existsSync(agentDataPath)) { fs.mkdirSync(agentDataPath, { recursive: true }); } } catch (err) { console.error( `[APM] Failed to create logs directory at ${agentDataPath}: ${err.message || err}`, err ); // Fallback: If creation fails, try temporary directory as last resort try { agentDataPath = path.join(os.tmpdir(), "apminsightdata"); if (!fs.existsSync(agentDataPath)) { fs.mkdirSync(agentDataPath, { recursive: true }); } console.log(`[APM] Using temporary directory for agent data: ${agentDataPath}`); } catch (fallbackErr) { console.error(`[APM] Failed to create fallback directory: ${fallbackErr.message || fallbackErr}`); return; } } return agentDataPath; } function getGenericThreshold(txnName) { var threshold; try { if (isNonEmptyString(txnName)) { const genericThreshold = apmInsightAgentInstance.getThreshold(); if (genericThreshold) { const keyTxnList = genericThreshold.getKeyTxnList(); if (keyTxnList && keyTxnList.includes(txnName)) { threshold = apmInsightAgentInstance.getKeyTxnThreshold()[txnName]; if (isEmpty(threshold)) { console.warn(`[APM] threshold object was empty for txnName ${txnName} and assigned with getThreshold`); threshold = apmInsightAgentInstance.getThreshold(); } } else { threshold = apmInsightAgentInstance.getThreshold(); } } } } catch (err) { console.error(`[APM] error while getting genericThreshold ${err}`); threshold = apmInsightAgentInstance.getThreshold(); } if (isEmpty(threshold)) { threshold = apmInsightAgentInstance.getThreshold(); } return threshold; } function checkpm2(pm2Id, options) { var agentDataPath = path.join(options.agentBaseDir, String(pm2Id)); try { if (!fs.existsSync(agentDataPath)) { fs.mkdirSync(agentDataPath, { recursive: true }); } } catch (e) { console.log( "[APM] Error while creating apminsight agent logs in " + agentDataPath ); return; } return agentDataPath; } function isValidLicenseKey(lKey) { if (isEmpty(lKey)) { return false; } else { var licenseKeySplit = lKey.split("_").pop(); if ( licenseKeySplit.length == 64 && lKey.match(constants.appManagerLicenseRegex) ) { return true; } if ( licenseKeySplit.length <= 40 && lKey.match(constants.site24x7LicenseRegex) ) { return true; } return false; } } function toEncryptKey(lKey) { try { // the cipher function var cipher = crypto.createCipheriv( algorithm, constants.securitykey, constants.initVector ); // encrypt the message var encryptedData = cipher.update(lKey, "utf-8", "base64"); encryptedData += cipher.final("base64"); return encryptedData; } catch (err) { return false; } } function toDecryptKey(lKey, securityKey, iV) { try { // the decipher function var decipher = crypto.createDecipheriv( algorithm, securityKey || constants.securitykey, iV || constants.initVector ); // decrypt the message let decryptedData = decipher.update(lKey, "base64", "utf-8"); decryptedData += decipher.final("utf8"); return decryptedData; } catch (err) { return false; } } function fetchAppname(configInstance) { try { var filePath = path.join(process.cwd(), "package.json"); var packageJson = JSON.parse(fs.readFileSync(filePath)); if ((!configInstance.getApplicationName()) && packageJson && packageJson.name) { configInstance.setApplicationName(packageJson.name); } } catch (e) { if (!configInstance.getApplicationName()) { configInstance.setApplicationName(constants.defaultAppName); } } } function parseIniFile(filePath) { if (isEmpty(filePath)) { return null; } try { const fileContent = fs.readFileSync(filePath, 'utf8'); const parsedData = ini.parse(fileContent); return parsedData; } catch (err) { console.error(`[APM] error parsing INI file at ${filePath}: ${err}`); return null; } } function isValidURL(url) { try { new URL(url); // Attempt to parse the URL return true; // If no error, it's valid } catch (err) { return false; // Invalid URL } } module.exports = { isEmpty: isEmpty, isNumber: isNumber, isTypeNumber: isTypeNumber, isPositiveNumber: isPositiveNumber, isNonEmptyString: isNonEmptyString, isLetter: isLetter, isFunction: isFunction, isObject: isObject, isBoolean: isBoolean, loadInfoFileSync: loadInfoFileSync, checkAndCreateBaseDir: checkAndCreateBaseDir, writeStream: writeStream, getGenericThreshold: getGenericThreshold, checkpm2: checkpm2, isValidLicenseKey: isValidLicenseKey, isEmptyObject: isEmptyObject, toEncryptKey: toEncryptKey, toDecryptKey: toDecryptKey, convertToString: convertToString, fetchAppname: fetchAppname, createInfoFileFolder: createInfoFileFolder, parseIniFile: parseIniFile, isValidURL: isValidURL };