Skip to content

Commit 55bc0b2

Browse files
committed
improve profiler command output, doc, timeout. #2961
1 parent 1df7f6b commit 55bc0b2

File tree

3 files changed

+62
-3
lines changed

3 files changed

+62
-3
lines changed

core/src/main/java/com/taobao/arthas/core/command/monitor200/ProfilerCommand.java

Lines changed: 50 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,9 @@
5151
+ " profiler list # list all supported events\n"
5252
+ " profiler actions # list all supported actions\n"
5353
+ " profiler start --event alloc\n"
54+
+ " profiler start --timeout 300s"
55+
+ " profiler start --loop 300s -f /tmp/result-%t.html"
56+
+ " profiler start --duration 300"
5457
+ " profiler stop --format html # output file format, support flat[=N]|traces[=N]|collapsed|flamegraph|tree|jfr\n"
5558
+ " profiler stop --file /tmp/result.html\n"
5659
+ " profiler stop --threads \n"
@@ -66,7 +69,10 @@
6669
//@formatter:on
6770
public class ProfilerCommand extends AnnotatedCommand {
6871
private static final Logger logger = LoggerFactory.getLogger(ProfilerCommand.class);
72+
// Track if a file was specified during profiler start
73+
private static String fileSpecifiedAtStart = null;
6974

75+
// TODO start 时,没指定 file, 是否在 stop 时,能生成 html 或者 jfr 不?
7076
private String action;
7177
private String actionArg;
7278

@@ -743,10 +749,36 @@ public void process(final CommandProcess process) {
743749
String result = execute(asyncProfiler, this.actionArg);
744750
appendExecuteResult(process, result);
745751
} else if (ProfilerAction.start.equals(profilerAction)) {
752+
// Track if file parameter was specified during start
753+
boolean autoGeneratedFile = false;
754+
if (this.file != null) {
755+
fileSpecifiedAtStart = this.file;
756+
logger.debug("File specified during profiler start: {}", fileSpecifiedAtStart);
757+
} else if (this.timeout != null) {
758+
// Auto-generate file if timeout is specified but file is not
759+
try {
760+
this.file = outputFile();
761+
logger.debug("Auto-generated file for timeout: {}", this.file);
762+
fileSpecifiedAtStart = this.file;
763+
autoGeneratedFile = true;
764+
} catch (IOException e) {
765+
logger.warn("Failed to auto-generate file for timeout", e);
766+
}
767+
}
768+
746769
if (this.duration == null) {
747770
String executeArgs = executeArgs(ProfilerAction.start);
748771
String result = execute(asyncProfiler, executeArgs);
749-
appendExecuteResult(process, result);
772+
ProfilerModel profilerModel = createProfilerModel(result);
773+
774+
// Add information about auto-generated file for timeout
775+
if (autoGeneratedFile && this.file != null) {
776+
profilerModel.setOutputFile(this.file);
777+
profilerModel.setExecuteResult(profilerModel.getExecuteResult()
778+
+ "\nAuto-generated output file will be: " + this.file + "\n");
779+
}
780+
781+
process.appendResult(profilerModel);
750782
} else { // 设置延时执行 stop
751783
final String outputFile = outputFile();
752784
String executeArgs = executeArgs(ProfilerAction.start);
@@ -833,12 +865,27 @@ public void run() {
833865
}
834866

835867
private ProfilerModel processStop(AsyncProfiler asyncProfiler, ProfilerAction profilerAction) throws IOException {
836-
String outputFile = outputFile();
868+
String outputFile = null;
869+
870+
// If we're stopping and a file was specified during start, don't generate a new
871+
// output file
872+
if (profilerAction == ProfilerAction.stop && fileSpecifiedAtStart != null) {
873+
outputFile = fileSpecifiedAtStart;
874+
// Reset the tracking variable after stop
875+
logger.debug("Using file specified during start: {}", fileSpecifiedAtStart);
876+
fileSpecifiedAtStart = null;
877+
} else {
878+
// Otherwise generate or use the specified output file
879+
outputFile = outputFile();
880+
}
881+
837882
String executeArgs = executeArgs(profilerAction);
838883
String result = execute(asyncProfiler, executeArgs);
839884

840885
ProfilerModel profilerModel = createProfilerModel(result);
841-
profilerModel.setOutputFile(outputFile);
886+
if (outputFile != null) {
887+
profilerModel.setOutputFile(outputFile);
888+
}
842889
return profilerModel;
843890
}
844891

site/docs/doc/profiler.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -377,12 +377,18 @@ profiler start -e cpu --jfrsync +jdk.YoungGarbageCollection+jdk.OldGarbageCollec
377377

378378
使用 `--loop TIME` 可以持续运行 profiler 并周期性保存结果。选项格式可以是具体时间 hh:mm:ss 或以秒、分钟、小时或天计算的时间间隔。需要确保指定的输出文件名中包含时间戳,否则每次输出的结果都会覆盖上次保存的结果。以下命令持续执行 profiling 并将每个小时内的记录保存到一个 jfr 文件中。
379379

380+
> 如果没有指定 `-f` 参数,则不会保存任何内容。如果 `-f` 参数里没有 `%t`,则会循环保存到同一个文件里。
381+
380382
```bash
381383
profiler start --loop 1h -f /var/log/profile-%t.jfr
382384
```
383385

384386
## `--timeout` 选项
385387

388+
```bash
389+
profiler start --timeout 300s
390+
```
391+
386392
这个选项指定 profiling 自动在多久后停止。该选项和 `--loop` 选项的格式一致,可以是时间点,也可以是一个时间间隔。这两个选项都是用于 `start` action。可参考 [async-profiler docs](https://github.com/async-profiler/async-profiler/blob/master/docs/ProfilerOptions.md) 了解更多信息。
387393

388394
## `--wall` 选项

site/docs/en/doc/profiler.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -379,12 +379,18 @@ profiler start -e cpu --jfrsync +jdk.YoungGarbageCollection+jdk.OldGarbageCollec
379379

380380
Use `--loop TIME` to run profiler in a loop (continuous profiling). The argument is either a clock time (hh:mm:ss) or a loop duration in seconds, minutes, hours, or days. Make sure the filename includes a timestamp pattern, or the output will be overwritten on each iteration. The command below will run profiling endlessly and save records of each hour to a jfr file.
381381

382+
> If the `-f` parameter is not specified, nothing will be saved. If the `-f` parameter does not contain `%t`, it will overwrite the same file repeatedly.
383+
382384
```bash
383385
profiler start --loop 1h -f /var/log/profile-%t.jfr
384386
```
385387

386388
## `--timeout` option
387389

390+
```bash
391+
profiler start --timeout 300s
392+
```
393+
388394
This option specifies the time when profiling will automatically stop. The format is the same as in loop: it is either a wall clock time (12:34:56) or a relative time interval (2h).
389395

390396
Both `--loop` and `--timeout` are used for `start` action, for further information refer to [async-profiler docs](https://github.com/async-profiler/async-profiler/blob/master/docs/ProfilerOptions.md).

0 commit comments

Comments
 (0)