GVKun编程网logo

如何在多个模块中使用Winston?(多个模块相互调用)

18

在这里,我们将给大家分享关于如何在多个模块中使用Winston?的知识,让您更了解多个模块相互调用的本质,同时也会涉及到如何更有效地angular–在模块中使用另一个模块:在路由中导入vs使用load

在这里,我们将给大家分享关于如何在多个模块中使用Winston?的知识,让您更了解多个模块相互调用的本质,同时也会涉及到如何更有效地angular – 在模块中使用另一个模块:在路由中导入vs使用loadChildren、Angular2组件在多个模块中声明、angularjs – 你能从一个模块中的Controller向另一个模块中的指令控制器发出事件吗?、javascript – 使用winston,morgan和winston-daily-rotate-file实现记录器的内容。

本文目录一览:

如何在多个模块中使用Winston?(多个模块相互调用)

如何在多个模块中使用Winston?(多个模块相互调用)

我有几个模块-假设是server.js,module1.js,…,moduleN.js。

我想在server.js中定义日志文件:

winston.add(winston.transports.File, { filename: ''mylogfile.log'' });

然后在我所有的模块中使用它

最好的方法是什么?我可以exports.winston=winston;在每个模块中,然后在server.js中进行设置,但是还有更好的解决方案吗?

先感谢您!

答案1

小编典典

默认的记录器概念很好地解决了这一问题。

Winston定义了一个默认记录器,任何对Winston的直接要求(及其后要求)都将检索该记录器。因此,您只需配置一次此默认记录器,即可通过其出色的调整后的多传输模式中的vanilla
require(’winston’)进行后续模块使用。

例如,这是我定义3种传输方式的完整日志记录设置。我有时将Loggly换成MongoDB。

server.js

var logger=require(''./log.js''); // requires winston and configures transports for winstons default logger- see code below.

所有其他.js文件

var logger=require(''winston''); // this retrieves default logger which was configured in log.jslogger.info("the default logger with my tricked out transports is rockin this module");

log.js-这是DEFAULT记录器的一次性配置

var logger = require(''winston'');var Loggly = require(''winston-loggly'').Loggly;var loggly_options={ subdomain: "mysubdomain", inputToken: "efake000-000d-000e-a000-xfakee000a00" }logger.add(Loggly, loggly_options);logger.add(winston.transports.File, { filename: "../logs/production.log" });logger.info(''Chill Winston, the logs are being captured 3 ways- console, file, and Loggly'');module.exports=logger;

另外,对于更复杂的情况,您可以使用Winston容器并从其他模块中的命名容器中检索记录器。我没有用过

我唯一的问题是部署主机上缺少日志目录,该目录很容易修复。

希望这可以帮助。

angular – 在模块中使用另一个模块:在路由中导入vs使用loadChildren

angular – 在模块中使用另一个模块:在路由中导入vs使用loadChildren

在我对Angular的探索中,我发现了两种可能的方法来在另一个模块中使用一个模块.

(使用angular-express-starter project作为参考)

>方法1:
在进口数组中声明它. For example

@NgModule({
  declarations: [
    AppComponent
  ],imports: [
    browserModule,SharedModule,FormsModule
  ]
})

>方法2:
使用loadChildrenin路由. For example:

export const routes: Route[] = [
  { path: '',pathMatch: 'full',redirectTo: 'weather'},{ loadChildren: 'app/dashboard/dashboard.module#DashboardModule',path: 'dashboard' },{ loadChildren: 'app/profile/profile.module#ProfileModule',path: 'profile' },{ loadChildren: 'app/weather/weather.module#WeatherModule',path: 'weather' }
];

这两种方法有什么实际差异?

解决方法

What are the practical differences between these two methods?

最大的区别是通过loadChildren加载的模块将拥有自己的注入器,而来自导入模块的提供程序将合并到一个根注入器中.这意味着您无法将延迟加载模块中的提供程序注入其他延迟加载的模块中.

其他差异:

>如果不使用路由,则无法使用loadChildren
>只有在导航到相应路径时才会加载通过loadChildren加载的模块

有关更多信息,请阅读

