介绍 Logpoints(日志断点)和自动附加功能
2018年7月12日 Kenneth Auchenberg, @auchenberg
在过去的几个月里,我们一直致力于改进 Visual Studio Code 的调试体验。在这篇文章中,我将分享我们对于调试的思考,介绍我们从用户那里收到的反馈,并解释我们为使 VS Code 中的调试工作变得更轻松、更简单所采取的措施。
自 VS Code 发布伊始,我们就内置了集成调试体验,因为我们坚信调试应该是你编写和编辑源代码的地方——即你的编辑器——不可或缺的一部分。

VS Code 的调试体验由通用的调试器 UI 提供支持,该 UI 通过调试适配器协议 (DAP) 与我们称为调试适配器 (DA) 的特定类型 VS Code 扩展进行通信。DA 与真正的调试器对话,并在 DAP 与调试器运行时特定的调试协议或 API 之间进行转换。
这意味着 VS Code 的核心与特定调试器完全解耦,这种架构使得 VS Code 能够调试任何东西,只要有可用的调试适配器,如下图所示:

观察与痛点
如今,有一大群满意的开发者经常使用 VS Code 进行调试。但作为我们的使命之一,我们希望让调试变得更简单,并让更多的开发者能够使用它。
为此,我们开始与用户交流,以更好地理解在 VS Code 中调试的痛点,并了解为什么有些开发者完全不使用我们的调试器。
以下是我们的观察结果
调试配置很难正确设置
VS Code 是一个通用编辑器,带有通用调试器,并非专门针对特定堆栈或运行时。因此,我们无法提供一个适用于所有人的通用默认调试配置。
这意味着 VS Code 要求你配置调试器设置,并指定如何使用正确的参数启动运行时等。
我们认识到这很难做到完全正确,但我们认为没有办法为每个人彻底消除调试配置。然而,我们确实相信调试配置可以被简化,并根据上下文减少到最低限度。
我稍后会回到这一点。
启动 (Launch) 和附加 (Attach) 配置之间的混淆
在 VS Code 中,我们有两个核心调试概念:启动 (Launch) 和 附加 (Attach),它们处理两种不同的工作流和开发者群体。根据你的工作流,了解哪种配置类型适合你的项目可能会让人感到困惑。
如果你有浏览器开发工具 (DevTools) 的背景,你就不会习惯“从工具启动”这个概念,因为你的浏览器实例已经打开了。当你打开 DevTools 时,你只是将 DevTools 附加到你打开的浏览器标签页上。另一方面,如果你有 Java 背景,让编辑器为你启动 Java 进程,并让编辑器自动将调试器附加到新启动的进程上,这是非常正常的。
解释 启动 (launch) 和 附加 (attach) 之间区别的最好方法是,将 启动配置 视为在 VS Code 附加到应用之前以调试模式启动应用的配方,而 附加配置 则是将 VS Code 调试器连接到已经运行的应用或进程的配方。
启动配置 的价值在于,它们提供了一种方法,通过创建可重复且可与项目和团队共享的配置,来减轻使用正确调试参数启动应用时的认知负担。
然而,当我们与开发者交流他们如何启动应用时,我们发现了一种模式,并得出了一个重要的观察结果:
观察结果:许多使用 VS Code 的开发者非常喜欢集成终端 (Integrated Terminal),并依赖命令行工具来启动他们的应用。对许多人来说,在终端中运行命令,然后从编辑器中附加调试器是一种更自然的工作流。这类似于在浏览器启动后打开 DevTools。
这个观察结果非常关键,我们意识到许多用户并不希望在他们的编辑器中获得完整的“魔法”启动体验。他们希望保持编辑器作为编辑和调试源代码的地方,并使用终端来启动应用、运行构建脚本等。这就是为什么我们在 VS Code 中提供集成终端体验的原因之一,因为我们相信良好的功能性 UI 应该与终端共存并良好集成。
许多开发者不使用断点,因为他们在检查状态变化
在观察开发者如何调试应用时,我们也看到了另一个有趣的模式:使用日志记录代替断点。
用于调试的日志记录并不是一个新概念,但这一观察结果很重要。
观察结果:传统的调试工作流主要集中在减慢执行速度以检查程序逻辑,而日志记录工作流通常涉及检查程序状态以及它在应用正常执行期间如何变化。这里的基本观察是,这两种技术用于不同的调试目的。
这一观察对于主要处理状态管理复杂性的 JavaScript 开发者尤其相关,这可能解释了为什么 大多数 JavaScript 开发者仍然喜欢在源代码中添加 console.log,而不是使用脚本调试器。
自动附加到 Node 进程
在反思一些开发者如何使用集成终端启动他们的调试会话时,我们看到了一个独特的机会。通过利用我们在 VS Code 编辑器和集成终端内拥有的上下文信息,我们可以检测你的上下文并推断你的调试意图,这可以为 Node.js 开发者提供更简单的调试体验。
因此,在 我们 3 月份的迭代 中,我们发布了一项名为 Node 自动附加 (Auto Attach for Node) 的新功能,它使 Node 调试器能够自动附加到从 VS Code 集成终端以调试模式启动的 Node.js 进程。
你可以通过在命令面板中运行 Debug: Toggle Auto Attach 命令来启用自动附加功能,激活后,你也可以从状态栏切换自动附加功能。

