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

Generate constants for JFR event type names and attributes #65

Open
gunnarmorling opened this issue Jul 18, 2021 · 13 comments
Open

Generate constants for JFR event type names and attributes #65

gunnarmorling opened this issue Jul 18, 2021 · 13 comments

Comments

@gunnarmorling
Copy link
Member

Allowing for a safe access to these literals in testing code.

@Croway
Copy link
Contributor

Croway commented Oct 14, 2021

Hi, I'm not sure if this can be a solution but I created this POC https://github.com/Croway/jfrunit/tree/jfr-event-constants JfrUnitTest.shouldHaveGcAndSleepEvents contains the changes

@gunnarmorling
Copy link
Member Author

Hey @Croway, yeah, I think that looks pretty amazing! How did you do this, did you create some kind of code generator which produces all the constants?

In terms of what to generate exactly, instead of String constants, how would you feel about a more typed approach; something like this:

public class JfrEventTypes {
    public static final JfrEventType THREAD_START = ThreadStart.INSTANCE;
    ...
}
public class ThreadStart extends JfrEventType {
 
    public static final Attribute<ThreadStart, Instant> START_TIME = new Attribute<>();
    public static final Attribute<ThreadStart, Thread> EVENT_THREAD = new Attribute<>();
    ...
}

With the right method signatures, the assertion API could then be fully type-safe:

assertThat(jfrEvents).contains(
                event(JfrEventTypes.THREAD_START).with(ThreadStart.START_TIME, Instant.of(...)));

It's just a rough sketch, but the idea would be that with allows only attributes of the right event type and accepts only the right value type.

WDYT?

@gunnarmorling
Copy link
Member Author

Or maybe even this:

assertThat(jfrEvents).contains(
    JfrEventTypes.THREAD_START.withStartTime(Instant.of(...))
        .withThread(...));

I.e. generate event descriptors with the right methods for all their attributes. Even easier to use actually.

@Croway
Copy link
Contributor

Croway commented Oct 14, 2021

yes, you are right, it's much better in this way, and I don't think it will be to hard to implement, in order to generate classes I created a simple code generator with freemarker that gets all the events from https://bestsolution-at.github.io/jfr-doc/openjdk-17.json (luckly there is a json api 😄 ), once I'll do the changes I'll share the code generator.

@Croway
Copy link
Contributor

Croway commented Oct 15, 2021

Hi @gunnarmorling I implemented your first comment solution, JfrUnit should be backwards compatible with the older version (since I had failures with groovy tests), right now all test passes but if you use Attribute instead of strings the compiler will help.

This is the code generator app, https://github.com/Croway/jfr-constants-generator

@gunnarmorling
Copy link
Member Author

Very nice! So how would you like to proceed with this one? Moving the generator into the JfrUnit project? We may for instance run it as part of the JfrUnit build. WDYT?

@Croway
Copy link
Contributor

Croway commented Oct 16, 2021

Sure, I can move the generator into the JfrUnit project, I don't know what is the best practice for this use case, run the generator as part of the build, or use it as a maven plugin.

@gunnarmorling
Copy link
Member Author

gunnarmorling commented Oct 16, 2021 via email

@Croway
Copy link
Contributor

Croway commented Oct 18, 2021

I have created an annotation processor, you are right, not 100% a use case, but it works, these are the branches https://github.com/Croway/jfrunit/tree/jfr-event-cons-annotation-proc and https://github.com/Croway/jfr-constants-generator/tree/annotation-processor I think that we can proceed this way:

  • Transform jfrunit in a multi module maven project and add the generator
    or
  • Release the generator on maven central and use it as a dependency (I'm not experienced with releasing on maven central)

WDYT?

@gunnarmorling
Copy link
Member Author

I'd definitely prefer option a), making this a multi-module project. This will allow for quicker turnaround times after changes to the generator, and I think it just makes more sense to maintain everything in one place.

@gunnarmorling
Copy link
Member Author

On the style of the generated code, do you think the Attribute model is advantageous over the one with actual methods? I feel this would be nicer to use. WDYT?

@Croway
Copy link
Contributor

Croway commented Oct 21, 2021

Hi @gunnarmorling, I pushed new commits into https://github.com/Croway/jfrunit/tree/jfr-event-cons-annotation-proc

  • I have converted jfrunit to a multi-module project, I need some help with naming and poms (I'm not sure how the release will work), right now I created 2 modules, core (ex jfrunit) and events-generator if you have any hint please let me know.
  • I managed to generate methods with right signature inside event classes, it works as you can see from JfrUnitTest#shouldHaveGcAndSleepEvents (line 47, 48) and it is much more clear and easy to use, but I need some time to integrate all functions and do a code cleanup.
  • I think that functions has and hasNot are pointless when using this typed approach, WDYT?

@gunnarmorling
Copy link
Member Author

Ok, that sounds great. I'd suggest you create a PR when you feel ready for it. Doesn't have to be polished yet, but it may help to discuss and converge on the overall approach (though I feel we're essentially there yet as per the discussion above). Thanks a lot!

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

No branches or pull requests

2 participants