package org.stagemonitor.web.monitor.rum;
import org.stagemonitor.core.Stagemonitor;
import org.stagemonitor.core.metrics.metrics2.Metric2Registry;
import org.stagemonitor.core.metrics.metrics2.MetricName;
import org.stagemonitor.web.WebPlugin;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import static java.util.concurrent.TimeUnit.MILLISECONDS;
import static org.stagemonitor.core.metrics.metrics2.MetricName.name;
/**
* The Real User Monitoring Servlet handles boomerang beacons (see http://www.lognormal.com/boomerang/doc/)
*/
public class RumServlet extends HttpServlet {
private final Metric2Registry metricRegistry;
private final WebPlugin webPlugin;
private final MetricName.MetricNameTemplate metricNameTemplate = name("response_time_rum").templateFor("request_name", "layer");
public RumServlet() {
this(Stagemonitor.getMetric2Registry(), Stagemonitor.getPlugin(WebPlugin.class));
}
public RumServlet(Metric2Registry metricRegistry, WebPlugin webPlugin) {
this.metricRegistry = metricRegistry;
this.webPlugin = webPlugin;
}
@Override
public void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
if (webPlugin.isRealUserMonitoringEnabled()) {
// Boomerang is requesting an image, so set appropriate header to not confuse browsers
resp.setContentType("image/png");
final String requestName = getRequiredParam(req, "requestName");
final long serverTime = Long.parseLong(getRequiredParam(req, "serverTime"));
final long timeToFirstByte = Long.parseLong(getRequiredParam(req, "timeToFirstByte"));
final long domProcessing = Long.parseLong(getRequiredParam(req, "domProcessing"));
final long pageRendering = Long.parseLong(getRequiredParam(req, "pageRendering"));
final long networkTime = timeToFirstByte - serverTime;
trackPageLoadTime("All", serverTime, domProcessing, pageRendering, networkTime);
if (webPlugin.isCollectPageLoadTimesPerRequest()) {
trackPageLoadTime(requestName, serverTime, domProcessing, pageRendering, networkTime);
}
} else {
resp.sendError(HttpServletResponse.SC_NOT_FOUND);
}
}
private void trackPageLoadTime(String requestName, long serverTime, long domProcessing, long pageRendering, long networkTime) {
metricRegistry.timer(metricNameTemplate.build(requestName, "Dom Processing")).update(domProcessing, MILLISECONDS);
metricRegistry.timer(metricNameTemplate.build(requestName, "Page Rendering")).update(pageRendering, MILLISECONDS);
metricRegistry.timer(metricNameTemplate.build(requestName, "Network")).update(networkTime, MILLISECONDS);
metricRegistry.timer(metricNameTemplate.build(requestName, "Server")).update(serverTime, MILLISECONDS);
metricRegistry.timer(metricNameTemplate.build(requestName, "All")).update(serverTime + networkTime + pageRendering + domProcessing, MILLISECONDS);
}
private String getRequiredParam(HttpServletRequest req, String parameterName) {
final String parameter = req.getParameter(parameterName);
if (parameter == null) {
throw new IllegalArgumentException("Parameter " + parameterName + " missing");
}
return parameter;
}
}