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

Auto-configure VirtualThreadMetrics from micrometer-java21 #43122

Open
shakuzen opened this issue Nov 12, 2024 · 3 comments
Open

Auto-configure VirtualThreadMetrics from micrometer-java21 #43122

shakuzen opened this issue Nov 12, 2024 · 3 comments
Labels
type: enhancement A general enhancement
Milestone

Comments

@shakuzen
Copy link
Member

Micrometer added a new MeterBinder for virtual thread metrics via micrometer-metrics/micrometer#5067 - documentation is at https://docs.micrometer.io/micrometer/reference/reference/jvm.html#_java_21_metrics. It is in a new module micrometer-java21. It would be nice if Spring Boot has auto-configuration for VirtualThreadMetrics.

@spring-projects-issues spring-projects-issues added the status: waiting-for-triage An issue we've not yet triaged label Nov 12, 2024
@mhalbritter mhalbritter added type: enhancement A general enhancement and removed status: waiting-for-triage An issue we've not yet triaged labels Nov 12, 2024
@mhalbritter mhalbritter added this to the 3.5.x milestone Nov 12, 2024
@nosan
Copy link
Contributor

nosan commented Nov 17, 2024

class file has wrong version 65.0, should be 61.0
Please remove or make sure it appears in the correct subdirectory of the classpath.

micrometer-java21 is built using JDK21, whereas Spring Boot source code is JDK17 source compatible, hence either reflection or multi-release jar should be used to add support for VirtualThreadMetrics.

I've prototyped changes in my branch by using reflection and FactoryBean.

I also checked VirtualThreadMetrics with a native-image, and unfortunately, I got the following exception:

org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'virtualThreadMetrics': Instantiation of supplied bean failed
        at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.obtainFromSupplier(AbstractAutowireCapableBeanFactory.java:1239)
        at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1176)
        at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:563)
        at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:523)
        at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:336)
        at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:288)
        at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:334)
        at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:199)
        at org.springframework.beans.factory.support.DefaultListableBeanFactory.instantiateSingleton(DefaultListableBeanFactory.java:1122)
        at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingleton(DefaultListableBeanFactory.java:1093)
        at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:1030)
        at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:987)
        at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:627)
        at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.refresh(ServletWebServerApplicationContext.java:146)
        at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:752)
        at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:439)
        at org.springframework.boot.SpringApplication.run(SpringApplication.java:318)
        at org.springframework.boot.SpringApplication.run(SpringApplication.java:1361)
        at org.springframework.boot.SpringApplication.run(SpringApplication.java:1350)
        at task.gh43122.Gh43122Application.main(Gh43122Application.java:12)
        at java.base@21.0.5/java.lang.invoke.LambdaForm$DMH/sa346b79c.invokeStaticInit(LambdaForm$DMH)
