1. 简介
本文将带你探索 Lightrun——一个强大的开发者可观测性平台。我们将通过实际应用演示,展示如何利用它解决开发中的痛点问题。
2. 什么是 Lightrun?
Lightrun 是一个可观测性平台,允许我们对 Java(也支持其他语言)应用进行动态插桩,并直接在 IntelliJ、Visual Studio Code 等开发环境中查看插桩结果。 它的设计目标是:在任何环境中无缝添加插桩,并从任何地方访问这些数据,让我们能快速诊断从本地工作站到生产实例的各种问题。
Lightrun 通过两个核心组件协同工作:
- Lightrun Agent:作为应用的一部分运行,根据请求执行插桩操作。在 Java 应用中,它以 Java Agent 形式工作。我们需要在所有需要使用 Lightrun 的应用中运行此 Agent。
- Lightrun Plugin:作为开发环境的一部分运行,负责与 Agent 通信。这是我们查看运行状态、添加新插桩并获取结果的主要工具。
配置完成后,我们可以管理三种不同类型的插桩:
- 日志(Logs):在运行时应用的任意位置添加自定义日志语句,输出任意可用值(包括复杂表达式)。这些日志可以发送到标准输出、开发环境中的 Lightrun 插件,或两者同时输出。还支持条件触发——例如基于代码中预定义的特定用户或会话 ID。
- 快照(Snapshots):在任意位置捕获应用的实时快照。这将记录触发快照的确切时间和位置、所有变量的值以及完整的调用栈。同样支持条件触发。
- 指标(Metrics):记录类似 Micrometer 生成的指标,可用于统计代码行执行次数、记录代码块执行时间或任何其他数值计算。
这些功能其实都能在代码中手动实现,但 Lightrun 的核心价值在于:无需修改或重新部署应用,就能在运行中的应用上实现这些操作。 这意味着我们可以在生产环境实现零停机的精准插桩。
更重要的是,所有这些日志都是临时的。它们不会持久化到源代码或运行的应用中,可以根据需要随时添加和移除。
3. 示例应用
本文使用一个已构建好的任务跟踪应用作为示例。该应用用于管理分配给人员的任务,并支持用户查询数据。代码可在 GitHub 获取,构建需要 Java 17+ 和 Maven 3.6。
该应用采用微服务架构,包含三个服务:
- 用户管理服务
- 任务管理服务
- 编排服务(协调前两个服务)
其中 tasks-service 和 users-service 各自拥有独立数据库,两者之间通过 JMS 队列通信——允许 users-service 通知 tasks-service 用户已删除,以便后者清理相关数据。
为方便演示,数据库和 JMS 队列都内嵌在应用中。实际生产环境中,这些组件通常会部署在独立基础设施上。
3.1. 任务服务
*本文主要聚焦 tasks-service。* 后续文章将深入探讨所有三个服务及其交互方式。
该服务是基于 Java 17 和 Maven 构建的 Spring Boot 应用,提供以下 HTTP 接口:
- GET / – 允许客户端搜索任务,支持按创建用户和状态过滤
- POST / – 允许客户端创建新任务
- GET /{id} – 允许客户端通过 ID 获取单个任务
- PATCH /{id} – 允许客户端更新任务状态和分配用户
- DELETE /{id} – 允许客户端删除任务
还包含一个 JMS 监听器,用于接收来自 users-service 的用户删除通知。当收到通知时,会自动删除该用户创建的所有任务,并取消分配给该用户的所有任务。
应用中故意埋了几个 Bug,我们将借助 Lightrun 来诊断这些问题。
4. Lightrun 环境搭建
开始前需要注册 Lightrun 账号并进行本地配置。 访问 https://app.lightrun.com/ 按指引操作即可。
注册完成后,选择开发环境和编程语言。本文使用 IntelliJ 和 Java,选择相应选项后继续:
系统会提供在开发环境安装 Lightrun 插件的说明,按提示操作即可。
确保在开发环境中登录新账号后,就能在编辑器内访问 Lightrun Agent(目前为空):
最后获取用于应用插桩的 Java Agent 下载说明。这些说明因平台而异,请确保选择与你的环境匹配的版本。
配置完成后,就可以启动带 Agent 的应用。确保 tasks-service 已构建,然后执行:
$ java -jar -agentpath:../agent/lightrun_agent.so target/tasks-service-0.0.1-SNAPSHOT.jar
此时浏览器中的引导页面会更新,开发环境 UI 也会自动显示运行中的应用:
注意:所有组件都连接到你的 Lightrun 账号,因此无论应用部署在哪里都能查看。 这意味着无论是本地运行、Docker 容器还是任何支持运行时的环境(即使部署在全球任何地方),都能使用完全相同的工具集进行诊断。
5. 捕获快照
Lightrun 最强大的功能之一是向运行中的应用添加快照。 这能让我们捕获应用执行到特定位置时的精确状态,为理解代码行为提供关键洞察。可以将其视为“虚拟断点”——它不会中断程序执行,而是捕获断点处的所有信息供后续分析。
快照(以及日志和指标)都通过开发环境添加。通常在目标代码行右键,选择“Lightrun”选项:
从后续菜单中选择添加快照:
系统会打开配置面板,我们需要:
- 选择要插桩的 Agent
- 指定其他工作细节(可选)
配置完成后点击 Create 按钮。侧边栏将新增快照条目,代码行旁出现蓝色相机图标:

图标表示该行执行时会捕获快照。如果图标变红,通常表示运行代码与源代码不匹配,需要排查其他可能原因。
6. 诊断 Bug:任务搜索问题
我们的 tasks-service 存在一个 Bug:带过滤条件的任务搜索永远返回空结果。 无过滤搜索能正常返回所有任务,但添加过滤条件(无论是 createdBy、status 或两者)时,结果立即变为空数组。
例如调用 http://localhost:8082?status=PENDING 应返回结果,实际却始终返回空数组。
应用架构中,TasksController 处理 HTTP 请求,调用 TasksService 执行业务逻辑,后者通过 TasksRepository 操作数据。
由于该 Repository 是 Spring Data 接口,没有可直接插桩的实现代码。因此我们在 TasksService 的 search() 方法首行添加快照:
添加后再次调用接口,仍返回空数组。但这次在开发环境捕获了快照,可在 Snapshots 标签页查看:
快照显示了触发位置的调用栈和所有可见变量状态。 重点观察变量:
- 两个方法参数(最值得关注)
- this 实例
立即发现问题:我们传入的状态值 "PENDING" 竟出现在 createdBy 参数中!
仔细检查代码发现,TasksController 和 TasksService 之间的参数顺序弄反了。修复方案很简单:交换 TasksService 的参数顺序,或调整 TasksController 的传参顺序。修复后搜索功能立即恢复正常。
7. 总结
本文快速介绍了 Lightrun 可观测性平台的基本概念、入门方法及其核心价值。 后续文章将深入探讨更多高级特性。
不妨在下一个项目中尝试使用 Lightrun,它能显著提升你对应用运行状态的洞察力和调试效率。