当前位置:首页 > 文章列表 > 文章 > java教程 > Java JFR Event 怎样只记录满足条件的事件

Java JFR Event 怎样只记录满足条件的事件

来源:17golang原创 2026-11-14 05:52:24 0浏览 收藏

Java 自定义 JFR Event 要只记录满足条件的事件,最直接的做法是在生产端用业务条件决定是否调用 commit(),再用 shouldCommit() 避免为未启用或未达到时长阈值的事件准备昂贵字段。事件类型开关、事件持续时长和字段业务条件是三个不同层次,给字段赋值不会自动建立过滤规则。

官方地址:https://docs.oracle.com/en/java/javase/25/

现象:已经设置字段,为什么普通事件仍然出现

假设批处理诊断只关心两类操作:执行失败,或者处理行数至少为 5。为 Event 增加 failed 与 rows 字段后,如果所有调用都执行 commit,普通操作依旧会进入记录。字段负责描述发生了什么,是否保留事件则需要额外条件。

另一个常见混淆是把 threshold 当成任意数值字段的阈值。JFR 的内置时长阈值针对事件持续时间,不会自动理解“rows 大于 5”或者“业务状态异常”。先区分这几层,就不必在事件找不到时反复修改字段名称。

分层检查:先看类型开关,再看时长与业务谓词

检查层控制对象不能替代的条件
Recording.enable/disable某个事件类型的启停每条事件的业务字段判断
withThreshold持续时间门槛处理行数或错误类别
生产端 if 判断业务谓词正在运行的记录配置
SettingControl自定义可配置过滤设置未经实现的任意字段表达式
Recording配置与事件字段的不同职责
事件字段与筛选条件的静态分层说明图。配置组控制类型和时长,字段组只保存业务值,二者不是同一种筛选机制。

isEnabled() 适合判断当前是否有启用该事件的运行记录,不能据此保证事件一定写入。对于持续时间条件,应在实际业务前 begin,结束后 end,然后判断 shouldCommit。若在开始计时前就拿 shouldCommit 判断一个慢操作是否值得记录,还没有获得完整时长,判断位置就错了。

证据判断:shouldCommit 不会读取你心里的过滤表达式

shouldCommit() 提供启用状态与时长方面的提交判断。没有自己实现业务谓词时,它不会自动把 failed 当成“只保留失败”的配置。最小方案因此把业务条件直接写成 failed || rows >= 5,让判断意图在代码中可见。

当字段采集比较昂贵时,先填充用于业务判断的低成本字段;只有业务条件和提交判断都成立,才准备额外详情。记录中的字段应采用 JFR 支持的类型。本文使用 String、int 和 boolean,不把任意业务对象直接塞进事件;例如一个 List 字段并不会自动序列化成完整业务列表。

修复动作:异常或行数达到条件才提交

下面是可保存为 ConditionalJfr.java 的独立示例,使用常规 JFR API。演示动作是空任务与主动抛出的异常,仅用于说明条件,不是性能基准。示例不设置时长门槛,因此方便单独理解业务筛选。

import jdk.jfr.*;
import java.nio.file.Path;

public class ConditionalJfr {
    @Name("demo.BatchOperation")
    @Label("批处理操作")
    @Enabled(false)
    static class BatchEvent extends Event {
        @Label("操作") String operation;
        @Label("行数") int rows;
        @Label("失败") boolean failed;
        @Label("详情") String detail;
    }

    static void observe(String operation, int rows, Runnable action) {
        BatchEvent event = new BatchEvent();
        boolean enabled = event.isEnabled();
        boolean failed = false;
        if (enabled) event.begin();
        try {
            // 即使没有开启记录,也必须执行真实业务。
            action.run();
        } catch (RuntimeException | Error problem) {
            failed = true;
            throw problem;
        } finally {
            if (enabled) {
                // 先结束计时,再检查固定后的事件时长。
                event.end();
                event.operation = operation;
                event.rows = rows;
                event.failed = failed;
                boolean interesting = failed || rows >= 5;
                if (interesting && event.shouldCommit()) {
                    // 仅在值得提交时组装额外详情。
                    event.detail = "operation=" + operation + ", rows=" + rows;
                    event.commit();
                }
            }
        }
    }

