前端进阶之旅前端进阶之旅
基础篇
进阶篇
高频篇
精选篇
手写篇
面经篇
AI 篇
原理篇
每日一题
小程序题库
知识卡片
  • 场景篇按分类整理的大前端场景考点
  • 历年面经按年份追踪真实考点
  • 算法题库NEW在线编码即时判题
  • 专项自测100 题快速查漏
  • 前端基础
    • HTTP从报文一路讲到 HTTPS
    • 浏览器渲染、事件循环、进程
    • 计算机基础Linux、网络、操作系统
  • 进阶专项
    • 设计模式23 种模式怎么用
    • 前端系统进阶学习大型项目工程化
    • 前端综合文章长期沉淀的实践文
  • 工程与工具
    • Node学习指南从环境搭建到服务端
    • NPM工作流script、依赖与发布
    • Docker容器化部署上手
    • Canvas图形与动画实战
  • 路线与导图
    • 思维导图知识点全景图
    • 学习路线按图索骥不跑偏
  • 动态
    • 公众号动态公众号历史文章
    • 博客动态站长的技术博客
    • 开发者导航常用工具与文档站
  • AI 助手随时提问,即时解析
  • AI 模拟面试模拟真实面试 + 报告
  • AI 知识地图串起全站知识点
  • AI 定制路线按你的简历现排
AI 热点
旧版
基础篇
进阶篇
高频篇
精选篇
手写篇
面经篇
AI 篇
原理篇
每日一题
小程序题库
知识卡片
  • 场景篇按分类整理的大前端场景考点
  • 历年面经按年份追踪真实考点
  • 算法题库NEW在线编码即时判题
  • 专项自测100 题快速查漏
  • 前端基础
    • HTTP从报文一路讲到 HTTPS
    • 浏览器渲染、事件循环、进程
    • 计算机基础Linux、网络、操作系统
  • 进阶专项
    • 设计模式23 种模式怎么用
    • 前端系统进阶学习大型项目工程化
    • 前端综合文章长期沉淀的实践文
  • 工程与工具
    • Node学习指南从环境搭建到服务端
    • NPM工作流script、依赖与发布
    • Docker容器化部署上手
    • Canvas图形与动画实战
  • 路线与导图
    • 思维导图知识点全景图
    • 学习路线按图索骥不跑偏
  • 动态
    • 公众号动态公众号历史文章
    • 博客动态站长的技术博客
    • 开发者导航常用工具与文档站
  • AI 助手随时提问,即时解析
  • AI 模拟面试模拟真实面试 + 报告
  • AI 知识地图串起全站知识点
  • AI 定制路线按你的简历现排