Caused by: java.lang.UnsatisfiedLinkError: jdk.jfr.internal.JVM.getPid()Ljava/lang/String; [symbol: Java_jdk_jfr_internal_JVM_getPid or Java_jdk_jfr_internal_JVM_getPid__]
        at org.graalvm.nativeimage.builder/com.oracle.svm.core.jni.access.JNINativeLinkage.getOrFindEntryPoint(JNINativeLinkage.java:152)
        at org.graalvm.nativeimage.builder/com.oracle.svm.core.jni.JNIGeneratedMethodSupport.nativeCallAddress(JNIGeneratedMethodSupport.java:54)
        at jdk.jfr@21.0.5/jdk.jfr.internal.JVM.getPid(Native Method)
        at jdk.jfr@21.0.5/jdk.jfr.internal.Repository.createRepository(Repository.java:110)
        at jdk.jfr@21.0.5/jdk.jfr.internal.Repository.setBasePath(Repository.java:65)
        at jdk.jfr@21.0.5/jdk.jfr.internal.Repository.ensureRepository(Repository.java:79)
        at jdk.jfr@21.0.5/jdk.jfr.internal.PlatformRecorder.<init>(PlatformRecorder.java:81)
        at jdk.jfr@21.0.5/jdk.jfr.FlightRecorder.getFlightRecorder(FlightRecorder.java:171)
        at jdk.jfr@21.0.5/jdk.jfr.Recording.<init>(Recording.java:107)
        at jdk.jfr@21.0.5/jdk.jfr.Recording.<init>(Recording.java:131)
        at jdk.jfr@21.0.5/jdk.jfr.consumer.RecordingStream.<init>(RecordingStream.java:108)
        at jdk.jfr@21.0.5/jdk.jfr.consumer.RecordingStream.<init>(RecordingStream.java:101)
        at io.micrometer.java21.instrument.binder.jdk.VirtualThreadMetrics.createRecordingStream(VirtualThreadMetrics.java:78)
        at io.micrometer.java21.instrument.binder.jdk.VirtualThreadMetrics.<init>(VirtualThreadMetrics.java:57)
        at io.micrometer.java21.instrument.binder.jdk.VirtualThreadMetrics.<init>(VirtualThreadMetrics.java:49)
        at task.gh43122.Gh43122Application.virtualThreadMetrics(Gh43122Application.java:17)
        at task.gh43122.Gh43122Application$$SpringCGLIB$$0.CGLIB$virtualThreadMetrics$0(<generated>)
        at task.gh43122.Gh43122Application$$SpringCGLIB$$FastClass$$1.invoke(<generated>)
        at org.springframework.cglib.proxy.MethodProxy.invokeSuper(MethodProxy.java:258)
        at org.springframework.context.annotation.ConfigurationClassEnhancer$BeanMethodInterceptor.intercept(ConfigurationClassEnhancer.java:348)
        at task.gh43122.Gh43122Application$$SpringCGLIB$$0.virtualThreadMetrics(<generated>)
        at task.gh43122.Gh43122Application__BeanDefinitions.lambda$getVirtualThreadMetricsInstanceSupplier$0(Gh43122Application__BeanDefinitions.java:32)
        at org.springframework.util.function.ThrowingFunction.apply(ThrowingFunction.java:63)
        at org.springframework.util.function.ThrowingFunction.apply(ThrowingFunction.java:51)
        at org.springframework.beans.factory.aot.BeanInstanceSupplier.lambda$get$1(BeanInstanceSupplier.java:219)
        at org.springframework.util.function.ThrowingSupplier.get(ThrowingSupplier.java:58)
        at org.springframework.util.function.ThrowingSupplier.get(ThrowingSupplier.java:46)
        at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiateWithFactoryMethod(SimpleInstantiationStrategy.java:88)
        at org.springframework.beans.factory.aot.BeanInstanceSupplier.invokeBeanSupplier(BeanInstanceSupplier.java:256)
        at org.springframework.beans.factory.aot.BeanInstanceSupplier.get(BeanInstanceSupplier.java:219)
        at org.springframework.beans.factory.support.DefaultListableBeanFactory.obtainInstanceFromSupplier(DefaultListableBeanFactory.java:979)
        at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.obtainFromSupplier(AbstractAutowireCapableBeanFactory.java:1233)
        ... 20 more

Sample to reproduce: gh-43122.zip

mvn clean spring-boot:build-image -Pnative
docker run -p 8080:8080 docker.io/library/gh-43122:0.0.1-SNAPSHOT

@oleksiizaitsev7
Copy link

Hi it can be done with some conditions as we have here. But I'm not sure if that is the right way or preferable strategy for the java 21 support

@nosan
Copy link
Contributor

nosan commented Dec 2, 2024

Thanks for the suggestion, @oleksiizaitsev7
The problem is that using the VirtualThreadMetrics class results in a compile error, so adding @EnabledForJreRange won't resolve the issue.

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

No branches or pull requests

6 participants
@nosan @shakuzen @oleksiizaitsev7 @spring-projects-issues @mhalbritter and others