    public static void main(String[] args) throws Exception {
        try (Recording recording = new Recording()) {
            // 本例去掉时长阈值,只观察业务条件是否成立。
            recording.enable(BatchEvent.class).withoutThreshold();
            recording.start();
            observe("lookup", 0, () -> {});
            observe("bulk", 8, () -> {});
            try {
                observe("failed", 0, () -> {
                    throw new IllegalStateException("demo failure");
                });
            } catch (IllegalStateException expected) {
                // 示例继续导出;观测代码没有吞掉业务异常。
            }
            recording.stop();
            recording.dump(Path.of("conditional.jfr"));
        } // 释放 recording 资源
    }
}

类上 @Enabled(false) 表达默认关闭意图,本次 Recording 再显式启用这个类型。没有运行记录时,action 仍然执行,事件开关不会变成业务开关。捕获到的异常继续向上传递,finally 只负责完成观测;main 中单独捕获演示异常,是为了继续导出文件。

failed或rows条件与shouldCommit共同约束事件提交
业务谓词与提交判断的静态依赖说明图。业务谓词与记录判断共同限制详情准备和提交,图中的连线表示依赖关系。

若目标改成“失败或行数多,且耗时不少于 20 毫秒”,可把启用配置改为 withThreshold(java.time.Duration.ofMillis(20))。这时快速失败也可能被时长门槛排除。若需求是“所有失败都保留,成功操作只保留慢请求”,可以拆成失败事件与耗时事件分别配置,避免把一个统一阈值误当成带例外的业务规则。

代码中的 rows 由调用方传入,代表已知任务规模。若要按实际成功行数过滤,应在业务处理过程中得到真实计数,再填入事件;不能把计划行数当成完成行数。示例提前保存 enabled,适用于录制在动作前已经启动的场景;运行中动态开启时,不应期待它回补已经开始但未计时的调用。

反向推导:用条件表解释预期,而不是只看文件是否生成

操作rowsfailed无时长门槛时的业务判断
lookup0false不提交
bulk8false满足条件
failed0true满足条件

以上是代码的预期条件表,没有声称本机运行记录。文件能够导出只说明有可导出的录制数据,不代表每条业务条件都正确。排查时应把启用类型、运行区间、计时边界和业务谓词分开看,不能把“文件存在”当成筛选逻辑的结论。

同一 JVM 可能同时存在多个 Recording。isEnabled 关注是否至少有一个运行记录启用该事件;shouldCommit 使用运行记录的有效阈值判断,其中时长门槛取各运行记录的最小值。因此不能把生产端的判断解释成“只代表我手里的这个 Recording”。配置冲突时,要先确认是否有其他诊断记录正在运行。

检查清单:什么时候需要可配置字段过滤

固定业务规则优先使用本文的 if 判断。若希望不改埋点代码,通过记录配置调整字段筛选,才考虑自定义 SettingControl:在 Event 上定义带 @SettingDefinition 的过滤方法,接收具体 SettingControl 子类并返回 boolean,由控制类解释设置值,再通过 EventSettings.with 传入自定义设置。配置键必须对应实际实现,不能随意写一个 rows>=5 就期待 JFR 执行。

自定义控制类需要处理默认值和非法输入;多个记录同时运行时,combine 应合并各自需求,使每个记录至少获得请求的数据。比如“最小行数”过滤通常需要采用更宽松的最小阈值,而不是最大值。过滤方法也应保持轻量,不把数据库查询或远程调用放在判断里。本文不展开完整控制类,以免把固定条件示例变成配置框架。

相关问题

在查看工具里筛选字段算不算减少记录量

不算生产端裁剪。消费端筛选能减少显示或后续处理的数据,但原始事件可能已经写入记录。需要减少采集量,应在提交前应用规则或配置合适的事件设置。

没有调用 end,commit 会不会自动结束事件

从 begin 开始且没有显式 end 时,commit 会结束计时。但本文在 shouldCommit 前显式 end,是为了先固定时长,再决定是否准备详情。

业务失败是否应该吞掉异常方便导出

不应该。记录属于观测职责,业务异常继续按调用契约传播;需要导出录制文件时,可由外层管理录制的代码处理保存与资源关闭。

参考资料

版本声明
本文转载于:17golang原创 如有侵犯,请联系study_golang@163.com删除
Java Files.mismatch 返回 -1 时如何解释Java Files.mismatch 返回 -1 时如何解释
上一篇
Java Files.mismatch 返回 -1 时如何解释
Java Arena.ofConfined 与 ofShared 如何选择
下一篇
Java Arena.ofConfined 与 ofShared 如何选择
查看更多
最新文章
查看更多
课程推荐
  • 前端进阶之JavaScript设计模式
    前端进阶之JavaScript设计模式
    设计模式是开发人员在软件开发过程中面临一般问题时的解决方案,代表了最佳的实践。本课程的主打内容包括JS常见设计模式以及具体应用场景,打造一站式知识长龙服务,适合有JS基础的同学学习。
    543次学习
  • GO语言核心编程课程
    GO语言核心编程课程
    本课程采用真实案例,全面具体可落地,从理论到实践,一步一步将GO核心编程技术、编程思想、底层实现融会贯通,使学习者贴近时代脉搏,做IT互联网时代的弄潮儿。
    516次学习
  • 简单聊聊mysql8与网络通信
    简单聊聊mysql8与网络通信
    如有问题加微信:Le-studyg;在课程中,我们将首先介绍MySQL8的新特性,包括性能优化、安全增强、新数据类型等,帮助学生快速熟悉MySQL8的最新功能。接着,我们将深入解析MySQL的网络通信机制,包括协议、连接管理、数据传输等,让
    500次学习
  • JavaScript正则表达式基础与实战
    JavaScript正则表达式基础与实战
    在任何一门编程语言中,正则表达式,都是一项重要的知识,它提供了高效的字符串匹配与捕获机制,可以极大的简化程序设计。
    487次学习
  • 从零制作响应式网站—Grid布局
    从零制作响应式网站—Grid布局
    本系列教程将展示从零制作一个假想的网络科技公司官网,分为导航,轮播,关于我们,成功案例,服务流程,团队介绍,数据部分,公司动态,底部信息等内容区块。网站整体采用CSSGrid布局,支持响应式,有流畅过渡和展现动画。
    485次学习
查看更多
AI推荐
  • PubMedQA数据集详解:生物医学问答基准、功能与应用指南
    PubMedQA
    深入了解PubMedQA生物医学问答数据集,涵盖其核心功能、使用方法及在临床决策、药物研发等场景的应用,助力提升NLP模型性能。
    1018次使用
  • H2O EvalGPT:开源LLM大模型评估与排行榜工具
    H2O EvalGPT
    H2O EvalGPT是H2O.ai推出的开源LLM评估平台,提供详细的大模型性能排行榜、行业特定基准测试及A/B测试功能,助您快速选择最适合项目的高性能大语言模型。
    1020次使用
  • LMArena是什么?伯克利AI模型评估平台使用指南与功能解析
    LMArena
    LMArena是加州大学伯克利分校推出的AI模型匿名评测平台。通过盲测投票机制,用户可对比不同大模型回答并生成实时排行榜,助力开发者优化模型及用户选择最佳AI工具。
    1155次使用
  • 斯坦福HELM:大语言模型Holistic Evaluation整体评估框架详解
    HELM
    深入了解斯坦福推出的HELM(Holistic Evaluation of Language Models)大模型评测体系。本文解析其核心功能、安装配置步骤及应用场景,涵盖准确性、公平性、鲁棒性等多维度指标,助力开发者全面优化语言模型性能。
    1121次使用
  • MMBench详解:多模态大模型基准测试、功能特点与使用指南
    MMBench
    MMBench是由上海人工智能实验室等机构联合推出的多模态基准测试平台,提供细粒度能力评估、大规模数据集及VLMEvalKit工具。本文详细介绍其核心功能、安装使用方法及应用场景,助力开发者全面评估多模态模型性能。
    962次使用
微信登录更方便
  • 密码登录
  • 注册账号
登录即同意 用户协议 和 隐私政策
返回登录
  • 重置密码