diff --git a/README.md b/README.md
index 7086f8c30..df711401a 100644
--- a/README.md
+++ b/README.md
@@ -449,7 +449,10 @@ measuring is also configurable, via the `path-components` init parameter. By
default, the servlet filter will record each path differently, but by setting an
integer here, you can tell the filter to only record up to the Nth slashes. That
is, all requests with greater than N "/" characters in the servlet URI path will
-be measured in the same bucket and you will lose that granularity.
+be measured in the same bucket and you will lose that granularity. The init
+parameter `strip-context-path` can be used to strip the leading part of the URL
+which is part of the deploy context (i.e. the folder the servlet is deployed to),
+so that the same servlet deployed to different paths can lead to similar metrics.
The code below is an example of the XML configuration for the filter. You will
need to place this (replace your own values) code in your
@@ -477,6 +480,11 @@ need to place this (replace your own values) code in your
path-components
1
+
+
+ strip-context-path
+ false
+
+ *
+ * strip-context-path
+ * false
+ *
*
* }
*
@@ -60,6 +69,7 @@ public class MetricsFilter implements Filter {
static final String HELP_PARAM = "help";
static final String METRIC_NAME_PARAM = "metric-name";
static final String BUCKET_CONFIG_PARAM = "buckets";
+ static final String STRIP_CONTEXT_PATH_PARAM = "strip-context-path";
static final String UNKNOWN_HTTP_STATUS_CODE = "";
private Histogram histogram = null;
@@ -68,6 +78,7 @@ public class MetricsFilter implements Filter {
// Package-level for testing purposes.
int pathComponents = 1;
private String metricName = null;
+ boolean stripContextPath = false;
private String help = "The time taken fulfilling servlet requests";
private double[] buckets = null;
@@ -145,6 +156,10 @@ public void init(FilterConfig filterConfig) throws ServletException {
buckets[i] = Double.parseDouble(bucketParams[i]);
}
}
+
+ if (!isEmpty(filterConfig.getInitParameter(STRIP_CONTEXT_PATH_PARAM))) {
+ stripContextPath = Boolean.parseBoolean(filterConfig.getInitParameter(STRIP_CONTEXT_PATH_PARAM));
+ }
}
if (buckets != null) {
@@ -171,6 +186,9 @@ public void doFilter(ServletRequest servletRequest, ServletResponse servletRespo
HttpServletRequest request = (HttpServletRequest) servletRequest;
String path = request.getRequestURI();
+ if (stripContextPath) {
+ path = path.substring(request.getContextPath().length());
+ }
String components = getComponents(path);
String method = request.getMethod();
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..40bccaa6f 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
@@ -17,6 +17,7 @@
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.Mockito.doAnswer;
@@ -231,4 +232,26 @@ public void testStatusCodeWithNonHttpServletResponse() throws Exception {
assertNotNull(sampleValue);
assertEquals(1, sampleValue, 0.0001);
}
+
+ @Test
+ public void testStripContextPath() throws Exception {
+ String metricName = "foo";
+ FilterConfig cfg = mock(FilterConfig.class);
+ when(cfg.getInitParameter(MetricsFilter.METRIC_NAME_PARAM)).thenReturn(metricName);
+ when(cfg.getInitParameter(MetricsFilter.PATH_COMPONENT_PARAM)).thenReturn("0");
+ when(cfg.getInitParameter(MetricsFilter.STRIP_CONTEXT_PATH_PARAM)).thenReturn("true");
+ f.init(cfg);
+ assertTrue(f.stripContextPath);
+ HttpServletRequest req = mock(HttpServletRequest.class);
+ when(req.getRequestURI()).thenReturn("/foo/bar/baz/bang");
+ when(req.getContextPath()).thenReturn("/foo/bar");
+ when(req.getMethod()).thenReturn(HttpMethods.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[]{"/baz/bang", HttpMethods.GET});
+ assertNotNull(sampleValue);
+ assertEquals(1, sampleValue, 0.0001);
+ }
}