Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

runtime delegation to JFR streaming APIs via reflection #223

Merged
merged 6 commits into from
Oct 12, 2023

Conversation

bjlaub
Copy link
Contributor

@bjlaub bjlaub commented Oct 11, 2023

Adds support for accessing JFR streaming APIs at runtime via reflection, while still supporting language levels below Java 14, in a manner similar to the VirtualThreads class from https://github.com/palantir/nylon-threads.

This allows consumers to access JFR streaming APIs when running on Java 14 or above, while still targeting language levels below Java 14. The EventStreams and RecordingStreams classes provide factory methods for creating an object similar in shape to jdk.jfr.consumer.EventStream or jdk.jfr.consumer.RecordingStream respectively, which delegates to an underlying instance at runtime. If JFR streaming is not supported by the runtime, an Optional.empty() is returned instead.

Note that EventStreams does not provide support for the onMetadata method of jdk.jfr.consumer.EventStream, as it depends upon a class added in Java 16. Similarly, RecordingStreams does not provide support for jdk.jfr.consumer.RecordingStream#stop() as it was added in Java 20 and I'm making the assumption that most consumers are still targeting Java 17 or below.

@bjlaub bjlaub requested a review from carterkozak October 11, 2023 18:14
@changelog-app
Copy link

changelog-app bot commented Oct 11, 2023

Generate changelog in changelog/@unreleased

What do the change types mean?
  • feature: A new feature of the service.
  • improvement: An incremental improvement in the functionality or operation of the service.
  • fix: Remedies the incorrect behaviour of a component of the service in a backwards-compatible way.
  • break: Has the potential to break consumers of this service's API, inclusive of both Palantir services
    and external consumers of the service's API (e.g. customer-written software or integrations).
  • deprecation: Advertises the intention to remove service functionality without any change to the
    operation of the service itself.
  • manualTask: Requires the possibility of manual intervention (running a script, eyeballing configuration,
    performing database surgery, ...) at the time of upgrade for it to succeed.
  • migration: A fully automatic upgrade migration task with no engineer input required.

Note: only one type should be chosen.

How are new versions calculated?
  • ❗The break and manual task changelog types will result in a major release!
  • 🐛 The fix changelog type will result in a minor release in most cases, and a patch release version for patch branches. This behaviour is configurable in autorelease.
  • ✨ All others will result in a minor version release.

Type

  • Feature
  • Improvement
  • Fix
  • Break
  • Deprecation
  • Manual task
  • Migration

Description

runtime delegation to JFR streaming APIs via reflection

Check the box to generate changelog(s)

  • Generate changelog entry


@Test
public void testOpenRepository() {
assertThat(EventStreams.openRepository()).isPresent();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

do we need to close resources here?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I suppose not, since it's only reading a view of the default repository

AtomicBoolean seen = new AtomicBoolean(false);
support.get().onEvent("jdk.ActiveRecording", (_ev) -> seen.compareAndSet(false, true));

support.get().startAsync();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we need to terminate this in some way

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

});
}

public interface RecordingStreamSupport extends AutoCloseable {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we should declare @Override void close() to narrow close from AutoCloseable not to throw a checked exception, matching RecordingStream.close.
This makes it easier to do something like the follwoing, since you can't throw checked exceptions within a functional method:

RecordingStreams.newRecordingStream()
     .ifPresent(recordingStream -> {
         try (recordingStream) {
             ///etc
         }
     });

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks like the same applies to EventStream as well

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

Copy link
Contributor

@carterkozak carterkozak left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

lgtm, thanks!

@bulldozer-bot bulldozer-bot bot merged commit 5ed9ed6 into develop Oct 12, 2023
@bulldozer-bot bulldozer-bot bot deleted the blaub/add-jfr-streaming branch October 12, 2023 14:57
@svc-autorelease
Copy link
Collaborator

Released 0.4.0

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants