clj-async-profiler icon indicating copy to clipboard operation
clj-async-profiler copied to clipboard

Profiling doesn't work on Alpine docker images out of the box

Open bsless opened this issue 4 years ago • 6 comments

Hello, The profiler wasn't working for me from inside Alpine docker images (related to #12) and I managed to refine down the steps required to make it work. Some could be additions to the profiler itself, some are just requirements which have to be satisfied:

  • The musl compatible .so is missing. Adding it as a resource is the simplest part.
  • There's no detection if running in a musl environment or regular linux kernel. Besides resetting the .so path manually there's no comfortable solution.
  • Without jdk installed the virtual machine class is missing. Can be remedied by adding com.sun/tools as a dependency or specify it should be required externally by the project. There's also an issue with it not being in the regular maven repositories, each version is in another repository entirely, and some of them don't provide https. Has success with [com.sun/tools "1.7.0.13"] and :repositories [["nuition" "https://nexus.nuiton.org/nexus/content/groups/releases/"]]
  • alpine packages requirements: apk add libstdc++ perl

Then the profiler works from inside a docker image (phew)

bsless avatar Feb 08 '20 11:02 bsless

Hi, thanks for reporting!

clj-async-profiler is shipped only with those binaries that are built by async-profiler maintainers, so I won't be adding a musl-based binary. But yes, it can be built manually and given to clj-async-profiler, just like you did.

I will add the JDK requirement into the README.

On a tangential note, I honestly wouldn't touch Alpine with a ten-foot pole. I had a fair share of problems with it regarding Unicode in Java, and those same musl-caused issues. Debian-slim image is only 27MB these days, and once you start installing dependencies there's no difference in size between it and Alpine anyway.

alexander-yakushev avatar Feb 08 '20 16:02 alexander-yakushev

Ah, I see. The musl compiled .so was added in v1.6 and you're using 1.5. If you're not interested in moving to the next version, another solution would be:

  • the user should have the .so somewhere loadable as a resource.
  • unpack-from-jar should be made public
  • finally: (reset! clj-async-profiler.core/async-profiler-agent-path (unpack-from-jar path)), which can be triggered externally (api call, etc).

Then the .so could be dynamically initialized by the user (that's what I ended up doing in my use case anyway)

I'll also take your Alpine recommendation to heart. It isn't exactly my decision, but I'll pass it on nonetheless.

bsless avatar Feb 09 '20 07:02 bsless

The musl compiled .so was added in v1.6 and you're using 1.5.

Oops, I am sorry, I missed that part 😄 In that case, I can surely add it to resources; however, we'll indeed need some sort of identifier that the musl replaces libc in the current environment.

alexander-yakushev avatar Feb 09 '20 09:02 alexander-yakushev

Perhaps this could help? https://gist.github.com/calebhailey/ed581beb1997892f63637da45263516f TL;DR - use ldd --version

bsless avatar Feb 09 '20 12:02 bsless

@bsless Hello Ben, hope you are doing well. Not sure if this still relevant to you, but version 0.5.2 includes the musl-linked binary and the code that chooses to use it when on Alpine.

alexander-yakushev avatar Jul 15 '22 20:07 alexander-yakushev

I'll check that it works in our production environment and report back

bsless avatar Jul 16 '22 12:07 bsless

Closing this since it should work on Alpine now (at least, the tests are passing on it!).

alexander-yakushev avatar Oct 16 '23 18:10 alexander-yakushev