apminsight
Version:
monitor nodejs applications
288 lines (264 loc) • 7.05 kB
JavaScript
var fs = require("fs");
var path = require("path");
var utils = require("./utils");
var constants = require("./../constants");
var cluster = require("cluster");
var writeStream, fd, logsDir, bytesWritten, baseDir;
var newLine = "\n",
space = " ",
emptyStr = "",
underScore = "_";
var maxSize = 10 * 1024 * 1024; // 10 MB
var retentionDays = 10;
var levels = {
DEBUG: 5,
INFO: 4,
WARNING: 3,
CRITICAL: 2,
ERROR: 1,
OFF: 0
};
function init(configInstance) {
const dir = configInstance && configInstance.getBaseDir();
if (utils.isEmpty(dir)) {
console.error("[APM] Base directory is not set in the configuration.");
writeStream = process.stdout;
return;
}
utils.fetchAppname(configInstance);
var appName = configInstance.getApplicationName();
baseDir = dir;
var date = new Date();
var month = date.getMonth() + 1;
var dateStr =
date.getDate() +
underScore +
month +
underScore +
date.getFullYear() +
underScore +
date.getHours() +
underScore +
date.getMinutes() +
underScore +
date.getSeconds() +
underScore +
date.getMilliseconds() +
underScore +
process.pid +
underScore +
appName;
try {
logsDir = path.join(baseDir, "logs");
if (!fs.existsSync(logsDir)) {
try {
fs.mkdirSync(logsDir);
} catch (dirErr) {
console.error(`[APM] Failed to create logs directory: ${dirErr.message}`, dirErr);
writeStream = process.stdout;
return;
}
}
cleanLogFiles();
var filePath = path.join(
logsDir,
"apminsight_agent_logs_" + dateStr + ".log"
);
try {
fd = fs.openSync(filePath, "a");
if (writeStream) {
try {
writeStream.end();
} catch (streamEndErr) {
console.error(`[APM] Failed to close previous write stream: ${streamEndErr.message}`, streamEndErr);
}
}
writeStream = fs.createWriteStream(null, { flags: "a", fd: fd });
writeStream.on("error", handleStreamError);
bytesWritten = 0;
} catch (fileErr) {
console.error(`[APM] Failed to open log file: ${fileErr.message}`, fileErr);
writeStream = process.stdout;
}
} catch (err) {
console.error(
`[APM] Failed to create apminsight agent logs at ${filePath || 'unknown path'}:`,
err
);
}
//scheduleLogFileSwapping();
}
/* eslint-disable no-unused-vars */
function scheduleLogFileSwapping() {
var now = new Date();
var night = new Date(
now.getFullYear(),
now.getMonth(),
now.getDate() + 1,
0,
0,
30
);
var msToMidnight = night.getTime() - now.getTime();
setTimeout(function () {
if (!global.apmInsightAgentInstance) {
console.error("[APM] schedule log file swap max size exceeded and no agent instance available to reinitialize.");
return;
}
init(global.apmInsightAgentInstance.getConfig());
}, msToMidnight).unref();
}
function cleanLogFiles() {
if (!cluster.isMaster) {
return;
}
fs.readdir(logsDir, function (err, files) {
if (err) {
return;
}
var now = new Date();
now.setDate(now.getDate() - retentionDays);
var retentionTime = now.getTime();
files.forEach(function (file, index) {
checkAndRemoveFile(path.join(logsDir, file), retentionTime);
});
});
}
/* eslint-enable no-unused-vars */
function checkAndRemoveFile(filePath, retentionTime) {
fs.stat(filePath, function (err, stat) {
if (err) {
return;
}
if (stat.mtime.getTime() < retentionTime) {
removeFile(filePath);
}
});
}
function removeFile(filePath) {
fs.unlink(filePath, function (err) {
if (err) {
return;
}
});
log(constants.info, "old log files removed properly");
}
function error(message, e) {
write(constants.error, message, getStackTrace, e);
}
function logAndThrowError(level, message, obj) {
log(level, message, obj);
throw new Error(message);
}
function debug(message, obj) {
log(constants.debug, message, obj);
}
function info(message, obj) {
log(constants.info, message, obj);
}
function critical(message, obj) {
log(constants.critical, message, obj);
}
function warning(message, obj) {
log(constants.warning, message, obj);
}
function log(level, message, obj) {
write(level, message, stringify, obj);
}
/* eslint-disable no-unused-vars */
function handleStreamError(error) {
//need to handle error
}
/* eslint-enable no-unused-vars */
function write(level, message, toStr, obj) {
if (!writeStream) {
console.error("[APM] WriteStream is not initialized.");
return;
}
if (!isAllowed(levels[level])) {
return;
}
if (bytesWritten > maxSize) {
if (!global.apmInsightAgentInstance) {
console.error("[APM] Write max size exceeded and no agent instance available to reinitialize.");
return;
}
init(global.apmInsightAgentInstance.getConfig());
}
var writeStr =
getTime() +
space +
"[" +
level +
"]" +
space +
message +
space +
toStr(obj) +
newLine;
bytesWritten += Buffer.byteLength(writeStr);
writeStream.write(writeStr);
}
function isAllowed(level) {
if (level <= getLogConf()) {
return true;
}
return false;
}
function getLogConf() {
if (!global.apmInsightAgentInstance) {
return levels.DEBUG;
}
if (levels[utils.getGenericThreshold().getLogLevel()]) {
return levels[utils.getGenericThreshold().getLogLevel()];
}
return levels.DEBUG;
}
function getTime() {
var date = new Date();
var month = date.getMonth() + 1;
return (
"[" +
date.getDate() +
"/" +
month +
"/" +
date.getFullYear() +
space +
date.getHours() +
":" +
date.getMinutes() +
":" +
date.getSeconds() +
"]"
);
}
function getStackTrace(e) {
try {
if (utils.isEmpty(e)) {
return emptyStr;
}
return e.stack;
} catch (e) {
return emptyStr;
}
}
function stringify(obj) {
try {
if (utils.isEmpty(obj)) {
return emptyStr;
}
return JSON.stringify(obj);
} catch (e) {
return emptyStr;
}
}
module.exports = {
init: init,
debug: debug,
info: info,
warning: warning,
critical: critical,
error: error,
logAndThrowError: logAndThrowError
};