Uploaded image for project: 'JDK'
  1. JDK
  2. JDK-8295350

JFR: Add stop methods for recording streams

    XMLWordPrintable

Details

    • Enhancement
    • Resolution: Fixed
    • P3
    • 20
    • None
    • hotspot
    • None
    • jfr
    • b27

    Description

      Today, the class jdk.jfr.consumer.Recording contains a stop() method, but it's not available in the RecordingStream or RemoteRecordingStream classes. The reason the method was omitted in the initial design (JDK 14) was because there was not a clear use case. Once a stream is stopped, what should you do with it, besides closing it?

      In case of the Recording class (from JDK 9), it was possible to invoke dump() on a stopped recording to extract data at a later time, or a subset of it using setMax or setMaxAge. In JDK 17, a RecordingStream::dump() method was added (JDK-8266266). I think two use cases for a RecordingStream::stop() method have emerged.

      1) Be able to dump a subset of the recording data using setMaxAge and setMaxSize, similar to Recording.

      2) An advantage of RecordingStream API compared to RecordingFile API (JDK 9) is that the stream operates on the disk repository directly. There is no need to specify a dump file or copy data to it before data can be read. Data can be filtered declaratively so the parser can skip events that are of no interest. This is efficient and convenient.

      Problem with the RecordingStream is that there is no way to know that all events have been consumed. Consider the following code:

          var c = Configuration.getConfiguration("default");
          try(var r = new RecordingStream(c)) {
            r.onEvent(e -> process(e));
            r.startAsync();
            doStuff();
            // Wait for all events to be consumed:
           ????
          }

      What should you write to make sure all events captured during doStuff have been processed? It's possible to create a custom event and use the commit() method as a point in time, but it unintuitive and cumbersome. See below:

       class DoStuffEvent extends Event {
       }
       try(var r = new RecordingStream(c)) {
            r.onEvent(DoStuffEvent.class, () -> r.close();
            r.onEvent(e -> process(e));
            r.startAsync();
            DoStuffEvent e = new DoStuffEvent();
            doStuff();
            e.commit();
            r.awaitTermination();
       }

      A more reasonable approach would be to add a stop() method, which will await all events to be consumed:

        try(var r = new RecordingStream(c)) {
           r.onEvent(e -> process(e));
           r.startAsync();
           doStuff();
           r.stop();
        }

      An added benefit is that the stream will be flushed immediately when stopped, so there is no need to wait 1 s for it to happen. This can be useful when JFR is used in unit tests. For example, doStuff() may not be allowed to allocate too much.

      Attachments

        Issue Links

          Activity

            People

              egahlin Erik Gahlin
              egahlin Erik Gahlin
              Votes:
              0 Vote for this issue
              Watchers:
              3 Start watching this issue

              Dates

                Created:
                Updated:
                Resolved: