ca.jimr.gae.profiler.MiniProfilerServlet Maven / Gradle / Ivy
/**
* Copyright (C) 2011 by Jim Riecken
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package ca.jimr.gae.profiler;
import java.io.*;
import java.text.SimpleDateFormat;
import java.util.*;
import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
import javax.servlet.http.*;
import org.codehaus.jackson.JsonGenerationException;
import org.codehaus.jackson.map.JsonMappingException;
import org.codehaus.jackson.map.ObjectMapper;
import ca.jimr.gae.profiler.resources.MiniProfilerResourceLoader;
import com.google.appengine.api.memcache.MemcacheService;
import com.google.appengine.api.memcache.MemcacheServiceFactory;
import com.google.appengine.tools.appstats.MiniProfilerAppstats;
/**
* Servlet that:
*
* - Returns profile information for a set of requests (in JSON format).
*
- Serves the static resources that make up the profiler UI.
*
*/
public class MiniProfilerServlet extends HttpServlet
{
private static final long serialVersionUID = 7906645907029238585L;
private static final String MAX_STACK_FRAMES_KEY = "maxStackFrames";
private static final String HTML_ID_PREFIX_KEY = "htmlIdPrefix";
private static final String RESOURCE_CACHE_HOURS_KEY = "resourceCacheHours";
/**
* The maximum number of stack frames that should show up in Appstats RPC
* details. If this is null the whole stack trace will be shown.
*/
private Integer maxStackFrames;
/**
* The prefix for all HTML element ids/classes used in the profiler UI. This
* must be the same value as the {@code htmlIdPrefix} field in
* {@link MiniProfilerFilter}.
*/
private String htmlIdPrefix = "mp";
/**
* The number of hours that the static resources should be cached in the
* browser for.
*/
private int resourceCacheHours = 0;
/**
* The loader that will load the static resources for the profiler UI from
* files in the classpath.
*/
private MiniProfilerResourceLoader resourceLoader;
/** Map of string replacements that will be done on loaded resources. */
private Map resourceReplacements = new HashMap();
/** The Appengine Memcache Service */
private MemcacheService ms;
@Override
public void init(ServletConfig config) throws ServletException
{
String configMaxStackFrames = config.getInitParameter(MAX_STACK_FRAMES_KEY);
if (!isEmpty(configMaxStackFrames))
{
maxStackFrames = Integer.valueOf(configMaxStackFrames);
}
String configHtmlIdPrefix = config.getInitParameter(HTML_ID_PREFIX_KEY);
if (!isEmpty(configHtmlIdPrefix))
{
htmlIdPrefix = configHtmlIdPrefix.trim();
}
String configResourceCacheHours = config.getInitParameter(RESOURCE_CACHE_HOURS_KEY);
if (!isEmpty(configResourceCacheHours))
{
resourceCacheHours = Integer.parseInt(configResourceCacheHours);
}
ms = MemcacheServiceFactory.getMemcacheService(MiniProfilerFilter.MEMCACHE_NAMESPACE);
resourceLoader = new MiniProfilerResourceLoader();
resourceReplacements.put("@@prefix@@", htmlIdPrefix);
}
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException
{
String requestURI = req.getRequestURI();
if (requestURI.endsWith("results"))
{
doResults(req, resp);
} else if (requestURI.endsWith("resource"))
{
doResource(req, resp);
}
}
/**
* Serve one of the static resources for the profiler UI.
*/
private void doResource(HttpServletRequest req, HttpServletResponse resp) throws IOException
{
boolean success = true;
String resource = (String) req.getParameter("id");
if (!isEmpty(resource))
{
if (resource.endsWith(".js"))
{
resp.setContentType("text/javascript");
} else if (resource.endsWith(".css"))
{
resp.setContentType("text/css");
} else if (resource.endsWith(".html"))
{
resp.setContentType("text/html");
} else
{
resp.setContentType("text/plain");
}
String contents = resourceLoader.getResource(resource, resourceReplacements);
if (contents != null)
{
if (resourceCacheHours > 0)
{
Calendar c = Calendar.getInstance();
c.add(Calendar.HOUR, resourceCacheHours);
resp.setHeader("Cache-Control", "public, must-revalidate");
resp.setHeader("Expires", new SimpleDateFormat("EEE, dd MMM yyyy HH:mm:ss zzz").format(c.getTime()));
} else
{
resp.setHeader("Cache-Control", "no-cache");
}
PrintWriter w = resp.getWriter();
w.print(contents);
} else
{
success = false;
}
}
if (!success)
{
resp.sendError(404);
}
}
/**
* Generate the results for a set of requests in JSON format.
*/
private void doResults(HttpServletRequest req, HttpServletResponse resp) throws IOException, JsonGenerationException, JsonMappingException
{
Map result = new HashMap();
String requestIds = req.getParameter("ids");
if (!isEmpty(requestIds))
{
List
© 2015 - 2025 Weber Informatics LLC | Privacy Policy