使用 Morgan.js 记录 HTTP 请求和错误
Morgan 是一个可用于 Node.js 的中间件,当我们需要记录 HTTP 请求时可以使用它。它主要用于 Express 项目。
Morgan 帮助我们通过单一语句简化应用程序发送和接收的 HTTP 请求的日志记录工作。在正常情况下,开发人员经常手动编写所有日志记录代码,最终需要记录要存储的内容、如何保存以及所有内容的保存位置。
它有助于收集服务器日志并准备读取。它还内置了许多预定义的默认值来帮助开发人员。它适用于大型项目和小型项目。
设置 Morgan.js
像我们通常对任何 Node.js 模块一样,可以使用 NPM 安装 Morgan:
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 https://127.0.0.1:${8989}`) })
在上面的代码中,我们演示了使用 Morgan 进行日志记录的简易性。首先,我们导入了 Morgan 包,然后将其添加为中间件,当我们向 "/" 端点发出 GET 请求时。
输出
运行代码时,它将在终端上显示以下输出:
Sample app listening at https://127.0.0.1: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 - 比 short 格式更短的版本。
如果你想在 Morgan 中使用“format”函数,则需要tokens、req 和res。
简单来说,req 就是 HTTP 请求,res 就是 HTTP 响应。
token 就是一个包含所有已声明令牌的对象。
如果你使用这三样东西,那么该函数将返回一个字符串,该字符串将是“长行”或“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'] })
上面的代码生成一个新的自定义令牌,我们可以通过添加“:type-of-user”在 Morgan 日志格式的代码中记录它。
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 https://127.0.0.1:${port}`) })
结论
在本教程中,我们解释了如何使用 Morgan 库记录文本并将其用作应用程序中的中间件。此外,我们讨论了可用的预定义格式和自定义格式的类型,最后我们通过几个示例探讨了如何使用它们。