Skip to content

Commit 866e7c7

Browse files
authored
java: Add --java-async-profiler-args, allowing to send arbitrary extra args to AP (#262)
1 parent e58352c commit 866e7c7

File tree

3 files changed

+32
-5
lines changed

3 files changed

+32
-5
lines changed

gprofiler/profilers/java.py

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -134,6 +134,7 @@ def __init__(
134134
buildids: bool,
135135
mode: str,
136136
ap_safemode: int,
137+
ap_args: str,
137138
):
138139
self.process = process
139140
# access the process' root via its topmost parent/ancestor which uses the same mount namespace.
@@ -178,6 +179,7 @@ def __init__(
178179
assert mode in ("cpu", "itimer"), f"unexpected mode: {mode}"
179180
self._mode = mode
180181
self._ap_safemode = ap_safemode
182+
self._ap_args = ap_args
181183

182184
def __enter__(self):
183185
os.makedirs(self._ap_dir_host, 0o755, exist_ok=True)
@@ -286,13 +288,16 @@ def _get_base_cmd(self) -> List[str]:
286288
"true",
287289
]
288290

291+
def _get_extra_ap_args(self) -> str:
292+
return f",{self._ap_args}" if self._ap_args else ""
293+
289294
def _get_start_cmd(self, interval: int) -> List[str]:
290295
return self._get_base_cmd() + [
291296
f"start,event={self._mode},file={self._output_path_process},"
292297
f"{self.OUTPUT_FORMAT},{self.FORMAT_PARAMS},interval={interval},"
293298
f"log={self._log_path_process}{',buildids' if self._buildids else ''}"
294299
f"{',fdtransfer' if self._mode == 'cpu' else ''}"
295-
f",safemode={self._ap_safemode}"
300+
f",safemode={self._ap_safemode}{self._get_extra_ap_args()}"
296301
]
297302

298303
def _get_stop_cmd(self, with_output: bool) -> List[str]:
@@ -302,7 +307,7 @@ def _get_stop_cmd(self, with_output: bool) -> List[str]:
302307
ap_params.append(self.OUTPUT_FORMAT)
303308
ap_params.append(self.FORMAT_PARAMS)
304309
ap_params.append(f"log={self._log_path_process}")
305-
return self._get_base_cmd() + [",".join(ap_params)]
310+
return self._get_base_cmd() + [",".join(ap_params) + self._get_extra_ap_args()]
306311

307312
def _run_async_profiler(self, cmd: List[str]) -> None:
308313
try:
@@ -464,6 +469,12 @@ def parse_jvm_version(version_string: str) -> JvmVersion:
464469
" enum in async-profiler's code, in profiler.cpp)."
465470
" Defaults to '%(default)s').",
466471
),
472+
ProfilerArgument(
473+
"--java-async-profiler-args",
474+
dest="java_async_profiler_args",
475+
type=str,
476+
help="Additional arguments to pass directly to async-profiler (start & stop commands)",
477+
),
467478
ProfilerArgument(
468479
"--java-safemode",
469480
dest="java_safemode",
@@ -499,6 +510,7 @@ def __init__(
499510
java_version_check: bool,
500511
java_async_profiler_mode: str,
501512
java_async_profiler_safemode: int,
513+
java_async_profiler_args: str,
502514
java_safemode: str,
503515
java_mode: str,
504516
):
@@ -514,6 +526,7 @@ def __init__(
514526
logger.warning("Java version checks are disabled")
515527
self._mode = java_async_profiler_mode
516528
self._ap_safemode = java_async_profiler_safemode
529+
self._ap_args = java_async_profiler_args
517530
self._init_java_safemode(java_safemode)
518531
self._should_profile = True
519532
# if set, profiling is disabled due to this safemode reason.
@@ -704,7 +717,9 @@ def _profile_process(self, process: Process) -> Optional[StackToSampleCount]:
704717
self._profiled_pids.add(process.pid)
705718

706719
logger.info(f"Profiling process {process.pid} with async-profiler")
707-
with AsyncProfiledProcess(process, self._storage_dir, self._buildids, self._mode, self._ap_safemode) as ap_proc:
720+
with AsyncProfiledProcess(
721+
process, self._storage_dir, self._buildids, self._mode, self._ap_safemode, self._ap_args
722+
) as ap_proc:
708723
return self._profile_ap_process(ap_proc, comm)
709724

710725
def _profile_ap_process(self, ap_proc: AsyncProfiledProcess, comm: str) -> Optional[StackToSampleCount]:

tests/test_java.py

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -42,11 +42,12 @@ def test_async_profiler_already_running(application_pid, assert_collapsed, tmp_p
4242
False,
4343
java_async_profiler_mode="cpu",
4444
java_async_profiler_safemode=0,
45+
java_async_profiler_args="",
4546
java_safemode="",
4647
java_mode="ap",
4748
) as profiler:
4849
process = profiler._select_processes_to_profile()[0]
49-
with AsyncProfiledProcess(process, profiler._storage_dir, False, profiler._mode, False) as ap_proc:
50+
with AsyncProfiledProcess(process, profiler._storage_dir, False, profiler._mode, False, "") as ap_proc:
5051
assert ap_proc.start_async_profiler(11)
5152
assert any("libasyncProfiler.so" in m.path for m in process.memory_maps())
5253
# run "status"
@@ -56,6 +57,7 @@ def test_async_profiler_already_running(application_pid, assert_collapsed, tmp_p
5657
False,
5758
mode="itimer",
5859
ap_safemode=False,
60+
ap_args="",
5961
) as ap_proc:
6062
ap_proc.status_async_profiler()
6163
# printed the output file, see ACTION_STATUS case in async-profiler/profiler.cpp
@@ -86,6 +88,7 @@ def test_java_async_profiler_cpu_mode(
8688
True,
8789
java_async_profiler_mode="cpu",
8890
java_async_profiler_safemode=0,
91+
java_async_profiler_args="",
8992
java_safemode="",
9093
java_mode="ap",
9194
) as profiler:
@@ -114,6 +117,7 @@ def test_java_async_profiler_musl_and_cpu(
114117
True,
115118
java_async_profiler_mode="cpu",
116119
java_async_profiler_safemode=0,
120+
java_async_profiler_args="",
117121
java_safemode="",
118122
java_mode="ap",
119123
) as profiler:
@@ -133,6 +137,7 @@ def test_java_safemode_parameters(tmp_path) -> None:
133137
True,
134138
java_async_profiler_mode="cpu",
135139
java_async_profiler_safemode=0,
140+
java_async_profiler_args="",
136141
java_safemode=JAVA_SAFEMODE_ALL,
137142
java_mode="ap",
138143
)
@@ -148,6 +153,7 @@ def test_java_safemode_parameters(tmp_path) -> None:
148153
False,
149154
java_async_profiler_mode="cpu",
150155
java_async_profiler_safemode=127,
156+
java_async_profiler_args="",
151157
java_safemode=JAVA_SAFEMODE_ALL,
152158
java_mode="ap",
153159
)
@@ -168,6 +174,7 @@ def test_java_safemode_version_check(
168174
True,
169175
java_async_profiler_mode="cpu",
170176
java_async_profiler_safemode=127,
177+
java_async_profiler_args="",
171178
java_safemode=JAVA_SAFEMODE_ALL,
172179
java_mode="ap",
173180
) as profiler:
@@ -193,6 +200,7 @@ def test_java_safemode_build_number_check(
193200
True,
194201
java_async_profiler_mode="cpu",
195202
java_async_profiler_safemode=127,
203+
java_async_profiler_args="",
196204
java_safemode=JAVA_SAFEMODE_ALL,
197205
java_mode="ap",
198206
) as profiler:
@@ -235,6 +243,7 @@ def sap_and_crash(self, *args, **kwargs):
235243
True,
236244
java_async_profiler_mode="cpu",
237245
java_async_profiler_safemode=127,
246+
java_async_profiler_args="",
238247
java_safemode=JAVA_SAFEMODE_ALL,
239248
java_mode="ap",
240249
)
@@ -253,7 +262,7 @@ def sap_and_crash(self, *args, **kwargs):
253262
def test_disable_java_profiling(application_pid, tmp_path, monkeypatch, caplog):
254263
caplog.set_level(logging.DEBUG)
255264