> Avoiding common confusions with modules in Angular

Angular2组件在多个模块中声明

Angular2组件在多个模块中声明

我的Angular2 RC6应用程序有两个模块,我不知道如何声明共享组件.

我有一个名为spinnerComponent的组件,它在整个应用程序中使用.我在app.modules.as中定义了它:

@NgModule({
    imports: [browserModule,routing,RepairReturnModule],providers: [ ],declarations: [AppComponent,SpinnerComponent],bootstrap: [AppComponent]
})

然后在RepairreturnModule中我再次定义它:

@NgModule({
    imports: [CommonModule],declarations: [
        SpinnerComponent
    ],providers: []
})

正如所料,我得到:

Type SpinnerComponent is part of the declarations of 2 modules:
RepairReturnModule and AppModule

我从RepairreturnModule中的声明中删除了SpinnerComponent,然后我得到:

Unhandled Promise rejection: Template parse errors: Can’t bind to
‘isRunning’ since it isn’t a kNown property of ‘spinner-component’.
1. If ‘spinner-component’ is an Angular component and it has ‘isRunning’ input,then verify that it is part of this module.
2. If ‘spinner-component’ is a Web Component then add “CUSTOM_ELEMENTS_SCHEMA” to the ‘@NgModule.schema’ of this component
to suppress this message. … which indicated that it is not declared.

我错过了什么?

解决方法

看到完整的代码将是有益的,但无论如何……

您可以尝试将微调器移回修复模块,然后从应用程序模块中将其导入.我使用单独的(在你的情况下它将是第三个)’共享’模块,其中共同的功能坐在这里,所以每个其他模块可以从那里导入它.

angularjs – 你能从一个模块中的Controller向另一个模块中的指令控制器发出事件吗?

angularjs – 你能从一个模块中的Controller向另一个模块中的指令控制器发出事件吗?

我在一个单独的模块“app”和“directiveModule”中分别有一个控制器“MyController”和一个指令“MyDirective”. DirectiveModule已被注入“app”的angular.module中.

我遇到的问题是作为“app”的一部分,我有一个控制器发出一个事件“TEST”,指令的控制器没有接收.如何成功获取自己模块的指令来捕获发射?这可能吗? (注意:我最初尝试过$scope,然后使用$rootScope,但两者都没有区别.)

我的控制器:

app.controller('MyController',function($scope,$rootScope) {
  $rootScope.$emit('TEST');
});

我的指示:

directiveModule.directive('MyDirective',['$rootScope','MyService',function($rootScope,MyService) {

return {
   restrict: 'E',controller: ['$scope','$rootScope',$rootScope) {
        $rootScope.$on('TEST',function() {alert("Event Caught")})

}]};
}];

更新:看起来我的指令尚未在广播事件发布时启动.是否有办法让我可以“等待指令实例化”而不是等待“1000”ms的仲裁或其他替代方案?

解决方法

我认为你的指令需要捕获该事件的唯一情况是根据MyController获取一些初始数据,因为如果你的指令独立于MyController,你不需要捕获该事件,只需单独启动指令即可.

我的解决方案是使用$watch在MyController的初始数据准备就绪时收到通知.

app.controller('MyController',function($scope) {
   $scope.data = {}; //initialize the data,this data Could be fetched from an ajax
});

directiveModule.directive('MyDirective',['MyService',function(MyService) {

return {
   restrict: 'E',function($scope) {
        $scope.$watch("data",function(newValue,OldValue,scope){
             //do your work here when data is changed.
        });  
    }]};
}];

如果您在指令中使用隔离范围:

directiveModule.directive('MyDirective',function(MyService) {

    return {
       restrict: 'E',scope : {
           directiveData:"=",},function($scope) {
            $scope.$watch("directiveData",scope){//watch on the directive scope property
                 //do your work here when data is changed.
            });  
        }]};
    }];

你的HTML可能如下所示:

<my-directive directive-data="data" /> //bind isolate scope directive property with controller's scope property.

我认为以下问题是类似的情况:

> AngularJS : Directive not able to access isolate scope objects
> AngularJS : directives and scope

