Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add per-path configurability #1891

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package com.codahale.metrics.servlets;

import javax.servlet.ServletConfig;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
Expand All @@ -16,14 +17,19 @@ public class AdminServlet extends HttpServlet {
public static final String DEFAULT_THREADS_URI = "/threads";
public static final String DEFAULT_CPU_PROFILE_URI = "/pprof";

public static final String METRICS_ENABLED_PARAM_KEY = "metrics-enabled";
public static final String METRICS_URI_PARAM_KEY = "metrics-uri";
public static final String PING_ENABLED_PARAM_KEY = "ping-enabled";
public static final String PING_URI_PARAM_KEY = "ping-uri";
public static final String THREADS_ENABLED_PARAM_KEY = "threads-enabled";
public static final String THREADS_URI_PARAM_KEY = "threads-uri";
public static final String HEALTHCHECK_ENABLED_PARAM_KEY = "healthcheck-enabled";
public static final String HEALTHCHECK_URI_PARAM_KEY = "healthcheck-uri";
public static final String SERVICE_NAME_PARAM_KEY = "service-name";
public static final String CPU_PROFILE_ENABLED_PARAM_KEY = "cpu-profile-enabled";
public static final String CPU_PROFILE_URI_PARAM_KEY = "cpu-profile-uri";

private static final String TEMPLATE = String.format(
private static final String BASE_TEMPLATE =
"<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\"%n" +
" \"http://www.w3.org/TR/html4/loose.dtd\">%n" +
"<html>%n" +
Expand All @@ -33,16 +39,18 @@ public class AdminServlet extends HttpServlet {
"<body>%n" +
" <h1>Operational Menu{10}</h1>%n" +
" <ul>%n" +
" <li><a href=\"{0}{1}?pretty=true\">Metrics</a></li>%n" +
" <li><a href=\"{2}{3}\">Ping</a></li>%n" +
" <li><a href=\"{4}{5}\">Threads</a></li>%n" +
" <li><a href=\"{6}{7}?pretty=true\">Healthcheck</a></li>%n" +
" <li><a href=\"{8}{9}\">CPU Profile</a></li>%n" +
" <li><a href=\"{8}{9}?state=blocked\">CPU Contention</a></li>%n" +
"%s" +
" </ul>%n" +
"</body>%n" +
"</html>"
);
"</html>";
private static final String METRICS_LINK = " <li><a href=\"{0}{1}?pretty=true\">Metrics</a></li>%n";
private static final String PING_LINK = " <li><a href=\"{2}{3}\">Ping</a></li>%n" ;
private static final String THREADS_LINK = " <li><a href=\"{4}{5}\">Threads</a></li>%n" ;
private static final String HEALTHCHECK_LINK = " <li><a href=\"{6}{7}?pretty=true\">Healthcheck</a></li>%n" ;
private static final String CPU_PROFILE_LINK = " <li><a href=\"{8}{9}\">CPU Profile</a></li>%n" +
" <li><a href=\"{8}{9}?state=blocked\">CPU Contention</a></li>%n";


private static final String CONTENT_TYPE = "text/html";
private static final long serialVersionUID = -2850794040708785318L;

Expand All @@ -51,38 +59,74 @@ public class AdminServlet extends HttpServlet {
private transient PingServlet pingServlet;
private transient ThreadDumpServlet threadDumpServlet;
private transient CpuProfileServlet cpuProfileServlet;
private transient boolean metricsEnabled;
private transient String metricsUri;
private transient boolean pingEnabled;
private transient String pingUri;
private transient boolean threadsEnabled;
private transient String threadsUri;
private transient boolean healthcheckEnabled;
private transient String healthcheckUri;
private transient String cpuprofileUri;
private transient boolean cpuProfileEnabled;
private transient String cpuProfileUri;
private transient String serviceName;
private transient String pageContentTemplate;

@Override
public void init(ServletConfig config) throws ServletException {
super.init(config);

this.healthCheckServlet = new HealthCheckServlet();
healthCheckServlet.init(config);
final ServletContext context = config.getServletContext();
final StringBuilder servletLinks = new StringBuilder();

this.metricsEnabled =
Boolean.parseBoolean(getParam(context.getInitParameter(METRICS_ENABLED_PARAM_KEY), "true"));
if (this.metricsEnabled) {
servletLinks.append(METRICS_LINK);
}
this.metricsServlet = new MetricsServlet();
metricsServlet.init(config);

this.pingEnabled =
Boolean.parseBoolean(getParam(context.getInitParameter(PING_ENABLED_PARAM_KEY), "true"));
if (this.pingEnabled) {
servletLinks.append(PING_LINK);
}
this.pingServlet = new PingServlet();
pingServlet.init(config);

this.threadsEnabled =
Boolean.parseBoolean(getParam(context.getInitParameter(THREADS_ENABLED_PARAM_KEY), "true"));
if (this.threadsEnabled) {
servletLinks.append(THREADS_LINK);
}
this.threadDumpServlet = new ThreadDumpServlet();
threadDumpServlet.init(config);

this.healthcheckEnabled =
Boolean.parseBoolean(getParam(context.getInitParameter(HEALTHCHECK_ENABLED_PARAM_KEY), "true"));
if (this.healthcheckEnabled) {
servletLinks.append(HEALTHCHECK_LINK);
}
this.healthCheckServlet = new HealthCheckServlet();
healthCheckServlet.init(config);

this.cpuProfileEnabled =
Boolean.parseBoolean(getParam(context.getInitParameter(CPU_PROFILE_ENABLED_PARAM_KEY), "true"));
if (this.cpuProfileEnabled) {
servletLinks.append(CPU_PROFILE_LINK);
}
this.cpuProfileServlet = new CpuProfileServlet();
cpuProfileServlet.init(config);

this.metricsUri = getParam(config.getInitParameter(METRICS_URI_PARAM_KEY), DEFAULT_METRICS_URI);
this.pingUri = getParam(config.getInitParameter(PING_URI_PARAM_KEY), DEFAULT_PING_URI);
this.threadsUri = getParam(config.getInitParameter(THREADS_URI_PARAM_KEY), DEFAULT_THREADS_URI);
this.healthcheckUri = getParam(config.getInitParameter(HEALTHCHECK_URI_PARAM_KEY), DEFAULT_HEALTHCHECK_URI);
this.cpuprofileUri = getParam(config.getInitParameter(CPU_PROFILE_URI_PARAM_KEY), DEFAULT_CPU_PROFILE_URI);
this.serviceName = getParam(config.getInitParameter(SERVICE_NAME_PARAM_KEY), null);
pageContentTemplate = String.format(BASE_TEMPLATE, String.format(servletLinks.toString()));

this.metricsUri = getParam(context.getInitParameter(METRICS_URI_PARAM_KEY), DEFAULT_METRICS_URI);
this.pingUri = getParam(context.getInitParameter(PING_URI_PARAM_KEY), DEFAULT_PING_URI);
this.threadsUri = getParam(context.getInitParameter(THREADS_URI_PARAM_KEY), DEFAULT_THREADS_URI);
this.healthcheckUri = getParam(context.getInitParameter(HEALTHCHECK_URI_PARAM_KEY), DEFAULT_HEALTHCHECK_URI);
this.cpuProfileUri = getParam(context.getInitParameter(CPU_PROFILE_URI_PARAM_KEY), DEFAULT_CPU_PROFILE_URI);
this.serviceName = getParam(context.getInitParameter(SERVICE_NAME_PARAM_KEY), null);
}

@Override
Expand All @@ -93,8 +137,8 @@ protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws Se
resp.setHeader("Cache-Control", "must-revalidate,no-cache,no-store");
resp.setContentType(CONTENT_TYPE);
try (PrintWriter writer = resp.getWriter()) {
writer.println(MessageFormat.format(TEMPLATE, path, metricsUri, path, pingUri, path,
threadsUri, path, healthcheckUri, path, cpuprofileUri,
writer.println(MessageFormat.format(pageContentTemplate, path, metricsUri, path, pingUri, path,
threadsUri, path, healthcheckUri, path, cpuProfileUri,
serviceName == null ? "" : " (" + serviceName + ")"));
}
}
Expand All @@ -105,15 +149,35 @@ protected void service(HttpServletRequest req, HttpServletResponse resp) throws
if (uri == null || uri.equals("/")) {
super.service(req, resp);
} else if (uri.equals(healthcheckUri)) {
healthCheckServlet.service(req, resp);
if (healthcheckEnabled) {
healthCheckServlet.service(req, resp);
} else {
resp.sendError(HttpServletResponse.SC_NOT_FOUND);
}
} else if (uri.startsWith(metricsUri)) {
metricsServlet.service(req, resp);
if (metricsEnabled) {
metricsServlet.service(req, resp);
} else {
resp.sendError(HttpServletResponse.SC_NOT_FOUND);
}
} else if (uri.equals(pingUri)) {
pingServlet.service(req, resp);
if (pingEnabled) {
pingServlet.service(req, resp);
} else {
resp.sendError(HttpServletResponse.SC_NOT_FOUND);
}
} else if (uri.equals(threadsUri)) {
threadDumpServlet.service(req, resp);
} else if (uri.equals(cpuprofileUri)) {
cpuProfileServlet.service(req, resp);
if (threadsEnabled) {
threadDumpServlet.service(req, resp);
} else {
resp.sendError(HttpServletResponse.SC_NOT_FOUND);
}
} else if (uri.equals(cpuProfileUri)) {
if (cpuProfileEnabled) {
cpuProfileServlet.service(req, resp);
} else {
resp.sendError(HttpServletResponse.SC_NOT_FOUND);
}
} else {
resp.sendError(HttpServletResponse.SC_NOT_FOUND);
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
package com.codahale.metrics.servlets;

import com.codahale.metrics.MetricRegistry;
import com.codahale.metrics.health.HealthCheckRegistry;
import static org.assertj.core.api.Assertions.assertThat;
import org.eclipse.jetty.http.HttpHeader;
import org.eclipse.jetty.servlet.ServletTester;
import org.junit.Before;
import org.junit.Test;

public class AdminServletExclusionTest extends AbstractServletTest {
private final MetricRegistry registry = new MetricRegistry();
private final HealthCheckRegistry healthCheckRegistry = new HealthCheckRegistry();

@Override
protected void setUp(ServletTester tester) {
tester.setContextPath("/context");

tester.setAttribute("com.codahale.metrics.servlets.MetricsServlet.registry", registry);
tester.setAttribute("com.codahale.metrics.servlets.HealthCheckServlet.registry", healthCheckRegistry);
tester.setInitParameter("threads-enabled", "false");
tester.setInitParameter("cpu-profile-enabled", "false");
tester.addServlet(AdminServlet.class, "/admin");
}

@Before
public void setUp() {
request.setMethod("GET");
request.setURI("/context/admin");
request.setVersion("HTTP/1.0");
}

@Test
public void returnsA200() throws Exception {
processRequest();

assertThat(response.getStatus())
.isEqualTo(200);
assertThat(response.getContent())
.isEqualTo(String.format(
"<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\"%n" +
" \"http://www.w3.org/TR/html4/loose.dtd\">%n" +
"<html>%n" +
"<head>%n" +
" <title>Metrics</title>%n" +
"</head>%n" +
"<body>%n" +
" <h1>Operational Menu</h1>%n" +
" <ul>%n" +
" <li><a href=\"/context/admin/metrics?pretty=true\">Metrics</a></li>%n" +
" <li><a href=\"/context/admin/ping\">Ping</a></li>%n" +
" <li><a href=\"/context/admin/healthcheck?pretty=true\">Healthcheck</a></li>%n" +
" </ul>%n" +
"</body>%n" +
"</html>%n"
));
assertThat(response.get(HttpHeader.CONTENT_TYPE))
.isEqualTo("text/html;charset=UTF-8");
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
package com.codahale.metrics.servlets;

import com.codahale.metrics.MetricRegistry;
import com.codahale.metrics.health.HealthCheckRegistry;
import static org.assertj.core.api.Assertions.assertThat;
import org.eclipse.jetty.http.HttpHeader;
import org.eclipse.jetty.servlet.ServletTester;
import org.junit.Before;
import org.junit.Test;

public class AdminServletUriTest extends AbstractServletTest {
private final MetricRegistry registry = new MetricRegistry();
private final HealthCheckRegistry healthCheckRegistry = new HealthCheckRegistry();

@Override
protected void setUp(ServletTester tester) {
tester.setContextPath("/context");

tester.setAttribute("com.codahale.metrics.servlets.MetricsServlet.registry", registry);
tester.setAttribute("com.codahale.metrics.servlets.HealthCheckServlet.registry", healthCheckRegistry);
tester.setInitParameter("metrics-uri", "/metrics-test");
tester.setInitParameter("ping-uri", "/ping-test");
tester.setInitParameter("threads-uri", "/threads-test");
tester.setInitParameter("healthcheck-uri", "/healthcheck-test");
tester.setInitParameter("cpu-profile-uri", "/pprof-test");
tester.addServlet(AdminServlet.class, "/admin");
}

@Before
public void setUp() {
request.setMethod("GET");
request.setURI("/context/admin");
request.setVersion("HTTP/1.0");
}

@Test
public void returnsA200() throws Exception {
processRequest();

assertThat(response.getStatus())
.isEqualTo(200);
assertThat(response.getContent())
.isEqualTo(String.format(
"<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\"%n" +
" \"http://www.w3.org/TR/html4/loose.dtd\">%n" +
"<html>%n" +
"<head>%n" +
" <title>Metrics</title>%n" +
"</head>%n" +
"<body>%n" +
" <h1>Operational Menu</h1>%n" +
" <ul>%n" +
" <li><a href=\"/context/admin/metrics-test?pretty=true\">Metrics</a></li>%n" +
" <li><a href=\"/context/admin/ping-test\">Ping</a></li>%n" +
" <li><a href=\"/context/admin/threads-test\">Threads</a></li>%n" +
" <li><a href=\"/context/admin/healthcheck-test?pretty=true\">Healthcheck</a></li>%n" +
" <li><a href=\"/context/admin/pprof-test\">CPU Profile</a></li>%n" +
" <li><a href=\"/context/admin/pprof-test?state=blocked\">CPU Contention</a></li>%n" +
" </ul>%n" +
"</body>%n" +
"</html>%n"
));
assertThat(response.get(HttpHeader.CONTENT_TYPE))
.isEqualTo("text/html;charset=UTF-8");
}
}