ProfilerPlugin.java 8.24 KB
/*
 * Decompiled with CFR 0_118.
 * 
 * Could not load the following classes:
 *  javax.servlet.Servlet
 *  javax.servlet.ServletException
 *  javax.servlet.http.HttpServletRequest
 *  javax.servlet.http.HttpServletResponse
 *  org.apache.felix.scr.annotations.Component
 *  org.apache.felix.scr.annotations.Property
 *  org.apache.felix.scr.annotations.Service
 *  org.apache.felix.webconsole.AbstractWebConsolePlugin
 *  org.apache.felix.webconsole.WebConsoleUtil
 */
package com.adobe.granite.webconsole.plugins.impl;

import com.adobe.granite.webconsole.plugins.impl.Profiler;
import java.io.IOException;
import java.io.PrintWriter;
import java.net.URL;
import javax.servlet.Servlet;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.felix.scr.annotations.Component;
import org.apache.felix.scr.annotations.Property;
import org.apache.felix.scr.annotations.Service;
import org.apache.felix.webconsole.AbstractWebConsolePlugin;
import org.apache.felix.webconsole.WebConsoleUtil;

@Component
@Service(value={Servlet.class})
public class ProfilerPlugin
extends AbstractWebConsolePlugin {
    @Property(name="felix.webconsole.label")
    private static final String LABEL = "profiler";
    @Property(name="felix.webconsole.title")
    private static final String TITLE = "Profiler";
    private static final String RESOURCE_PREFIX = "/profiler/";
    private static volatile Profiler prof;

    public String getLabel() {
        return "profiler";
    }

    public String getTitle() {
        return "Profiler";
    }

    protected void doPost(HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException {
        this.doGet(req, res);
    }

    protected void renderContent(HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException {
        PrintWriter pw = res.getWriter();
        pw.println("<p class=\"intro\">Collects statistics about thread dumps similar to <code>java -agentlib:hprof</code>. Stack traces from runnable threads are then listed sorted by count.</p>");
        String action = req.getParameter("action");
        if ("start".equals(action) && "POST".equals(req.getMethod())) {
            this.start(req, res);
        } else if (action == null || "stop".equals(action)) {
            this.stop(req, res);
        }
    }

    private void start(HttpServletRequest req, HttpServletResponse res) throws IOException {
        String ignoreList = req.getParameter("ignoreList");
        String ignoreThreadList = req.getParameter("ignoreThreadList");
        String ignorePackageList = req.getParameter("ignorePackageList");
        prof = new Profiler();
        ProfilerPlugin.prof.interval = Integer.parseInt(req.getParameter("interval"));
        ProfilerPlugin.prof.depth = Integer.parseInt(req.getParameter("depth"));
        ProfilerPlugin.prof.ignoreThreads = Profiler.arraySplit(ignoreList, ',', true);
        ProfilerPlugin.prof.ignoreThreads = Profiler.arraySplit(ignoreThreadList, ',', true);
        ProfilerPlugin.prof.ignorePackages = Profiler.arraySplit(ignorePackageList, ',', true);
        PrintWriter pw = res.getWriter();
        pw.println("<form method=\"post\">");
        pw.println("<input type=\"hidden\" name=\"action\" value=\"stop\">");
        pw.println("<input type=\"submit\" value=\"Stop\">");
        pw.println("</form>");
        pw.println("<div>");
        pw.println("Sample interval (milliseconds): " + ProfilerPlugin.prof.interval);
        pw.println("<br>Stack trace depth: " + ProfilerPlugin.prof.depth);
        pw.println("<br>Collecting...</div>");
        prof.startCollecting();
        pw.flush();
        long oldTick = ProfilerPlugin.prof.total;
        while (prof != null) {
            try {
                long newTick = ProfilerPlugin.prof.total;
                if (newTick != oldTick) {
                    pw.println('.');
                    pw.flush();
                    oldTick = newTick;
                }
                Thread.sleep(1000);
            }
            catch (Exception e) {
                pw.println(e.getLocalizedMessage());
            }
        }
    }

    private void stop(HttpServletRequest req, HttpServletResponse res) throws IOException {
        PrintWriter pw = res.getWriter();
        pw.println("<form method=\"post\">");
        pw.println("<input class=\"options\" type=\"button\" value=\"Options >\">");
        pw.println("<fieldset id=\"options\">");
        pw.println("<div><label>Sample interval (ms): <input type=\"number\" name=\"interval\" value=\"5\"></label>");
        pw.println("<p class=\"desc\">To increase accuracy, use 1000 or higher when running for many hours.</p></div>");
        pw.println("<div><label>Stack trace depth: <input type=\"number\" name=\"depth\" value=\"160\"></label>");
        pw.println("<p class=\"desc\">The number of stack trace lines to analyze.</p></div>");
        pw.println("<div><label>Ignore threads:");
        pw.println("<textarea cols=50 rows=4 name=\"ignoreThreadList\">");
        pw.println("java.lang.Object.wait,");
        pw.println("java.lang.Thread.dumpThreads,");
        pw.println("java.lang.Thread.getThreads,");
        pw.println("java.lang.Thread.sleep,");
        pw.println("java.lang.UNIXProcess.waitForProcessExit,");
        pw.println("java.net.PlainSocketImpl.accept,");
        pw.println("java.net.PlainSocketImpl.socketAccept,");
        pw.println("java.net.SocketInputStream.socketRead,");
        pw.println("java.net.SocketOutputStream.socketWrite,");
        pw.println("sun.awt.windows.WToolkit.eventLoop,");
        pw.println("sun.misc.Unsafe.park,");
        pw.println("EDU.oswego,");
        pw.println("java.lang.Object.$$YJP$$wait,");
        pw.println("java.lang.Thread.$$YJP$$sleep,");
        pw.println("sun.misc.Unsafe.$$YJP$$park,");
        pw.println("java.net.PlainSocketImpl.$$YJP$$socketAccept,");
        pw.println("java.net.SocketInputStream.$$YJP$$socketRead,");
        pw.println("java.net.PlainSocketImpl.$$YJP$$accept,");
        pw.println("java.lang.Thread.$$YJP$$dumpThreads,");
        pw.println("</textarea></label>");
        pw.println("<p class=\"desc\">Threads where the first line start with one of these prefixes are ignored.</p></div>");
        pw.println("<div><label>Ignore lines:");
        pw.println("<textarea cols=50 rows=2 name=\"ignoreList\">");
        pw.println("org.apache.commons,");
        pw.println("org.apache.tika.parser.txt.Charset,");
        pw.println("EDU.oswego,");
        pw.println("</textarea></label>");
        pw.println("<p class=\"desc\">Lines that start one of these prefixes are not included in a stack trace.</p></div>");
        pw.println("<div><label>Ignore packages:");
        pw.println("<textarea cols=50 rows=2 name=\"ignorePackageList\">");
        pw.println("java,");
        pw.println("sun,");
        pw.println("com.sun.,");
        pw.println("EDU,");
        pw.println("org.apache.jsp.,");
        pw.println("org.apache.commons.,");
        pw.println("org.eclipse.jdt,");
        pw.println("org.json.,");
        pw.println("org.kxml2.,");
        pw.println("com.apple.,");
        pw.println("</textarea></label>");
        pw.println("<p class=\"desc\">These packages are ignored in the package summary.</p></div>");
        pw.println("</fieldset>");
        pw.println("<input type=\"hidden\" name=\"action\" value=\"start\">");
        pw.println("<input type=\"submit\" value=\"Start Collecting\">");
        pw.println("</form>");
        Profiler old = prof;
        prof = null;
        if (old != null) {
            pw.println("<pre>");
            pw.println(WebConsoleUtil.escapeHtml((String)old.getTop(20)));
            pw.println("</pre>");
            pw.flush();
        }
        pw.println("<script>");
        pw.println("$(function() {");
        pw.println("$(\"input.options\").click(function() {");
        pw.println("$(\"#options\").toggle();");
        pw.println("});");
        pw.println("});");
        pw.println("</script>");
    }

    protected String[] getCssReferences() {
        return new String[]{"/profiler/res/profiler.css"};
    }

    private URL getResource(String path) {
        return path != null && path.startsWith("/profiler/") ? this.getClass().getResource(path.substring("/profiler/".length() - 1)) : null;
    }
}