2. 快照(Snapshots)

快照是 Lightrun 的核心功能之一,它的工作原理类似于调试器断点,但有一个关键区别:非侵入性。当我们在代码中设置快照时,每次触发都会自动记录完整的调用栈和所有可见变量(包括局部变量、方法参数和类字段),而不会阻塞应用程序或线程的执行。

2.1. 放置快照

直接在代码编辑器中操作(以 IntelliJ IDEA 为例):

  1. 右键点击目标代码行
  2. 选择 Lightrun > Snapshot (Virtual Breakpoint)
  3. 在弹出的对话框中配置参数:
    • 默认行为:记录首次触发、无触发条件、无额外表达式、1小时后过期
    • 支持自定义条件、表达式和过期时间
// 示例:在方法入口设置快照
public void processOrder(Order order) {
    // 右键此行添加快照
    orderValidator.validate(order); 
}

配置完成后,代码行左侧会出现蓝色相机图标。当快照触发时,调试面板会显示:

  • 完整调用栈
  • 所有变量值(包括 this 对象的类字段)
  • 支持深度查看变量和方法调用

2.2. 条件快照

通过条件表达式精准控制触发时机(类似条件断点):

// 仅当用户ID为特定值时触发
public User getUserById(String userId) {
    // 条件表达式:userId.equals("test-user-123")
    return userRepository.findById(userId);
}

关键优势

  • 避免生产环境噪音数据
  • 精准定位问题场景
  • 支持访问所有可见变量(局部变量/参数/类字段)

2.3. 附加表达式

在快照中记录额外计算值:

// 示例:记录请求上下文信息
public void handleRequest(HttpServletRequest request) {
    // 附加表达式:
    // 1. request.getHeader("X-Request-ID")
    // 2. SecurityContextHolder.getContext().getAuthentication()
    processRequest(request);
}

使用场景

  • 提取嵌套对象属性
  • 获取静态上下文数据(如 Spring Security)
  • 计算衍生变量值

2.4. 多次记录快照

通过设置最大命中次数捕获多次执行:

// 配置:最大命中次数 = 3
public void processBatch(List<Item> items) {
    for (Item item : items) {
        // 此行快照将记录前3次循环
        processItem(item);
    }
}

查看技巧

  • 点击快照标签旁的 i 图标查看元数据
  • 对比不同时间点的执行状态
  • 识别重复执行中的差异

2.5. 自动过期机制

为什么需要过期?

  • 减少性能开销(约1-5ms/次触发)
  • 控制数据传输成本
  • 避免长期影响生产环境

配置建议

短期调试:5-10分钟  
夜间监控:8-12小时  
周末捕获:48-72小时

过期后图标变红,已记录数据仍可查看,但停止新记录。

3. 动态日志(Logs)

3.1. 添加动态日志

无需重启即可插入日志语句:

  1. 右键目标代码行
  2. 选择 Lightrun > Log
  3. 配置参数:
    • 日志消息(支持表达式插值)
    • 触发条件
    • 日志级别(默认 INFO)
    • 过期时间
// 示例:在关键路径添加日志
public PaymentResult processPayment(Payment payment) {
    // 日志消息:Processing payment: {payment.id} amount={payment.amount}
    PaymentResult result = paymentGateway.charge(payment);
    return result;
}

3.2. 查看日志

两种输出模式

  1. 应用日志流(默认):

    • 与应用日志混合输出
    • 需配置 Lightrun Agent 日志格式 ```properties

      agent 配置示例

    • Dlightrun.jul.logger.name=Lightrun
    • Dlightrun.jul.logger.level=INFO ```
  2. 编辑器控制台

    • 独立显示不干扰生产日志
    • 适合敏感调试场景

切换方式:侧边栏 Agent 菜单 > Log Piping

3.3. 日志表达式

使用 {} 插入动态值:

public List<Task> searchTasks(TaskFilter filter) {
    // 日志:Searching tasks: status={filter.status}, createdBy={filter.createdBy}
    return taskRepository.findByFilter(filter);
}

性能注意

  • 复杂表达式可能导致 CPU 暂停
  • 优先使用简单变量访问
  • 避免在循环中使用复杂表达式

4. 指标监控(Metrics)

4.1. 计数器(Counter)

统计代码执行次数:

public void deleteUser(String userId) {
    // 计数器名称:user_deletion_total
    // 条件:!userId.startsWith("test_")
    userRepository.delete(userId);
}

输出示例

// 每10秒更新(编辑器)
Lightrun Metric [user_deletion_total]: 23 (count)

// 每秒更新(日志)
2023-08-20 14:30:01 INFO  [lightrun] Metric user_deletion_total: 23

4.2. 时长测量(Time Duration)

测量代码块执行时间:

public void generateReport() {
    // 开始标记:tic
    reportEngine.initialize();
    // 结束标记:toc
}

输出数据

  • 执行次数
  • 最快/最慢/平均耗时
    Metric [report_generation]: 
    count=5, 
    min=120ms, 
    max=340ms, 
    mean=210ms
    

4.3. 方法耗时(Method Duration)

自动测量整个方法:

// 右键方法名选择 Lightrun > Metrics > Method Duration
public void sendNotification(Notification notification) {
    // 自动记录入口/出口时间
    notificationService.deliver(notification);
}

特点

  • 自动处理异常退出
  • 无需手动标记起止点
  • 输出格式同 Time Duration

4.4. 自定义指标(Custom Metric)

聚合业务数据:

public SearchResult searchProducts(Query query) {
    SearchResult result = searchEngine.execute(query);
    // 指标表达式:result.products.size()
    return result;
}

使用场景

  • 记录结果集大小
  • 监控缓存命中率
  • 跟踪业务指标(如订单金额)

5. 总结

Lightrun 提供了三大核心能力,彻底改变生产环境调试方式:

  1. 非侵入式快照

    • 替代传统断点,零线程阻塞
    • 条件触发 + 附加表达式精准定位
    • 自动过期机制保障系统安全
  2. 动态日志注入

    • 无需重启即可添加日志
    • 表达式插值增强日志上下文
    • 灵活输出控制(应用/控制台)
  3. 实时指标监控

    • 四种指标类型覆盖所有场景
    • 与 Prometheus/StatsD 无缝集成
    • 毫秒级数据粒度

实战建议

  • 先用快照定位异常上下文
  • 通过动态日志补充执行轨迹
  • 最后用指标量化问题影响
  • 始终设置合理的过期时间

下次遇到生产环境问题,不妨试试 Lightrun —— 让调试像打日志一样简单,像断点一样精准。


原始标题:Diving Deeper with Lightrun