cf-nodejs-logging-support
Advanced tools
Comparing version 2.2.3 to 3.0.0
var util = require('util'); | ||
var os = require('os'); | ||
var uuid = require('uuid/v4'); | ||
var jwt = require('jsonwebtoken'); | ||
const envDynLogHeader = "DYN_LOG_HEADER"; | ||
const envDynLogKey = "DYN_LOG_LEVEL_KEY"; | ||
const dynLogLevelDefaultHeader = "SAP-LOG-LEVEL" | ||
const reductedPlaceholder = "reducted" | ||
const nsPerSec = 1e9; | ||
@@ -17,3 +24,3 @@ const logType = "log"; | ||
var fixedValues = {}; | ||
var initDummy = null; | ||
var initDummy = "{}"; | ||
var logLevelInt = 2; | ||
@@ -25,3 +32,93 @@ var pattern = null; | ||
var preLogConfig = []; | ||
var postLogConfig = []; | ||
var dynLogLevelHeader = dynLogLevelDefaultHeader; | ||
// Initializes the core logger, including setup of environment var defined settings | ||
var init = function() { | ||
// Read dyn. log level header name from environment var | ||
var headerName = process.env[envDynLogHeader]; | ||
if(headerName != null && headerName != "") { | ||
dynLogLevelHeader = headerName; | ||
} else { | ||
dynLogLevelHeader = dynLogLevelDefaultHeader; | ||
} | ||
// Read dyn log level key from environemt var. | ||
dynLogLevelKey = process.env[envDynLogKey]; | ||
} | ||
var setConfig = function (config) { | ||
precompileConfig(config); | ||
} | ||
var precompileConfig = function (config) { | ||
var coreConfig = []; | ||
preLogConfig = []; | ||
postLogConfig = []; | ||
for (var i = 0; i < config.length; i++) { | ||
var obj = config[i]; | ||
// Check if config field needs a set env var to be enabled. If specified env var does not exist, the resulting log field will be replaced by reductedPlaceholder | ||
if(obj.envVarSwitch != null) { | ||
var val = process.env[obj.envVarSwitch]; | ||
var pass = (val == "true" || val == "True" || val == "TRUE"); | ||
if(!pass) { | ||
// Uncomment to enable log field reduction (currently breaking test cases) | ||
obj.reduce = true; | ||
} | ||
} | ||
if (obj.core) { | ||
coreConfig.push(obj); | ||
} else if (obj.source.type == "time") { | ||
preLogConfig.push(obj); | ||
postLogConfig.push(obj); | ||
} else if ((obj.source.parent != null && obj.source.parent == "res")) { | ||
postLogConfig.push(obj); | ||
} else { | ||
preLogConfig.push(obj); | ||
} | ||
} | ||
var logObject = prepareInitDummy(coreConfig); | ||
initDummy = JSON.stringify(logObject); | ||
} | ||
var getPreLogConfig = function () { | ||
return preLogConfig; | ||
} | ||
var getPostLogConfig = function () { | ||
return postLogConfig; | ||
} | ||
var handleConfigDefaults = function (configEntry, logObject, fallbacks) { | ||
if (configEntry.mandatory && logObject[configEntry.name] == null) { | ||
if (configEntry.default != null) { | ||
logObject[configEntry.name] = configEntry.default; | ||
} else { | ||
fallbacks[configEntry.name] = configEntry.fallback; | ||
} | ||
} | ||
} | ||
// Replace all fields, which are marked to be reduced and do not equal to their default value, empty or "-", to reductedPlaceholder. | ||
var reduceFields = function(config, logObject) { | ||
for(var i = 0; i < config.length; i++) { | ||
var configEntry = config[i]; | ||
if(configEntry.reduce) { | ||
var value = logObject[configEntry.name]; | ||
var defaultValue = configEntry.default != null ? configEntry.default : "-"; | ||
if(value == null || value == "" || value == defaultValue) { | ||
continue; | ||
} | ||
logObject[configEntry.name] = reductedPlaceholder; | ||
} | ||
} | ||
} | ||
// Stringify and log given object to console. If a custom pattern is set, the referenced object fields are used to replace the references. | ||
@@ -35,2 +132,3 @@ var writeLogToConsole = function (logObject) { | ||
var value; | ||
//iterates over split custom pattern, where n%3=0 is text outside the marked fields and n%3=2 are the fields to be replaced (inside {{}}), n elem rest. | ||
for (i = 0; i < (rest.length - 1) / 3; i++) { | ||
@@ -78,9 +176,3 @@ output += rest[i * 3]; | ||
var time = process.hrtime(); | ||
var logObject = {}; | ||
if (initDummy == null) { | ||
logObject = prepareInitDummy(); | ||
initDummy = JSON.stringify(logObject); | ||
} else { | ||
logObject = JSON.parse(initDummy); | ||
} | ||
var logObject = JSON.parse(initDummy); | ||
@@ -94,34 +186,108 @@ logObject.written_at = (new Date()).toJSON(); | ||
var prepareInitDummy = function () { | ||
var prepareInitDummy = function (coreConfig) { | ||
var obj = {}; | ||
var vcapEnvironment = ("VCAP_APPLICATION" in process.env) ? JSON.parse(process.env.VCAP_APPLICATION) : {}; | ||
obj.component_type = "application"; | ||
obj.component_id = !("application_id" in vcapEnvironment) ? "-" : vcapEnvironment.application_id; | ||
obj.component_name = !("application_name" in vcapEnvironment) ? "-" : vcapEnvironment.application_name; | ||
obj.component_instance = !("instance_index" in vcapEnvironment) ? "0" : vcapEnvironment.instance_index.toString(); | ||
obj.source_instance = obj.component_instance; | ||
obj.layer = "[NODEJS]"; | ||
var fallbacks = []; | ||
var selfReferences = []; | ||
var configEntry; | ||
obj.organisation_id = "-"; | ||
obj.organisation_name = "-"; | ||
for (var i = 0; i < coreConfig.length; i++) { | ||
configEntry = coreConfig[i]; | ||
switch (configEntry.source.type) { | ||
case "env": | ||
obj[configEntry.name] = process.env[configEntry.source.name]; | ||
break; | ||
case "nested-env": | ||
obj[configEntry.name] = resolveNestedVariable(process.env, configEntry.source.path); | ||
break; | ||
case "static": | ||
obj[configEntry.name] = configEntry.source.value; | ||
break; | ||
case "self": | ||
selfReferences[configEntry.name] = configEntry.source.name; | ||
break; | ||
} | ||
handleConfigDefaults(configEntry, obj, fallbacks); | ||
} | ||
obj.space_name = !("space_name" in vcapEnvironment) ? "-" : vcapEnvironment.space_name; | ||
obj.space_id = !("space_id" in vcapEnvironment) ? "-" : vcapEnvironment.space_id; | ||
for (var key in fallbacks) { | ||
obj[key] = fallbacks[key](req, res, obj); | ||
} | ||
obj.container_id = !("CF_INSTANCE_IP" in process.env) ? "-" : process.env.CF_INSTANCE_IP; | ||
for (var key in selfReferences) { | ||
obj[key] = obj[selfReferences[key]]; | ||
} | ||
obj.logger = "nodejs-logger"; | ||
reduceFields(coreConfig, obj); | ||
// obj.component_type = "application"; | ||
// obj.component_id = !("application_id" in vcapEnvironment) ? "-" : vcapEnvironment.application_id; | ||
//obj.component_name = !("application_name" in vcapEnvironment) ? "-" : vcapEnvironment.application_name; | ||
//obj.component_instance = !("instance_index" in vcapEnvironment) ? "0" : vcapEnvironment.instance_index.toString(); | ||
//obj.source_instance = obj.component_instance; | ||
//obj.layer = "[NODEJS]"; | ||
//obj.organisation_id = "-"; | ||
//obj.organisation_name = "-"; | ||
//obj.space_name = !("space_name" in vcapEnvironment) ? "-" : vcapEnvironment.space_name; | ||
//obj.space_id = !("space_id" in vcapEnvironment) ? "-" : vcapEnvironment.space_id; | ||
//obj.container_id = !("CF_INSTANCE_IP" in process.env) ? "-" : process.env.CF_INSTANCE_IP; | ||
//obj.logger = "nodejs-logger"; | ||
return obj; | ||
}; | ||
// Resolves a path to a variable in a structure of objects to its value. Parts of the object hierarchy that are represented as strings will be parsed. | ||
var resolveNestedVariable = function (root, path) { | ||
// return, if path is empty. | ||
if(path == null || path.length == 0) { | ||
return null; | ||
} | ||
var rootObj; | ||
// if root is a string => parse it to an object. Otherwise => use it directly as object. | ||
if (typeof root === 'string') { | ||
rootObj = JSON.parse(root); | ||
} else if (typeof root === 'object') { | ||
rootObj = root; | ||
} else { | ||
return null; | ||
} | ||
// get value from root object | ||
var value = rootObj[path[0]]; | ||
// cut first entry of the object path | ||
path.shift(); | ||
// if the path is not empty, recursively resolve the remaining waypoints. | ||
if(path.length >= 1) { | ||
return resolveNestedVariable(value, path); | ||
} | ||
// return the resolved value, if path is empty. | ||
return value; | ||
} | ||
// Writes the given log file to stdout | ||
var sendLog = function (level, logObject) { | ||
var sendLog = function (level, logObject, dynamicLogLevel) { | ||
//Attach level to logobject | ||
logObject.level = level; | ||
// Write log to console to be parsed by logstash | ||
//winstonLogger.log(level, '', logObject); | ||
if (logLevelInt >= loggingLevels[level]) { | ||
var threshold; | ||
if(dynamicLogLevel != null) { | ||
threshold = dynamicLogLevel; // use dynamic log level | ||
} else { | ||
threshold = logLevelInt; // use global log level | ||
} | ||
// Write log to console | ||
if (threshold >= loggingLevels[level]) { | ||
writeLogToConsole(logObject); | ||
@@ -154,6 +320,13 @@ } | ||
var dynamicLogLevel = this.dynamicLogLevel; | ||
var level = args[0]; | ||
if (logLevelInt < loggingLevels[level]) { | ||
if (dynamicLogLevel != null) { // check if dynamic log level is setup | ||
if (dynamicLogLevel < loggingLevels[level]) { | ||
return false; | ||
} | ||
} else if (logLevelInt < loggingLevels[level]) { | ||
return false; | ||
} | ||
var customFields = null; | ||
@@ -195,3 +368,3 @@ | ||
sendLog(level, logObject); | ||
sendLog(level, logObject, dynamicLogLevel); | ||
return true; | ||
@@ -275,4 +448,36 @@ }; | ||
// Get the name of the dynamic log level header | ||
var getDynLogLevelHeaderName = function() { | ||
return dynLogLevelHeader; | ||
} | ||
// Get the dynamic logging level from the given JWT. | ||
var getLogLevelFromJWT = function(token) { | ||
var level; | ||
var payload = verifyAndDecodeJWT(token, dynLogLevelKey); | ||
if(payload == null) { | ||
return null; | ||
} | ||
return loggingLevels[payload.level]; | ||
} | ||
// Verifies the given JWT and returns its payload. | ||
var verifyAndDecodeJWT = function(token, key) { | ||
if(key == null || token == null) { | ||
return null; // no public key or jwt provided | ||
} | ||
try { | ||
return jwt.verify(token, key); | ||
} catch(err) { | ||
return null; // token not verified | ||
} | ||
} | ||
exports.init = init; | ||
exports.overrideField = overrideField; | ||
exports.writeStaticFields = writeStaticFields; | ||
exports.reduceFields = reduceFields; | ||
exports.setLoggingLevel = setLoggingLevel; | ||
@@ -286,2 +491,8 @@ exports.getLoggingLevel = getLoggingLevel; | ||
exports.bindLogFunctions = bindLogFunctions; | ||
exports.getCorrelationObject = getCorrelationObject; | ||
exports.getCorrelationObject = getCorrelationObject; | ||
exports.setConfig = setConfig; | ||
exports.getPostLogConfig = getPostLogConfig; | ||
exports.getPreLogConfig = getPreLogConfig; | ||
exports.handleConfigDefaults = handleConfigDefaults; | ||
exports.getDynLogLevelHeaderName = getDynLogLevelHeaderName; | ||
exports.getLogLevelFromJWT = getLogLevelFromJWT; |
@@ -11,2 +11,6 @@ // Log network activity for express applications | ||
var setConfig = function (config) { | ||
core.setConfig(config); | ||
} | ||
// Set the minimum logging level. Messages with a lower level, will not be forwarded. (Levels: error, warn, info, verbose, debug, silly) | ||
@@ -35,2 +39,6 @@ var setLoggingLevel = function (level) { | ||
} | ||
if (req.url == null) { | ||
req.url = req.originalUrl; | ||
} | ||
if (res.get == null) { | ||
@@ -42,36 +50,58 @@ res.get = function () { | ||
if (req.header("X-CorrelationID") != null) { | ||
logObject.correlation_id = req.header("X-CorrelationID"); | ||
} else if (req.header("x-vcap-request-id") != null) { | ||
logObject.correlation_id = req.header("x-vcap-request-id"); | ||
var token = req.header(core.getDynLogLevelHeaderName()); | ||
if(token != null) { | ||
req.dynamicLogLevel = core.getLogLevelFromJWT(token); | ||
} else { | ||
logObject.correlation_id = uuid(); | ||
req.dynamicLogLevel = null; | ||
} | ||
var fallbacks = []; | ||
var selfReferences = []; | ||
var configEntry; | ||
var preConfig = core.getPreLogConfig(); | ||
for (var i = 0; i < preConfig.length; i++) { | ||
configEntry = preConfig[i]; | ||
logObject.request_id = req.header("x-vcap-request-id") == null ? "-" : req.header("x-vcap-request-id"); | ||
logObject.type = "request"; | ||
logObject.request = req.originalUrl == null ? "-" : req.originalUrl; | ||
logObject.referer = "-"; | ||
logObject.response_status = -1; // Set later | ||
logObject.method = req.method == null ? "-" : req.method; | ||
logObject.response_size_b = -1; // Set later | ||
logObject.request_size_b = req.header("content-length") == null ? -1 : req.header("content-length"); | ||
logObject.remote_host = req.connection.remoteAddress == null ? "-" : req.connection.remoteAddress; | ||
logObject.remote_port = req.connection.remotePort == null ? "-" : req.connection.remotePort.toString(); | ||
logObject.remote_user = "-"; | ||
logObject.x_forwarded_for = req.headers['x-forwarded-for'] == null ? "" : req.headers['x-forwarded-for']; | ||
logObject.protocol = "HTTP" + (req.httpVersion == null ? "" : "/" + req.httpVersion); | ||
logObject.remote_ip = logObject.remote_host; | ||
logObject.response_content_type = "-1"; //set later | ||
logObject.request_received_at = logObject.written_at; | ||
logObject.response_time_ms = -1; // Set later | ||
logObject.direction = "IN"; | ||
switch (configEntry.source.type) { | ||
case "header": | ||
logObject[configEntry.name] = req.header(configEntry.source.name); | ||
break; | ||
case "static": | ||
logObject[configEntry.name] = configEntry.source.value; | ||
break; | ||
case "field": | ||
logObject[configEntry.name] = req[configEntry.source.name]; | ||
break; | ||
case "self": | ||
selfReferences[configEntry.name] = configEntry.source.name; | ||
break; | ||
case "time": | ||
if (configEntry.source.pre != null) | ||
logObject[configEntry.name] = configEntry.source.pre(req, res, logObject); | ||
else | ||
logObject[configEntry.name] = -1 //defaulting for time fields | ||
break; | ||
case "special": | ||
fallbacks[configEntry.name] = configEntry.fallback; | ||
break; | ||
} | ||
core.handleConfigDefaults(configEntry, logObject, fallbacks); | ||
} | ||
for (var key in fallbacks) { | ||
logObject[key] = fallbacks[key](req, res, logObject); | ||
} | ||
for (var key in selfReferences) { | ||
logObject[key] = logObject[selfReferences[key]]; | ||
} | ||
// Replace all set fields, which are marked to be reduced, with a placeholder (defined in log-core.js) | ||
core.reduceFields(preConfig, logObject); | ||
req.logObject = logObject; | ||
core.bindLogFunctions(req); | ||
var start = Date.now(); | ||
res.on('finish', function () { | ||
@@ -87,12 +117,47 @@ finishLog(); | ||
if (!logSent) { | ||
var timeObj = new Date(); | ||
logObject.response_sent_at = timeObj.toJSON(); | ||
logObject.response_time_ms = timeObj.getTime() - start; | ||
logObject.response_size_b = res.get("content-length") == null ? -1 : res.get("content-length"); | ||
logObject.response_content_type = res.get("content-type") == null ? "-" : res.get("content-type"); | ||
logObject.response_status = res.statusCode; | ||
var postConfig = core.getPostLogConfig(); | ||
var fallbacks = []; | ||
var selfReferences = []; | ||
for (var i = 0; i < postConfig.length; i++) { | ||
configEntry = postConfig[i]; | ||
switch (configEntry.source.type) { | ||
case "header": | ||
logObject[configEntry.name] = res.get(configEntry.source.name); | ||
break; | ||
case "field": | ||
logObject[configEntry.name] = res[configEntry.source.name]; | ||
break; | ||
case "self": | ||
selfReferences[configEntry.name] = configEntry.source.name; | ||
break; | ||
case "time": | ||
if (configEntry.source.post != null) | ||
logObject[configEntry.name] = configEntry.source.post(req, res, logObject); | ||
break; | ||
case "special": | ||
fallbacks[configEntry.name] = configEntry.fallback; | ||
break; | ||
} | ||
core.handleConfigDefaults(configEntry, logObject, fallbacks); | ||
} | ||
for (var key in fallbacks) { | ||
logObject[key] = fallbacks[key](req, res, logObject); | ||
} | ||
for (var key in selfReferences) { | ||
logObject[key] = logObject[selfReferences[key]]; | ||
} | ||
//override values with predefined values | ||
core.writeStaticFields(logObject); | ||
core.sendLog('info', logObject); | ||
// Replace all set fields, which are marked to be reduced, with a placeholder (defined in log-core.js) | ||
core.reduceFields(postConfig, logObject); | ||
core.sendLog('info', logObject, req.dynamicLogLevel); | ||
logSent = true; | ||
@@ -115,3 +180,3 @@ } | ||
// Provides a context object, which allows message logging and uses correlationId from its parent request. | ||
var getCorrelationObject = function() { | ||
var getCorrelationObject = function () { | ||
return core.getCorrelationObject(); | ||
@@ -132,1 +197,2 @@ } | ||
exports.overrideField = overrideField; | ||
exports.setConfig = setConfig; |
@@ -11,2 +11,6 @@ // Log network activity for express applications | ||
var setConfig = function (config) { | ||
core.setConfig(config); | ||
} | ||
// Set the minimum logging level. Messages with a lower level, will not be forwarded. (Levels: error, warn, info, verbose, debug, silly) | ||
@@ -31,29 +35,56 @@ var setLoggingLevel = function (level) { | ||
if (req.headers["X-CorrelationID"] != null) { | ||
logObject.correlation_id = req.headers["X-CorrelationID"]; | ||
} else if (req.headers["x-vcap-request-id"] != null) { | ||
logObject.correlation_id = req.headers["x-vcap-request-id"]; | ||
var token = req.headers[core.getDynLogLevelHeaderName()]; | ||
if (token != null) { | ||
req.dynamicLogLevel = core.getLogLevelFromJWT(token); | ||
} else { | ||
logObject.correlation_id = uuid(); | ||
req.dynamicLogLevel = null; | ||
} | ||
logObject.request_id = req.headers["x-vcap-request-id"] == null ? "-" : req.headers["x-vcap-request-id"]; | ||
logObject.type = "request"; | ||
logObject.request = req.url == null ? "-" : req.url; | ||
logObject.referer = req.headers.referer == null ? "-" : req.headers.referer; | ||
logObject.response_status = -1; // Set later | ||
logObject.method = req.method == null ? "-" : req.method; | ||
logObject.response_size_b = -1; // Set later | ||
logObject.request_size_b = req.headers["content-length"] == null ? -1 : req.headers["content-length"]; | ||
logObject.remote_host = req.connection.remoteAddress == null ? "-" : req.connection.remoteAddress; | ||
logObject.remote_port = req.connection.remotePort == null ? "-" : req.connection.remotePort.toString(); | ||
logObject.remote_user = "-"; | ||
logObject.x_forwarded_for = req.headers['x-forwarded-for'] == null ? "" : req.headers['x-forwarded-for']; | ||
logObject.protocol = "HTTP" + (req.httpVersion == null ? "" : "/" + req.httpVersion); | ||
logObject.remote_ip = logObject.remote_host; | ||
logObject.response_content_type = "-1"; //set later | ||
logObject.request_received_at = logObject.written_at; | ||
logObject.response_time_ms = -1; // Set later | ||
logObject.direction = "IN"; | ||
var fallbacks = []; | ||
var selfReferences = []; | ||
var configEntry; | ||
var preConfig = core.getPreLogConfig(); | ||
for (var i = 0; i < preConfig.length; i++) { | ||
configEntry = preConfig[i]; | ||
switch (configEntry.source.type) { | ||
case "header": | ||
logObject[configEntry.name] = req.headers[configEntry.source.name]; | ||
break; | ||
case "static": | ||
logObject[configEntry.name] = configEntry.source.value; | ||
break; | ||
case "field": | ||
logObject[configEntry.name] = req[configEntry.source.name]; | ||
break; | ||
case "self": | ||
selfReferences[configEntry.name] = configEntry.source.name; | ||
break; | ||
case "time": | ||
if (configEntry.source.pre != null) | ||
logObject[configEntry.name] = configEntry.source.pre(req, res, logObject); | ||
else | ||
logObject[configEntry.name] = -1 //defaulting for time fields | ||
break; | ||
case "special": | ||
fallbacks[configEntry.name] = configEntry.fallback; | ||
break; | ||
} | ||
core.handleConfigDefaults(configEntry, logObject, fallbacks); | ||
} | ||
for (var key in fallbacks) { | ||
logObject[key] = fallbacks[key](req, res, logObject); | ||
} | ||
for (var key in selfReferences) { | ||
logObject[key] = logObject[selfReferences[key]]; | ||
} | ||
// Replace all set fields, which are marked to be reduced, with a placeholder (defined in log-core.js) | ||
core.reduceFields(preConfig, logObject); | ||
req.logObject = logObject; | ||
@@ -75,11 +106,45 @@ | ||
if (!logSent) { | ||
var dateObj = new Date(); | ||
logObject.response_time_ms = dateObj.getTime() - start; | ||
logObject.response_sent_at = dateObj.toJSON(); | ||
logObject.response_size_b = (res._headers == null || res._headers["content-length"] == null) ? -1 : res._headers["content-length"]; | ||
logObject.response_content_type = (res._headers == null || res._headers["content-type"] == null) ? "-" : res._headers["content-type"]; | ||
logObject.response_status = res.statusCode; | ||
var postConfig = core.getPostLogConfig(); | ||
var fallbacks = []; | ||
var selfReferences = []; | ||
for (var i = 0; i < postConfig.length; i++) { | ||
configEntry = postConfig[i]; | ||
switch (configEntry.source.type) { | ||
case "header": | ||
if(res._headers) | ||
logObject[configEntry.name] = res._headers[configEntry.source.name]; | ||
break; | ||
case "field": | ||
logObject[configEntry.name] = res[configEntry.source.name]; | ||
break; | ||
case "self": | ||
selfReferences[configEntry.name] = configEntry.source.name; | ||
break; | ||
case "time": | ||
if (configEntry.source.post != null) | ||
logObject[configEntry.name] = configEntry.source.post(req, res, logObject); | ||
break; | ||
case "special": | ||
fallbacks[configEntry.name] = configEntry.fallback; | ||
break; | ||
} | ||
core.handleConfigDefaults(configEntry, logObject, fallbacks); | ||
} | ||
for (var key in fallbacks) { | ||
logObject[key] = fallbacks[key](req, res, logObject); | ||
} | ||
for (var key in selfReferences) { | ||
logObject[key] = logObject[selfReferences[key]]; | ||
} | ||
//override values with predefined values | ||
core.writeStaticFields(logObject); | ||
core.sendLog('info', logObject); | ||
// Replace all set fields, which are marked to be reduced, with a placeholder (defined in log-core.js) | ||
core.reduceFields(postConfig, logObject); | ||
core.sendLog('info', logObject, req.dynamicLogLevel); | ||
logSent = true; | ||
@@ -117,2 +182,3 @@ } | ||
exports.getCorrelationObject = getCorrelationObject; | ||
exports.overrideField = overrideField; | ||
exports.overrideField = overrideField; | ||
exports.setConfig = setConfig; |
@@ -13,2 +13,6 @@ /*jshint node:true */ | ||
var setConfig = function (config) { | ||
core.setConfig(config); | ||
} | ||
// Set the minimum logging level. Messages with a lower level, will not be forwarded. (Levels: error, warn, info, verbose, debug, silly) | ||
@@ -43,30 +47,56 @@ var setLoggingLevel = function (level) { | ||
var token = req.header(core.getDynLogLevelHeaderName()); | ||
if (req.header("X-CorrelationID") != null) { | ||
logObject.correlation_id = req.header("X-CorrelationID"); | ||
} else if (req.header("x-vcap-request-id") != null) { | ||
logObject.correlation_id = req.header("x-vcap-request-id"); | ||
if (token != null) { | ||
req.dynamicLogLevel = core.getLogLevelFromJWT(token); | ||
} else { | ||
logObject.correlation_id = uuid(); | ||
req.dynamicLogLevel = null; | ||
} | ||
logObject.request_id = req.header("x-vcap-request-id") == null ? "-" : req.header("x-vcap-request-id"); | ||
logObject.type = "request"; | ||
logObject.request = req.url == null ? "-" : req.url; | ||
logObject.referer = "-"; | ||
logObject.response_status = 200; // Set later | ||
logObject.method = req.method == null ? "-" : req.method; | ||
logObject.response_size_b = -1; // Set later | ||
logObject.request_size_b = req.header("content-length") == null ? -1 : req.header("content-length"); | ||
logObject.remote_host = req.connection.remoteAddress == null ? "-" : req.connection.remoteAddress; | ||
logObject.remote_port = req.connection.remotePort == null ? "-" : req.connection.remotePort.toString(); | ||
logObject.remote_user = "-"; | ||
logObject.x_forwarded_for = req.headers['x-forwarded-for'] == null ? "" : req.headers['x-forwarded-for']; | ||
logObject.protocol = "HTTP" + (req.httpVersion == null ? "" : "/" + req.httpVersion); | ||
logObject.remote_ip = logObject.remote_host; | ||
logObject.response_content_type = "text/html;charset=UTF-8"; | ||
logObject.request_received_at = logObject.written_at; | ||
logObject.response_time_ms = 0; // Set later | ||
logObject.direction = "IN"; | ||
var fallbacks = []; | ||
var selfReferences = []; | ||
var configEntry; | ||
var preConfig = core.getPreLogConfig(); | ||
for (var i = 0; i < preConfig.length; i++) { | ||
configEntry = preConfig[i]; | ||
switch (configEntry.source.type) { | ||
case "header": | ||
logObject[configEntry.name] = req.header(configEntry.source.name); | ||
break; | ||
case "static": | ||
logObject[configEntry.name] = configEntry.source.value; | ||
break; | ||
case "field": | ||
logObject[configEntry.name] = req[configEntry.source.name]; | ||
break; | ||
case "self": | ||
selfReferences[configEntry.name] = configEntry.source.name; | ||
break; | ||
case "time": | ||
if (configEntry.source.pre != null) | ||
logObject[configEntry.name] = configEntry.source.pre(req, res, logObject); | ||
else | ||
logObject[configEntry.name] = -1 //defaulting for time fields | ||
break; | ||
case "special": | ||
fallbacks[configEntry.name] = configEntry.fallback; | ||
break; | ||
} | ||
core.handleConfigDefaults(configEntry, logObject, fallbacks); | ||
} | ||
for (var key in fallbacks) { | ||
logObject[key] = fallbacks[key](req, res, logObject); | ||
} | ||
for (var key in selfReferences) { | ||
logObject[key] = logObject[selfReferences[key]]; | ||
} | ||
// Replace all set fields, which are marked to be reduced, with a placeholder (defined in log-core.js) | ||
core.reduceFields(preConfig, logObject); | ||
req.logObject = logObject; | ||
@@ -76,15 +106,48 @@ | ||
var start = Date.now(); | ||
res.on('finish', function () { | ||
var timeObj = new Date(); | ||
logObject.response_sent_at = timeObj.toJSON(); | ||
logObject.response_time_ms = timeObj.getTime() - start; | ||
logObject.response_size_b = res.get("content-length") == null ? -1 : res.get("content-length"); | ||
logObject.response_content_type = res.get("content-type") == null ? "-" : res.get("content-type"); | ||
logObject.response_status = res.statusCode; | ||
var postConfig = core.getPostLogConfig(); | ||
var fallbacks = []; | ||
var selfReferences = []; | ||
for (var i = 0; i < postConfig.length; i++) { | ||
configEntry = postConfig[i]; | ||
switch (configEntry.source.type) { | ||
case "header": | ||
logObject[configEntry.name] = res.get(configEntry.source.name); | ||
break; | ||
case "field": | ||
logObject[configEntry.name] = res[configEntry.source.name]; | ||
break; | ||
case "self": | ||
selfReferences[configEntry.name] = configEntry.source.name; | ||
break; | ||
case "time": | ||
if (configEntry.source.post != null) | ||
logObject[configEntry.name] = configEntry.source.post(req, res, logObject); | ||
break; | ||
case "special": | ||
fallbacks[configEntry.name] = configEntry.fallback; | ||
break; | ||
} | ||
core.handleConfigDefaults(configEntry, logObject, fallbacks); | ||
} | ||
for (var key in fallbacks) { | ||
logObject[key] = fallbacks[key](req, res, logObject); | ||
} | ||
for (var key in selfReferences) { | ||
logObject[key] = logObject[selfReferences[key]]; | ||
} | ||
//override values with predefined values | ||
core.writeStaticFields(logObject); | ||
core.sendLog('info', logObject); | ||
// Replace all set fields, which are marked to be reduced, with a placeholder (defined in log-core.js) | ||
core.reduceFields(postConfig, logObject); | ||
core.sendLog('info', logObject, req.dynamicLogLevel); | ||
}); | ||
@@ -120,2 +183,3 @@ | ||
exports.getCorrelationObject = getCorrelationObject; | ||
exports.overrideField = overrideField; | ||
exports.overrideField = overrideField; | ||
exports.setConfig = setConfig; |
@@ -5,4 +5,8 @@ //loading core logger functionality | ||
coreLogger.init(); | ||
effectiveLogger = require("./cf-nodejs-logging-support-express/log-express"); | ||
defaultConfig = require("./config.js"); | ||
effectiveLogger.setCoreLogger(coreLogger); | ||
effectiveLogger.setConfig(defaultConfig.config); | ||
@@ -26,2 +30,3 @@ exports.setLoggingLevel = function (level) { | ||
effectiveLogger.setCoreLogger(coreLogger); | ||
effectiveLogger.setConfig(defaultConfig.config); | ||
}; | ||
@@ -28,0 +33,0 @@ |
{ | ||
"name": "cf-nodejs-logging-support", | ||
"version": "2.2.3", | ||
"version": "3.0.0", | ||
"description": "Logging tool for Cloud Foundry", | ||
@@ -23,12 +23,14 @@ "keywords": [ | ||
"dependencies": { | ||
"uuid": "3.0.1" | ||
"jsonwebtoken": "^8.1.1", | ||
"uuid": "^3.1.0" | ||
}, | ||
"devDependencies": { | ||
"chai": "^3.5.0", | ||
"chai": "^4.1.2", | ||
"eslint": "latest", | ||
"import-fresh": "^2.0.0", | ||
"istanbul": "^0.4.4", | ||
"mocha": "^2.5.3", | ||
"mock-require": "^1.3.0", | ||
"mocha": "^4.0.1", | ||
"mock-require": "^2.0.2", | ||
"node-mocks-http": "^1.6.4", | ||
"rewire": "^2.5.2", | ||
"rewire": "^3.0.2", | ||
"sinon": "latest", | ||
@@ -48,4 +50,4 @@ "winston": "^2.3.1" | ||
"scripts": { | ||
"test": "istanbul cover node_modules/mocha/bin/_mocha" | ||
"test": "istanbul cover node_modules/mocha/bin/_mocha -- --timeout 10000" | ||
} | ||
} |
Environment variable access
Supply chain riskPackage accesses environment variables, which may be a sign of credential stuffing or data theft.
Found 3 instances in 1 package
Environment variable access
Supply chain riskPackage accesses environment variables, which may be a sign of credential stuffing or data theft.
Found 2 instances in 1 package
64442
1240
2
10
5
+ Addedjsonwebtoken@^8.1.1
+ Addedbuffer-equal-constant-time@1.0.1(transitive)
+ Addedecdsa-sig-formatter@1.0.11(transitive)
+ Addedjsonwebtoken@8.5.1(transitive)
+ Addedjwa@1.4.1(transitive)
+ Addedjws@3.2.2(transitive)
+ Addedlodash.includes@4.3.0(transitive)
+ Addedlodash.isboolean@3.0.3(transitive)
+ Addedlodash.isinteger@4.0.4(transitive)
+ Addedlodash.isnumber@3.0.3(transitive)
+ Addedlodash.isplainobject@4.0.6(transitive)
+ Addedlodash.isstring@4.0.1(transitive)
+ Addedlodash.once@4.1.1(transitive)
+ Addedms@2.1.3(transitive)
+ Addedsafe-buffer@5.2.1(transitive)
+ Addedsemver@5.7.2(transitive)
+ Addeduuid@3.4.0(transitive)
- Removeduuid@3.0.1(transitive)
Updateduuid@^3.1.0