使用 Morgan.js 记录 HTTP 请求和错误
Morgan 是一个可用于 Node.js 的中间件,用于记录 HTTP 请求。它主要用于 Express 项目。
Morgan 帮助我们简化了来自应用程序的 HTTP 请求的记录工作,只需一条语句即可。在正常情况下,开发人员通常手动编写所有日志记录代码,然后记录要存储的内容、如何保存以及所有内容的保存位置。
它有助于从您的服务器收集日志并准备读取它们。它还内置了许多预定的默认值来帮助开发人员。它适用于大型项目和小型项目。
设置 Morgan.js
Morgan 可以通过 NPM 的帮助进行安装,就像我们通常对任何 Node.js 模块所做的那样 -
npm install morgan
设置完成后,您可以通过告诉 Node.js 将 Morgan 包含在您的应用程序中来使用此模块。
const morgan = require('morgan')
使用 Morgan 的简单应用程序
现在我们已经熟悉了基础知识,是时候专注于创建一个非常简单的应用程序了,我们将在 Morgan 的帮助下记录日志。请考虑下面显示的代码。
index.js
示例
const express = require('express') const morgan = require('morgan') const app = express() const port = process.env.PORT || 8989 app.use(morgan('combined')) app.get('/', function(req, res) { res.send('TutorialsPoint is Awesome!!!') }) app.listen(port, () => { console.log(`Sample app listening at http://localhost:${8989}`) })
在上面的代码中,我们演示了使用 Morgan 进行日志记录是多么容易。首先,我们导入了 Morgan 包,然后将其添加为中间件,然后向"/"端点发出 GET 请求。
输出
运行代码时,它将在终端上显示以下输出 -
Sample app listening at http://localhost:8989
单击链接时,它将在浏览器上显示以下输出 -
TutorialsPoint is Awesome!!!
然后,它将在终端上打印日志,如下所示 -
::1 - - [28/Sep/2022:05:20:44 +0000] "GET / HTTP/1.1" 304 - "-" "Mozilla/5.0 (Windows NT 6.3; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/104.0.0.0 Safari/537.36"
定义 Morgan 中日志的输出格式
我们可以通过两种方式定义 Morgan 中日志的输出格式。这些是 −
预定义日志 − 这种输出格式意味着有一些预定义的项目可供您记录,而您只需要选择适合您需求的组合即可。
手动设置 − 此手动设置是在令牌的帮助下完成的。
Morgan 中的预定义日志
总共有五种预定义格式,当我们想在 Morgan 的帮助下快速获取信息时,可以使用这些格式。这些是 −
combined − 当我们想要将日志设置为 Apache 标准组合格式时使用它。
common − 它只是指通用格式 Apache 标准。
dev − 它只不过是一种颜色编码的日志格式,这些颜色会随着请求状态而变化。
short − 这是较短的版本,其中打印的项目较少。
tiny − 比短格式更短的版本。
如果您想在 Morgan 中使用"format"功能,您将需要 tokens、req 和 res。
简单来说术语中,res 就是 HTTP 请求,而 res 是 HTTP 响应。
token 就是包含所有声明的 token 的对象。
如果您使用这三个东西,那么如果您认为您不想记录所有内容,该函数将返回一个字符串,该字符串要么是"longline",要么是"null"。
您可以使用的另一种预定义格式是 −
app.use(morgan('tiny'))
预定义标记的 format 字符串将如下所示 -
app.use(morgan(':method :url :res[content-length] - :response-time ms'))
还要注意,预定义格式字符串可以产生与预定义标记相同的结果。
"Tiny"格式的输出将如下所示 -
GET / 201 - - 45.730 ms
日志标记
如前所述,我们甚至可以创建自己的自定义标记和日志格式,以替代使用预定义格式。Morgan 确实可以完全访问 HTTP 请求和响应的内容。换句话说,这意味着即使应用程序使用自定义 HTTP 标头,Morgan 仍然能够记录它们。
这个想法是,如果您希望自定义中间件例程,则必须生成令牌,这可以通过使用名称和回调函数调用 morgan.token() 函数来完成,该函数将用于创建令牌。
思考令牌的一种方法是,它们只不过是我们可以在中间件格式字符串中使用的基本占位符。预定义格式确实可以有效地执行相同的操作,但您始终可以匹配和混合 13 个令牌中的任何一个,以获得所需的确切日志行。
Morgan 为您提供了一个与客户端的用户代理、请求的 URL 和响应时间等完全相同的令牌。
现在让我们考虑这样一种情况,我们有一个应用程序生成一个名为"type-of-user"的自定义 HTTP 标头,并且我们想要记录此标头的内容。我们可以使用下面显示的代码片段来实现这一点。
morgan.token('type-of-user', function(req, res) { return req.headers['type-of-user'] })
上述代码生成了一个新的自定义令牌,我们可以借助 Morgan 日志格式通过添加":type-of-user"将其记录在我们的代码中。
app.use(morgan(':method :url :status :type-of-user'));
它将在终端上记录以下内容 -
Server listening on port :8989 GET / 201 user
将日志保存在文件中
有时我们也希望将日志重定向到特定文件,而不是简单地将它们转储到控制台或终端中的应用程序输出。
在 Morgan 中,我们可以通过创建一个新的 Stream 对象然后将其提供给中间件来执行相同操作。然后,我们将能够将记录器的输出路由到单个文件。考虑下面显示的代码片段。
let logStream = fs.createWriteStream(path.join(_dirname,'output.log'), { flags: 'a' }) // setting up the logger app.use(morgan('update', { stream: logStream }))
我们能够将日志重定向到外部文件的这一概念有助于提高开发人员的灵活性。
index.js
Morgan 的包含多个"预定义"和"logStream"的最终代码如下所示。
const express = require('express') const morgan = require('morgan') const Writable = require("stream").Writable const app = express() const port = process.env.PORT || 8989 let logStream = fs.createWriteStream(path.join(_dirname, 'output.log'), { flags: 'a' }) // setting up the logger app.use(morgan('update', { stream: logStream })) class MyStream extends Writable { write(line) { console.log("Logger - ", line) } } // Create a new format morgan.token("timed", "A new :method request added for the :url. " + "In total, it took :total-time[2] milliseconds to be resolved") let writer = new MyStream() // Use the new format by name app.use(morgan('timed', { stream: writer })) app.get('/', function(req, res) { res.send('TutorialsPoint is Awesome!') }) app.listen(port, () => { console.log(`Application listening at http://localhost:${port}`) })
结论
在本教程中,我们解释了如何使用 Morgan 库来记录文本并将其用作应用程序中的中间件。此外,我们还讨论了可用的预定义格式和自定义格式类型,最后我们借助几个示例探讨了如何使用它们。