AI 热点
旧版
  • 基础篇

    • 环境搭建
    • node部署
    • 基础应用
  • 内置模块

    • 1.0 本地路径处理 path
    • 2.0 文件系统操作 fs
    • 3.1 基础调试 console
    • 3.2 本地调试远程服务器上的Node代码
    • 4.1 网络服务 http
    • 4.2 网络服务 http res
    • 4.3 网络服务 http req
    • 4.4 网络服务 http server
    • 4.5 网络服务 http client
    • 4.6 网络服务 https
    • 4.7 网络TCP net
    • 4.8 网络UDP dgram
    • 4.9 域名解析 dns
    • 5.0 网络地址解析 url
    • 5.1 URL查询字符串 querystring
    • 6.1 流操作 stream
    • 6.2 逐行读取 readline
    • 7.1 进程相关 process
    • 7.2 子进程 child
    • 8.1 二进制数据 buffer
    • 8.2 二进制解码 string_decoder
    • 9.1 事件机制 events
    • 9.2 实用工具模块 util
    • 9.3 数据加密 crypto
    • 9.4 MD5入门介绍及crypto模块的应用
    • 9.4 资源压缩 zlib
    • 9.5 集群 cluster
    • 9.6 v8
  • 进阶篇

    • 5分钟入门非对称加密用法
    • cluster
    • cookie_parser深入
    • crypto模块之理论篇
    • express+cookie_parser签名机制深入剖析
    • express+session实现简易身份认证
    • https
    • log4js入门实例
    • node8_napi
    • 使用 async 控制并发
    • 使用 eventproxy 控制并发
    • 使用 superagent 与 cheerio 完成简单爬虫
    • 基于express+muter的文件上传
    • 将图片转成datauri嵌入到html
    • 常用中间件 body_parser 实现解析
    • 日志模块morgan
    • 服务端字符编解码&乱码处理 charset_enc_dec
    • 测试用例mocha,should,istanbul
    • 调试日志打印debug模块
  • Express

    • 1.1 Express概览篇
    • 1.2 Express
  • Koa2

    • 1.0 koa2概览篇
    • 1.1 快速开始
    • 1.2 async await使用
    • 1.3 koa2简析结构
    • 1.4 koa中间件开发与使用
    • 10.1 单元测试
    • 11.1 开发debug
    • 12.1 快速启动
    • 12.2 框架设计
    • 12.3 分层操作
    • 12.4 数据库设计
    • 12.5 路由设计
    • 12.6 webpack4环境搭建
    • 12.7 使用react
    • 12.8 登录注册功能实现
    • 12.9 session登录态判断处理
    • 13.1 import export使用
    • 2.1 原生koa2实现路由
    • 2.2 koa router中间
    • 3.1 GET请求数据获取
    • 3.2 POST请求数据获取
    • 3.3 koa bodyparser中间件
    • 4.1 原生koa2实现静态资源服务器
    • 4.2 koa static中间件
    • 5.1 koa2使用cookie
    • 5.2 koa2实现session
    • 6.1 koa2加载模板引擎
    • 6.2 ejs模板引擎
    • 7.1 busboy模块
    • 7.2 上传文件简单实现
    • 7.3 异步上传图片实现
    • 8.1 mysql模块
    • 8.2 async await封装使用mysql
    • 8.3 项目建表初始化
    • 9.1 原生koa2实现JSONP
    • 9.2 koa jsonp中间件
  • 其他

    • 操作数据库
    • Session 与 Token
    • Cookie、Session、Token、JWT
    • Socket

# 调试日志打印debug模块

30 秒速记

  • 用法:const debug = require('debug')('app:db'),启动时 DEBUG=app:* node app.js 才会输出
  • 不设 DEBUG 时完全静默,可以放心留在代码里;Express 内部也用它,DEBUG=express:* 能看路由匹配过程
  • 命名空间按业务领域起(app:order、app:pay),支持通配 * 和排除 -app:sql
  • 默认输出到 stderr,浏览器里用 localStorage.debug = 'app:*' 开启
  • 它是开发调试工具,生产日志用 pino / winston 做结构化输出;debug 里同样别打密钥

debug 是一个按命名空间开关的调试打印工具,代码里随便写,只有通过 DEBUG 环境变量点名的命名空间才会真正输出。 比如数据库模块用 app:db,订单模块用 app:order,平时不设 DEBUG 一行都不打,排查订单问题时 DEBUG=app:order node app.js 只看订单相关的输出,还会自动带上颜色和两次输出之间的毫秒间隔。它比 console.log 好在不用删、不用注释,想看就开。不过它只适合开发和临时排查,生产环境的正式日志要用结构化的日志库,而且就算默认关着,也别往 debug 里打 token、密码这类东西。

const debug = require('debug')('app:order')
debug('create order %o', { id: 42, amount: 99 })
// DEBUG=app:* node app.js
// app:order create order { id: 42, amount: 99 } +0ms
@前端进阶之旅: 代码已经复制到剪贴板

理解「调试日志打印debug模块」时,要先明确输入、运行阶段和可观察输出。这里的交互实验会分别执行正常路径与失败路径,并把 Node.js 的关键状态变化和同屏代码对应起来;不能只记命令名称。

工程中还要验证退出码、资源清理和异常输入。属于 testing 场景的配置应保持最小可复现,并在开发环境与 CI 中使用相同命令复跑,避免把平台差异或隐式默认值带到线上。

debug 模块的思路很简单:每个模块创建一个带名字的打印函数,运行时由 DEBUG 环境变量决定哪些名字被启用。

// db.js
const debug = require('debug')('app:db')
debug('connecting to %s', 'mysql://localhost')