javascript – 使用winston,morgan和winston-daily-rotate-file实现记录器

javascript – 使用winston,morgan和winston-daily-rotate-file实现记录器

我正在尝试在节点js中实现一个记录器,它将在日志的自定义格式上每天创建一个新的日志文件

为此,我使用了三个包

> winston
> morgan
> winston-daily-rotate-file

所以每天应该在日志文件夹中创建一个新的日志文件的最终输出,它应该将所有http(摩根日志)和键入的日志(winston日志)记录到以下格式的单个文件中

日期||文件名|| statusCode || logMessage || uuid(用于追踪)

例如:Fri Jan 18 2019 13:48:18 GMT 0530(IST)|| [index.js] || 200 ||调用新路径|| 287dccb0-1afa-11e9-88a0-dfb1c665be9d

所以为此,我写了三个文件index.js(nodejs的根文件)logger.js(logger实现和配置)和logger.test.js(使用jest的logger测试用例)

额外的包

> cors
> uuid
> http-context
> app-root-path
> express-http-context
> jest

我遇到的问题

>如果我在app.listen上的index.js中放入一个logger.error({message:{statusCode:200,logMsg:“服务器将在端口3000中启动”}}},之后再转到console.log()uuid一片空白
>我写的测试用例是错误的,我是开玩笑的新手,我只想知道如何检查所有这些情况.
>为什么当我测试套装uuid为null时,我怎么能通过uuid测试用例呢
>我如何检查是否将创建新文件夹,如果已经登录文件夹,那么新文件就会被创建一种测试用例.
>我如何添加其他级别,信息,debuge,警告基于环境.如何改进此代码以实现记录器功能

// index.js

const app = require('express')();
const cors = require('cors')
const morgan = require('morgan') // HTTP request logger middleware 
const logger = require('./config/logger')(module) //Logger
const uuid = require('uuid')
const httpContext = require('express-http-context')

// Use any third party middleware that does not need access to the context here
// app.use(some3rdParty.middleware);

app.use(httpContext.middleware);
// all code from here on has access to the same context for each request

// Run the context for each request.
// Assigning a unique identifier to each request
app.use((req,res,next) => {
  httpContext.set('reqId',uuid.v1());
  next()
})


// using morgan with winston(logger)
app.use(morgan('combined',{
  stream: {
    write: (message) => logger.error(message)
  }
}))


app.use(cors());

app.use("/new",(req,res) => {
  logger.error({
    message: {
      statusCode: 400,logMsg: "hitting new route"
    }
  })
  nextLayer(res)
})

const nextLayer = (res) => {
  logger.error({
    message: {
      statusCode: 400,logMsg: "hitting in nextLayer function"
    }
  })
  res.send("OK")
}

app.listen(4000,() => {
  console.log('Server running on port 4000');
})





// Logger.js

const appRoot = require('app-root-path')
const {
  createLogger,format,transports
} = require('winston')
const {
  combine,timestamp,label,printf
} = format
const path = require('path')
require('winston-daily-rotate-file');
const httpContext = require('express-http-context')

/**
 * @method checkMessageProp
 * @param {message} can be object if developer defined,else it will be string
 *                  if its a network request
 * @returns a fixed format how the status code and message should show
 */
const checkMessageProp = (message) => {
  switch (typeof message) {
    case "object":
      const {
        statusCode,logMsg
      } = message
      return `${statusCode ? statusCode : "Not Defined"} || ${logMsg ? logMsg : "Not Defined"}`;
    case "string":
      let messageSplit = message.split(`"`)
      var message = messageSplit ? `${messageSplit[2].trim().split(" ")[0]} || ${messageSplit[1]}` : null
      return message
    default:
      return message
  }
}

/**
 * @method customFormat
 * @param {log} the log passed by the developer or based on network requests
 * @returns a customFormat how it should be logged to the log files
 */
const customFormat = printf(log => {
  const Now = new Date();
  const reqId = httpContext.get('reqId');
  return `${log.timestamp ? new Date(log.timestamp) : Now} || [${log.label}] || ${checkMessageProp(log.message)} || ${reqId ? reqId : null}`
});

