Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 0 additions & 12 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,18 +29,6 @@ of `pyroscope.jar`

Visit [docs](https://pyroscope.io/docs/java/) page for usage and configuration documentation.

### Experimental OTLP Profiles export

The agent can export async-profiler recordings using the experimental OpenTelemetry Profiles signal. Set
`PYROSCOPE_FORMAT=otlp` and configure `PYROSCOPE_SERVER_ADDRESS` with the base address of an OTLP/HTTP receiver.
The agent sends protobuf requests to `<server-address>/v1development/profiles`.

OTLP export requires the default `ASYNC` profiler and is not supported by the JFR profiler used on Windows.
Only one profiling event can run at a time. Allocation and lock thresholds can be configured when their event is
selected, for example with `PYROSCOPE_PROFILER_EVENT=alloc` and `PYROSCOPE_PROFILER_ALLOC=512k`. Multiple events
remain supported in sampling mode because they run sequentially.
The OpenTelemetry Profiles protocol and async-profiler output are experimental and may change incompatibly.

## Building

If you want to build the agent JAR yourself, from this repo run:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -147,6 +147,8 @@ private Snapshot dumpImpl(Instant started, Instant ended) {
started,
ended,
data,
// This also removes closed scoped contexts. Keep draining them even though the
// current OTLP exporter does not include the resulting labels snapshot.
Pyroscope.LabelsWrapper.dump()
);
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package io.pyroscope.javaagent;

import io.pyroscope.http.Format;
import io.pyroscope.javaagent.api.Exporter;
import io.pyroscope.javaagent.api.Logger;
import io.pyroscope.javaagent.api.ProfilingScheduler;
Expand Down Expand Up @@ -59,6 +60,11 @@ public static void start(@NotNull Options options) {
}
sOptions = options;
logger.log(Logger.Level.DEBUG, "Config: %s", options.config);
if (options.config.format == Format.OTLP) {
logger.log(Logger.Level.WARN,
"OTLP export does not include the configured application name or labels; " +
"profiles may appear under service_name=\"unknown_service\"");
}
try {
options.scheduler.start(options.profiler);
ScopedContext.ENABLED.set(true);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package io.pyroscope.javaagent;

import io.pyroscope.http.Format;
import io.pyroscope.javaagent.api.Logger;
import io.pyroscope.javaagent.api.ProfilingScheduler;
import io.pyroscope.javaagent.config.Config;
Expand Down Expand Up @@ -27,6 +28,9 @@ public class PyroscopeAgentTest {
@Mock
private ProfilingScheduler profilingScheduler;

@Mock
private ProfilerDelegate profiler;

@BeforeEach
void setUp() {
configAgentEnabled = new Config.Builder()
Expand All @@ -35,6 +39,7 @@ void setUp() {
optionsAgentEnabled = new PyroscopeAgent.Options.Builder(configAgentEnabled)
.setScheduler(profilingScheduler)
.setLogger(logger)
.setProfiler(profiler)
.build();

configAgentDisabled = new Config.Builder()
Expand All @@ -43,6 +48,7 @@ void setUp() {
optionsAgentDisabled = new PyroscopeAgent.Options.Builder(configAgentDisabled)
.setScheduler(profilingScheduler)
.setLogger(logger)
.setProfiler(profiler)
.build();
}

Expand All @@ -56,6 +62,7 @@ void startupTestWithEnabledAgent() {
PyroscopeAgent.start(optionsAgentEnabled);

verify(profilingScheduler, times(1)).start(any());
verify(logger, never()).log(eq(Logger.Level.WARN), contains("OTLP export"));
}

@Test
Expand All @@ -64,4 +71,24 @@ void startupTestWithDisabledAgent() {

verify(profilingScheduler, never()).start(any());
}
}

@Test
void warnsWhenOtlpDoesNotIncludeApplicationNameOrLabels() {
Config config = new Config.Builder()
.setAgentEnabled(true)
.setFormat(Format.OTLP)
.build();
PyroscopeAgent.Options options = new PyroscopeAgent.Options.Builder(config)
.setScheduler(profilingScheduler)
.setLogger(logger)
.setProfiler(profiler)
.build();

PyroscopeAgent.start(options);

verify(logger).log(
Logger.Level.WARN,
"OTLP export does not include the configured application name or labels; " +
"profiles may appear under service_name=\"unknown_service\"");
}
}
Loading