Some ideas about the Java API:
OK, it would be nice, if someone volunteered to help with this.
I may help with jar packing and API in my spare time. But I have never published jars to central personally, that needs an experienced one
I can do the publishing part.
Some other issues popped during my experience with async-profiler, one feature I hope Java API has:
ability to specify dumped file path in API.
The rationale is that sometimes we want to defer the start of profiler: after loading other native library by calling System.load or similar, so the native library's symbol can be identified correctly. Then the profiler output can be dumped at the JVM exit. However it's impossible for Java API to specify an output file.
@apangin what do you think? If this seems ok. I will try to send a PR. And Let's keep this issue open for a while
Java API returns profiling data as a String, then you do whatever you want with this String: write to a file etc.
Shutdown Hook can be used to stop profiler before VM exit.
Java API returns profiling data as a String, then you do whatever you want with this String: write to a file etc.
Yeah, I know, but that requires wrapper code to flush the output into file. If we can flush output to file, the execute API can be used as same as Java Agent(or Attach)'s options.
OK. Now if execute(command) contains file= option, the output will be dumped directly to the given file.
OK. Now if execute(command) contains file= option, the output will be dumped directly to the given file.
Thanks, it works as expected after I check the master branch.
However my old approach was persisting execute's argument into vmEntry's internal _agent_args: so it's dumped automatically at JVM exit.
I would argue that Java API should not modify global arguments designed primarily for the agent loaded at start-up. At Java level an application can still use Java mechanisms such as Shutdown Hook.
I would argue that Java API should not modify global arguments designed primarily for the agent loaded at start-up. At Java level an application can still use Java mechanisms such as Shutdown Hook.
Yeah, that's a fair point. It's ugly to modify _agent_args. User can register a shutdown hook, however it would be more convenient if provided(or handled) by the Java API. I am still thinking other possible approaches.
Adding
public static final String EVENT_CPU = "cpu";
public static final String EVENT_ALLOC = "alloc";
public static final String EVENT_LOCK = "lock";
to AsyncProfiler.java would make the event parameter for start() more clear.
@jesperpedersen Agree
Jar contains libAsynProfiler.so(dylib) so that the jar can be used independently
How would you load the native library? OS-dependently export libasyncProfiler.so to a temp folder and load via System.load?
@apangin soft reminder #365
Hi
We were just in a middle of working on this:
https://github.com/taboola/async-profiler-actuator-endpoint
And we made it public today.
It is relevant to this discussion, so - sharing.
Feedback is welcome, share your thoughts :)
Thanks
@apangin I've seen your review remarks as #365 of @JigarJoshi PR.
I have following idea to fulfill your requirements:
async-profiler-linux-x64-1.8.2.jar with async-profiler-linux-x64-1.8.2.soasync-profiler-linux-x86-1.8.2.jar with async-profiler-linux-x86-1.8.2.soasync-profiler-linux-musl-x64-1.8.2.jar with async-profiler-linux-musl-x64-1.8.2.soasync-profiler-linux-arm-1.8.2.jar with async-profiler-linux-arm-1.8.2.soasync-profiler-linux-aarch64-1.8.2.jar with async-profiler-linux-aarch64-1.8.2.soasync-profiler-macos-x64-1.8.2.jar with async-profiler-macos-x64-1.8.2.soasync-profiler-linux-x64-2.0-b1.jar with async-profiler-linux-x64-2.0-b1.soasync-profiler-macos-x64-2.0-b1.jar with async-profiler-macos-x64-2.0-b1.soasync-profiler sources at async-profiler-2.0-b1.jargetInstance() with enumeration param representing one of native's library jar.Thanks to such approach it would be easily to integrate mavenized async-profiler with IoC (i.e. Spring). I can imagine that someone would need to import on classpath async-profiler-macos-x64-1.8.2.jar for development and async-profiler-linux-x64-1.8.2.jar for production. Thanks to the IoC configuration proper native library would be loaded for each environment. Pls let me know what is your opinion for such approach.
I can either continue work on #365 PR or create brand new branch.
Remarks:
We could also validate if user mistakenly choose wrong library (as linux lib on mac os and so on). However it adds additional code to maintain so I rather think we can just fail on loading such library, try to load one in default locations if it's also fails then just throw exception.
@wyhasany Thank you for working on this. The plans sounds good to me. I'm only not sure what you mean by "enumeration param representing one of native's library jar"? Can you give an example please?
@apangin First of all thank you for your feedback, I can start work now 馃憤
Enum can looks like as following:
enum NativeJarLibrary {
LINUX_X64_1_8_2("api.one.profiler.Linux64_1_8_2"),
LINUX_X86_1_8_2("api.one.profiler.Linux86_1_8_2"),
LINUX_MUSL_X64_1_8_2("api.one.profiler.LinuxMusl64_1_8_2"),
LINUX_ARM_1_8_2("api.one.profiler.LinuxArm_1_8_2"),
LINUX_AARCH64_1_8_2("api.one.profiler.LinuxAarch64_1_8_2"),
MACOS_X64_1_8_2("api.one.profiler.MacOsX64_1_8_2"),
MACOS_X64_2_0_0("api.one.profiler.MacOsX64_2_0_0"),
LINUX_X64_2_0_0("api.one.profiler.Linux64_2_0_0");
private String clazzNextToNativeLibrary;
NativeJarLibrary(String clazzNextToNativeLibrary) {
this.clazzNextToNativeLibrary = clazzNextToNativeLibrary;
}
Class<?> classNextToNativeLibrary(ClassLoader classLoader) {
if (classLoader != null) {
return getClass(classLoader);
} else {
return getClass(NativeJarLibrary.class.getClassLoader());
}
}
private Class<?> getClass(ClassLoader classLoader) {
try {
return Class.forName(clazzNextToNativeLibrary, true, classLoader);
} catch (ClassNotFoundException e) {
//log warn
return null;
}
}
}
based on class we can find native library. Current API then could be extended with following method:
+ public static AsyncProfiler getInstance(NativeJarLibrary nativeJarLibrary)
any client can call that getInstance if it fails because that user uses different architecture or he have forgotten to add dependency we'll log warning and fallback to standard native library resolution (as in getInstance()).
In the Elastic APM Java agent, we bundle async-profiler as a resource and load it depending on the system it's running on: https://github.com/elastic/apm-agent-java/blob/f9a1bfd6a15c9c8e2bb6512a6973375a78ebb97d/apm-agent-plugins/apm-profiling-plugin/src/main/java/co/elastic/apm/agent/profiler/asyncprofiler/AsyncProfiler.java#L94-L121
Could that approach be an option for the official async-profiler jar?
Netty project uses https://github.com/trustin/os-maven-plugin and this is the best solution I have seen in Java world for detecting the OS and architecture and to decide what extension to produce at artifact build time and what dependency to download when using a third party library.
@felixbarny There are two differents:
@martin-g Thank you for your recommendation. I don't know os-maven-plugin. I'm going to learn how we can use it to simplify async-profiler mavenizing.
@wyhasany TBH, I don't see much value in enumerating native libraries and letting developers choose one themselves.
@apangin ok. I'm going to do it as you wish :)
Never mind - it looks like I need to do the routine myself anyway, in order to be able to make releases on Maven Central.
I've just managed to published async-profiler API under the following artifact:
<dependency>
<groupId>tools.profiler</groupId>
<artifactId>async-profiler</artifactId>
<version>1.8.3</version>
</dependency>
It does not include agent library though. This will be only included in v2.0.
FWIW, a minor datapoint: clj-async-profiler does exactly what @felixbarny suggested 鈥撀爀xtracting the native binary into a temp directory at runtime and loading it with System.load. Hacky, but it works.
Some hardened systems are configured so that they don't run binaries from temp. A workaround for that would be to let users define the target folder. That can be one through a system property, for example. But temp is still a good default, I think.
It does not include agent library though. This will be only included in v2.0.
Is there an estimated available time?
Is there an estimated available time?
I don't have an estimate, sorry. The task is pretty high on my list, but there are other current requests from business.
@apangin I saw v2.0 has been released several days ago, seems this feature is absent, any update for future plan?
@pan3793 The task is in the nearest plans. No specific commitments though.
Most helpful comment
Never mind - it looks like I need to do the routine myself anyway, in order to be able to make releases on Maven Central.
I've just managed to published async-profiler API under the following artifact:
It does not include agent library though. This will be only included in v2.0.