// order.js
const debug = require('debug')('app:order')
debug('order %o', { id: 1 })
@前端进阶之旅: 代码已经复制到剪贴板
DEBUG=app:db node app.js          # 只看数据库
DEBUG=app:* node app.js           # 看 app 下所有模块
DEBUG=*,-express:* node app.js    # 全开,但排除 express 内部
@前端进阶之旅: 代码已经复制到剪贴板

几个实用细节:

  • 输出默认写到 stderr,不会和程序正常输出到 stdout 的内容混在一起,重定向时要注意 2>。
  • 每行末尾的 +12ms 是距离同一命名空间上一次输出的时间间隔,粗略看耗时很方便。
  • 支持 %s、%d、%j、%o、%O 等占位符,其中 %o / %O 会在启用时才格式化对象。
  • 可以用 debug.enabled 判断当前命名空间是否开启,把昂贵的计算包起来。
  • 浏览器端同样可用,在控制台执行 localStorage.debug = 'app:*' 后刷新页面即可。
  • 很多库内部都用 debug 打调试信息,比如 Express,设置 DEBUG=express:* 能看到路由匹配和中间件执行的过程,排查「为什么这个路由没命中」很有用。

debug 适合开发阶段和临时排查。生产环境需要的是分级、结构化(JSON)、可集中采集的日志,这部分交给 pino、winston 这类日志库。

面试官追问

追问 1代码里写了 debug(...),运行时什么都没打出来,说明那段代码没执行吗?
参考回答

不一定,更可能是没设 DEBUG,或者命名空间写得对不上,比如代码里是 app:order,启动时写成了 DEBUG=order。先用 DEBUG=* 确认能打出来,再收窄范围。

追问 2DEBUG=* 一开日志刷屏,怎么只看自己的?
参考回答

用通配加排除:DEBUG=app:*,-app:sql 打开所有 app 开头的,但去掉 SQL 那个。所以命名空间要按领域分层起名,排查时才能精确控制范围。

追问 3debug 关着的时候,debug('data %s', JSON.stringify(bigObj)) 有性能开销吗?
参考回答

有,JSON.stringify 作为参数在调用前就执行了,不管开没开。用 %O 占位符直接传对象,它只在启用时才格式化;特别重的计算用 if (debug.enabled) 包一下。

追问 4Windows 上 DEBUG=app:* node app.js 报错,怎么写?
参考回答

cmd 里是 set DEBUG=app:* & node app.js,PowerShell 是 $env:DEBUG='app:*'; node app.js。团队里跨平台的话在 scripts 里用 cross-env DEBUG=app:* node app.js。

追问 5线上偶发问题想临时开 debug 看一下,要注意什么?
参考回答

只开相关的命名空间,限定时间和实例,看完就关;高频路径全开会明显增加 CPU 和 I/O。输出里有用户数据的话,和正式日志一样要脱敏。

# 前言

30 秒速记

  • debug = 带开关的 console.log:代码里一直留着,默认不输出,用 DEBUG 环境变量按需打开
  • 按命名空间分类,比如 app:db、app:api,排查哪块就开哪块
  • 内置替代:util.debuglog('foo'),用 NODE_DEBUG=foo 打开,不用装依赖
  • NODE_DEBUG=http,net 还能直接看 Node 内核模块自己的调试输出
  • 定位:开发期诊断工具,不是生产日志方案;线上要的是结构化日志(pino / winston)加集中采集

debug 模块说白了就是一个能开关的 console.log,日志一直留在代码里,平时不出声,要查问题时用环境变量打开。 它最大的好处是按命名空间分类,排查数据库就只开 app:db,不会被满屏无关输出淹没,Express、Koa 这些库内部也是用它打调试信息的。Node 本身也带了一个类似的 util.debuglog(),用 NODE_DEBUG 开关,功能简单一些但零依赖。不过要分清,这俩都是开发期的诊断手段,线上要查问题还是靠结构化日志和日志平台。

在node程序开发中时,经常需要打印调试日志。用的比较多的是debug模块,比如express框架中就用到了

备注:node在0.11.3版本也加入了util.debuglog()用于打印调试日志,使用方法跟debug模块大同小异。

面试官追问

