UNPKG

@sap/xsodata

Version:

Expose data from a HANA database as OData V2 service with help of .xsodata files.

311 lines (256 loc) 9.98 kB
'use strict'; const logMemory = process.env.XSODATA_LOG_MEMORY_CONSUMPTION >= 1; // PREREQUISITE // This logging api logs only if XS_APP_LOG_LEVEL = debug // 0 error // 1 warn // 2 info // 3 verbose // 4 debug // 5 silly let XSODATA_LOG_LEVEL = process.env.XSODATA_LOG_LEVEL || 4; // Logging for request time // Requires XSODATA_LOG_LEVEL >= 4 // 0: no Request times are logged // 1: Request times are logged let XSODATA_LOG_REQUEST_TIME = process.env.XSODATA_LOG_REQUEST_TIME || 0; // Log long requests // Requires XSODATA_LOG_LEVEL >= 2 // Requires request length > XSODATA_FORCE_LOG_LONG_REQUEST let XSODATA_FORCE_LOG_LONG_REQUEST = process.env.XSODATA_FORCE_LOG_LONG_REQUEST || 2; // Log sql commands // 0-1: no SQL query commands are logged // 2: SQL query commands are logged ( and time if XSODATA_LOG_SQL_TIME is > 1) let XSODATA_LOG_SQL_COMMAND = process.env.XSODATA_LOG_SQL_COMMAND || 2; // Logging for sql commands execution time // Requires XSODATA_LOG_SQL_COMMAND >= 2 // 0: no SQL times are logged // 1: SQL times are logged let XSODATA_LOG_SQL_TIME = process.env.XSODATA_LOG_SQL_TIME || 0; // Log long sql commands // Requires request length > XSODATA_FORCE_LOG_LONG_SQL let XSODATA_FORCE_LOG_LONG_SQL = process.env.XSODATA_FORCE_LOG_LONG_SQL || 2; // Log long sql query parameter // Requires XSODATA_LOG_SQL_COMMAND >= 2 // 0-1: no SQL query parameters are logged // 2: SQL query parameters are logged let XSODATA_LOG_SQL_PARAMETERS = process.env.XSODATA_LOG_SQL_PARAMETERS || 2; // XSODATA_LOG_SQL_PARAM_VALUE_SIZE: sets the length of the parameter value loggged out let XSODATA_LOG_SQL_PARAM_VALUE_SIZE = process.env.XSODATA_LOG_SQL_PARAM_VALUE_SIZE || 80; let XSODATA_LOG_SQL_PARAM_ARRAY_SIZE = process.env.XSODATA_LOG_SQL_PARAM_ARRAY_SIZE || 80; // Log long sql results // Requires XSODATA_LOG_SQL_COMMAND >= 2 // 0-1: no SQL results are logged // 2: SQL results are logged let XSODATA_LOG_SQL_DATA = process.env.XSODATA_LOG_SQL_DATA || 0; let XSODATA_LOG_SQL_DATA_VALUE_SIZE = process.env.XSODATA_LOG_SQL_DATA_VALUE_SIZE || 20; let XSODATA_LOG_SQL_DATA_ARRAY_SIZE = process.env.XSODATA_LOG_SQL_DATA_ARRAY_SIZE || 30; //XSODATA_LOG_LEVEL = 0; //XSODATA_LOG_REQUEST_TIME = 1; //XSODATA_FORCE_LOG_LONG_REQUEST = 1; //XSODATA_LOG_SQL_COMMAND = 0; //XSODATA_LOG_SQL_TIME = 0; //XSODATA_FORCE_LOG_LONG_SQL = 2; //XSODATA_LOG_SQL_PARAMETERS = 0; //XSODATA_LOG_SQL_DATA = 0; var logLevels = { "error": 0, "warn": 1, "info": 2, "verbose": 3, "debug": 4, "silly": 5 }; function printSqlData(array) { let ret = ''; for (const value of array) { if (ret.length) { ret += ','; } if (typeof value === 'string' && value.length > XSODATA_LOG_SQL_DATA_VALUE_SIZE) { ret += value.substr(0, XSODATA_LOG_SQL_DATA_VALUE_SIZE) + '.LEN:' + value.length; continue; } if (Array.isArray(value) && value.length > XSODATA_LOG_SQL_DATA_ARRAY_SIZE) { ret += value.slice(0, XSODATA_LOG_SQL_DATA_ARRAY_SIZE); continue; } if (Buffer.isBuffer(value) && value.length > XSODATA_LOG_SQL_DATA_VALUE_SIZE) { ret += value.slice(0, XSODATA_LOG_SQL_DATA_VALUE_SIZE).toString('hex') + '.LEN:' + value.length; continue; } if (typeof value === 'object') { ret += JSON.stringify(value); continue; } ret += value; } return ret; } function printSqlParameters(array) { let ret = ''; if (array && Array.isArray(array)) { for (const value of array) { if (ret.length) { ret += ','; } if (typeof value === 'string' && value.length > XSODATA_LOG_SQL_PARAM_VALUE_SIZE) { ret += value.substr(0, XSODATA_LOG_SQL_PARAM_VALUE_SIZE) + '<' + value.length + '>'; continue; } if (Array.isArray(value) && value.length > XSODATA_LOG_SQL_PARAM_ARRAY_SIZE) { ret += value.slice(0, XSODATA_LOG_SQL_PARAM_VALUE_SIZE); continue; } if (Buffer.isBuffer(value) && value.length > XSODATA_LOG_SQL_PARAM_VALUE_SIZE) { ret += value.slice(0, XSODATA_LOG_SQL_PARAM_VALUE_SIZE).toString('hex') + '.LEN:' + value.length; continue; } ret += value; } } return ret; } //Code var EmptyLogger = function () { }; EmptyLogger.prototype.cloneWithContext = function () { return new EmptyLogger(); }; Object.keys(logLevels).forEach(function (levelKey) { EmptyLogger.prototype[levelKey] = function () {}; }); function getMemStats() { const used = process.memoryUsage(); let rssMB = (used.rss / 1024 / 1024).toFixed(2); let heapTotalMB = (used.heapTotal / 1024 / 1024).toFixed(2); let heapUsedMB = (used.heapUsed / 1024 / 1024).toFixed(2); return `rss (MB): ${rssMB}, heapTotal (MB): ${heapTotalMB}, heapUsed (MB): ${heapUsedMB}`; } function Logger(logger, context) { this.logger = logger || new EmptyLogger(); this.context = context || { callId: 0, uniqueNetworkRequestID: 0, uniqueRequestID: 0 }; this.info('Logger', 'Logger created for request'); //this.XSODATA_LOG_SQL_TIME = XSODATA_LOG_SQL_TIME; //this.XSODATA_LOG_REQUEST_TIME = XSODATA_LOG_REQUEST_TIME; } Logger.prototype.cloneWithContext = function (context) { this.info('Logger', 'cloneWithContext'); return new Logger(this.logger, context); }; Logger.prototype.getKey = function () { return '[' + this.context.uniqueNetworkRequestID + '][' + this.context.uniqueRequestID + '] '; }; Logger.prototype.error = function (scope, text) { //level 0 this.logger.error(this.getKey() + scope + '::' + text); }; Logger.prototype.warn = function (scope, text) { //level 1 this.logger.warn(this.getKey() + scope + '::' + text); }; Logger.prototype.info = function (scope, text, textIndent) { if (XSODATA_LOG_LEVEL >= 2) { //level 2 if (textIndent) { textIndent = '\n ' + textIndent.replace('\n', '\n '); } else { textIndent = ''; } this.logger.info(this.getKey() + scope + '::' + text + textIndent); } }; Logger.prototype.verbose = function (scope, text) { //level 3 if (XSODATA_LOG_LEVEL >= 3) { this.logger.verbose(this.getKey() + scope + '::' + text); } }; Logger.prototype.debug = function (scope, text) { //level 4 if (XSODATA_LOG_LEVEL >= 4) { const out = !logMemory ? text : text + ' --- ' + getMemStats(); this.logger.debug(this.getKey() + scope + '::' + out); } }; Logger.prototype.silly = function (scope, text) { //level 5 if (XSODATA_LOG_LEVEL >= 5) { const out = !logMemory ? text : text + ' --- ' + getMemStats(); this.logger.debug(this.getKey() + scope + '::' + out); } }; Logger.prototype.logSqlData = function (data) { if (XSODATA_LOG_SQL_COMMAND >= 2 && XSODATA_LOG_SQL_DATA >= 2) { let out = "[]"; if (Array.isArray(data) && data.length > 0) { out = printSqlData(data); } this.logger.debug(this.getKey() + 'SQL data: ' + out); } }; Logger.prototype.logSqlCommand = function (sql) { if (XSODATA_LOG_SQL_COMMAND >= 2) { this.logger.debug(this.getKey() + 'SQL command: ' + sql); } }; Logger.prototype.logSqlParameters = function (parameters, force, asError) { if (XSODATA_LOG_SQL_COMMAND >= 2 && (XSODATA_LOG_SQL_PARAMETERS >= 2 || force || asError)) { let out = printSqlParameters(parameters); if (asError) { this.logger.error(this.getKey() + 'SQL param: ' + out); } else { this.logger.debug(this.getKey() + 'SQL param: ' + out); } } }; Logger.prototype.getStartTimeSql = function () { if (XSODATA_LOG_SQL_TIME || XSODATA_FORCE_LOG_LONG_SQL) { return process.hrtime(); } return null; }; Logger.prototype.logSqlTime = function (text, startTime, sql) { const padZeroMS = (value) => { while (value.length < 6) { value = '0' + value; } return value; }; if (startTime) { const hrtime = process.hrtime(startTime); const ms = padZeroMS('' + Math.round(hrtime[1] / 1000)); if (XSODATA_LOG_SQL_COMMAND >= 2 && XSODATA_LOG_SQL_TIME) { // sql is already logged for same request (don't log twice) this.logger.debug(this.getKey() + 'SQL ' + text + ' time: ' + hrtime[0] + '.' + ms + ' s'); } else if (XSODATA_FORCE_LOG_LONG_SQL && hrtime[0] >= XSODATA_FORCE_LOG_LONG_SQL) { this.logger.debug(this.getKey() + 'SQL command: ' + sql); this.logger.debug(this.getKey() + 'SQL ' + text + ' time: ' + hrtime[0] + '.' + ms + ' s'); } } }; Logger.prototype.getStartTimeRequest = function () { if (XSODATA_LOG_REQUEST_TIME || XSODATA_FORCE_LOG_LONG_REQUEST) { return process.hrtime(); } return null; }; Logger.prototype.logRequestTime = function (text, startTime, url) { const padZeroMS = (value) => { while (value.length < 6) { value = '0' + value; } return value; }; if (startTime) { const hrtime = process.hrtime(startTime); const ms = padZeroMS('' + Math.round(hrtime[1] / 1000)); if (XSODATA_LOG_LEVEL >= 2) { // sql is already logged for same request (don't log twice) this.logger.debug(this.getKey() + 'Request ' + text + ' time: ' + hrtime[0] + '.' + ms + ' s'); } else if (XSODATA_FORCE_LOG_LONG_REQUEST && hrtime[0] > XSODATA_FORCE_LOG_LONG_REQUEST) { this.logger.debug(this.getKey() + 'Request ' + text + ' time: ' + hrtime[0] + '.' + ms + ' s (' + url + ')'); } } }; module.exports = Logger;