Skip to main content

Java

Pyroscope uses async-profiler to collect profiling data from Java applications.

Supported platforms#

LinuxmacOSWindowsDocker
โœ…โœ…โœ…

Installation#

Java integration is distributed as a single jar file: pyroscope.jar. It contains native async-profiler libraries for:

  • Linux on x64;
  • Linux on ARM64;
  • MacOS on x64.
  • MacOS on ARM64.

Visit our GitHub releases page to download the latest version of pyroscope.jar.

The latest release is also available on Maven Central.

Profiling Java application#

You can start pyroscope either from your apps's java code or attach it as javaagent

Start pyroscope from app's java code#

Add pyroscope dependency:

implementation("io.pyroscope:agent:${pyroscope_version}")

Then add the following code to your application:

PyroscopeAgent.start(  new Config.Builder()    .setApplicationName("ride-sharing-app-java")    .setProfilingEvent(EventType.ITIMER)    .setFormat(Format.JFR)    .setServerAddress("http://pyroscope-server:4040")    // Optionally, if authentication is enabled, specify the API key.    // .setAuthToken(System.getenv("PYROSCOPE_AUTH_TOKEN"))    .build());

You can also optionally replace some pyroscope components

PyroscopeAgent.start(  new PyroscopeAgent.Options.Builder(config)    .setExporter(snapshot -> {      // Your custom export/upload logic may go here      // It is invoked every 10 seconds by default with snapshot of       // profiling data    })    .setLogger((l, msg, args) -> {      // Your custom logging may go here      // Pyroscope does not depend on any logging library      System.out.printf((msg) + "%n", args);    })    .setScheduler(profiler -> {      // Your custom profiling schedule logic may go here    })    .build());

Start pyroscope as javaagent#

To start profiling a Java application, run your application with pyroscope.jar javaagent:

export PYROSCOPE_APPLICATION_NAME=my.java.appexport PYROSCOPE_SERVER_ADDRESS=http://pyroscope-server:4040
# Optionally, if authentication is enabled, specify the API key.# export PYROSCOPE_AUTH_TOKEN={YOUR_API_KEY}
java -javaagent:pyroscope.jar -jar app.jar

Configuration#

When you start pyroscope as javaagent or obtain configuration by Config.build() pyroscope searches for configuration in multiple sources: system properties, environment variables, pyroscope.properties file. Properties keys has same name as environment variables, but lowercased and replaced _ with ., so PYROSCOPE_FORMAT becomes pyroscope.format

Java integration supports JFR format to be able to support multiple events (JFR is the only output format that supports multiple events in async-profiler). There are several environment variables that define how multiple event configuration works:

  • PYROSCOPE_FORMAT sets the profiler output format. The default is collapsed, but in order to support multiple formats it must be set to jfr.
  • PYROSCOPE_PROFILER_EVENT sets the profiler event. With JFR format enabled, this event refers to one of the possible CPU profiling events: itimer, cpu, wall. The default is itimer.
  • PYROSCOPE_PROFILER_ALLOC sets the allocation threshold to register the events, in bytes (equivalent to --alloc= in async-profiler). The default value is "" - empty string, which means that allocation profiling is disabled. Setting it to 0 will register all the events.
  • PYROSCOPE_PROFILER_LOCK sets the lock threshold to register the events, in nanoseconds (equivalent to --lock= in async-profiler). The default value is "" - empty string, which means that lock profiling is disabled. Setting it to 0 will register all the events.
  • PYROSCOPE_PUSH_QUEUE_CAPACITY sets the default pyroscope exporter push queue capacity. The default value is 32 snapshots.
  • PYROSCOPE_CONFIGURATION_FILE sets an additional properties configuration file. The default value is pyroscope.properties.
  • PYROSCOPE_LABELS sets static labels in the form of comma separated key=value pairs. The default value is "" - enpty string, no labels.

Labels#

It is possible to add dynamic tags (labels) to the profiling data. These tags can be used to filter the data in the UI.

Add labels dynamically:

Pyroscope.LabelsWrapper.run(new LabelsSet("controller", "slow_controller"), () -> {  slowCode();});

It is also possible to possible to add static tags (labels) to the profiling data:

Pyroscope.setStaticLabels(Map.of("region", System.getenv("REGION")));// or with Config.Builder if you start pyroscope with PyroscopeAgent.startPyroscopeAgent.start(new Config.Builder()    .setLabels(mapOf("region", System.getenv("REGION")))    // ...    .build());

Examples#

Check out the examples folder in our repository to learn more ๐Ÿ”ฅ