diff --git a/src/jdk.jfr/share/classes/jdk/jfr/consumer/RecordingStream.java b/src/jdk.jfr/share/classes/jdk/jfr/consumer/RecordingStream.java
index 564b97797fc..2e7d23bb84c 100644
--- a/src/jdk.jfr/share/classes/jdk/jfr/consumer/RecordingStream.java
+++ b/src/jdk.jfr/share/classes/jdk/jfr/consumer/RecordingStream.java
@@ -455,6 +455,27 @@ public final class RecordingStream implements AutoCloseable, EventStream {
directoryStream.awaitTermination();
}
+ /**
+ * Registers an action to perform when new metadata arrives in the stream.
+ *
+ * The event type of an event always arrives sometime before the actual event.
+ * The action must be registered before the stream is started.
+ *
+ * The following example shows how to listen to new event types, register
+ * an action if the event type name matches a regular expression and increase a
+ * counter if a matching event is found. A benefit of using an action per
+ * event type, instead of the generic {@link #onEvent(Consumer)} method,
+ * is that a stream implementation can avoid reading events that are of no
+ * interest.
+ *
+ * {@snippet class = "Snippets" region = "RecordingStreamMetadata"}
+ *
+ * @param action to perform, not {@code null}
+ *
+ * @throws IllegalStateException if an action is added after the stream has
+ * started
+ * @since 16
+ */
@Override
public void onMetadata(Consumer action) {
directoryStream.onMetadata(action);
diff --git a/src/jdk.jfr/share/classes/jdk/jfr/consumer/snippet-files/Snippets.java b/src/jdk.jfr/share/classes/jdk/jfr/consumer/snippet-files/Snippets.java
index 1aa45fa52c6..3f363c4536a 100644
--- a/src/jdk.jfr/share/classes/jdk/jfr/consumer/snippet-files/Snippets.java
+++ b/src/jdk.jfr/share/classes/jdk/jfr/consumer/snippet-files/Snippets.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2022, 2023, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2022, 2024, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -109,6 +109,27 @@ public class Snippets {
// @end
}
+ class RecordingStreamMetadata {
+ // @start region="RecordingStreamMetadata"
+ static long count = 0;
+ public static void main(String... args) throws Exception {
+ String regExp = args[0];
+ var pr = Pattern.compile(regExp).asMatchPredicate();
+ Configuration c = Configuration.getConfiguration("default");
+ try (var s = new RecordingStream(c)) {
+ s.setOrdered(false);
+ s.onMetadata(metadata -> metadata.getAddedEventTypes()
+ .stream().map(EventType::getName).filter(pr)
+ .forEach(eventName -> s.onEvent(eventName, event -> count++)));
+ s.startAsync();
+ System.out.println("Running recording for 5 s. Please wait.");
+ s.awaitTermination(Duration.ofSeconds(5));
+ System.out.println(count + " events matches " + regExp);
+ }
+ }
+ // @end
+ }
+
void RecordingFileOverview() throws Exception {
// @start region="RecordingFileOverview"
try (RecordingFile recordingFile = new RecordingFile(Paths.get("recording.jfr"))) {