Skip to content
AITroveRead. Build. Understand.
Make this comfortable

Java JFR incident evidence: outcome events and failure counts

Last updated: 29 Sept 20264 min read
tutorial
IntermediateBy AITrove Editorial

A JFR recording captures enabled events during a defined interval, allowing an incident review to correlate operation outcomes with runtime observations.

Download Java source kit

Java 11+. The program uses JDK classes and requires no preview flags.

Record the operation boundary

A file-import operation should report success or failure at the boundary where that result becomes known. Recording only successful imports hides failed work from the incident timeline. The custom event below records an outcome in finally, including the rejected branch.

Keep event fields small and intentional. Counts and phase labels can be useful without storing full input lines, credentials or user payloads. Stack traces and event thresholds also affect what the recording contains; a missing event does not prove that no operation was attempted.

The program owns a short recording, commits two operation events, dumps the recording and reads it back. It counts successful and failed outcomes independently. That checks the capture and consumption path instead of merely printing a recording file name.

Compare a defined interval

For an incident, write down which JVM, workload and recording interval produced the artifact. CPU sampling, allocations, lock contention and application events answer different questions. A short synthetic fixture can validate event plumbing, but its counts and durations are not a production latency distribution.

Working program

Java
import jdk.jfr.*;
import jdk.jfr.consumer.*;
import java.nio.file.*;
@Name("in.aitrove.ImportOutcome")
class ImportOutcome extends Event {boolean success;int rows;}
public class ImportOutcomeRecording {
    static void importRows(int rows,boolean reject){
        ImportOutcome event=new ImportOutcome();event.begin();
        try{if(reject)throw new IllegalArgumentException("Rejected rows");event.rows=rows;event.success=true;}
        catch(IllegalArgumentException failed){event.success=false;}
        finally{event.end();event.commit();}
    }
    public static void main(String[] args)throws Exception{
        Path file=Files.createTempFile("aitrove-outcomes-",".jfr");
        try(Recording recording=new Recording()){
            recording.enable(ImportOutcome.class).withStackTrace();recording.start();importRows(4,false);importRows(0,true);recording.stop();recording.dump(file);
            int accepted=0,rejected=0;
            try(RecordingFile events=new RecordingFile(file)){
                while(events.hasMoreEvents()){RecordedEvent event=events.readEvent();if(event.getEventType().getName().equals("in.aitrove.ImportOutcome")){if(event.getBoolean("success"))accepted++;else rejected++;}}
            }System.out.println("accepted="+accepted+", rejected="+rejected);
        }finally{Files.deleteIfExists(file);}
    }
}

Output

Output
accepted=1, rejected=1

Costs and boundaries

Recorded volume grows with the enabled event rate and fields. Stack traces and event settings have their own cost. This fixture checks two events, not JFR overhead under production load, and the finally block cleans its own temporary file.

Common Mistakes

  • Success-only events omit the failure side of an incident.
  • Thresholds and settings can suppress observations.
  • A synthetic recording is not a production performance conclusion.

Read next

Recording APIs, Retained-state evidence.

java
jfr-incident-workflow
Storage details