日志记录
Asciidoctor.js 中的所有警告和错误消息都通过日志记录器进行处理。与输入文档相关的消息还会包括有关源位置的上下文信息(如文件名、文件目录、文件路径、行号),这对集成和工具开发非常有用。
使用 API 时,您可以将自定义日志记录器传递给 LoggerManager
,以捕获、路由或观察这些消息。
日志记录器
默认日志记录器
默认的日志记录器会将所有警告和错误消息输出到 stderr
(标准错误输出流)。
根据您的 JavaScript 环境,stderr
将解析为:
-
在浏览器环境中是 console.warn 函数
-
在 Node.js 环境中是 process.stderr 属性
内存日志记录器
除了默认日志记录器外,Asciidoctor.js 还提供了一个内存日志记录器 MemoryLogger
。这个日志记录器不会将消息输出到 stderr
,而是将其存储在内存中。
首先,您需要使用 create
函数实例化该日志记录器:
const memoryLogger = asciidoctor.MemoryLogger.create()
一旦实例化了日志记录器,您需要告诉 Asciidoctor 处理器使用它:
asciidoctor.LoggerManager.setLogger(memoryLogger)
上述代码将用内存日志记录器替换默认的日志记录器。
错误和警告消息
内存日志记录器会存储 Asciidoctor.js 处理器生成的每条警告和错误消息。处理完成后,您可以使用 getMessages
函数获取所有这些消息:
const loggerManager = asciidoctor.LoggerManager
const memoryLogger = asciidoctor.MemoryLogger.create()
loggerManager.setLogger(memoryLogger)
asciidoctor.convert('input')
memoryLogger.getMessages() // returns an array of Message
对于每条消息,您可以获取以下信息:
const message = memoryLogger.getMessages()[0]
console.log(message.getSeverity()) (1)
console.log(message.getText()) (2)
const sourceLocation = message.getSourceLocation() (3)
if (sourceLocation) {
console.log(sourceLocation.getLineNumber()) (4)
console.log(sourceLocation.getFile()) (5)
console.log(sourceLocation.getDirectory()) (6)
console.log(sourceLocation.getPath()) (7)
}
1 | 返回严重性(ERROR 或 WARNING) |
2 | 返回错误或警告的文本消息 |
3 | 返回源位置的上下文(可能为 undefined) |
4 | 返回与消息关联的源代码行号 |
5 | 返回与消息关联的文件名(如果是从字符串转换,则为 undefined) |
6 | 返回源文件父目录的绝对路径,或者当从字符串转换时为执行路径 |
7 | 返回与消息关联的路径(如果是从字符串转换,则为 <stdin> ) |
日志记录器实例
Asciidoctor.js 处理器只能配置一个日志记录器。如果您想在替换后恢复默认的日志记录器,应该保存一个引用:
const loggerManager = asciidoctor.LoggerManager
const defaultLogger = loggerManager.getLogger() (1)
try {
const memoryLogger = asciidoctor.MemoryLogger.create()
loggerManager.setLogger(memoryLogger) (2)
// convert a document then do something with the in-memory logger
} finally {
loggerManager.setLogger(defaultLogger) (3)
}
1 | 保存默认日志器 |
2 | 用内存日志器替换默认日志器 |
3 | 恢复默认日志器 |
自定义日志记录器
在本节中,我们将说明如何使用流行的日志库 Winston 来替换默认的日志记录器。要实例化一个新的日志记录器,我们可以使用 LoggerManager
的 newLogger
函数:
const winston = require('winston') (1)
const winstonLogger = asciidoctor.LoggerManager.newLogger('WinstonLogger', {
postConstruct: function () {
this.logger = winston.createLogger({
level: 'warning',
format: winston.format.json(),
transports: [
new winston.transports.File({ filename: 'error.log', level: 'error' }),
new winston.transports.File({ filename: 'combined.log' })
]
})
},
add: function (severity, _, message) {
const level = asciidoctor.LoggerSeverity.get(severity).toLowerCase() (2)
logger.log({
level: level,
message: message.getText()
}) (3)
}
})
1 | 导入 Winston 库(必须安装 winston 包:npm install winston ) |
2 | 将严重性(数字)转换为日志级别(如 'error', 'warn' 等) |
3 | 将消息发送到 Winston 日志器 |
日志记录器格式化器
默认日志记录器格式化器
默认的格式化器将以以下人类可读的格式输出消息:
asciidoctor: ${severity}: ${message}
消息可以包含关于源位置的上下文信息。 |
以下是一个使用默认格式化器的示例:
asciidoctor: ERROR: <stdin>: line 8: invalid part, must have at least one section (e.g., chapter, appendix, etc.)
自定义日志记录器格式化器
在本节中,我们将演示如何替换默认格式化器,以将消息输出为 JSON 格式。为此,我们将使用 newFormatter
函数实例化一个新的格式化器,并使用 setFormatter
函数替换日志记录器的默认格式化器:
const loggerManager = asciidoctor.LoggerManager
const defaultLogger = loggerManager.getLogger()
const jsonFormatter = asciidoctor.LoggerManager.newFormatter('JsonFormatter', {
call: function (severity, time, programName, message) {
const text = message['text']
const sourceLocation = message['source_location']
return JSON.stringify({
programName: programName,
message: text,
sourceLocation: {
lineNumber: sourceLocation.getLineNumber(),
path: sourceLocation.getPath()
},
severity: severity
}) + '\n'
}
})
defaultLogger.setFormatter(jsonFormatter)
结果如下:
{"programName":"asciidoctor","message":"invalid part, must have at least one section (e.g., chapter, appendix, etc.)","sourceLocation":{"lineNumber":8,"path":"<stdin>"},"severity":"ERROR"}