本章节的主题是console,笔者原有一篇博文其实已经比较详细的讨论了相关的内容,这里主要是为了Nodejs开发进阶这个系列内容整体的完整性考虑。大部分内容来自原有的博文,小部分内容进行了增加和修改。
关于Console
Console,一般译为"控制台",笔者这个翻译还是不是特别准确和直观。我们经常在新闻中看到卫星发射的控制中心,前面有一个大屏幕,会在发射过程中,显示各种发射中的状态和数据,那就是控制台了。更准确的说,那是"显控台",因为不仅是可以显示信息,也可以输入和操作控制指令。
程序中的控制台就简陋多了,基本上只是输出信息,不能输入指令(因为),但这部分的基本功能是一样的。一般情况下,就是除了程序内部的数据处理输出之外,还提供了另外的一个渠道,可以向外部输出程序运行的状态和一些运行中间数据,目的是监控程序运行是否正常,或者在开发过程中跟踪一些数据或者状态,确认程序是否按照设计和期望正确的运行。
基于实现简单,不能过于干扰和侵入主程序的考虑,一般程序控制台的功能都设计的非常简单,就是向预定义的输出设备,输出一些文本信息,经常也被称为log(日志)。
控制台信息
鉴于前面的理解,我们应该认真思考在应用开发和运行过程如何合理的使用控制台。笔者觉得,可能需要将控制台的使用在开发测试和生产阶段区别配置和使用。console本身是一个开发的架构,它不限制开发人员何时或者怎样使用,完全由开发者决定。所以我们需要先来确定哪些内容和信息需要被输出或者记录。笔者简单整理如下:
- 调试信息
这个场景是最常见的。就是在开发和测试。对于有疑问的代码或者流程,可以在代码中设置相关的监测点,使用console来打印一些程序运行过程中的信息,比如变量的值、流程阶段标志等等。
除了普通的console系统之外,对于部署或者生产环境中,一般建议使用更专业和独立的日志系统,而不是直接使用console。因为它的可配置性比较差,和程序的耦合也比较强。这部分信息已经超出了本文讨论的内容,这里就不在展开了。
- 运行信息状态
在进行迁移或者部署到其他环境的时候,有些环境的信息会发生变化,这时开发者需要确认这些配置信息和状态是正确的,通常使用console来输出这些信息。
比如笔者经常使用这种方式来确认HTTP服务启动绑定的地址和端口,确认数据库连接正常等等。这种操作一般都是在初始化的时候进行,不会频繁操作,一般不会对系统性能和运行造成太大影响。
- 关键变量
通常是根据业务需求,在测试或者部署阶段,需要跟踪的一些关键的变量或者流程,确认信息正确或者流程工作正常。比如在一些全局变量被修改的时候,开发者需要确认这个操作并知晓相关的值,就可以使用console来进行跟踪和输出。
- 错误信息
对于一些比较关键的操作或者处理,当出错的时候,开发者希望获得错误的反馈信息,甚至包括相关的细节,从而能够为程序的后续改进提供依据。
正常情况下,经过测试后上线的系统,很多错误并不是程序本身的问题,而是错误数据导致的,这时候开发者或者运维人员也希望了解这些错误数据是如何造成程序错误,并在数据和系统维护工作中尽量避免这些情况的出现。这时候也需要尽量的在错误发生时尽量了解相关的技术细节。
比如笔者在SQL操作类中,定义了一个全局的错误捕获机制,当有SQL程序执行错误时,会将其打印出来并记录到日志中,以备后续排查。
结构
我们一般在使用console的时候,比如在开发应用过程中的源代码中,是可以直接使用console这个对象的。笔者理解这应该是一个默认的全局变量。但实际上Console还是一个类,可以将其实例化,实例化的目的应该是定义不同的输出方式。我们一般不会搞得那么复杂,就直接使用那个默认得全局实例变量就可以了。
通过查阅技术文档,我们可以看到Console这个类的结构,在nodejs官方技术文档中,有相关的章节。当然最简单的方式,就是使用REPL环境,可以直接看到console这个类的定义:
js
> console
Object [console] {
log: [Function: log],
warn: [Function: warn],
dir: [Function: dir],
time: [Function: time],
timeEnd: [Function: timeEnd],
timeLog: [Function: timeLog], name
trace: [Function: trace],
assert: [Function: assert],
clear: [Function: clear],
count: [Function: count],
countReset: [Function: countReset],
group: [Function: group],
groupEnd: [Function: groupEnd],
table: [Function: table],
debug: [Function: debug],
info: [Function: info],
dirxml: [Function: dirxml],
error: [Function: error],
groupCollapsed: [Function: groupCollapsed],
Console: [Function: Console],
profile: [Function: profile],
profileEnd: [Function: profileEnd],
timeStamp: [Function: timeStamp],
context: [Function: context]
}
应用
作为主要功能就是输出信息的工具,console就是使用各种方式,像预定的输出设备(默认时stdout)输出信息,所以那些主要方法的差异就是输出的形式略有差别。
- .debug: 输出调试信息
- .info: 普通程序运行信息
- .log: 日志方式
- .warn: 警告类型信息
- .error: 错误类型的信息,注意其输出通道是stderr
稍微增加一点花样,可以对特定的需求简化程序编写的:
- .time/.timeLog/.timeEnd: 可以对计时器进行命名和计时,还可以支持中间计时点
- .count: 命名并使用计数器
- .group/.groupEnd: 安装分组输出信息
- .table: 为JSON array输入表格
- .dirxml: 以xml格式输出信息
- .assert: 根据断言结果输出信息
- .trace: 可以输出当前代码的调用堆栈和位置
- .content: 输出上下文信息
- .clear: 清理console输出内容
输出重定向
nodejs环境中,默认情况下,console的输出目标就是其调用环境,如linux系统中的命令行环境。但可能由于业务或者管理的需求,需要调整记录和输出的目标,可以对其进行重定向。方法是新建console实例时,指定输出目标,参考代码如下:
js
const output = fs.createWriteStream('./stdout.log');
const errorOutput = fs.createWriteStream('./stderr.log');
// Custom simple logger
const logger = new Console({ stdout: output, stderr: errorOutput });
// use it like console
const count = 5;
logger.log('count: %d', count);
// In stdout.log: count 5
这里的输出目标有两个,一般输出目标和错误信息输出目标,可以使用写入流的方式。代码中使用的是文件写入流。我们可以理解,如果这个写入流是一个网络上的日志系统,这些console日志就会被记录到那些系统中。
浏览器
console不仅可以在nodejs中使用,也可以在浏览器环境中使用(下图),使用的方式基本相同,但有一点差异:
- 输出设备: 浏览器的开发工具提供了专门的console模块和页面来处理相关的功能
- 有一些专用的方法如profile、profileEnd、timeStamp等,只能在浏览器环境中使用
小结
本文讨论了在nodejs开发中,console控制台的基本概念,使用场景和主要的应用方式,并简单解读了相关技术文档和类定义的相关内容。合理并正确的使用console,可以有力的支持开发工作。