3

我正在尝试使用 sequelize cls 和 logger 模块记录 mysql 查询。在这我失去了命名空间的上下文,Request-Id它打印空白或一些随机的先前Request-Id

节点版本:8.9.4
续集:4.33.4
cls-hooked:4.2.2

任何帮助/解决方案表示赞赏。

mysql.js

const parameterStore = require( './parameterStore.js' );
var config = require( './config/main.js' )[ process.env.STAGE || 'local' ];
var mysqlConfig = config.MYSQL;

var logger = require( '../../lib/logger.js' );

var Sequelize = require( 'sequelize' );

function MySQL() {

}

MySQL.prototype.getSequelizeMysqlConnection = function() {
    return new Promise( async function( resolve, reject ) {
        try{
            var credentials = await parameterStoreInstance.getMySqlDbCredentials()
            .then( function( data ) {
                return data;
            } )
            .catch( function( error ) {
                throw error;
            } );
            sequelize = new Sequelize (
            {
                database: mysqlConfig.DATABASE,
                username: credentials.USERNAME,
                password: credentials.PASSWORD,
                host: mysqlConfig.HOST,
                port: mysqlConfig.PORT,
                dialect: 'mysql',
                pool: {
                    max: 3,
                    min: 0,
                    idle: 10000,
                    acquire: 20000
                },
                logging: sequelizeLogger,
                benchmark: true
            } );
            return resolve( sequelize );
        } catch( error ) {
            reject( error );
        }
    } );
};

function sequelizeLogger( query, time ) {
    logger.debug( query + ` [${ time }ms]` );
}

module.exports = MySQL;

logger.js

const winston = require('winston');
const date_time = require('moment-timezone');
const on_headers = require('on-headers');
const on_finished = require('on-finished');
// const continuation_local_storage = require('continuation-local-storage');
const continuation_local_storage = require('cls-hooked');
const Promise = require('bluebird');
const continuation_local_storage_bluebird = require('cls-bluebird');
const redis = require('redis');
const continuation_local_storage_redis = require('cls-redis');
var appName = undefined;
var Sequelize = require('sequelize');

const winston_config = winston.config;

var winstonLogger = new winston.Logger({
  transports: [
    new winston.transports.Console({
        level : process.env.STAGE === 'prod' ? 'info' : 'debug',
        showLevel : false
    } )
  ],
  exitOnError: false
});


var getNamespace = continuation_local_storage.getNamespace;
var createNamespace = continuation_local_storage.createNamespace;
var createRequest = createNamespace( 'Request-Id' );
var getRequest = getNamespace( 'Request-Id' );
continuation_local_storage_bluebird( createRequest );
continuation_local_storage_redis( createRequest );
Sequelize.useCLS( createRequest );

function logger() {
}

logger.prototype.log = function( level, ...message ) {
    // body...
    var combinedMessage = combineMessage( message );
    winstonLogger.log( formatterMessage( level, combinedMessage ) );
};

logger.prototype.info = function( ...message ) {
    // body...
    var combinedMessage = combineMessage( message );
    winstonLogger.info( formatterMessage( 'info', combinedMessage ) );
};

logger.prototype.debug = function( ...message ) {
    // body...
    var combinedMessage = combineMessage( message );
    winstonLogger.debug( formatterMessage( 'debug', combinedMessage ) );
};

logger.prototype.error = function( ...message ) {
    // body...
    var combinedMessage = combineMessage( message );
    winstonLogger.error( formatterMessage( 'error', combinedMessage ) );
};

logger.prototype.getNamespace = function() {
    // body...
    return getRequest;
};

logger.prototype.useSequelizeCls = function( serviceSequelize ) {
    // body...
    serviceSequelize.useCLS( createRequest );
    Sequelize = serviceSequelize;
    return serviceSequelize;
};

logger.prototype.logger = function( appNameLocal ) { 
    // var createRequest = createNamespace( 'Request-Id' );
    // continuation_local_storage_bluebird( createRequest );
    // continuation_local_storage_redis( createRequest );
    // Sequelize.useCLS(createRequest);
    return function( req, res, next ) {
        // create requestId and append it in header as Request-Id...
        appName = appNameLocal;
        createRequest.run( function( context ) {
            req._logStartTime = process.hrtime();
            on_finished( res, function() {
                res._logEndTime = process.hrtime();
                res._logDiffTime = process.hrtime( req._logStartTime );
                winstonLogger.info( formatterHTTP( 'info', req, res ) );
            } );

            var requestId = req.get( 'Request-Id' ) || req.headers[ 'Request-Id' ] || '';
            // createRequest.bindEmitter( req );
            // createRequest.bindEmitter( res );
            createRequest.set( 'Request-Id', requestId );
            if( requestId === '' ) {
                winstonLogger.error( formatterMessage( 'error', 'Request-Id not found in headers.' ) )
            }
            next();
        } );
    };
};

function formatterMessage( logLevel, message ) {
    var timestamp = dateTimeIST();
    logLevel = getLogLevel( logLevel );
    var requestId = getRequestId();
    var serviceName = getServiceName();
    var formattedMessage = `[${ timestamp }] [${ logLevel }] [${ requestId }] [${ serviceName }] ${ message }`;
    return formattedMessage;
}

function dateTimeIST() {
    return `${ date_time( new Date() ).tz('Asia/Kolkata').format('YYYY-MM-DD HH:mm:ss.SSS') }`;
}

function getLogLevel( logLevel ) {
    return logLevel.toLowerCase();
}

function getRequestId() {
    // var getRequest = getNamespace( 'Request-Id' );
    return getRequest.get( 'Request-Id' ) || '';
    // return getRequest && getRequest.get( 'Request-Id' ) ? getRequest.get( 'Request-Id' ) : '';
}

function getRequestIdAfterFinished( req ) {
    return ( req.get( 'Request-Id' ) || req.headers[ 'Request-Id' ] || '' );
}

function getServiceName() {
    return appName || process.env.APP_NAME || 'local';
}

function formatterHTTP( logLevel, req, res ) {
    var timestamp = dateTimeIST();
    logLevel = getLogLevel( logLevel );
    var requestId = getRequestIdAfterFinished( req );
    var serviceName = getServiceName();
    var httpMessage = buildHTTPMessage( req, res );
    var formattedHTTPMessage = `[${ timestamp }] [${ logLevel }] [${ requestId }] [${ serviceName }] ${ httpMessage }`;
    return formattedHTTPMessage;
}

function buildHTTPMessage( req, res ) {
    return `[${ req.method }] [${ req.originalUrl || req.url }] [${ res.getHeader( 'Content-Length' ) ? res.statusCode : 504 }] [${ res.getHeader( 'Content-Length' ) || 0 }] [${ ( ( res._logEndTime[ 0 ] - req._logStartTime[ 0 ] ) * 1e3 + ( res._logEndTime[ 1 ] - req._logStartTime[ 1 ] ) * 1e-6 ).toFixed(3) }ms]`;
}

function combineMessage( message ) {
    return message.join( ' ' );
}

module.exports = new logger();
4

1 回答 1

1

我们在这里发现的问题是通过 async/await 引入的 Promise

我们尝试使用cls-hooked而不是continuation-local-storage,因为它使用的是异步挂钩,但问题仍然存在。

最近我们尝试了另一个名为async-local-storage 的模块,它解决了我们案例中的问题

于 2019-02-21T07:13:24.087 回答