in tez-common/src/main/java/org/apache/tez/common/web/ProfileServlet.java [159:301]
public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
response.setContentType("text/plain; charset=UTF-8");
PrintStream out = new PrintStream(response.getOutputStream(), false, "UTF-8");
if (!HttpServer2.isInstrumentationAccessAllowed(this.getServletContext(), request, response)) {
response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
setResponseHeader(response);
out.println("Unauthorized: Instrumentation access is not allowed!");
out.close();
return;
}
// make sure async profiler home is set
if (asyncProfilerHome == null || asyncProfilerHome.trim().isEmpty()) {
response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
setResponseHeader(response);
out.println("ASYNC_PROFILER_HOME env is not set");
out.close();
return;
}
// if pid is explicitly specified, use it else default to current process
pid = getInteger(request, "pid", pid);
// if pid is not specified in query param and if current process pid cannot be determined
if (pid == null) {
response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
setResponseHeader(response);
out.println("'pid' query parameter unspecified or unable to determine PID of current process.");
out.close();
return;
}
final int duration = getInteger(request, "duration", DEFAULT_DURATION_SECONDS);
final Output output = getOutput(request);
final Event event = getEvent(request);
final Long interval = getLong(request, "interval");
final Integer jstackDepth = getInteger(request, "jstackdepth", null);
final Long bufsize = getLong(request, "bufsize");
final boolean thread = request.getParameterMap().containsKey("thread");
final boolean simple = request.getParameterMap().containsKey("simple");
final Integer width = getInteger(request, "width", null);
final Integer height = getInteger(request, "height", null);
final Double minwidth = getMinWidth(request);
final boolean reverse = request.getParameterMap().containsKey("reverse");
final String method = request.getParameter("method");
if (request.getParameter("event") != null && method != null) {
response.setStatus(HttpServletResponse.SC_BAD_REQUEST);
setResponseHeader(response);
response.getWriter().write("Event and method aren't allowed to be both used in the same request.");
return;
}
if (process == null || !process.isAlive()) {
try {
int lockTimeoutSecs = 3;
if (profilerLock.tryLock(lockTimeoutSecs, TimeUnit.SECONDS)) {
try {
File outputFile = new File(OUTPUT_DIR,
"async-prof-pid-" + pid + "-"
+ (method == null ? event.name().toLowerCase() : method) + "-" + ID_GEN.incrementAndGet() + "."
+ output.name().toLowerCase());
List<String> cmd = new ArrayList<>();
cmd.add(getProfilerScriptPath());
cmd.add("-e");
cmd.add(method == null ? event.getInternalName() : method);
cmd.add("-d");
cmd.add("" + duration);
cmd.add("-o");
cmd.add(output.name().toLowerCase());
cmd.add("-f");
cmd.add(outputFile.getAbsolutePath());
if (interval != null) {
cmd.add("-i");
cmd.add(interval.toString());
}
if (jstackDepth != null) {
cmd.add("-j");
cmd.add(jstackDepth.toString());
}
if (bufsize != null) {
cmd.add("-b");
cmd.add(bufsize.toString());
}
if (thread) {
cmd.add("-t");
}
if (simple) {
cmd.add("-s");
}
if (width != null) {
cmd.add("--width");
cmd.add(width.toString());
}
if (height != null) {
cmd.add("--height");
cmd.add(height.toString());
}
if (minwidth != null) {
cmd.add("--minwidth");
cmd.add(minwidth.toString());
}
if (reverse) {
cmd.add("--reverse");
}
cmd.add(pid.toString());
process = new ProcessBuilder(cmd).start();
// set response and set refresh header to output location
setResponseHeader(response);
response.setStatus(HttpServletResponse.SC_ACCEPTED);
String relativeUrl = "/prof-output";
// to avoid auto-refresh by ProfileOutputServlet, refreshDelay can be specified via url param
int refreshDelay = getInteger(request, "refreshDelay", 0);
// instead of sending redirect, set auto-refresh so that browsers will refresh with redirected url
response.setHeader("Refresh", (duration + refreshDelay) + "; URL=" + relativeUrl + '?'
+ ProfileOutputServlet.FILE_QUERY_PARAM + '=' + outputFile.getName());
out.println("Profiled PID: " + pid);
out.println("Started [" + event.getInternalName()
+ "] profiling. This page will automatically redirect to "
+ relativeUrl + " after " + duration + " seconds.\n\ncommand:\n" + Joiner.on(" ").join(cmd));
out.flush();
} finally {
profilerLock.unlock();
}
} else {
setResponseHeader(response);
response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
out.println("Unable to acquire lock. Another instance of profiler might be running.");
LOG.warn("Unable to acquire lock in {} seconds. Another instance of profiler might be running.",
lockTimeoutSecs);
}
} catch (InterruptedException e) {
LOG.warn("Interrupted while acquiring profile lock.", e);
response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
}
} else {
setResponseHeader(response);
response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
out.println("Another instance of profiler is already running.");
}
out.close();
}