1111import java .net .InetSocketAddress ;
1212import java .net .URLDecoder ;
1313import java .nio .charset .Charset ;
14+ import java .util .ArrayList ;
15+ import java .util .Collection ;
16+ import java .util .Collections ;
1417import java .util .HashSet ;
1518import java .util .List ;
1619import java .util .Set ;
@@ -62,16 +65,16 @@ protected ByteArrayOutputStream initialValue()
6265 public static class HTTPMetricHandler implements HttpHandler {
6366 private final CollectorRegistry registry ;
6467 private final LocalByteArray response = new LocalByteArray ();
65- private final MetricNameFilter filter ;
68+ private final Config config ;
6669 private final static String HEALTHY_RESPONSE = "Exporter is Healthy." ;
6770
6871 HTTPMetricHandler (CollectorRegistry registry ) {
6972 this (registry , null );
7073 }
7174
72- HTTPMetricHandler (CollectorRegistry registry , MetricNameFilter filter ) {
75+ HTTPMetricHandler (CollectorRegistry registry , Config config ) {
7376 this .registry = registry ;
74- this .filter = filter ;
77+ this .config = config == null ? new Config () : config ;
7578 }
7679
7780 @ Override
@@ -87,9 +90,12 @@ public void handle(HttpExchange t) throws IOException {
8790 } else {
8891 String contentType = TextFormat .chooseContentType (t .getRequestHeaders ().getFirst ("Accept" ));
8992 t .getResponseHeaders ().set ("Content-Type" , contentType );
90- MetricNameFilter .Builder filterBuilder = filter == null ? new MetricNameFilter .Builder () : filter .toBuilder ();
91- TextFormat .writeFormat (contentType , osw ,
92- registry .filteredMetricFamilySamples (filterBuilder .includeNames (parseQuery (query )).build ()));
93+ MetricNameFilter filter = new MetricNameFilter .Builder ()
94+ .includeNames (parseQuery (query ))
95+ .includePrefixes (config .getIncludedPrefixes ())
96+ .excludePrefixes (config .getExcludedPrefixes ())
97+ .build ();
98+ TextFormat .writeFormat (contentType , osw , registry .filteredMetricFamilySamples (filter ));
9399 }
94100
95101 osw .close ();
@@ -174,67 +180,164 @@ static ThreadFactory defaultThreadFactory(boolean daemon) {
174180 protected final ExecutorService executorService ;
175181
176182 /**
177- * Start a HTTP server serving Prometheus metrics from the given registry using the given {@link HttpServer}.
178- * The {@code httpServer} is expected to already be bound to an address
183+ * Configure the HTTPServer to include / exclude metrics by name prefix.
179184 */
180- public HTTPServer (HttpServer httpServer , CollectorRegistry registry , boolean daemon ) throws IOException {
181- this (httpServer , registry , null , daemon );
182- }
185+ public static class Config {
183186
184- public HTTPServer (HttpServer httpServer , CollectorRegistry registry , MetricNameFilter filter , boolean daemon ) throws IOException {
185- if (httpServer .getAddress () == null )
186- throw new IllegalArgumentException ("HttpServer hasn't been bound to an address" );
187+ private final Collection <String > includedPrefixes ;
188+ private final Collection <String > excludedPrefixes ;
187189
188- server = httpServer ;
189- HttpHandler mHandler = new HTTPMetricHandler (registry , filter );
190- server .createContext ("/" , mHandler );
191- server .createContext ("/metrics" , mHandler );
192- server .createContext ("/-/healthy" , mHandler );
193- executorService = Executors .newFixedThreadPool (5 , NamedDaemonThreadFactory .defaultThreadFactory (daemon ));
194- server .setExecutor (executorService );
195- start (daemon );
190+ /**
191+ * Empty config means nothing is filtered; all metrics are exported.
192+ */
193+ public Config () {
194+ includedPrefixes = Collections .emptyList ();
195+ excludedPrefixes = Collections .emptyList ();
196+ }
197+
198+ /**
199+ * If {@code includedNamePrefixes} is not empty, only metrics with a name starting with one of these
200+ * prefixes will be exported. If {@code excludedNamePrefixes} is not empty, metrics with a name
201+ * starting with one of these prefixes will not be exported. If both parameters are not empty, metrics
202+ * must match both criteria in order to be exported.
203+ */
204+ public Config (Collection <String > includedNamePrefixes , Collection <String > excludedNamePrefixes ) {
205+ this .includedPrefixes = unmodifiableCopy (includedNamePrefixes );
206+ this .excludedPrefixes = unmodifiableCopy (excludedNamePrefixes );
207+ }
208+
209+ private Collection <String > unmodifiableCopy (Collection <String > collection ) {
210+ if (collection == null ) {
211+ return Collections .emptyList ();
212+ } else {
213+ return Collections .unmodifiableCollection (new ArrayList <String >(collection ));
214+ }
215+ }
216+
217+ public Collection <String > getIncludedPrefixes () {
218+ return includedPrefixes ;
219+ }
220+
221+ public Collection <String > getExcludedPrefixes () {
222+ return excludedPrefixes ;
223+ }
196224 }
197225
198226 /**
199- * Start a HTTP server serving Prometheus metrics from the given registry .
227+ * Start an HTTP server serving the default Prometheus registry using non-daemon threads .
200228 */
201- public HTTPServer (InetSocketAddress addr , CollectorRegistry registry , boolean daemon ) throws IOException {
202- this (HttpServer . create ( addr , 3 ), registry , daemon );
229+ public HTTPServer (int port ) throws IOException {
230+ this (port , null );
203231 }
204232
205233 /**
206- * Start a HTTP server serving Prometheus metrics from the given registry using non-daemon threads.
234+ * Like {@link #HTTPServer(int)}, but with an additional {@link Config} parameter to configure
235+ * which metrics should be exported.
207236 */
208- public HTTPServer (InetSocketAddress addr , CollectorRegistry registry ) throws IOException {
209- this (addr , registry , false );
237+ public HTTPServer (int port , Config config ) throws IOException {
238+ this (port , false , config );
210239 }
211240
212241 /**
213- * Start a HTTP server serving the default Prometheus registry.
242+ * Start an HTTP server serving the default Prometheus registry.
214243 */
215244 public HTTPServer (int port , boolean daemon ) throws IOException {
216- this (new InetSocketAddress ( port ), CollectorRegistry . defaultRegistry , daemon );
245+ this (port , daemon , null );
217246 }
218247
219248 /**
220- * Start a HTTP server serving the default Prometheus registry using non-daemon threads.
249+ * Like {@link #HTTPServer(int, boolean)}, but with an additional {@link Config}
250+ * parameter to configure which metrics should be exported.
221251 */
222- public HTTPServer (int port ) throws IOException {
223- this (port , false );
252+ public HTTPServer (int port , boolean daemon , Config config ) throws IOException {
253+ this (new InetSocketAddress ( port ), CollectorRegistry . defaultRegistry , daemon , config );
224254 }
225255
226256 /**
227- * Start a HTTP server serving the default Prometheus registry.
257+ * Start an HTTP server serving the default Prometheus registry using non-daemon threads.
258+ */
259+ public HTTPServer (String host , int port ) throws IOException {
260+ this (host , port , null );
261+ }
262+
263+ /**
264+ * Like {@link #HTTPServer(String, int)}, but with an additional {@link Config}
265+ * parameter to configure which metrics should be exported.
266+ */
267+ public HTTPServer (String host , int port , Config config ) throws IOException {
268+ this (host , port , false , config );
269+ }
270+
271+ /**
272+ * Start an HTTP server serving the default Prometheus registry.
228273 */
229274 public HTTPServer (String host , int port , boolean daemon ) throws IOException {
230- this (new InetSocketAddress ( host , port ), CollectorRegistry . defaultRegistry , daemon );
275+ this (host , port , daemon , null );
231276 }
232277
233278 /**
234- * Start a HTTP server serving the default Prometheus registry using non-daemon threads.
279+ * Like {@link #HTTPServer(String, int, boolean)}, but with an additional {@link Config}
280+ * parameter to configure which metrics should be exported.
235281 */
236- public HTTPServer (String host , int port ) throws IOException {
237- this (new InetSocketAddress (host , port ), CollectorRegistry .defaultRegistry , false );
282+ public HTTPServer (String host , int port , boolean daemon , Config config ) throws IOException {
283+ this (new InetSocketAddress (host , port ), CollectorRegistry .defaultRegistry , daemon , config );
284+ }
285+
286+ /**
287+ * Start an HTTP server serving Prometheus metrics from the given registry using non-daemon threads.
288+ */
289+ public HTTPServer (InetSocketAddress addr , CollectorRegistry registry ) throws IOException {
290+ this (addr , registry , null );
291+ }
292+
293+ /**
294+ * Like {@link #HTTPServer(InetSocketAddress, CollectorRegistry)}, but with an additional {@link Config}
295+ * parameter to configure which metrics should be exported.
296+ */
297+ public HTTPServer (InetSocketAddress addr , CollectorRegistry registry , Config config ) throws IOException {
298+ this (addr , registry , false , config );
299+ }
300+
301+ /**
302+ * Start an HTTP server serving Prometheus metrics from the given registry.
303+ */
304+ public HTTPServer (InetSocketAddress addr , CollectorRegistry registry , boolean daemon ) throws IOException {
305+ this (addr , registry , daemon , null );
306+ }
307+
308+ /**
309+ * Like {@link #HTTPServer(InetSocketAddress, CollectorRegistry, boolean)}, but with an additional {@link Config}
310+ * parameter to configure which metrics should be exported.
311+ */
312+ public HTTPServer (InetSocketAddress addr , CollectorRegistry registry , boolean daemon , Config config ) throws IOException {
313+ this (HttpServer .create (addr , 3 ), registry , daemon , config );
314+ }
315+
316+ /**
317+ * Start an HTTP server serving Prometheus metrics from the given registry using the given {@link HttpServer}.
318+ * The {@code httpServer} is expected to already be bound to an address
319+ */
320+ public HTTPServer (HttpServer httpServer , CollectorRegistry registry , boolean daemon ) throws IOException {
321+ this (httpServer , registry , daemon , null );
322+ }
323+
324+
325+ /**
326+ * Like {@link #HTTPServer(HttpServer, CollectorRegistry, boolean)}, but with an additional {@link Config}
327+ * parameter to configure which metrics should be exported.
328+ */
329+ public HTTPServer (HttpServer httpServer , CollectorRegistry registry , boolean daemon , Config config ) throws IOException {
330+ if (httpServer .getAddress () == null )
331+ throw new IllegalArgumentException ("HttpServer hasn't been bound to an address" );
332+
333+ server = httpServer ;
334+ HttpHandler mHandler = new HTTPMetricHandler (registry , config );
335+ server .createContext ("/" , mHandler );
336+ server .createContext ("/metrics" , mHandler );
337+ server .createContext ("/-/healthy" , mHandler );
338+ executorService = Executors .newFixedThreadPool (5 , NamedDaemonThreadFactory .defaultThreadFactory (daemon ));
339+ server .setExecutor (executorService );
340+ start (daemon );
238341 }
239342
240343 /**
0 commit comments