Skip to content

Commit d663d04

Browse files
authoredJul 31, 2021
Add parameter to optionally strip deploy path. (#639)
* Add parameter to optionally strip deploy path. Closes #631. Signed-off-by: Lapo Luchini <lapo@lapo.it> * Add documentation and test as requested in PR#639. Signed-off-by: Lapo Luchini <lapo@lapo.it>
1 parent 8976c99 commit d663d04

File tree

3 files changed

+50
-1
lines changed

3 files changed

+50
-1
lines changed
 

‎README.md

+9-1
Original file line numberDiff line numberDiff line change
@@ -577,7 +577,10 @@ measuring is also configurable, via the `path-components` init parameter. By
577577
default, the servlet filter will record each path differently, but by setting an
578578
integer here, you can tell the filter to only record up to the Nth slashes. That
579579
is, all requests with greater than N "/" characters in the servlet URI path will
580-
be measured in the same bucket and you will lose that granularity.
580+
be measured in the same bucket and you will lose that granularity. The init
581+
parameter `strip-context-path` can be used to strip the leading part of the URL
582+
which is part of the deploy context (i.e. the folder the servlet is deployed to),
583+
so that the same servlet deployed to different paths can lead to similar metrics.
581584

582585
The code below is an example of the XML configuration for the filter. You will
583586
need to place this (replace your own values) code in your
@@ -605,6 +608,11 @@ need to place this (replace your own values) code in your
605608
<param-name>path-components</param-name>
606609
<param-value>1</param-value>
607610
</init-param>
611+
<!-- strip-context-path is optional, defaults to false -->
612+
<init-param>
613+
<param-name>strip-context-path</param-name>
614+
<param-value>false</param-value>
615+
</init-param>
608616
</filter>
609617

610618
<!-- You will most likely want this to be the first filter in the chain

‎simpleclient_servlet/src/main/java/io/prometheus/client/filter/MetricsFilter.java

+18
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,10 @@
2525
* (including servlet context path), but can be configured with the {@code path-components} init parameter. Any number
2626
* provided that is less than 1 will provide the full path granularity (warning, this may affect performance).
2727
*
28+
* <p>The {@code strip-context-path} init parameter can be used to avoid including the leading path components which are
29+
* part of the context (i.e. the folder where the servlet is deployed) so that the same project deployed under different
30+
* paths can produce the same metrics.
31+
*
2832
* <p>The Histogram buckets can be configured with a {@code buckets} init parameter whose value is a comma-separated list
2933
* of valid {@code double} values.
3034
*
@@ -50,6 +54,11 @@
5054
* <param-name>path-components</param-name>
5155
* <param-value>0</param-value>
5256
* </init-param>
57+
* <!-- strip-context-path is optional, defaults to false -->
58+
* <init-param>
59+
* <param-name>strip-context-path</param-name>
60+
* <param-value>false</param-value>
61+
* </init-param>
5362
* </filter>
5463
* }</pre>
5564
*
@@ -60,6 +69,7 @@ public class MetricsFilter implements Filter {
6069
static final String HELP_PARAM = "help";
6170
static final String METRIC_NAME_PARAM = "metric-name";
6271
static final String BUCKET_CONFIG_PARAM = "buckets";
72+
static final String STRIP_CONTEXT_PATH_PARAM = "strip-context-path";
6373
static final String UNKNOWN_HTTP_STATUS_CODE = "";
6474

6575
private Histogram histogram = null;
@@ -68,6 +78,7 @@ public class MetricsFilter implements Filter {
6878
// Package-level for testing purposes.
6979
int pathComponents = 1;
7080
private String metricName = null;
81+
boolean stripContextPath = false;
7182
private String help = "The time taken fulfilling servlet requests";
7283
private double[] buckets = null;
7384

@@ -145,6 +156,10 @@ public void init(FilterConfig filterConfig) throws ServletException {
145156
buckets[i] = Double.parseDouble(bucketParams[i]);
146157
}
147158
}
159+
160+
if (!isEmpty(filterConfig.getInitParameter(STRIP_CONTEXT_PATH_PARAM))) {
161+
stripContextPath = Boolean.parseBoolean(filterConfig.getInitParameter(STRIP_CONTEXT_PATH_PARAM));
162+
}
148163
}
149164

150165
if (buckets != null) {
@@ -171,6 +186,9 @@ public void doFilter(ServletRequest servletRequest, ServletResponse servletRespo
171186
HttpServletRequest request = (HttpServletRequest) servletRequest;
172187

173188
String path = request.getRequestURI();
189+
if (stripContextPath) {
190+
path = path.substring(request.getContextPath().length());
191+
}
174192

175193
String components = getComponents(path);
176194
String method = request.getMethod();

‎simpleclient_servlet/src/test/java/io/prometheus/client/filter/MetricsFilterTest.java

+23
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717

1818
import static org.junit.Assert.assertEquals;
1919
import static org.junit.Assert.assertNotNull;
20+
import static org.junit.Assert.assertTrue;
2021
import static org.mockito.ArgumentMatchers.any;
2122
import static org.mockito.ArgumentMatchers.anyString;
2223
import static org.mockito.Mockito.doAnswer;
@@ -231,4 +232,26 @@ public void testStatusCodeWithNonHttpServletResponse() throws Exception {
231232
assertNotNull(sampleValue);
232233
assertEquals(1, sampleValue, 0.0001);
233234
}
235+
236+
@Test
237+
public void testStripContextPath() throws Exception {
238+
String metricName = "foo";
239+
FilterConfig cfg = mock(FilterConfig.class);
240+
when(cfg.getInitParameter(MetricsFilter.METRIC_NAME_PARAM)).thenReturn(metricName);
241+
when(cfg.getInitParameter(MetricsFilter.PATH_COMPONENT_PARAM)).thenReturn("0");
242+
when(cfg.getInitParameter(MetricsFilter.STRIP_CONTEXT_PATH_PARAM)).thenReturn("true");
243+
f.init(cfg);
244+
assertTrue(f.stripContextPath);
245+
HttpServletRequest req = mock(HttpServletRequest.class);
246+
when(req.getRequestURI()).thenReturn("/foo/bar/baz/bang");
247+
when(req.getContextPath()).thenReturn("/foo/bar");
248+
when(req.getMethod()).thenReturn(HttpMethods.GET);
249+
HttpServletResponse res = mock(HttpServletResponse.class);
250+
FilterChain c = mock(FilterChain.class);
251+
f.doFilter(req, res, c);
252+
verify(c).doFilter(req, res);
253+
final Double sampleValue = CollectorRegistry.defaultRegistry.getSampleValue(metricName + "_count", new String[]{"path", "method"}, new String[]{"/baz/bang", HttpMethods.GET});
254+
assertNotNull(sampleValue);
255+
assertEquals(1, sampleValue, 0.0001);
256+
}
234257
}

0 commit comments

Comments
 (0)