ca-apm-probe
Version:
CA APM Node.js Agent monitors real-time health and performance of Node.js applications
229 lines (202 loc) • 6.82 kB
JavaScript
/**
* Copyright (c) 2015 CA. All rights reserved.
*
* This software and all information contained therein is confidential and proprietary and
* shall not be duplicated, used, disclosed or disseminated in any way except as authorized
* by the applicable license agreement, without the express written permission of CA. All
* authorized reproductions must be marked with this language.
*
* EXCEPT AS SET FORTH IN THE APPLICABLE LICENSE AGREEMENT, TO THE EXTENT
* PERMITTED BY APPLICABLE LAW, CA PROVIDES THIS SOFTWARE WITHOUT WARRANTY
* OF ANY KIND, INCLUDING WITHOUT LIMITATION, ANY IMPLIED WARRANTIES OF
* MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT WILL CA BE
* LIABLE TO THE END USER OR ANY THIRD PARTY FOR ANY LOSS OR DAMAGE, DIRECT OR
* INDIRECT, FROM THE USE OF THIS SOFTWARE, INCLUDING WITHOUT LIMITATION, LOST
* PROFITS, BUSINESS INTERRUPTION, GOODWILL, OR LOST DATA, EVEN IF CA IS
* EXPRESSLY ADVISED OF SUCH LOSS OR DAMAGE.
*/
var winston = require('winston');
var fs = require('fs');
var path = require('path');
var config = require('./configdata').getConfigData();
var logFile = config.logging.logFile;
var enableFileMode = config.logging.fileModeLog == "enabled";
var enableConsoleMode = config.logging.consoleModeLog == "enabled";
var maxLogFileSize = (config.logging.maxLogFileSize || 2) * 1024 * 1024; // MB to byte
var maxLogFileCount = config.logging.maxLogFileCount || 5;
var logLevel = config.logging.logLevel || 'info';
var isDebugEnabled = false;
var isVerboseEnabled = false;
var logToConsole = false;
var isDeepStackTraceEnabled = false;
var savedDeepStackTraceLimit = -1;
var probeNameResolver = require('./probename-resolver');
function logConfiguration() {
config = require('./configdata').getConfigData();
if (config.logging) {
var logLevelProp = config.logging.logLevel;
if (logLevelProp.toLowerCase() !== logLevel.toLowerCase()) {
var prevLogLevel = logLevel;
logLevel = logLevelProp.toLowerCase();
if (logger) {
logger.level = logLevel;
logger.info('log level changed %s -> %s', prevLogLevel, logLevel);
}
}
var isDeepStackTraceFlag = (config.logging.deepStackTraceEnabled == undefined) ? false : config.logging.deepStackTraceEnabled;
if (isDeepStackTraceFlag) {
if (!isDeepStackTraceEnabled) {
savedDeepStackTraceLimit = Error.stackTraceLimit;
Error.stackTraceLimit = Infinity;
isDeepStackTraceEnabled = true;
}
}
else {
if (isDeepStackTraceEnabled && Error.stackTraceLimit == Infinity && savedDeepStackTraceLimit != -1) {
Error.stackTraceLimit = savedDeepStackTraceLimit;
}
isDeepStackTraceEnabled = false;
}
enableFileMode = config.logging.fileModeLog == "enabled";
enableConsoleMode = config.logging.consoleModeLog == "enabled";
maxLogFileCount = config.logging.maxLogFileCount || 5;
maxLogFileSize = (config.logging.maxLogFileSize || 2) * 1024 * 1024; // MB to byte
}
if (logLevel === 'debug') {
isDebugEnabled = true;
isVerboseEnabled = true;
}
if (logLevel === 'verbose') {
isVerboseEnabled = true;
}
}
function checkPermissions(){
if(!logger) {
return;
}
try {
var stats = fs.statSync(logFile);
}
catch(err) {
// file does not exist, so no need to check for permissions
return;
}
// logFile has write permission
if (!(stats["mode"] & 200)) {
logger.transports[1].silent = false;
logger.transports[0].silent = true;
logger.info("Log file "+logFile+" does not have write permissions. Hence logging to console");
logToConsole = true;
}
}
function createLogsFolderIfDontExist(){
try{
fs.mkdirSync(path.dirname(logFile));
} catch(e) {
if(e.code == 'EEXIST') {
return;
}
else {
// creation threw other error like access denied or something, so log to console in that case.
logger.transports[1].silent = false;
logger.transports[0].silent = true;
logger.info("Log folder "+path.dirname(logFile)+" cannot be created. Hence logging to console");
logToConsole = true;
}
}
}
function logFromBuffer() {
var buffer = probeNameResolver.getBuffer();
if(buffer) {
var infoArr = buffer.info;
for(var entry in infoArr) {
logger.info(infoArr[entry]);
}
if(logger.isDebug()) {
var debugArr = buffer.debug;
for(var entry in debugArr) {
logger.debug(debugArr[entry]);
}
}
}
}
var transport = new winston.transports.File({
filename: logFile,
handleExceptions: false,
maxsize: maxLogFileSize,
maxFiles: maxLogFileCount,
colorize: false,
silent: !enableFileMode
});
var consoleTransport = new winston.transports.Console({
name: 'console',
silent: !enableConsoleMode,
format: winston.format.combine(
winston.format.colorize({ all : true })
),
});
const customFormat = winston.format.printf(({ timestamp, level, message }) => {
return `${timestamp} - ${level}: ${message}`;
});
var logger = winston.createLogger({
format: winston.format.combine(
winston.format.timestamp({
format: 'YYYY/MM/DD HH:mm:ss:SSSZ'
}),
winston.format.splat(),
customFormat
),
level: logLevel,
transports: [
transport,
consoleTransport
]
});
createLogsFolderIfDontExist();
checkPermissions();
logConfiguration();
console.log("[CA APM PROBE] monitoring application with pid "+ process.pid);
if(!logToConsole && logLevel.toLowerCase() !== 'disabled') {
console.log("[CA APM PROBE] Log file location: " + path.normalize(logFile));
}
logger.isDebug = function(){
return isDebugEnabled;
};
logger.isVerbose = function(){
return isVerboseEnabled;
};
logger.setLabel = function(str) {
transport.label = str;
};
logFromBuffer();
var disableLogger = {
debug: function(){},
verbose: function(){},
info: function(){},
error: function(){},
fatal: function(){},
log: function(){},
warn: function(){},
isDebug: function() { return false; },
isVerbose: function() { return false; },
setLabel: function() {}
};
var wrappedLogger = {
debug: function(){ if (isDebugEnabled) logger.debug.apply(logger, arguments); },
verbose: function(){ if (isVerboseEnabled) logger.verbose.apply(logger, arguments); },
info: function(){ logger.info.apply(logger, arguments); },
error: function(){ logger.error.apply(logger, arguments); },
fatal: function(){ logger.fatal.apply(logger, arguments); },
log: function(){ logger.log.apply(logger, arguments); },
warn: function(){ logger.warn.apply(logger, arguments); },
isDebug: function() { return isDebugEnabled; },
isVerbose: function() { return isVerboseEnabled; },
setLabel: function(str) { logger.setLabel(str); }
};
if (logLevel.toLowerCase() === 'disabled') {
module.exports = disableLogger;
}
else {
module.exports = wrappedLogger;
}
module.exports.logConfiguration = logConfiguration;