Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

TEZ-4568: ProfileServlet: add html to output formats and prepare for profiler 3.0 #360

Merged
merged 1 commit into from
Jun 6, 2024
Merged
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
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,9 @@
import java.io.File;
import java.io.IOException;
import java.io.PrintStream;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.TimeUnit;
Expand All @@ -50,19 +53,19 @@
* // -m method fully qualified method name: 'ClassName.methodName'
* // -t profile different threads separately
* // -s simple class names instead of FQN
* // -o fmt[,fmt...] output format: summary|traces|flat|collapsed|svg|tree|jfr
* // -o fmt[,fmt...] output format: summary|traces|flat|collapsed|svg|tree|jfr|html
* // --width px SVG width pixels (integer)
* // --height px SVG frame height pixels (integer)
* // --minwidth px skip frames smaller than px (double)
* // --reverse generate stack-reversed FlameGraph / Call tree
* Example:
* - To collect 30 second CPU profile of current process (returns FlameGraph svg)
* - To collect 10 second CPU profile of current process (returns FlameGraph html)
* {@literal curl "http://localhost:10002/prof"}
* - To collect 1 minute CPU profile of current process and output in tree format (html)
* {@literal curl "http://localhost:10002/prof?output=tree&duration=60"}
* - To collect 30 second heap allocation profile of current process (returns FlameGraph svg)
* - To collect 10 second heap allocation profile of current process (returns FlameGraph html)
* {@literal curl "http://localhost:10002/prof?event=alloc"}
* - To collect lock contention profile of current process (returns FlameGraph svg)
* - To collect lock contention profile of current process (returns FlameGraph html)
* {@literal curl "http://localhost:10002/prof?event=lock"}
* Following event types are supported (default is 'cpu') (NOTE: not all OS'es support all events)
* // Perf events:
Expand Down Expand Up @@ -95,7 +98,6 @@ public class ProfileServlet extends HttpServlet {
private static final String CONTENT_TYPE_TEXT = "text/plain; charset=utf-8";
private static final String ASYNC_PROFILER_HOME_ENV = "ASYNC_PROFILER_HOME";
private static final String ASYNC_PROFILER_HOME_SYSTEM_PROPERTY = "async.profiler.home";
private static final String PROFILER_SCRIPT = "/profiler.sh";
private static final int DEFAULT_DURATION_SECONDS = 10;
private static final AtomicInteger ID_GEN = new AtomicInteger(0);
public static final String OUTPUT_DIR = System.getProperty("java.io.tmpdir") + "/prof-output";
Expand Down Expand Up @@ -140,7 +142,7 @@ public static Event fromInternalName(final String name) {
}

enum Output {
SUMMARY, TRACES, FLAT, COLLAPSED, SVG, TREE, JFR
SUMMARY, TRACES, FLAT, COLLAPSED, SVG, TREE, JFR, HTML
}

private final Lock profilerLock = new ReentrantLock();
Expand Down Expand Up @@ -216,7 +218,7 @@ public void doGet(HttpServletRequest request, HttpServletResponse response) thro
+ (method == null ? event.name().toLowerCase() : method) + "-" + ID_GEN.incrementAndGet() + "."
+ output.name().toLowerCase());
List<String> cmd = new ArrayList<>();
cmd.add(asyncProfilerHome + PROFILER_SCRIPT);
cmd.add(getProfilerScriptPath());
cmd.add("-e");
cmd.add(method == null ? event.getInternalName() : method);
cmd.add("-d");
Expand Down Expand Up @@ -298,6 +300,16 @@ public void doGet(HttpServletRequest request, HttpServletResponse response) thro
out.close();
}

/**
* Get the path of the profiler script to be executed.
* Before async-profiler 3.0, the script was named profiler.sh, and after 3.0 it's bin/asprof
* @return
*/
private String getProfilerScriptPath() {
Path defaultPath = Paths.get(asyncProfilerHome + "/bin/asprof");
return Files.exists(defaultPath)? defaultPath.toString() : asyncProfilerHome + "/profiler.sh";
}

private Integer getInteger(final HttpServletRequest req, final String param, final Integer defaultValue) {
final String value = req.getParameter(param);
if (value != null) {
Expand Down Expand Up @@ -349,11 +361,11 @@ private Output getOutput(final HttpServletRequest req) {
try {
return Output.valueOf(outputArg.trim().toUpperCase());
} catch (IllegalArgumentException e) {
LOG.warn("Output format value is invalid, returning with default SVG");
return Output.SVG;
LOG.warn("Output format value is invalid, returning with default HTML");
return Output.HTML;
}
}
return Output.SVG;
return Output.HTML;
}

private void setResponseHeader(final HttpServletResponse response) {
Expand Down
Loading