package org.stagemonitor.web.metrics; import static org.stagemonitor.core.metrics.metrics2.MetricName.name; import java.io.IOException; import java.io.OutputStream; import java.util.ArrayList; import java.util.List; import java.util.concurrent.TimeUnit; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.ObjectWriter; import com.fasterxml.jackson.databind.util.JSONPObject; import org.stagemonitor.core.Stagemonitor; import org.stagemonitor.core.metrics.MetricNameFilter; import org.stagemonitor.core.metrics.metrics2.Metric2Filter; import org.stagemonitor.core.metrics.metrics2.Metric2Registry; import org.stagemonitor.core.metrics.metrics2.Metric2RegistryModule; import org.stagemonitor.core.metrics.metrics2.MetricName; import org.stagemonitor.core.util.JsonUtils; import org.stagemonitor.web.WebPlugin; /** * A servlet which returns the metrics in a given registry as an {@code application/json} response. * Derived from com.codahale.metrics.servlets.MetricsServlet * (https://github.com/dropwizard/metrics/blob/master/metrics-servlets/src/main/java/com/codahale/metrics/servlets/MetricsServlet.java) */ public class StagemonitorMetricsServlet extends HttpServlet { private final transient Metric2Registry registry; private final transient WebPlugin webPlugin; private final transient ObjectMapper mapper; public StagemonitorMetricsServlet() { this(Stagemonitor.getMetric2Registry(), Stagemonitor.getPlugin(WebPlugin.class), JsonUtils.getMapper()); } public StagemonitorMetricsServlet(Metric2Registry registry, WebPlugin webPlugin, ObjectMapper mapper) { this.registry = registry; this.webPlugin = webPlugin; this.mapper = mapper; } @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { resp.setContentType("application/json"); if (webPlugin.getMetricsServletAllowedOrigin() != null) { resp.setHeader("Access-Control-Allow-Origin", webPlugin.getMetricsServletAllowedOrigin()); } resp.setHeader("Cache-Control", "must-revalidate,no-cache,no-store"); resp.setStatus(HttpServletResponse.SC_OK); final OutputStream output = resp.getOutputStream(); try { String jsonpParamName = webPlugin.getMetricsServletJsonpParamName(); if (jsonpParamName != null && req.getParameter(jsonpParamName) != null) { getWriter(req).writeValue(output, new JSONPObject(req.getParameter(jsonpParamName), registry)); } else { getWriter(req).writeValue(output, registry); } } finally { output.close(); } } private ObjectWriter getWriter(HttpServletRequest request) { ObjectMapper objectMapperCopy = mapper.copy(); registerMetricsRegistryModule(request, objectMapperCopy); if (Boolean.parseBoolean(request.getParameter("pretty"))) { return objectMapperCopy.writerWithDefaultPrettyPrinter(); } return objectMapperCopy.writer(); } private void registerMetricsRegistryModule(HttpServletRequest request, ObjectMapper objectMapperCopy) { Metric2Filter metricFilter = Metric2Filter.ALL; final String[] metricNames = request.getParameterValues("metricNames[]"); if (metricNames != null && metricNames.length > 0) { List<MetricName> metricNameList = new ArrayList<MetricName>(metricNames.length); for (String metricName : metricNames) { metricNameList.add(name(metricName).build()); } metricFilter = new MetricNameFilter(metricNameList); } objectMapperCopy.registerModule(new Metric2RegistryModule(TimeUnit.SECONDS, TimeUnit.MILLISECONDS, metricFilter)); } }