追问 1都有 console.log 了,为什么还要专门引一个 debug?
参考回答

console.log 要么删要么一直打,调试完删掉,下次出问题又得加回来。debug 的日志可以常驻代码里,默认零输出,DEBUG=app:db node app.js 一开就有,还自带命名空间颜色和距上一条的耗时 +12ms。

追问 2线上请求报了 500,翻日志一行 debug 输出都没有,能说明请求没进服务吗?
参考回答

不能。生产环境一般根本没设 DEBUG,debug 函数调了也是空操作。判断请求有没有进来要看访问日志、网关日志或者 APM 链路,debug 输出不是业务执行的凭据。

追问 3util.debuglog 和 debug 模块怎么选?
参考回答

写给别人用的 npm 库、想零依赖,用 util.debuglog,开关是 NODE_DEBUG=mylib;业务项目已经大量用 debug 的命名空间,就别搞两套。一个项目里两种开关并存,新人光记环境变量就得踩一遍坑。

追问 4想看 http 模块内部到底在干嘛,比如连接有没有复用,怎么看?
参考回答

直接 NODE_DEBUG=http,net node app.js,Node 内核模块本身就是用 debuglog 打的调试信息,socket 复用、keep-alive 这些都会打到 stderr。

追问 5debug 打出来的日志能不能直接当线上日志用?
参考回答

不建议。它是纯文本、没有级别、没有请求 ID,日志平台很难检索聚合。线上用 pino 这类输出 JSON 的库,debug 只在本地或临时排障时打开。

# 基础例子

30 秒速记

  • require('debug')('app') 返回一个日志函数,命名空间就是 app
  • 运行时加环境变量打开:DEBUG=app node 01.js,输出 app hello +0ms
  • +0ms 是距同一命名空间上一条日志的时间差,顺手就能看出哪步慢
  • 输出走 stderr 不走 stdout,重定向时要用 2>
  • Windows 上写法不同:PowerShell 是 $env:DEBUG='app',跨平台用 cross-env

用法就两步:代码里

基础篇
进阶篇
高频篇
精选篇
手写篇
面经篇
AI 篇
原理篇
每日一题
小程序题库
知识卡片
  • 场景篇按分类整理的大前端场景考点
  • 历年面经按年份追踪真实考点
  • 算法题库NEW在线编码即时判题
  • 专项自测100 题快速查漏
  • 前端基础
    • HTTP从报文一路讲到 HTTPS
    • 浏览器渲染、事件循环、进程
    • 计算机基础Linux、网络、操作系统
  • 进阶专项
    • 设计模式23 种模式怎么用
    • 前端系统进阶学习大型项目工程化
    • 前端综合文章长期沉淀的实践文
  • 工程与工具
    • Node学习指南从环境搭建到服务端
    • NPM工作流script、依赖与发布
    • Docker容器化部署上手
    • Canvas图形与动画实战
  • 路线与导图
    • 思维导图知识点全景图
    • 学习路线按图索骥不跑偏
  • 动态
    • 公众号动态公众号历史文章
    • 博客动态站长的技术博客
    • 开发者导航常用工具与文档站
  • AI 助手随时提问,即时解析
  • AI 模拟面试模拟真实面试 + 报告
  • AI 知识地图串起全站知识点
  • AI 定制路线按你的简历现排