/**
 * @method getFileName
 * @param {moduleObj} the module realted object passed from the require of logger file 
 * @returns the file name where the logger was invoked
 */
const getFileName = moduleObj => {
  if (Object.keys(moduleObj).length > 0) {
    let parts = moduleObj.filename.split(path.sep)
    return parts.pop()
  } else {
    return "Module not passed while requiring the logger"
  }
}

// Custom settings for each transport 
const options = moduleObj => {
  return {
    dailyRotateFile: {
      filename: `${appRoot}/logs/TPS-UI-%DATE%.log`,datePattern: 'YYYY-MM-DD',prepend: true,level: "error",timestamp: new Date(),localTime: true
    }
  }
}

// Instantiate a Winston Logger with the settings
let logger = moduleObj => {
  return createLogger({
    format: combine(
      label({
        label: getFileName(moduleObj)
      }),customFormat
    ),transports: [
      new transports.DailyRotateFile(options(moduleObj).dailyRotateFile)
    ],exitOnError: false // do not exit on handled exceptions
  })
}



module.exports = logger








// logger.test.js

const logger = require('./logger')

beforeEach(() => {
  mockLoggerMessageObject = {
    message: {
      statusCode: 400,logMsg: "Calling in test suite"
    }
  }
  mockLoggerMessageString = `::ffff:127.0.0.1 - - [18/Jan/2019:04:50:57 +0000] 
                               "GET /new HTTP/1.1" 200 2 "http://localhost/" "Mozilla/5.0 
                               (linux) AppleWebKit/537.36 (KHTML,like Gecko) jsdom/11.12.0"`
  mockLoggerMessageNumberFormat = 123
  mockLoggerMessageArrayFormat = ["data","test",123]
})

describe(`Logger test cases`,() => {
  test('should invoke the logger function with the mock Logger message object',() => {
    expect(logger(module).error(mockLoggerMessageObject)).tobedefined()
  })
  test(`should invoke the logger function with empty object`,() => {
    expect(logger(module).error({})).tobedefined()
  })
  test(`should invoke the logger function without any module object`,() => {
    expect(logger({}).error(mockLoggerMessageObject)).tobedefined()
  })
  test(`should invoke the logger function without any module and message object`,() => {
    expect(logger({}).error({})).tobedefined()
  })
  test(`should invoke the logger function with the http request`,() => {
    expect(logger(module).error(mockLoggerMessageString)).tobedefined()
  })
  test(`should invoke the logger function with the number format`,() => {
    expect(logger(module).error(mockLoggerMessageNumberFormat)).tobedefined()
  })
  test(`should invoke the logger function with the array format`,() => {
    expect(logger(module).error(mockLoggerMessageArrayFormat)).tobedefined()
  })

})
最佳答案
对于winston我正在使用timestamp(),这样它会自动将timestamp()属性添加到对象

const {transports,createLogger,format} = require('winston');
const logger = createLogger({
        format: format.combine(
            format.timestamp(),format.json()
        ),

另外要检查它是否创建文件你可以模拟日期,说2019-01-01并检查它是否创建文件2019-01-01.log
比将日期移至2019-01-02并记录其他内容.
Winston将创建新的文件夹和gzip存档,您可以检查文件是否存在,并且可以解压缩并包含信息

尝试阅读winston的文档.
基本上我会说你可能需要使用

format.timestamp()
format.json()
colorize()

dailyRotate with zippedArchive:true

如果摩根不适合您的需求,您可以尝试直接登录

app.use((req,next) => { 
    logger.silly({ message:'start',req,res}); 

    return next().then(r=>logger.silly({ message:'end',res}; return r;);
}

我们今天的关于如何在多个模块中使用Winston?多个模块相互调用的分享就到这里,谢谢您的阅读,如果想了解更多关于angular – 在模块中使用另一个模块:在路由中导入vs使用loadChildren、Angular2组件在多个模块中声明、angularjs – 你能从一个模块中的Controller向另一个模块中的指令控制器发出事件吗?、javascript – 使用winston,morgan和winston-daily-rotate-file实现记录器的相关信息,可以在本站进行搜索。

本文标签: