diff --git a/Changelog b/Changelog index a2cc7c8..76d3673 100644 --- a/Changelog +++ b/Changelog @@ -1,3 +1,5 @@ +- Remove: dependency on deprecated domain node module (#268) + 3.2.0 (February 27th, 2024) - Add: support `POST /iot/op/delete` operation at iotAgent API to delete multiple devices at once (iota-node-lib#1578) diff --git a/lib/iotagent-manager.js b/lib/iotagent-manager.js index 06813d9..3431d82 100644 --- a/lib/iotagent-manager.js +++ b/lib/iotagent-manager.js @@ -31,51 +31,50 @@ const protocols = require('./services/protocols'); const configurations = require('./services/configurations'); const iotaRedirector = require('./services/iotaRedirector'); const dbConn = require('./model/dbConn'); -const iotaLib = require('iotagent-node-lib'); const async = require('async'); const apply = async.apply; let northboundServer; const logger = require('logops'); -const context = { - op: 'IoTAManager.NorthboundServer' -}; +const loggingMiddleware = require('./utils/logging').requestLogger('IotAgent-Manager'); + +/** + * Express middleware for tracing the complete request arriving to the IoTA in debug mode. + */ +function traceRequest(req, res, next) { + const logger = req.logger; + logger.debug('Request for path [%s] from [%s]', req.path, req.get('host')); + logger.debug('Headers:\n%j\n', req.headers); + logger.debug('Request for path [%s] query [%j] from [%s]', req.path, req.query, req.get('host')); + + if (req.is('json') || req.is('application/ld+json')) { + logger.debug('Body:\n\n%s\n\n', JSON.stringify(req.body, null, 4)); + } + + next(); +} function startServer(newConfig, callback) { let baseRoot = '/'; logger.format = logger.formatters.pipe; - logger.getContext = function domainContext() { - var domainObj = require('domain').active || {}; - return { - corr: domainObj.corr, - trans: domainObj.trans, - op: domainObj.op, - from: domainObj.from, - srv: domainObj.service, - subsrv: domainObj.subservice, - msg: domainObj.msg, - comp: config.componentName || 'IoTAgentManager' - }; - }; - northboundServer = { server: null, app: express(), router: express.Router() }; - logger.info(context, 'Starting IoT Agent Manager listening on port [%s]', newConfig.server.port); - logger.debug(context, 'Using config:\n\n%s\n', JSON.stringify(newConfig, null, 4)); + logger.info('Starting IoT Agent Manager listening on port [%s]', newConfig.server.port); + logger.debug('Using config:\n\n%s\n', JSON.stringify(newConfig, null, 4)); northboundServer.app.set('port', newConfig.server.port); northboundServer.app.set('host', newConfig.server.host || '0.0.0.0'); northboundServer.app.set('etag', false); - northboundServer.app.use(iotaLib.requestDomain); + northboundServer.app.use(loggingMiddleware); northboundServer.app.use(bodyParser.json({ limit: newConfig.bodyParserLimit })); if (newConfig.logLevel && newConfig.logLevel === 'DEBUG') { - northboundServer.app.use(middleware.traceRequest); + northboundServer.app.use(traceRequest); } if (newConfig.server.baseRoot) { @@ -120,7 +119,7 @@ function startServer(newConfig, callback) { function start(newConfig, callback) { config.setConfig(newConfig); - async.series([apply(startServer, newConfig), dbConn.configureDb], callback); + async.series([apply(startServer, newConfig), apply(dbConn.configureDb, logger)], callback); } /** @@ -128,7 +127,7 @@ function start(newConfig, callback) { * */ function stop(callback) { - logger.info(context, 'Stopping IoTA Manager'); + logger.info('Stopping IoTA Manager'); if (northboundServer) { northboundServer.server.close(callback); @@ -142,10 +141,10 @@ function stop(callback) { * */ function handleShutdown(signal) { - logger.info(context, 'Received %s, starting shutdown processs', signal); + logger.info('Received %s, starting shutdown processs', signal); stop((err) => { if (err) { - logger.error(context, err); + logger.error(err); return process.exit(1); } return process.exit(0); diff --git a/lib/model/dbConn.js b/lib/model/dbConn.js index b4b56f1..08e2963 100644 --- a/lib/model/dbConn.js +++ b/lib/model/dbConn.js @@ -29,14 +29,10 @@ const mongoose = require('mongoose'); const config = require('../utils/commonConfig'); const constants = require('../utils/constants'); -const logger = require('logops'); const async = require('async'); const errors = require('../errors'); let defaultDb; const DEFAULT_DB_NAME = 'iotagent-manager'; -const context = { - op: 'IoTAManager.DbConn' -}; mongoose.Promise = global.Promise; // not including this causes DeprecationWarning @@ -50,7 +46,7 @@ function loadModels() { * * @this Reference to the dbConn module itself. */ -function init(host, db, port, username, password, options, callback) { +function init(logger, host, db, port, username, password, options, callback) { let url; let credentials = ''; let retries = 0; @@ -87,11 +83,11 @@ function init(host, db, port, username, password, options, callback) { /* eslint-disable-next-line no-unused-vars */ function createConnectionHandler(error, results) { if (defaultDb) { - logger.info(context, 'Successfully connected to MongoDB.'); + logger.info('Successfully connected to MongoDB.'); module.exports.db = defaultDb; loadModels(); } else { - logger.error(context, 'MONGODB-002: Error found after [%d] attempts: %s', retries, error || lastError); + logger.error('MONGODB-002: Error found after [%d] attempts: %s', retries, error || lastError); } callback(error); @@ -103,7 +99,6 @@ function init(host, db, port, username, password, options, callback) { function connectionAttempt(url, options, callback) { logger.info( - context, 'Attempting to connect to MongoDB instance with url %j and options %j. Attempt %d', url, options, @@ -116,39 +111,39 @@ function init(host, db, port, username, password, options, callback) { /* eslint-disable-next-line no-unused-vars */ const candidateDb = mongoose.createConnection(url, options, function (error, result) { if (error) { - logger.error(context, 'MONGODB-001: Error trying to connect to MongoDB: %s', error); + logger.error('MONGODB-001: Error trying to connect to MongoDB: %s', error); lastError = error; } else { defaultDb = candidateDb; defaultDb.on('error', function (error) { - logger.error(context, 'Mongo Driver error: %j', error); + logger.error('Mongo Driver error: %j', error); }); /* eslint-disable-next-line no-unused-vars */ defaultDb.on('connecting', function (error) { - logger.debug(context, 'Mongo Driver connecting'); + logger.debug('Mongo Driver connecting'); }); defaultDb.on('connected', function () { - logger.debug(context, 'Mongo Driver connected'); + logger.debug('Mongo Driver connected'); }); defaultDb.on('reconnected', function () { - logger.debug(context, 'Mongo Driver reconnected'); + logger.debug('Mongo Driver reconnected'); }); defaultDb.on('disconnected', function () { - logger.debug(context, 'Mongo Driver disconnected'); + logger.debug('Mongo Driver disconnected'); }); defaultDb.on('reconnectFailed', function () { - logger.error(context, 'MONGODB-004: MongoDB connection was lost'); + logger.error('MONGODB-004: MongoDB connection was lost'); process.exit(1); }); defaultDb.on('disconnecting', function () { - logger.debug(context, 'Mongo Driver disconnecting'); + logger.debug('Mongo Driver disconnecting'); }); defaultDb.on('open', function () { - logger.debug(context, 'Mongo Driver open'); + logger.debug('Mongo Driver open'); }); defaultDb.on('close', function () { - logger.debug(context, 'Mongo Driver close'); + logger.debug('Mongo Driver close'); }); } @@ -165,10 +160,10 @@ function init(host, db, port, username, password, options, callback) { retries++; if (retries === 1) { - logger.info(context, 'First connection attempt'); + logger.info('First connection attempt'); attempt(); } else { - logger.info(context, 'Waiting %d seconds before attempting again.', seconds); + logger.info('Waiting %d seconds before attempting again.', seconds); setTimeout(attempt, seconds * 1000); } } @@ -177,11 +172,11 @@ function init(host, db, port, username, password, options, callback) { async.whilst(retryCheck, tryCreateConnection, createConnectionHandler); } -function configureDb(callback) { +function configureDb(logger, callback) { const currentConfig = config.getConfig(); if (!currentConfig.mongodb || !currentConfig.mongodb.host) { - logger.fatal(context, 'No host found for MongoDB driver.'); + logger.fatal('No host found for MongoDB driver.'); callback(new errors.BadConfiguration('No host found for MongoDB driver')); } else { let dbName = currentConfig.mongodb.db; @@ -197,6 +192,7 @@ function configureDb(callback) { } init( + logger, config.getConfig().mongodb.host, dbName, port, diff --git a/lib/services/configurationData.js b/lib/services/configurationData.js index 4daa7b1..b0996b8 100644 --- a/lib/services/configurationData.js +++ b/lib/services/configurationData.js @@ -28,9 +28,7 @@ const iotagentLib = require('iotagent-node-lib'); const errors = require('../errors'); const logger = require('logops'); const async = require('async'); -const context = { - op: 'IoTAManager.ConfigurationDB' -}; + const provisioningAPITranslation = { name: 'id', service: 'service', @@ -68,7 +66,7 @@ function createGetWithFields(fields) { const callback = arguments[i]; - logger.debug(context, 'Looking for configuration with params %j and query %j', fields, queryObj); + logger.debug('Looking for configuration with params %j and query %j', fields, queryObj); const query = Configuration.model.find(queryObj); @@ -98,7 +96,7 @@ function createGetWithFields(fields) { }; } -function save(protocol, description, iotagent, resource, configuration, oldConfiguration, callback) { +function save(theLogger, protocol, description, iotagent, resource, configuration, oldConfiguration, callback) { /* eslint-disable-next-line new-cap */ const configurationObj = oldConfiguration || new Configuration.model(); const attributeList = [ @@ -125,7 +123,7 @@ function save(protocol, description, iotagent, resource, configuration, oldConfi 'payloadType' ]; - logger.debug(context, 'Saving Configuration [%s][%s][%s]', protocol, iotagent, resource); + theLogger.debug('Saving Configuration [%s][%s][%s]', protocol, iotagent, resource); configurationObj.protocol = protocol; configurationObj.description = description; @@ -142,7 +140,7 @@ function save(protocol, description, iotagent, resource, configuration, oldConfi configurationObj[provisioningAPITranslation[attributeList[i]] || attributeList[i]] = description; } } - logger.debug(context, 'Saving Configuration %j translated to %j ', configuration, configurationObj); + theLogger.debug('Saving Configuration %j translated to %j ', configuration, configurationObj); configurationObj.save(callback); } diff --git a/lib/services/configurations.js b/lib/services/configurations.js index 5218fc2..42e1b37 100644 --- a/lib/services/configurations.js +++ b/lib/services/configurations.js @@ -23,12 +23,6 @@ const errors = require('../errors'); const configurationData = require('./configurationData'); -const logger = require('logops'); -const domain = require('../utils/domain'); -const fillService = domain.fillService; -var context = { - op: 'IoTAManager.Configurations' -}; const retrievingAPITranslation = { subservice: 'service_path', type: 'entity_type', @@ -59,7 +53,7 @@ function validateListParameters(req, res, next) { } } -function translateToApi(configurations) { +function translateToApi(logger, configurations) { const services = []; const attributeList = [ '_id', @@ -90,7 +84,7 @@ function translateToApi(configurations) { 'transport' ]; - logger.debug(context, 'configurations %j', configurations); + logger.debug('configurations %j', configurations); for (let j = 0; j < configurations.services.length; j++) { const service = {}; @@ -98,7 +92,7 @@ function translateToApi(configurations) { service[retrievingAPITranslation[attributeList[i]] || attributeList[i]] = configurations.services[j][attributeList[i]]; } - logger.debug(context, 'translated to %j', service); + logger.debug('translated to %j', service); services.push(service); } @@ -109,10 +103,7 @@ function translateToApi(configurations) { } function handleListRequest(req, res, next) { - context = fillService(context, { - service: req.headers['fiware-service'], - subservice: req.headers['fiware-servicepath'] - }); + const logger = req.logger; configurationData.list( req.headers['fiware-service'], req.headers['fiware-servicepath'], @@ -125,7 +116,7 @@ function handleListRequest(req, res, next) { if (error) { next(error); } else { - res.status(200).json(translateToApi(configurations)); + res.status(200).json(translateToApi(logger, configurations)); } } ); diff --git a/lib/services/iotaRedirector.js b/lib/services/iotaRedirector.js index 1900a2f..af3b003 100644 --- a/lib/services/iotaRedirector.js +++ b/lib/services/iotaRedirector.js @@ -23,15 +23,9 @@ const protocols = require('./protocolData'); const request = require('iotagent-node-lib').request; -const logger = require('logops'); const errors = require('../errors'); const _ = require('underscore'); const async = require('async'); -const domain = require('../utils/domain'); -const fillService = domain.fillService; -var context = { - op: 'IoTAManager.Redirector' -}; function guessCollection(body) { if (body.services) { @@ -42,11 +36,11 @@ function guessCollection(body) { return null; } -function extractProtocols(body) { +function extractProtocols(logger, body) { const collectionName = guessCollection(body); let protocols; - logger.debug(context, 'Extracting protocols from body for collection [%s]', collectionName); + logger.debug('Extracting protocols from body for collection [%s]', collectionName); function extractProtocol(previous, item) { if (item.protocol) { @@ -63,7 +57,7 @@ function extractProtocols(body) { if (collectionName) { protocols = body[collectionName].reduce(extractProtocol, []); - logger.debug(context, 'Protocols found: %j', protocols); + logger.debug('Protocols found: %j', protocols); return protocols; } @@ -71,18 +65,20 @@ function extractProtocols(body) { } function queryParamExtractor(req, res, next) { + const logger = req.logger; if (req.query.protocol) { - logger.debug(context, 'Protocol found in the query parameters [%s]', req.query.protocol); + logger.debug('Protocol found in the query parameters [%s]', req.query.protocol); req.protocolId = [req.query.protocol]; } else if (req.method !== 'GET') { req.splitAndRedirect = true; - req.protocolId = extractProtocols(req.body); + req.protocolId = extractProtocols(logger, req.body); } next(); } function getProtocols(req, res, next) { + const logger = req.logger; function addProtocolAsync(previous, item, callback) { protocols.get(item, function (error, protocol) { if (error) { @@ -104,7 +100,7 @@ function getProtocols(req, res, next) { } if (req.protocolId) { - logger.debug(context, 'Finding objects for the following protocols: %j', req.protocolId); + logger.debug('Finding objects for the following protocols: %j', req.protocolId); if (req.protocolId.length === 0) { next(new errors.ProtocolNotFound('', '')); @@ -115,7 +111,7 @@ function getProtocols(req, res, next) { next(error); }); } else { - logger.debug(context, 'Finding objects for all the protocols'); + logger.debug('Finding objects for all the protocols'); protocols.list(function (error, protocols) { if (error) { @@ -123,7 +119,7 @@ function getProtocols(req, res, next) { } else { req.protocolId = protocols.map(extractId); req.protocolObj = protocols.reduce(addProtocolSync, {}); - logger.debug(context, 'Finding objects for this protocol: %j', req.protocolId); + logger.debug('Finding objects for this protocol: %j', req.protocolId); next(); } }); @@ -187,6 +183,7 @@ function splitByProtocol(req) { * @return {Object} Request object prepared to be sent. */ function createRequest(req, protocol, body) { + const logger = req.logger; const options = { qs: _.clone(req.query), method: req.method, @@ -195,7 +192,7 @@ function createRequest(req, protocol, body) { const protocolObj = req.protocolObj[protocol]; let protocolAddress = protocolObj.iotagent; - logger.debug(context, 'creating request using protocol:\n\n%j\n', protocolObj); + logger.debug('creating request using protocol:\n\n%j\n', protocolObj); // Save original apikey before be overwrite by apikey from body (probably modified) if (req.query.apikey) { @@ -236,16 +233,13 @@ function createRequest(req, protocol, body) { delete options.headers['content-length']; options.headers.connection = 'close'; - context = fillService(context, { - service: options.headers['fiware-service'], - subservice: options.headers['fiware-servicepath'] - }); - logger.debug(context, 'Forwarding request:\n\n%j\n', options); + logger.debug('Forwarding request:\n\n%j\n', options); return options; } function createRequests(req, res, next) { + const logger = req.logger; function mapToBody(split, protocol) { return createRequest(req, protocol, split[protocol]); } @@ -253,11 +247,11 @@ function createRequests(req, res, next) { if (req.splitAndRedirect) { const split = splitByProtocol(req); - logger.debug(context, 'Creating request for multiple elements'); + logger.debug('Creating request for multiple elements'); req.requests = req.protocolId.map(mapToBody.bind(null, split)); } else { - logger.debug(context, 'Creating request for redirecting single requests'); + logger.debug('Creating request for redirecting single requests'); req.requests = []; for (let i = 0; i < req.protocolId.length; i++) { req.requests.push(createRequest(req, req.protocolId[i], req.body)); @@ -268,6 +262,7 @@ function createRequests(req, res, next) { } function processRequests(req, res, next) { + const logger = req.logger; function extractStatusCode(result) { if (result && result.length === 2 && result[0].statusCode) { return result[0].statusCode; @@ -276,7 +271,7 @@ function processRequests(req, res, next) { } function sendRequest(options, callback) { - logger.debug(context, 'Sending redirection with following options: %j', options); + logger.debug('Sending redirection with following options: %j', options); // Use original apikey, not apikey from body if (options.qs.apikeyReq) { options.qs.apikey = options.qs.apikeyReq; @@ -287,7 +282,6 @@ function processRequests(req, res, next) { // Parsing is done directly within the Got library. if (error.name === 'ParseError') { logger.error( - context, 'REDIRECTION-003: Error parsing response body from the redirected request: %s to [%s]', error, options.uri @@ -295,17 +289,11 @@ function processRequests(req, res, next) { return callback(new errors.TargetResponseError({ msg: error.name })); } - logger.error( - context, - 'REDIRECTION-001: Error found redirecting requests to [%s]: %j', - options.uri, - error - ); + logger.error('REDIRECTION-001: Error found redirecting requests to [%s]: %j', options.uri, error); return callback(new errors.TargetServerError(error)); } else if (response.statusCode >= 500) { logger.error( - context, 'REDIRECTION-002: Wrong status code detected [%s] and body response [%s] redirecting request to [%s]', response.statusCode, response.body, @@ -327,7 +315,7 @@ function processRequests(req, res, next) { if (response.statusCode === 409) { parseError = new errors.DuplicateError(body); } - logger.debug(context, 'Response body from the redirected request parsed: \n\n%j\n', body); + logger.debug('Response body from the redirected request parsed: \n\n%j\n', body); return callback(parseError, [response, body]); } else { return callback(null, [response, null]); @@ -354,7 +342,7 @@ function processRequests(req, res, next) { } for (let i = 0; i < results.length; i++) { - logger.debug(context, 'results[%s][1] %j ', i, results[i][1]); + logger.debug('results[%s][1] %j ', i, results[i][1]); if (results[i][1].count) { totalCount += results[i][1].count; @@ -389,7 +377,7 @@ function processRequests(req, res, next) { function requestHandler(error, results) { let combinedResult; if (error) { - logger.error(context, 'The redirection ended up in error: ', error); + logger.error('The redirection ended up in error: ', error); next(error); } else { const statusCodes = _.uniq(results.map(extractStatusCode)); @@ -413,7 +401,7 @@ function processRequests(req, res, next) { JSON.stringify(statusCodes) + '] redirecting request'; - logger.error(context, errorMsg); + logger.error(errorMsg); next(new errors.TargetServerError(errorMsg)); } @@ -443,9 +431,10 @@ exports.loadContextRoutes = loadContextRoutes; /* eslint-disable-next-line no-unused-vars */ function handleError(error, req, res, next) { + const logger = req.logger; let code = 500; - logger.warn(context, 'Error [%s] handling request: %s', error.name, error.message); + logger.warn('Error [%s] handling request: %s', error.name, error.message); if (error.code && String(error.code).match(/^[2345]\d\d$/)) { code = error.code; diff --git a/lib/services/protocolData.js b/lib/services/protocolData.js index c1bdd7b..0c69742 100644 --- a/lib/services/protocolData.js +++ b/lib/services/protocolData.js @@ -28,19 +28,16 @@ const configurations = require('./configurationData'); const async = require('async'); const errors = require('../errors'); const apply = async.apply; -const logger = require('logops'); -const context = { - op: 'IoTAManager.ProtocolAPI' -}; -function processConfiguration(protocol, description, iotagent, resource, configuration, callback) { +function processConfiguration(logger, protocol, description, iotagent, resource, configuration, callback) { configurations.get(configuration.apikey, resource, protocol, function (error, oldConfiguration) { if (error) { callback(error); } else if (oldConfiguration.services.length === 0) { - configurations.save(protocol, description, iotagent, resource, configuration, null, callback); + configurations.save(logger, protocol, description, iotagent, resource, configuration, null, callback); } else { configurations.save( + logger, protocol, description, iotagent, @@ -53,7 +50,7 @@ function processConfiguration(protocol, description, iotagent, resource, configu }); } -function cleanConfigurations(protocol, iotagent, resource, callback) { +function cleanConfigurations(logger, protocol, iotagent, resource, callback) { Configuration.model.deleteMany( { protocol, @@ -63,12 +60,11 @@ function cleanConfigurations(protocol, iotagent, resource, callback) { /* eslint-disable-next-line no-unused-vars */ function (error, commandResult) { if (error) { - logger.error(context, 'MONGODB-003: Internal MongoDB Error removing services from protocol: %s', error); + logger.error('MONGODB-003: Internal MongoDB Error removing services from protocol: %s', error); callback(new errors.InternalDbError(error)); } else { logger.debug( - context, 'Configurations for Protocol [%s][%s][%s] successfully removed.', protocol, iotagent, @@ -117,7 +113,7 @@ function listProtocol(callback) { }); } -function save(newProtocol, callback) { +function save(logger, newProtocol, callback) { getProtocol(newProtocol.protocol, function (error, protocol) { if (error && error.name !== 'PROTOCOL_NOT_FOUND') { callback(error); @@ -131,7 +127,9 @@ function save(newProtocol, callback) { protocolObj[attributeList[i]] = newProtocol[attributeList[i]]; } - actions.push(apply(cleanConfigurations, newProtocol.protocol, newProtocol.iotagent, newProtocol.resource)); + actions.push( + apply(cleanConfigurations, logger, newProtocol.protocol, newProtocol.iotagent, newProtocol.resource) + ); if (newProtocol.services) { actions.push( @@ -140,6 +138,7 @@ function save(newProtocol, callback) { newProtocol.services, apply( processConfiguration, + logger, newProtocol.protocol, newProtocol.description, newProtocol.iotagent, @@ -156,12 +155,12 @@ function save(newProtocol, callback) { }); } -function removeProtocol(id, callback) { +function removeProtocol(logger, id, callback) { const condition = { protocol: id }; - logger.debug(context, 'Removing protocol with id [%s]', id); + logger.debug('Removing protocol with id [%s]', id); /* eslint-disable-next-line no-unused-vars */ getProtocol(condition.protocol, function (error, protocol) { if (error) { @@ -169,10 +168,10 @@ function removeProtocol(id, callback) { } else { Protocol.model.deleteOne(condition, function (error, results) { if (error) { - logger.debug(context, 'Internal MongoDB Error getting device: %s', error); + logger.debug('Internal MongoDB Error getting device: %s', error); callback(new errors.InternalDbError(error)); } else { - logger.debug(context, 'Protocol [%s] successfully removed with results [%j]', id, results); + logger.debug('Protocol [%s] successfully removed with results [%j]', id, results); callback(null); } }); diff --git a/lib/services/protocols.js b/lib/services/protocols.js index 9244037..b4c9ae7 100644 --- a/lib/services/protocols.js +++ b/lib/services/protocols.js @@ -25,16 +25,13 @@ const protocolTemplate = require('../templates/protocol.json'); const Protocol = require('../model/Protocol'); const protocols = require('./protocolData'); const async = require('async'); -const logger = require('logops'); const middleware = require('iotagent-node-lib').middlewares; -const context = { - op: 'IoTAManager.ProtocolAPI' -}; function readProtocolList(req, res, next) { + const logger = req.logger; const condition = {}; - logger.debug(context, 'List protocols request with args %j', JSON.stringify(req.query)); + logger.debug('List protocols request with args %j', JSON.stringify(req.query)); const query = Protocol.model.find(condition).sort(); @@ -51,10 +48,10 @@ function readProtocolList(req, res, next) { results ) { if (error) { - logger.error(context, 'error: %j', error); + logger.error('error: %j', error); next(error); } else { - logger.debug(context, 'results of query: %j', results); + logger.debug('results of query: %j', results); req.protocolList = results[0]; req.protocolCount = results[1]; next(); @@ -63,9 +60,10 @@ function readProtocolList(req, res, next) { } function saveProtocol(req, res, next) { - logger.debug(context, 'Update/create protocol request: %j', req.body); + const logger = req.logger; + logger.debug('Update/create protocol request: %j', req.body); - protocols.save(req.body, next); + protocols.save(logger, req.body, next); } /* eslint-disable-next-line no-unused-vars */ function handleProtocolList(req, res, next) { @@ -80,7 +78,8 @@ function returnProtocolCreationResponse(req, res, next) { } /* eslint-disable-next-line no-unused-vars */ function deleteProtocol(req, res, next) { - protocols.remove(req.params.id, function (error) { + const logger = req.logger; + protocols.remove(logger, req.params.id, function (error) { if (error) { res.status(error.code).json(error); } else { diff --git a/lib/utils/constants.js b/lib/utils/constants.js index a2b2c54..66a0184 100644 --- a/lib/utils/constants.js +++ b/lib/utils/constants.js @@ -35,5 +35,10 @@ module.exports = { DEFAULT_RESOURCE: '/iot/d', DEFAULT_MONGODB_RETRIES: 5, - DEFAULT_MONGODB_RETRY_TIME: 5 + DEFAULT_MONGODB_RETRY_TIME: 5, + + X_FORWARDED_FOR_HEADER: 'x-forwarded-for', + FORWARDED_HEADER: 'forwarded', + X_REAL_IP_HEADER: 'x-real-ip', + CORRELATOR_HEADER: 'fiware-correlator' }; diff --git a/lib/utils/domain.js b/lib/utils/domain.js deleted file mode 100644 index 9b6d371..0000000 --- a/lib/utils/domain.js +++ /dev/null @@ -1,46 +0,0 @@ -/* - * Copyright 2014 Telefonica Investigación y Desarrollo, S.A.U - * - * This file is part of fiware-pep-steelskin - * - * fiware-pep-steelskin is free software: you can redistribute it and/or - * modify it under the terms of the GNU Affero General Public License as - * published by the Free Software Foundation, either version 3 of the License, - * or (at your option) any later version. - * - * fiware-pep-steelskin is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * See the GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public - * License along with fiware-pep-steelskin. - * If not, see http://www.gnu.org/licenses/. - * - * For those usages not covered by the GNU Affero General Public License - * please contact with::[iot_support@tid.es] - */ - -'use strict'; - - -/** - * Fills service and subservice information in a context object for logging matters. - * - * @param {Object} context Context object that will be used to add the service and subservice information. - * @param {Object} data Data object (configuration or device) containing service information. - * @return {Object} New context containing service information. - */ -function fillService(context, data) { - if (data.service) { - context.srv = data.service; - } - - if (data.subservice) { - context.subsrv = data.subservice; - } - - return context; -} - -exports.fillService = fillService; diff --git a/lib/utils/logging.js b/lib/utils/logging.js new file mode 100644 index 0000000..0350bd3 --- /dev/null +++ b/lib/utils/logging.js @@ -0,0 +1,83 @@ +/* + * Copyright 2014 Telefonica Investigaci�n y Desarrollo, S.A.U + * + * This file is part of iotagent-manager + * + * iotagent-manager is free software: you can redistribute it and/or + * modify it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the License, + * or (at your option) any later version. + * + * iotagent-manager is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See the GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public + * License along with iotagent-manager. + * If not, seehttp://www.gnu.org/licenses/. + * + * For those usages not covered by the GNU Affero General Public License + * please contact with::[iot_support@tid.es] + */ + +const { v4: uuidv4 } = require('uuid'); +const constants = require('./constants'); + +const logger = require('logops'); + +/** + * Express middleWare that creates a domain per request + * It also generates a unique request id that can be used to track requests in logs. + * + * @return {Function} Express middleWare. + */ + +function requestLogger(componentName) { + return function (req, res, next) { + let contextSrv; + if (req.headers && req.headers[constants.SERVICE_HEADER]) { + contextSrv = req.headers[constants.SERVICE_HEADER]; + } + let contextSubsrv; + if (req.headers && req.headers[constants.SUBSERVICE_HEADER]) { + contextSubsrv = req.headers[constants.SUBSERVICE_HEADER]; + } + let contextFrom; + // x-forwarded-for/forwarded overwrites x-real-ip + if (req.headers[constants.X_REAL_IP_HEADER]) { + contextFrom = req.headers[constants.X_REAL_IP_HEADER]; + } + if (req.headers[constants.X_FORWARDED_FOR_HEADER]) { + contextFrom = req.headers[constants.X_FORWARDED_FOR_HEADER]; + } + if (req.headers[constants.FORWARDED_HEADER]) { + contextFrom = req.headers[constants.FORWARDED_HEADER]; + } + req.requestId = uuidv4(); + const contextTrans = req.requestId; + let contextCorr = req.get(constants.CORRELATOR_HEADER); + if (!contextCorr) { + contextCorr = contextTrans; + } + req.corr = contextCorr; // for propagate in FWD request + res.set(constants.CORRELATOR_HEADER, contextCorr); // for response + const contextStart = Date.now(); + req.logger = logger.child({ + corr: contextCorr, + trans: contextTrans, + op: req.url, + from: contextFrom, + srv: contextSrv, + subsrv: contextSubsrv, + comp: componentName + }); + res.once('finish', function () { + const responseTime = Date.now() - contextStart; + req.logger.debug('response-time: ' + responseTime + ' statusCode: ' + res.statusCode); + }); + next(); + }; +} + +exports.requestLogger = requestLogger;