AI 热点
旧版
  • 基础篇

    • 环境搭建
    • node部署
    • 基础应用
  • 内置模块

    • 1.0 本地路径处理 path
    • 2.0 文件系统操作 fs
    • 3.1 基础调试 console
    • 3.2 本地调试远程服务器上的Node代码
    • 4.1 网络服务 http
    • 4.2 网络服务 http res
    • 4.3 网络服务 http req
    • 4.4 网络服务 http server
    • 4.5 网络服务 http client
    • 4.6 网络服务 https
    • 4.7 网络TCP net
    • 4.8 网络UDP dgram
    • 4.9 域名解析 dns
    • 5.0 网络地址解析 url
    • 5.1 URL查询字符串 querystring
    • 6.1 流操作 stream
    • 6.2 逐行读取 readline
    • 7.1 进程相关 process
    • 7.2 子进程 child
    • 8.1 二进制数据 buffer
    • 8.2 二进制解码 string_decoder
    • 9.1 事件机制 events
    • 9.2 实用工具模块 util
    • 9.3 数据加密 crypto
    • 9.4 MD5入门介绍及crypto模块的应用
    • 9.4 资源压缩 zlib
    • 9.5 集群 cluster
    • 9.6 v8
  • 进阶篇

    • 5分钟入门非对称加密用法
    • cluster
    • cookie_parser深入
    • crypto模块之理论篇
    • express+cookie_parser签名机制深入剖析
    • express+session实现简易身份认证
    • https
    • log4js入门实例
    • node8_napi
    • 使用 async 控制并发
    • 使用 eventproxy 控制并发
    • 使用 superagent 与 cheerio 完成简单爬虫
    • 基于express+muter的文件上传
    • 将图片转成datauri嵌入到html
    • 常用中间件 body_parser 实现解析
    • 日志模块morgan
    • 服务端字符编解码&乱码处理 charset_enc_dec
    • 测试用例mocha,should,istanbul
    • 调试日志打印debug模块
      • 前言
      • 基础例子
      • 例子:命名空间
      • 例子:命名空间排除
      • 例子:自定义格式化
      • 相关链接
  • Express

    • 1.1 Express概览篇
    • 1.2 Express
  • Koa2

    • 1.0 koa2概览篇
    • 1.1 快速开始
    • 1.2 async await使用
    • 1.3 koa2简析结构
    • 1.4 koa中间件开发与使用
    • 10.1 单元测试
    • 11.1 开发debug
    • 12.1 快速启动
    • 12.2 框架设计
    • 12.3 分层操作
    • 12.4 数据库设计
    • 12.5 路由设计
    • 12.6 webpack4环境搭建
    • 12.7 使用react
    • 12.8 登录注册功能实现
    • 12.9 session登录态判断处理
    • 13.1 import export使用
    • 2.1 原生koa2实现路由
    • 2.2 koa router中间
    • 3.1 GET请求数据获取
    • 3.2 POST请求数据获取
    • 3.3 koa bodyparser中间件
    • 4.1 原生koa2实现静态资源服务器
    • 4.2 koa static中间件
    • 5.1 koa2使用cookie
    • 5.2 koa2实现session
    • 6.1 koa2加载模板引擎
    • 6.2 ejs模板引擎
    • 7.1 busboy模块
    • 7.2 上传文件简单实现
    • 7.3 异步上传图片实现
    • 8.1 mysql模块
    • 8.2 async await封装使用mysql
    • 8.3 项目建表初始化
    • 9.1 原生koa2实现JSONP
    • 9.2 koa jsonp中间件
  • 其他

    • 操作数据库
    • Session 与 Token
    • Cookie、Session、Token、JWT
    • Socket
完整面试题地址:
作者:程序员poetry
扫码关注作者公众号:「前端进阶之旅」 每天分享技术干货
前端进阶之旅公众号二维码

调试日志打印debug模块|Nodejs专题系列

# 调试日志打印debug模块

30 秒速记

  • 用法:const debug = require('debug')('app:db'),启动时 DEBUG=app:* node app.js 才会输出
  • 不设 DEBUG 时完全静默,可以放心留在代码里;Express 内部也用它,DEBUG=express:* 能看路由匹配过程
  • 命名空间按业务领域起(app:order、app:pay),支持通配 * 和排除 -app:sql
  • 默认输出到 stderr,浏览器里用 localStorage.debug = 'app:*' 开启
  • 它是开发调试工具,生产日志用 pino / winston 做结构化输出;debug 里同样别打密钥

debug 是一个按命名空间开关的调试打印工具,代码里随便写,只有通过 DEBUG 环境变量点名的命名空间才会真正输出。 比如数据库模块用 app:db,订单模块用 app:order,平时不设 DEBUG 一行都不打,排查订单问题时 DEBUG=app:order node app.js 只看订单相关的输出,还会自动带上颜色和两次输出之间的毫秒间隔。它比 console.log 好在不用删、不用注释,想看就开。不过它只适合开发和临时排查,生产环境的正式日志要用结构化的日志库,而且就算默认关着,也别往 debug 里打 token、密码这类东西。

