- xml - AJAX/Jquery XML 解析
- 具有多重继承的 XML 模式
- .net - 枚举序列化 Json 与 XML
- XML 简单类型、简单内容、复杂类型、复杂内容
我正在尝试在 Node js 中实现一个记录器,它将每天以自定义格式的日志创建一个新的日志文件
为此我使用了三个包
所以最终输出应该每天在日志文件夹中创建一个新的日志文件,它应该将所有 http( morgan 日志)和键入的日志(winston 日志)记录到以下格式的单个文件中
日期 ||文件名 ||状态码 ||日志消息 || uuid(用于跟踪)
例如:2019 年 1 月 18 日星期五 13:48:18 GMT+0530 (IST) || [index.js] || 200 ||调用新路由 || 287dccb0-1afa-11e9-88a0-dfb1c665be9d
为此我写了三个文件 index.js(nodejs 的根文件)logger.js(记录器实现和配置)和 logger.test.js(使用 jest 的记录器测试用例)
附加包
我遇到的问题
// 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
如果morgan不符合你的需求你可以尝试直接登录
app.use((req, res, next) => {
logger.silly({ message:'start', req,res});
return next().then(r=>logger.silly({ message:'end', req,res}; return r;);
}
关于javascript - 使用 winston 、 morgan 和 winston-daily-rotate-file 实现记录器,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54250372/
如果我调用会发生什么变化 schedule->call(function() { .. do something ... })->daily() 如果我打电话 schedule->job(... my
Google Play 控制台中有一个名为“安装事件”(每日安装事件)的新指标。我只是将这些指标与经典的“用户安装量”进行了比较(我有法语版的控制台,我认为控制台上的英文翻译是每日“每个用户的安装量”
题目地址:https://leetcode.com/problems/daily-temperatures/description/ 题目描述 Given a list of daily temp
这个问题在这里已经有了答案: "TypeError: string indices must be integers" when getting data of a stock from Yahoo
嘿嘿,我知道如何在 SharedPreferences 中保存变量和其他数据,但我想知道如何每天递减一个变量。 这个 var (int) 已经在共享首选项中,并且我们每天递减 -1。 例如,我知道用户
我需要让我的 Java 程序每天在 linux 机器上运行一次。所以我创建了一个只有一行的简单文件: java -jar /opt/location/my_jar.jar 并将它放在 etc/cron
我在 cron.daily 中有几个 cron 作业,它们应该每天执行。我知道这些任务已执行,因为我可以看到最终结果。例如:我正在备份 MySQL 数据库,我可以看到备份文件。但是,我找不到这方面的日
我的 CentOS 7.4 安装了 logrotate 3.8.6。我在 /etc/logrotate.d/ 下有一个自定义 logrotate 文件,用于轮换安装在同一台机器上的 Tomcat(例如
我一直在摆弄cron。如果您安排一个脚本每天运行,而您的计算机在 acron 安排它时关闭,如果您在当天晚些时候打开您的计算机,它会运行吗? 最佳答案 cron.daily 计划每天在特定时间运行一次
我们目前正在为本地报纸准备 iPhone 应用程序。几周后,该报将在其网站上实现付费内容和免费内容。计划将有多种方式购买此内容: 单篇文章 每日订阅 每月订阅 按年订阅 还应允许注册用户访问 iPho
我有一个脚本可以每天随时运行。所以/etc/cron.daily似乎是一个简单的解决方案。 但是现在我遇到了问题,cronjob 不会运行该脚本。似乎 cronjob 不会运行任何日常工作。 所以我试
有谁知道如何获取Bing“每日手机壁纸”地址。如果您通过 iPhone 访问 bing.com,您将看到漂亮的壁纸。Bing 每天都会更改,并提供纵向和横向两种分辨率格式。 比如今天的Bing手机壁纸
我正在尝试创建一个循环异步任务来调用带有 JobScheduler 和 JobService 的 Web 服务。但我的想法是尝试每天执行一次此任务,并且始终在同一时间执行。甚至可以让用户更新任务启动日
我在数据库中有一个表statistics: CREATE TABLE `statistics` ( `id` INT UNSIGNED NOT NULL AUTO_INCREMENT, `ti
当我在 Android Developer Console 中查看我的“每日设备安装量”时,这些数字与 Google 支付的费用没有任何相似之处。 任何人都可以阐明这一点吗?例如,根据 Google
我正在尝试实现本地通知 这是我设置的 // Current date NSDate *date = [NSDate date]; // Add one minute to th
我在 Spring 应用程序中通过 Lombok 和 @Slf4j 注释使用 Logback,因此我的日志记录配置在 logback-spring.xml 文件中。一般日志记录工作正常,但问题是我正在
在this tutorial在 Daily inspirations 的部分,他说: $quote = array( 1 => "Quote 1", 2 => "Quote 2", 3 => "Quo
我有使用 Net::Finger 的 perl 程序并已从 cron.daily 成功运行在 Fedora 11 中。 我刚刚将服务器升级到 Fedora 18,这些相同的 perl 程序不再从 cr
我以每月 25 美元的价格升级到“Flame”订阅,因为它支持 Daily private backups . 日常备份应该上传到 Google Cloud Storage 或 Amazon S3。
我是一名优秀的程序员,十分优秀!