此功能完全消除了任何调试配置,因为我们将任何以 node --inspect 启动的 Node.js 进程解释为调试意图。当与集成终端结合使用时,这是一种更简单的调试体验,允许开发者以自己的方式启动应用,同时消除了调试配置!🎉
NPM 脚本与调试
许多 Node.js 开发者依赖 npm 脚本 来启动应用或开始调试会话,我们在这一方面也有好消息:自动附加功能也适用于 npm 脚本。如果你运行 npm run debug,并且 "debug" 脚本是 "node --inspect" 或任何包含 --inspect 的命令,那么自动附加功能将检测到这一点并附加调试器 🎉
我们还认识到,一些开发者希望有一种更直观的方式来查找和运行 npm 脚本,因此在 我们 2018 年 4 月的迭代 中,我们添加了一个新的 NPM 脚本资源管理器,允许你直接从 UI 浏览和运行 NPM 脚本。作为简化调试配置工作的一部分,我们还使直接从资源管理器启动 Node.js 调试成为可能,而无需创建调试配置。
如果你有一个包含 --inspect 等调试参数的 npm 脚本,我们将自动检测到这一点并提供一个启动调试器的调试操作,如下图所示:

介绍 Logpoints(日志断点)
基于日志记录是一项重要调试技术的认识,我们看到了将状态检查添加到我们现有调试体验中的机会。在 VS Code 的 3 月迭代 中,我们发布了名为 Logpoints 的调试功能的第一个实现。
Logpoint 是断点的一种变体,它不会“中断”进入调试器,而是将消息记录到控制台。

Logpoints 的概念并不新鲜。在过去的几年里,我们在 Visual Studio、Edge DevTools 和 GDB 等工具中看到了这一概念的不同变体,它们被称为 Tracepoints 和 Logpoints 等名称。
为什么要使用 Logpoints,以及何时使用?
Logpoints 基于这样一个观察:在许多情况下,你并不想在应用的特定部分停止执行,而是想检查状态如何在应用的整个生命周期中发生变化。
Logpoints 允许你“按需注入”日志记录语句到你的应用逻辑中,就像你在启动应用之前添加了日志记录语句一样。Logpoints 在执行时注入,不会持久保存在源代码中,因此你不必提前计划,可以根据需要随时注入 Logpoints。另一个好处是,你不必担心调试结束后清理源代码。
对于 JavaScript 开发者来说,这意味着你不再需要担心遗留 console.log——只需使用 Logpoints!更好的是,你可以结合使用 console.log 和 Logpoints。如果你在一段已经有 console.log 的源代码块中插入一个 Logpoint,你将在调试控制台中同时看到这两种类型的日志记录语句。
云环境中的 Logpoints
Logpoints 在云环境(或任何远程环境)中特别有用,因为它们使你能够在不重新部署应用的情况下将日志记录注入到远程环境中。同样重要的是,Logpoints 不会停止脚本执行,因此你的用户不会受到影响,这与在普通断点处停止运行中的应用不同。
你可以点击此处阅读更多关于如何使用 Azure 上 Node.js 的 Logpoints 的信息。
支持的语言
自 VS Code 中首次发布 Logpoints 以来,我们已经看到 VS Code 调试适配器的采用率不断提高,如今以下语言已支持 Logpoints:
- Node.js 调试器
- Chrome 调试器
- Firefox 调试器
- Microsoft Edge 调试器
- React Native 调试器
- Python 调试器
- Dart 调试器
- Lua 调试器
- Java 调试器
- 大型机 (Mainframe) 调试器
在 VS Code 中使用 Logpoints
如果你有兴趣在你的 VS Code 调试适配器中添加 Logpoint 支持,请查看协议中的 这些更改。你也可以查看上述调试适配器,了解每个运行时是如何选择实现 Logpoints 的。
后续步骤
目前就是这样,但我们还没有完成。在我们的 7 月迭代 中,我们正在改进自动附加功能以提高可发现性 (#53640),这些改进均基于用户反馈。
我们希望自动附加、NPM 脚本资源管理器和 Logpoints 的引入将使在 VS Code 中进行调试变得更加容易。一如既往,我们非常渴望听到你的反馈,请通过 GitHub 或 Twitter 上的 @code 与我们联系。
代表 VS Code 团队:祝您编码愉快!
/Kenneth Auchenberg - Twitter 上的 @auchenberg