const debug = require('debug')('app:order')
debug('create order %o', { id: 42, amount: 99 })
// DEBUG=app:* node app.js
// app:order create order { id: 42, amount: 99 } +0ms
@前端进阶之旅: 代码已经复制到剪贴板

理解「调试日志打印debug模块」时,要先明确输入、运行阶段和可观察输出。这里的交互实验会分别执行正常路径与失败路径,并把 Node.js 的关键状态变化和同屏代码对应起来;不能只记命令名称。

工程中还要验证退出码、资源清理和异常输入。属于 testing 场景的配置应保持最小可复现,并在开发环境与 CI 中使用相同命令复跑,避免把平台差异或隐式默认值带到线上。

debug 模块的思路很简单:每个模块创建一个带名字的打印函数,运行时由 DEBUG 环境变量决定哪些名字被启用。

// db.js
const debug = require('debug')('app:db')
debug('connecting to %s', 'mysql://localhost')

// order.js
const debug = require('debug')('app:order')
debug('order %o', { id: 1 })
@前端进阶之旅: 代码已经复制到剪贴板
DEBUG=app:db node app.js          # 只看数据库
DEBUG=app:* node app.js           # 看 app 下所有模块
DEBUG=*,-express:* node app.js    # 全开,但排除 express 内部
@前端进阶之旅: 代码已经复制到剪贴板

几个实用细节:

  • 输出默认写到 stderr,不会和程序正常输出到 stdout 的内容混在一起,重定向时要注意 2>。
  • 每行末尾的 +12ms 是距离同一命名空间上一次输出的时间间隔,粗略看耗时很方便。
  • 支持 %s、%d、%j、%o、%O 等占位符,其中 %o / %O 会在启用时才格式化对象。
  • 可以用 debug.enabled 判断当前命名空间是否开启,把昂贵的计算包起来。
  • 浏览器端同样可用,在控制台执行 localStorage.debug = 'app:*' 后刷新页面即可。
  • 很多库内部都用 debug 打调试信息,比如 Express,设置 DEBUG=express:* 能看到路由匹配和中间件执行的过程,排查「为什么这个路由没命中」很有用。

debug 适合开发阶段和临时排查。生产环境需要的是分级、结构化(JSON)、可集中采集的日志,这部分交给 pino、winston 这类日志库。

面试官追问

追问 1代码里写了 debug(...),运行时什么都没打出来,说明那段代码没执行吗?
参考回答

不一定,更可能是没设 DEBUG,或者命名空间写得对不上,比如代码里是 app:order,启动时写成了 DEBUG=order。先用 DEBUG=* 确认能打出来,再收窄范围。

追问 2DEBUG=* 一开日志刷屏,怎么只看自己的?
参考回答

用通配加排除:DEBUG=app:*,-app:sql 打开所有 app 开头的,但去掉 SQL 那个。所以命名空间要按领域分层起名,排查时才能精确控制范围。

追问 3debug 关着的时候,debug('data %s', JSON.stringify(bigObj)) 有性能开销吗?
参考回答

有,JSON.stringify 作为参数在调用前就执行了,不管开没开。用 %O 占位符直接传对象,它只在启用时才格式化;特别重的计算用 if (debug.enabled) 包一下。

追问 4Windows 上 DEBUG=app:* node app.js 报错,怎么写?
参考回答

cmd 里是 set DEBUG=app:* & node app.js,PowerShell 是 $env:DEBUG='app:*'; node app.js。团队里跨平台的话在 scripts 里用 cross-env DEBUG=app:* node app.js。

追问 5线上偶发问题想临时开 debug 看一下,要注意什么?
参考回答

只开相关的命名空间,限定时间和实例,看完就关;高频路径全开会明显增加 CPU 和 I/O。输出里有用户数据的话,和正式日志一样要脱敏。

# 前言

30 秒速记

  • debug = 带开关的 console.log:代码里一直留着,默认不输出,用 DEBUG 环境变量按需打开
  • 按命名空间分类,比如 app:db、app:api,排查哪块就开哪块
  • 内置替代:util.debuglog('foo'),用 NODE_DEBUG=foo 打开,不用装依赖
  • NODE_DEBUG=http,net 还能直接看 Node 内核模块自己的调试输出
  • 定位:开发期诊断工具,不是生产日志方案;线上要的是结构化日志(pino / winston)加集中采集

