diff --git a/simpleclient_servlet/pom.xml b/simpleclient_servlet/pom.xml index a6423e25e..f05393825 100644 --- a/simpleclient_servlet/pom.xml +++ b/simpleclient_servlet/pom.xml @@ -80,4 +80,59 @@ test + + + + updateSource + + + + maven-resources-plugin + 3.2.0 + + + copy-resources + generate-sources + + copy-resources + + + ${basedir}/../simpleclient_servlet_jakarta/src + + + src + + + true + + + + + + maven-antrun-plugin + 1.7 + + + generate-sources + + + + + + + + + run + + + + + + + + diff --git a/simpleclient_servlet/src/test/java/io/prometheus/client/exporter/ExampleBenchmark.java b/simpleclient_servlet/src/test/java/io/prometheus/client/exporter/ExampleBenchmark.java index 066da1499..0196f34aa 100644 --- a/simpleclient_servlet/src/test/java/io/prometheus/client/exporter/ExampleBenchmark.java +++ b/simpleclient_servlet/src/test/java/io/prometheus/client/exporter/ExampleBenchmark.java @@ -1,6 +1,8 @@ package io.prometheus.client.exporter; import io.prometheus.client.Gauge; + +import org.eclipse.jetty.server.Connector; import org.eclipse.jetty.server.Server; import org.eclipse.jetty.servlet.ServletContextHandler; import org.eclipse.jetty.servlet.ServletHolder; @@ -28,8 +30,9 @@ public static void main(String[] args) throws Exception { server.start(); Thread.sleep(1000); + Connector connector = (Connector) server.getConnectors()[0]; byte[] bytes = new byte[8192]; - URL url = new URL("http", "localhost", server.getConnectors()[0].getLocalPort(), "/metrics"); + URL url = new URL("http", "localhost", connector.getLocalPort(), "/metrics"); long start = System.nanoTime(); for (int i = 0; i < 100; i++) { diff --git a/simpleclient_servlet/src/test/java/io/prometheus/client/filter/MetricsFilterTest.java b/simpleclient_servlet/src/test/java/io/prometheus/client/filter/MetricsFilterTest.java index 622756b6b..55267f0e2 100644 --- a/simpleclient_servlet/src/test/java/io/prometheus/client/filter/MetricsFilterTest.java +++ b/simpleclient_servlet/src/test/java/io/prometheus/client/filter/MetricsFilterTest.java @@ -2,7 +2,6 @@ import io.prometheus.client.Collector; import io.prometheus.client.CollectorRegistry; -import org.eclipse.jetty.http.HttpMethods; import org.junit.After; import org.junit.Test; import org.mockito.invocation.InvocationOnMock; @@ -25,6 +24,10 @@ import static org.mockito.Mockito.when; public class MetricsFilterTest { + + public static final String GET = "GET"; + public static final String POST = "POST"; + MetricsFilter f = new MetricsFilter(); @After @@ -49,7 +52,7 @@ public void init() throws Exception { HttpServletRequest req = mock(HttpServletRequest.class); when(req.getRequestURI()).thenReturn("/foo/bar/baz/bang/zilch/zip/nada"); - when(req.getMethod()).thenReturn(HttpMethods.GET); + when(req.getMethod()).thenReturn(GET); HttpServletResponse res = mock(HttpServletResponse.class); FilterChain c = mock(FilterChain.class); @@ -58,7 +61,7 @@ public void init() throws Exception { verify(c).doFilter(req, res); - final Double sampleValue = CollectorRegistry.defaultRegistry.getSampleValue(metricName + "_count", new String[]{"path", "method"}, new String[]{"/foo/bar/baz/bang", HttpMethods.GET}); + final Double sampleValue = CollectorRegistry.defaultRegistry.getSampleValue(metricName + "_count", new String[]{"path", "method"}, new String[]{"/foo/bar/baz/bang", GET}); assertNotNull(sampleValue); assertEquals(1, sampleValue, 0.0001); } @@ -69,7 +72,7 @@ public void doFilter() throws Exception { final String path = "/foo/bar/baz/bang/zilch/zip/nada"; when(req.getRequestURI()).thenReturn(path); - when(req.getMethod()).thenReturn(HttpMethods.GET); + when(req.getMethod()).thenReturn(GET); HttpServletResponse res = mock(HttpServletResponse.class); FilterChain c = mock(FilterChain.class); @@ -85,7 +88,7 @@ public void doFilter() throws Exception { verify(c).doFilter(req, res); - final Double sampleValue = CollectorRegistry.defaultRegistry.getSampleValue(name + "_count", new String[]{"path", "method"}, new String[]{path, HttpMethods.GET}); + final Double sampleValue = CollectorRegistry.defaultRegistry.getSampleValue(name + "_count", new String[]{"path", "method"}, new String[]{path, GET}); assertNotNull(sampleValue); assertEquals(1, sampleValue, 0.0001); } @@ -95,7 +98,7 @@ public void testConstructor() throws Exception { HttpServletRequest req = mock(HttpServletRequest.class); final String path = "/foo/bar/baz/bang"; when(req.getRequestURI()).thenReturn(path); - when(req.getMethod()).thenReturn(HttpMethods.POST); + when(req.getMethod()).thenReturn(POST); FilterChain c = mock(FilterChain.class); doAnswer(new Answer() { @@ -117,7 +120,7 @@ public Void answer(InvocationOnMock invocationOnMock) throws Throwable { HttpServletResponse res = mock(HttpServletResponse.class); constructed.doFilter(req, res, c); - final Double sum = CollectorRegistry.defaultRegistry.getSampleValue("foobar_baz_filter_duration_seconds_sum", new String[]{"path", "method"}, new String[]{path, HttpMethods.POST}); + final Double sum = CollectorRegistry.defaultRegistry.getSampleValue("foobar_baz_filter_duration_seconds_sum", new String[]{"path", "method"}, new String[]{path, POST}); assertNotNull(sum); assertEquals(0.1, sum, 0.01); } @@ -127,7 +130,7 @@ public void testBucketsAndName() throws Exception { HttpServletRequest req = mock(HttpServletRequest.class); final String path = "/foo/bar/baz/bang"; when(req.getRequestURI()).thenReturn(path); - when(req.getMethod()).thenReturn(HttpMethods.POST); + when(req.getMethod()).thenReturn(POST); FilterChain c = mock(FilterChain.class); doAnswer(new Answer() { @@ -149,13 +152,13 @@ public Void answer(InvocationOnMock invocationOnMock) throws Throwable { f.doFilter(req, res, c); - final Double sum = CollectorRegistry.defaultRegistry.getSampleValue("foo_sum", new String[]{"path", "method"}, new String[]{"/foo", HttpMethods.POST}); + final Double sum = CollectorRegistry.defaultRegistry.getSampleValue("foo_sum", new String[]{"path", "method"}, new String[]{"/foo", POST}); assertEquals(0.1, sum, 0.01); - final Double le05 = CollectorRegistry.defaultRegistry.getSampleValue("foo_bucket", new String[]{"path", "method", "le"}, new String[]{"/foo", HttpMethods.POST, "0.05"}); + final Double le05 = CollectorRegistry.defaultRegistry.getSampleValue("foo_bucket", new String[]{"path", "method", "le"}, new String[]{"/foo", POST, "0.05"}); assertNotNull(le05); assertEquals(0, le05, 0.01); - final Double le15 = CollectorRegistry.defaultRegistry.getSampleValue("foo_bucket", new String[]{"path", "method", "le"}, new String[]{"/foo", HttpMethods.POST, "0.15"}); + final Double le15 = CollectorRegistry.defaultRegistry.getSampleValue("foo_bucket", new String[]{"path", "method", "le"}, new String[]{"/foo", POST, "0.15"}); assertNotNull(le15); assertEquals(1, le15, 0.01); @@ -185,7 +188,7 @@ public Void answer(InvocationOnMock invocationOnMock) throws Throwable { public void testStatusCode() throws Exception { HttpServletRequest req = mock(HttpServletRequest.class); when(req.getRequestURI()).thenReturn("/foo/bar/baz/bang"); - when(req.getMethod()).thenReturn(HttpMethods.GET); + when(req.getMethod()).thenReturn(GET); HttpServletResponse res = mock(HttpServletResponse.class); when(res.getStatus()).thenReturn(200); @@ -202,7 +205,7 @@ public void testStatusCode() throws Exception { constructed.doFilter(req, res, c); - final Double sampleValue = CollectorRegistry.defaultRegistry.getSampleValue("foobar_filter_status_total", new String[]{"path", "method", "status"}, new String[]{"/foo/bar", HttpMethods.GET, "200"}); + final Double sampleValue = CollectorRegistry.defaultRegistry.getSampleValue("foobar_filter_status_total", new String[]{"path", "method", "status"}, new String[]{"/foo/bar", GET, "200"}); assertNotNull(sampleValue); assertEquals(1, sampleValue, 0.0001); } @@ -211,7 +214,7 @@ public void testStatusCode() throws Exception { public void testStatusCodeWithNonHttpServletResponse() throws Exception { HttpServletRequest req = mock(HttpServletRequest.class); when(req.getRequestURI()).thenReturn("/foo/bar/baz/bang"); - when(req.getMethod()).thenReturn(HttpMethods.GET); + when(req.getMethod()).thenReturn(GET); ServletResponse res = mock(ServletResponse.class); @@ -227,7 +230,7 @@ public void testStatusCodeWithNonHttpServletResponse() throws Exception { constructed.doFilter(req, res, c); - final Double sampleValue = CollectorRegistry.defaultRegistry.getSampleValue("foobar_filter_status_total", new String[]{"path", "method", "status"}, new String[]{"/foo/bar", HttpMethods.GET, MetricsFilter.UNKNOWN_HTTP_STATUS_CODE}); + final Double sampleValue = CollectorRegistry.defaultRegistry.getSampleValue("foobar_filter_status_total", new String[]{"path", "method", "status"}, new String[]{"/foo/bar", GET, MetricsFilter.UNKNOWN_HTTP_STATUS_CODE}); assertNotNull(sampleValue); assertEquals(1, sampleValue, 0.0001); } diff --git a/simpleclient_servlet_jakarta/src/main/java/io/prometheus/client/filter/MetricsFilter.java b/simpleclient_servlet_jakarta/src/main/java/io/prometheus/client/filter/MetricsFilter.java index 32c795271..7e64f89a3 100644 --- a/simpleclient_servlet_jakarta/src/main/java/io/prometheus/client/filter/MetricsFilter.java +++ b/simpleclient_servlet_jakarta/src/main/java/io/prometheus/client/filter/MetricsFilter.java @@ -14,32 +14,23 @@ import java.io.IOException; /** - * The MetricsFilter class exists to provide a high-level filter that enables tunable collection of - * metrics for Servlet performance. + * The MetricsFilter class exists to provide a high-level filter that enables tunable collection of metrics for Servlet + * performance. * - *

- * The metric name itself is required, and configured with a {@code metric-name} init parameter. + *

The metric name itself is required, and configured with a {@code metric-name} init parameter. * - *

- * The help parameter, configured with the {@code help} init parameter, is not required but strongly - * recommended. + *

The help parameter, configured with the {@code help} init parameter, is not required but strongly recommended. * - *

- * By default, this filter will provide metrics that distinguish only 1 level deep for the request - * path (including servlet context path), but can be configured with the {@code path-components} - * init parameter. Any number provided that is less than 1 will provide the full path granularity - * (warning, this may affect performance). + *

By default, this filter will provide metrics that distinguish only 1 level deep for the request path + * (including servlet context path), but can be configured with the {@code path-components} init parameter. Any number + * provided that is less than 1 will provide the full path granularity (warning, this may affect performance). * - *

- * The Histogram buckets can be configured with a {@code buckets} init parameter whose value is a - * comma-separated list of valid {@code double} values. + *

The Histogram buckets can be configured with a {@code buckets} init parameter whose value is a comma-separated list + * of valid {@code double} values. * - *

- * HTTP statuses will be aggregated via Counter. The name for this counter will be derived from the - * {@code metric-name} init parameter. + *

HTTP statuses will be aggregated via Counter. The name for this counter will be derived from the {@code metric-name} init parameter. * - *

- * {@code
+ * 
{@code
  * 
  *   prometheusFilter
  *   io.prometheus.client.filter.MetricsFilter
@@ -60,147 +51,150 @@
  *      0
  *   
  * 
- * }
- * 
+ * }
* * @author Andrew Stuart <andrew.stuart2@gmail.com> */ public class MetricsFilter implements Filter { - static final String PATH_COMPONENT_PARAM = "path-components"; - static final String HELP_PARAM = "help"; - static final String METRIC_NAME_PARAM = "metric-name"; - static final String BUCKET_CONFIG_PARAM = "buckets"; - static final String UNKNOWN_HTTP_STATUS_CODE = ""; - - private Histogram histogram = null; - private Counter statusCounter = null; - - // Package-level for testing purposes. - int pathComponents = 1; - private String metricName = null; - private String help = "The time taken fulfilling servlet requests"; - private double[] buckets = null; - - public MetricsFilter() { - } - - public MetricsFilter(String metricName, String help, Integer pathComponents, double[] buckets) { - this.metricName = metricName; - this.buckets = buckets; - if (help != null) { - this.help = help; - } - if (pathComponents != null) { - this.pathComponents = pathComponents; - } - } - - private boolean isEmpty(String s) { - return s == null || s.length() == 0; - } - - private String getComponents(String str) { - if (str == null || pathComponents < 1) { - return str; - } - int count = 0; - int i = -1; - do { - i = str.indexOf("/", i + 1); - if (i < 0) { - // Path is longer than specified pathComponents. - return str; - } - count++; - } while (count <= pathComponents); - - return str.substring(0, i); - } - - @Override - public void init(FilterConfig filterConfig) throws ServletException { - Histogram.Builder builder = Histogram.build().labelNames("path", "method"); - - if (filterConfig == null && isEmpty(metricName)) { - throw new ServletException( - "No configuration object provided, and no metricName passed via constructor"); - } - - if (filterConfig != null) { - if (isEmpty(metricName)) { - metricName = filterConfig.getInitParameter(METRIC_NAME_PARAM); - if (isEmpty(metricName)) { - throw new ServletException("Init parameter \"" + METRIC_NAME_PARAM - + "\" is required; please supply a value"); - } - } - - if (!isEmpty(filterConfig.getInitParameter(HELP_PARAM))) { - help = filterConfig.getInitParameter(HELP_PARAM); - } - - // Allow overriding of the path "depth" to track - if (!isEmpty(filterConfig.getInitParameter(PATH_COMPONENT_PARAM))) { - pathComponents = Integer - .valueOf(filterConfig.getInitParameter(PATH_COMPONENT_PARAM)); - } - - // Allow users to override the default bucket configuration - if (!isEmpty(filterConfig.getInitParameter(BUCKET_CONFIG_PARAM))) { - String[] bucketParams = filterConfig.getInitParameter(BUCKET_CONFIG_PARAM) - .split(","); - buckets = new double[bucketParams.length]; - - for (int i = 0; i < bucketParams.length; i++) { - buckets[i] = Double.parseDouble(bucketParams[i]); - } - } - } - - if (buckets != null) { - builder = builder.buckets(buckets); - } - - histogram = builder.help(help).name(metricName).register(); - - statusCounter = Counter.build(metricName + "_status_total", "HTTP status codes of " + help) - .labelNames("path", "method", "status") - .register(); - } - - @Override - public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, - FilterChain filterChain) throws IOException, ServletException { - if (!(servletRequest instanceof HttpServletRequest)) { - filterChain.doFilter(servletRequest, servletResponse); - return; - } - - HttpServletRequest request = (HttpServletRequest) servletRequest; - - String path = request.getRequestURI(); - - String components = getComponents(path); - String method = request.getMethod(); - Histogram.Timer timer = histogram.labels(components, method).startTimer(); - - try { - filterChain.doFilter(servletRequest, servletResponse); - } finally { - timer.observeDuration(); - statusCounter.labels(components, method, getStatusCode(servletResponse)).inc(); - } - } - - private String getStatusCode(ServletResponse servletResponse) { - if (!(servletResponse instanceof HttpServletResponse)) { - return UNKNOWN_HTTP_STATUS_CODE; - } - - return Integer.toString(((HttpServletResponse) servletResponse).getStatus()); - } - - @Override - public void destroy() { - } + static final String PATH_COMPONENT_PARAM = "path-components"; + static final String HELP_PARAM = "help"; + static final String METRIC_NAME_PARAM = "metric-name"; + static final String BUCKET_CONFIG_PARAM = "buckets"; + static final String UNKNOWN_HTTP_STATUS_CODE = ""; + + private Histogram histogram = null; + private Counter statusCounter = null; + + // Package-level for testing purposes. + int pathComponents = 1; + private String metricName = null; + private String help = "The time taken fulfilling servlet requests"; + private double[] buckets = null; + + public MetricsFilter() {} + + public MetricsFilter( + String metricName, + String help, + Integer pathComponents, + double[] buckets) { + this.metricName = metricName; + this.buckets = buckets; + if (help != null) { + this.help = help; + } + if (pathComponents != null) { + this.pathComponents = pathComponents; + } + } + + private boolean isEmpty(String s) { + return s == null || s.length() == 0; + } + + private String getComponents(String str) { + if (str == null || pathComponents < 1) { + return str; + } + int count = 0; + int i = -1; + do { + i = str.indexOf("/", i + 1); + if (i < 0) { + // Path is longer than specified pathComponents. + return str; + } + count++; + } while (count <= pathComponents); + + return str.substring(0, i); + } + + @Override + public void init(FilterConfig filterConfig) throws ServletException { + Histogram.Builder builder = Histogram.build() + .labelNames("path", "method"); + + if (filterConfig == null && isEmpty(metricName)) { + throw new ServletException("No configuration object provided, and no metricName passed via constructor"); + } + + if (filterConfig != null) { + if (isEmpty(metricName)) { + metricName = filterConfig.getInitParameter(METRIC_NAME_PARAM); + if (isEmpty(metricName)) { + throw new ServletException("Init parameter \"" + METRIC_NAME_PARAM + "\" is required; please supply a value"); + } + } + + if (!isEmpty(filterConfig.getInitParameter(HELP_PARAM))) { + help = filterConfig.getInitParameter(HELP_PARAM); + } + + // Allow overriding of the path "depth" to track + if (!isEmpty(filterConfig.getInitParameter(PATH_COMPONENT_PARAM))) { + pathComponents = Integer.valueOf(filterConfig.getInitParameter(PATH_COMPONENT_PARAM)); + } + + // Allow users to override the default bucket configuration + if (!isEmpty(filterConfig.getInitParameter(BUCKET_CONFIG_PARAM))) { + String[] bucketParams = filterConfig.getInitParameter(BUCKET_CONFIG_PARAM).split(","); + buckets = new double[bucketParams.length]; + + for (int i = 0; i < bucketParams.length; i++) { + buckets[i] = Double.parseDouble(bucketParams[i]); + } + } + } + + if (buckets != null) { + builder = builder.buckets(buckets); + } + + histogram = builder + .help(help) + .name(metricName) + .register(); + + statusCounter = Counter.build(metricName + "_status_total", "HTTP status codes of " + help) + .labelNames("path", "method", "status") + .register(); + } + + @Override + public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException { + if (!(servletRequest instanceof HttpServletRequest)) { + filterChain.doFilter(servletRequest, servletResponse); + return; + } + + HttpServletRequest request = (HttpServletRequest) servletRequest; + + String path = request.getRequestURI(); + + String components = getComponents(path); + String method = request.getMethod(); + Histogram.Timer timer = histogram + .labels(components, method) + .startTimer(); + + try { + filterChain.doFilter(servletRequest, servletResponse); + } finally { + timer.observeDuration(); + statusCounter.labels(components, method, getStatusCode(servletResponse)).inc(); + } + } + + private String getStatusCode(ServletResponse servletResponse) { + if (!(servletResponse instanceof HttpServletResponse)) { + return UNKNOWN_HTTP_STATUS_CODE; + } + + return Integer.toString(((HttpServletResponse) servletResponse).getStatus()); + } + + @Override + public void destroy() { + } } diff --git a/simpleclient_servlet_jakarta/src/test/java/io/prometheus/client/exporter/ExampleBenchmark.java b/simpleclient_servlet_jakarta/src/test/java/io/prometheus/client/exporter/ExampleBenchmark.java index 6f710177e..bfbe9cd48 100644 --- a/simpleclient_servlet_jakarta/src/test/java/io/prometheus/client/exporter/ExampleBenchmark.java +++ b/simpleclient_servlet_jakarta/src/test/java/io/prometheus/client/exporter/ExampleBenchmark.java @@ -1,8 +1,9 @@ package io.prometheus.client.exporter; import io.prometheus.client.Gauge; -import org.eclipse.jetty.server.Server; + import org.eclipse.jetty.server.ServerConnector; +import org.eclipse.jetty.server.Server; import org.eclipse.jetty.servlet.ServletContextHandler; import org.eclipse.jetty.servlet.ServletHolder; @@ -28,6 +29,7 @@ public static void main(String[] args) throws Exception { server.setHandler(context); server.start(); Thread.sleep(1000); + ServerConnector connector = (ServerConnector) server.getConnectors()[0]; byte[] bytes = new byte[8192]; URL url = new URL("http", "localhost", connector.getLocalPort(), "/metrics"); diff --git a/simpleclient_servlet_jakarta/src/test/java/io/prometheus/client/filter/MetricsFilterTest.java b/simpleclient_servlet_jakarta/src/test/java/io/prometheus/client/filter/MetricsFilterTest.java index 93581ce51..493222cbc 100644 --- a/simpleclient_servlet_jakarta/src/test/java/io/prometheus/client/filter/MetricsFilterTest.java +++ b/simpleclient_servlet_jakarta/src/test/java/io/prometheus/client/filter/MetricsFilterTest.java @@ -2,8 +2,6 @@ import io.prometheus.client.Collector; import io.prometheus.client.CollectorRegistry; - -import org.eclipse.jetty.http.HttpMethod; import org.junit.After; import org.junit.Test; import org.mockito.invocation.InvocationOnMock; @@ -26,220 +24,214 @@ import static org.mockito.Mockito.when; public class MetricsFilterTest { - MetricsFilter f = new MetricsFilter(); + + public static final String GET = "GET"; + public static final String POST = "POST"; + + MetricsFilter f = new MetricsFilter(); + + @After + public void clear() { + CollectorRegistry.defaultRegistry.clear(); + } + + @Test + public void init() throws Exception { + FilterConfig cfg = mock(FilterConfig.class); + when(cfg.getInitParameter(anyString())).thenReturn(null); + + String metricName = "foo"; + + when(cfg.getInitParameter(MetricsFilter.METRIC_NAME_PARAM)).thenReturn(metricName); + when(cfg.getInitParameter(MetricsFilter.PATH_COMPONENT_PARAM)).thenReturn("4"); + + f.init(cfg); + + assertEquals(f.pathComponents, 4); + + HttpServletRequest req = mock(HttpServletRequest.class); + + when(req.getRequestURI()).thenReturn("/foo/bar/baz/bang/zilch/zip/nada"); + when(req.getMethod()).thenReturn(GET); + + HttpServletResponse res = mock(HttpServletResponse.class); + FilterChain c = mock(FilterChain.class); + + f.doFilter(req, res, c); + + verify(c).doFilter(req, res); + + final Double sampleValue = CollectorRegistry.defaultRegistry.getSampleValue(metricName + "_count", new String[]{"path", "method"}, new String[]{"/foo/bar/baz/bang", GET}); + assertNotNull(sampleValue); + assertEquals(1, sampleValue, 0.0001); + } - @After - public void clear() { - CollectorRegistry.defaultRegistry.clear(); - } + @Test + public void doFilter() throws Exception { + HttpServletRequest req = mock(HttpServletRequest.class); + final String path = "/foo/bar/baz/bang/zilch/zip/nada"; + + when(req.getRequestURI()).thenReturn(path); + when(req.getMethod()).thenReturn(GET); - @Test - public void init() throws Exception { - FilterConfig cfg = mock(FilterConfig.class); - when(cfg.getInitParameter(anyString())).thenReturn(null); - - String metricName = "foo"; - - when(cfg.getInitParameter(MetricsFilter.METRIC_NAME_PARAM)).thenReturn(metricName); - when(cfg.getInitParameter(MetricsFilter.PATH_COMPONENT_PARAM)).thenReturn("4"); - - f.init(cfg); - - assertEquals(f.pathComponents, 4); - - HttpServletRequest req = mock(HttpServletRequest.class); - - when(req.getRequestURI()).thenReturn("/foo/bar/baz/bang/zilch/zip/nada"); - when(req.getMethod()).thenReturn(HttpMethod.GET.asString()); - - HttpServletResponse res = mock(HttpServletResponse.class); - FilterChain c = mock(FilterChain.class); - - f.doFilter(req, res, c); - - verify(c).doFilter(req, res); - - final Double sampleValue = CollectorRegistry.defaultRegistry.getSampleValue( - metricName + "_count", - new String[] { "path", "method" }, - new String[] { "/foo/bar/baz/bang", HttpMethod.GET.asString() }); - assertNotNull(sampleValue); - assertEquals(1, sampleValue, 0.0001); - } - - @Test - public void doFilter() throws Exception { - HttpServletRequest req = mock(HttpServletRequest.class); - final String path = "/foo/bar/baz/bang/zilch/zip/nada"; - - when(req.getRequestURI()).thenReturn(path); - when(req.getMethod()).thenReturn(HttpMethod.GET.asString()); - - HttpServletResponse res = mock(HttpServletResponse.class); - FilterChain c = mock(FilterChain.class); - - String name = "foo"; - FilterConfig cfg = mock(FilterConfig.class); - when(cfg.getInitParameter(MetricsFilter.METRIC_NAME_PARAM)).thenReturn(name); - when(cfg.getInitParameter(MetricsFilter.PATH_COMPONENT_PARAM)).thenReturn("0"); - - f.init(cfg); - f.doFilter(req, res, c); - - verify(c).doFilter(req, res); - - final Double sampleValue = CollectorRegistry.defaultRegistry.getSampleValue(name + "_count", - new String[] { "path", "method" }, - new String[] { path, HttpMethod.GET.asString() }); - assertNotNull(sampleValue); - assertEquals(1, sampleValue, 0.0001); - } - - @Test - public void testConstructor() throws Exception { - HttpServletRequest req = mock(HttpServletRequest.class); - final String path = "/foo/bar/baz/bang"; - when(req.getRequestURI()).thenReturn(path); - when(req.getMethod()).thenReturn(HttpMethod.POST.asString()); - - FilterChain c = mock(FilterChain.class); - doAnswer(new Answer() { - @Override - public Void answer(InvocationOnMock invocationOnMock) throws Throwable { - Thread.sleep(100); - return null; - } - }).when(c).doFilter(any(HttpServletRequest.class), any(HttpServletResponse.class)); - - MetricsFilter constructed = new MetricsFilter("foobar_baz_filter_duration_seconds", - "Help for my filter", 0, null); - constructed.init(mock(FilterConfig.class)); - - HttpServletResponse res = mock(HttpServletResponse.class); - constructed.doFilter(req, res, c); - - final Double sum = CollectorRegistry.defaultRegistry.getSampleValue( - "foobar_baz_filter_duration_seconds_sum", - new String[] { "path", "method" }, - new String[] { path, HttpMethod.POST.asString() }); - assertNotNull(sum); - assertEquals(0.1, sum, 0.01); - } - - @Test - public void testBucketsAndName() throws Exception { - HttpServletRequest req = mock(HttpServletRequest.class); - final String path = "/foo/bar/baz/bang"; - when(req.getRequestURI()).thenReturn(path); - when(req.getMethod()).thenReturn(HttpMethod.POST.asString()); - - FilterChain c = mock(FilterChain.class); - doAnswer(new Answer() { - @Override - public Void answer(InvocationOnMock invocationOnMock) throws Throwable { - Thread.sleep(100); - return null; - } - }).when(c).doFilter(any(HttpServletRequest.class), any(HttpServletResponse.class)); - - final String buckets = "0.01,0.05,0.1,0.15,0.25"; - FilterConfig cfg = mock(FilterConfig.class); - when(cfg.getInitParameter(MetricsFilter.BUCKET_CONFIG_PARAM)).thenReturn(buckets); - when(cfg.getInitParameter(MetricsFilter.METRIC_NAME_PARAM)).thenReturn("foo"); - - HttpServletResponse res = mock(HttpServletResponse.class); - - f.init(cfg); - - f.doFilter(req, res, c); - - final Double sum = CollectorRegistry.defaultRegistry.getSampleValue("foo_sum", - new String[] { "path", "method" }, - new String[] { "/foo", HttpMethod.POST.asString() }); - assertEquals(0.1, sum, 0.01); - - final Double le05 = CollectorRegistry.defaultRegistry.getSampleValue("foo_bucket", - new String[] { "path", "method", "le" }, - new String[] { "/foo", HttpMethod.POST.asString(), "0.05" }); - assertNotNull(le05); - assertEquals(0, le05, 0.01); - final Double le15 = CollectorRegistry.defaultRegistry.getSampleValue("foo_bucket", - new String[] { "path", "method", "le" }, - new String[] { "/foo", HttpMethod.POST.asString(), "0.15" }); - assertNotNull(le15); - assertEquals(1, le15, 0.01); - - final Enumeration samples = CollectorRegistry.defaultRegistry - .metricFamilySamples(); - Collector.MetricFamilySamples sample = null; - while (samples.hasMoreElements()) { - sample = samples.nextElement(); - if (sample.name.equals("foo")) { - break; - } - } - - assertNotNull(sample); - - int count = 0; - for (Collector.MetricFamilySamples.Sample s : sample.samples) { - if (s.name.equals("foo_bucket")) { - count++; - } - } - // +1 because of the final le=+infinity bucket - assertEquals(buckets.split(",").length + 1, count); - } - - @Test - public void testStatusCode() throws Exception { - HttpServletRequest req = mock(HttpServletRequest.class); - when(req.getRequestURI()).thenReturn("/foo/bar/baz/bang"); - when(req.getMethod()).thenReturn(HttpMethod.GET.asString()); - - HttpServletResponse res = mock(HttpServletResponse.class); - when(res.getStatus()).thenReturn(200); - - FilterChain c = mock(FilterChain.class); - - MetricsFilter constructed = new MetricsFilter("foobar_filter", "Help for my filter", 2, - null); - constructed.init(mock(FilterConfig.class)); - - constructed.doFilter(req, res, c); - - final Double sampleValue = CollectorRegistry.defaultRegistry.getSampleValue( - "foobar_filter_status_total", - new String[] { "path", "method", "status" }, - new String[] { "/foo/bar", HttpMethod.GET.asString(), "200" }); - assertNotNull(sampleValue); - assertEquals(1, sampleValue, 0.0001); - } - - @Test - public void testStatusCodeWithNonHttpServletResponse() throws Exception { - HttpServletRequest req = mock(HttpServletRequest.class); - when(req.getRequestURI()).thenReturn("/foo/bar/baz/bang"); - when(req.getMethod()).thenReturn(HttpMethod.GET.asString()); - - ServletResponse res = mock(ServletResponse.class); - - FilterChain c = mock(FilterChain.class); - - MetricsFilter constructed = new MetricsFilter("foobar_filter", "Help for my filter", 2, - null); - constructed.init(mock(FilterConfig.class)); - - constructed.doFilter(req, res, c); - - final Double sampleValue = CollectorRegistry.defaultRegistry.getSampleValue( - "foobar_filter_status_total", - new String[] { "path", "method", "status" }, - new String[] { - "/foo/bar", - HttpMethod.GET.asString(), - MetricsFilter.UNKNOWN_HTTP_STATUS_CODE }); - assertNotNull(sampleValue); - assertEquals(1, sampleValue, 0.0001); - } + HttpServletResponse res = mock(HttpServletResponse.class); + FilterChain c = mock(FilterChain.class); + + String name = "foo"; + FilterConfig cfg = mock(FilterConfig.class); + when(cfg.getInitParameter(MetricsFilter.METRIC_NAME_PARAM)).thenReturn(name); + when(cfg.getInitParameter(MetricsFilter.PATH_COMPONENT_PARAM)).thenReturn("0"); + + f.init(cfg); + f.doFilter(req, res, c); + + verify(c).doFilter(req, res); + + + final Double sampleValue = CollectorRegistry.defaultRegistry.getSampleValue(name + "_count", new String[]{"path", "method"}, new String[]{path, GET}); + assertNotNull(sampleValue); + assertEquals(1, sampleValue, 0.0001); + } + + @Test + public void testConstructor() throws Exception { + HttpServletRequest req = mock(HttpServletRequest.class); + final String path = "/foo/bar/baz/bang"; + when(req.getRequestURI()).thenReturn(path); + when(req.getMethod()).thenReturn(POST); + + FilterChain c = mock(FilterChain.class); + doAnswer(new Answer() { + @Override + public Void answer(InvocationOnMock invocationOnMock) throws Throwable { + Thread.sleep(100); + return null; + } + }).when(c).doFilter(any(HttpServletRequest.class), any(HttpServletResponse.class)); + + MetricsFilter constructed = new MetricsFilter( + "foobar_baz_filter_duration_seconds", + "Help for my filter", + 0, + null + ); + constructed.init(mock(FilterConfig.class)); + + HttpServletResponse res = mock(HttpServletResponse.class); + constructed.doFilter(req, res, c); + + final Double sum = CollectorRegistry.defaultRegistry.getSampleValue("foobar_baz_filter_duration_seconds_sum", new String[]{"path", "method"}, new String[]{path, POST}); + assertNotNull(sum); + assertEquals(0.1, sum, 0.01); + } + + @Test + public void testBucketsAndName() throws Exception { + HttpServletRequest req = mock(HttpServletRequest.class); + final String path = "/foo/bar/baz/bang"; + when(req.getRequestURI()).thenReturn(path); + when(req.getMethod()).thenReturn(POST); + + FilterChain c = mock(FilterChain.class); + doAnswer(new Answer() { + @Override + public Void answer(InvocationOnMock invocationOnMock) throws Throwable { + Thread.sleep(100); + return null; + } + }).when(c).doFilter(any(HttpServletRequest.class), any(HttpServletResponse.class)); + + final String buckets = "0.01,0.05,0.1,0.15,0.25"; + FilterConfig cfg = mock(FilterConfig.class); + when(cfg.getInitParameter(MetricsFilter.BUCKET_CONFIG_PARAM)).thenReturn(buckets); + when(cfg.getInitParameter(MetricsFilter.METRIC_NAME_PARAM)).thenReturn("foo"); + + HttpServletResponse res = mock(HttpServletResponse.class); + + f.init(cfg); + + f.doFilter(req, res, c); + + final Double sum = CollectorRegistry.defaultRegistry.getSampleValue("foo_sum", new String[]{"path", "method"}, new String[]{"/foo", POST}); + assertEquals(0.1, sum, 0.01); + + final Double le05 = CollectorRegistry.defaultRegistry.getSampleValue("foo_bucket", new String[]{"path", "method", "le"}, new String[]{"/foo", POST, "0.05"}); + assertNotNull(le05); + assertEquals(0, le05, 0.01); + final Double le15 = CollectorRegistry.defaultRegistry.getSampleValue("foo_bucket", new String[]{"path", "method", "le"}, new String[]{"/foo", POST, "0.15"}); + assertNotNull(le15); + assertEquals(1, le15, 0.01); + + + final Enumeration samples = CollectorRegistry.defaultRegistry.metricFamilySamples(); + Collector.MetricFamilySamples sample = null; + while(samples.hasMoreElements()) { + sample = samples.nextElement(); + if (sample.name.equals("foo")) { + break; + } + } + + assertNotNull(sample); + + int count = 0; + for (Collector.MetricFamilySamples.Sample s : sample.samples) { + if (s.name.equals("foo_bucket")) { + count++; + } + } + // +1 because of the final le=+infinity bucket + assertEquals(buckets.split(",").length+1, count); + } + + @Test + public void testStatusCode() throws Exception { + HttpServletRequest req = mock(HttpServletRequest.class); + when(req.getRequestURI()).thenReturn("/foo/bar/baz/bang"); + when(req.getMethod()).thenReturn(GET); + + HttpServletResponse res = mock(HttpServletResponse.class); + when(res.getStatus()).thenReturn(200); + + FilterChain c = mock(FilterChain.class); + + MetricsFilter constructed = new MetricsFilter( + "foobar_filter", + "Help for my filter", + 2, + null + ); + constructed.init(mock(FilterConfig.class)); + + constructed.doFilter(req, res, c); + + final Double sampleValue = CollectorRegistry.defaultRegistry.getSampleValue("foobar_filter_status_total", new String[]{"path", "method", "status"}, new String[]{"/foo/bar", GET, "200"}); + assertNotNull(sampleValue); + assertEquals(1, sampleValue, 0.0001); + } + + @Test + public void testStatusCodeWithNonHttpServletResponse() throws Exception { + HttpServletRequest req = mock(HttpServletRequest.class); + when(req.getRequestURI()).thenReturn("/foo/bar/baz/bang"); + when(req.getMethod()).thenReturn(GET); + + ServletResponse res = mock(ServletResponse.class); + + FilterChain c = mock(FilterChain.class); + + MetricsFilter constructed = new MetricsFilter( + "foobar_filter", + "Help for my filter", + 2, + null + ); + constructed.init(mock(FilterConfig.class)); + + constructed.doFilter(req, res, c); + + final Double sampleValue = CollectorRegistry.defaultRegistry.getSampleValue("foobar_filter_status_total", new String[]{"path", "method", "status"}, new String[]{"/foo/bar", GET, MetricsFilter.UNKNOWN_HTTP_STATUS_CODE}); + assertNotNull(sampleValue); + assertEquals(1, sampleValue, 0.0001); + } }