256-
profiler = JavaProfiler(1, 5, Event(), str(tmp_path), False, False, "cpu", 0, False, "ap")
265+
profiler = JavaProfiler(1, 5, Event(), str(tmp_path), False, False, "cpu", 0, "", False, "ap")
257266
dummy_reason = "dummy reason"
258267
monkeypatch.setattr(profiler, "_safemode_disable_reason", dummy_reason)
259268
with profiler:
@@ -275,6 +284,7 @@ def test_already_loaded_async_profiler_profiling_failure(tmp_path, monkeypatch,
275284
True,
276285
java_async_profiler_mode="cpu",
277286
java_async_profiler_safemode=127,
287+
java_async_profiler_args="",
278288
java_safemode=JAVA_SAFEMODE_ALL,
279289
java_mode="ap",
280290
) as profiler:
@@ -289,6 +299,7 @@ def test_already_loaded_async_profiler_profiling_failure(tmp_path, monkeypatch,
289299
True,
290300
java_async_profiler_mode="cpu",
291301
java_async_profiler_safemode=127,
302+
java_async_profiler_args="",
292303
java_safemode=JAVA_SAFEMODE_ALL,
293304
java_mode="ap",
294305
) as profiler:

tests/test_sanity.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ def test_java_from_host(
4141
True,
4242
java_async_profiler_mode="itimer",
4343
java_async_profiler_safemode=0,
44+
java_async_profiler_args="",
4445
java_safemode="",
4546
java_mode="ap",
4647
) as profiler:

0 commit comments

Comments
 (0)