debug 模块说白了就是一个能开关的 console.log,日志一直留在代码里,平时不出声,要查问题时用环境变量打开。 它最大的好处是按命名空间分类,排查数据库就只开 app:db,不会被满屏无关输出淹没,Express、Koa 这些库内部也是用它打调试信息的。Node 本身也带了一个类似的 util.debuglog(),用 NODE_DEBUG 开关,功能简单一些但零依赖。不过要分清,这俩都是开发期的诊断手段,线上要查问题还是靠结构化日志和日志平台。

在node程序开发中时,经常需要打印调试日志。用的比较多的是debug模块,比如express框架中就用到了

备注:node在0.11.3版本也加入了util.debuglog()用于打印调试日志,使用方法跟debug模块大同小异。

面试官追问

追问 1都有 console.log 了,为什么还要专门引一个 debug?
参考回答

console.log 要么删要么一直打,调试完删掉,下次出问题又得加回来。debug 的日志可以常驻代码里,默认零输出,DEBUG=app:db node app.js 一开就有,还自带命名空间颜色和距上一条的耗时 +12ms。

追问 2线上请求报了 500,翻日志一行 debug 输出都没有,能说明请求没进服务吗?
参考回答

不能。生产环境一般根本没设 DEBUG,debug 函数调了也是空操作。判断请求有没有进来要看访问日志、网关日志或者 APM 链路,debug 输出不是业务执行的凭据。

追问 3util.debuglog 和 debug 模块怎么选?
参考回答

写给别人用的 npm 库、想零依赖,用 util.debuglog,开关是 NODE_DEBUG=mylib;业务项目已经大量用 debug 的命名空间,就别搞两套。一个项目里两种开关并存,新人光记环境变量就得踩一遍坑。

追问 4想看 http 模块内部到底在干嘛,比如连接有没有复用,怎么看?
参考回答

直接 NODE_DEBUG=http,net node app.js,Node 内核模块本身就是用 debuglog 打的调试信息,socket 复用、keep-alive 这些都会打到 stderr。

追问 5debug 打出来的日志能不能直接当线上日志用?
参考回答

不建议。它是纯文本、没有级别、没有请求 ID,日志平台很难检索聚合。线上用 pino 这类输出 JSON 的库,debug 只在本地或临时排障时打开。

# 基础例子

30 秒速记

  • require('debug')('app') 返回一个日志函数,命名空间就是 app
  • 运行时加环境变量打开:DEBUG=app node 01.js,输出 app hello +0ms
  • +0ms 是距同一命名空间上一条日志的时间差,顺手就能看出哪步慢
  • 输出走 stderr 不走 stdout,重定向时要用 2>
  • Windows 上写法不同:PowerShell 是 $env:DEBUG='app',跨平台用 cross-env

用法就两步:代码里 require('debug')('app') 拿到日志函数,运行时加上 DEBUG=app 才会真正输出。 没设 DEBUG 的时候调用 debug('hello') 什么都不打,所以这类日志可以放心留在代码里。输出末尾的 +0ms 很实用,它表示距离这个命名空间上一条日志过了多久,粗略看性能不用自己掐时间。还有一个小坑,debug 写的是 stderr,你用 > log.txt 重定向会发现文件是空的,要写成 2> log.txt。

// 01.js
const debug = require('debug')('app');
debug('hello');
setTimeout(() => debug('world'), 100);
// DEBUG=app node 01.js
// app hello +0ms
// app world +101ms
@前端进阶之旅: 代码已经复制到剪贴板

首先,安装debug模块。

npm install debug
@前端进阶之旅: 代码已经复制到剪贴板

使用很简单,运行node程序时,加上DEBUG=app环境变量即可。

/**
 * debug基础例子
 */
var debug = require('debug')('app');

// 运行 DEBUG=app node 01.js
// 输出:app hello +0ms
debug('hello');
@前端进阶之旅: 代码已经复制到剪贴板

← 测试用例mocha,should,istanbul1.1 Express概览篇 →

fe