001package io.prometheus.client.servlet.common.exporter; 002 003import io.prometheus.client.CollectorRegistry; 004import io.prometheus.client.SampleNameFilter; 005import io.prometheus.client.Predicate; 006import io.prometheus.client.servlet.common.adapter.HttpServletRequestAdapter; 007import io.prometheus.client.servlet.common.adapter.HttpServletResponseAdapter; 008import io.prometheus.client.exporter.common.TextFormat; 009import io.prometheus.client.servlet.common.adapter.ServletConfigAdapter; 010 011import java.io.BufferedWriter; 012import java.io.IOException; 013import java.io.Writer; 014import java.util.Arrays; 015import java.util.Collections; 016import java.util.HashSet; 017import java.util.List; 018import java.util.Set; 019 020/** 021 * The MetricsServlet class exists to provide a simple way of exposing the metrics values. 022 */ 023public class Exporter { 024 025 public static final String NAME_MUST_BE_EQUAL_TO = "name-must-be-equal-to"; 026 public static final String NAME_MUST_NOT_BE_EQUAL_TO = "name-must-not-be-equal-to"; 027 public static final String NAME_MUST_START_WITH = "name-must-start-with"; 028 public static final String NAME_MUST_NOT_START_WITH = "name-must-not-start-with"; 029 030 private CollectorRegistry registry; 031 private Predicate<String> sampleNameFilter; 032 033 /** 034 * Construct a MetricsServlet for the given registry. 035 * @param registry collector registry 036 * @param sampleNameFilter programmatically set a {@link SampleNameFilter}. 037 * If there are any filter options configured in {@code ServletConfig}, they will be merged 038 * so that samples need to pass both filters to be exported. 039 * sampleNameFilter may be {@code null} indicating that nothing should be filtered. 040 */ 041 public Exporter(CollectorRegistry registry, Predicate<String> sampleNameFilter) { 042 this.registry = registry; 043 this.sampleNameFilter = sampleNameFilter; 044 } 045 046 public void init(ServletConfigAdapter servletConfig) throws ServletConfigurationException { 047 List<String> allowedNames = SampleNameFilter.stringToList(servletConfig.getInitParameter(NAME_MUST_BE_EQUAL_TO)); 048 List<String> excludedNames = SampleNameFilter.stringToList(servletConfig.getInitParameter(NAME_MUST_NOT_BE_EQUAL_TO)); 049 List<String> allowedPrefixes = SampleNameFilter.stringToList(servletConfig.getInitParameter(NAME_MUST_START_WITH)); 050 List<String> excludedPrefixes = SampleNameFilter.stringToList(servletConfig.getInitParameter(NAME_MUST_NOT_START_WITH)); 051 if (!allowedPrefixes.isEmpty() || !excludedPrefixes.isEmpty() || !allowedNames.isEmpty() || !excludedNames.isEmpty()) { 052 SampleNameFilter filter = new SampleNameFilter.Builder() 053 .nameMustBeEqualTo(allowedNames) 054 .nameMustNotBeEqualTo(excludedNames) 055 .nameMustStartWith(allowedPrefixes) 056 .nameMustNotStartWith(excludedPrefixes) 057 .build(); 058 if (this.sampleNameFilter != null) { 059 this.sampleNameFilter = filter.and(this.sampleNameFilter); 060 } else { 061 this.sampleNameFilter = filter; 062 } 063 } 064 } 065 066 public void doGet(final HttpServletRequestAdapter req, final HttpServletResponseAdapter resp) throws IOException { 067 resp.setStatus(200); 068 String contentType = TextFormat.chooseContentType(req.getHeader("Accept")); 069 resp.setContentType(contentType); 070 071 Writer writer = new BufferedWriter(resp.getWriter()); 072 try { 073 Predicate<String> filter = SampleNameFilter.restrictToNamesEqualTo(sampleNameFilter, parse(req)); 074 if (filter == null) { 075 TextFormat.writeFormat(contentType, writer, registry.metricFamilySamples()); 076 } else { 077 TextFormat.writeFormat(contentType, writer, registry.filteredMetricFamilySamples(filter)); 078 } 079 writer.flush(); 080 } finally { 081 writer.close(); 082 } 083 } 084 085 private Set<String> parse(HttpServletRequestAdapter req) { 086 String[] includedParam = req.getParameterValues("name[]"); 087 if (includedParam == null) { 088 return Collections.emptySet(); 089 } else { 090 return new HashSet<String>(Arrays.asList(includedParam)); 091 } 092 } 093 094 public void doPost(final HttpServletRequestAdapter req, final HttpServletResponseAdapter resp) 095 throws IOException { 096 doGet(req, resp); 097 } 098}