From 3c3095a85ebb77bd2869a1dd3169bc5966c96f8a Mon Sep 17 00:00:00 2001 From: mbiscocho Date: Tue, 2 Apr 2024 13:31:57 -0400 Subject: [PATCH 01/32] Init commit for dropwizard to prometheus --- solr/core/build.gradle | 9 ++ .../java/org/apache/solr/core/SolrCore.java | 19 +--- .../solr/handler/admin/MetricsHandler.java | 101 +++++++++++++++--- .../response/PrometheusResponseWriter.java | 46 ++++++++ 4 files changed, 146 insertions(+), 29 deletions(-) create mode 100644 solr/core/src/java/org/apache/solr/response/PrometheusResponseWriter.java diff --git a/solr/core/build.gradle b/solr/core/build.gradle index 1c043353ec9..4eac5c2e9a3 100644 --- a/solr/core/build.gradle +++ b/solr/core/build.gradle @@ -153,6 +153,15 @@ dependencies { implementation 'org.apache.logging.log4j:log4j-core' runtimeOnly 'org.apache.logging.log4j:log4j-slf4j2-impl' + // Prometheus client + implementation 'io.prometheus:simpleclient' + implementation 'io.prometheus:simpleclient_common' + implementation 'io.prometheus:simpleclient_dropwizard' + implementation 'io.prometheus:prometheus-metrics-exposition-formats:1.1.0' + implementation 'io.prometheus:prometheus-metrics-simpleclient-bridge:1.1.0' + implementation 'io.prometheus:prometheus-metrics-core:1.1.0' + implementation 'io.prometheus:prometheus-metrics-instrumentation-jvm:1.1.0' + // For faster XML processing than the JDK implementation 'org.codehaus.woodstox:stax2-api' implementation 'com.fasterxml.woodstox:woodstox-core' diff --git a/solr/core/src/java/org/apache/solr/core/SolrCore.java b/solr/core/src/java/org/apache/solr/core/SolrCore.java index c72d9debc55..3179461e02f 100644 --- a/solr/core/src/java/org/apache/solr/core/SolrCore.java +++ b/solr/core/src/java/org/apache/solr/core/SolrCore.java @@ -17,6 +17,7 @@ package org.apache.solr.core; import static org.apache.solr.common.params.CommonParams.PATH; +import static org.apache.solr.handler.admin.MetricsHandler.PROMETHEUS_METRICS_WT; import com.codahale.metrics.Counter; import com.codahale.metrics.Timer; @@ -122,22 +123,7 @@ import org.apache.solr.request.SolrQueryRequest; import org.apache.solr.request.SolrRequestHandler; import org.apache.solr.request.SolrRequestInfo; -import org.apache.solr.response.BinaryResponseWriter; -import org.apache.solr.response.CSVResponseWriter; -import org.apache.solr.response.CborResponseWriter; -import org.apache.solr.response.GeoJSONResponseWriter; -import org.apache.solr.response.GraphMLResponseWriter; -import org.apache.solr.response.JacksonJsonWriter; -import org.apache.solr.response.PHPResponseWriter; -import org.apache.solr.response.PHPSerializedResponseWriter; -import org.apache.solr.response.PythonResponseWriter; -import org.apache.solr.response.QueryResponseWriter; -import org.apache.solr.response.RawResponseWriter; -import org.apache.solr.response.RubyResponseWriter; -import org.apache.solr.response.SchemaXmlResponseWriter; -import org.apache.solr.response.SmileResponseWriter; -import org.apache.solr.response.SolrQueryResponse; -import org.apache.solr.response.XMLResponseWriter; +import org.apache.solr.response.*; import org.apache.solr.response.transform.TransformerFactory; import org.apache.solr.rest.ManagedResourceStorage; import org.apache.solr.rest.ManagedResourceStorage.StorageIO; @@ -3032,6 +3018,7 @@ public PluginBag getResponseWriters() { m.put("csv", new CSVResponseWriter()); m.put("schema.xml", new SchemaXmlResponseWriter()); m.put("smile", new SmileResponseWriter()); + m.put(PROMETHEUS_METRICS_WT, new PrometheusResponseWriter()); m.put(ReplicationHandler.FILE_STREAM, getFileStreamWriter()); DEFAULT_RESPONSE_WRITERS = Collections.unmodifiableMap(m); try { diff --git a/solr/core/src/java/org/apache/solr/handler/admin/MetricsHandler.java b/solr/core/src/java/org/apache/solr/handler/admin/MetricsHandler.java index 7490278ffc8..03b820f5a8b 100644 --- a/solr/core/src/java/org/apache/solr/handler/admin/MetricsHandler.java +++ b/solr/core/src/java/org/apache/solr/handler/admin/MetricsHandler.java @@ -38,8 +38,11 @@ import java.util.function.Predicate; import java.util.regex.Pattern; import java.util.stream.Collectors; + +import io.prometheus.metrics.model.registry.PrometheusRegistry; import org.apache.solr.common.MapWriter; import org.apache.solr.common.SolrException; +import org.apache.solr.common.params.CommonParams; import org.apache.solr.common.params.SolrParams; import org.apache.solr.common.util.CommonTestInjection; import org.apache.solr.common.util.NamedList; @@ -68,6 +71,7 @@ public class MetricsHandler extends RequestHandlerBase implements PermissionName public static final String KEY_PARAM = "key"; public static final String EXPR_PARAM = "expr"; public static final String TYPE_PARAM = "type"; + public static final String PROMETHEUS_METRICS_WT = "prometheus"; public static final String ALL = "all"; @@ -117,12 +121,21 @@ public void handleRequestBody(SolrQueryRequest req, SolrQueryResponse rsp) throw } private void handleRequest(SolrParams params, BiConsumer consumer) - throws Exception { + throws Exception { + NamedList response; + if (!enabled) { consumer.accept("error", "metrics collection is disabled"); return; } boolean compact = params.getBool(COMPACT_PARAM, true); + + Set requestedRegistries = parseRegistries(params); + if (PROMETHEUS_METRICS_WT.equals(params.get(CommonParams.WT))) { + response = handlePrometheusRegistry(params, requestedRegistries); + consumer.accept("metrics", response); + return; + } String[] keys = params.getParams(KEY_PARAM); if (keys != null && keys.length > 0) { handleKeyRequest(keys, consumer); @@ -133,32 +146,94 @@ private void handleRequest(SolrParams params, BiConsumer consume handleExprRequest(exprs, consumer); return; } + + response = handleDropwizardRegistry(params, requestedRegistries); + + consumer.accept("metrics", response); + + } + + private NamedList handleDropwizardRegistry(SolrParams params, Set requestedRegistries) { + boolean compact = params.getBool(COMPACT_PARAM, true); MetricFilter mustMatchFilter = parseMustMatchFilter(params); Predicate propertyFilter = parsePropertyFilter(params); List metricTypes = parseMetricTypes(params); List metricFilters = - metricTypes.stream().map(MetricType::asMetricFilter).collect(Collectors.toList()); - Set requestedRegistries = parseRegistries(params); + metricTypes.stream().map(MetricType::asMetricFilter).collect(Collectors.toList()); + metricTypes.stream().map(MetricType::asMetricFilter).collect(Collectors.toList()); NamedList response = new SimpleOrderedMap<>(); for (String registryName : requestedRegistries) { MetricRegistry registry = metricManager.registry(registryName); SimpleOrderedMap result = new SimpleOrderedMap<>(); + MetricUtils.toMaps( - registry, - metricFilters, - mustMatchFilter, - propertyFilter, - false, - false, - compact, - false, - (k, v) -> result.add(k, v)); + registry, + metricFilters, + mustMatchFilter, + propertyFilter, + false, + false, + compact, + false, + (k, v) -> result.add(k, v)); if (result.size() > 0) { response.add(registryName, result); } } - consumer.accept("metrics", response); + return response; + } + + private NamedList handlePrometheusRegistry(SolrParams params, Set requestedRegistries) { + NamedList response = new SimpleOrderedMap<>(); + boolean compact = params.getBool(COMPACT_PARAM, true); + MetricFilter mustMatchFilter = parseMustMatchFilter(params); + Predicate propertyFilter = parsePropertyFilter(params); + List metricTypes = parseMetricTypes(params); + List metricFilters = + metricTypes.stream().map(MetricType::asMetricFilter).collect(Collectors.toList()); + for (String registryName : requestedRegistries) { + MetricRegistry dropWizardRegistry = metricManager.registry(registryName); + SimpleOrderedMap result = new SimpleOrderedMap<>(); + PrometheusRegistry prometheusRegistry = new PrometheusRegistry(); + if(registryName.equals("solr.core.demo")){ + MetricUtils.toMaps( + dropWizardRegistry, + metricFilters, + mustMatchFilter, + propertyFilter, + false, + false, + compact, + false, + (k, v) -> { + result.add(k, v); + }); + } + Map registryMap = result.asShallowMap(); + String[] splitRegistryName = registryName.split("\\."); + String coreName; + if (splitRegistryName.length == 3) { + coreName = splitRegistryName[2]; + } else if (splitRegistryName.length == 5) { + coreName = "NoCoreNameFound"; + } else { + coreName = "NoCoreNameFound"; + } + io.prometheus.metrics.core.metrics.Counter requestsTotal = io.prometheus.metrics.core.metrics.Counter.builder().name("solr_metrics_core_requests_total").help("Total number of requests to Solr").labelNames("category", "handler", "collection").register(prometheusRegistry); + for (Map.Entry entry : registryMap.entrySet()) { + String key = entry.getKey(); + Object value = entry.getValue(); + if (key.endsWith("requests")) { + String[] splitString = key.split("\\."); + if( value instanceof Long ) { + requestsTotal.labelValues(splitString[0], splitString[1], coreName).inc((long) value); + } + } + } + response.add(registryName, prometheusRegistry); + } + return response; } private static class MetricsExpr { diff --git a/solr/core/src/java/org/apache/solr/response/PrometheusResponseWriter.java b/solr/core/src/java/org/apache/solr/response/PrometheusResponseWriter.java new file mode 100644 index 00000000000..834265bdaf1 --- /dev/null +++ b/solr/core/src/java/org/apache/solr/response/PrometheusResponseWriter.java @@ -0,0 +1,46 @@ +package org.apache.solr.response; + +import io.prometheus.client.CollectorRegistry; + +import io.prometheus.metrics.expositionformats.TextFormatUtil; +import io.prometheus.metrics.model.registry.PrometheusRegistry; +import io.prometheus.metrics.model.snapshots.MetricSnapshots; +import org.apache.solr.common.SolrException; +import org.apache.solr.common.params.SolrParams; +import org.apache.solr.common.util.NamedList; +import org.apache.solr.common.util.SimpleOrderedMap; +import org.apache.solr.handler.admin.MetricsHandler; +import org.apache.solr.request.SolrQueryRequest; +import org.w3c.dom.Text; + +import java.io.IOException; +import java.io.OutputStream; +import java.io.OutputStreamWriter; +import java.io.Writer; +import java.util.Iterator; +import java.util.Map; +import java.util.Set; + +import io.prometheus.metrics.expositionformats.PrometheusTextFormatWriter; + +@SuppressWarnings (value="unchecked") +public class PrometheusResponseWriter extends RawResponseWriter { + @Override + public void write(OutputStream out, SolrQueryRequest request, SolrQueryResponse response) + throws IOException { + + NamedList prometheusRegistries = (NamedList) response.getValues().get("metrics"); + Map registryMap = prometheusRegistries.asShallowMap(); + PrometheusTextFormatWriter prometheusTextFormatWriter = new PrometheusTextFormatWriter(true); + registryMap.forEach((name, registry) -> { + try { + PrometheusRegistry prometheusRegistry = (PrometheusRegistry) registry; + prometheusTextFormatWriter.write(out, prometheusRegistry.scrape()); + } catch (IOException e) { + throw new RuntimeException(e); + } + }); + + } + +} \ No newline at end of file From b38b55ba54ecd2ad689eb7ab8556d332205fb165 Mon Sep 17 00:00:00 2001 From: mbiscocho Date: Wed, 17 Apr 2024 10:54:47 -0400 Subject: [PATCH 02/32] Expose Prometheus Metrics directly from Solr from Core registry --- solr/core/build.gradle | 8 +- .../java/org/apache/solr/core/SolrCore.java | 18 +- .../solr/handler/admin/MetricsHandler.java | 92 +++----- .../SolrPrometheusCoreRegistry.java | 93 ++++++++ .../prometheus/SolrPrometheusRegistry.java | 144 +++++++++++++ .../prometheus/core/SolrCoreCacheMetric.java | 48 +++++ .../core/SolrCoreHandlerMetric.java | 70 ++++++ .../core/SolrCoreHighlighterMetric.java | 48 +++++ .../prometheus/core/SolrCoreIndexMetric.java | 45 ++++ .../prometheus/core/SolrCoreMetric.java | 47 ++++ .../prometheus/core/SolrCoreNoOpMetric.java | 36 ++++ .../core/SolrCoreSearcherMetric.java | 59 +++++ .../prometheus/core/SolrCoreTlogMetric.java | 48 +++++ .../metrics/prometheus/core/package-info.java | 22 ++ .../solr/metrics/prometheus/package-info.java | 23 ++ .../response/PrometheusResponseWriter.java | 75 +++---- .../apache/solr/util/stats/MetricUtils.java | 54 +++++ .../prometheus-metrics-config-1.1.0.jar.sha1 | 1 + .../prometheus-metrics-config-LICENSE-ASL.txt | 201 ++++++++++++++++++ .../prometheus-metrics-config-NOTICE.txt | 11 + .../prometheus-metrics-core-1.1.0.jar.sha1 | 1 + .../prometheus-metrics-core-LICENSE-ASL.txt | 201 ++++++++++++++++++ .../prometheus-metrics-core-NOTICE.txt | 11 + ...-metrics-exposition-formats-1.1.0.jar.sha1 | 1 + ...metrics-exposition-formats-LICENSE-ASL.txt | 201 ++++++++++++++++++ ...heus-metrics-exposition-formats-NOTICE.txt | 11 + .../prometheus-metrics-model-1.1.0.jar.sha1 | 1 + .../prometheus-metrics-model-LICENSE-ASL.txt | 201 ++++++++++++++++++ .../prometheus-metrics-model-NOTICE.txt | 11 + ...eus-metrics-shaded-protobuf-1.1.0.jar.sha1 | 1 + ...us-metrics-shaded-protobuf-LICENSE-ASL.txt | 201 ++++++++++++++++++ ...metheus-metrics-shaded-protobuf-NOTICE.txt | 11 + ...theus-metrics-tracer-common-1.1.0.jar.sha1 | 1 + ...heus-metrics-tracer-common-LICENSE-ASL.txt | 201 ++++++++++++++++++ ...rometheus-metrics-tracer-common-NOTICE.txt | 11 + ...-metrics-tracer-initializer-1.1.0.jar.sha1 | 1 + ...metrics-tracer-initializer-LICENSE-ASL.txt | 201 ++++++++++++++++++ ...heus-metrics-tracer-initializer-NOTICE.txt | 11 + ...metheus-metrics-tracer-otel-1.1.0.jar.sha1 | 1 + ...etheus-metrics-tracer-otel-LICENSE-ASL.txt | 201 ++++++++++++++++++ .../prometheus-metrics-tracer-otel-NOTICE.txt | 11 + ...s-metrics-tracer-otel-agent-1.1.0.jar.sha1 | 1 + ...-metrics-tracer-otel-agent-LICENSE-ASL.txt | 201 ++++++++++++++++++ ...theus-metrics-tracer-otel-agent-NOTICE.txt | 11 + versions.lock | 9 + 45 files changed, 2753 insertions(+), 103 deletions(-) create mode 100644 solr/core/src/java/org/apache/solr/metrics/prometheus/SolrPrometheusCoreRegistry.java create mode 100644 solr/core/src/java/org/apache/solr/metrics/prometheus/SolrPrometheusRegistry.java create mode 100644 solr/core/src/java/org/apache/solr/metrics/prometheus/core/SolrCoreCacheMetric.java create mode 100644 solr/core/src/java/org/apache/solr/metrics/prometheus/core/SolrCoreHandlerMetric.java create mode 100644 solr/core/src/java/org/apache/solr/metrics/prometheus/core/SolrCoreHighlighterMetric.java create mode 100644 solr/core/src/java/org/apache/solr/metrics/prometheus/core/SolrCoreIndexMetric.java create mode 100644 solr/core/src/java/org/apache/solr/metrics/prometheus/core/SolrCoreMetric.java create mode 100644 solr/core/src/java/org/apache/solr/metrics/prometheus/core/SolrCoreNoOpMetric.java create mode 100644 solr/core/src/java/org/apache/solr/metrics/prometheus/core/SolrCoreSearcherMetric.java create mode 100644 solr/core/src/java/org/apache/solr/metrics/prometheus/core/SolrCoreTlogMetric.java create mode 100644 solr/core/src/java/org/apache/solr/metrics/prometheus/core/package-info.java create mode 100644 solr/core/src/java/org/apache/solr/metrics/prometheus/package-info.java create mode 100644 solr/licenses/prometheus-metrics-config-1.1.0.jar.sha1 create mode 100644 solr/licenses/prometheus-metrics-config-LICENSE-ASL.txt create mode 100644 solr/licenses/prometheus-metrics-config-NOTICE.txt create mode 100644 solr/licenses/prometheus-metrics-core-1.1.0.jar.sha1 create mode 100644 solr/licenses/prometheus-metrics-core-LICENSE-ASL.txt create mode 100644 solr/licenses/prometheus-metrics-core-NOTICE.txt create mode 100644 solr/licenses/prometheus-metrics-exposition-formats-1.1.0.jar.sha1 create mode 100644 solr/licenses/prometheus-metrics-exposition-formats-LICENSE-ASL.txt create mode 100644 solr/licenses/prometheus-metrics-exposition-formats-NOTICE.txt create mode 100644 solr/licenses/prometheus-metrics-model-1.1.0.jar.sha1 create mode 100644 solr/licenses/prometheus-metrics-model-LICENSE-ASL.txt create mode 100644 solr/licenses/prometheus-metrics-model-NOTICE.txt create mode 100644 solr/licenses/prometheus-metrics-shaded-protobuf-1.1.0.jar.sha1 create mode 100644 solr/licenses/prometheus-metrics-shaded-protobuf-LICENSE-ASL.txt create mode 100644 solr/licenses/prometheus-metrics-shaded-protobuf-NOTICE.txt create mode 100644 solr/licenses/prometheus-metrics-tracer-common-1.1.0.jar.sha1 create mode 100644 solr/licenses/prometheus-metrics-tracer-common-LICENSE-ASL.txt create mode 100644 solr/licenses/prometheus-metrics-tracer-common-NOTICE.txt create mode 100644 solr/licenses/prometheus-metrics-tracer-initializer-1.1.0.jar.sha1 create mode 100644 solr/licenses/prometheus-metrics-tracer-initializer-LICENSE-ASL.txt create mode 100644 solr/licenses/prometheus-metrics-tracer-initializer-NOTICE.txt create mode 100644 solr/licenses/prometheus-metrics-tracer-otel-1.1.0.jar.sha1 create mode 100644 solr/licenses/prometheus-metrics-tracer-otel-LICENSE-ASL.txt create mode 100644 solr/licenses/prometheus-metrics-tracer-otel-NOTICE.txt create mode 100644 solr/licenses/prometheus-metrics-tracer-otel-agent-1.1.0.jar.sha1 create mode 100644 solr/licenses/prometheus-metrics-tracer-otel-agent-LICENSE-ASL.txt create mode 100644 solr/licenses/prometheus-metrics-tracer-otel-agent-NOTICE.txt diff --git a/solr/core/build.gradle b/solr/core/build.gradle index 4eac5c2e9a3..a7d0df10b64 100644 --- a/solr/core/build.gradle +++ b/solr/core/build.gradle @@ -154,13 +154,9 @@ dependencies { runtimeOnly 'org.apache.logging.log4j:log4j-slf4j2-impl' // Prometheus client - implementation 'io.prometheus:simpleclient' - implementation 'io.prometheus:simpleclient_common' - implementation 'io.prometheus:simpleclient_dropwizard' - implementation 'io.prometheus:prometheus-metrics-exposition-formats:1.1.0' - implementation 'io.prometheus:prometheus-metrics-simpleclient-bridge:1.1.0' implementation 'io.prometheus:prometheus-metrics-core:1.1.0' - implementation 'io.prometheus:prometheus-metrics-instrumentation-jvm:1.1.0' + implementation 'io.prometheus:prometheus-metrics-model:1.1.0' + implementation 'io.prometheus:prometheus-metrics-exposition-formats:1.1.0' // For faster XML processing than the JDK implementation 'org.codehaus.woodstox:stax2-api' diff --git a/solr/core/src/java/org/apache/solr/core/SolrCore.java b/solr/core/src/java/org/apache/solr/core/SolrCore.java index 3179461e02f..598b41de020 100644 --- a/solr/core/src/java/org/apache/solr/core/SolrCore.java +++ b/solr/core/src/java/org/apache/solr/core/SolrCore.java @@ -123,7 +123,23 @@ import org.apache.solr.request.SolrQueryRequest; import org.apache.solr.request.SolrRequestHandler; import org.apache.solr.request.SolrRequestInfo; -import org.apache.solr.response.*; +import org.apache.solr.response.BinaryResponseWriter; +import org.apache.solr.response.CSVResponseWriter; +import org.apache.solr.response.CborResponseWriter; +import org.apache.solr.response.GeoJSONResponseWriter; +import org.apache.solr.response.GraphMLResponseWriter; +import org.apache.solr.response.JacksonJsonWriter; +import org.apache.solr.response.PHPResponseWriter; +import org.apache.solr.response.PHPSerializedResponseWriter; +import org.apache.solr.response.PrometheusResponseWriter; +import org.apache.solr.response.PythonResponseWriter; +import org.apache.solr.response.QueryResponseWriter; +import org.apache.solr.response.RawResponseWriter; +import org.apache.solr.response.RubyResponseWriter; +import org.apache.solr.response.SchemaXmlResponseWriter; +import org.apache.solr.response.SmileResponseWriter; +import org.apache.solr.response.SolrQueryResponse; +import org.apache.solr.response.XMLResponseWriter; import org.apache.solr.response.transform.TransformerFactory; import org.apache.solr.rest.ManagedResourceStorage; import org.apache.solr.rest.ManagedResourceStorage.StorageIO; diff --git a/solr/core/src/java/org/apache/solr/handler/admin/MetricsHandler.java b/solr/core/src/java/org/apache/solr/handler/admin/MetricsHandler.java index 03b820f5a8b..83e60ef0eb8 100644 --- a/solr/core/src/java/org/apache/solr/handler/admin/MetricsHandler.java +++ b/solr/core/src/java/org/apache/solr/handler/admin/MetricsHandler.java @@ -38,8 +38,6 @@ import java.util.function.Predicate; import java.util.regex.Pattern; import java.util.stream.Collectors; - -import io.prometheus.metrics.model.registry.PrometheusRegistry; import org.apache.solr.common.MapWriter; import org.apache.solr.common.SolrException; import org.apache.solr.common.params.CommonParams; @@ -121,18 +119,16 @@ public void handleRequestBody(SolrQueryRequest req, SolrQueryResponse rsp) throw } private void handleRequest(SolrParams params, BiConsumer consumer) - throws Exception { + throws Exception { NamedList response; if (!enabled) { consumer.accept("error", "metrics collection is disabled"); return; } - boolean compact = params.getBool(COMPACT_PARAM, true); - Set requestedRegistries = parseRegistries(params); if (PROMETHEUS_METRICS_WT.equals(params.get(CommonParams.WT))) { - response = handlePrometheusRegistry(params, requestedRegistries); + response = handlePrometheusRegistry(params); consumer.accept("metrics", response); return; } @@ -147,20 +143,19 @@ private void handleRequest(SolrParams params, BiConsumer consume return; } - response = handleDropwizardRegistry(params, requestedRegistries); + response = handleDropwizardRegistry(params); consumer.accept("metrics", response); - } - private NamedList handleDropwizardRegistry(SolrParams params, Set requestedRegistries) { + private NamedList handleDropwizardRegistry(SolrParams params) { boolean compact = params.getBool(COMPACT_PARAM, true); MetricFilter mustMatchFilter = parseMustMatchFilter(params); Predicate propertyFilter = parsePropertyFilter(params); List metricTypes = parseMetricTypes(params); List metricFilters = - metricTypes.stream().map(MetricType::asMetricFilter).collect(Collectors.toList()); - metricTypes.stream().map(MetricType::asMetricFilter).collect(Collectors.toList()); + metricTypes.stream().map(MetricType::asMetricFilter).collect(Collectors.toList()); + Set requestedRegistries = parseRegistries(params); NamedList response = new SimpleOrderedMap<>(); for (String registryName : requestedRegistries) { @@ -168,15 +163,15 @@ private NamedList handleDropwizardRegistry(SolrParams params, Set result = new SimpleOrderedMap<>(); MetricUtils.toMaps( - registry, - metricFilters, - mustMatchFilter, - propertyFilter, - false, - false, - compact, - false, - (k, v) -> result.add(k, v)); + registry, + metricFilters, + mustMatchFilter, + propertyFilter, + false, + false, + compact, + false, + (k, v) -> result.add(k, v)); if (result.size() > 0) { response.add(registryName, result); } @@ -184,54 +179,33 @@ private NamedList handleDropwizardRegistry(SolrParams params, Set handlePrometheusRegistry(SolrParams params, Set requestedRegistries) { + private NamedList handlePrometheusRegistry(SolrParams params) { NamedList response = new SimpleOrderedMap<>(); boolean compact = params.getBool(COMPACT_PARAM, true); MetricFilter mustMatchFilter = parseMustMatchFilter(params); Predicate propertyFilter = parsePropertyFilter(params); List metricTypes = parseMetricTypes(params); List metricFilters = - metricTypes.stream().map(MetricType::asMetricFilter).collect(Collectors.toList()); + metricTypes.stream().map(MetricType::asMetricFilter).collect(Collectors.toList()); + Set requestedRegistries = parseRegistries(params); + for (String registryName : requestedRegistries) { MetricRegistry dropWizardRegistry = metricManager.registry(registryName); - SimpleOrderedMap result = new SimpleOrderedMap<>(); - PrometheusRegistry prometheusRegistry = new PrometheusRegistry(); - if(registryName.equals("solr.core.demo")){ - MetricUtils.toMaps( - dropWizardRegistry, - metricFilters, - mustMatchFilter, - propertyFilter, - false, - false, - compact, - false, - (k, v) -> { - result.add(k, v); - }); - } - Map registryMap = result.asShallowMap(); - String[] splitRegistryName = registryName.split("\\."); - String coreName; - if (splitRegistryName.length == 3) { - coreName = splitRegistryName[2]; - } else if (splitRegistryName.length == 5) { - coreName = "NoCoreNameFound"; - } else { - coreName = "NoCoreNameFound"; - } - io.prometheus.metrics.core.metrics.Counter requestsTotal = io.prometheus.metrics.core.metrics.Counter.builder().name("solr_metrics_core_requests_total").help("Total number of requests to Solr").labelNames("category", "handler", "collection").register(prometheusRegistry); - for (Map.Entry entry : registryMap.entrySet()) { - String key = entry.getKey(); - Object value = entry.getValue(); - if (key.endsWith("requests")) { - String[] splitString = key.split("\\."); - if( value instanceof Long ) { - requestsTotal.labelValues(splitString[0], splitString[1], coreName).inc((long) value); - } - } + // Currently only export Solr Core registries + if (registryName.startsWith("solr.core")) { + MetricUtils.toPrometheusRegistry( + dropWizardRegistry, + registryName, + metricFilters, + mustMatchFilter, + propertyFilter, + false, + false, + compact, + (registry) -> { + response.add(registryName, registry); + }); } - response.add(registryName, prometheusRegistry); } return response; } diff --git a/solr/core/src/java/org/apache/solr/metrics/prometheus/SolrPrometheusCoreRegistry.java b/solr/core/src/java/org/apache/solr/metrics/prometheus/SolrPrometheusCoreRegistry.java new file mode 100644 index 00000000000..0ae8dced071 --- /dev/null +++ b/solr/core/src/java/org/apache/solr/metrics/prometheus/SolrPrometheusCoreRegistry.java @@ -0,0 +1,93 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.solr.metrics.prometheus; + +import com.codahale.metrics.Metric; +import io.prometheus.metrics.model.registry.PrometheusRegistry; +import org.apache.solr.metrics.prometheus.core.SolrCoreCacheMetric; +import org.apache.solr.metrics.prometheus.core.SolrCoreHandlerMetric; +import org.apache.solr.metrics.prometheus.core.SolrCoreHighlighterMetric; +import org.apache.solr.metrics.prometheus.core.SolrCoreIndexMetric; +import org.apache.solr.metrics.prometheus.core.SolrCoreMetric; +import org.apache.solr.metrics.prometheus.core.SolrCoreNoOpMetric; +import org.apache.solr.metrics.prometheus.core.SolrCoreSearcherMetric; +import org.apache.solr.metrics.prometheus.core.SolrCoreTlogMetric; + +public class SolrPrometheusCoreRegistry extends SolrPrometheusRegistry { + public final String coreName; + public final boolean cloudMode; + public static final String ADMIN = "ADMIN"; + public static final String QUERY = "QUERY"; + public static final String UPDATE = "UPDATE"; + public static final String REPLICATION = "REPLICATION"; + public static final String TLOG = "TLOG"; + public static final String CACHE = "CACHE"; + public static final String SEARCHER = "SEARCHER"; + public static final String HIGHLIGHTER = "HIGHLIGHTER"; + public static final String INDEX = "INDEX"; + public static final String CORE = "CORE"; + + public SolrPrometheusCoreRegistry( + PrometheusRegistry prometheusRegistry, String coreName, boolean cloudMode) { + super(prometheusRegistry); + this.coreName = coreName; + this.cloudMode = cloudMode; + } + + public void exportDropwizardMetric(String metricName, Metric dropwizardMetric) { + SolrCoreMetric solrCoreMetric = categorizeCoreMetric(dropwizardMetric, metricName); + solrCoreMetric.parseLabels().toPrometheus(this); + } + + private SolrCoreMetric categorizeCoreMetric(Metric dropwizardMetric, String metricName) { + String metricCategory = metricName.split("\\.")[0]; + switch (metricCategory) { + case ADMIN: + case QUERY: + case UPDATE: + case REPLICATION: + { + return new SolrCoreHandlerMetric(dropwizardMetric, coreName, metricName, cloudMode); + } + case TLOG: + { + return new SolrCoreTlogMetric(dropwizardMetric, coreName, metricName, cloudMode); + } + case CACHE: + { + return new SolrCoreCacheMetric(dropwizardMetric, coreName, metricName, cloudMode); + } + case SEARCHER: + { + return new SolrCoreSearcherMetric(dropwizardMetric, coreName, metricName, cloudMode); + } + case HIGHLIGHTER: + { + return new SolrCoreHighlighterMetric(dropwizardMetric, coreName, metricName, cloudMode); + } + case INDEX: + { + return new SolrCoreIndexMetric(dropwizardMetric, coreName, metricName, cloudMode); + } + case CORE: + default: + { + return new SolrCoreNoOpMetric(dropwizardMetric, coreName, metricName, cloudMode); + } + } + } +} diff --git a/solr/core/src/java/org/apache/solr/metrics/prometheus/SolrPrometheusRegistry.java b/solr/core/src/java/org/apache/solr/metrics/prometheus/SolrPrometheusRegistry.java new file mode 100644 index 00000000000..e50da37298d --- /dev/null +++ b/solr/core/src/java/org/apache/solr/metrics/prometheus/SolrPrometheusRegistry.java @@ -0,0 +1,144 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.solr.metrics.prometheus; + +import com.codahale.metrics.Meter; +import com.codahale.metrics.Timer; +import io.prometheus.metrics.core.metrics.Counter; +import io.prometheus.metrics.core.metrics.Gauge; +import io.prometheus.metrics.model.registry.PrometheusRegistry; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.Map; + +public abstract class SolrPrometheusRegistry { + PrometheusRegistry prometheusRegistry; + String registryName; + private final Map metricCounters; + private final Map metricGauges; + + public SolrPrometheusRegistry(PrometheusRegistry prometheusRegistry) { + this.prometheusRegistry = prometheusRegistry; + this.metricCounters = new HashMap<>(); + this.metricGauges = new HashMap<>(); + } + + public PrometheusRegistry getPrometheusRegistry() { + return prometheusRegistry; + } + + public String getRegistryName() { + return registryName; + } + + public void exportMeter( + Meter dropwizardMetric, String prometheusMetricName, Map labelsMap) { + if (!metricCounters.containsKey(prometheusMetricName)) { + ArrayList labels = new ArrayList<>(labelsMap.keySet()); + registerCounter(prometheusMetricName, labels.toArray(String[]::new)); + } + ArrayList labelValues = new ArrayList<>(labelsMap.values()); + getMetricCounter(prometheusMetricName) + .labelValues(labelValues.toArray(String[]::new)) + .inc(dropwizardMetric.getCount()); + } + + public void exportCounter( + com.codahale.metrics.Counter dropwizardMetric, + String prometheusMetricName, + Map labelsMap) { + if (!metricCounters.containsKey(prometheusMetricName)) { + ArrayList labels = new ArrayList<>(labelsMap.keySet()); + registerCounter(prometheusMetricName, labels.toArray(String[]::new)); + } + ArrayList labelValues = new ArrayList<>(labelsMap.values()); + getMetricCounter(prometheusMetricName) + .labelValues(labelValues.toArray(String[]::new)) + .inc(dropwizardMetric.getCount()); + } + + public void exportTimer( + Timer dropwizardMetric, String prometheusMetricName, Map labelsMap) { + if (!metricCounters.containsKey(prometheusMetricName)) { + ArrayList labels = new ArrayList<>(labelsMap.keySet()); + registerGauge(prometheusMetricName, labels.toArray(String[]::new)); + } + ArrayList labelValues = new ArrayList<>(labelsMap.values()); + getMetricGauge(prometheusMetricName) + .labelValues(labelValues.toArray(String[]::new)) + .set(dropwizardMetric.getMeanRate()); + } + + public void exportGauge( + com.codahale.metrics.Gauge dropwizardMetricRaw, + String prometheusMetricName, + Map labelsMap) { + Object dropwizardMetric = (dropwizardMetricRaw).getValue(); + if (!metricGauges.containsKey(prometheusMetricName)) { + ArrayList labels = new ArrayList<>(labelsMap.keySet()); + if (dropwizardMetric instanceof HashMap) { + labels.add("item"); + } + registerGauge(prometheusMetricName, labels.toArray(String[]::new)); + } + ArrayList labelValues = new ArrayList<>(labelsMap.values()); + String[] labels = labelValues.toArray(String[]::new); + if (dropwizardMetric instanceof Number) { + getMetricGauge(prometheusMetricName) + .labelValues(labels) + .set(((Number) dropwizardMetric).doubleValue()); + } else if (dropwizardMetric instanceof HashMap) { + HashMap itemsMap = (HashMap) dropwizardMetric; + for (Object item : itemsMap.keySet()) { + if (itemsMap.get(item) instanceof Number) { + String[] newLabels = new String[labels.length + 1]; + System.arraycopy(labels, 0, newLabels, 0, labels.length); + newLabels[labels.length] = (String) item; + getMetricGauge(prometheusMetricName) + .labelValues(newLabels) + .set(((Number) itemsMap.get(item)).doubleValue()); + } + } + } + } + + private Counter getMetricCounter(String metricName) { + return metricCounters.get(metricName); + } + + private Gauge getMetricGauge(String metricName) { + return metricGauges.get(metricName); + } + + private void registerCounter(String metricName, String... labelNames) { + Counter counter = + io.prometheus.metrics.core.metrics.Counter.builder() + .name(metricName) + .labelNames(labelNames) + .register(prometheusRegistry); + metricCounters.put(metricName, counter); + } + + private void registerGauge(String metricName, String... labelNames) { + Gauge gauge = + io.prometheus.metrics.core.metrics.Gauge.builder() + .name(metricName) + .labelNames(labelNames) + .register(prometheusRegistry); + metricGauges.put(metricName, gauge); + } +} diff --git a/solr/core/src/java/org/apache/solr/metrics/prometheus/core/SolrCoreCacheMetric.java b/solr/core/src/java/org/apache/solr/metrics/prometheus/core/SolrCoreCacheMetric.java new file mode 100644 index 00000000000..46064bf366b --- /dev/null +++ b/solr/core/src/java/org/apache/solr/metrics/prometheus/core/SolrCoreCacheMetric.java @@ -0,0 +1,48 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.solr.metrics.prometheus.core; + +import com.codahale.metrics.Gauge; +import com.codahale.metrics.Metric; +import org.apache.solr.metrics.prometheus.SolrPrometheusCoreRegistry; + +public class SolrCoreCacheMetric extends SolrCoreMetric { + public static final String CORE_CACHE_SEARCHER_METRICS = "solr_metrics_core_cache"; + + public SolrCoreCacheMetric( + Metric dropwizardMetric, String coreName, String metricName, boolean cloudMode) { + super(dropwizardMetric, coreName, metricName, cloudMode); + } + + @Override + public SolrCoreMetric parseLabels() { + String[] parsedMetric = metricName.split("\\."); + if (dropwizardMetric instanceof Gauge) { + String cacheType = parsedMetric[2]; + labels.put("cacheType", cacheType); + } + return this; + } + + @Override + public void toPrometheus(SolrPrometheusCoreRegistry solrPrometheusCoreRegistry) { + if (dropwizardMetric instanceof Gauge) { + solrPrometheusCoreRegistry.exportGauge( + (Gauge) dropwizardMetric, CORE_CACHE_SEARCHER_METRICS, labels); + } + } +} diff --git a/solr/core/src/java/org/apache/solr/metrics/prometheus/core/SolrCoreHandlerMetric.java b/solr/core/src/java/org/apache/solr/metrics/prometheus/core/SolrCoreHandlerMetric.java new file mode 100644 index 00000000000..f9247da4d6b --- /dev/null +++ b/solr/core/src/java/org/apache/solr/metrics/prometheus/core/SolrCoreHandlerMetric.java @@ -0,0 +1,70 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.solr.metrics.prometheus.core; + +import com.codahale.metrics.Counter; +import com.codahale.metrics.Gauge; +import com.codahale.metrics.Meter; +import com.codahale.metrics.Metric; +import com.codahale.metrics.Timer; +import org.apache.solr.metrics.prometheus.SolrPrometheusCoreRegistry; + +public class SolrCoreHandlerMetric extends SolrCoreMetric { + public static final String CORE_REQUESTS_TOTAL = "solr_metrics_core_requests"; + public static final String CORE_REQUESTS_UPDATE_HANDLER = "solr_metrics_core_update_handler"; + public static final String CORE_REQUESTS_TOTAL_TIME = "solr_metrics_core_requests_time"; + public static final String CORE_REQUEST_TIMES = "solr_metrics_core_average_request_time"; + + public SolrCoreHandlerMetric( + Metric dropwizardMetric, String coreName, String metricName, boolean cloudMode) { + super(dropwizardMetric, coreName, metricName, cloudMode); + } + + @Override + public SolrCoreMetric parseLabels() { + String[] parsedMetric = metricName.split("\\."); + String category = parsedMetric[0]; + String handler = parsedMetric[1]; + String type = parsedMetric[2]; + labels.put("category", category); + labels.put("type", type); + if (!(dropwizardMetric instanceof Gauge)) { + labels.put("handler", handler); + } + return this; + } + + @Override + public void toPrometheus(SolrPrometheusCoreRegistry solrPrometheusCoreRegistry) { + if (dropwizardMetric instanceof Meter) { + solrPrometheusCoreRegistry.exportMeter((Meter) dropwizardMetric, CORE_REQUESTS_TOTAL, labels); + } else if (dropwizardMetric instanceof Counter) { + if (metricName.endsWith("requests")) { + solrPrometheusCoreRegistry.exportCounter( + (Counter) dropwizardMetric, CORE_REQUESTS_TOTAL, labels); + } else if (metricName.endsWith("totalTime")) { + solrPrometheusCoreRegistry.exportCounter( + (Counter) dropwizardMetric, CORE_REQUESTS_TOTAL_TIME, labels); + } + } else if (dropwizardMetric instanceof Gauge) { + solrPrometheusCoreRegistry.exportGauge( + (Gauge) dropwizardMetric, CORE_REQUESTS_UPDATE_HANDLER, labels); + } else if (dropwizardMetric instanceof Timer) { + solrPrometheusCoreRegistry.exportTimer((Timer) dropwizardMetric, CORE_REQUEST_TIMES, labels); + } + } +} diff --git a/solr/core/src/java/org/apache/solr/metrics/prometheus/core/SolrCoreHighlighterMetric.java b/solr/core/src/java/org/apache/solr/metrics/prometheus/core/SolrCoreHighlighterMetric.java new file mode 100644 index 00000000000..742c580d2db --- /dev/null +++ b/solr/core/src/java/org/apache/solr/metrics/prometheus/core/SolrCoreHighlighterMetric.java @@ -0,0 +1,48 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.solr.metrics.prometheus.core; + +import com.codahale.metrics.Counter; +import com.codahale.metrics.Metric; +import org.apache.solr.metrics.prometheus.SolrPrometheusCoreRegistry; + +public class SolrCoreHighlighterMetric extends SolrCoreMetric { + public static final String CORE_HIGHLIGHER_METRICS = "solr_metrics_core_highlighter_requests"; + + public SolrCoreHighlighterMetric( + Metric dropwizardMetric, String coreName, String metricName, boolean cloudMode) { + super(dropwizardMetric, coreName, metricName, cloudMode); + } + + @Override + public SolrCoreMetric parseLabels() { + String[] parsedMetric = metricName.split("\\."); + String type = parsedMetric[1]; + String item = parsedMetric[2]; + labels.put("type", type); + labels.put("item", item); + return this; + } + + @Override + public void toPrometheus(SolrPrometheusCoreRegistry solrPrometheusCoreRegistry) { + if (dropwizardMetric instanceof Counter) { + solrPrometheusCoreRegistry.exportCounter( + (Counter) dropwizardMetric, CORE_HIGHLIGHER_METRICS, labels); + } + } +} diff --git a/solr/core/src/java/org/apache/solr/metrics/prometheus/core/SolrCoreIndexMetric.java b/solr/core/src/java/org/apache/solr/metrics/prometheus/core/SolrCoreIndexMetric.java new file mode 100644 index 00000000000..54e582152a7 --- /dev/null +++ b/solr/core/src/java/org/apache/solr/metrics/prometheus/core/SolrCoreIndexMetric.java @@ -0,0 +1,45 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.solr.metrics.prometheus.core; + +import com.codahale.metrics.Gauge; +import com.codahale.metrics.Metric; +import org.apache.solr.metrics.prometheus.SolrPrometheusCoreRegistry; + +public class SolrCoreIndexMetric extends SolrCoreMetric { + public static final String CORE_INDEX_METRICS = "solr_metrics_core_index_size_bytes"; + + public SolrCoreIndexMetric( + Metric dropwizardMetric, String coreName, String metricName, boolean cloudMode) { + super(dropwizardMetric, coreName, metricName, cloudMode); + } + + @Override + public SolrCoreMetric parseLabels() { + return this; + } + + @Override + public void toPrometheus(SolrPrometheusCoreRegistry solrPrometheusCoreRegistry) { + if (dropwizardMetric instanceof Gauge) { + if (metricName.endsWith("sizeInBytes")) { + solrPrometheusCoreRegistry.exportGauge( + (Gauge) dropwizardMetric, CORE_INDEX_METRICS, labels); + } + } + } +} diff --git a/solr/core/src/java/org/apache/solr/metrics/prometheus/core/SolrCoreMetric.java b/solr/core/src/java/org/apache/solr/metrics/prometheus/core/SolrCoreMetric.java new file mode 100644 index 00000000000..08bdd63c4d0 --- /dev/null +++ b/solr/core/src/java/org/apache/solr/metrics/prometheus/core/SolrCoreMetric.java @@ -0,0 +1,47 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.solr.metrics.prometheus.core; + +import com.codahale.metrics.Metric; +import java.util.HashMap; +import java.util.Map; +import org.apache.solr.metrics.prometheus.SolrPrometheusCoreRegistry; + +public abstract class SolrCoreMetric { + public Metric dropwizardMetric; + public String coreName; + public String metricName; + public Map labels = new HashMap<>(); + + public SolrCoreMetric( + Metric dropwizardMetric, String coreName, String metricName, boolean cloudMode) { + this.dropwizardMetric = dropwizardMetric; + this.coreName = coreName; + this.metricName = metricName; + labels.put("core", coreName); + if (cloudMode) { + String[] coreNameParsed = coreName.split("_"); + labels.put("collection", coreNameParsed[1]); + labels.put("shard", coreNameParsed[2]); + labels.put("replica", coreNameParsed[3] + "_" + coreNameParsed[4]); + } + } + + public abstract SolrCoreMetric parseLabels(); + + public abstract void toPrometheus(SolrPrometheusCoreRegistry solrPrometheusCoreRegistry); +} diff --git a/solr/core/src/java/org/apache/solr/metrics/prometheus/core/SolrCoreNoOpMetric.java b/solr/core/src/java/org/apache/solr/metrics/prometheus/core/SolrCoreNoOpMetric.java new file mode 100644 index 00000000000..6d22b6f8255 --- /dev/null +++ b/solr/core/src/java/org/apache/solr/metrics/prometheus/core/SolrCoreNoOpMetric.java @@ -0,0 +1,36 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.solr.metrics.prometheus.core; + +import com.codahale.metrics.Metric; +import org.apache.solr.metrics.prometheus.SolrPrometheusCoreRegistry; + +public class SolrCoreNoOpMetric extends SolrCoreMetric { + + public SolrCoreNoOpMetric( + Metric dropwizardMetric, String coreName, String metricName, boolean cloudMode) { + super(dropwizardMetric, coreName, metricName, cloudMode); + } + + @Override + public SolrCoreMetric parseLabels() { + return this; + } + + @Override + public void toPrometheus(SolrPrometheusCoreRegistry solrPrometheusCoreRegistry) {} +} diff --git a/solr/core/src/java/org/apache/solr/metrics/prometheus/core/SolrCoreSearcherMetric.java b/solr/core/src/java/org/apache/solr/metrics/prometheus/core/SolrCoreSearcherMetric.java new file mode 100644 index 00000000000..ec47e93432a --- /dev/null +++ b/solr/core/src/java/org/apache/solr/metrics/prometheus/core/SolrCoreSearcherMetric.java @@ -0,0 +1,59 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.solr.metrics.prometheus.core; + +import static org.apache.solr.metrics.prometheus.core.SolrCoreCacheMetric.CORE_CACHE_SEARCHER_METRICS; + +import com.codahale.metrics.Gauge; +import com.codahale.metrics.Metric; +import com.codahale.metrics.Timer; +import org.apache.solr.metrics.prometheus.SolrPrometheusCoreRegistry; + +public class SolrCoreSearcherMetric extends SolrCoreMetric { + public static final String CORE_SEARCHER_METRICS = "solr_metrics_core_searcher_documents"; + public static final String CORE_SEARCHER_TIMES = "solr_metrics_core_average_searcher_warmup_time"; + + public SolrCoreSearcherMetric( + Metric dropwizardMetric, String coreName, String metricName, boolean cloudMode) { + super(dropwizardMetric, coreName, metricName, cloudMode); + } + + @Override + public SolrCoreMetric parseLabels() { + String[] parsedMetric = metricName.split("\\."); + if (dropwizardMetric instanceof Gauge) { + String type = parsedMetric[2]; + labels.put("type", type); + } + return this; + } + + @Override + public void toPrometheus(SolrPrometheusCoreRegistry solrPrometheusCoreRegistry) { + if (dropwizardMetric instanceof Gauge) { + if (metricName.endsWith("liveDocsCache")) { + solrPrometheusCoreRegistry.exportGauge( + (Gauge) dropwizardMetric, CORE_CACHE_SEARCHER_METRICS, labels); + } else { + solrPrometheusCoreRegistry.exportGauge( + (Gauge) dropwizardMetric, CORE_SEARCHER_METRICS, labels); + } + } else if (dropwizardMetric instanceof Timer) { + solrPrometheusCoreRegistry.exportTimer((Timer) dropwizardMetric, CORE_SEARCHER_TIMES, labels); + } + } +} diff --git a/solr/core/src/java/org/apache/solr/metrics/prometheus/core/SolrCoreTlogMetric.java b/solr/core/src/java/org/apache/solr/metrics/prometheus/core/SolrCoreTlogMetric.java new file mode 100644 index 00000000000..86eb7b08a8e --- /dev/null +++ b/solr/core/src/java/org/apache/solr/metrics/prometheus/core/SolrCoreTlogMetric.java @@ -0,0 +1,48 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.solr.metrics.prometheus.core; + +import com.codahale.metrics.Meter; +import com.codahale.metrics.Metric; +import org.apache.solr.metrics.prometheus.SolrPrometheusCoreRegistry; + +public class SolrCoreTlogMetric extends SolrCoreMetric { + public static final String CORE_TLOG_METRICS = "solr_metrics_core_tlog"; + + public SolrCoreTlogMetric( + Metric dropwizardMetric, String coreName, String metricName, boolean cloudMode) { + super(dropwizardMetric, coreName, metricName, cloudMode); + } + + @Override + public SolrCoreMetric parseLabels() { + String[] parsedMetric = metricName.split("\\."); + if (dropwizardMetric instanceof Meter) { + String item = parsedMetric[1]; + String type = parsedMetric[2]; + labels.put("item", item); + } + return this; + } + + @Override + public void toPrometheus(SolrPrometheusCoreRegistry solrPrometheusCoreRegistry) { + if (dropwizardMetric instanceof Meter) { + solrPrometheusCoreRegistry.exportMeter((Meter) dropwizardMetric, CORE_TLOG_METRICS, labels); + } + } +} diff --git a/solr/core/src/java/org/apache/solr/metrics/prometheus/core/package-info.java b/solr/core/src/java/org/apache/solr/metrics/prometheus/core/package-info.java new file mode 100644 index 00000000000..8d0cb5a569f --- /dev/null +++ b/solr/core/src/java/org/apache/solr/metrics/prometheus/core/package-info.java @@ -0,0 +1,22 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * The {@link org.apache.solr.metrics.prometheus.core.SolrCoreMetric} is a wrapper to export {@link + * com.codahale.metrics.Metric} to {@link io.prometheus.metrics.core.metrics.Metric} + */ +package org.apache.solr.metrics.prometheus.core; diff --git a/solr/core/src/java/org/apache/solr/metrics/prometheus/package-info.java b/solr/core/src/java/org/apache/solr/metrics/prometheus/package-info.java new file mode 100644 index 00000000000..384d0c42bc4 --- /dev/null +++ b/solr/core/src/java/org/apache/solr/metrics/prometheus/package-info.java @@ -0,0 +1,23 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * The {@link org.apache.solr.metrics.prometheus.SolrPrometheusRegistry} is responsible for + * collecting Prometheus metrics from exporting {@link com.codahale.metrics.Metric}'s from {@link + * com.codahale.metrics.MetricRegistry} + */ +package org.apache.solr.metrics.prometheus; diff --git a/solr/core/src/java/org/apache/solr/response/PrometheusResponseWriter.java b/solr/core/src/java/org/apache/solr/response/PrometheusResponseWriter.java index 834265bdaf1..869e0575630 100644 --- a/solr/core/src/java/org/apache/solr/response/PrometheusResponseWriter.java +++ b/solr/core/src/java/org/apache/solr/response/PrometheusResponseWriter.java @@ -1,46 +1,47 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ package org.apache.solr.response; -import io.prometheus.client.CollectorRegistry; - -import io.prometheus.metrics.expositionformats.TextFormatUtil; +import io.prometheus.metrics.expositionformats.PrometheusTextFormatWriter; import io.prometheus.metrics.model.registry.PrometheusRegistry; -import io.prometheus.metrics.model.snapshots.MetricSnapshots; -import org.apache.solr.common.SolrException; -import org.apache.solr.common.params.SolrParams; -import org.apache.solr.common.util.NamedList; -import org.apache.solr.common.util.SimpleOrderedMap; -import org.apache.solr.handler.admin.MetricsHandler; -import org.apache.solr.request.SolrQueryRequest; -import org.w3c.dom.Text; - import java.io.IOException; import java.io.OutputStream; -import java.io.OutputStreamWriter; -import java.io.Writer; -import java.util.Iterator; import java.util.Map; -import java.util.Set; - -import io.prometheus.metrics.expositionformats.PrometheusTextFormatWriter; +import org.apache.solr.common.util.NamedList; +import org.apache.solr.request.SolrQueryRequest; -@SuppressWarnings (value="unchecked") +@SuppressWarnings(value = "unchecked") public class PrometheusResponseWriter extends RawResponseWriter { - @Override - public void write(OutputStream out, SolrQueryRequest request, SolrQueryResponse response) - throws IOException { - - NamedList prometheusRegistries = (NamedList) response.getValues().get("metrics"); - Map registryMap = prometheusRegistries.asShallowMap(); - PrometheusTextFormatWriter prometheusTextFormatWriter = new PrometheusTextFormatWriter(true); - registryMap.forEach((name, registry) -> { - try { - PrometheusRegistry prometheusRegistry = (PrometheusRegistry) registry; - prometheusTextFormatWriter.write(out, prometheusRegistry.scrape()); - } catch (IOException e) { - throw new RuntimeException(e); - } + @Override + public void write(OutputStream out, SolrQueryRequest request, SolrQueryResponse response) + throws IOException { + + NamedList prometheusRegistries = + (NamedList) response.getValues().get("metrics"); + Map registryMap = prometheusRegistries.asShallowMap(); + PrometheusTextFormatWriter prometheusTextFormatWriter = new PrometheusTextFormatWriter(false); + registryMap.forEach( + (name, registry) -> { + try { + PrometheusRegistry prometheusRegistry = (PrometheusRegistry) registry; + prometheusTextFormatWriter.write(out, prometheusRegistry.scrape()); + } catch (IOException e) { + throw new RuntimeException(e); + } }); - - } - -} \ No newline at end of file + } +} diff --git a/solr/core/src/java/org/apache/solr/util/stats/MetricUtils.java b/solr/core/src/java/org/apache/solr/util/stats/MetricUtils.java index 1e14ae452fa..2e0bdfc51ad 100644 --- a/solr/core/src/java/org/apache/solr/util/stats/MetricUtils.java +++ b/solr/core/src/java/org/apache/solr/util/stats/MetricUtils.java @@ -26,6 +26,7 @@ import com.codahale.metrics.MetricRegistry; import com.codahale.metrics.Snapshot; import com.codahale.metrics.Timer; +import io.prometheus.metrics.model.registry.PrometheusRegistry; import java.beans.BeanInfo; import java.beans.IntrospectionException; import java.beans.Introspector; @@ -35,6 +36,8 @@ import java.lang.management.OperatingSystemMXBean; import java.lang.management.PlatformManagedObject; import java.lang.reflect.InvocationTargetException; +import java.util.ArrayList; +import java.util.Arrays; import java.util.Collection; import java.util.HashMap; import java.util.List; @@ -45,6 +48,7 @@ import java.util.function.BiConsumer; import java.util.function.Consumer; import java.util.function.Predicate; +import java.util.stream.Collectors; import org.apache.solr.common.ConditionalKeyMapWriter; import org.apache.solr.common.IteratorWriter; import org.apache.solr.common.MapWriter; @@ -53,6 +57,7 @@ import org.apache.solr.core.SolrInfoBean; import org.apache.solr.metrics.AggregateMetric; import org.apache.solr.metrics.SolrMetricManager; +import org.apache.solr.metrics.prometheus.SolrPrometheusCoreRegistry; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -165,6 +170,55 @@ public static void toSolrInputDocuments( }); } + public static void toPrometheusRegistry( + MetricRegistry registry, + String registryName, + List shouldMatchFilters, + MetricFilter mustMatchFilter, + Predicate propertyFilter, + boolean skipHistograms, + boolean skipAggregateValues, + boolean compact, + Consumer consumer) { + String coreName; + boolean cloudMode = false; + Map dropwizardMetrics = registry.getMetrics(); + String[] rawParsedRegistry = registryName.split("\\."); + List parsedRegistry = new ArrayList<>(Arrays.asList(rawParsedRegistry)); + + if (parsedRegistry.size() == 3) { + coreName = parsedRegistry.get(2); + } else if (parsedRegistry.size() == 5) { + coreName = parsedRegistry.stream().skip(1).collect(Collectors.joining("_")); + cloudMode = true; + } else { + coreName = registryName; + } + + SolrPrometheusCoreRegistry solrPrometheusCoreMetrics = + new SolrPrometheusCoreRegistry(new PrometheusRegistry(), coreName, cloudMode); + + toMaps( + registry, + shouldMatchFilters, + mustMatchFilter, + propertyFilter, + skipHistograms, + skipAggregateValues, + compact, + false, + (metricName, metric) -> { + try { + Metric dropwizardMetric = dropwizardMetrics.get(metricName); + solrPrometheusCoreMetrics.exportDropwizardMetric(metricName, dropwizardMetric); + } catch (Exception e) { + // Do not fail entirely for metrics exporting. Log and try to export next metric + log.warn("Error occurred exporting Dropwizard Metric to Prometheus", e); + } + }); + consumer.accept(solrPrometheusCoreMetrics.getPrometheusRegistry()); + } + /** * Fill in a SolrInputDocument with values from a converted metric, recursively. * diff --git a/solr/licenses/prometheus-metrics-config-1.1.0.jar.sha1 b/solr/licenses/prometheus-metrics-config-1.1.0.jar.sha1 new file mode 100644 index 00000000000..954a48dcf64 --- /dev/null +++ b/solr/licenses/prometheus-metrics-config-1.1.0.jar.sha1 @@ -0,0 +1 @@ +4588ed1d1bbdcebb2663ccef1162f4cc4c5eb9fb diff --git a/solr/licenses/prometheus-metrics-config-LICENSE-ASL.txt b/solr/licenses/prometheus-metrics-config-LICENSE-ASL.txt new file mode 100644 index 00000000000..f49a4e16e68 --- /dev/null +++ b/solr/licenses/prometheus-metrics-config-LICENSE-ASL.txt @@ -0,0 +1,201 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. \ No newline at end of file diff --git a/solr/licenses/prometheus-metrics-config-NOTICE.txt b/solr/licenses/prometheus-metrics-config-NOTICE.txt new file mode 100644 index 00000000000..cbd3cd95bef --- /dev/null +++ b/solr/licenses/prometheus-metrics-config-NOTICE.txt @@ -0,0 +1,11 @@ +Prometheus instrumentation library for JVM applications +Copyright 2012-2015 The Prometheus Authors + +This product includes software developed at +Boxever Ltd. (http://www.boxever.com/). + +This product includes software developed at +SoundCloud Ltd. (http://soundcloud.com/). + +This product includes software developed as part of the +Ocelli project by Netflix Inc. (https://github.com/Netflix/ocelli/). \ No newline at end of file diff --git a/solr/licenses/prometheus-metrics-core-1.1.0.jar.sha1 b/solr/licenses/prometheus-metrics-core-1.1.0.jar.sha1 new file mode 100644 index 00000000000..aefaedc39a6 --- /dev/null +++ b/solr/licenses/prometheus-metrics-core-1.1.0.jar.sha1 @@ -0,0 +1 @@ +b25424c069a44fce42b55626512718d49c9dcc5d diff --git a/solr/licenses/prometheus-metrics-core-LICENSE-ASL.txt b/solr/licenses/prometheus-metrics-core-LICENSE-ASL.txt new file mode 100644 index 00000000000..f49a4e16e68 --- /dev/null +++ b/solr/licenses/prometheus-metrics-core-LICENSE-ASL.txt @@ -0,0 +1,201 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. \ No newline at end of file diff --git a/solr/licenses/prometheus-metrics-core-NOTICE.txt b/solr/licenses/prometheus-metrics-core-NOTICE.txt new file mode 100644 index 00000000000..cbd3cd95bef --- /dev/null +++ b/solr/licenses/prometheus-metrics-core-NOTICE.txt @@ -0,0 +1,11 @@ +Prometheus instrumentation library for JVM applications +Copyright 2012-2015 The Prometheus Authors + +This product includes software developed at +Boxever Ltd. (http://www.boxever.com/). + +This product includes software developed at +SoundCloud Ltd. (http://soundcloud.com/). + +This product includes software developed as part of the +Ocelli project by Netflix Inc. (https://github.com/Netflix/ocelli/). \ No newline at end of file diff --git a/solr/licenses/prometheus-metrics-exposition-formats-1.1.0.jar.sha1 b/solr/licenses/prometheus-metrics-exposition-formats-1.1.0.jar.sha1 new file mode 100644 index 00000000000..60b2586d867 --- /dev/null +++ b/solr/licenses/prometheus-metrics-exposition-formats-1.1.0.jar.sha1 @@ -0,0 +1 @@ +466f12bdde0dcb5b5469d1bd01370db7b62bead3 diff --git a/solr/licenses/prometheus-metrics-exposition-formats-LICENSE-ASL.txt b/solr/licenses/prometheus-metrics-exposition-formats-LICENSE-ASL.txt new file mode 100644 index 00000000000..f49a4e16e68 --- /dev/null +++ b/solr/licenses/prometheus-metrics-exposition-formats-LICENSE-ASL.txt @@ -0,0 +1,201 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. \ No newline at end of file diff --git a/solr/licenses/prometheus-metrics-exposition-formats-NOTICE.txt b/solr/licenses/prometheus-metrics-exposition-formats-NOTICE.txt new file mode 100644 index 00000000000..cbd3cd95bef --- /dev/null +++ b/solr/licenses/prometheus-metrics-exposition-formats-NOTICE.txt @@ -0,0 +1,11 @@ +Prometheus instrumentation library for JVM applications +Copyright 2012-2015 The Prometheus Authors + +This product includes software developed at +Boxever Ltd. (http://www.boxever.com/). + +This product includes software developed at +SoundCloud Ltd. (http://soundcloud.com/). + +This product includes software developed as part of the +Ocelli project by Netflix Inc. (https://github.com/Netflix/ocelli/). \ No newline at end of file diff --git a/solr/licenses/prometheus-metrics-model-1.1.0.jar.sha1 b/solr/licenses/prometheus-metrics-model-1.1.0.jar.sha1 new file mode 100644 index 00000000000..6cac482dd0c --- /dev/null +++ b/solr/licenses/prometheus-metrics-model-1.1.0.jar.sha1 @@ -0,0 +1 @@ +4a6093076e5b526aff26611e6c4f0eb4518211b3 diff --git a/solr/licenses/prometheus-metrics-model-LICENSE-ASL.txt b/solr/licenses/prometheus-metrics-model-LICENSE-ASL.txt new file mode 100644 index 00000000000..f49a4e16e68 --- /dev/null +++ b/solr/licenses/prometheus-metrics-model-LICENSE-ASL.txt @@ -0,0 +1,201 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. \ No newline at end of file diff --git a/solr/licenses/prometheus-metrics-model-NOTICE.txt b/solr/licenses/prometheus-metrics-model-NOTICE.txt new file mode 100644 index 00000000000..cbd3cd95bef --- /dev/null +++ b/solr/licenses/prometheus-metrics-model-NOTICE.txt @@ -0,0 +1,11 @@ +Prometheus instrumentation library for JVM applications +Copyright 2012-2015 The Prometheus Authors + +This product includes software developed at +Boxever Ltd. (http://www.boxever.com/). + +This product includes software developed at +SoundCloud Ltd. (http://soundcloud.com/). + +This product includes software developed as part of the +Ocelli project by Netflix Inc. (https://github.com/Netflix/ocelli/). \ No newline at end of file diff --git a/solr/licenses/prometheus-metrics-shaded-protobuf-1.1.0.jar.sha1 b/solr/licenses/prometheus-metrics-shaded-protobuf-1.1.0.jar.sha1 new file mode 100644 index 00000000000..c593438438d --- /dev/null +++ b/solr/licenses/prometheus-metrics-shaded-protobuf-1.1.0.jar.sha1 @@ -0,0 +1 @@ +5a18603c6281609b0e9e1e7f21d647c6ce994adb diff --git a/solr/licenses/prometheus-metrics-shaded-protobuf-LICENSE-ASL.txt b/solr/licenses/prometheus-metrics-shaded-protobuf-LICENSE-ASL.txt new file mode 100644 index 00000000000..f49a4e16e68 --- /dev/null +++ b/solr/licenses/prometheus-metrics-shaded-protobuf-LICENSE-ASL.txt @@ -0,0 +1,201 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. \ No newline at end of file diff --git a/solr/licenses/prometheus-metrics-shaded-protobuf-NOTICE.txt b/solr/licenses/prometheus-metrics-shaded-protobuf-NOTICE.txt new file mode 100644 index 00000000000..cbd3cd95bef --- /dev/null +++ b/solr/licenses/prometheus-metrics-shaded-protobuf-NOTICE.txt @@ -0,0 +1,11 @@ +Prometheus instrumentation library for JVM applications +Copyright 2012-2015 The Prometheus Authors + +This product includes software developed at +Boxever Ltd. (http://www.boxever.com/). + +This product includes software developed at +SoundCloud Ltd. (http://soundcloud.com/). + +This product includes software developed as part of the +Ocelli project by Netflix Inc. (https://github.com/Netflix/ocelli/). \ No newline at end of file diff --git a/solr/licenses/prometheus-metrics-tracer-common-1.1.0.jar.sha1 b/solr/licenses/prometheus-metrics-tracer-common-1.1.0.jar.sha1 new file mode 100644 index 00000000000..942ecf85c06 --- /dev/null +++ b/solr/licenses/prometheus-metrics-tracer-common-1.1.0.jar.sha1 @@ -0,0 +1 @@ +daf7dbdb867221e418be0771663eae50a9199228 diff --git a/solr/licenses/prometheus-metrics-tracer-common-LICENSE-ASL.txt b/solr/licenses/prometheus-metrics-tracer-common-LICENSE-ASL.txt new file mode 100644 index 00000000000..f49a4e16e68 --- /dev/null +++ b/solr/licenses/prometheus-metrics-tracer-common-LICENSE-ASL.txt @@ -0,0 +1,201 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. \ No newline at end of file diff --git a/solr/licenses/prometheus-metrics-tracer-common-NOTICE.txt b/solr/licenses/prometheus-metrics-tracer-common-NOTICE.txt new file mode 100644 index 00000000000..cbd3cd95bef --- /dev/null +++ b/solr/licenses/prometheus-metrics-tracer-common-NOTICE.txt @@ -0,0 +1,11 @@ +Prometheus instrumentation library for JVM applications +Copyright 2012-2015 The Prometheus Authors + +This product includes software developed at +Boxever Ltd. (http://www.boxever.com/). + +This product includes software developed at +SoundCloud Ltd. (http://soundcloud.com/). + +This product includes software developed as part of the +Ocelli project by Netflix Inc. (https://github.com/Netflix/ocelli/). \ No newline at end of file diff --git a/solr/licenses/prometheus-metrics-tracer-initializer-1.1.0.jar.sha1 b/solr/licenses/prometheus-metrics-tracer-initializer-1.1.0.jar.sha1 new file mode 100644 index 00000000000..f308f25736c --- /dev/null +++ b/solr/licenses/prometheus-metrics-tracer-initializer-1.1.0.jar.sha1 @@ -0,0 +1 @@ +169f3dae0c95b4154696407de0e1213373f074e1 diff --git a/solr/licenses/prometheus-metrics-tracer-initializer-LICENSE-ASL.txt b/solr/licenses/prometheus-metrics-tracer-initializer-LICENSE-ASL.txt new file mode 100644 index 00000000000..f49a4e16e68 --- /dev/null +++ b/solr/licenses/prometheus-metrics-tracer-initializer-LICENSE-ASL.txt @@ -0,0 +1,201 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. \ No newline at end of file diff --git a/solr/licenses/prometheus-metrics-tracer-initializer-NOTICE.txt b/solr/licenses/prometheus-metrics-tracer-initializer-NOTICE.txt new file mode 100644 index 00000000000..cbd3cd95bef --- /dev/null +++ b/solr/licenses/prometheus-metrics-tracer-initializer-NOTICE.txt @@ -0,0 +1,11 @@ +Prometheus instrumentation library for JVM applications +Copyright 2012-2015 The Prometheus Authors + +This product includes software developed at +Boxever Ltd. (http://www.boxever.com/). + +This product includes software developed at +SoundCloud Ltd. (http://soundcloud.com/). + +This product includes software developed as part of the +Ocelli project by Netflix Inc. (https://github.com/Netflix/ocelli/). \ No newline at end of file diff --git a/solr/licenses/prometheus-metrics-tracer-otel-1.1.0.jar.sha1 b/solr/licenses/prometheus-metrics-tracer-otel-1.1.0.jar.sha1 new file mode 100644 index 00000000000..c28f7197ac4 --- /dev/null +++ b/solr/licenses/prometheus-metrics-tracer-otel-1.1.0.jar.sha1 @@ -0,0 +1 @@ +25c2d488b084a9757a7b5e23cbce8dc812147e54 diff --git a/solr/licenses/prometheus-metrics-tracer-otel-LICENSE-ASL.txt b/solr/licenses/prometheus-metrics-tracer-otel-LICENSE-ASL.txt new file mode 100644 index 00000000000..f49a4e16e68 --- /dev/null +++ b/solr/licenses/prometheus-metrics-tracer-otel-LICENSE-ASL.txt @@ -0,0 +1,201 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. \ No newline at end of file diff --git a/solr/licenses/prometheus-metrics-tracer-otel-NOTICE.txt b/solr/licenses/prometheus-metrics-tracer-otel-NOTICE.txt new file mode 100644 index 00000000000..cbd3cd95bef --- /dev/null +++ b/solr/licenses/prometheus-metrics-tracer-otel-NOTICE.txt @@ -0,0 +1,11 @@ +Prometheus instrumentation library for JVM applications +Copyright 2012-2015 The Prometheus Authors + +This product includes software developed at +Boxever Ltd. (http://www.boxever.com/). + +This product includes software developed at +SoundCloud Ltd. (http://soundcloud.com/). + +This product includes software developed as part of the +Ocelli project by Netflix Inc. (https://github.com/Netflix/ocelli/). \ No newline at end of file diff --git a/solr/licenses/prometheus-metrics-tracer-otel-agent-1.1.0.jar.sha1 b/solr/licenses/prometheus-metrics-tracer-otel-agent-1.1.0.jar.sha1 new file mode 100644 index 00000000000..45a83f1dda1 --- /dev/null +++ b/solr/licenses/prometheus-metrics-tracer-otel-agent-1.1.0.jar.sha1 @@ -0,0 +1 @@ +393255f85063e08684131ac75af5e65aef070a60 diff --git a/solr/licenses/prometheus-metrics-tracer-otel-agent-LICENSE-ASL.txt b/solr/licenses/prometheus-metrics-tracer-otel-agent-LICENSE-ASL.txt new file mode 100644 index 00000000000..f49a4e16e68 --- /dev/null +++ b/solr/licenses/prometheus-metrics-tracer-otel-agent-LICENSE-ASL.txt @@ -0,0 +1,201 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. \ No newline at end of file diff --git a/solr/licenses/prometheus-metrics-tracer-otel-agent-NOTICE.txt b/solr/licenses/prometheus-metrics-tracer-otel-agent-NOTICE.txt new file mode 100644 index 00000000000..cbd3cd95bef --- /dev/null +++ b/solr/licenses/prometheus-metrics-tracer-otel-agent-NOTICE.txt @@ -0,0 +1,11 @@ +Prometheus instrumentation library for JVM applications +Copyright 2012-2015 The Prometheus Authors + +This product includes software developed at +Boxever Ltd. (http://www.boxever.com/). + +This product includes software developed at +SoundCloud Ltd. (http://soundcloud.com/). + +This product includes software developed as part of the +Ocelli project by Netflix Inc. (https://github.com/Netflix/ocelli/). \ No newline at end of file diff --git a/versions.lock b/versions.lock index 8ca94aa7689..2d11a7b1716 100644 --- a/versions.lock +++ b/versions.lock @@ -145,6 +145,15 @@ io.opentelemetry:opentelemetry-sdk-logs:1.35.0 (3 constraints: eb32b3b2) io.opentelemetry:opentelemetry-sdk-metrics:1.35.0 (3 constraints: eb32b3b2) io.opentelemetry:opentelemetry-sdk-trace:1.35.0 (3 constraints: eb32b3b2) io.perfmark:perfmark-api:0.26.0 (3 constraints: 21212b16) +io.prometheus:prometheus-metrics-config:1.1.0 (2 constraints: a926cf59) +io.prometheus:prometheus-metrics-core:1.1.0 (1 constraints: 0405f335) +io.prometheus:prometheus-metrics-exposition-formats:1.1.0 (1 constraints: 0405f335) +io.prometheus:prometheus-metrics-model:1.1.0 (3 constraints: ac2b1ea3) +io.prometheus:prometheus-metrics-shaded-protobuf:1.1.0 (1 constraints: 3e164ed8) +io.prometheus:prometheus-metrics-tracer-common:1.1.0 (3 constraints: 993ee7d1) +io.prometheus:prometheus-metrics-tracer-initializer:1.1.0 (1 constraints: 6c1022a8) +io.prometheus:prometheus-metrics-tracer-otel:1.1.0 (1 constraints: 1516fed3) +io.prometheus:prometheus-metrics-tracer-otel-agent:1.1.0 (1 constraints: 1516fed3) io.prometheus:simpleclient:0.16.0 (3 constraints: 9d257513) io.prometheus:simpleclient_common:0.16.0 (1 constraints: 1a1139c0) io.prometheus:simpleclient_httpserver:0.16.0 (1 constraints: 3905353b) From 8eb18f75084fee28d626302381c342d0cefe6d8b Mon Sep 17 00:00:00 2001 From: mbiscocho Date: Wed, 17 Apr 2024 11:17:25 -0400 Subject: [PATCH 03/32] Incorrect check on counter instead of gauge --- .../apache/solr/metrics/prometheus/SolrPrometheusRegistry.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/solr/core/src/java/org/apache/solr/metrics/prometheus/SolrPrometheusRegistry.java b/solr/core/src/java/org/apache/solr/metrics/prometheus/SolrPrometheusRegistry.java index e50da37298d..6bbe7c21e22 100644 --- a/solr/core/src/java/org/apache/solr/metrics/prometheus/SolrPrometheusRegistry.java +++ b/solr/core/src/java/org/apache/solr/metrics/prometheus/SolrPrometheusRegistry.java @@ -73,7 +73,7 @@ public void exportCounter( public void exportTimer( Timer dropwizardMetric, String prometheusMetricName, Map labelsMap) { - if (!metricCounters.containsKey(prometheusMetricName)) { + if (!metricGauges.containsKey(prometheusMetricName)) { ArrayList labels = new ArrayList<>(labelsMap.keySet()); registerGauge(prometheusMetricName, labels.toArray(String[]::new)); } From f531e49b78168a6c24886f94a97cf97ac13f7a37 Mon Sep 17 00:00:00 2001 From: mbiscocho Date: Wed, 17 Apr 2024 11:22:43 -0400 Subject: [PATCH 04/32] Keep continuity in parameter orderings --- .../java/org/apache/solr/handler/admin/MetricsHandler.java | 4 ++-- .../solr/metrics/prometheus/SolrPrometheusCoreRegistry.java | 2 +- .../core/src/java/org/apache/solr/util/stats/MetricUtils.java | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/solr/core/src/java/org/apache/solr/handler/admin/MetricsHandler.java b/solr/core/src/java/org/apache/solr/handler/admin/MetricsHandler.java index 83e60ef0eb8..d9a294bc04b 100644 --- a/solr/core/src/java/org/apache/solr/handler/admin/MetricsHandler.java +++ b/solr/core/src/java/org/apache/solr/handler/admin/MetricsHandler.java @@ -190,11 +190,11 @@ private NamedList handlePrometheusRegistry(SolrParams params) { Set requestedRegistries = parseRegistries(params); for (String registryName : requestedRegistries) { - MetricRegistry dropWizardRegistry = metricManager.registry(registryName); + MetricRegistry dropwizardRegistry = metricManager.registry(registryName); // Currently only export Solr Core registries if (registryName.startsWith("solr.core")) { MetricUtils.toPrometheusRegistry( - dropWizardRegistry, + dropwizardRegistry, registryName, metricFilters, mustMatchFilter, diff --git a/solr/core/src/java/org/apache/solr/metrics/prometheus/SolrPrometheusCoreRegistry.java b/solr/core/src/java/org/apache/solr/metrics/prometheus/SolrPrometheusCoreRegistry.java index 0ae8dced071..33c4cb55411 100644 --- a/solr/core/src/java/org/apache/solr/metrics/prometheus/SolrPrometheusCoreRegistry.java +++ b/solr/core/src/java/org/apache/solr/metrics/prometheus/SolrPrometheusCoreRegistry.java @@ -48,7 +48,7 @@ public SolrPrometheusCoreRegistry( this.cloudMode = cloudMode; } - public void exportDropwizardMetric(String metricName, Metric dropwizardMetric) { + public void exportDropwizardMetric( Metric dropwizardMetric, String metricName) { SolrCoreMetric solrCoreMetric = categorizeCoreMetric(dropwizardMetric, metricName); solrCoreMetric.parseLabels().toPrometheus(this); } diff --git a/solr/core/src/java/org/apache/solr/util/stats/MetricUtils.java b/solr/core/src/java/org/apache/solr/util/stats/MetricUtils.java index 2e0bdfc51ad..db8986ff746 100644 --- a/solr/core/src/java/org/apache/solr/util/stats/MetricUtils.java +++ b/solr/core/src/java/org/apache/solr/util/stats/MetricUtils.java @@ -210,7 +210,7 @@ public static void toPrometheusRegistry( (metricName, metric) -> { try { Metric dropwizardMetric = dropwizardMetrics.get(metricName); - solrPrometheusCoreMetrics.exportDropwizardMetric(metricName, dropwizardMetric); + solrPrometheusCoreMetrics.exportDropwizardMetric(dropwizardMetric, metricName); } catch (Exception e) { // Do not fail entirely for metrics exporting. Log and try to export next metric log.warn("Error occurred exporting Dropwizard Metric to Prometheus", e); From d594f50761ec835fedc632ba8d19521918079e05 Mon Sep 17 00:00:00 2001 From: mbiscocho Date: Wed, 17 Apr 2024 12:47:35 -0400 Subject: [PATCH 05/32] gradle tidy --- .../solr/metrics/prometheus/SolrPrometheusCoreRegistry.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/solr/core/src/java/org/apache/solr/metrics/prometheus/SolrPrometheusCoreRegistry.java b/solr/core/src/java/org/apache/solr/metrics/prometheus/SolrPrometheusCoreRegistry.java index 33c4cb55411..cd69bf02078 100644 --- a/solr/core/src/java/org/apache/solr/metrics/prometheus/SolrPrometheusCoreRegistry.java +++ b/solr/core/src/java/org/apache/solr/metrics/prometheus/SolrPrometheusCoreRegistry.java @@ -48,7 +48,7 @@ public SolrPrometheusCoreRegistry( this.cloudMode = cloudMode; } - public void exportDropwizardMetric( Metric dropwizardMetric, String metricName) { + public void exportDropwizardMetric(Metric dropwizardMetric, String metricName) { SolrCoreMetric solrCoreMetric = categorizeCoreMetric(dropwizardMetric, metricName); solrCoreMetric.parseLabels().toPrometheus(this); } From 59cc9b422a396eef14d0f187cf0b5b3ff51ee324 Mon Sep 17 00:00:00 2001 From: mbiscocho Date: Mon, 29 Apr 2024 15:46:58 -0400 Subject: [PATCH 06/32] Write javadocs for new classes --- .../SolrPrometheusCoreRegistry.java | 9 +++++ .../prometheus/SolrPrometheusRegistry.java | 36 +++++++++++++++++++ .../prometheus/core/SolrCoreMetric.java | 4 +++ .../apache/solr/util/stats/MetricUtils.java | 16 +++++++++ 4 files changed, 65 insertions(+) diff --git a/solr/core/src/java/org/apache/solr/metrics/prometheus/SolrPrometheusCoreRegistry.java b/solr/core/src/java/org/apache/solr/metrics/prometheus/SolrPrometheusCoreRegistry.java index cd69bf02078..4f15bdab33b 100644 --- a/solr/core/src/java/org/apache/solr/metrics/prometheus/SolrPrometheusCoreRegistry.java +++ b/solr/core/src/java/org/apache/solr/metrics/prometheus/SolrPrometheusCoreRegistry.java @@ -16,6 +16,7 @@ */ package org.apache.solr.metrics.prometheus; +import com.codahale.metrics.Meter; import com.codahale.metrics.Metric; import io.prometheus.metrics.model.registry.PrometheusRegistry; import org.apache.solr.metrics.prometheus.core.SolrCoreCacheMetric; @@ -27,6 +28,7 @@ import org.apache.solr.metrics.prometheus.core.SolrCoreSearcherMetric; import org.apache.solr.metrics.prometheus.core.SolrCoreTlogMetric; +/** This class maintains a {@link PrometheusRegistry} specific to solr.core Dropwizard metrics */ public class SolrPrometheusCoreRegistry extends SolrPrometheusRegistry { public final String coreName; public final boolean cloudMode; @@ -48,6 +50,13 @@ public SolrPrometheusCoreRegistry( this.cloudMode = cloudMode; } + /** + * Export {@link Meter} to {@link io.prometheus.metrics.core.metrics.Metric} and register to + * {@link PrometheusRegistry}. + * + * @param dropwizardMetric the {@link Meter} to be exported + * @param metricName Dropwizard metric name + */ public void exportDropwizardMetric(Metric dropwizardMetric, String metricName) { SolrCoreMetric solrCoreMetric = categorizeCoreMetric(dropwizardMetric, metricName); solrCoreMetric.parseLabels().toPrometheus(this); diff --git a/solr/core/src/java/org/apache/solr/metrics/prometheus/SolrPrometheusRegistry.java b/solr/core/src/java/org/apache/solr/metrics/prometheus/SolrPrometheusRegistry.java index 6bbe7c21e22..d17bf3895d0 100644 --- a/solr/core/src/java/org/apache/solr/metrics/prometheus/SolrPrometheusRegistry.java +++ b/solr/core/src/java/org/apache/solr/metrics/prometheus/SolrPrometheusRegistry.java @@ -25,6 +25,10 @@ import java.util.HashMap; import java.util.Map; +/** + * Base class for all {@link SolrPrometheusRegistry} holding {@link PrometheusRegistry}. Can export + * {@link Meter} to {@link io.prometheus.metrics.core.metrics.Metric} + */ public abstract class SolrPrometheusRegistry { PrometheusRegistry prometheusRegistry; String registryName; @@ -45,6 +49,14 @@ public String getRegistryName() { return registryName; } + /** + * Export {@link Meter} to {@link Counter}. Registers new {@link Counter} to {@link + * PrometheusRegistry} metric name does not exist + * + * @param dropwizardMetric the {@link Meter} to be exported + * @param prometheusMetricName name of prometheus metric + * @param labelsMap label names and values to register with {@link Counter} + */ public void exportMeter( Meter dropwizardMetric, String prometheusMetricName, Map labelsMap) { if (!metricCounters.containsKey(prometheusMetricName)) { @@ -57,6 +69,14 @@ public void exportMeter( .inc(dropwizardMetric.getCount()); } + /** + * Export {@link com.codahale.metrics.Counter} to {@link Counter}. Registers new {@link Counter} + * to {@link PrometheusRegistry} metric name does not exist + * + * @param dropwizardMetric the {@link com.codahale.metrics.Counter} to be exported + * @param prometheusMetricName name of prometheus metric + * @param labelsMap label names and values to record with {@link Counter} + */ public void exportCounter( com.codahale.metrics.Counter dropwizardMetric, String prometheusMetricName, @@ -71,6 +91,14 @@ public void exportCounter( .inc(dropwizardMetric.getCount()); } + /** + * Export {@link Timer} to {@link Gauge}. Registers new {@link Gauge} to {@link + * PrometheusRegistry} metric name does not exist + * + * @param dropwizardMetric the {@link Timer} to be exported + * @param prometheusMetricName name of prometheus metric + * @param labelsMap label names and values to record with {@link Gauge} + */ public void exportTimer( Timer dropwizardMetric, String prometheusMetricName, Map labelsMap) { if (!metricGauges.containsKey(prometheusMetricName)) { @@ -83,6 +111,14 @@ public void exportTimer( .set(dropwizardMetric.getMeanRate()); } + /** + * Export {@link Timer} to {@link Gauge}. Registers new {@link Gauge} to {@link + * PrometheusRegistry} metric name does not exist + * + * @param dropwizardMetricRaw the {@link com.codahale.metrics.Gauge} to be exported + * @param prometheusMetricName name of prometheus metric + * @param labelsMap label names and values to record with {@link Gauge} + */ public void exportGauge( com.codahale.metrics.Gauge dropwizardMetricRaw, String prometheusMetricName, diff --git a/solr/core/src/java/org/apache/solr/metrics/prometheus/core/SolrCoreMetric.java b/solr/core/src/java/org/apache/solr/metrics/prometheus/core/SolrCoreMetric.java index 08bdd63c4d0..5a4ec9849a2 100644 --- a/solr/core/src/java/org/apache/solr/metrics/prometheus/core/SolrCoreMetric.java +++ b/solr/core/src/java/org/apache/solr/metrics/prometheus/core/SolrCoreMetric.java @@ -21,6 +21,10 @@ import java.util.Map; import org.apache.solr.metrics.prometheus.SolrPrometheusCoreRegistry; +/** + * Base class is a wrapper to export {@link com.codahale.metrics.Metric} to {@link + * io.prometheus.metrics.core.metrics.Metric} and register to a {@link SolrPrometheusCoreRegistry} + */ public abstract class SolrCoreMetric { public Metric dropwizardMetric; public String coreName; diff --git a/solr/core/src/java/org/apache/solr/util/stats/MetricUtils.java b/solr/core/src/java/org/apache/solr/util/stats/MetricUtils.java index db8986ff746..dcedc1899f6 100644 --- a/solr/core/src/java/org/apache/solr/util/stats/MetricUtils.java +++ b/solr/core/src/java/org/apache/solr/util/stats/MetricUtils.java @@ -170,6 +170,22 @@ public static void toSolrInputDocuments( }); } + /** + * Provides a representation of the given Dropwizard metric registry as {@link + * SolrPrometheusCoreRegistry}-s. Only those metrics are converted which match at least one of the + * given MetricFilter instances. + * + * @param registry the {@link MetricRegistry} to be converted + * @param shouldMatchFilters a list of {@link MetricFilter} instances. A metric must match any + * one of the filters from this list to be included in the output + * @param mustMatchFilter a {@link MetricFilter}. A metric must match this filter to be + * included in the output. + * @param propertyFilter limit what properties of a metric are returned + * @param skipHistograms discard any {@link Histogram}-s and histogram parts of {@link Timer}-s. + * @param skipAggregateValues discard internal values of {@link AggregateMetric}-s. + * @param compact use compact representation for counters and gauges. + * @param consumer consumer that accepts produced {@link SolrPrometheusCoreRegistry}-s + */ public static void toPrometheusRegistry( MetricRegistry registry, String registryName, From bc6a60a4eaec896a6408ff1d8f553d155adf6f88 Mon Sep 17 00:00:00 2001 From: mbiscocho Date: Wed, 1 May 2024 14:22:51 -0400 Subject: [PATCH 07/32] Refactor out prometheus registry to Prometheus metric snapshots --- .../solr/handler/admin/MetricsHandler.java | 2 +- .../SolrPrometheusCoreRegistry.java | 15 +- .../prometheus/SolrPrometheusRegistry.java | 183 +++++++++--------- .../prometheus/core/SolrCoreCacheMetric.java | 2 +- .../core/SolrCoreHandlerMetric.java | 22 ++- .../core/SolrCoreHighlighterMetric.java | 2 +- .../prometheus/core/SolrCoreIndexMetric.java | 2 +- .../prometheus/core/SolrCoreMetric.java | 3 + .../core/SolrCoreSearcherMetric.java | 9 +- .../prometheus/core/SolrCoreTlogMetric.java | 3 +- .../metrics/prometheus/core/package-info.java | 2 +- .../response/PrometheusResponseWriter.java | 6 +- .../apache/solr/util/stats/MetricUtils.java | 7 +- 13 files changed, 128 insertions(+), 130 deletions(-) diff --git a/solr/core/src/java/org/apache/solr/handler/admin/MetricsHandler.java b/solr/core/src/java/org/apache/solr/handler/admin/MetricsHandler.java index d9a294bc04b..7484c677137 100644 --- a/solr/core/src/java/org/apache/solr/handler/admin/MetricsHandler.java +++ b/solr/core/src/java/org/apache/solr/handler/admin/MetricsHandler.java @@ -181,7 +181,7 @@ private NamedList handleDropwizardRegistry(SolrParams params) { private NamedList handlePrometheusRegistry(SolrParams params) { NamedList response = new SimpleOrderedMap<>(); - boolean compact = params.getBool(COMPACT_PARAM, true); + boolean compact = params.getBool(COMPACT_PARAM, false); MetricFilter mustMatchFilter = parseMustMatchFilter(params); Predicate propertyFilter = parsePropertyFilter(params); List metricTypes = parseMetricTypes(params); diff --git a/solr/core/src/java/org/apache/solr/metrics/prometheus/SolrPrometheusCoreRegistry.java b/solr/core/src/java/org/apache/solr/metrics/prometheus/SolrPrometheusCoreRegistry.java index 4f15bdab33b..5a60588d9e8 100644 --- a/solr/core/src/java/org/apache/solr/metrics/prometheus/SolrPrometheusCoreRegistry.java +++ b/solr/core/src/java/org/apache/solr/metrics/prometheus/SolrPrometheusCoreRegistry.java @@ -18,7 +18,6 @@ import com.codahale.metrics.Meter; import com.codahale.metrics.Metric; -import io.prometheus.metrics.model.registry.PrometheusRegistry; import org.apache.solr.metrics.prometheus.core.SolrCoreCacheMetric; import org.apache.solr.metrics.prometheus.core.SolrCoreHandlerMetric; import org.apache.solr.metrics.prometheus.core.SolrCoreHighlighterMetric; @@ -28,7 +27,10 @@ import org.apache.solr.metrics.prometheus.core.SolrCoreSearcherMetric; import org.apache.solr.metrics.prometheus.core.SolrCoreTlogMetric; -/** This class maintains a {@link PrometheusRegistry} specific to solr.core Dropwizard metrics */ +/** + * This class maintains a {@link io.prometheus.metrics.model.snapshots.MetricSnapshot}s exported + * from solr.core {@link com.codahale.metrics.MetricRegistry} + */ public class SolrPrometheusCoreRegistry extends SolrPrometheusRegistry { public final String coreName; public final boolean cloudMode; @@ -43,16 +45,15 @@ public class SolrPrometheusCoreRegistry extends SolrPrometheusRegistry { public static final String INDEX = "INDEX"; public static final String CORE = "CORE"; - public SolrPrometheusCoreRegistry( - PrometheusRegistry prometheusRegistry, String coreName, boolean cloudMode) { - super(prometheusRegistry); + public SolrPrometheusCoreRegistry(String coreName, boolean cloudMode) { + super(); this.coreName = coreName; this.cloudMode = cloudMode; } /** - * Export {@link Meter} to {@link io.prometheus.metrics.core.metrics.Metric} and register to - * {@link PrometheusRegistry}. + * Export {@link Meter} to {@link io.prometheus.metrics.model.snapshots.MetricSnapshot} and + * registers the Snapshot * * @param dropwizardMetric the {@link Meter} to be exported * @param metricName Dropwizard metric name diff --git a/solr/core/src/java/org/apache/solr/metrics/prometheus/SolrPrometheusRegistry.java b/solr/core/src/java/org/apache/solr/metrics/prometheus/SolrPrometheusRegistry.java index d17bf3895d0..5cb6135de89 100644 --- a/solr/core/src/java/org/apache/solr/metrics/prometheus/SolrPrometheusRegistry.java +++ b/solr/core/src/java/org/apache/solr/metrics/prometheus/SolrPrometheusRegistry.java @@ -18,163 +18,154 @@ import com.codahale.metrics.Meter; import com.codahale.metrics.Timer; -import io.prometheus.metrics.core.metrics.Counter; import io.prometheus.metrics.core.metrics.Gauge; -import io.prometheus.metrics.model.registry.PrometheusRegistry; +import io.prometheus.metrics.model.snapshots.CounterSnapshot; +import io.prometheus.metrics.model.snapshots.GaugeSnapshot; +import io.prometheus.metrics.model.snapshots.Labels; +import io.prometheus.metrics.model.snapshots.MetricMetadata; +import io.prometheus.metrics.model.snapshots.MetricSnapshot; +import io.prometheus.metrics.model.snapshots.MetricSnapshots; import java.util.ArrayList; import java.util.HashMap; +import java.util.List; import java.util.Map; /** - * Base class for all {@link SolrPrometheusRegistry} holding {@link PrometheusRegistry}. Can export - * {@link Meter} to {@link io.prometheus.metrics.core.metrics.Metric} + * Base class for all {@link SolrPrometheusRegistry} holding {@link MetricSnapshot}s. Can export + * {@link Meter} to {@link MetricSnapshot} to be outputted for {@link + * org.apache.solr.response.PrometheusResponseWriter} */ public abstract class SolrPrometheusRegistry { - PrometheusRegistry prometheusRegistry; - String registryName; - private final Map metricCounters; - private final Map metricGauges; + private final Map> metricCounters; + private final Map> metricGauges; - public SolrPrometheusRegistry(PrometheusRegistry prometheusRegistry) { - this.prometheusRegistry = prometheusRegistry; + public SolrPrometheusRegistry() { this.metricCounters = new HashMap<>(); this.metricGauges = new HashMap<>(); } - public PrometheusRegistry getPrometheusRegistry() { - return prometheusRegistry; - } - - public String getRegistryName() { - return registryName; - } - /** - * Export {@link Meter} to {@link Counter}. Registers new {@link Counter} to {@link - * PrometheusRegistry} metric name does not exist + * Export {@link Meter} to {@link CounterSnapshot}. Registers new Prometheus Metric and {@link + * io.prometheus.metrics.model.snapshots.CounterSnapshot.CounterDataPointSnapshot} if metric does + * not exist * - * @param dropwizardMetric the {@link Meter} to be exported * @param prometheusMetricName name of prometheus metric - * @param labelsMap label names and values to register with {@link Counter} + * @param dropwizardMetric the {@link Meter} to be exported + * @param labels label names and values to register with {@link CounterSnapshot} */ public void exportMeter( - Meter dropwizardMetric, String prometheusMetricName, Map labelsMap) { + String prometheusMetricName, Meter dropwizardMetric, Map labels) { + CounterSnapshot.CounterDataPointSnapshot dataPointBuilder = + CounterSnapshot.CounterDataPointSnapshot.builder() + .value(dropwizardMetric.getCount()) + .labels(Labels.of(new ArrayList<>(labels.keySet()), new ArrayList<>(labels.values()))) + .build(); if (!metricCounters.containsKey(prometheusMetricName)) { - ArrayList labels = new ArrayList<>(labelsMap.keySet()); - registerCounter(prometheusMetricName, labels.toArray(String[]::new)); + metricCounters.put(prometheusMetricName, new ArrayList<>()); } - ArrayList labelValues = new ArrayList<>(labelsMap.values()); - getMetricCounter(prometheusMetricName) - .labelValues(labelValues.toArray(String[]::new)) - .inc(dropwizardMetric.getCount()); + metricCounters.get(prometheusMetricName).add(dataPointBuilder); } /** - * Export {@link com.codahale.metrics.Counter} to {@link Counter}. Registers new {@link Counter} - * to {@link PrometheusRegistry} metric name does not exist + * Export {@link com.codahale.metrics.Counter} to {@link CounterSnapshot}. Registers new + * Prometheus Metric and {@link + * io.prometheus.metrics.model.snapshots.CounterSnapshot.CounterDataPointSnapshot} if metric does + * not exist * - * @param dropwizardMetric the {@link com.codahale.metrics.Counter} to be exported * @param prometheusMetricName name of prometheus metric - * @param labelsMap label names and values to record with {@link Counter} + * @param dropwizardMetric the {@link com.codahale.metrics.Counter} to be exported + * @param labels label names and values to record with {@link CounterSnapshot} */ public void exportCounter( - com.codahale.metrics.Counter dropwizardMetric, String prometheusMetricName, - Map labelsMap) { + com.codahale.metrics.Counter dropwizardMetric, + Map labels) { + CounterSnapshot.CounterDataPointSnapshot dataPointBuilder = + CounterSnapshot.CounterDataPointSnapshot.builder() + .value(dropwizardMetric.getCount()) + .labels(Labels.of(new ArrayList<>(labels.keySet()), new ArrayList<>(labels.values()))) + .build(); if (!metricCounters.containsKey(prometheusMetricName)) { - ArrayList labels = new ArrayList<>(labelsMap.keySet()); - registerCounter(prometheusMetricName, labels.toArray(String[]::new)); + metricCounters.put(prometheusMetricName, new ArrayList<>()); } - ArrayList labelValues = new ArrayList<>(labelsMap.values()); - getMetricCounter(prometheusMetricName) - .labelValues(labelValues.toArray(String[]::new)) - .inc(dropwizardMetric.getCount()); + metricCounters.get(prometheusMetricName).add(dataPointBuilder); } /** - * Export {@link Timer} to {@link Gauge}. Registers new {@link Gauge} to {@link - * PrometheusRegistry} metric name does not exist + * Export {@link Timer} to {@link GaugeSnapshot}. Registers new Prometheus Metric and {@link + * io.prometheus.metrics.model.snapshots.GaugeSnapshot.GaugeDataPointSnapshot} if metric does not + * exist * - * @param dropwizardMetric the {@link Timer} to be exported * @param prometheusMetricName name of prometheus metric - * @param labelsMap label names and values to record with {@link Gauge} + * @param dropwizardMetric the {@link Timer} to be exported + * @param labels label names and values to record with {@link GaugeSnapshot} */ public void exportTimer( - Timer dropwizardMetric, String prometheusMetricName, Map labelsMap) { + String prometheusMetricName, Timer dropwizardMetric, Map labels) { + GaugeSnapshot.GaugeDataPointSnapshot dataPointBuilder = + GaugeSnapshot.GaugeDataPointSnapshot.builder() + .value(dropwizardMetric.getCount()) + .labels(Labels.of(new ArrayList<>(labels.keySet()), new ArrayList<>(labels.values()))) + .build(); if (!metricGauges.containsKey(prometheusMetricName)) { - ArrayList labels = new ArrayList<>(labelsMap.keySet()); - registerGauge(prometheusMetricName, labels.toArray(String[]::new)); + metricGauges.put(prometheusMetricName, new ArrayList<>()); } - ArrayList labelValues = new ArrayList<>(labelsMap.values()); - getMetricGauge(prometheusMetricName) - .labelValues(labelValues.toArray(String[]::new)) - .set(dropwizardMetric.getMeanRate()); + metricGauges.get(prometheusMetricName).add(dataPointBuilder); } /** - * Export {@link Timer} to {@link Gauge}. Registers new {@link Gauge} to {@link - * PrometheusRegistry} metric name does not exist + * Export {@link com.codahale.metrics.Gauge} to {@link GaugeSnapshot}. Registers new Prometheus + * Metric and {@link io.prometheus.metrics.model.snapshots.GaugeSnapshot.GaugeDataPointSnapshot} + * if metric does not exist * - * @param dropwizardMetricRaw the {@link com.codahale.metrics.Gauge} to be exported * @param prometheusMetricName name of prometheus metric + * @param dropwizardMetricRaw the {@link com.codahale.metrics.Gauge} to be exported * @param labelsMap label names and values to record with {@link Gauge} */ public void exportGauge( - com.codahale.metrics.Gauge dropwizardMetricRaw, String prometheusMetricName, + com.codahale.metrics.Gauge dropwizardMetricRaw, Map labelsMap) { Object dropwizardMetric = (dropwizardMetricRaw).getValue(); if (!metricGauges.containsKey(prometheusMetricName)) { - ArrayList labels = new ArrayList<>(labelsMap.keySet()); - if (dropwizardMetric instanceof HashMap) { - labels.add("item"); - } - registerGauge(prometheusMetricName, labels.toArray(String[]::new)); + metricGauges.put(prometheusMetricName, new ArrayList<>()); } - ArrayList labelValues = new ArrayList<>(labelsMap.values()); - String[] labels = labelValues.toArray(String[]::new); if (dropwizardMetric instanceof Number) { - getMetricGauge(prometheusMetricName) - .labelValues(labels) - .set(((Number) dropwizardMetric).doubleValue()); + GaugeSnapshot.GaugeDataPointSnapshot dataPointBuilder = + GaugeSnapshot.GaugeDataPointSnapshot.builder() + .value(((Number) dropwizardMetric).doubleValue()) + .labels( + Labels.of( + new ArrayList<>(labelsMap.keySet()), new ArrayList<>(labelsMap.values()))) + .build(); + metricGauges.get(prometheusMetricName).add(dataPointBuilder); } else if (dropwizardMetric instanceof HashMap) { HashMap itemsMap = (HashMap) dropwizardMetric; for (Object item : itemsMap.keySet()) { if (itemsMap.get(item) instanceof Number) { - String[] newLabels = new String[labels.length + 1]; - System.arraycopy(labels, 0, newLabels, 0, labels.length); - newLabels[labels.length] = (String) item; - getMetricGauge(prometheusMetricName) - .labelValues(newLabels) - .set(((Number) itemsMap.get(item)).doubleValue()); + List labelKeys = new ArrayList<>(labelsMap.keySet()); + labelKeys.add("item"); + List labelValues = new ArrayList<>(labelsMap.values()); + labelValues.add((String) item); + GaugeSnapshot.GaugeDataPointSnapshot dataPointBuilder = + GaugeSnapshot.GaugeDataPointSnapshot.builder() + .value(((Number) itemsMap.get(item)).doubleValue()) + .labels(Labels.of(labelKeys, labelValues)) + .build(); + metricGauges.get(prometheusMetricName).add(dataPointBuilder); } } } } - private Counter getMetricCounter(String metricName) { - return metricCounters.get(metricName); - } - - private Gauge getMetricGauge(String metricName) { - return metricGauges.get(metricName); - } - - private void registerCounter(String metricName, String... labelNames) { - Counter counter = - io.prometheus.metrics.core.metrics.Counter.builder() - .name(metricName) - .labelNames(labelNames) - .register(prometheusRegistry); - metricCounters.put(metricName, counter); - } - - private void registerGauge(String metricName, String... labelNames) { - Gauge gauge = - io.prometheus.metrics.core.metrics.Gauge.builder() - .name(metricName) - .labelNames(labelNames) - .register(prometheusRegistry); - metricGauges.put(metricName, gauge); + public MetricSnapshots collect() { + ArrayList snapshots = new ArrayList<>(); + for (String names : metricCounters.keySet()) { + snapshots.add(new CounterSnapshot(new MetricMetadata(names), metricCounters.get(names))); + } + for (String names : metricGauges.keySet()) { + snapshots.add(new GaugeSnapshot(new MetricMetadata(names), metricGauges.get(names))); + } + return new MetricSnapshots(snapshots); } } diff --git a/solr/core/src/java/org/apache/solr/metrics/prometheus/core/SolrCoreCacheMetric.java b/solr/core/src/java/org/apache/solr/metrics/prometheus/core/SolrCoreCacheMetric.java index 46064bf366b..c03d93f8836 100644 --- a/solr/core/src/java/org/apache/solr/metrics/prometheus/core/SolrCoreCacheMetric.java +++ b/solr/core/src/java/org/apache/solr/metrics/prometheus/core/SolrCoreCacheMetric.java @@ -42,7 +42,7 @@ public SolrCoreMetric parseLabels() { public void toPrometheus(SolrPrometheusCoreRegistry solrPrometheusCoreRegistry) { if (dropwizardMetric instanceof Gauge) { solrPrometheusCoreRegistry.exportGauge( - (Gauge) dropwizardMetric, CORE_CACHE_SEARCHER_METRICS, labels); + CORE_CACHE_SEARCHER_METRICS, (Gauge) dropwizardMetric, labels); } } } diff --git a/solr/core/src/java/org/apache/solr/metrics/prometheus/core/SolrCoreHandlerMetric.java b/solr/core/src/java/org/apache/solr/metrics/prometheus/core/SolrCoreHandlerMetric.java index f9247da4d6b..cde405a41f0 100644 --- a/solr/core/src/java/org/apache/solr/metrics/prometheus/core/SolrCoreHandlerMetric.java +++ b/solr/core/src/java/org/apache/solr/metrics/prometheus/core/SolrCoreHandlerMetric.java @@ -42,29 +42,33 @@ public SolrCoreMetric parseLabels() { String type = parsedMetric[2]; labels.put("category", category); labels.put("type", type); - if (!(dropwizardMetric instanceof Gauge)) { - labels.put("handler", handler); - } + labels.put("handler", handler); return this; } @Override public void toPrometheus(SolrPrometheusCoreRegistry solrPrometheusCoreRegistry) { if (dropwizardMetric instanceof Meter) { - solrPrometheusCoreRegistry.exportMeter((Meter) dropwizardMetric, CORE_REQUESTS_TOTAL, labels); + solrPrometheusCoreRegistry.exportMeter(CORE_REQUESTS_TOTAL, (Meter) dropwizardMetric, labels); } else if (dropwizardMetric instanceof Counter) { if (metricName.endsWith("requests")) { solrPrometheusCoreRegistry.exportCounter( - (Counter) dropwizardMetric, CORE_REQUESTS_TOTAL, labels); + CORE_REQUESTS_TOTAL, (Counter) dropwizardMetric, labels); } else if (metricName.endsWith("totalTime")) { + // Do not need type label for total time + labels.remove("type"); solrPrometheusCoreRegistry.exportCounter( - (Counter) dropwizardMetric, CORE_REQUESTS_TOTAL_TIME, labels); + CORE_REQUESTS_TOTAL_TIME, (Counter) dropwizardMetric, labels); } } else if (dropwizardMetric instanceof Gauge) { - solrPrometheusCoreRegistry.exportGauge( - (Gauge) dropwizardMetric, CORE_REQUESTS_UPDATE_HANDLER, labels); + if (!metricName.endsWith("handlerStart")) { + solrPrometheusCoreRegistry.exportGauge( + CORE_REQUESTS_UPDATE_HANDLER, (Gauge) dropwizardMetric, labels); + } } else if (dropwizardMetric instanceof Timer) { - solrPrometheusCoreRegistry.exportTimer((Timer) dropwizardMetric, CORE_REQUEST_TIMES, labels); + // Do not need type label for request times + labels.remove("type"); + solrPrometheusCoreRegistry.exportTimer(CORE_REQUEST_TIMES, (Timer) dropwizardMetric, labels); } } } diff --git a/solr/core/src/java/org/apache/solr/metrics/prometheus/core/SolrCoreHighlighterMetric.java b/solr/core/src/java/org/apache/solr/metrics/prometheus/core/SolrCoreHighlighterMetric.java index 742c580d2db..d71e7a69b7e 100644 --- a/solr/core/src/java/org/apache/solr/metrics/prometheus/core/SolrCoreHighlighterMetric.java +++ b/solr/core/src/java/org/apache/solr/metrics/prometheus/core/SolrCoreHighlighterMetric.java @@ -42,7 +42,7 @@ public SolrCoreMetric parseLabels() { public void toPrometheus(SolrPrometheusCoreRegistry solrPrometheusCoreRegistry) { if (dropwizardMetric instanceof Counter) { solrPrometheusCoreRegistry.exportCounter( - (Counter) dropwizardMetric, CORE_HIGHLIGHER_METRICS, labels); + CORE_HIGHLIGHER_METRICS, (Counter) dropwizardMetric, labels); } } } diff --git a/solr/core/src/java/org/apache/solr/metrics/prometheus/core/SolrCoreIndexMetric.java b/solr/core/src/java/org/apache/solr/metrics/prometheus/core/SolrCoreIndexMetric.java index 54e582152a7..f46399c0a09 100644 --- a/solr/core/src/java/org/apache/solr/metrics/prometheus/core/SolrCoreIndexMetric.java +++ b/solr/core/src/java/org/apache/solr/metrics/prometheus/core/SolrCoreIndexMetric.java @@ -38,7 +38,7 @@ public void toPrometheus(SolrPrometheusCoreRegistry solrPrometheusCoreRegistry) if (dropwizardMetric instanceof Gauge) { if (metricName.endsWith("sizeInBytes")) { solrPrometheusCoreRegistry.exportGauge( - (Gauge) dropwizardMetric, CORE_INDEX_METRICS, labels); + CORE_INDEX_METRICS, (Gauge) dropwizardMetric, labels); } } } diff --git a/solr/core/src/java/org/apache/solr/metrics/prometheus/core/SolrCoreMetric.java b/solr/core/src/java/org/apache/solr/metrics/prometheus/core/SolrCoreMetric.java index 5a4ec9849a2..95cf967ce3f 100644 --- a/solr/core/src/java/org/apache/solr/metrics/prometheus/core/SolrCoreMetric.java +++ b/solr/core/src/java/org/apache/solr/metrics/prometheus/core/SolrCoreMetric.java @@ -24,6 +24,9 @@ /** * Base class is a wrapper to export {@link com.codahale.metrics.Metric} to {@link * io.prometheus.metrics.core.metrics.Metric} and register to a {@link SolrPrometheusCoreRegistry} + * {@link com.codahale.metrics.MetricRegistry} does not support tags unlike prometheus. Metrics + * registered to the registry need to be parsed out from the metric name and exported to {@link + * io.prometheus.metrics.model.snapshots.MetricSnapshot} be output to Prometheus */ public abstract class SolrCoreMetric { public Metric dropwizardMetric; diff --git a/solr/core/src/java/org/apache/solr/metrics/prometheus/core/SolrCoreSearcherMetric.java b/solr/core/src/java/org/apache/solr/metrics/prometheus/core/SolrCoreSearcherMetric.java index ec47e93432a..932b1d96288 100644 --- a/solr/core/src/java/org/apache/solr/metrics/prometheus/core/SolrCoreSearcherMetric.java +++ b/solr/core/src/java/org/apache/solr/metrics/prometheus/core/SolrCoreSearcherMetric.java @@ -18,6 +18,7 @@ import static org.apache.solr.metrics.prometheus.core.SolrCoreCacheMetric.CORE_CACHE_SEARCHER_METRICS; +import com.codahale.metrics.Counter; import com.codahale.metrics.Gauge; import com.codahale.metrics.Metric; import com.codahale.metrics.Timer; @@ -35,7 +36,7 @@ public SolrCoreSearcherMetric( @Override public SolrCoreMetric parseLabels() { String[] parsedMetric = metricName.split("\\."); - if (dropwizardMetric instanceof Gauge) { + if (!(dropwizardMetric instanceof Counter)) { String type = parsedMetric[2]; labels.put("type", type); } @@ -47,13 +48,13 @@ public void toPrometheus(SolrPrometheusCoreRegistry solrPrometheusCoreRegistry) if (dropwizardMetric instanceof Gauge) { if (metricName.endsWith("liveDocsCache")) { solrPrometheusCoreRegistry.exportGauge( - (Gauge) dropwizardMetric, CORE_CACHE_SEARCHER_METRICS, labels); + CORE_CACHE_SEARCHER_METRICS, (Gauge) dropwizardMetric, labels); } else { solrPrometheusCoreRegistry.exportGauge( - (Gauge) dropwizardMetric, CORE_SEARCHER_METRICS, labels); + CORE_SEARCHER_METRICS, (Gauge) dropwizardMetric, labels); } } else if (dropwizardMetric instanceof Timer) { - solrPrometheusCoreRegistry.exportTimer((Timer) dropwizardMetric, CORE_SEARCHER_TIMES, labels); + solrPrometheusCoreRegistry.exportTimer(CORE_SEARCHER_TIMES, (Timer) dropwizardMetric, labels); } } } diff --git a/solr/core/src/java/org/apache/solr/metrics/prometheus/core/SolrCoreTlogMetric.java b/solr/core/src/java/org/apache/solr/metrics/prometheus/core/SolrCoreTlogMetric.java index 86eb7b08a8e..b81de46ec41 100644 --- a/solr/core/src/java/org/apache/solr/metrics/prometheus/core/SolrCoreTlogMetric.java +++ b/solr/core/src/java/org/apache/solr/metrics/prometheus/core/SolrCoreTlogMetric.java @@ -33,7 +33,6 @@ public SolrCoreMetric parseLabels() { String[] parsedMetric = metricName.split("\\."); if (dropwizardMetric instanceof Meter) { String item = parsedMetric[1]; - String type = parsedMetric[2]; labels.put("item", item); } return this; @@ -42,7 +41,7 @@ public SolrCoreMetric parseLabels() { @Override public void toPrometheus(SolrPrometheusCoreRegistry solrPrometheusCoreRegistry) { if (dropwizardMetric instanceof Meter) { - solrPrometheusCoreRegistry.exportMeter((Meter) dropwizardMetric, CORE_TLOG_METRICS, labels); + solrPrometheusCoreRegistry.exportMeter(CORE_TLOG_METRICS, (Meter) dropwizardMetric, labels); } } } diff --git a/solr/core/src/java/org/apache/solr/metrics/prometheus/core/package-info.java b/solr/core/src/java/org/apache/solr/metrics/prometheus/core/package-info.java index 8d0cb5a569f..aa2311f8192 100644 --- a/solr/core/src/java/org/apache/solr/metrics/prometheus/core/package-info.java +++ b/solr/core/src/java/org/apache/solr/metrics/prometheus/core/package-info.java @@ -17,6 +17,6 @@ /** * The {@link org.apache.solr.metrics.prometheus.core.SolrCoreMetric} is a wrapper to export {@link - * com.codahale.metrics.Metric} to {@link io.prometheus.metrics.core.metrics.Metric} + * com.codahale.metrics.Metric} to {@link io.prometheus.metrics.model.snapshots.MetricSnapshot} */ package org.apache.solr.metrics.prometheus.core; diff --git a/solr/core/src/java/org/apache/solr/response/PrometheusResponseWriter.java b/solr/core/src/java/org/apache/solr/response/PrometheusResponseWriter.java index 869e0575630..382d2094d13 100644 --- a/solr/core/src/java/org/apache/solr/response/PrometheusResponseWriter.java +++ b/solr/core/src/java/org/apache/solr/response/PrometheusResponseWriter.java @@ -17,11 +17,11 @@ package org.apache.solr.response; import io.prometheus.metrics.expositionformats.PrometheusTextFormatWriter; -import io.prometheus.metrics.model.registry.PrometheusRegistry; import java.io.IOException; import java.io.OutputStream; import java.util.Map; import org.apache.solr.common.util.NamedList; +import org.apache.solr.metrics.prometheus.SolrPrometheusCoreRegistry; import org.apache.solr.request.SolrQueryRequest; @SuppressWarnings(value = "unchecked") @@ -37,8 +37,8 @@ public void write(OutputStream out, SolrQueryRequest request, SolrQueryResponse registryMap.forEach( (name, registry) -> { try { - PrometheusRegistry prometheusRegistry = (PrometheusRegistry) registry; - prometheusTextFormatWriter.write(out, prometheusRegistry.scrape()); + SolrPrometheusCoreRegistry prometheusRegistry = (SolrPrometheusCoreRegistry) registry; + prometheusTextFormatWriter.write(out, prometheusRegistry.collect()); } catch (IOException e) { throw new RuntimeException(e); } diff --git a/solr/core/src/java/org/apache/solr/util/stats/MetricUtils.java b/solr/core/src/java/org/apache/solr/util/stats/MetricUtils.java index dcedc1899f6..ddc5c82ab69 100644 --- a/solr/core/src/java/org/apache/solr/util/stats/MetricUtils.java +++ b/solr/core/src/java/org/apache/solr/util/stats/MetricUtils.java @@ -26,7 +26,6 @@ import com.codahale.metrics.MetricRegistry; import com.codahale.metrics.Snapshot; import com.codahale.metrics.Timer; -import io.prometheus.metrics.model.registry.PrometheusRegistry; import java.beans.BeanInfo; import java.beans.IntrospectionException; import java.beans.Introspector; @@ -195,7 +194,7 @@ public static void toPrometheusRegistry( boolean skipHistograms, boolean skipAggregateValues, boolean compact, - Consumer consumer) { + Consumer consumer) { String coreName; boolean cloudMode = false; Map dropwizardMetrics = registry.getMetrics(); @@ -212,7 +211,7 @@ public static void toPrometheusRegistry( } SolrPrometheusCoreRegistry solrPrometheusCoreMetrics = - new SolrPrometheusCoreRegistry(new PrometheusRegistry(), coreName, cloudMode); + new SolrPrometheusCoreRegistry(coreName, cloudMode); toMaps( registry, @@ -232,7 +231,7 @@ public static void toPrometheusRegistry( log.warn("Error occurred exporting Dropwizard Metric to Prometheus", e); } }); - consumer.accept(solrPrometheusCoreMetrics.getPrometheusRegistry()); + consumer.accept(solrPrometheusCoreMetrics); } /** From a57ffb4e83934bb6d52d68e4758afa8fd2c85c5c Mon Sep 17 00:00:00 2001 From: mbiscocho Date: Wed, 1 May 2024 17:11:00 -0400 Subject: [PATCH 08/32] Update dependencies --- solr/core/build.gradle | 1 - .../SolrPrometheusCoreRegistry.java | 2 +- .../prometheus/SolrPrometheusRegistry.java | 45 ++-- .../prometheus/core/SolrCoreMetric.java | 9 +- .../prometheus-metrics-core-1.1.0.jar.sha1 | 1 - .../prometheus-metrics-core-LICENSE-ASL.txt | 201 ------------------ .../prometheus-metrics-core-NOTICE.txt | 11 - ...theus-metrics-tracer-common-1.1.0.jar.sha1 | 1 - ...heus-metrics-tracer-common-LICENSE-ASL.txt | 201 ------------------ ...rometheus-metrics-tracer-common-NOTICE.txt | 11 - ...-metrics-tracer-initializer-1.1.0.jar.sha1 | 1 - ...metrics-tracer-initializer-LICENSE-ASL.txt | 201 ------------------ ...heus-metrics-tracer-initializer-NOTICE.txt | 11 - ...metheus-metrics-tracer-otel-1.1.0.jar.sha1 | 1 - ...etheus-metrics-tracer-otel-LICENSE-ASL.txt | 201 ------------------ .../prometheus-metrics-tracer-otel-NOTICE.txt | 11 - ...s-metrics-tracer-otel-agent-1.1.0.jar.sha1 | 1 - ...-metrics-tracer-otel-agent-LICENSE-ASL.txt | 201 ------------------ ...theus-metrics-tracer-otel-agent-NOTICE.txt | 11 - versions.lock | 9 +- 20 files changed, 33 insertions(+), 1098 deletions(-) delete mode 100644 solr/licenses/prometheus-metrics-core-1.1.0.jar.sha1 delete mode 100644 solr/licenses/prometheus-metrics-core-LICENSE-ASL.txt delete mode 100644 solr/licenses/prometheus-metrics-core-NOTICE.txt delete mode 100644 solr/licenses/prometheus-metrics-tracer-common-1.1.0.jar.sha1 delete mode 100644 solr/licenses/prometheus-metrics-tracer-common-LICENSE-ASL.txt delete mode 100644 solr/licenses/prometheus-metrics-tracer-common-NOTICE.txt delete mode 100644 solr/licenses/prometheus-metrics-tracer-initializer-1.1.0.jar.sha1 delete mode 100644 solr/licenses/prometheus-metrics-tracer-initializer-LICENSE-ASL.txt delete mode 100644 solr/licenses/prometheus-metrics-tracer-initializer-NOTICE.txt delete mode 100644 solr/licenses/prometheus-metrics-tracer-otel-1.1.0.jar.sha1 delete mode 100644 solr/licenses/prometheus-metrics-tracer-otel-LICENSE-ASL.txt delete mode 100644 solr/licenses/prometheus-metrics-tracer-otel-NOTICE.txt delete mode 100644 solr/licenses/prometheus-metrics-tracer-otel-agent-1.1.0.jar.sha1 delete mode 100644 solr/licenses/prometheus-metrics-tracer-otel-agent-LICENSE-ASL.txt delete mode 100644 solr/licenses/prometheus-metrics-tracer-otel-agent-NOTICE.txt diff --git a/solr/core/build.gradle b/solr/core/build.gradle index a7d0df10b64..933ab5c04d7 100644 --- a/solr/core/build.gradle +++ b/solr/core/build.gradle @@ -154,7 +154,6 @@ dependencies { runtimeOnly 'org.apache.logging.log4j:log4j-slf4j2-impl' // Prometheus client - implementation 'io.prometheus:prometheus-metrics-core:1.1.0' implementation 'io.prometheus:prometheus-metrics-model:1.1.0' implementation 'io.prometheus:prometheus-metrics-exposition-formats:1.1.0' diff --git a/solr/core/src/java/org/apache/solr/metrics/prometheus/SolrPrometheusCoreRegistry.java b/solr/core/src/java/org/apache/solr/metrics/prometheus/SolrPrometheusCoreRegistry.java index 5a60588d9e8..aea6d17cdda 100644 --- a/solr/core/src/java/org/apache/solr/metrics/prometheus/SolrPrometheusCoreRegistry.java +++ b/solr/core/src/java/org/apache/solr/metrics/prometheus/SolrPrometheusCoreRegistry.java @@ -52,7 +52,7 @@ public SolrPrometheusCoreRegistry(String coreName, boolean cloudMode) { } /** - * Export {@link Meter} to {@link io.prometheus.metrics.model.snapshots.MetricSnapshot} and + * Export {@link Metric} to {@link io.prometheus.metrics.model.snapshots.MetricSnapshot} and * registers the Snapshot * * @param dropwizardMetric the {@link Meter} to be exported diff --git a/solr/core/src/java/org/apache/solr/metrics/prometheus/SolrPrometheusRegistry.java b/solr/core/src/java/org/apache/solr/metrics/prometheus/SolrPrometheusRegistry.java index 5cb6135de89..b141d3fe753 100644 --- a/solr/core/src/java/org/apache/solr/metrics/prometheus/SolrPrometheusRegistry.java +++ b/solr/core/src/java/org/apache/solr/metrics/prometheus/SolrPrometheusRegistry.java @@ -18,7 +18,6 @@ import com.codahale.metrics.Meter; import com.codahale.metrics.Timer; -import io.prometheus.metrics.core.metrics.Gauge; import io.prometheus.metrics.model.snapshots.CounterSnapshot; import io.prometheus.metrics.model.snapshots.GaugeSnapshot; import io.prometheus.metrics.model.snapshots.Labels; @@ -32,7 +31,7 @@ /** * Base class for all {@link SolrPrometheusRegistry} holding {@link MetricSnapshot}s. Can export - * {@link Meter} to {@link MetricSnapshot} to be outputted for {@link + * {@link com.codahale.metrics.Metric} to {@link MetricSnapshot} to be outputted for {@link * org.apache.solr.response.PrometheusResponseWriter} */ public abstract class SolrPrometheusRegistry { @@ -51,11 +50,12 @@ public SolrPrometheusRegistry() { * * @param prometheusMetricName name of prometheus metric * @param dropwizardMetric the {@link Meter} to be exported - * @param labels label names and values to register with {@link CounterSnapshot} + * @param labels label names and values to register with {@link + * io.prometheus.metrics.model.snapshots.CounterSnapshot.CounterDataPointSnapshot} */ public void exportMeter( String prometheusMetricName, Meter dropwizardMetric, Map labels) { - CounterSnapshot.CounterDataPointSnapshot dataPointBuilder = + CounterSnapshot.CounterDataPointSnapshot dataPoint = CounterSnapshot.CounterDataPointSnapshot.builder() .value(dropwizardMetric.getCount()) .labels(Labels.of(new ArrayList<>(labels.keySet()), new ArrayList<>(labels.values()))) @@ -63,7 +63,7 @@ public void exportMeter( if (!metricCounters.containsKey(prometheusMetricName)) { metricCounters.put(prometheusMetricName, new ArrayList<>()); } - metricCounters.get(prometheusMetricName).add(dataPointBuilder); + metricCounters.get(prometheusMetricName).add(dataPoint); } /** @@ -74,13 +74,14 @@ public void exportMeter( * * @param prometheusMetricName name of prometheus metric * @param dropwizardMetric the {@link com.codahale.metrics.Counter} to be exported - * @param labels label names and values to record with {@link CounterSnapshot} + * @param labels label names and values to record with {@link + * io.prometheus.metrics.model.snapshots.CounterSnapshot.CounterDataPointSnapshot} */ public void exportCounter( String prometheusMetricName, com.codahale.metrics.Counter dropwizardMetric, Map labels) { - CounterSnapshot.CounterDataPointSnapshot dataPointBuilder = + CounterSnapshot.CounterDataPointSnapshot dataPoint = CounterSnapshot.CounterDataPointSnapshot.builder() .value(dropwizardMetric.getCount()) .labels(Labels.of(new ArrayList<>(labels.keySet()), new ArrayList<>(labels.values()))) @@ -88,7 +89,7 @@ public void exportCounter( if (!metricCounters.containsKey(prometheusMetricName)) { metricCounters.put(prometheusMetricName, new ArrayList<>()); } - metricCounters.get(prometheusMetricName).add(dataPointBuilder); + metricCounters.get(prometheusMetricName).add(dataPoint); } /** @@ -98,11 +99,12 @@ public void exportCounter( * * @param prometheusMetricName name of prometheus metric * @param dropwizardMetric the {@link Timer} to be exported - * @param labels label names and values to record with {@link GaugeSnapshot} + * @param labels label names and values to record with {@link + * io.prometheus.metrics.model.snapshots.GaugeSnapshot.GaugeDataPointSnapshot} */ public void exportTimer( String prometheusMetricName, Timer dropwizardMetric, Map labels) { - GaugeSnapshot.GaugeDataPointSnapshot dataPointBuilder = + GaugeSnapshot.GaugeDataPointSnapshot dataPoint = GaugeSnapshot.GaugeDataPointSnapshot.builder() .value(dropwizardMetric.getCount()) .labels(Labels.of(new ArrayList<>(labels.keySet()), new ArrayList<>(labels.values()))) @@ -110,7 +112,7 @@ public void exportTimer( if (!metricGauges.containsKey(prometheusMetricName)) { metricGauges.put(prometheusMetricName, new ArrayList<>()); } - metricGauges.get(prometheusMetricName).add(dataPointBuilder); + metricGauges.get(prometheusMetricName).add(dataPoint); } /** @@ -120,7 +122,8 @@ public void exportTimer( * * @param prometheusMetricName name of prometheus metric * @param dropwizardMetricRaw the {@link com.codahale.metrics.Gauge} to be exported - * @param labelsMap label names and values to record with {@link Gauge} + * @param labelsMap label names and values to record with {@link + * io.prometheus.metrics.model.snapshots.GaugeSnapshot.GaugeDataPointSnapshot} */ public void exportGauge( String prometheusMetricName, @@ -131,14 +134,14 @@ public void exportGauge( metricGauges.put(prometheusMetricName, new ArrayList<>()); } if (dropwizardMetric instanceof Number) { - GaugeSnapshot.GaugeDataPointSnapshot dataPointBuilder = + GaugeSnapshot.GaugeDataPointSnapshot dataPoint = GaugeSnapshot.GaugeDataPointSnapshot.builder() .value(((Number) dropwizardMetric).doubleValue()) .labels( Labels.of( new ArrayList<>(labelsMap.keySet()), new ArrayList<>(labelsMap.values()))) .build(); - metricGauges.get(prometheusMetricName).add(dataPointBuilder); + metricGauges.get(prometheusMetricName).add(dataPoint); } else if (dropwizardMetric instanceof HashMap) { HashMap itemsMap = (HashMap) dropwizardMetric; for (Object item : itemsMap.keySet()) { @@ -147,12 +150,12 @@ public void exportGauge( labelKeys.add("item"); List labelValues = new ArrayList<>(labelsMap.values()); labelValues.add((String) item); - GaugeSnapshot.GaugeDataPointSnapshot dataPointBuilder = + GaugeSnapshot.GaugeDataPointSnapshot dataPoint = GaugeSnapshot.GaugeDataPointSnapshot.builder() .value(((Number) itemsMap.get(item)).doubleValue()) .labels(Labels.of(labelKeys, labelValues)) .build(); - metricGauges.get(prometheusMetricName).add(dataPointBuilder); + metricGauges.get(prometheusMetricName).add(dataPoint); } } } @@ -160,11 +163,13 @@ public void exportGauge( public MetricSnapshots collect() { ArrayList snapshots = new ArrayList<>(); - for (String names : metricCounters.keySet()) { - snapshots.add(new CounterSnapshot(new MetricMetadata(names), metricCounters.get(names))); + for (String metricName : metricCounters.keySet()) { + snapshots.add( + new CounterSnapshot(new MetricMetadata(metricName), metricCounters.get(metricName))); } - for (String names : metricGauges.keySet()) { - snapshots.add(new GaugeSnapshot(new MetricMetadata(names), metricGauges.get(names))); + for (String metricName : metricGauges.keySet()) { + snapshots.add( + new GaugeSnapshot(new MetricMetadata(metricName), metricGauges.get(metricName))); } return new MetricSnapshots(snapshots); } diff --git a/solr/core/src/java/org/apache/solr/metrics/prometheus/core/SolrCoreMetric.java b/solr/core/src/java/org/apache/solr/metrics/prometheus/core/SolrCoreMetric.java index 95cf967ce3f..4b5fb8a644d 100644 --- a/solr/core/src/java/org/apache/solr/metrics/prometheus/core/SolrCoreMetric.java +++ b/solr/core/src/java/org/apache/solr/metrics/prometheus/core/SolrCoreMetric.java @@ -23,10 +23,11 @@ /** * Base class is a wrapper to export {@link com.codahale.metrics.Metric} to {@link - * io.prometheus.metrics.core.metrics.Metric} and register to a {@link SolrPrometheusCoreRegistry} - * {@link com.codahale.metrics.MetricRegistry} does not support tags unlike prometheus. Metrics - * registered to the registry need to be parsed out from the metric name and exported to {@link - * io.prometheus.metrics.model.snapshots.MetricSnapshot} be output to Prometheus + * io.prometheus.metrics.model.snapshots.MetricSnapshot} and register to a {@link + * SolrPrometheusCoreRegistry} {@link com.codahale.metrics.MetricRegistry} does not support tags + * unlike prometheus. Metrics registered to the registry need to be parsed out from the metric name + * and exported to {@link io.prometheus.metrics.model.snapshots.MetricSnapshot} be output to + * Prometheus */ public abstract class SolrCoreMetric { public Metric dropwizardMetric; diff --git a/solr/licenses/prometheus-metrics-core-1.1.0.jar.sha1 b/solr/licenses/prometheus-metrics-core-1.1.0.jar.sha1 deleted file mode 100644 index aefaedc39a6..00000000000 --- a/solr/licenses/prometheus-metrics-core-1.1.0.jar.sha1 +++ /dev/null @@ -1 +0,0 @@ -b25424c069a44fce42b55626512718d49c9dcc5d diff --git a/solr/licenses/prometheus-metrics-core-LICENSE-ASL.txt b/solr/licenses/prometheus-metrics-core-LICENSE-ASL.txt deleted file mode 100644 index f49a4e16e68..00000000000 --- a/solr/licenses/prometheus-metrics-core-LICENSE-ASL.txt +++ /dev/null @@ -1,201 +0,0 @@ - Apache License - Version 2.0, January 2004 - http://www.apache.org/licenses/ - - TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION - - 1. Definitions. - - "License" shall mean the terms and conditions for use, reproduction, - and distribution as defined by Sections 1 through 9 of this document. - - "Licensor" shall mean the copyright owner or entity authorized by - the copyright owner that is granting the License. - - "Legal Entity" shall mean the union of the acting entity and all - other entities that control, are controlled by, or are under common - control with that entity. For the purposes of this definition, - "control" means (i) the power, direct or indirect, to cause the - direction or management of such entity, whether by contract or - otherwise, or (ii) ownership of fifty percent (50%) or more of the - outstanding shares, or (iii) beneficial ownership of such entity. - - "You" (or "Your") shall mean an individual or Legal Entity - exercising permissions granted by this License. - - "Source" form shall mean the preferred form for making modifications, - including but not limited to software source code, documentation - source, and configuration files. - - "Object" form shall mean any form resulting from mechanical - transformation or translation of a Source form, including but - not limited to compiled object code, generated documentation, - and conversions to other media types. - - "Work" shall mean the work of authorship, whether in Source or - Object form, made available under the License, as indicated by a - copyright notice that is included in or attached to the work - (an example is provided in the Appendix below). - - "Derivative Works" shall mean any work, whether in Source or Object - form, that is based on (or derived from) the Work and for which the - editorial revisions, annotations, elaborations, or other modifications - represent, as a whole, an original work of authorship. For the purposes - of this License, Derivative Works shall not include works that remain - separable from, or merely link (or bind by name) to the interfaces of, - the Work and Derivative Works thereof. - - "Contribution" shall mean any work of authorship, including - the original version of the Work and any modifications or additions - to that Work or Derivative Works thereof, that is intentionally - submitted to Licensor for inclusion in the Work by the copyright owner - or by an individual or Legal Entity authorized to submit on behalf of - the copyright owner. For the purposes of this definition, "submitted" - means any form of electronic, verbal, or written communication sent - to the Licensor or its representatives, including but not limited to - communication on electronic mailing lists, source code control systems, - and issue tracking systems that are managed by, or on behalf of, the - Licensor for the purpose of discussing and improving the Work, but - excluding communication that is conspicuously marked or otherwise - designated in writing by the copyright owner as "Not a Contribution." - - "Contributor" shall mean Licensor and any individual or Legal Entity - on behalf of whom a Contribution has been received by Licensor and - subsequently incorporated within the Work. - - 2. Grant of Copyright License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - copyright license to reproduce, prepare Derivative Works of, - publicly display, publicly perform, sublicense, and distribute the - Work and such Derivative Works in Source or Object form. - - 3. Grant of Patent License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - (except as stated in this section) patent license to make, have made, - use, offer to sell, sell, import, and otherwise transfer the Work, - where such license applies only to those patent claims licensable - by such Contributor that are necessarily infringed by their - Contribution(s) alone or by combination of their Contribution(s) - with the Work to which such Contribution(s) was submitted. If You - institute patent litigation against any entity (including a - cross-claim or counterclaim in a lawsuit) alleging that the Work - or a Contribution incorporated within the Work constitutes direct - or contributory patent infringement, then any patent licenses - granted to You under this License for that Work shall terminate - as of the date such litigation is filed. - - 4. Redistribution. You may reproduce and distribute copies of the - Work or Derivative Works thereof in any medium, with or without - modifications, and in Source or Object form, provided that You - meet the following conditions: - - (a) You must give any other recipients of the Work or - Derivative Works a copy of this License; and - - (b) You must cause any modified files to carry prominent notices - stating that You changed the files; and - - (c) You must retain, in the Source form of any Derivative Works - that You distribute, all copyright, patent, trademark, and - attribution notices from the Source form of the Work, - excluding those notices that do not pertain to any part of - the Derivative Works; and - - (d) If the Work includes a "NOTICE" text file as part of its - distribution, then any Derivative Works that You distribute must - include a readable copy of the attribution notices contained - within such NOTICE file, excluding those notices that do not - pertain to any part of the Derivative Works, in at least one - of the following places: within a NOTICE text file distributed - as part of the Derivative Works; within the Source form or - documentation, if provided along with the Derivative Works; or, - within a display generated by the Derivative Works, if and - wherever such third-party notices normally appear. The contents - of the NOTICE file are for informational purposes only and - do not modify the License. You may add Your own attribution - notices within Derivative Works that You distribute, alongside - or as an addendum to the NOTICE text from the Work, provided - that such additional attribution notices cannot be construed - as modifying the License. - - You may add Your own copyright statement to Your modifications and - may provide additional or different license terms and conditions - for use, reproduction, or distribution of Your modifications, or - for any such Derivative Works as a whole, provided Your use, - reproduction, and distribution of the Work otherwise complies with - the conditions stated in this License. - - 5. Submission of Contributions. Unless You explicitly state otherwise, - any Contribution intentionally submitted for inclusion in the Work - by You to the Licensor shall be under the terms and conditions of - this License, without any additional terms or conditions. - Notwithstanding the above, nothing herein shall supersede or modify - the terms of any separate license agreement you may have executed - with Licensor regarding such Contributions. - - 6. Trademarks. This License does not grant permission to use the trade - names, trademarks, service marks, or product names of the Licensor, - except as required for reasonable and customary use in describing the - origin of the Work and reproducing the content of the NOTICE file. - - 7. Disclaimer of Warranty. Unless required by applicable law or - agreed to in writing, Licensor provides the Work (and each - Contributor provides its Contributions) on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - implied, including, without limitation, any warranties or conditions - of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A - PARTICULAR PURPOSE. You are solely responsible for determining the - appropriateness of using or redistributing the Work and assume any - risks associated with Your exercise of permissions under this License. - - 8. Limitation of Liability. In no event and under no legal theory, - whether in tort (including negligence), contract, or otherwise, - unless required by applicable law (such as deliberate and grossly - negligent acts) or agreed to in writing, shall any Contributor be - liable to You for damages, including any direct, indirect, special, - incidental, or consequential damages of any character arising as a - result of this License or out of the use or inability to use the - Work (including but not limited to damages for loss of goodwill, - work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses), even if such Contributor - has been advised of the possibility of such damages. - - 9. Accepting Warranty or Additional Liability. While redistributing - the Work or Derivative Works thereof, You may choose to offer, - and charge a fee for, acceptance of support, warranty, indemnity, - or other liability obligations and/or rights consistent with this - License. However, in accepting such obligations, You may act only - on Your own behalf and on Your sole responsibility, not on behalf - of any other Contributor, and only if You agree to indemnify, - defend, and hold each Contributor harmless for any liability - incurred by, or claims asserted against, such Contributor by reason - of your accepting any such warranty or additional liability. - - END OF TERMS AND CONDITIONS - - APPENDIX: How to apply the Apache License to your work. - - To apply the Apache License to your work, attach the following - boilerplate notice, with the fields enclosed by brackets "[]" - replaced with your own identifying information. (Don't include - the brackets!) The text should be enclosed in the appropriate - comment syntax for the file format. We also recommend that a - file or class name and description of purpose be included on the - same "printed page" as the copyright notice for easier - identification within third-party archives. - - Copyright [yyyy] [name of copyright owner] - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. \ No newline at end of file diff --git a/solr/licenses/prometheus-metrics-core-NOTICE.txt b/solr/licenses/prometheus-metrics-core-NOTICE.txt deleted file mode 100644 index cbd3cd95bef..00000000000 --- a/solr/licenses/prometheus-metrics-core-NOTICE.txt +++ /dev/null @@ -1,11 +0,0 @@ -Prometheus instrumentation library for JVM applications -Copyright 2012-2015 The Prometheus Authors - -This product includes software developed at -Boxever Ltd. (http://www.boxever.com/). - -This product includes software developed at -SoundCloud Ltd. (http://soundcloud.com/). - -This product includes software developed as part of the -Ocelli project by Netflix Inc. (https://github.com/Netflix/ocelli/). \ No newline at end of file diff --git a/solr/licenses/prometheus-metrics-tracer-common-1.1.0.jar.sha1 b/solr/licenses/prometheus-metrics-tracer-common-1.1.0.jar.sha1 deleted file mode 100644 index 942ecf85c06..00000000000 --- a/solr/licenses/prometheus-metrics-tracer-common-1.1.0.jar.sha1 +++ /dev/null @@ -1 +0,0 @@ -daf7dbdb867221e418be0771663eae50a9199228 diff --git a/solr/licenses/prometheus-metrics-tracer-common-LICENSE-ASL.txt b/solr/licenses/prometheus-metrics-tracer-common-LICENSE-ASL.txt deleted file mode 100644 index f49a4e16e68..00000000000 --- a/solr/licenses/prometheus-metrics-tracer-common-LICENSE-ASL.txt +++ /dev/null @@ -1,201 +0,0 @@ - Apache License - Version 2.0, January 2004 - http://www.apache.org/licenses/ - - TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION - - 1. Definitions. - - "License" shall mean the terms and conditions for use, reproduction, - and distribution as defined by Sections 1 through 9 of this document. - - "Licensor" shall mean the copyright owner or entity authorized by - the copyright owner that is granting the License. - - "Legal Entity" shall mean the union of the acting entity and all - other entities that control, are controlled by, or are under common - control with that entity. For the purposes of this definition, - "control" means (i) the power, direct or indirect, to cause the - direction or management of such entity, whether by contract or - otherwise, or (ii) ownership of fifty percent (50%) or more of the - outstanding shares, or (iii) beneficial ownership of such entity. - - "You" (or "Your") shall mean an individual or Legal Entity - exercising permissions granted by this License. - - "Source" form shall mean the preferred form for making modifications, - including but not limited to software source code, documentation - source, and configuration files. - - "Object" form shall mean any form resulting from mechanical - transformation or translation of a Source form, including but - not limited to compiled object code, generated documentation, - and conversions to other media types. - - "Work" shall mean the work of authorship, whether in Source or - Object form, made available under the License, as indicated by a - copyright notice that is included in or attached to the work - (an example is provided in the Appendix below). - - "Derivative Works" shall mean any work, whether in Source or Object - form, that is based on (or derived from) the Work and for which the - editorial revisions, annotations, elaborations, or other modifications - represent, as a whole, an original work of authorship. For the purposes - of this License, Derivative Works shall not include works that remain - separable from, or merely link (or bind by name) to the interfaces of, - the Work and Derivative Works thereof. - - "Contribution" shall mean any work of authorship, including - the original version of the Work and any modifications or additions - to that Work or Derivative Works thereof, that is intentionally - submitted to Licensor for inclusion in the Work by the copyright owner - or by an individual or Legal Entity authorized to submit on behalf of - the copyright owner. For the purposes of this definition, "submitted" - means any form of electronic, verbal, or written communication sent - to the Licensor or its representatives, including but not limited to - communication on electronic mailing lists, source code control systems, - and issue tracking systems that are managed by, or on behalf of, the - Licensor for the purpose of discussing and improving the Work, but - excluding communication that is conspicuously marked or otherwise - designated in writing by the copyright owner as "Not a Contribution." - - "Contributor" shall mean Licensor and any individual or Legal Entity - on behalf of whom a Contribution has been received by Licensor and - subsequently incorporated within the Work. - - 2. Grant of Copyright License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - copyright license to reproduce, prepare Derivative Works of, - publicly display, publicly perform, sublicense, and distribute the - Work and such Derivative Works in Source or Object form. - - 3. Grant of Patent License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - (except as stated in this section) patent license to make, have made, - use, offer to sell, sell, import, and otherwise transfer the Work, - where such license applies only to those patent claims licensable - by such Contributor that are necessarily infringed by their - Contribution(s) alone or by combination of their Contribution(s) - with the Work to which such Contribution(s) was submitted. If You - institute patent litigation against any entity (including a - cross-claim or counterclaim in a lawsuit) alleging that the Work - or a Contribution incorporated within the Work constitutes direct - or contributory patent infringement, then any patent licenses - granted to You under this License for that Work shall terminate - as of the date such litigation is filed. - - 4. Redistribution. You may reproduce and distribute copies of the - Work or Derivative Works thereof in any medium, with or without - modifications, and in Source or Object form, provided that You - meet the following conditions: - - (a) You must give any other recipients of the Work or - Derivative Works a copy of this License; and - - (b) You must cause any modified files to carry prominent notices - stating that You changed the files; and - - (c) You must retain, in the Source form of any Derivative Works - that You distribute, all copyright, patent, trademark, and - attribution notices from the Source form of the Work, - excluding those notices that do not pertain to any part of - the Derivative Works; and - - (d) If the Work includes a "NOTICE" text file as part of its - distribution, then any Derivative Works that You distribute must - include a readable copy of the attribution notices contained - within such NOTICE file, excluding those notices that do not - pertain to any part of the Derivative Works, in at least one - of the following places: within a NOTICE text file distributed - as part of the Derivative Works; within the Source form or - documentation, if provided along with the Derivative Works; or, - within a display generated by the Derivative Works, if and - wherever such third-party notices normally appear. The contents - of the NOTICE file are for informational purposes only and - do not modify the License. You may add Your own attribution - notices within Derivative Works that You distribute, alongside - or as an addendum to the NOTICE text from the Work, provided - that such additional attribution notices cannot be construed - as modifying the License. - - You may add Your own copyright statement to Your modifications and - may provide additional or different license terms and conditions - for use, reproduction, or distribution of Your modifications, or - for any such Derivative Works as a whole, provided Your use, - reproduction, and distribution of the Work otherwise complies with - the conditions stated in this License. - - 5. Submission of Contributions. Unless You explicitly state otherwise, - any Contribution intentionally submitted for inclusion in the Work - by You to the Licensor shall be under the terms and conditions of - this License, without any additional terms or conditions. - Notwithstanding the above, nothing herein shall supersede or modify - the terms of any separate license agreement you may have executed - with Licensor regarding such Contributions. - - 6. Trademarks. This License does not grant permission to use the trade - names, trademarks, service marks, or product names of the Licensor, - except as required for reasonable and customary use in describing the - origin of the Work and reproducing the content of the NOTICE file. - - 7. Disclaimer of Warranty. Unless required by applicable law or - agreed to in writing, Licensor provides the Work (and each - Contributor provides its Contributions) on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - implied, including, without limitation, any warranties or conditions - of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A - PARTICULAR PURPOSE. You are solely responsible for determining the - appropriateness of using or redistributing the Work and assume any - risks associated with Your exercise of permissions under this License. - - 8. Limitation of Liability. In no event and under no legal theory, - whether in tort (including negligence), contract, or otherwise, - unless required by applicable law (such as deliberate and grossly - negligent acts) or agreed to in writing, shall any Contributor be - liable to You for damages, including any direct, indirect, special, - incidental, or consequential damages of any character arising as a - result of this License or out of the use or inability to use the - Work (including but not limited to damages for loss of goodwill, - work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses), even if such Contributor - has been advised of the possibility of such damages. - - 9. Accepting Warranty or Additional Liability. While redistributing - the Work or Derivative Works thereof, You may choose to offer, - and charge a fee for, acceptance of support, warranty, indemnity, - or other liability obligations and/or rights consistent with this - License. However, in accepting such obligations, You may act only - on Your own behalf and on Your sole responsibility, not on behalf - of any other Contributor, and only if You agree to indemnify, - defend, and hold each Contributor harmless for any liability - incurred by, or claims asserted against, such Contributor by reason - of your accepting any such warranty or additional liability. - - END OF TERMS AND CONDITIONS - - APPENDIX: How to apply the Apache License to your work. - - To apply the Apache License to your work, attach the following - boilerplate notice, with the fields enclosed by brackets "[]" - replaced with your own identifying information. (Don't include - the brackets!) The text should be enclosed in the appropriate - comment syntax for the file format. We also recommend that a - file or class name and description of purpose be included on the - same "printed page" as the copyright notice for easier - identification within third-party archives. - - Copyright [yyyy] [name of copyright owner] - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. \ No newline at end of file diff --git a/solr/licenses/prometheus-metrics-tracer-common-NOTICE.txt b/solr/licenses/prometheus-metrics-tracer-common-NOTICE.txt deleted file mode 100644 index cbd3cd95bef..00000000000 --- a/solr/licenses/prometheus-metrics-tracer-common-NOTICE.txt +++ /dev/null @@ -1,11 +0,0 @@ -Prometheus instrumentation library for JVM applications -Copyright 2012-2015 The Prometheus Authors - -This product includes software developed at -Boxever Ltd. (http://www.boxever.com/). - -This product includes software developed at -SoundCloud Ltd. (http://soundcloud.com/). - -This product includes software developed as part of the -Ocelli project by Netflix Inc. (https://github.com/Netflix/ocelli/). \ No newline at end of file diff --git a/solr/licenses/prometheus-metrics-tracer-initializer-1.1.0.jar.sha1 b/solr/licenses/prometheus-metrics-tracer-initializer-1.1.0.jar.sha1 deleted file mode 100644 index f308f25736c..00000000000 --- a/solr/licenses/prometheus-metrics-tracer-initializer-1.1.0.jar.sha1 +++ /dev/null @@ -1 +0,0 @@ -169f3dae0c95b4154696407de0e1213373f074e1 diff --git a/solr/licenses/prometheus-metrics-tracer-initializer-LICENSE-ASL.txt b/solr/licenses/prometheus-metrics-tracer-initializer-LICENSE-ASL.txt deleted file mode 100644 index f49a4e16e68..00000000000 --- a/solr/licenses/prometheus-metrics-tracer-initializer-LICENSE-ASL.txt +++ /dev/null @@ -1,201 +0,0 @@ - Apache License - Version 2.0, January 2004 - http://www.apache.org/licenses/ - - TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION - - 1. Definitions. - - "License" shall mean the terms and conditions for use, reproduction, - and distribution as defined by Sections 1 through 9 of this document. - - "Licensor" shall mean the copyright owner or entity authorized by - the copyright owner that is granting the License. - - "Legal Entity" shall mean the union of the acting entity and all - other entities that control, are controlled by, or are under common - control with that entity. For the purposes of this definition, - "control" means (i) the power, direct or indirect, to cause the - direction or management of such entity, whether by contract or - otherwise, or (ii) ownership of fifty percent (50%) or more of the - outstanding shares, or (iii) beneficial ownership of such entity. - - "You" (or "Your") shall mean an individual or Legal Entity - exercising permissions granted by this License. - - "Source" form shall mean the preferred form for making modifications, - including but not limited to software source code, documentation - source, and configuration files. - - "Object" form shall mean any form resulting from mechanical - transformation or translation of a Source form, including but - not limited to compiled object code, generated documentation, - and conversions to other media types. - - "Work" shall mean the work of authorship, whether in Source or - Object form, made available under the License, as indicated by a - copyright notice that is included in or attached to the work - (an example is provided in the Appendix below). - - "Derivative Works" shall mean any work, whether in Source or Object - form, that is based on (or derived from) the Work and for which the - editorial revisions, annotations, elaborations, or other modifications - represent, as a whole, an original work of authorship. For the purposes - of this License, Derivative Works shall not include works that remain - separable from, or merely link (or bind by name) to the interfaces of, - the Work and Derivative Works thereof. - - "Contribution" shall mean any work of authorship, including - the original version of the Work and any modifications or additions - to that Work or Derivative Works thereof, that is intentionally - submitted to Licensor for inclusion in the Work by the copyright owner - or by an individual or Legal Entity authorized to submit on behalf of - the copyright owner. For the purposes of this definition, "submitted" - means any form of electronic, verbal, or written communication sent - to the Licensor or its representatives, including but not limited to - communication on electronic mailing lists, source code control systems, - and issue tracking systems that are managed by, or on behalf of, the - Licensor for the purpose of discussing and improving the Work, but - excluding communication that is conspicuously marked or otherwise - designated in writing by the copyright owner as "Not a Contribution." - - "Contributor" shall mean Licensor and any individual or Legal Entity - on behalf of whom a Contribution has been received by Licensor and - subsequently incorporated within the Work. - - 2. Grant of Copyright License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - copyright license to reproduce, prepare Derivative Works of, - publicly display, publicly perform, sublicense, and distribute the - Work and such Derivative Works in Source or Object form. - - 3. Grant of Patent License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - (except as stated in this section) patent license to make, have made, - use, offer to sell, sell, import, and otherwise transfer the Work, - where such license applies only to those patent claims licensable - by such Contributor that are necessarily infringed by their - Contribution(s) alone or by combination of their Contribution(s) - with the Work to which such Contribution(s) was submitted. If You - institute patent litigation against any entity (including a - cross-claim or counterclaim in a lawsuit) alleging that the Work - or a Contribution incorporated within the Work constitutes direct - or contributory patent infringement, then any patent licenses - granted to You under this License for that Work shall terminate - as of the date such litigation is filed. - - 4. Redistribution. You may reproduce and distribute copies of the - Work or Derivative Works thereof in any medium, with or without - modifications, and in Source or Object form, provided that You - meet the following conditions: - - (a) You must give any other recipients of the Work or - Derivative Works a copy of this License; and - - (b) You must cause any modified files to carry prominent notices - stating that You changed the files; and - - (c) You must retain, in the Source form of any Derivative Works - that You distribute, all copyright, patent, trademark, and - attribution notices from the Source form of the Work, - excluding those notices that do not pertain to any part of - the Derivative Works; and - - (d) If the Work includes a "NOTICE" text file as part of its - distribution, then any Derivative Works that You distribute must - include a readable copy of the attribution notices contained - within such NOTICE file, excluding those notices that do not - pertain to any part of the Derivative Works, in at least one - of the following places: within a NOTICE text file distributed - as part of the Derivative Works; within the Source form or - documentation, if provided along with the Derivative Works; or, - within a display generated by the Derivative Works, if and - wherever such third-party notices normally appear. The contents - of the NOTICE file are for informational purposes only and - do not modify the License. You may add Your own attribution - notices within Derivative Works that You distribute, alongside - or as an addendum to the NOTICE text from the Work, provided - that such additional attribution notices cannot be construed - as modifying the License. - - You may add Your own copyright statement to Your modifications and - may provide additional or different license terms and conditions - for use, reproduction, or distribution of Your modifications, or - for any such Derivative Works as a whole, provided Your use, - reproduction, and distribution of the Work otherwise complies with - the conditions stated in this License. - - 5. Submission of Contributions. Unless You explicitly state otherwise, - any Contribution intentionally submitted for inclusion in the Work - by You to the Licensor shall be under the terms and conditions of - this License, without any additional terms or conditions. - Notwithstanding the above, nothing herein shall supersede or modify - the terms of any separate license agreement you may have executed - with Licensor regarding such Contributions. - - 6. Trademarks. This License does not grant permission to use the trade - names, trademarks, service marks, or product names of the Licensor, - except as required for reasonable and customary use in describing the - origin of the Work and reproducing the content of the NOTICE file. - - 7. Disclaimer of Warranty. Unless required by applicable law or - agreed to in writing, Licensor provides the Work (and each - Contributor provides its Contributions) on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - implied, including, without limitation, any warranties or conditions - of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A - PARTICULAR PURPOSE. You are solely responsible for determining the - appropriateness of using or redistributing the Work and assume any - risks associated with Your exercise of permissions under this License. - - 8. Limitation of Liability. In no event and under no legal theory, - whether in tort (including negligence), contract, or otherwise, - unless required by applicable law (such as deliberate and grossly - negligent acts) or agreed to in writing, shall any Contributor be - liable to You for damages, including any direct, indirect, special, - incidental, or consequential damages of any character arising as a - result of this License or out of the use or inability to use the - Work (including but not limited to damages for loss of goodwill, - work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses), even if such Contributor - has been advised of the possibility of such damages. - - 9. Accepting Warranty or Additional Liability. While redistributing - the Work or Derivative Works thereof, You may choose to offer, - and charge a fee for, acceptance of support, warranty, indemnity, - or other liability obligations and/or rights consistent with this - License. However, in accepting such obligations, You may act only - on Your own behalf and on Your sole responsibility, not on behalf - of any other Contributor, and only if You agree to indemnify, - defend, and hold each Contributor harmless for any liability - incurred by, or claims asserted against, such Contributor by reason - of your accepting any such warranty or additional liability. - - END OF TERMS AND CONDITIONS - - APPENDIX: How to apply the Apache License to your work. - - To apply the Apache License to your work, attach the following - boilerplate notice, with the fields enclosed by brackets "[]" - replaced with your own identifying information. (Don't include - the brackets!) The text should be enclosed in the appropriate - comment syntax for the file format. We also recommend that a - file or class name and description of purpose be included on the - same "printed page" as the copyright notice for easier - identification within third-party archives. - - Copyright [yyyy] [name of copyright owner] - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. \ No newline at end of file diff --git a/solr/licenses/prometheus-metrics-tracer-initializer-NOTICE.txt b/solr/licenses/prometheus-metrics-tracer-initializer-NOTICE.txt deleted file mode 100644 index cbd3cd95bef..00000000000 --- a/solr/licenses/prometheus-metrics-tracer-initializer-NOTICE.txt +++ /dev/null @@ -1,11 +0,0 @@ -Prometheus instrumentation library for JVM applications -Copyright 2012-2015 The Prometheus Authors - -This product includes software developed at -Boxever Ltd. (http://www.boxever.com/). - -This product includes software developed at -SoundCloud Ltd. (http://soundcloud.com/). - -This product includes software developed as part of the -Ocelli project by Netflix Inc. (https://github.com/Netflix/ocelli/). \ No newline at end of file diff --git a/solr/licenses/prometheus-metrics-tracer-otel-1.1.0.jar.sha1 b/solr/licenses/prometheus-metrics-tracer-otel-1.1.0.jar.sha1 deleted file mode 100644 index c28f7197ac4..00000000000 --- a/solr/licenses/prometheus-metrics-tracer-otel-1.1.0.jar.sha1 +++ /dev/null @@ -1 +0,0 @@ -25c2d488b084a9757a7b5e23cbce8dc812147e54 diff --git a/solr/licenses/prometheus-metrics-tracer-otel-LICENSE-ASL.txt b/solr/licenses/prometheus-metrics-tracer-otel-LICENSE-ASL.txt deleted file mode 100644 index f49a4e16e68..00000000000 --- a/solr/licenses/prometheus-metrics-tracer-otel-LICENSE-ASL.txt +++ /dev/null @@ -1,201 +0,0 @@ - Apache License - Version 2.0, January 2004 - http://www.apache.org/licenses/ - - TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION - - 1. Definitions. - - "License" shall mean the terms and conditions for use, reproduction, - and distribution as defined by Sections 1 through 9 of this document. - - "Licensor" shall mean the copyright owner or entity authorized by - the copyright owner that is granting the License. - - "Legal Entity" shall mean the union of the acting entity and all - other entities that control, are controlled by, or are under common - control with that entity. For the purposes of this definition, - "control" means (i) the power, direct or indirect, to cause the - direction or management of such entity, whether by contract or - otherwise, or (ii) ownership of fifty percent (50%) or more of the - outstanding shares, or (iii) beneficial ownership of such entity. - - "You" (or "Your") shall mean an individual or Legal Entity - exercising permissions granted by this License. - - "Source" form shall mean the preferred form for making modifications, - including but not limited to software source code, documentation - source, and configuration files. - - "Object" form shall mean any form resulting from mechanical - transformation or translation of a Source form, including but - not limited to compiled object code, generated documentation, - and conversions to other media types. - - "Work" shall mean the work of authorship, whether in Source or - Object form, made available under the License, as indicated by a - copyright notice that is included in or attached to the work - (an example is provided in the Appendix below). - - "Derivative Works" shall mean any work, whether in Source or Object - form, that is based on (or derived from) the Work and for which the - editorial revisions, annotations, elaborations, or other modifications - represent, as a whole, an original work of authorship. For the purposes - of this License, Derivative Works shall not include works that remain - separable from, or merely link (or bind by name) to the interfaces of, - the Work and Derivative Works thereof. - - "Contribution" shall mean any work of authorship, including - the original version of the Work and any modifications or additions - to that Work or Derivative Works thereof, that is intentionally - submitted to Licensor for inclusion in the Work by the copyright owner - or by an individual or Legal Entity authorized to submit on behalf of - the copyright owner. For the purposes of this definition, "submitted" - means any form of electronic, verbal, or written communication sent - to the Licensor or its representatives, including but not limited to - communication on electronic mailing lists, source code control systems, - and issue tracking systems that are managed by, or on behalf of, the - Licensor for the purpose of discussing and improving the Work, but - excluding communication that is conspicuously marked or otherwise - designated in writing by the copyright owner as "Not a Contribution." - - "Contributor" shall mean Licensor and any individual or Legal Entity - on behalf of whom a Contribution has been received by Licensor and - subsequently incorporated within the Work. - - 2. Grant of Copyright License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - copyright license to reproduce, prepare Derivative Works of, - publicly display, publicly perform, sublicense, and distribute the - Work and such Derivative Works in Source or Object form. - - 3. Grant of Patent License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - (except as stated in this section) patent license to make, have made, - use, offer to sell, sell, import, and otherwise transfer the Work, - where such license applies only to those patent claims licensable - by such Contributor that are necessarily infringed by their - Contribution(s) alone or by combination of their Contribution(s) - with the Work to which such Contribution(s) was submitted. If You - institute patent litigation against any entity (including a - cross-claim or counterclaim in a lawsuit) alleging that the Work - or a Contribution incorporated within the Work constitutes direct - or contributory patent infringement, then any patent licenses - granted to You under this License for that Work shall terminate - as of the date such litigation is filed. - - 4. Redistribution. You may reproduce and distribute copies of the - Work or Derivative Works thereof in any medium, with or without - modifications, and in Source or Object form, provided that You - meet the following conditions: - - (a) You must give any other recipients of the Work or - Derivative Works a copy of this License; and - - (b) You must cause any modified files to carry prominent notices - stating that You changed the files; and - - (c) You must retain, in the Source form of any Derivative Works - that You distribute, all copyright, patent, trademark, and - attribution notices from the Source form of the Work, - excluding those notices that do not pertain to any part of - the Derivative Works; and - - (d) If the Work includes a "NOTICE" text file as part of its - distribution, then any Derivative Works that You distribute must - include a readable copy of the attribution notices contained - within such NOTICE file, excluding those notices that do not - pertain to any part of the Derivative Works, in at least one - of the following places: within a NOTICE text file distributed - as part of the Derivative Works; within the Source form or - documentation, if provided along with the Derivative Works; or, - within a display generated by the Derivative Works, if and - wherever such third-party notices normally appear. The contents - of the NOTICE file are for informational purposes only and - do not modify the License. You may add Your own attribution - notices within Derivative Works that You distribute, alongside - or as an addendum to the NOTICE text from the Work, provided - that such additional attribution notices cannot be construed - as modifying the License. - - You may add Your own copyright statement to Your modifications and - may provide additional or different license terms and conditions - for use, reproduction, or distribution of Your modifications, or - for any such Derivative Works as a whole, provided Your use, - reproduction, and distribution of the Work otherwise complies with - the conditions stated in this License. - - 5. Submission of Contributions. Unless You explicitly state otherwise, - any Contribution intentionally submitted for inclusion in the Work - by You to the Licensor shall be under the terms and conditions of - this License, without any additional terms or conditions. - Notwithstanding the above, nothing herein shall supersede or modify - the terms of any separate license agreement you may have executed - with Licensor regarding such Contributions. - - 6. Trademarks. This License does not grant permission to use the trade - names, trademarks, service marks, or product names of the Licensor, - except as required for reasonable and customary use in describing the - origin of the Work and reproducing the content of the NOTICE file. - - 7. Disclaimer of Warranty. Unless required by applicable law or - agreed to in writing, Licensor provides the Work (and each - Contributor provides its Contributions) on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - implied, including, without limitation, any warranties or conditions - of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A - PARTICULAR PURPOSE. You are solely responsible for determining the - appropriateness of using or redistributing the Work and assume any - risks associated with Your exercise of permissions under this License. - - 8. Limitation of Liability. In no event and under no legal theory, - whether in tort (including negligence), contract, or otherwise, - unless required by applicable law (such as deliberate and grossly - negligent acts) or agreed to in writing, shall any Contributor be - liable to You for damages, including any direct, indirect, special, - incidental, or consequential damages of any character arising as a - result of this License or out of the use or inability to use the - Work (including but not limited to damages for loss of goodwill, - work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses), even if such Contributor - has been advised of the possibility of such damages. - - 9. Accepting Warranty or Additional Liability. While redistributing - the Work or Derivative Works thereof, You may choose to offer, - and charge a fee for, acceptance of support, warranty, indemnity, - or other liability obligations and/or rights consistent with this - License. However, in accepting such obligations, You may act only - on Your own behalf and on Your sole responsibility, not on behalf - of any other Contributor, and only if You agree to indemnify, - defend, and hold each Contributor harmless for any liability - incurred by, or claims asserted against, such Contributor by reason - of your accepting any such warranty or additional liability. - - END OF TERMS AND CONDITIONS - - APPENDIX: How to apply the Apache License to your work. - - To apply the Apache License to your work, attach the following - boilerplate notice, with the fields enclosed by brackets "[]" - replaced with your own identifying information. (Don't include - the brackets!) The text should be enclosed in the appropriate - comment syntax for the file format. We also recommend that a - file or class name and description of purpose be included on the - same "printed page" as the copyright notice for easier - identification within third-party archives. - - Copyright [yyyy] [name of copyright owner] - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. \ No newline at end of file diff --git a/solr/licenses/prometheus-metrics-tracer-otel-NOTICE.txt b/solr/licenses/prometheus-metrics-tracer-otel-NOTICE.txt deleted file mode 100644 index cbd3cd95bef..00000000000 --- a/solr/licenses/prometheus-metrics-tracer-otel-NOTICE.txt +++ /dev/null @@ -1,11 +0,0 @@ -Prometheus instrumentation library for JVM applications -Copyright 2012-2015 The Prometheus Authors - -This product includes software developed at -Boxever Ltd. (http://www.boxever.com/). - -This product includes software developed at -SoundCloud Ltd. (http://soundcloud.com/). - -This product includes software developed as part of the -Ocelli project by Netflix Inc. (https://github.com/Netflix/ocelli/). \ No newline at end of file diff --git a/solr/licenses/prometheus-metrics-tracer-otel-agent-1.1.0.jar.sha1 b/solr/licenses/prometheus-metrics-tracer-otel-agent-1.1.0.jar.sha1 deleted file mode 100644 index 45a83f1dda1..00000000000 --- a/solr/licenses/prometheus-metrics-tracer-otel-agent-1.1.0.jar.sha1 +++ /dev/null @@ -1 +0,0 @@ -393255f85063e08684131ac75af5e65aef070a60 diff --git a/solr/licenses/prometheus-metrics-tracer-otel-agent-LICENSE-ASL.txt b/solr/licenses/prometheus-metrics-tracer-otel-agent-LICENSE-ASL.txt deleted file mode 100644 index f49a4e16e68..00000000000 --- a/solr/licenses/prometheus-metrics-tracer-otel-agent-LICENSE-ASL.txt +++ /dev/null @@ -1,201 +0,0 @@ - Apache License - Version 2.0, January 2004 - http://www.apache.org/licenses/ - - TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION - - 1. Definitions. - - "License" shall mean the terms and conditions for use, reproduction, - and distribution as defined by Sections 1 through 9 of this document. - - "Licensor" shall mean the copyright owner or entity authorized by - the copyright owner that is granting the License. - - "Legal Entity" shall mean the union of the acting entity and all - other entities that control, are controlled by, or are under common - control with that entity. For the purposes of this definition, - "control" means (i) the power, direct or indirect, to cause the - direction or management of such entity, whether by contract or - otherwise, or (ii) ownership of fifty percent (50%) or more of the - outstanding shares, or (iii) beneficial ownership of such entity. - - "You" (or "Your") shall mean an individual or Legal Entity - exercising permissions granted by this License. - - "Source" form shall mean the preferred form for making modifications, - including but not limited to software source code, documentation - source, and configuration files. - - "Object" form shall mean any form resulting from mechanical - transformation or translation of a Source form, including but - not limited to compiled object code, generated documentation, - and conversions to other media types. - - "Work" shall mean the work of authorship, whether in Source or - Object form, made available under the License, as indicated by a - copyright notice that is included in or attached to the work - (an example is provided in the Appendix below). - - "Derivative Works" shall mean any work, whether in Source or Object - form, that is based on (or derived from) the Work and for which the - editorial revisions, annotations, elaborations, or other modifications - represent, as a whole, an original work of authorship. For the purposes - of this License, Derivative Works shall not include works that remain - separable from, or merely link (or bind by name) to the interfaces of, - the Work and Derivative Works thereof. - - "Contribution" shall mean any work of authorship, including - the original version of the Work and any modifications or additions - to that Work or Derivative Works thereof, that is intentionally - submitted to Licensor for inclusion in the Work by the copyright owner - or by an individual or Legal Entity authorized to submit on behalf of - the copyright owner. For the purposes of this definition, "submitted" - means any form of electronic, verbal, or written communication sent - to the Licensor or its representatives, including but not limited to - communication on electronic mailing lists, source code control systems, - and issue tracking systems that are managed by, or on behalf of, the - Licensor for the purpose of discussing and improving the Work, but - excluding communication that is conspicuously marked or otherwise - designated in writing by the copyright owner as "Not a Contribution." - - "Contributor" shall mean Licensor and any individual or Legal Entity - on behalf of whom a Contribution has been received by Licensor and - subsequently incorporated within the Work. - - 2. Grant of Copyright License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - copyright license to reproduce, prepare Derivative Works of, - publicly display, publicly perform, sublicense, and distribute the - Work and such Derivative Works in Source or Object form. - - 3. Grant of Patent License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - (except as stated in this section) patent license to make, have made, - use, offer to sell, sell, import, and otherwise transfer the Work, - where such license applies only to those patent claims licensable - by such Contributor that are necessarily infringed by their - Contribution(s) alone or by combination of their Contribution(s) - with the Work to which such Contribution(s) was submitted. If You - institute patent litigation against any entity (including a - cross-claim or counterclaim in a lawsuit) alleging that the Work - or a Contribution incorporated within the Work constitutes direct - or contributory patent infringement, then any patent licenses - granted to You under this License for that Work shall terminate - as of the date such litigation is filed. - - 4. Redistribution. You may reproduce and distribute copies of the - Work or Derivative Works thereof in any medium, with or without - modifications, and in Source or Object form, provided that You - meet the following conditions: - - (a) You must give any other recipients of the Work or - Derivative Works a copy of this License; and - - (b) You must cause any modified files to carry prominent notices - stating that You changed the files; and - - (c) You must retain, in the Source form of any Derivative Works - that You distribute, all copyright, patent, trademark, and - attribution notices from the Source form of the Work, - excluding those notices that do not pertain to any part of - the Derivative Works; and - - (d) If the Work includes a "NOTICE" text file as part of its - distribution, then any Derivative Works that You distribute must - include a readable copy of the attribution notices contained - within such NOTICE file, excluding those notices that do not - pertain to any part of the Derivative Works, in at least one - of the following places: within a NOTICE text file distributed - as part of the Derivative Works; within the Source form or - documentation, if provided along with the Derivative Works; or, - within a display generated by the Derivative Works, if and - wherever such third-party notices normally appear. The contents - of the NOTICE file are for informational purposes only and - do not modify the License. You may add Your own attribution - notices within Derivative Works that You distribute, alongside - or as an addendum to the NOTICE text from the Work, provided - that such additional attribution notices cannot be construed - as modifying the License. - - You may add Your own copyright statement to Your modifications and - may provide additional or different license terms and conditions - for use, reproduction, or distribution of Your modifications, or - for any such Derivative Works as a whole, provided Your use, - reproduction, and distribution of the Work otherwise complies with - the conditions stated in this License. - - 5. Submission of Contributions. Unless You explicitly state otherwise, - any Contribution intentionally submitted for inclusion in the Work - by You to the Licensor shall be under the terms and conditions of - this License, without any additional terms or conditions. - Notwithstanding the above, nothing herein shall supersede or modify - the terms of any separate license agreement you may have executed - with Licensor regarding such Contributions. - - 6. Trademarks. This License does not grant permission to use the trade - names, trademarks, service marks, or product names of the Licensor, - except as required for reasonable and customary use in describing the - origin of the Work and reproducing the content of the NOTICE file. - - 7. Disclaimer of Warranty. Unless required by applicable law or - agreed to in writing, Licensor provides the Work (and each - Contributor provides its Contributions) on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - implied, including, without limitation, any warranties or conditions - of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A - PARTICULAR PURPOSE. You are solely responsible for determining the - appropriateness of using or redistributing the Work and assume any - risks associated with Your exercise of permissions under this License. - - 8. Limitation of Liability. In no event and under no legal theory, - whether in tort (including negligence), contract, or otherwise, - unless required by applicable law (such as deliberate and grossly - negligent acts) or agreed to in writing, shall any Contributor be - liable to You for damages, including any direct, indirect, special, - incidental, or consequential damages of any character arising as a - result of this License or out of the use or inability to use the - Work (including but not limited to damages for loss of goodwill, - work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses), even if such Contributor - has been advised of the possibility of such damages. - - 9. Accepting Warranty or Additional Liability. While redistributing - the Work or Derivative Works thereof, You may choose to offer, - and charge a fee for, acceptance of support, warranty, indemnity, - or other liability obligations and/or rights consistent with this - License. However, in accepting such obligations, You may act only - on Your own behalf and on Your sole responsibility, not on behalf - of any other Contributor, and only if You agree to indemnify, - defend, and hold each Contributor harmless for any liability - incurred by, or claims asserted against, such Contributor by reason - of your accepting any such warranty or additional liability. - - END OF TERMS AND CONDITIONS - - APPENDIX: How to apply the Apache License to your work. - - To apply the Apache License to your work, attach the following - boilerplate notice, with the fields enclosed by brackets "[]" - replaced with your own identifying information. (Don't include - the brackets!) The text should be enclosed in the appropriate - comment syntax for the file format. We also recommend that a - file or class name and description of purpose be included on the - same "printed page" as the copyright notice for easier - identification within third-party archives. - - Copyright [yyyy] [name of copyright owner] - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. \ No newline at end of file diff --git a/solr/licenses/prometheus-metrics-tracer-otel-agent-NOTICE.txt b/solr/licenses/prometheus-metrics-tracer-otel-agent-NOTICE.txt deleted file mode 100644 index cbd3cd95bef..00000000000 --- a/solr/licenses/prometheus-metrics-tracer-otel-agent-NOTICE.txt +++ /dev/null @@ -1,11 +0,0 @@ -Prometheus instrumentation library for JVM applications -Copyright 2012-2015 The Prometheus Authors - -This product includes software developed at -Boxever Ltd. (http://www.boxever.com/). - -This product includes software developed at -SoundCloud Ltd. (http://soundcloud.com/). - -This product includes software developed as part of the -Ocelli project by Netflix Inc. (https://github.com/Netflix/ocelli/). \ No newline at end of file diff --git a/versions.lock b/versions.lock index 2d11a7b1716..cc0232a65d8 100644 --- a/versions.lock +++ b/versions.lock @@ -145,15 +145,10 @@ io.opentelemetry:opentelemetry-sdk-logs:1.35.0 (3 constraints: eb32b3b2) io.opentelemetry:opentelemetry-sdk-metrics:1.35.0 (3 constraints: eb32b3b2) io.opentelemetry:opentelemetry-sdk-trace:1.35.0 (3 constraints: eb32b3b2) io.perfmark:perfmark-api:0.26.0 (3 constraints: 21212b16) -io.prometheus:prometheus-metrics-config:1.1.0 (2 constraints: a926cf59) -io.prometheus:prometheus-metrics-core:1.1.0 (1 constraints: 0405f335) +io.prometheus:prometheus-metrics-config:1.1.0 (1 constraints: 3e164ed8) io.prometheus:prometheus-metrics-exposition-formats:1.1.0 (1 constraints: 0405f335) -io.prometheus:prometheus-metrics-model:1.1.0 (3 constraints: ac2b1ea3) +io.prometheus:prometheus-metrics-model:1.1.0 (2 constraints: 411b133b) io.prometheus:prometheus-metrics-shaded-protobuf:1.1.0 (1 constraints: 3e164ed8) -io.prometheus:prometheus-metrics-tracer-common:1.1.0 (3 constraints: 993ee7d1) -io.prometheus:prometheus-metrics-tracer-initializer:1.1.0 (1 constraints: 6c1022a8) -io.prometheus:prometheus-metrics-tracer-otel:1.1.0 (1 constraints: 1516fed3) -io.prometheus:prometheus-metrics-tracer-otel-agent:1.1.0 (1 constraints: 1516fed3) io.prometheus:simpleclient:0.16.0 (3 constraints: 9d257513) io.prometheus:simpleclient_common:0.16.0 (1 constraints: 1a1139c0) io.prometheus:simpleclient_httpserver:0.16.0 (1 constraints: 3905353b) From 58fb18dc13c69edbec74ef5f398864fa29bb7d5c Mon Sep 17 00:00:00 2001 From: mbiscocho Date: Wed, 1 May 2024 17:11:40 -0400 Subject: [PATCH 09/32] Add MetricsHandler prometheus test --- .../handler/admin/MetricsHandlerTest.java | 228 ++++++++++++++++++ 1 file changed, 228 insertions(+) diff --git a/solr/core/src/test/org/apache/solr/handler/admin/MetricsHandlerTest.java b/solr/core/src/test/org/apache/solr/handler/admin/MetricsHandlerTest.java index c2ccdb43baf..4af82d345ee 100644 --- a/solr/core/src/test/org/apache/solr/handler/admin/MetricsHandlerTest.java +++ b/solr/core/src/test/org/apache/solr/handler/admin/MetricsHandlerTest.java @@ -18,9 +18,15 @@ package org.apache.solr.handler.admin; import com.codahale.metrics.Counter; +import io.prometheus.metrics.model.snapshots.CounterSnapshot; +import io.prometheus.metrics.model.snapshots.GaugeSnapshot; +import io.prometheus.metrics.model.snapshots.Labels; +import io.prometheus.metrics.model.snapshots.MetricSnapshot; +import io.prometheus.metrics.model.snapshots.MetricSnapshots; import java.util.Arrays; import java.util.HashMap; import java.util.Map; +import java.util.Optional; import org.apache.solr.SolrTestCaseJ4; import org.apache.solr.common.MapWriter; import org.apache.solr.common.params.CommonParams; @@ -32,6 +38,7 @@ import org.apache.solr.handler.RequestHandlerBase; import org.apache.solr.metrics.MetricsMap; import org.apache.solr.metrics.SolrMetricsContext; +import org.apache.solr.metrics.prometheus.SolrPrometheusRegistry; import org.apache.solr.request.SolrQueryRequest; import org.apache.solr.request.SolrRequestHandler; import org.apache.solr.response.SolrQueryResponse; @@ -677,6 +684,227 @@ public void testExprMetrics() throws Exception { assertTrue(map.toString(), map.containsKey("count")); } + @Test + @SuppressWarnings("unchecked") + public void testPrometheusMetrics() throws Exception { + MetricsHandler handler = new MetricsHandler(h.getCoreContainer()); + + SolrQueryResponse resp = new SolrQueryResponse(); + handler.handleRequestBody( + req( + CommonParams.QT, + "/admin/metrics", + MetricsHandler.COMPACT_PARAM, + "false", + CommonParams.WT, + "prometheus"), + resp); + + NamedList values = resp.getValues(); + assertNotNull(values.get("metrics")); + values = (NamedList) values.get("metrics"); + SolrPrometheusRegistry registry = (SolrPrometheusRegistry) values.get("solr.core.collection1"); + assertNotNull(registry); + MetricSnapshots actualSnapshots = registry.collect(); + assertNotNull(actualSnapshots); + + Optional actualSnapshot = + actualSnapshots.stream() + .filter( + ss -> + ss.getMetadata() + .getPrometheusName() + .equals("solr_metrics_core_average_request_time")) + .findAny(); + assertTrue(actualSnapshot.isPresent()); + Optional actualGaugeDataPoint = + (Optional) + actualSnapshot.get().getDataPoints().stream() + .filter( + ss -> + ss.getLabels() + .hasSameValues( + Labels.of( + "category", + "QUERY", + "core", + "collection1", + "handler", + "/select"))) + .findAny(); + assertTrue(actualGaugeDataPoint.isPresent()); + assertEquals(0, actualGaugeDataPoint.get().getValue(), 0); + + actualSnapshot = + actualSnapshots.stream() + .filter(ss -> ss.getMetadata().getPrometheusName().equals("solr_metrics_core_requests")) + .findAny(); + assertTrue(actualSnapshot.isPresent()); + Optional actualCounterDataPoint = + (Optional) + actualSnapshot.get().getDataPoints().stream() + .filter( + ss -> + ss.getLabels() + .hasSameValues( + Labels.of( + "category", + "QUERY", + "core", + "collection1", + "handler", + "/select", + "type", + "requests"))) + .findAny(); + assertTrue(actualCounterDataPoint.isPresent()); + assertEquals(0, actualCounterDataPoint.get().getValue(), 0); + + actualSnapshot = + actualSnapshots.stream() + .filter(ss -> ss.getMetadata().getPrometheusName().equals("solr_metrics_core_cache")) + .findAny(); + assertTrue(actualSnapshot.isPresent()); + actualGaugeDataPoint = + (Optional) + actualSnapshot.get().getDataPoints().stream() + .filter( + ss -> + ss.getLabels() + .hasSameValues( + Labels.of( + "cacheType", + "fieldValueCache", + "core", + "collection1", + "item", + "hits"))) + .findAny(); + assertTrue(actualGaugeDataPoint.isPresent()); + assertEquals(0, actualGaugeDataPoint.get().getValue(), 0); + + actualSnapshot = + actualSnapshots.stream() + .filter( + ss -> + ss.getMetadata() + .getPrometheusName() + .equals("solr_metrics_core_highlighter_requests")) + .findAny(); + assertTrue(actualSnapshot.isPresent()); + actualCounterDataPoint = + (Optional) + actualSnapshot.get().getDataPoints().stream() + .filter( + ss -> + ss.getLabels() + .hasSameValues( + Labels.of( + "item", + "default", + "core", + "collection1", + "type", + "SolrFragmenter"))) + .findAny(); + assertTrue(actualCounterDataPoint.isPresent()); + assertEquals(0, actualCounterDataPoint.get().getValue(), 0); + + actualSnapshot = + actualSnapshots.stream() + .filter( + ss -> + ss.getMetadata().getPrometheusName().equals("solr_metrics_core_requests_time")) + .findAny(); + assertTrue(actualSnapshot.isPresent()); + actualCounterDataPoint = + (Optional) + actualSnapshot.get().getDataPoints().stream() + .filter( + ss -> + ss.getLabels() + .hasSameValues( + Labels.of( + "category", + "QUERY", + "core", + "collection1", + "handler", + "/select"))) + .findAny(); + assertTrue(actualCounterDataPoint.isPresent()); + assertEquals(0, actualCounterDataPoint.get().getValue(), 0); + + actualSnapshot = + actualSnapshots.stream() + .filter( + ss -> + ss.getMetadata() + .getPrometheusName() + .equals("solr_metrics_core_searcher_documents")) + .findAny(); + assertTrue(actualSnapshot.isPresent()); + actualGaugeDataPoint = + (Optional) + actualSnapshot.get().getDataPoints().stream() + .filter( + ss -> + ss.getLabels() + .hasSameValues(Labels.of("core", "collection1", "type", "numDocs"))) + .findAny(); + assertTrue(actualGaugeDataPoint.isPresent()); + assertEquals(0, actualGaugeDataPoint.get().getValue(), 0); + + actualSnapshot = + actualSnapshots.stream() + .filter( + ss -> + ss.getMetadata().getPrometheusName().equals("solr_metrics_core_update_handler")) + .findAny(); + assertTrue(actualSnapshot.isPresent()); + actualGaugeDataPoint = + (Optional) + actualSnapshot.get().getDataPoints().stream() + .filter( + ss -> + ss.getLabels() + .hasSameValues( + Labels.of( + "category", + "UPDATE", + "core", + "collection1", + "type", + "adds", + "handler", + "updateHandler"))) + .findAny(); + assertTrue(actualGaugeDataPoint.isPresent()); + assertEquals(0, actualGaugeDataPoint.get().getValue(), 0); + + actualSnapshot = + actualSnapshots.stream() + .filter( + ss -> + ss.getMetadata() + .getPrometheusName() + .equals("solr_metrics_core_average_searcher_warmup_time")) + .findAny(); + assertTrue(actualSnapshot.isPresent()); + actualGaugeDataPoint = + (Optional) + actualSnapshot.get().getDataPoints().stream() + .filter( + ss -> + ss.getLabels() + .hasSameValues(Labels.of("core", "collection1", "type", "warmup"))) + .findAny(); + assertTrue(actualGaugeDataPoint.isPresent()); + assertEquals(0, actualGaugeDataPoint.get().getValue(), 0); + + handler.close(); + } + @Test public void testMetricsUnload() throws Exception { From 680a0a332a06212c38d7a95d8b5b2c881796ebc3 Mon Sep 17 00:00:00 2001 From: mbiscocho Date: Thu, 2 May 2024 11:42:29 -0400 Subject: [PATCH 10/32] Add new methods of creating and collecting datapoints --- .../solr/handler/admin/MetricsHandler.java | 3 +- .../prometheus/SolrPrometheusRegistry.java | 160 +++++++++++------- .../prometheus/core/SolrCoreCacheMetric.java | 1 + .../core/SolrCoreHandlerMetric.java | 1 + .../core/SolrCoreHighlighterMetric.java | 1 + .../prometheus/core/SolrCoreIndexMetric.java | 1 + .../prometheus/core/SolrCoreMetric.java | 9 +- .../core/SolrCoreSearcherMetric.java | 1 + .../prometheus/core/SolrCoreTlogMetric.java | 1 + .../metrics/prometheus/core/package-info.java | 2 +- 10 files changed, 110 insertions(+), 70 deletions(-) diff --git a/solr/core/src/java/org/apache/solr/handler/admin/MetricsHandler.java b/solr/core/src/java/org/apache/solr/handler/admin/MetricsHandler.java index 7484c677137..f42bb20b642 100644 --- a/solr/core/src/java/org/apache/solr/handler/admin/MetricsHandler.java +++ b/solr/core/src/java/org/apache/solr/handler/admin/MetricsHandler.java @@ -181,7 +181,6 @@ private NamedList handleDropwizardRegistry(SolrParams params) { private NamedList handlePrometheusRegistry(SolrParams params) { NamedList response = new SimpleOrderedMap<>(); - boolean compact = params.getBool(COMPACT_PARAM, false); MetricFilter mustMatchFilter = parseMustMatchFilter(params); Predicate propertyFilter = parsePropertyFilter(params); List metricTypes = parseMetricTypes(params); @@ -201,7 +200,7 @@ private NamedList handlePrometheusRegistry(SolrParams params) { propertyFilter, false, false, - compact, + true, (registry) -> { response.add(registryName, registry); }); diff --git a/solr/core/src/java/org/apache/solr/metrics/prometheus/SolrPrometheusRegistry.java b/solr/core/src/java/org/apache/solr/metrics/prometheus/SolrPrometheusRegistry.java index b141d3fe753..26b5c8c102f 100644 --- a/solr/core/src/java/org/apache/solr/metrics/prometheus/SolrPrometheusRegistry.java +++ b/solr/core/src/java/org/apache/solr/metrics/prometheus/SolrPrometheusRegistry.java @@ -44,104 +44,85 @@ public SolrPrometheusRegistry() { } /** - * Export {@link Meter} to {@link CounterSnapshot}. Registers new Prometheus Metric and {@link - * io.prometheus.metrics.model.snapshots.CounterSnapshot.CounterDataPointSnapshot} if metric does - * not exist + * Export {@link Meter} to {@link + * io.prometheus.metrics.model.snapshots.CounterSnapshot.CounterDataPointSnapshot} and collect + * datapoint * - * @param prometheusMetricName name of prometheus metric + * @param metricName name of prometheus metric * @param dropwizardMetric the {@link Meter} to be exported * @param labels label names and values to register with {@link * io.prometheus.metrics.model.snapshots.CounterSnapshot.CounterDataPointSnapshot} */ - public void exportMeter( - String prometheusMetricName, Meter dropwizardMetric, Map labels) { + public void exportMeter(String metricName, Meter dropwizardMetric, Map labels) { CounterSnapshot.CounterDataPointSnapshot dataPoint = - CounterSnapshot.CounterDataPointSnapshot.builder() - .value(dropwizardMetric.getCount()) - .labels(Labels.of(new ArrayList<>(labels.keySet()), new ArrayList<>(labels.values()))) - .build(); - if (!metricCounters.containsKey(prometheusMetricName)) { - metricCounters.put(prometheusMetricName, new ArrayList<>()); - } - metricCounters.get(prometheusMetricName).add(dataPoint); + createCounterDatapoint( + (double) dropwizardMetric.getCount(), + Labels.of(new ArrayList<>(labels.keySet()), new ArrayList<>(labels.values()))); + collectCounterDatapoint(metricName, dataPoint); } /** - * Export {@link com.codahale.metrics.Counter} to {@link CounterSnapshot}. Registers new - * Prometheus Metric and {@link - * io.prometheus.metrics.model.snapshots.CounterSnapshot.CounterDataPointSnapshot} if metric does - * not exist + * Export {@link com.codahale.metrics.Counter} to {@link + * io.prometheus.metrics.model.snapshots.CounterSnapshot.CounterDataPointSnapshot} and collect + * datapoint * - * @param prometheusMetricName name of prometheus metric + * @param metricName name of prometheus metric * @param dropwizardMetric the {@link com.codahale.metrics.Counter} to be exported * @param labels label names and values to record with {@link * io.prometheus.metrics.model.snapshots.CounterSnapshot.CounterDataPointSnapshot} */ public void exportCounter( - String prometheusMetricName, + String metricName, com.codahale.metrics.Counter dropwizardMetric, Map labels) { CounterSnapshot.CounterDataPointSnapshot dataPoint = - CounterSnapshot.CounterDataPointSnapshot.builder() - .value(dropwizardMetric.getCount()) - .labels(Labels.of(new ArrayList<>(labels.keySet()), new ArrayList<>(labels.values()))) - .build(); - if (!metricCounters.containsKey(prometheusMetricName)) { - metricCounters.put(prometheusMetricName, new ArrayList<>()); - } - metricCounters.get(prometheusMetricName).add(dataPoint); + createCounterDatapoint( + (double) dropwizardMetric.getCount(), + Labels.of(new ArrayList<>(labels.keySet()), new ArrayList<>(labels.values()))); + collectCounterDatapoint(metricName, dataPoint); } /** - * Export {@link Timer} to {@link GaugeSnapshot}. Registers new Prometheus Metric and {@link - * io.prometheus.metrics.model.snapshots.GaugeSnapshot.GaugeDataPointSnapshot} if metric does not - * exist + * Export {@link Timer} ands its mean rate to {@link + * io.prometheus.metrics.model.snapshots.GaugeSnapshot.GaugeDataPointSnapshot} and collect + * datapoint * - * @param prometheusMetricName name of prometheus metric + * @param metricName name of prometheus metric * @param dropwizardMetric the {@link Timer} to be exported * @param labels label names and values to record with {@link * io.prometheus.metrics.model.snapshots.GaugeSnapshot.GaugeDataPointSnapshot} */ - public void exportTimer( - String prometheusMetricName, Timer dropwizardMetric, Map labels) { + public void exportTimer(String metricName, Timer dropwizardMetric, Map labels) { GaugeSnapshot.GaugeDataPointSnapshot dataPoint = - GaugeSnapshot.GaugeDataPointSnapshot.builder() - .value(dropwizardMetric.getCount()) - .labels(Labels.of(new ArrayList<>(labels.keySet()), new ArrayList<>(labels.values()))) - .build(); - if (!metricGauges.containsKey(prometheusMetricName)) { - metricGauges.put(prometheusMetricName, new ArrayList<>()); - } - metricGauges.get(prometheusMetricName).add(dataPoint); + createGaugeDatapoint( + dropwizardMetric.getMeanRate(), + Labels.of(new ArrayList<>(labels.keySet()), new ArrayList<>(labels.values()))); + collectGaugeDatapoint(metricName, dataPoint); } /** - * Export {@link com.codahale.metrics.Gauge} to {@link GaugeSnapshot}. Registers new Prometheus - * Metric and {@link io.prometheus.metrics.model.snapshots.GaugeSnapshot.GaugeDataPointSnapshot} - * if metric does not exist + * Export {@link com.codahale.metrics.Gauge} to {@link + * io.prometheus.metrics.model.snapshots.GaugeSnapshot.GaugeDataPointSnapshot} and collect to + * datapoint. Unlike other Dropwizard metric types, Gauges can have more complex types. In the + * case of a hashmap, collect each as an individual metric and have its key appended as a label to + * the metric called "item" * - * @param prometheusMetricName name of prometheus metric + * @param metricName name of prometheus metric * @param dropwizardMetricRaw the {@link com.codahale.metrics.Gauge} to be exported * @param labelsMap label names and values to record with {@link * io.prometheus.metrics.model.snapshots.GaugeSnapshot.GaugeDataPointSnapshot} */ public void exportGauge( - String prometheusMetricName, + String metricName, com.codahale.metrics.Gauge dropwizardMetricRaw, Map labelsMap) { Object dropwizardMetric = (dropwizardMetricRaw).getValue(); - if (!metricGauges.containsKey(prometheusMetricName)) { - metricGauges.put(prometheusMetricName, new ArrayList<>()); - } if (dropwizardMetric instanceof Number) { GaugeSnapshot.GaugeDataPointSnapshot dataPoint = - GaugeSnapshot.GaugeDataPointSnapshot.builder() - .value(((Number) dropwizardMetric).doubleValue()) - .labels( - Labels.of( - new ArrayList<>(labelsMap.keySet()), new ArrayList<>(labelsMap.values()))) - .build(); - metricGauges.get(prometheusMetricName).add(dataPoint); + createGaugeDatapoint( + ((Number) dropwizardMetric).doubleValue(), + Labels.of(new ArrayList<>(labelsMap.keySet()), new ArrayList<>(labelsMap.values()))); + collectGaugeDatapoint(metricName, dataPoint); } else if (dropwizardMetric instanceof HashMap) { HashMap itemsMap = (HashMap) dropwizardMetric; for (Object item : itemsMap.keySet()) { @@ -151,16 +132,71 @@ public void exportGauge( List labelValues = new ArrayList<>(labelsMap.values()); labelValues.add((String) item); GaugeSnapshot.GaugeDataPointSnapshot dataPoint = - GaugeSnapshot.GaugeDataPointSnapshot.builder() - .value(((Number) itemsMap.get(item)).doubleValue()) - .labels(Labels.of(labelKeys, labelValues)) - .build(); - metricGauges.get(prometheusMetricName).add(dataPoint); + createGaugeDatapoint( + ((Number) itemsMap.get(item)).doubleValue(), Labels.of(labelKeys, labelValues)); + collectGaugeDatapoint(metricName, dataPoint); } } } } + /** + * Create a {@link io.prometheus.metrics.model.snapshots.CounterSnapshot.CounterDataPointSnapshot} + * with labels + * + * @param value metric value + * @param labels set of name/values labels + */ + public CounterSnapshot.CounterDataPointSnapshot createCounterDatapoint( + double value, Labels labels) { + return CounterSnapshot.CounterDataPointSnapshot.builder().value(value).labels(labels).build(); + } + + /** + * Create a {@link io.prometheus.metrics.model.snapshots.GaugeSnapshot.GaugeDataPointSnapshot} + * with labels + * + * @param value metric value + * @param labels set of name/values labels + */ + public GaugeSnapshot.GaugeDataPointSnapshot createGaugeDatapoint(double value, Labels labels) { + return GaugeSnapshot.GaugeDataPointSnapshot.builder().value(value).labels(labels).build(); + } + + /** + * Collects {@link io.prometheus.metrics.model.snapshots.CounterSnapshot.CounterDataPointSnapshot} + * and appends to existing metric or create new metric if name does not exist + * + * @param metricName Name of metric + * @param dataPoint Counter datapoint to be collected + */ + public void collectCounterDatapoint( + String metricName, CounterSnapshot.CounterDataPointSnapshot dataPoint) { + if (!metricCounters.containsKey(metricName)) { + metricCounters.put(metricName, new ArrayList<>()); + } + metricCounters.get(metricName).add(dataPoint); + } + + /** + * Collects {@link io.prometheus.metrics.model.snapshots.GaugeSnapshot.GaugeDataPointSnapshot} and + * appends to existing metric or create new metric if name does not exist + * + * @param metricName Name of metric + * @param dataPoint Gauge datapoint to be collected + */ + public void collectGaugeDatapoint( + String metricName, GaugeSnapshot.GaugeDataPointSnapshot dataPoint) { + if (!metricGauges.containsKey(metricName)) { + metricGauges.put(metricName, new ArrayList<>()); + } + metricGauges.get(metricName).add(dataPoint); + } + + /** + * Returns an immutable {@link MetricSnapshots} from the {@link + * io.prometheus.metrics.model.snapshots.DataPointSnapshot}s collected from the registry + */ public MetricSnapshots collect() { ArrayList snapshots = new ArrayList<>(); for (String metricName : metricCounters.keySet()) { diff --git a/solr/core/src/java/org/apache/solr/metrics/prometheus/core/SolrCoreCacheMetric.java b/solr/core/src/java/org/apache/solr/metrics/prometheus/core/SolrCoreCacheMetric.java index c03d93f8836..5d963b4a9c2 100644 --- a/solr/core/src/java/org/apache/solr/metrics/prometheus/core/SolrCoreCacheMetric.java +++ b/solr/core/src/java/org/apache/solr/metrics/prometheus/core/SolrCoreCacheMetric.java @@ -20,6 +20,7 @@ import com.codahale.metrics.Metric; import org.apache.solr.metrics.prometheus.SolrPrometheusCoreRegistry; +/** Dropwizard metrics of name CACHE.* */ public class SolrCoreCacheMetric extends SolrCoreMetric { public static final String CORE_CACHE_SEARCHER_METRICS = "solr_metrics_core_cache"; diff --git a/solr/core/src/java/org/apache/solr/metrics/prometheus/core/SolrCoreHandlerMetric.java b/solr/core/src/java/org/apache/solr/metrics/prometheus/core/SolrCoreHandlerMetric.java index cde405a41f0..32802a80809 100644 --- a/solr/core/src/java/org/apache/solr/metrics/prometheus/core/SolrCoreHandlerMetric.java +++ b/solr/core/src/java/org/apache/solr/metrics/prometheus/core/SolrCoreHandlerMetric.java @@ -23,6 +23,7 @@ import com.codahale.metrics.Timer; import org.apache.solr.metrics.prometheus.SolrPrometheusCoreRegistry; +/** Dropwizard metrics of name ADMIN/QUERY/UPDATE/REPLICATION.* */ public class SolrCoreHandlerMetric extends SolrCoreMetric { public static final String CORE_REQUESTS_TOTAL = "solr_metrics_core_requests"; public static final String CORE_REQUESTS_UPDATE_HANDLER = "solr_metrics_core_update_handler"; diff --git a/solr/core/src/java/org/apache/solr/metrics/prometheus/core/SolrCoreHighlighterMetric.java b/solr/core/src/java/org/apache/solr/metrics/prometheus/core/SolrCoreHighlighterMetric.java index d71e7a69b7e..a9674c1820d 100644 --- a/solr/core/src/java/org/apache/solr/metrics/prometheus/core/SolrCoreHighlighterMetric.java +++ b/solr/core/src/java/org/apache/solr/metrics/prometheus/core/SolrCoreHighlighterMetric.java @@ -20,6 +20,7 @@ import com.codahale.metrics.Metric; import org.apache.solr.metrics.prometheus.SolrPrometheusCoreRegistry; +/** Dropwizard metrics of name HIGHLIGHTER.* */ public class SolrCoreHighlighterMetric extends SolrCoreMetric { public static final String CORE_HIGHLIGHER_METRICS = "solr_metrics_core_highlighter_requests"; diff --git a/solr/core/src/java/org/apache/solr/metrics/prometheus/core/SolrCoreIndexMetric.java b/solr/core/src/java/org/apache/solr/metrics/prometheus/core/SolrCoreIndexMetric.java index f46399c0a09..1c97eb1e924 100644 --- a/solr/core/src/java/org/apache/solr/metrics/prometheus/core/SolrCoreIndexMetric.java +++ b/solr/core/src/java/org/apache/solr/metrics/prometheus/core/SolrCoreIndexMetric.java @@ -20,6 +20,7 @@ import com.codahale.metrics.Metric; import org.apache.solr.metrics.prometheus.SolrPrometheusCoreRegistry; +/** Dropwizard metrics of name INDEX.* */ public class SolrCoreIndexMetric extends SolrCoreMetric { public static final String CORE_INDEX_METRICS = "solr_metrics_core_index_size_bytes"; diff --git a/solr/core/src/java/org/apache/solr/metrics/prometheus/core/SolrCoreMetric.java b/solr/core/src/java/org/apache/solr/metrics/prometheus/core/SolrCoreMetric.java index 4b5fb8a644d..7e894a1b9c6 100644 --- a/solr/core/src/java/org/apache/solr/metrics/prometheus/core/SolrCoreMetric.java +++ b/solr/core/src/java/org/apache/solr/metrics/prometheus/core/SolrCoreMetric.java @@ -22,12 +22,11 @@ import org.apache.solr.metrics.prometheus.SolrPrometheusCoreRegistry; /** - * Base class is a wrapper to export {@link com.codahale.metrics.Metric} to {@link - * io.prometheus.metrics.model.snapshots.MetricSnapshot} and register to a {@link - * SolrPrometheusCoreRegistry} {@link com.codahale.metrics.MetricRegistry} does not support tags + * Base class is a wrapper to categorize and export {@link com.codahale.metrics.Metric} to {@link + * io.prometheus.metrics.model.snapshots.DataPointSnapshot} and register to a {@link + * SolrPrometheusCoreRegistry}. {@link com.codahale.metrics.MetricRegistry} does not support tags * unlike prometheus. Metrics registered to the registry need to be parsed out from the metric name - * and exported to {@link io.prometheus.metrics.model.snapshots.MetricSnapshot} be output to - * Prometheus + * to be exported to {@link io.prometheus.metrics.model.snapshots.DataPointSnapshot} */ public abstract class SolrCoreMetric { public Metric dropwizardMetric; diff --git a/solr/core/src/java/org/apache/solr/metrics/prometheus/core/SolrCoreSearcherMetric.java b/solr/core/src/java/org/apache/solr/metrics/prometheus/core/SolrCoreSearcherMetric.java index 932b1d96288..7f6564ed576 100644 --- a/solr/core/src/java/org/apache/solr/metrics/prometheus/core/SolrCoreSearcherMetric.java +++ b/solr/core/src/java/org/apache/solr/metrics/prometheus/core/SolrCoreSearcherMetric.java @@ -24,6 +24,7 @@ import com.codahale.metrics.Timer; import org.apache.solr.metrics.prometheus.SolrPrometheusCoreRegistry; +/** Dropwizard metrics of name SEARCHER.* */ public class SolrCoreSearcherMetric extends SolrCoreMetric { public static final String CORE_SEARCHER_METRICS = "solr_metrics_core_searcher_documents"; public static final String CORE_SEARCHER_TIMES = "solr_metrics_core_average_searcher_warmup_time"; diff --git a/solr/core/src/java/org/apache/solr/metrics/prometheus/core/SolrCoreTlogMetric.java b/solr/core/src/java/org/apache/solr/metrics/prometheus/core/SolrCoreTlogMetric.java index b81de46ec41..dacc385bb0e 100644 --- a/solr/core/src/java/org/apache/solr/metrics/prometheus/core/SolrCoreTlogMetric.java +++ b/solr/core/src/java/org/apache/solr/metrics/prometheus/core/SolrCoreTlogMetric.java @@ -20,6 +20,7 @@ import com.codahale.metrics.Metric; import org.apache.solr.metrics.prometheus.SolrPrometheusCoreRegistry; +/** Dropwizard metrics of name TLOG.* */ public class SolrCoreTlogMetric extends SolrCoreMetric { public static final String CORE_TLOG_METRICS = "solr_metrics_core_tlog"; diff --git a/solr/core/src/java/org/apache/solr/metrics/prometheus/core/package-info.java b/solr/core/src/java/org/apache/solr/metrics/prometheus/core/package-info.java index aa2311f8192..b419047dd18 100644 --- a/solr/core/src/java/org/apache/solr/metrics/prometheus/core/package-info.java +++ b/solr/core/src/java/org/apache/solr/metrics/prometheus/core/package-info.java @@ -17,6 +17,6 @@ /** * The {@link org.apache.solr.metrics.prometheus.core.SolrCoreMetric} is a wrapper to export {@link - * com.codahale.metrics.Metric} to {@link io.prometheus.metrics.model.snapshots.MetricSnapshot} + * com.codahale.metrics.Metric} to {@link io.prometheus.metrics.model.snapshots.DataPointSnapshot} */ package org.apache.solr.metrics.prometheus.core; From e4c50537e74d66132dcf747f239c4afff7308006 Mon Sep 17 00:00:00 2001 From: mbiscocho Date: Thu, 2 May 2024 14:32:28 -0400 Subject: [PATCH 11/32] Add tests for SolrPrometheusExporter --- ...y.java => SolrPrometheusCoreExporter.java} | 5 +- ...istry.java => SolrPrometheusExporter.java} | 69 ++++----- .../prometheus/core/SolrCoreCacheMetric.java | 10 +- .../core/SolrCoreHandlerMetric.java | 28 +++- .../core/SolrCoreHighlighterMetric.java | 10 +- .../prometheus/core/SolrCoreIndexMetric.java | 10 +- .../prometheus/core/SolrCoreMetric.java | 6 +- .../prometheus/core/SolrCoreNoOpMetric.java | 4 +- .../core/SolrCoreSearcherMetric.java | 19 ++- .../prometheus/core/SolrCoreTlogMetric.java | 11 +- .../solr/metrics/prometheus/package-info.java | 2 +- .../response/PrometheusResponseWriter.java | 5 +- .../apache/solr/util/stats/MetricUtils.java | 16 +- .../handler/admin/MetricsHandlerTest.java | 4 +- .../metrics/SolrPrometheusExporterTest.java | 145 ++++++++++++++++++ 15 files changed, 260 insertions(+), 84 deletions(-) rename solr/core/src/java/org/apache/solr/metrics/prometheus/{SolrPrometheusCoreRegistry.java => SolrPrometheusCoreExporter.java} (96%) rename solr/core/src/java/org/apache/solr/metrics/prometheus/{SolrPrometheusRegistry.java => SolrPrometheusExporter.java} (74%) create mode 100644 solr/core/src/test/org/apache/solr/metrics/SolrPrometheusExporterTest.java diff --git a/solr/core/src/java/org/apache/solr/metrics/prometheus/SolrPrometheusCoreRegistry.java b/solr/core/src/java/org/apache/solr/metrics/prometheus/SolrPrometheusCoreExporter.java similarity index 96% rename from solr/core/src/java/org/apache/solr/metrics/prometheus/SolrPrometheusCoreRegistry.java rename to solr/core/src/java/org/apache/solr/metrics/prometheus/SolrPrometheusCoreExporter.java index aea6d17cdda..56d928acacc 100644 --- a/solr/core/src/java/org/apache/solr/metrics/prometheus/SolrPrometheusCoreRegistry.java +++ b/solr/core/src/java/org/apache/solr/metrics/prometheus/SolrPrometheusCoreExporter.java @@ -31,7 +31,7 @@ * This class maintains a {@link io.prometheus.metrics.model.snapshots.MetricSnapshot}s exported * from solr.core {@link com.codahale.metrics.MetricRegistry} */ -public class SolrPrometheusCoreRegistry extends SolrPrometheusRegistry { +public class SolrPrometheusCoreExporter extends SolrPrometheusExporter { public final String coreName; public final boolean cloudMode; public static final String ADMIN = "ADMIN"; @@ -45,7 +45,7 @@ public class SolrPrometheusCoreRegistry extends SolrPrometheusRegistry { public static final String INDEX = "INDEX"; public static final String CORE = "CORE"; - public SolrPrometheusCoreRegistry(String coreName, boolean cloudMode) { + public SolrPrometheusCoreExporter(String coreName, boolean cloudMode) { super(); this.coreName = coreName; this.cloudMode = cloudMode; @@ -58,6 +58,7 @@ public SolrPrometheusCoreRegistry(String coreName, boolean cloudMode) { * @param dropwizardMetric the {@link Meter} to be exported * @param metricName Dropwizard metric name */ + @Override public void exportDropwizardMetric(Metric dropwizardMetric, String metricName) { SolrCoreMetric solrCoreMetric = categorizeCoreMetric(dropwizardMetric, metricName); solrCoreMetric.parseLabels().toPrometheus(this); diff --git a/solr/core/src/java/org/apache/solr/metrics/prometheus/SolrPrometheusRegistry.java b/solr/core/src/java/org/apache/solr/metrics/prometheus/SolrPrometheusExporter.java similarity index 74% rename from solr/core/src/java/org/apache/solr/metrics/prometheus/SolrPrometheusRegistry.java rename to solr/core/src/java/org/apache/solr/metrics/prometheus/SolrPrometheusExporter.java index 26b5c8c102f..5b3844b5c1f 100644 --- a/solr/core/src/java/org/apache/solr/metrics/prometheus/SolrPrometheusRegistry.java +++ b/solr/core/src/java/org/apache/solr/metrics/prometheus/SolrPrometheusExporter.java @@ -17,6 +17,7 @@ package org.apache.solr.metrics.prometheus; import com.codahale.metrics.Meter; +import com.codahale.metrics.Metric; import com.codahale.metrics.Timer; import io.prometheus.metrics.model.snapshots.CounterSnapshot; import io.prometheus.metrics.model.snapshots.GaugeSnapshot; @@ -30,34 +31,40 @@ import java.util.Map; /** - * Base class for all {@link SolrPrometheusRegistry} holding {@link MetricSnapshot}s. Can export + * Base class for all {@link SolrPrometheusExporter} holding {@link MetricSnapshot}s. Can export * {@link com.codahale.metrics.Metric} to {@link MetricSnapshot} to be outputted for {@link * org.apache.solr.response.PrometheusResponseWriter} */ -public abstract class SolrPrometheusRegistry { - private final Map> metricCounters; - private final Map> metricGauges; +public abstract class SolrPrometheusExporter { + protected final Map> metricCounters; + protected final Map> metricGauges; - public SolrPrometheusRegistry() { + public SolrPrometheusExporter() { this.metricCounters = new HashMap<>(); this.metricGauges = new HashMap<>(); } + /** + * Export {@link Metric} to {@link io.prometheus.metrics.model.snapshots.MetricSnapshot} and + * registers the Snapshot + * + * @param dropwizardMetric the {@link Metric} to be exported + * @param metricName Dropwizard metric name + */ + public abstract void exportDropwizardMetric(Metric dropwizardMetric, String metricName); + /** * Export {@link Meter} to {@link * io.prometheus.metrics.model.snapshots.CounterSnapshot.CounterDataPointSnapshot} and collect * datapoint * - * @param metricName name of prometheus metric + * @param metricName name of metric after export * @param dropwizardMetric the {@link Meter} to be exported - * @param labels label names and values to register with {@link - * io.prometheus.metrics.model.snapshots.CounterSnapshot.CounterDataPointSnapshot} + * @param labels label names and values to record */ - public void exportMeter(String metricName, Meter dropwizardMetric, Map labels) { + public void exportMeter(String metricName, Meter dropwizardMetric, Labels labels) { CounterSnapshot.CounterDataPointSnapshot dataPoint = - createCounterDatapoint( - (double) dropwizardMetric.getCount(), - Labels.of(new ArrayList<>(labels.keySet()), new ArrayList<>(labels.values()))); + createCounterDatapoint((double) dropwizardMetric.getCount(), labels); collectCounterDatapoint(metricName, dataPoint); } @@ -68,17 +75,12 @@ public void exportMeter(String metricName, Meter dropwizardMetric, Map labels) { + String metricName, com.codahale.metrics.Counter dropwizardMetric, Labels labels) { CounterSnapshot.CounterDataPointSnapshot dataPoint = - createCounterDatapoint( - (double) dropwizardMetric.getCount(), - Labels.of(new ArrayList<>(labels.keySet()), new ArrayList<>(labels.values()))); + createCounterDatapoint((double) dropwizardMetric.getCount(), labels); collectCounterDatapoint(metricName, dataPoint); } @@ -89,14 +91,11 @@ public void exportCounter( * * @param metricName name of prometheus metric * @param dropwizardMetric the {@link Timer} to be exported - * @param labels label names and values to record with {@link - * io.prometheus.metrics.model.snapshots.GaugeSnapshot.GaugeDataPointSnapshot} + * @param labels label names and values to record */ - public void exportTimer(String metricName, Timer dropwizardMetric, Map labels) { + public void exportTimer(String metricName, Timer dropwizardMetric, Labels labels) { GaugeSnapshot.GaugeDataPointSnapshot dataPoint = - createGaugeDatapoint( - dropwizardMetric.getMeanRate(), - Labels.of(new ArrayList<>(labels.keySet()), new ArrayList<>(labels.values()))); + createGaugeDatapoint(dropwizardMetric.getSnapshot().getMean(), labels); collectGaugeDatapoint(metricName, dataPoint); } @@ -109,31 +108,23 @@ public void exportTimer(String metricName, Timer dropwizardMetric, Map dropwizardMetricRaw, - Map labelsMap) { + String metricName, com.codahale.metrics.Gauge dropwizardMetricRaw, Labels labels) { Object dropwizardMetric = (dropwizardMetricRaw).getValue(); if (dropwizardMetric instanceof Number) { GaugeSnapshot.GaugeDataPointSnapshot dataPoint = - createGaugeDatapoint( - ((Number) dropwizardMetric).doubleValue(), - Labels.of(new ArrayList<>(labelsMap.keySet()), new ArrayList<>(labelsMap.values()))); + createGaugeDatapoint(((Number) dropwizardMetric).doubleValue(), labels); collectGaugeDatapoint(metricName, dataPoint); } else if (dropwizardMetric instanceof HashMap) { HashMap itemsMap = (HashMap) dropwizardMetric; for (Object item : itemsMap.keySet()) { if (itemsMap.get(item) instanceof Number) { - List labelKeys = new ArrayList<>(labelsMap.keySet()); - labelKeys.add("item"); - List labelValues = new ArrayList<>(labelsMap.values()); - labelValues.add((String) item); GaugeSnapshot.GaugeDataPointSnapshot dataPoint = createGaugeDatapoint( - ((Number) itemsMap.get(item)).doubleValue(), Labels.of(labelKeys, labelValues)); + ((Number) itemsMap.get(item)).doubleValue(), + labels.merge(Labels.of("item", (String) item))); collectGaugeDatapoint(metricName, dataPoint); } } diff --git a/solr/core/src/java/org/apache/solr/metrics/prometheus/core/SolrCoreCacheMetric.java b/solr/core/src/java/org/apache/solr/metrics/prometheus/core/SolrCoreCacheMetric.java index 5d963b4a9c2..36c96ffeedc 100644 --- a/solr/core/src/java/org/apache/solr/metrics/prometheus/core/SolrCoreCacheMetric.java +++ b/solr/core/src/java/org/apache/solr/metrics/prometheus/core/SolrCoreCacheMetric.java @@ -18,7 +18,9 @@ import com.codahale.metrics.Gauge; import com.codahale.metrics.Metric; -import org.apache.solr.metrics.prometheus.SolrPrometheusCoreRegistry; +import io.prometheus.metrics.model.snapshots.Labels; +import java.util.ArrayList; +import org.apache.solr.metrics.prometheus.SolrPrometheusCoreExporter; /** Dropwizard metrics of name CACHE.* */ public class SolrCoreCacheMetric extends SolrCoreMetric { @@ -40,10 +42,12 @@ public SolrCoreMetric parseLabels() { } @Override - public void toPrometheus(SolrPrometheusCoreRegistry solrPrometheusCoreRegistry) { + public void toPrometheus(SolrPrometheusCoreExporter solrPrometheusCoreRegistry) { if (dropwizardMetric instanceof Gauge) { solrPrometheusCoreRegistry.exportGauge( - CORE_CACHE_SEARCHER_METRICS, (Gauge) dropwizardMetric, labels); + CORE_CACHE_SEARCHER_METRICS, + (Gauge) dropwizardMetric, + Labels.of(new ArrayList<>(labels.keySet()), new ArrayList<>(labels.values()))); } } } diff --git a/solr/core/src/java/org/apache/solr/metrics/prometheus/core/SolrCoreHandlerMetric.java b/solr/core/src/java/org/apache/solr/metrics/prometheus/core/SolrCoreHandlerMetric.java index 32802a80809..2faa290dd6d 100644 --- a/solr/core/src/java/org/apache/solr/metrics/prometheus/core/SolrCoreHandlerMetric.java +++ b/solr/core/src/java/org/apache/solr/metrics/prometheus/core/SolrCoreHandlerMetric.java @@ -21,7 +21,9 @@ import com.codahale.metrics.Meter; import com.codahale.metrics.Metric; import com.codahale.metrics.Timer; -import org.apache.solr.metrics.prometheus.SolrPrometheusCoreRegistry; +import io.prometheus.metrics.model.snapshots.Labels; +import java.util.ArrayList; +import org.apache.solr.metrics.prometheus.SolrPrometheusCoreExporter; /** Dropwizard metrics of name ADMIN/QUERY/UPDATE/REPLICATION.* */ public class SolrCoreHandlerMetric extends SolrCoreMetric { @@ -48,28 +50,40 @@ public SolrCoreMetric parseLabels() { } @Override - public void toPrometheus(SolrPrometheusCoreRegistry solrPrometheusCoreRegistry) { + public void toPrometheus(SolrPrometheusCoreExporter solrPrometheusCoreRegistry) { if (dropwizardMetric instanceof Meter) { - solrPrometheusCoreRegistry.exportMeter(CORE_REQUESTS_TOTAL, (Meter) dropwizardMetric, labels); + solrPrometheusCoreRegistry.exportMeter( + CORE_REQUESTS_TOTAL, + (Meter) dropwizardMetric, + Labels.of(new ArrayList<>(labels.keySet()), new ArrayList<>(labels.values()))); } else if (dropwizardMetric instanceof Counter) { if (metricName.endsWith("requests")) { solrPrometheusCoreRegistry.exportCounter( - CORE_REQUESTS_TOTAL, (Counter) dropwizardMetric, labels); + CORE_REQUESTS_TOTAL, + (Counter) dropwizardMetric, + Labels.of(new ArrayList<>(labels.keySet()), new ArrayList<>(labels.values()))); } else if (metricName.endsWith("totalTime")) { // Do not need type label for total time labels.remove("type"); solrPrometheusCoreRegistry.exportCounter( - CORE_REQUESTS_TOTAL_TIME, (Counter) dropwizardMetric, labels); + CORE_REQUESTS_TOTAL_TIME, + (Counter) dropwizardMetric, + Labels.of(new ArrayList<>(labels.keySet()), new ArrayList<>(labels.values()))); } } else if (dropwizardMetric instanceof Gauge) { if (!metricName.endsWith("handlerStart")) { solrPrometheusCoreRegistry.exportGauge( - CORE_REQUESTS_UPDATE_HANDLER, (Gauge) dropwizardMetric, labels); + CORE_REQUESTS_UPDATE_HANDLER, + (Gauge) dropwizardMetric, + Labels.of(new ArrayList<>(labels.keySet()), new ArrayList<>(labels.values()))); } } else if (dropwizardMetric instanceof Timer) { // Do not need type label for request times labels.remove("type"); - solrPrometheusCoreRegistry.exportTimer(CORE_REQUEST_TIMES, (Timer) dropwizardMetric, labels); + solrPrometheusCoreRegistry.exportTimer( + CORE_REQUEST_TIMES, + (Timer) dropwizardMetric, + Labels.of(new ArrayList<>(labels.keySet()), new ArrayList<>(labels.values()))); } } } diff --git a/solr/core/src/java/org/apache/solr/metrics/prometheus/core/SolrCoreHighlighterMetric.java b/solr/core/src/java/org/apache/solr/metrics/prometheus/core/SolrCoreHighlighterMetric.java index a9674c1820d..95a7f8159b1 100644 --- a/solr/core/src/java/org/apache/solr/metrics/prometheus/core/SolrCoreHighlighterMetric.java +++ b/solr/core/src/java/org/apache/solr/metrics/prometheus/core/SolrCoreHighlighterMetric.java @@ -18,7 +18,9 @@ import com.codahale.metrics.Counter; import com.codahale.metrics.Metric; -import org.apache.solr.metrics.prometheus.SolrPrometheusCoreRegistry; +import io.prometheus.metrics.model.snapshots.Labels; +import java.util.ArrayList; +import org.apache.solr.metrics.prometheus.SolrPrometheusCoreExporter; /** Dropwizard metrics of name HIGHLIGHTER.* */ public class SolrCoreHighlighterMetric extends SolrCoreMetric { @@ -40,10 +42,12 @@ public SolrCoreMetric parseLabels() { } @Override - public void toPrometheus(SolrPrometheusCoreRegistry solrPrometheusCoreRegistry) { + public void toPrometheus(SolrPrometheusCoreExporter solrPrometheusCoreRegistry) { if (dropwizardMetric instanceof Counter) { solrPrometheusCoreRegistry.exportCounter( - CORE_HIGHLIGHER_METRICS, (Counter) dropwizardMetric, labels); + CORE_HIGHLIGHER_METRICS, + (Counter) dropwizardMetric, + Labels.of(new ArrayList<>(labels.keySet()), new ArrayList<>(labels.values()))); } } } diff --git a/solr/core/src/java/org/apache/solr/metrics/prometheus/core/SolrCoreIndexMetric.java b/solr/core/src/java/org/apache/solr/metrics/prometheus/core/SolrCoreIndexMetric.java index 1c97eb1e924..e4584ad758e 100644 --- a/solr/core/src/java/org/apache/solr/metrics/prometheus/core/SolrCoreIndexMetric.java +++ b/solr/core/src/java/org/apache/solr/metrics/prometheus/core/SolrCoreIndexMetric.java @@ -18,7 +18,9 @@ import com.codahale.metrics.Gauge; import com.codahale.metrics.Metric; -import org.apache.solr.metrics.prometheus.SolrPrometheusCoreRegistry; +import io.prometheus.metrics.model.snapshots.Labels; +import java.util.ArrayList; +import org.apache.solr.metrics.prometheus.SolrPrometheusCoreExporter; /** Dropwizard metrics of name INDEX.* */ public class SolrCoreIndexMetric extends SolrCoreMetric { @@ -35,11 +37,13 @@ public SolrCoreMetric parseLabels() { } @Override - public void toPrometheus(SolrPrometheusCoreRegistry solrPrometheusCoreRegistry) { + public void toPrometheus(SolrPrometheusCoreExporter solrPrometheusCoreRegistry) { if (dropwizardMetric instanceof Gauge) { if (metricName.endsWith("sizeInBytes")) { solrPrometheusCoreRegistry.exportGauge( - CORE_INDEX_METRICS, (Gauge) dropwizardMetric, labels); + CORE_INDEX_METRICS, + (Gauge) dropwizardMetric, + Labels.of(new ArrayList<>(labels.keySet()), new ArrayList<>(labels.values()))); } } } diff --git a/solr/core/src/java/org/apache/solr/metrics/prometheus/core/SolrCoreMetric.java b/solr/core/src/java/org/apache/solr/metrics/prometheus/core/SolrCoreMetric.java index 7e894a1b9c6..748c053f205 100644 --- a/solr/core/src/java/org/apache/solr/metrics/prometheus/core/SolrCoreMetric.java +++ b/solr/core/src/java/org/apache/solr/metrics/prometheus/core/SolrCoreMetric.java @@ -19,12 +19,12 @@ import com.codahale.metrics.Metric; import java.util.HashMap; import java.util.Map; -import org.apache.solr.metrics.prometheus.SolrPrometheusCoreRegistry; +import org.apache.solr.metrics.prometheus.SolrPrometheusCoreExporter; /** * Base class is a wrapper to categorize and export {@link com.codahale.metrics.Metric} to {@link * io.prometheus.metrics.model.snapshots.DataPointSnapshot} and register to a {@link - * SolrPrometheusCoreRegistry}. {@link com.codahale.metrics.MetricRegistry} does not support tags + * SolrPrometheusCoreExporter}. {@link com.codahale.metrics.MetricRegistry} does not support tags * unlike prometheus. Metrics registered to the registry need to be parsed out from the metric name * to be exported to {@link io.prometheus.metrics.model.snapshots.DataPointSnapshot} */ @@ -50,5 +50,5 @@ public SolrCoreMetric( public abstract SolrCoreMetric parseLabels(); - public abstract void toPrometheus(SolrPrometheusCoreRegistry solrPrometheusCoreRegistry); + public abstract void toPrometheus(SolrPrometheusCoreExporter solrPrometheusCoreRegistry); } diff --git a/solr/core/src/java/org/apache/solr/metrics/prometheus/core/SolrCoreNoOpMetric.java b/solr/core/src/java/org/apache/solr/metrics/prometheus/core/SolrCoreNoOpMetric.java index 6d22b6f8255..3e0ab963d28 100644 --- a/solr/core/src/java/org/apache/solr/metrics/prometheus/core/SolrCoreNoOpMetric.java +++ b/solr/core/src/java/org/apache/solr/metrics/prometheus/core/SolrCoreNoOpMetric.java @@ -17,7 +17,7 @@ package org.apache.solr.metrics.prometheus.core; import com.codahale.metrics.Metric; -import org.apache.solr.metrics.prometheus.SolrPrometheusCoreRegistry; +import org.apache.solr.metrics.prometheus.SolrPrometheusCoreExporter; public class SolrCoreNoOpMetric extends SolrCoreMetric { @@ -32,5 +32,5 @@ public SolrCoreMetric parseLabels() { } @Override - public void toPrometheus(SolrPrometheusCoreRegistry solrPrometheusCoreRegistry) {} + public void toPrometheus(SolrPrometheusCoreExporter solrPrometheusCoreRegistry) {} } diff --git a/solr/core/src/java/org/apache/solr/metrics/prometheus/core/SolrCoreSearcherMetric.java b/solr/core/src/java/org/apache/solr/metrics/prometheus/core/SolrCoreSearcherMetric.java index 7f6564ed576..f653128aa00 100644 --- a/solr/core/src/java/org/apache/solr/metrics/prometheus/core/SolrCoreSearcherMetric.java +++ b/solr/core/src/java/org/apache/solr/metrics/prometheus/core/SolrCoreSearcherMetric.java @@ -22,7 +22,9 @@ import com.codahale.metrics.Gauge; import com.codahale.metrics.Metric; import com.codahale.metrics.Timer; -import org.apache.solr.metrics.prometheus.SolrPrometheusCoreRegistry; +import io.prometheus.metrics.model.snapshots.Labels; +import java.util.ArrayList; +import org.apache.solr.metrics.prometheus.SolrPrometheusCoreExporter; /** Dropwizard metrics of name SEARCHER.* */ public class SolrCoreSearcherMetric extends SolrCoreMetric { @@ -45,17 +47,24 @@ public SolrCoreMetric parseLabels() { } @Override - public void toPrometheus(SolrPrometheusCoreRegistry solrPrometheusCoreRegistry) { + public void toPrometheus(SolrPrometheusCoreExporter solrPrometheusCoreRegistry) { if (dropwizardMetric instanceof Gauge) { if (metricName.endsWith("liveDocsCache")) { solrPrometheusCoreRegistry.exportGauge( - CORE_CACHE_SEARCHER_METRICS, (Gauge) dropwizardMetric, labels); + CORE_CACHE_SEARCHER_METRICS, + (Gauge) dropwizardMetric, + Labels.of(new ArrayList<>(labels.keySet()), new ArrayList<>(labels.values()))); } else { solrPrometheusCoreRegistry.exportGauge( - CORE_SEARCHER_METRICS, (Gauge) dropwizardMetric, labels); + CORE_SEARCHER_METRICS, + (Gauge) dropwizardMetric, + Labels.of(new ArrayList<>(labels.keySet()), new ArrayList<>(labels.values()))); } } else if (dropwizardMetric instanceof Timer) { - solrPrometheusCoreRegistry.exportTimer(CORE_SEARCHER_TIMES, (Timer) dropwizardMetric, labels); + solrPrometheusCoreRegistry.exportTimer( + CORE_SEARCHER_TIMES, + (Timer) dropwizardMetric, + Labels.of(new ArrayList<>(labels.keySet()), new ArrayList<>(labels.values()))); } } } diff --git a/solr/core/src/java/org/apache/solr/metrics/prometheus/core/SolrCoreTlogMetric.java b/solr/core/src/java/org/apache/solr/metrics/prometheus/core/SolrCoreTlogMetric.java index dacc385bb0e..2c49e612292 100644 --- a/solr/core/src/java/org/apache/solr/metrics/prometheus/core/SolrCoreTlogMetric.java +++ b/solr/core/src/java/org/apache/solr/metrics/prometheus/core/SolrCoreTlogMetric.java @@ -18,7 +18,9 @@ import com.codahale.metrics.Meter; import com.codahale.metrics.Metric; -import org.apache.solr.metrics.prometheus.SolrPrometheusCoreRegistry; +import io.prometheus.metrics.model.snapshots.Labels; +import java.util.ArrayList; +import org.apache.solr.metrics.prometheus.SolrPrometheusCoreExporter; /** Dropwizard metrics of name TLOG.* */ public class SolrCoreTlogMetric extends SolrCoreMetric { @@ -40,9 +42,12 @@ public SolrCoreMetric parseLabels() { } @Override - public void toPrometheus(SolrPrometheusCoreRegistry solrPrometheusCoreRegistry) { + public void toPrometheus(SolrPrometheusCoreExporter solrPrometheusCoreRegistry) { if (dropwizardMetric instanceof Meter) { - solrPrometheusCoreRegistry.exportMeter(CORE_TLOG_METRICS, (Meter) dropwizardMetric, labels); + solrPrometheusCoreRegistry.exportMeter( + CORE_TLOG_METRICS, + (Meter) dropwizardMetric, + Labels.of(new ArrayList<>(labels.keySet()), new ArrayList<>(labels.values()))); } } } diff --git a/solr/core/src/java/org/apache/solr/metrics/prometheus/package-info.java b/solr/core/src/java/org/apache/solr/metrics/prometheus/package-info.java index 384d0c42bc4..8702fc1aefb 100644 --- a/solr/core/src/java/org/apache/solr/metrics/prometheus/package-info.java +++ b/solr/core/src/java/org/apache/solr/metrics/prometheus/package-info.java @@ -16,7 +16,7 @@ */ /** - * The {@link org.apache.solr.metrics.prometheus.SolrPrometheusRegistry} is responsible for + * The {@link org.apache.solr.metrics.prometheus.SolrPrometheusExporter} is responsible for * collecting Prometheus metrics from exporting {@link com.codahale.metrics.Metric}'s from {@link * com.codahale.metrics.MetricRegistry} */ diff --git a/solr/core/src/java/org/apache/solr/response/PrometheusResponseWriter.java b/solr/core/src/java/org/apache/solr/response/PrometheusResponseWriter.java index 382d2094d13..aae7bb1b29e 100644 --- a/solr/core/src/java/org/apache/solr/response/PrometheusResponseWriter.java +++ b/solr/core/src/java/org/apache/solr/response/PrometheusResponseWriter.java @@ -21,7 +21,7 @@ import java.io.OutputStream; import java.util.Map; import org.apache.solr.common.util.NamedList; -import org.apache.solr.metrics.prometheus.SolrPrometheusCoreRegistry; +import org.apache.solr.metrics.prometheus.SolrPrometheusCoreExporter; import org.apache.solr.request.SolrQueryRequest; @SuppressWarnings(value = "unchecked") @@ -29,7 +29,6 @@ public class PrometheusResponseWriter extends RawResponseWriter { @Override public void write(OutputStream out, SolrQueryRequest request, SolrQueryResponse response) throws IOException { - NamedList prometheusRegistries = (NamedList) response.getValues().get("metrics"); Map registryMap = prometheusRegistries.asShallowMap(); @@ -37,7 +36,7 @@ public void write(OutputStream out, SolrQueryRequest request, SolrQueryResponse registryMap.forEach( (name, registry) -> { try { - SolrPrometheusCoreRegistry prometheusRegistry = (SolrPrometheusCoreRegistry) registry; + SolrPrometheusCoreExporter prometheusRegistry = (SolrPrometheusCoreExporter) registry; prometheusTextFormatWriter.write(out, prometheusRegistry.collect()); } catch (IOException e) { throw new RuntimeException(e); diff --git a/solr/core/src/java/org/apache/solr/util/stats/MetricUtils.java b/solr/core/src/java/org/apache/solr/util/stats/MetricUtils.java index ddc5c82ab69..1a7474d8bdb 100644 --- a/solr/core/src/java/org/apache/solr/util/stats/MetricUtils.java +++ b/solr/core/src/java/org/apache/solr/util/stats/MetricUtils.java @@ -56,7 +56,7 @@ import org.apache.solr.core.SolrInfoBean; import org.apache.solr.metrics.AggregateMetric; import org.apache.solr.metrics.SolrMetricManager; -import org.apache.solr.metrics.prometheus.SolrPrometheusCoreRegistry; +import org.apache.solr.metrics.prometheus.SolrPrometheusCoreExporter; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -171,7 +171,7 @@ public static void toSolrInputDocuments( /** * Provides a representation of the given Dropwizard metric registry as {@link - * SolrPrometheusCoreRegistry}-s. Only those metrics are converted which match at least one of the + * SolrPrometheusCoreExporter}-s. Only those metrics are converted which match at least one of the * given MetricFilter instances. * * @param registry the {@link MetricRegistry} to be converted @@ -183,7 +183,7 @@ public static void toSolrInputDocuments( * @param skipHistograms discard any {@link Histogram}-s and histogram parts of {@link Timer}-s. * @param skipAggregateValues discard internal values of {@link AggregateMetric}-s. * @param compact use compact representation for counters and gauges. - * @param consumer consumer that accepts produced {@link SolrPrometheusCoreRegistry}-s + * @param consumer consumer that accepts produced {@link SolrPrometheusCoreExporter}-s */ public static void toPrometheusRegistry( MetricRegistry registry, @@ -194,7 +194,7 @@ public static void toPrometheusRegistry( boolean skipHistograms, boolean skipAggregateValues, boolean compact, - Consumer consumer) { + Consumer consumer) { String coreName; boolean cloudMode = false; Map dropwizardMetrics = registry.getMetrics(); @@ -210,8 +210,8 @@ public static void toPrometheusRegistry( coreName = registryName; } - SolrPrometheusCoreRegistry solrPrometheusCoreMetrics = - new SolrPrometheusCoreRegistry(coreName, cloudMode); + SolrPrometheusCoreExporter solrPrometheusCoreExporter = + new SolrPrometheusCoreExporter(coreName, cloudMode); toMaps( registry, @@ -225,13 +225,13 @@ public static void toPrometheusRegistry( (metricName, metric) -> { try { Metric dropwizardMetric = dropwizardMetrics.get(metricName); - solrPrometheusCoreMetrics.exportDropwizardMetric(dropwizardMetric, metricName); + solrPrometheusCoreExporter.exportDropwizardMetric(dropwizardMetric, metricName); } catch (Exception e) { // Do not fail entirely for metrics exporting. Log and try to export next metric log.warn("Error occurred exporting Dropwizard Metric to Prometheus", e); } }); - consumer.accept(solrPrometheusCoreMetrics); + consumer.accept(solrPrometheusCoreExporter); } /** diff --git a/solr/core/src/test/org/apache/solr/handler/admin/MetricsHandlerTest.java b/solr/core/src/test/org/apache/solr/handler/admin/MetricsHandlerTest.java index 4af82d345ee..64765e277a4 100644 --- a/solr/core/src/test/org/apache/solr/handler/admin/MetricsHandlerTest.java +++ b/solr/core/src/test/org/apache/solr/handler/admin/MetricsHandlerTest.java @@ -38,7 +38,7 @@ import org.apache.solr.handler.RequestHandlerBase; import org.apache.solr.metrics.MetricsMap; import org.apache.solr.metrics.SolrMetricsContext; -import org.apache.solr.metrics.prometheus.SolrPrometheusRegistry; +import org.apache.solr.metrics.prometheus.SolrPrometheusExporter; import org.apache.solr.request.SolrQueryRequest; import org.apache.solr.request.SolrRequestHandler; import org.apache.solr.response.SolrQueryResponse; @@ -703,7 +703,7 @@ public void testPrometheusMetrics() throws Exception { NamedList values = resp.getValues(); assertNotNull(values.get("metrics")); values = (NamedList) values.get("metrics"); - SolrPrometheusRegistry registry = (SolrPrometheusRegistry) values.get("solr.core.collection1"); + SolrPrometheusExporter registry = (SolrPrometheusExporter) values.get("solr.core.collection1"); assertNotNull(registry); MetricSnapshots actualSnapshots = registry.collect(); assertNotNull(actualSnapshots); diff --git a/solr/core/src/test/org/apache/solr/metrics/SolrPrometheusExporterTest.java b/solr/core/src/test/org/apache/solr/metrics/SolrPrometheusExporterTest.java new file mode 100644 index 00000000000..632b20bcc11 --- /dev/null +++ b/solr/core/src/test/org/apache/solr/metrics/SolrPrometheusExporterTest.java @@ -0,0 +1,145 @@ +package org.apache.solr.metrics; + +import com.codahale.metrics.Counter; +import com.codahale.metrics.Gauge; +import com.codahale.metrics.Meter; +import com.codahale.metrics.Metric; +import com.codahale.metrics.SettableGauge; +import com.codahale.metrics.Timer; +import io.prometheus.metrics.model.snapshots.CounterSnapshot; +import io.prometheus.metrics.model.snapshots.GaugeSnapshot; +import io.prometheus.metrics.model.snapshots.Labels; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.concurrent.TimeUnit; +import org.apache.solr.SolrTestCaseJ4; +import org.apache.solr.metrics.prometheus.SolrPrometheusExporter; +import org.junit.Test; + +public class SolrPrometheusExporterTest extends SolrTestCaseJ4 { + @Test + public void testExportMeter() { + TestSolrPrometheusExporter testExporter = new TestSolrPrometheusExporter(); + String expectedMetricName = "test_metric"; + Meter metric = new Meter(); + metric.mark(123); + Labels expectedLabels = Labels.of("test", "test-value"); + + testExporter.exportMeter(expectedMetricName, metric, expectedLabels); + assertTrue(testExporter.getMetricCounters().containsKey(expectedMetricName)); + + CounterSnapshot.CounterDataPointSnapshot actual = + testExporter.getMetricCounters().get("test_metric").get(0); + assertEquals(123.0, actual.getValue(), 0); + assertEquals(expectedLabels, actual.getLabels()); + } + + @Test + public void testExportCounter() { + TestSolrPrometheusExporter testExporter = new TestSolrPrometheusExporter(); + String expectedMetricName = "test_metric"; + Counter metric = new Counter(); + metric.inc(123); + Labels expectedLabels = Labels.of("test", "test-value"); + + testExporter.exportCounter(expectedMetricName, metric, expectedLabels); + assertTrue(testExporter.getMetricCounters().containsKey(expectedMetricName)); + + CounterSnapshot.CounterDataPointSnapshot actual = + testExporter.getMetricCounters().get("test_metric").get(0); + assertEquals(123.0, actual.getValue(), 0); + assertEquals(expectedLabels, actual.getLabels()); + } + + @Test + public void testExportTimer() throws InterruptedException { + TestSolrPrometheusExporter testExporter = new TestSolrPrometheusExporter(); + String expectedMetricName = "test_metric"; + Timer metric = new Timer(); + Timer.Context context = metric.time(); + TimeUnit.SECONDS.sleep(5); + context.stop(); + + Labels expectedLabels = Labels.of("test", "test-value"); + testExporter.exportTimer(expectedMetricName, metric, expectedLabels); + assertTrue(testExporter.getMetricGauges().containsKey(expectedMetricName)); + + GaugeSnapshot.GaugeDataPointSnapshot actual = + testExporter.getMetricGauges().get("test_metric").get(0); + assertEquals(5000000000L, actual.getValue(), 500000000L); + assertEquals(expectedLabels, actual.getLabels()); + } + + @Test + public void testExportGaugeNumber() throws InterruptedException { + TestSolrPrometheusExporter testExporter = new TestSolrPrometheusExporter(); + String expectedMetricName = "test_metric"; + Gauge metric = + new SettableGauge<>() { + @Override + public void setValue(Number value) { + return; + } + + @Override + public Number getValue() { + return 123.0; + } + }; + + Labels expectedLabels = Labels.of("test", "test-value"); + testExporter.exportGauge(expectedMetricName, metric, expectedLabels); + assertTrue(testExporter.getMetricGauges().containsKey(expectedMetricName)); + + GaugeSnapshot.GaugeDataPointSnapshot actual = + testExporter.getMetricGauges().get("test_metric").get(0); + assertEquals(123.0, actual.getValue(), 0); + assertEquals(expectedLabels, actual.getLabels()); + } + + @Test + public void testExportGaugeMap() throws InterruptedException { + TestSolrPrometheusExporter testExporter = new TestSolrPrometheusExporter(); + String expectedMetricName = "test_metric"; + Gauge> metric = + new SettableGauge<>() { + @Override + public void setValue(Map value) { + return; + } + + @Override + public Map getValue() { + final Map expected = new HashMap<>(); + expected.put("test-item", 123.0); + return expected; + } + }; + + Labels labels = Labels.of("test", "test-value"); + testExporter.exportGauge(expectedMetricName, metric, labels); + assertTrue(testExporter.getMetricGauges().containsKey(expectedMetricName)); + + GaugeSnapshot.GaugeDataPointSnapshot actual = + testExporter.getMetricGauges().get("test_metric").get(0); + assertEquals(123.0, actual.getValue(), 0); + Labels expectedLabels = Labels.of("test", "test-value", "item", "test-item"); + assertEquals(expectedLabels, actual.getLabels()); + } + + static class TestSolrPrometheusExporter extends SolrPrometheusExporter { + @Override + public void exportDropwizardMetric(Metric dropwizardMetric, String metricName) { + return; + } + + public Map> getMetricCounters() { + return metricCounters; + } + + public Map> getMetricGauges() { + return metricGauges; + } + } +} From a802716bb13b1da1533010f8b4b9b63df84b5e09 Mon Sep 17 00:00:00 2001 From: mbiscocho Date: Thu, 2 May 2024 14:45:02 -0400 Subject: [PATCH 12/32] Add test for Prometheus Response Writer --- .../TestPrometheusResponseWriter.java | 66 +++++++++++++++++++ 1 file changed, 66 insertions(+) create mode 100644 solr/core/src/test/org/apache/solr/response/TestPrometheusResponseWriter.java diff --git a/solr/core/src/test/org/apache/solr/response/TestPrometheusResponseWriter.java b/solr/core/src/test/org/apache/solr/response/TestPrometheusResponseWriter.java new file mode 100644 index 00000000000..bed816d894a --- /dev/null +++ b/solr/core/src/test/org/apache/solr/response/TestPrometheusResponseWriter.java @@ -0,0 +1,66 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.solr.response; + +import io.prometheus.metrics.model.snapshots.CounterSnapshot; +import io.prometheus.metrics.model.snapshots.GaugeSnapshot; +import io.prometheus.metrics.model.snapshots.Labels; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import org.apache.solr.SolrTestCaseJ4; +import org.apache.solr.common.util.NamedList; +import org.apache.solr.common.util.SimpleOrderedMap; +import org.apache.solr.metrics.prometheus.SolrPrometheusCoreExporter; +import org.apache.solr.request.SolrQueryRequest; +import org.junit.BeforeClass; +import org.junit.Test; + +/** Tests the {@link PrometheusResponseWriter} behavior */ +public class TestPrometheusResponseWriter extends SolrTestCaseJ4 { + + @BeforeClass + public static void beforeClass() throws Exception { + initCore("solrconfig.xml", "schema.xml"); + } + + @Test + public void testPrometheusOutput() throws IOException { + SolrQueryRequest req = req("dummy"); + SolrQueryResponse rsp = new SolrQueryResponse(); + PrometheusResponseWriter w = new PrometheusResponseWriter(); + NamedList registries = new SimpleOrderedMap<>(); + ByteArrayOutputStream actual = new ByteArrayOutputStream(); + Labels expectedLabels = Labels.of("test", "test-value"); + + SolrPrometheusCoreExporter registry = new SolrPrometheusCoreExporter("collection1", false); + CounterSnapshot.CounterDataPointSnapshot counterDatapoint = + registry.createCounterDatapoint(1.234, expectedLabels); + GaugeSnapshot.GaugeDataPointSnapshot gaugeDataPoint = + registry.createGaugeDatapoint(9.876, expectedLabels); + registry.collectCounterDatapoint("test_counter_metric_name", counterDatapoint); + registry.collectGaugeDatapoint("test_gauge_metric_name", gaugeDataPoint); + registries.add("solr.core.collection1", registry); + rsp.add("metrics", registries); + + w.write(actual, req, rsp); + String test = actual.toString(); + assertEquals( + "# TYPE test_counter_metric_name_total counter\ntest_counter_metric_name_total{test=\"test-value\"} 1.234\n# TYPE test_gauge_metric_name gauge\ntest_gauge_metric_name{test=\"test-value\"} 9.876\n", + actual.toString()); + req.close(); + } +} From a57e10786296cbcc1b234b44fdf75ea42f67932e Mon Sep 17 00:00:00 2001 From: mbiscocho Date: Thu, 2 May 2024 15:52:29 -0400 Subject: [PATCH 13/32] Remove fobidden api usages --- .../solr/metrics/SolrPrometheusExporterTest.java | 16 ++++++++++++++++ .../response/TestPrometheusResponseWriter.java | 9 +++++---- 2 files changed, 21 insertions(+), 4 deletions(-) diff --git a/solr/core/src/test/org/apache/solr/metrics/SolrPrometheusExporterTest.java b/solr/core/src/test/org/apache/solr/metrics/SolrPrometheusExporterTest.java index 632b20bcc11..75e45d73c66 100644 --- a/solr/core/src/test/org/apache/solr/metrics/SolrPrometheusExporterTest.java +++ b/solr/core/src/test/org/apache/solr/metrics/SolrPrometheusExporterTest.java @@ -1,3 +1,19 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ package org.apache.solr.metrics; import com.codahale.metrics.Counter; diff --git a/solr/core/src/test/org/apache/solr/response/TestPrometheusResponseWriter.java b/solr/core/src/test/org/apache/solr/response/TestPrometheusResponseWriter.java index bed816d894a..b02dada6098 100644 --- a/solr/core/src/test/org/apache/solr/response/TestPrometheusResponseWriter.java +++ b/solr/core/src/test/org/apache/solr/response/TestPrometheusResponseWriter.java @@ -21,6 +21,7 @@ import io.prometheus.metrics.model.snapshots.Labels; import java.io.ByteArrayOutputStream; import java.io.IOException; +import java.nio.charset.StandardCharsets; import org.apache.solr.SolrTestCaseJ4; import org.apache.solr.common.util.NamedList; import org.apache.solr.common.util.SimpleOrderedMap; @@ -43,7 +44,7 @@ public void testPrometheusOutput() throws IOException { SolrQueryResponse rsp = new SolrQueryResponse(); PrometheusResponseWriter w = new PrometheusResponseWriter(); NamedList registries = new SimpleOrderedMap<>(); - ByteArrayOutputStream actual = new ByteArrayOutputStream(); + ByteArrayOutputStream byteOut = new ByteArrayOutputStream(); Labels expectedLabels = Labels.of("test", "test-value"); SolrPrometheusCoreExporter registry = new SolrPrometheusCoreExporter("collection1", false); @@ -56,11 +57,11 @@ public void testPrometheusOutput() throws IOException { registries.add("solr.core.collection1", registry); rsp.add("metrics", registries); - w.write(actual, req, rsp); - String test = actual.toString(); + w.write(byteOut, req, rsp); + String actual = byteOut.toString(StandardCharsets.UTF_8); assertEquals( "# TYPE test_counter_metric_name_total counter\ntest_counter_metric_name_total{test=\"test-value\"} 1.234\n# TYPE test_gauge_metric_name gauge\ntest_gauge_metric_name{test=\"test-value\"} 9.876\n", - actual.toString()); + actual); req.close(); } } From c40dda3c3b2c49e7cac8fa511b2b570598189b9f Mon Sep 17 00:00:00 2001 From: mbiscocho Date: Fri, 3 May 2024 11:35:11 -0400 Subject: [PATCH 14/32] Check against different metric for test --- .../org/apache/solr/handler/admin/MetricsHandlerTest.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/solr/core/src/test/org/apache/solr/handler/admin/MetricsHandlerTest.java b/solr/core/src/test/org/apache/solr/handler/admin/MetricsHandlerTest.java index 64765e277a4..08ad2f73489 100644 --- a/solr/core/src/test/org/apache/solr/handler/admin/MetricsHandlerTest.java +++ b/solr/core/src/test/org/apache/solr/handler/admin/MetricsHandlerTest.java @@ -730,7 +730,7 @@ public void testPrometheusMetrics() throws Exception { "core", "collection1", "handler", - "/select"))) + "/select[shard]"))) .findAny(); assertTrue(actualGaugeDataPoint.isPresent()); assertEquals(0, actualGaugeDataPoint.get().getValue(), 0); @@ -753,7 +753,7 @@ public void testPrometheusMetrics() throws Exception { "core", "collection1", "handler", - "/select", + "/select[shard]", "type", "requests"))) .findAny(); From 0aa1b5510d8a9d3dbe7f6b71d079c547d30c7202 Mon Sep 17 00:00:00 2001 From: mbiscocho Date: Fri, 3 May 2024 12:57:19 -0400 Subject: [PATCH 15/32] Broken precommit --- .../solr/handler/admin/MetricsHandlerTest.java | 2 +- .../solr/metrics/SolrPrometheusExporterTest.java | 12 +++--------- 2 files changed, 4 insertions(+), 10 deletions(-) diff --git a/solr/core/src/test/org/apache/solr/handler/admin/MetricsHandlerTest.java b/solr/core/src/test/org/apache/solr/handler/admin/MetricsHandlerTest.java index 08ad2f73489..458aadf28aa 100644 --- a/solr/core/src/test/org/apache/solr/handler/admin/MetricsHandlerTest.java +++ b/solr/core/src/test/org/apache/solr/handler/admin/MetricsHandlerTest.java @@ -830,7 +830,7 @@ public void testPrometheusMetrics() throws Exception { "core", "collection1", "handler", - "/select"))) + "/select[shard]"))) .findAny(); assertTrue(actualCounterDataPoint.isPresent()); assertEquals(0, actualCounterDataPoint.get().getValue(), 0); diff --git a/solr/core/src/test/org/apache/solr/metrics/SolrPrometheusExporterTest.java b/solr/core/src/test/org/apache/solr/metrics/SolrPrometheusExporterTest.java index 75e45d73c66..f0759c8fb75 100644 --- a/solr/core/src/test/org/apache/solr/metrics/SolrPrometheusExporterTest.java +++ b/solr/core/src/test/org/apache/solr/metrics/SolrPrometheusExporterTest.java @@ -94,9 +94,7 @@ public void testExportGaugeNumber() throws InterruptedException { Gauge metric = new SettableGauge<>() { @Override - public void setValue(Number value) { - return; - } + public void setValue(Number value) {} @Override public Number getValue() { @@ -121,9 +119,7 @@ public void testExportGaugeMap() throws InterruptedException { Gauge> metric = new SettableGauge<>() { @Override - public void setValue(Map value) { - return; - } + public void setValue(Map value) {} @Override public Map getValue() { @@ -146,9 +142,7 @@ public Map getValue() { static class TestSolrPrometheusExporter extends SolrPrometheusExporter { @Override - public void exportDropwizardMetric(Metric dropwizardMetric, String metricName) { - return; - } + public void exportDropwizardMetric(Metric dropwizardMetric, String metricName) {} public Map> getMetricCounters() { return metricCounters; From 88e6347e65939bc5f63a43896141415d34bcd4e9 Mon Sep 17 00:00:00 2001 From: mbiscocho Date: Tue, 7 May 2024 13:35:17 -0400 Subject: [PATCH 16/32] Remove transitive dependencies --- solr/core/build.gradle | 5 +- .../prometheus-metrics-config-1.1.0.jar.sha1 | 1 - .../prometheus-metrics-config-LICENSE-ASL.txt | 201 ------------------ .../prometheus-metrics-config-NOTICE.txt | 11 - ...eus-metrics-shaded-protobuf-1.1.0.jar.sha1 | 1 - ...us-metrics-shaded-protobuf-LICENSE-ASL.txt | 201 ------------------ ...metheus-metrics-shaded-protobuf-NOTICE.txt | 11 - versions.lock | 2 - 8 files changed, 4 insertions(+), 429 deletions(-) delete mode 100644 solr/licenses/prometheus-metrics-config-1.1.0.jar.sha1 delete mode 100644 solr/licenses/prometheus-metrics-config-LICENSE-ASL.txt delete mode 100644 solr/licenses/prometheus-metrics-config-NOTICE.txt delete mode 100644 solr/licenses/prometheus-metrics-shaded-protobuf-1.1.0.jar.sha1 delete mode 100644 solr/licenses/prometheus-metrics-shaded-protobuf-LICENSE-ASL.txt delete mode 100644 solr/licenses/prometheus-metrics-shaded-protobuf-NOTICE.txt diff --git a/solr/core/build.gradle b/solr/core/build.gradle index 933ab5c04d7..76cef0bd876 100644 --- a/solr/core/build.gradle +++ b/solr/core/build.gradle @@ -155,7 +155,10 @@ dependencies { // Prometheus client implementation 'io.prometheus:prometheus-metrics-model:1.1.0' - implementation 'io.prometheus:prometheus-metrics-exposition-formats:1.1.0' + implementation('io.prometheus:prometheus-metrics-exposition-formats:1.1.0', { + exclude group: "io.prometheus", module: "prometheus-metrics-shaded-protobuf" + exclude group: "io.prometheus", module: "prometheus-metrics-config" + }) // For faster XML processing than the JDK implementation 'org.codehaus.woodstox:stax2-api' diff --git a/solr/licenses/prometheus-metrics-config-1.1.0.jar.sha1 b/solr/licenses/prometheus-metrics-config-1.1.0.jar.sha1 deleted file mode 100644 index 954a48dcf64..00000000000 --- a/solr/licenses/prometheus-metrics-config-1.1.0.jar.sha1 +++ /dev/null @@ -1 +0,0 @@ -4588ed1d1bbdcebb2663ccef1162f4cc4c5eb9fb diff --git a/solr/licenses/prometheus-metrics-config-LICENSE-ASL.txt b/solr/licenses/prometheus-metrics-config-LICENSE-ASL.txt deleted file mode 100644 index f49a4e16e68..00000000000 --- a/solr/licenses/prometheus-metrics-config-LICENSE-ASL.txt +++ /dev/null @@ -1,201 +0,0 @@ - Apache License - Version 2.0, January 2004 - http://www.apache.org/licenses/ - - TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION - - 1. Definitions. - - "License" shall mean the terms and conditions for use, reproduction, - and distribution as defined by Sections 1 through 9 of this document. - - "Licensor" shall mean the copyright owner or entity authorized by - the copyright owner that is granting the License. - - "Legal Entity" shall mean the union of the acting entity and all - other entities that control, are controlled by, or are under common - control with that entity. For the purposes of this definition, - "control" means (i) the power, direct or indirect, to cause the - direction or management of such entity, whether by contract or - otherwise, or (ii) ownership of fifty percent (50%) or more of the - outstanding shares, or (iii) beneficial ownership of such entity. - - "You" (or "Your") shall mean an individual or Legal Entity - exercising permissions granted by this License. - - "Source" form shall mean the preferred form for making modifications, - including but not limited to software source code, documentation - source, and configuration files. - - "Object" form shall mean any form resulting from mechanical - transformation or translation of a Source form, including but - not limited to compiled object code, generated documentation, - and conversions to other media types. - - "Work" shall mean the work of authorship, whether in Source or - Object form, made available under the License, as indicated by a - copyright notice that is included in or attached to the work - (an example is provided in the Appendix below). - - "Derivative Works" shall mean any work, whether in Source or Object - form, that is based on (or derived from) the Work and for which the - editorial revisions, annotations, elaborations, or other modifications - represent, as a whole, an original work of authorship. For the purposes - of this License, Derivative Works shall not include works that remain - separable from, or merely link (or bind by name) to the interfaces of, - the Work and Derivative Works thereof. - - "Contribution" shall mean any work of authorship, including - the original version of the Work and any modifications or additions - to that Work or Derivative Works thereof, that is intentionally - submitted to Licensor for inclusion in the Work by the copyright owner - or by an individual or Legal Entity authorized to submit on behalf of - the copyright owner. For the purposes of this definition, "submitted" - means any form of electronic, verbal, or written communication sent - to the Licensor or its representatives, including but not limited to - communication on electronic mailing lists, source code control systems, - and issue tracking systems that are managed by, or on behalf of, the - Licensor for the purpose of discussing and improving the Work, but - excluding communication that is conspicuously marked or otherwise - designated in writing by the copyright owner as "Not a Contribution." - - "Contributor" shall mean Licensor and any individual or Legal Entity - on behalf of whom a Contribution has been received by Licensor and - subsequently incorporated within the Work. - - 2. Grant of Copyright License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - copyright license to reproduce, prepare Derivative Works of, - publicly display, publicly perform, sublicense, and distribute the - Work and such Derivative Works in Source or Object form. - - 3. Grant of Patent License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - (except as stated in this section) patent license to make, have made, - use, offer to sell, sell, import, and otherwise transfer the Work, - where such license applies only to those patent claims licensable - by such Contributor that are necessarily infringed by their - Contribution(s) alone or by combination of their Contribution(s) - with the Work to which such Contribution(s) was submitted. If You - institute patent litigation against any entity (including a - cross-claim or counterclaim in a lawsuit) alleging that the Work - or a Contribution incorporated within the Work constitutes direct - or contributory patent infringement, then any patent licenses - granted to You under this License for that Work shall terminate - as of the date such litigation is filed. - - 4. Redistribution. You may reproduce and distribute copies of the - Work or Derivative Works thereof in any medium, with or without - modifications, and in Source or Object form, provided that You - meet the following conditions: - - (a) You must give any other recipients of the Work or - Derivative Works a copy of this License; and - - (b) You must cause any modified files to carry prominent notices - stating that You changed the files; and - - (c) You must retain, in the Source form of any Derivative Works - that You distribute, all copyright, patent, trademark, and - attribution notices from the Source form of the Work, - excluding those notices that do not pertain to any part of - the Derivative Works; and - - (d) If the Work includes a "NOTICE" text file as part of its - distribution, then any Derivative Works that You distribute must - include a readable copy of the attribution notices contained - within such NOTICE file, excluding those notices that do not - pertain to any part of the Derivative Works, in at least one - of the following places: within a NOTICE text file distributed - as part of the Derivative Works; within the Source form or - documentation, if provided along with the Derivative Works; or, - within a display generated by the Derivative Works, if and - wherever such third-party notices normally appear. The contents - of the NOTICE file are for informational purposes only and - do not modify the License. You may add Your own attribution - notices within Derivative Works that You distribute, alongside - or as an addendum to the NOTICE text from the Work, provided - that such additional attribution notices cannot be construed - as modifying the License. - - You may add Your own copyright statement to Your modifications and - may provide additional or different license terms and conditions - for use, reproduction, or distribution of Your modifications, or - for any such Derivative Works as a whole, provided Your use, - reproduction, and distribution of the Work otherwise complies with - the conditions stated in this License. - - 5. Submission of Contributions. Unless You explicitly state otherwise, - any Contribution intentionally submitted for inclusion in the Work - by You to the Licensor shall be under the terms and conditions of - this License, without any additional terms or conditions. - Notwithstanding the above, nothing herein shall supersede or modify - the terms of any separate license agreement you may have executed - with Licensor regarding such Contributions. - - 6. Trademarks. This License does not grant permission to use the trade - names, trademarks, service marks, or product names of the Licensor, - except as required for reasonable and customary use in describing the - origin of the Work and reproducing the content of the NOTICE file. - - 7. Disclaimer of Warranty. Unless required by applicable law or - agreed to in writing, Licensor provides the Work (and each - Contributor provides its Contributions) on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - implied, including, without limitation, any warranties or conditions - of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A - PARTICULAR PURPOSE. You are solely responsible for determining the - appropriateness of using or redistributing the Work and assume any - risks associated with Your exercise of permissions under this License. - - 8. Limitation of Liability. In no event and under no legal theory, - whether in tort (including negligence), contract, or otherwise, - unless required by applicable law (such as deliberate and grossly - negligent acts) or agreed to in writing, shall any Contributor be - liable to You for damages, including any direct, indirect, special, - incidental, or consequential damages of any character arising as a - result of this License or out of the use or inability to use the - Work (including but not limited to damages for loss of goodwill, - work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses), even if such Contributor - has been advised of the possibility of such damages. - - 9. Accepting Warranty or Additional Liability. While redistributing - the Work or Derivative Works thereof, You may choose to offer, - and charge a fee for, acceptance of support, warranty, indemnity, - or other liability obligations and/or rights consistent with this - License. However, in accepting such obligations, You may act only - on Your own behalf and on Your sole responsibility, not on behalf - of any other Contributor, and only if You agree to indemnify, - defend, and hold each Contributor harmless for any liability - incurred by, or claims asserted against, such Contributor by reason - of your accepting any such warranty or additional liability. - - END OF TERMS AND CONDITIONS - - APPENDIX: How to apply the Apache License to your work. - - To apply the Apache License to your work, attach the following - boilerplate notice, with the fields enclosed by brackets "[]" - replaced with your own identifying information. (Don't include - the brackets!) The text should be enclosed in the appropriate - comment syntax for the file format. We also recommend that a - file or class name and description of purpose be included on the - same "printed page" as the copyright notice for easier - identification within third-party archives. - - Copyright [yyyy] [name of copyright owner] - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. \ No newline at end of file diff --git a/solr/licenses/prometheus-metrics-config-NOTICE.txt b/solr/licenses/prometheus-metrics-config-NOTICE.txt deleted file mode 100644 index cbd3cd95bef..00000000000 --- a/solr/licenses/prometheus-metrics-config-NOTICE.txt +++ /dev/null @@ -1,11 +0,0 @@ -Prometheus instrumentation library for JVM applications -Copyright 2012-2015 The Prometheus Authors - -This product includes software developed at -Boxever Ltd. (http://www.boxever.com/). - -This product includes software developed at -SoundCloud Ltd. (http://soundcloud.com/). - -This product includes software developed as part of the -Ocelli project by Netflix Inc. (https://github.com/Netflix/ocelli/). \ No newline at end of file diff --git a/solr/licenses/prometheus-metrics-shaded-protobuf-1.1.0.jar.sha1 b/solr/licenses/prometheus-metrics-shaded-protobuf-1.1.0.jar.sha1 deleted file mode 100644 index c593438438d..00000000000 --- a/solr/licenses/prometheus-metrics-shaded-protobuf-1.1.0.jar.sha1 +++ /dev/null @@ -1 +0,0 @@ -5a18603c6281609b0e9e1e7f21d647c6ce994adb diff --git a/solr/licenses/prometheus-metrics-shaded-protobuf-LICENSE-ASL.txt b/solr/licenses/prometheus-metrics-shaded-protobuf-LICENSE-ASL.txt deleted file mode 100644 index f49a4e16e68..00000000000 --- a/solr/licenses/prometheus-metrics-shaded-protobuf-LICENSE-ASL.txt +++ /dev/null @@ -1,201 +0,0 @@ - Apache License - Version 2.0, January 2004 - http://www.apache.org/licenses/ - - TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION - - 1. Definitions. - - "License" shall mean the terms and conditions for use, reproduction, - and distribution as defined by Sections 1 through 9 of this document. - - "Licensor" shall mean the copyright owner or entity authorized by - the copyright owner that is granting the License. - - "Legal Entity" shall mean the union of the acting entity and all - other entities that control, are controlled by, or are under common - control with that entity. For the purposes of this definition, - "control" means (i) the power, direct or indirect, to cause the - direction or management of such entity, whether by contract or - otherwise, or (ii) ownership of fifty percent (50%) or more of the - outstanding shares, or (iii) beneficial ownership of such entity. - - "You" (or "Your") shall mean an individual or Legal Entity - exercising permissions granted by this License. - - "Source" form shall mean the preferred form for making modifications, - including but not limited to software source code, documentation - source, and configuration files. - - "Object" form shall mean any form resulting from mechanical - transformation or translation of a Source form, including but - not limited to compiled object code, generated documentation, - and conversions to other media types. - - "Work" shall mean the work of authorship, whether in Source or - Object form, made available under the License, as indicated by a - copyright notice that is included in or attached to the work - (an example is provided in the Appendix below). - - "Derivative Works" shall mean any work, whether in Source or Object - form, that is based on (or derived from) the Work and for which the - editorial revisions, annotations, elaborations, or other modifications - represent, as a whole, an original work of authorship. For the purposes - of this License, Derivative Works shall not include works that remain - separable from, or merely link (or bind by name) to the interfaces of, - the Work and Derivative Works thereof. - - "Contribution" shall mean any work of authorship, including - the original version of the Work and any modifications or additions - to that Work or Derivative Works thereof, that is intentionally - submitted to Licensor for inclusion in the Work by the copyright owner - or by an individual or Legal Entity authorized to submit on behalf of - the copyright owner. For the purposes of this definition, "submitted" - means any form of electronic, verbal, or written communication sent - to the Licensor or its representatives, including but not limited to - communication on electronic mailing lists, source code control systems, - and issue tracking systems that are managed by, or on behalf of, the - Licensor for the purpose of discussing and improving the Work, but - excluding communication that is conspicuously marked or otherwise - designated in writing by the copyright owner as "Not a Contribution." - - "Contributor" shall mean Licensor and any individual or Legal Entity - on behalf of whom a Contribution has been received by Licensor and - subsequently incorporated within the Work. - - 2. Grant of Copyright License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - copyright license to reproduce, prepare Derivative Works of, - publicly display, publicly perform, sublicense, and distribute the - Work and such Derivative Works in Source or Object form. - - 3. Grant of Patent License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - (except as stated in this section) patent license to make, have made, - use, offer to sell, sell, import, and otherwise transfer the Work, - where such license applies only to those patent claims licensable - by such Contributor that are necessarily infringed by their - Contribution(s) alone or by combination of their Contribution(s) - with the Work to which such Contribution(s) was submitted. If You - institute patent litigation against any entity (including a - cross-claim or counterclaim in a lawsuit) alleging that the Work - or a Contribution incorporated within the Work constitutes direct - or contributory patent infringement, then any patent licenses - granted to You under this License for that Work shall terminate - as of the date such litigation is filed. - - 4. Redistribution. You may reproduce and distribute copies of the - Work or Derivative Works thereof in any medium, with or without - modifications, and in Source or Object form, provided that You - meet the following conditions: - - (a) You must give any other recipients of the Work or - Derivative Works a copy of this License; and - - (b) You must cause any modified files to carry prominent notices - stating that You changed the files; and - - (c) You must retain, in the Source form of any Derivative Works - that You distribute, all copyright, patent, trademark, and - attribution notices from the Source form of the Work, - excluding those notices that do not pertain to any part of - the Derivative Works; and - - (d) If the Work includes a "NOTICE" text file as part of its - distribution, then any Derivative Works that You distribute must - include a readable copy of the attribution notices contained - within such NOTICE file, excluding those notices that do not - pertain to any part of the Derivative Works, in at least one - of the following places: within a NOTICE text file distributed - as part of the Derivative Works; within the Source form or - documentation, if provided along with the Derivative Works; or, - within a display generated by the Derivative Works, if and - wherever such third-party notices normally appear. The contents - of the NOTICE file are for informational purposes only and - do not modify the License. You may add Your own attribution - notices within Derivative Works that You distribute, alongside - or as an addendum to the NOTICE text from the Work, provided - that such additional attribution notices cannot be construed - as modifying the License. - - You may add Your own copyright statement to Your modifications and - may provide additional or different license terms and conditions - for use, reproduction, or distribution of Your modifications, or - for any such Derivative Works as a whole, provided Your use, - reproduction, and distribution of the Work otherwise complies with - the conditions stated in this License. - - 5. Submission of Contributions. Unless You explicitly state otherwise, - any Contribution intentionally submitted for inclusion in the Work - by You to the Licensor shall be under the terms and conditions of - this License, without any additional terms or conditions. - Notwithstanding the above, nothing herein shall supersede or modify - the terms of any separate license agreement you may have executed - with Licensor regarding such Contributions. - - 6. Trademarks. This License does not grant permission to use the trade - names, trademarks, service marks, or product names of the Licensor, - except as required for reasonable and customary use in describing the - origin of the Work and reproducing the content of the NOTICE file. - - 7. Disclaimer of Warranty. Unless required by applicable law or - agreed to in writing, Licensor provides the Work (and each - Contributor provides its Contributions) on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - implied, including, without limitation, any warranties or conditions - of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A - PARTICULAR PURPOSE. You are solely responsible for determining the - appropriateness of using or redistributing the Work and assume any - risks associated with Your exercise of permissions under this License. - - 8. Limitation of Liability. In no event and under no legal theory, - whether in tort (including negligence), contract, or otherwise, - unless required by applicable law (such as deliberate and grossly - negligent acts) or agreed to in writing, shall any Contributor be - liable to You for damages, including any direct, indirect, special, - incidental, or consequential damages of any character arising as a - result of this License or out of the use or inability to use the - Work (including but not limited to damages for loss of goodwill, - work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses), even if such Contributor - has been advised of the possibility of such damages. - - 9. Accepting Warranty or Additional Liability. While redistributing - the Work or Derivative Works thereof, You may choose to offer, - and charge a fee for, acceptance of support, warranty, indemnity, - or other liability obligations and/or rights consistent with this - License. However, in accepting such obligations, You may act only - on Your own behalf and on Your sole responsibility, not on behalf - of any other Contributor, and only if You agree to indemnify, - defend, and hold each Contributor harmless for any liability - incurred by, or claims asserted against, such Contributor by reason - of your accepting any such warranty or additional liability. - - END OF TERMS AND CONDITIONS - - APPENDIX: How to apply the Apache License to your work. - - To apply the Apache License to your work, attach the following - boilerplate notice, with the fields enclosed by brackets "[]" - replaced with your own identifying information. (Don't include - the brackets!) The text should be enclosed in the appropriate - comment syntax for the file format. We also recommend that a - file or class name and description of purpose be included on the - same "printed page" as the copyright notice for easier - identification within third-party archives. - - Copyright [yyyy] [name of copyright owner] - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. \ No newline at end of file diff --git a/solr/licenses/prometheus-metrics-shaded-protobuf-NOTICE.txt b/solr/licenses/prometheus-metrics-shaded-protobuf-NOTICE.txt deleted file mode 100644 index cbd3cd95bef..00000000000 --- a/solr/licenses/prometheus-metrics-shaded-protobuf-NOTICE.txt +++ /dev/null @@ -1,11 +0,0 @@ -Prometheus instrumentation library for JVM applications -Copyright 2012-2015 The Prometheus Authors - -This product includes software developed at -Boxever Ltd. (http://www.boxever.com/). - -This product includes software developed at -SoundCloud Ltd. (http://soundcloud.com/). - -This product includes software developed as part of the -Ocelli project by Netflix Inc. (https://github.com/Netflix/ocelli/). \ No newline at end of file diff --git a/versions.lock b/versions.lock index cc0232a65d8..ed23a8cb6a2 100644 --- a/versions.lock +++ b/versions.lock @@ -145,10 +145,8 @@ io.opentelemetry:opentelemetry-sdk-logs:1.35.0 (3 constraints: eb32b3b2) io.opentelemetry:opentelemetry-sdk-metrics:1.35.0 (3 constraints: eb32b3b2) io.opentelemetry:opentelemetry-sdk-trace:1.35.0 (3 constraints: eb32b3b2) io.perfmark:perfmark-api:0.26.0 (3 constraints: 21212b16) -io.prometheus:prometheus-metrics-config:1.1.0 (1 constraints: 3e164ed8) io.prometheus:prometheus-metrics-exposition-formats:1.1.0 (1 constraints: 0405f335) io.prometheus:prometheus-metrics-model:1.1.0 (2 constraints: 411b133b) -io.prometheus:prometheus-metrics-shaded-protobuf:1.1.0 (1 constraints: 3e164ed8) io.prometheus:simpleclient:0.16.0 (3 constraints: 9d257513) io.prometheus:simpleclient_common:0.16.0 (1 constraints: 1a1139c0) io.prometheus:simpleclient_httpserver:0.16.0 (1 constraints: 3905353b) From 5d399efdd12312dcaec580a6d443073f3014115d Mon Sep 17 00:00:00 2001 From: mbiscocho Date: Wed, 22 May 2024 15:25:20 -0400 Subject: [PATCH 17/32] Refactor based on review comments --- solr/core/build.gradle | 2 +- .../solr/handler/admin/MetricsHandler.java | 10 +- .../prometheus/PrometheusExporterInfo.java | 33 ++++++ .../SolrPrometheusCoreExporter.java | 12 +-- .../prometheus/SolrPrometheusExporter.java | 2 +- .../prometheus/core/SolrCoreCacheMetric.java | 10 +- .../core/SolrCoreHandlerMetric.java | 39 +++---- .../core/SolrCoreHighlighterMetric.java | 14 +-- .../prometheus/core/SolrCoreIndexMetric.java | 10 +- .../prometheus/core/SolrCoreMetric.java | 31 +++++- .../prometheus/core/SolrCoreNoOpMetric.java | 2 +- .../core/SolrCoreSearcherMetric.java | 22 ++-- .../prometheus/core/SolrCoreTlogMetric.java | 10 +- .../response/PrometheusResponseWriter.java | 100 ++++++++++++++++-- .../apache/solr/util/stats/MetricUtils.java | 69 ------------ .../handler/admin/MetricsHandlerTest.java | 6 +- .../solr/metrics/SolrCoreMetricTest.java | 81 ++++++++++++++ .../TestPrometheusResponseWriter.java | 12 +-- 18 files changed, 284 insertions(+), 181 deletions(-) create mode 100644 solr/core/src/java/org/apache/solr/metrics/prometheus/PrometheusExporterInfo.java create mode 100644 solr/core/src/test/org/apache/solr/metrics/SolrCoreMetricTest.java diff --git a/solr/core/build.gradle b/solr/core/build.gradle index 76cef0bd876..e6817672426 100644 --- a/solr/core/build.gradle +++ b/solr/core/build.gradle @@ -153,7 +153,7 @@ dependencies { implementation 'org.apache.logging.log4j:log4j-core' runtimeOnly 'org.apache.logging.log4j:log4j-slf4j2-impl' - // Prometheus client + // For the PrometheusResponseWriter implementation 'io.prometheus:prometheus-metrics-model:1.1.0' implementation('io.prometheus:prometheus-metrics-exposition-formats:1.1.0', { exclude group: "io.prometheus", module: "prometheus-metrics-shaded-protobuf" diff --git a/solr/core/src/java/org/apache/solr/handler/admin/MetricsHandler.java b/solr/core/src/java/org/apache/solr/handler/admin/MetricsHandler.java index f42bb20b642..a7328e2bbba 100644 --- a/solr/core/src/java/org/apache/solr/handler/admin/MetricsHandler.java +++ b/solr/core/src/java/org/apache/solr/handler/admin/MetricsHandler.java @@ -51,6 +51,7 @@ import org.apache.solr.metrics.SolrMetricManager; import org.apache.solr.request.SolrQueryRequest; import org.apache.solr.request.SolrRequestInfo; +import org.apache.solr.response.PrometheusResponseWriter; import org.apache.solr.response.SolrQueryResponse; import org.apache.solr.security.AuthorizationContext; import org.apache.solr.security.PermissionNameProvider; @@ -118,8 +119,7 @@ public void handleRequestBody(SolrQueryRequest req, SolrQueryResponse rsp) throw } } - private void handleRequest(SolrParams params, BiConsumer consumer) - throws Exception { + private void handleRequest(SolrParams params, BiConsumer consumer) { NamedList response; if (!enabled) { @@ -128,7 +128,7 @@ private void handleRequest(SolrParams params, BiConsumer consume } if (PROMETHEUS_METRICS_WT.equals(params.get(CommonParams.WT))) { - response = handlePrometheusRegistry(params); + response = handlePrometheusExport(params); consumer.accept("metrics", response); return; } @@ -179,7 +179,7 @@ private NamedList handleDropwizardRegistry(SolrParams params) { return response; } - private NamedList handlePrometheusRegistry(SolrParams params) { + private NamedList handlePrometheusExport(SolrParams params) { NamedList response = new SimpleOrderedMap<>(); MetricFilter mustMatchFilter = parseMustMatchFilter(params); Predicate propertyFilter = parsePropertyFilter(params); @@ -192,7 +192,7 @@ private NamedList handlePrometheusRegistry(SolrParams params) { MetricRegistry dropwizardRegistry = metricManager.registry(registryName); // Currently only export Solr Core registries if (registryName.startsWith("solr.core")) { - MetricUtils.toPrometheusRegistry( + PrometheusResponseWriter.toPrometheus( dropwizardRegistry, registryName, metricFilters, diff --git a/solr/core/src/java/org/apache/solr/metrics/prometheus/PrometheusExporterInfo.java b/solr/core/src/java/org/apache/solr/metrics/prometheus/PrometheusExporterInfo.java new file mode 100644 index 00000000000..ce00543dadd --- /dev/null +++ b/solr/core/src/java/org/apache/solr/metrics/prometheus/PrometheusExporterInfo.java @@ -0,0 +1,33 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.solr.metrics.prometheus; + +public interface PrometheusExporterInfo { + /** Category of prefix Solr Core dropwizard handler metric names */ + enum CoreCategory { + ADMIN, + QUERY, + UPDATE, + REPLICATION, + TLOG, + CACHE, + SEARCHER, + HIGHLIGHTER, + INDEX, + CORE + } +} diff --git a/solr/core/src/java/org/apache/solr/metrics/prometheus/SolrPrometheusCoreExporter.java b/solr/core/src/java/org/apache/solr/metrics/prometheus/SolrPrometheusCoreExporter.java index 56d928acacc..6c8b6b484b6 100644 --- a/solr/core/src/java/org/apache/solr/metrics/prometheus/SolrPrometheusCoreExporter.java +++ b/solr/core/src/java/org/apache/solr/metrics/prometheus/SolrPrometheusCoreExporter.java @@ -34,16 +34,6 @@ public class SolrPrometheusCoreExporter extends SolrPrometheusExporter { public final String coreName; public final boolean cloudMode; - public static final String ADMIN = "ADMIN"; - public static final String QUERY = "QUERY"; - public static final String UPDATE = "UPDATE"; - public static final String REPLICATION = "REPLICATION"; - public static final String TLOG = "TLOG"; - public static final String CACHE = "CACHE"; - public static final String SEARCHER = "SEARCHER"; - public static final String HIGHLIGHTER = "HIGHLIGHTER"; - public static final String INDEX = "INDEX"; - public static final String CORE = "CORE"; public SolrPrometheusCoreExporter(String coreName, boolean cloudMode) { super(); @@ -66,7 +56,7 @@ public void exportDropwizardMetric(Metric dropwizardMetric, String metricName) { private SolrCoreMetric categorizeCoreMetric(Metric dropwizardMetric, String metricName) { String metricCategory = metricName.split("\\.")[0]; - switch (metricCategory) { + switch (CoreCategory.valueOf(metricCategory)) { case ADMIN: case QUERY: case UPDATE: diff --git a/solr/core/src/java/org/apache/solr/metrics/prometheus/SolrPrometheusExporter.java b/solr/core/src/java/org/apache/solr/metrics/prometheus/SolrPrometheusExporter.java index 5b3844b5c1f..86992f76f55 100644 --- a/solr/core/src/java/org/apache/solr/metrics/prometheus/SolrPrometheusExporter.java +++ b/solr/core/src/java/org/apache/solr/metrics/prometheus/SolrPrometheusExporter.java @@ -35,7 +35,7 @@ * {@link com.codahale.metrics.Metric} to {@link MetricSnapshot} to be outputted for {@link * org.apache.solr.response.PrometheusResponseWriter} */ -public abstract class SolrPrometheusExporter { +public abstract class SolrPrometheusExporter implements PrometheusExporterInfo { protected final Map> metricCounters; protected final Map> metricGauges; diff --git a/solr/core/src/java/org/apache/solr/metrics/prometheus/core/SolrCoreCacheMetric.java b/solr/core/src/java/org/apache/solr/metrics/prometheus/core/SolrCoreCacheMetric.java index 36c96ffeedc..3c6fc78e659 100644 --- a/solr/core/src/java/org/apache/solr/metrics/prometheus/core/SolrCoreCacheMetric.java +++ b/solr/core/src/java/org/apache/solr/metrics/prometheus/core/SolrCoreCacheMetric.java @@ -18,8 +18,6 @@ import com.codahale.metrics.Gauge; import com.codahale.metrics.Metric; -import io.prometheus.metrics.model.snapshots.Labels; -import java.util.ArrayList; import org.apache.solr.metrics.prometheus.SolrPrometheusCoreExporter; /** Dropwizard metrics of name CACHE.* */ @@ -42,12 +40,10 @@ public SolrCoreMetric parseLabels() { } @Override - public void toPrometheus(SolrPrometheusCoreExporter solrPrometheusCoreRegistry) { + public void toPrometheus(SolrPrometheusCoreExporter solrPrometheusCoreExporter) { if (dropwizardMetric instanceof Gauge) { - solrPrometheusCoreRegistry.exportGauge( - CORE_CACHE_SEARCHER_METRICS, - (Gauge) dropwizardMetric, - Labels.of(new ArrayList<>(labels.keySet()), new ArrayList<>(labels.values()))); + solrPrometheusCoreExporter.exportGauge( + CORE_CACHE_SEARCHER_METRICS, (Gauge) dropwizardMetric, getLabels()); } } } diff --git a/solr/core/src/java/org/apache/solr/metrics/prometheus/core/SolrCoreHandlerMetric.java b/solr/core/src/java/org/apache/solr/metrics/prometheus/core/SolrCoreHandlerMetric.java index 2faa290dd6d..b972a567e95 100644 --- a/solr/core/src/java/org/apache/solr/metrics/prometheus/core/SolrCoreHandlerMetric.java +++ b/solr/core/src/java/org/apache/solr/metrics/prometheus/core/SolrCoreHandlerMetric.java @@ -21,8 +21,7 @@ import com.codahale.metrics.Meter; import com.codahale.metrics.Metric; import com.codahale.metrics.Timer; -import io.prometheus.metrics.model.snapshots.Labels; -import java.util.ArrayList; +import java.util.Map; import org.apache.solr.metrics.prometheus.SolrPrometheusCoreExporter; /** Dropwizard metrics of name ADMIN/QUERY/UPDATE/REPLICATION.* */ @@ -43,47 +42,35 @@ public SolrCoreMetric parseLabels() { String category = parsedMetric[0]; String handler = parsedMetric[1]; String type = parsedMetric[2]; - labels.put("category", category); - labels.put("type", type); - labels.put("handler", handler); + labels.putAll(Map.of("category", category, "type", type, "handler", handler)); return this; } @Override - public void toPrometheus(SolrPrometheusCoreExporter solrPrometheusCoreRegistry) { + public void toPrometheus(SolrPrometheusCoreExporter solrPrometheusCoreExporter) { if (dropwizardMetric instanceof Meter) { - solrPrometheusCoreRegistry.exportMeter( - CORE_REQUESTS_TOTAL, - (Meter) dropwizardMetric, - Labels.of(new ArrayList<>(labels.keySet()), new ArrayList<>(labels.values()))); + solrPrometheusCoreExporter.exportMeter( + CORE_REQUESTS_TOTAL, (Meter) dropwizardMetric, getLabels()); } else if (dropwizardMetric instanceof Counter) { if (metricName.endsWith("requests")) { - solrPrometheusCoreRegistry.exportCounter( - CORE_REQUESTS_TOTAL, - (Counter) dropwizardMetric, - Labels.of(new ArrayList<>(labels.keySet()), new ArrayList<>(labels.values()))); + solrPrometheusCoreExporter.exportCounter( + CORE_REQUESTS_TOTAL, (Counter) dropwizardMetric, getLabels()); } else if (metricName.endsWith("totalTime")) { // Do not need type label for total time labels.remove("type"); - solrPrometheusCoreRegistry.exportCounter( - CORE_REQUESTS_TOTAL_TIME, - (Counter) dropwizardMetric, - Labels.of(new ArrayList<>(labels.keySet()), new ArrayList<>(labels.values()))); + solrPrometheusCoreExporter.exportCounter( + CORE_REQUESTS_TOTAL_TIME, (Counter) dropwizardMetric, getLabels()); } } else if (dropwizardMetric instanceof Gauge) { if (!metricName.endsWith("handlerStart")) { - solrPrometheusCoreRegistry.exportGauge( - CORE_REQUESTS_UPDATE_HANDLER, - (Gauge) dropwizardMetric, - Labels.of(new ArrayList<>(labels.keySet()), new ArrayList<>(labels.values()))); + solrPrometheusCoreExporter.exportGauge( + CORE_REQUESTS_UPDATE_HANDLER, (Gauge) dropwizardMetric, getLabels()); } } else if (dropwizardMetric instanceof Timer) { // Do not need type label for request times labels.remove("type"); - solrPrometheusCoreRegistry.exportTimer( - CORE_REQUEST_TIMES, - (Timer) dropwizardMetric, - Labels.of(new ArrayList<>(labels.keySet()), new ArrayList<>(labels.values()))); + solrPrometheusCoreExporter.exportTimer( + CORE_REQUEST_TIMES, (Timer) dropwizardMetric, getLabels()); } } } diff --git a/solr/core/src/java/org/apache/solr/metrics/prometheus/core/SolrCoreHighlighterMetric.java b/solr/core/src/java/org/apache/solr/metrics/prometheus/core/SolrCoreHighlighterMetric.java index 95a7f8159b1..9f772de4421 100644 --- a/solr/core/src/java/org/apache/solr/metrics/prometheus/core/SolrCoreHighlighterMetric.java +++ b/solr/core/src/java/org/apache/solr/metrics/prometheus/core/SolrCoreHighlighterMetric.java @@ -18,8 +18,7 @@ import com.codahale.metrics.Counter; import com.codahale.metrics.Metric; -import io.prometheus.metrics.model.snapshots.Labels; -import java.util.ArrayList; +import java.util.Map; import org.apache.solr.metrics.prometheus.SolrPrometheusCoreExporter; /** Dropwizard metrics of name HIGHLIGHTER.* */ @@ -36,18 +35,15 @@ public SolrCoreMetric parseLabels() { String[] parsedMetric = metricName.split("\\."); String type = parsedMetric[1]; String item = parsedMetric[2]; - labels.put("type", type); - labels.put("item", item); + labels.putAll(Map.of("type", type, "item", item)); return this; } @Override - public void toPrometheus(SolrPrometheusCoreExporter solrPrometheusCoreRegistry) { + public void toPrometheus(SolrPrometheusCoreExporter solrPrometheusCoreExporter) { if (dropwizardMetric instanceof Counter) { - solrPrometheusCoreRegistry.exportCounter( - CORE_HIGHLIGHER_METRICS, - (Counter) dropwizardMetric, - Labels.of(new ArrayList<>(labels.keySet()), new ArrayList<>(labels.values()))); + solrPrometheusCoreExporter.exportCounter( + CORE_HIGHLIGHER_METRICS, (Counter) dropwizardMetric, getLabels()); } } } diff --git a/solr/core/src/java/org/apache/solr/metrics/prometheus/core/SolrCoreIndexMetric.java b/solr/core/src/java/org/apache/solr/metrics/prometheus/core/SolrCoreIndexMetric.java index e4584ad758e..18a5c4c9df9 100644 --- a/solr/core/src/java/org/apache/solr/metrics/prometheus/core/SolrCoreIndexMetric.java +++ b/solr/core/src/java/org/apache/solr/metrics/prometheus/core/SolrCoreIndexMetric.java @@ -18,8 +18,6 @@ import com.codahale.metrics.Gauge; import com.codahale.metrics.Metric; -import io.prometheus.metrics.model.snapshots.Labels; -import java.util.ArrayList; import org.apache.solr.metrics.prometheus.SolrPrometheusCoreExporter; /** Dropwizard metrics of name INDEX.* */ @@ -37,13 +35,11 @@ public SolrCoreMetric parseLabels() { } @Override - public void toPrometheus(SolrPrometheusCoreExporter solrPrometheusCoreRegistry) { + public void toPrometheus(SolrPrometheusCoreExporter solrPrometheusCoreExporter) { if (dropwizardMetric instanceof Gauge) { if (metricName.endsWith("sizeInBytes")) { - solrPrometheusCoreRegistry.exportGauge( - CORE_INDEX_METRICS, - (Gauge) dropwizardMetric, - Labels.of(new ArrayList<>(labels.keySet()), new ArrayList<>(labels.values()))); + solrPrometheusCoreExporter.exportGauge( + CORE_INDEX_METRICS, (Gauge) dropwizardMetric, getLabels()); } } } diff --git a/solr/core/src/java/org/apache/solr/metrics/prometheus/core/SolrCoreMetric.java b/solr/core/src/java/org/apache/solr/metrics/prometheus/core/SolrCoreMetric.java index 748c053f205..4e1b59d549f 100644 --- a/solr/core/src/java/org/apache/solr/metrics/prometheus/core/SolrCoreMetric.java +++ b/solr/core/src/java/org/apache/solr/metrics/prometheus/core/SolrCoreMetric.java @@ -17,8 +17,13 @@ package org.apache.solr.metrics.prometheus.core; import com.codahale.metrics.Metric; +import io.prometheus.metrics.model.snapshots.Labels; +import java.util.ArrayList; import java.util.HashMap; import java.util.Map; +import java.util.regex.Matcher; +import java.util.regex.Pattern; +import org.apache.solr.common.SolrException; import org.apache.solr.metrics.prometheus.SolrPrometheusCoreExporter; /** @@ -41,14 +46,30 @@ public SolrCoreMetric( this.metricName = metricName; labels.put("core", coreName); if (cloudMode) { - String[] coreNameParsed = coreName.split("_"); - labels.put("collection", coreNameParsed[1]); - labels.put("shard", coreNameParsed[2]); - labels.put("replica", coreNameParsed[3] + "_" + coreNameParsed[4]); + appendCloudModeLabels(); } } + public Labels getLabels() { + return Labels.of(new ArrayList<>(labels.keySet()), new ArrayList<>(labels.values())); + } + public abstract SolrCoreMetric parseLabels(); - public abstract void toPrometheus(SolrPrometheusCoreExporter solrPrometheusCoreRegistry); + public abstract void toPrometheus(SolrPrometheusCoreExporter solrPrometheusCoreExporter); + + private void appendCloudModeLabels() { + Pattern p = Pattern.compile("^core_(.*)_(shard[0-9]+)_(replica_n[0-9]+)"); + Matcher m = p.matcher(coreName); + if (m.find()) { + String collectionName = m.group(1); + String shard = m.group(2); + String replica = m.group(3); + labels.putAll(Map.of("collection", collectionName, "shard", shard, "replica", replica)); + } else { + throw new SolrException( + SolrException.ErrorCode.SERVER_ERROR, + "Core name does not match pattern for parsing " + coreName); + } + } } diff --git a/solr/core/src/java/org/apache/solr/metrics/prometheus/core/SolrCoreNoOpMetric.java b/solr/core/src/java/org/apache/solr/metrics/prometheus/core/SolrCoreNoOpMetric.java index 3e0ab963d28..47c980e03cb 100644 --- a/solr/core/src/java/org/apache/solr/metrics/prometheus/core/SolrCoreNoOpMetric.java +++ b/solr/core/src/java/org/apache/solr/metrics/prometheus/core/SolrCoreNoOpMetric.java @@ -32,5 +32,5 @@ public SolrCoreMetric parseLabels() { } @Override - public void toPrometheus(SolrPrometheusCoreExporter solrPrometheusCoreRegistry) {} + public void toPrometheus(SolrPrometheusCoreExporter solrPrometheusCoreExporter) {} } diff --git a/solr/core/src/java/org/apache/solr/metrics/prometheus/core/SolrCoreSearcherMetric.java b/solr/core/src/java/org/apache/solr/metrics/prometheus/core/SolrCoreSearcherMetric.java index f653128aa00..a8be62edf53 100644 --- a/solr/core/src/java/org/apache/solr/metrics/prometheus/core/SolrCoreSearcherMetric.java +++ b/solr/core/src/java/org/apache/solr/metrics/prometheus/core/SolrCoreSearcherMetric.java @@ -22,8 +22,6 @@ import com.codahale.metrics.Gauge; import com.codahale.metrics.Metric; import com.codahale.metrics.Timer; -import io.prometheus.metrics.model.snapshots.Labels; -import java.util.ArrayList; import org.apache.solr.metrics.prometheus.SolrPrometheusCoreExporter; /** Dropwizard metrics of name SEARCHER.* */ @@ -47,24 +45,18 @@ public SolrCoreMetric parseLabels() { } @Override - public void toPrometheus(SolrPrometheusCoreExporter solrPrometheusCoreRegistry) { + public void toPrometheus(SolrPrometheusCoreExporter solrPrometheusCoreExporter) { if (dropwizardMetric instanceof Gauge) { if (metricName.endsWith("liveDocsCache")) { - solrPrometheusCoreRegistry.exportGauge( - CORE_CACHE_SEARCHER_METRICS, - (Gauge) dropwizardMetric, - Labels.of(new ArrayList<>(labels.keySet()), new ArrayList<>(labels.values()))); + solrPrometheusCoreExporter.exportGauge( + CORE_CACHE_SEARCHER_METRICS, (Gauge) dropwizardMetric, getLabels()); } else { - solrPrometheusCoreRegistry.exportGauge( - CORE_SEARCHER_METRICS, - (Gauge) dropwizardMetric, - Labels.of(new ArrayList<>(labels.keySet()), new ArrayList<>(labels.values()))); + solrPrometheusCoreExporter.exportGauge( + CORE_SEARCHER_METRICS, (Gauge) dropwizardMetric, getLabels()); } } else if (dropwizardMetric instanceof Timer) { - solrPrometheusCoreRegistry.exportTimer( - CORE_SEARCHER_TIMES, - (Timer) dropwizardMetric, - Labels.of(new ArrayList<>(labels.keySet()), new ArrayList<>(labels.values()))); + solrPrometheusCoreExporter.exportTimer( + CORE_SEARCHER_TIMES, (Timer) dropwizardMetric, getLabels()); } } } diff --git a/solr/core/src/java/org/apache/solr/metrics/prometheus/core/SolrCoreTlogMetric.java b/solr/core/src/java/org/apache/solr/metrics/prometheus/core/SolrCoreTlogMetric.java index 2c49e612292..73b9f18c470 100644 --- a/solr/core/src/java/org/apache/solr/metrics/prometheus/core/SolrCoreTlogMetric.java +++ b/solr/core/src/java/org/apache/solr/metrics/prometheus/core/SolrCoreTlogMetric.java @@ -18,8 +18,6 @@ import com.codahale.metrics.Meter; import com.codahale.metrics.Metric; -import io.prometheus.metrics.model.snapshots.Labels; -import java.util.ArrayList; import org.apache.solr.metrics.prometheus.SolrPrometheusCoreExporter; /** Dropwizard metrics of name TLOG.* */ @@ -42,12 +40,10 @@ public SolrCoreMetric parseLabels() { } @Override - public void toPrometheus(SolrPrometheusCoreExporter solrPrometheusCoreRegistry) { + public void toPrometheus(SolrPrometheusCoreExporter solrPrometheusCoreExporter) { if (dropwizardMetric instanceof Meter) { - solrPrometheusCoreRegistry.exportMeter( - CORE_TLOG_METRICS, - (Meter) dropwizardMetric, - Labels.of(new ArrayList<>(labels.keySet()), new ArrayList<>(labels.values()))); + solrPrometheusCoreExporter.exportMeter( + CORE_TLOG_METRICS, (Meter) dropwizardMetric, getLabels()); } } } diff --git a/solr/core/src/java/org/apache/solr/response/PrometheusResponseWriter.java b/solr/core/src/java/org/apache/solr/response/PrometheusResponseWriter.java index aae7bb1b29e..4cca2160fe4 100644 --- a/solr/core/src/java/org/apache/solr/response/PrometheusResponseWriter.java +++ b/solr/core/src/java/org/apache/solr/response/PrometheusResponseWriter.java @@ -16,31 +16,115 @@ */ package org.apache.solr.response; +import com.codahale.metrics.Histogram; +import com.codahale.metrics.Metric; +import com.codahale.metrics.MetricFilter; +import com.codahale.metrics.MetricRegistry; +import com.codahale.metrics.Timer; import io.prometheus.metrics.expositionformats.PrometheusTextFormatWriter; import java.io.IOException; import java.io.OutputStream; +import java.lang.invoke.MethodHandles; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Iterator; +import java.util.List; import java.util.Map; +import java.util.function.Consumer; +import java.util.function.Predicate; +import java.util.stream.Collectors; import org.apache.solr.common.util.NamedList; +import org.apache.solr.metrics.AggregateMetric; import org.apache.solr.metrics.prometheus.SolrPrometheusCoreExporter; import org.apache.solr.request.SolrQueryRequest; +import org.apache.solr.util.stats.MetricUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +/** + * Response writer for Prometheus metrics. This is used only by the {@link + * org.apache.solr.handler.admin.MetricsHandler} + */ @SuppressWarnings(value = "unchecked") public class PrometheusResponseWriter extends RawResponseWriter { + private static final Logger log = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass()); + @Override public void write(OutputStream out, SolrQueryRequest request, SolrQueryResponse response) throws IOException { NamedList prometheusRegistries = (NamedList) response.getValues().get("metrics"); - Map registryMap = prometheusRegistries.asShallowMap(); - PrometheusTextFormatWriter prometheusTextFormatWriter = new PrometheusTextFormatWriter(false); - registryMap.forEach( - (name, registry) -> { + Iterator> it = prometheusRegistries.iterator(); + var prometheusTextFormatWriter = new PrometheusTextFormatWriter(false); + while (it.hasNext()) { + Map.Entry entry = it.next(); + SolrPrometheusCoreExporter prometheusExporter = (SolrPrometheusCoreExporter) entry.getValue(); + prometheusTextFormatWriter.write(out, prometheusExporter.collect()); + } + } + + /** + * Provides a representation of the given Dropwizard metric registry as {@link + * SolrPrometheusCoreExporter}-s. Only those metrics are converted which match at least one of the + * given MetricFilter instances. + * + * @param registry the {@link MetricRegistry} to be converted + * @param shouldMatchFilters a list of {@link MetricFilter} instances. A metric must match any + * one of the filters from this list to be included in the output + * @param mustMatchFilter a {@link MetricFilter}. A metric must match this filter to be + * included in the output. + * @param propertyFilter limit what properties of a metric are returned + * @param skipHistograms discard any {@link Histogram}-s and histogram parts of {@link Timer}-s. + * @param skipAggregateValues discard internal values of {@link AggregateMetric}-s. + * @param compact use compact representation for counters and gauges. + * @param consumer consumer that accepts produced {@link SolrPrometheusCoreExporter}-s + */ + public static void toPrometheus( + MetricRegistry registry, + String registryName, + List shouldMatchFilters, + MetricFilter mustMatchFilter, + Predicate propertyFilter, + boolean skipHistograms, + boolean skipAggregateValues, + boolean compact, + Consumer consumer) { + String coreName; + boolean cloudMode = false; + Map dropwizardMetrics = registry.getMetrics(); + String[] rawParsedRegistry = registryName.split("\\."); + List parsedRegistry = new ArrayList<>(Arrays.asList(rawParsedRegistry)); + + if (parsedRegistry.size() == 3) { + coreName = parsedRegistry.get(2); + } else if (parsedRegistry.size() == 5) { + coreName = parsedRegistry.stream().skip(1).collect(Collectors.joining("_")); + cloudMode = true; + } else { + coreName = registryName; + } + + var solrPrometheusCoreExporter = new SolrPrometheusCoreExporter(coreName, cloudMode); + + MetricUtils.toMaps( + registry, + shouldMatchFilters, + mustMatchFilter, + propertyFilter, + skipHistograms, + skipAggregateValues, + compact, + false, + (metricName, metric) -> { try { - SolrPrometheusCoreExporter prometheusRegistry = (SolrPrometheusCoreExporter) registry; - prometheusTextFormatWriter.write(out, prometheusRegistry.collect()); - } catch (IOException e) { - throw new RuntimeException(e); + Metric dropwizardMetric = dropwizardMetrics.get(metricName); + solrPrometheusCoreExporter.exportDropwizardMetric(dropwizardMetric, metricName); + } catch (Exception e) { + // Do not fail entirely for metrics exporting. Log and try to export next metric + log.warn("Error occurred exporting Dropwizard Metric to Prometheus", e); } }); + + consumer.accept(solrPrometheusCoreExporter); } } diff --git a/solr/core/src/java/org/apache/solr/util/stats/MetricUtils.java b/solr/core/src/java/org/apache/solr/util/stats/MetricUtils.java index 1a7474d8bdb..1e14ae452fa 100644 --- a/solr/core/src/java/org/apache/solr/util/stats/MetricUtils.java +++ b/solr/core/src/java/org/apache/solr/util/stats/MetricUtils.java @@ -35,8 +35,6 @@ import java.lang.management.OperatingSystemMXBean; import java.lang.management.PlatformManagedObject; import java.lang.reflect.InvocationTargetException; -import java.util.ArrayList; -import java.util.Arrays; import java.util.Collection; import java.util.HashMap; import java.util.List; @@ -47,7 +45,6 @@ import java.util.function.BiConsumer; import java.util.function.Consumer; import java.util.function.Predicate; -import java.util.stream.Collectors; import org.apache.solr.common.ConditionalKeyMapWriter; import org.apache.solr.common.IteratorWriter; import org.apache.solr.common.MapWriter; @@ -56,7 +53,6 @@ import org.apache.solr.core.SolrInfoBean; import org.apache.solr.metrics.AggregateMetric; import org.apache.solr.metrics.SolrMetricManager; -import org.apache.solr.metrics.prometheus.SolrPrometheusCoreExporter; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -169,71 +165,6 @@ public static void toSolrInputDocuments( }); } - /** - * Provides a representation of the given Dropwizard metric registry as {@link - * SolrPrometheusCoreExporter}-s. Only those metrics are converted which match at least one of the - * given MetricFilter instances. - * - * @param registry the {@link MetricRegistry} to be converted - * @param shouldMatchFilters a list of {@link MetricFilter} instances. A metric must match any - * one of the filters from this list to be included in the output - * @param mustMatchFilter a {@link MetricFilter}. A metric must match this filter to be - * included in the output. - * @param propertyFilter limit what properties of a metric are returned - * @param skipHistograms discard any {@link Histogram}-s and histogram parts of {@link Timer}-s. - * @param skipAggregateValues discard internal values of {@link AggregateMetric}-s. - * @param compact use compact representation for counters and gauges. - * @param consumer consumer that accepts produced {@link SolrPrometheusCoreExporter}-s - */ - public static void toPrometheusRegistry( - MetricRegistry registry, - String registryName, - List shouldMatchFilters, - MetricFilter mustMatchFilter, - Predicate propertyFilter, - boolean skipHistograms, - boolean skipAggregateValues, - boolean compact, - Consumer consumer) { - String coreName; - boolean cloudMode = false; - Map dropwizardMetrics = registry.getMetrics(); - String[] rawParsedRegistry = registryName.split("\\."); - List parsedRegistry = new ArrayList<>(Arrays.asList(rawParsedRegistry)); - - if (parsedRegistry.size() == 3) { - coreName = parsedRegistry.get(2); - } else if (parsedRegistry.size() == 5) { - coreName = parsedRegistry.stream().skip(1).collect(Collectors.joining("_")); - cloudMode = true; - } else { - coreName = registryName; - } - - SolrPrometheusCoreExporter solrPrometheusCoreExporter = - new SolrPrometheusCoreExporter(coreName, cloudMode); - - toMaps( - registry, - shouldMatchFilters, - mustMatchFilter, - propertyFilter, - skipHistograms, - skipAggregateValues, - compact, - false, - (metricName, metric) -> { - try { - Metric dropwizardMetric = dropwizardMetrics.get(metricName); - solrPrometheusCoreExporter.exportDropwizardMetric(dropwizardMetric, metricName); - } catch (Exception e) { - // Do not fail entirely for metrics exporting. Log and try to export next metric - log.warn("Error occurred exporting Dropwizard Metric to Prometheus", e); - } - }); - consumer.accept(solrPrometheusCoreExporter); - } - /** * Fill in a SolrInputDocument with values from a converted metric, recursively. * diff --git a/solr/core/src/test/org/apache/solr/handler/admin/MetricsHandlerTest.java b/solr/core/src/test/org/apache/solr/handler/admin/MetricsHandlerTest.java index 458aadf28aa..44ab23a7542 100644 --- a/solr/core/src/test/org/apache/solr/handler/admin/MetricsHandlerTest.java +++ b/solr/core/src/test/org/apache/solr/handler/admin/MetricsHandlerTest.java @@ -703,9 +703,9 @@ public void testPrometheusMetrics() throws Exception { NamedList values = resp.getValues(); assertNotNull(values.get("metrics")); values = (NamedList) values.get("metrics"); - SolrPrometheusExporter registry = (SolrPrometheusExporter) values.get("solr.core.collection1"); - assertNotNull(registry); - MetricSnapshots actualSnapshots = registry.collect(); + SolrPrometheusExporter exporter = (SolrPrometheusExporter) values.get("solr.core.collection1"); + assertNotNull(exporter); + MetricSnapshots actualSnapshots = exporter.collect(); assertNotNull(actualSnapshots); Optional actualSnapshot = diff --git a/solr/core/src/test/org/apache/solr/metrics/SolrCoreMetricTest.java b/solr/core/src/test/org/apache/solr/metrics/SolrCoreMetricTest.java new file mode 100644 index 00000000000..dbea7a21d0c --- /dev/null +++ b/solr/core/src/test/org/apache/solr/metrics/SolrCoreMetricTest.java @@ -0,0 +1,81 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.solr.metrics; + +import com.codahale.metrics.Metric; +import io.prometheus.metrics.model.snapshots.Labels; +import org.apache.solr.SolrTestCaseJ4; +import org.apache.solr.metrics.prometheus.SolrPrometheusCoreExporter; +import org.apache.solr.metrics.prometheus.core.SolrCoreMetric; +import org.junit.Test; + +public class SolrCoreMetricTest extends SolrTestCaseJ4 { + + @Test + public void testStandaloneDefaultLabels() throws InterruptedException { + String expectedCoreName = "test_core"; + String expectedMetricName = "test_core_metric"; + Labels expectedLabels = Labels.of("core", expectedCoreName); + TestSolrCoreMetric testSolrCoreMetric = + new TestSolrCoreMetric(null, expectedCoreName, expectedMetricName, false); + + assertEquals(expectedCoreName, testSolrCoreMetric.coreName); + assertEquals(expectedMetricName, testSolrCoreMetric.metricName); + assertEquals(expectedLabels, testSolrCoreMetric.getLabels()); + } + + @Test + public void testCloudDefaultLabels() throws InterruptedException { + String expectedCoreName = "core_test_core_shard1_replica_n1"; + String expectedMetricName = "test_core_metric"; + String expectedCollectionName = "test_core"; + String expectedShardName = "shard1"; + String expectedReplicaName = "replica_n1"; + + Labels expectedLabels = + Labels.of( + "core", + expectedCoreName, + "collection", + expectedCollectionName, + "shard", + expectedShardName, + "replica", + expectedReplicaName); + TestSolrCoreMetric testSolrCoreMetric = + new TestSolrCoreMetric(null, expectedCoreName, expectedMetricName, true); + + assertEquals(expectedCoreName, testSolrCoreMetric.coreName); + assertEquals(expectedMetricName, testSolrCoreMetric.metricName); + assertEquals(expectedLabels, testSolrCoreMetric.getLabels()); + } + + static class TestSolrCoreMetric extends SolrCoreMetric { + public TestSolrCoreMetric( + Metric dropwizardMetric, String coreName, String metricName, boolean cloudMode) { + super(dropwizardMetric, coreName, metricName, cloudMode); + } + + @Override + public SolrCoreMetric parseLabels() { + return null; + } + + @Override + public void toPrometheus(SolrPrometheusCoreExporter solrPrometheusCoreExporter) {} + } +} diff --git a/solr/core/src/test/org/apache/solr/response/TestPrometheusResponseWriter.java b/solr/core/src/test/org/apache/solr/response/TestPrometheusResponseWriter.java index b02dada6098..26b3a6d356f 100644 --- a/solr/core/src/test/org/apache/solr/response/TestPrometheusResponseWriter.java +++ b/solr/core/src/test/org/apache/solr/response/TestPrometheusResponseWriter.java @@ -47,14 +47,14 @@ public void testPrometheusOutput() throws IOException { ByteArrayOutputStream byteOut = new ByteArrayOutputStream(); Labels expectedLabels = Labels.of("test", "test-value"); - SolrPrometheusCoreExporter registry = new SolrPrometheusCoreExporter("collection1", false); + SolrPrometheusCoreExporter exporter = new SolrPrometheusCoreExporter("collection1", false); CounterSnapshot.CounterDataPointSnapshot counterDatapoint = - registry.createCounterDatapoint(1.234, expectedLabels); + exporter.createCounterDatapoint(1.234, expectedLabels); GaugeSnapshot.GaugeDataPointSnapshot gaugeDataPoint = - registry.createGaugeDatapoint(9.876, expectedLabels); - registry.collectCounterDatapoint("test_counter_metric_name", counterDatapoint); - registry.collectGaugeDatapoint("test_gauge_metric_name", gaugeDataPoint); - registries.add("solr.core.collection1", registry); + exporter.createGaugeDatapoint(9.876, expectedLabels); + exporter.collectCounterDatapoint("test_counter_metric_name", counterDatapoint); + exporter.collectGaugeDatapoint("test_gauge_metric_name", gaugeDataPoint); + registries.add("solr.core.collection1", exporter); rsp.add("metrics", registries); w.write(byteOut, req, rsp); From 58280e55bb6676203fbcae9df0776ddd3c5d7741 Mon Sep 17 00:00:00 2001 From: mbiscocho Date: Thu, 23 May 2024 15:43:56 -0400 Subject: [PATCH 18/32] 2nd round refactor from review comments --- ...o.java => PrometheusCoreExporterInfo.java} | 7 +++- .../SolrPrometheusCoreExporter.java | 33 ++++++------------- .../prometheus/SolrPrometheusExporter.java | 2 +- .../prometheus/core/SolrCoreCacheMetric.java | 8 ++--- .../core/SolrCoreHandlerMetric.java | 24 +++++--------- .../core/SolrCoreHighlighterMetric.java | 11 +++---- .../prometheus/core/SolrCoreIndexMetric.java | 5 ++- .../prometheus/core/SolrCoreMetric.java | 15 ++++----- .../prometheus/core/SolrCoreNoOpMetric.java | 2 +- .../core/SolrCoreSearcherMetric.java | 14 +++----- .../prometheus/core/SolrCoreTlogMetric.java | 8 ++--- .../response/PrometheusResponseWriter.java | 8 ++--- .../solr/metrics/SolrCoreMetricTest.java | 2 +- 13 files changed, 56 insertions(+), 83 deletions(-) rename solr/core/src/java/org/apache/solr/metrics/prometheus/{PrometheusExporterInfo.java => PrometheusCoreExporterInfo.java} (80%) diff --git a/solr/core/src/java/org/apache/solr/metrics/prometheus/PrometheusExporterInfo.java b/solr/core/src/java/org/apache/solr/metrics/prometheus/PrometheusCoreExporterInfo.java similarity index 80% rename from solr/core/src/java/org/apache/solr/metrics/prometheus/PrometheusExporterInfo.java rename to solr/core/src/java/org/apache/solr/metrics/prometheus/PrometheusCoreExporterInfo.java index ce00543dadd..2481bfda4c3 100644 --- a/solr/core/src/java/org/apache/solr/metrics/prometheus/PrometheusExporterInfo.java +++ b/solr/core/src/java/org/apache/solr/metrics/prometheus/PrometheusCoreExporterInfo.java @@ -16,7 +16,9 @@ */ package org.apache.solr.metrics.prometheus; -public interface PrometheusExporterInfo { +import java.util.regex.Pattern; + +public interface PrometheusCoreExporterInfo { /** Category of prefix Solr Core dropwizard handler metric names */ enum CoreCategory { ADMIN, @@ -30,4 +32,7 @@ enum CoreCategory { INDEX, CORE } + + String PROMETHEUS_CLOUD_CORE_REGEX = "^core_(.*)_(shard[0-9]+)_(replica_n[0-9]+)$"; + Pattern PROMETHEUS_CLOUD_CORE_PATTERN = Pattern.compile(PROMETHEUS_CLOUD_CORE_REGEX); } diff --git a/solr/core/src/java/org/apache/solr/metrics/prometheus/SolrPrometheusCoreExporter.java b/solr/core/src/java/org/apache/solr/metrics/prometheus/SolrPrometheusCoreExporter.java index 6c8b6b484b6..507743a66d9 100644 --- a/solr/core/src/java/org/apache/solr/metrics/prometheus/SolrPrometheusCoreExporter.java +++ b/solr/core/src/java/org/apache/solr/metrics/prometheus/SolrPrometheusCoreExporter.java @@ -31,7 +31,8 @@ * This class maintains a {@link io.prometheus.metrics.model.snapshots.MetricSnapshot}s exported * from solr.core {@link com.codahale.metrics.MetricRegistry} */ -public class SolrPrometheusCoreExporter extends SolrPrometheusExporter { +public class SolrPrometheusCoreExporter extends SolrPrometheusExporter + implements PrometheusCoreExporterInfo { public final String coreName; public final boolean cloudMode; @@ -55,40 +56,26 @@ public void exportDropwizardMetric(Metric dropwizardMetric, String metricName) { } private SolrCoreMetric categorizeCoreMetric(Metric dropwizardMetric, String metricName) { - String metricCategory = metricName.split("\\.")[0]; + String metricCategory = metricName.split("\\.", 2)[0]; switch (CoreCategory.valueOf(metricCategory)) { case ADMIN: case QUERY: case UPDATE: case REPLICATION: - { - return new SolrCoreHandlerMetric(dropwizardMetric, coreName, metricName, cloudMode); - } + return new SolrCoreHandlerMetric(dropwizardMetric, coreName, metricName, cloudMode); case TLOG: - { - return new SolrCoreTlogMetric(dropwizardMetric, coreName, metricName, cloudMode); - } + return new SolrCoreTlogMetric(dropwizardMetric, coreName, metricName, cloudMode); case CACHE: - { - return new SolrCoreCacheMetric(dropwizardMetric, coreName, metricName, cloudMode); - } + return new SolrCoreCacheMetric(dropwizardMetric, coreName, metricName, cloudMode); case SEARCHER: - { - return new SolrCoreSearcherMetric(dropwizardMetric, coreName, metricName, cloudMode); - } + return new SolrCoreSearcherMetric(dropwizardMetric, coreName, metricName, cloudMode); case HIGHLIGHTER: - { - return new SolrCoreHighlighterMetric(dropwizardMetric, coreName, metricName, cloudMode); - } + return new SolrCoreHighlighterMetric(dropwizardMetric, coreName, metricName, cloudMode); case INDEX: - { - return new SolrCoreIndexMetric(dropwizardMetric, coreName, metricName, cloudMode); - } + return new SolrCoreIndexMetric(dropwizardMetric, coreName, metricName, cloudMode); case CORE: default: - { - return new SolrCoreNoOpMetric(dropwizardMetric, coreName, metricName, cloudMode); - } + return new SolrCoreNoOpMetric(dropwizardMetric, coreName, metricName, cloudMode); } } } diff --git a/solr/core/src/java/org/apache/solr/metrics/prometheus/SolrPrometheusExporter.java b/solr/core/src/java/org/apache/solr/metrics/prometheus/SolrPrometheusExporter.java index 86992f76f55..5b3844b5c1f 100644 --- a/solr/core/src/java/org/apache/solr/metrics/prometheus/SolrPrometheusExporter.java +++ b/solr/core/src/java/org/apache/solr/metrics/prometheus/SolrPrometheusExporter.java @@ -35,7 +35,7 @@ * {@link com.codahale.metrics.Metric} to {@link MetricSnapshot} to be outputted for {@link * org.apache.solr.response.PrometheusResponseWriter} */ -public abstract class SolrPrometheusExporter implements PrometheusExporterInfo { +public abstract class SolrPrometheusExporter { protected final Map> metricCounters; protected final Map> metricGauges; diff --git a/solr/core/src/java/org/apache/solr/metrics/prometheus/core/SolrCoreCacheMetric.java b/solr/core/src/java/org/apache/solr/metrics/prometheus/core/SolrCoreCacheMetric.java index 3c6fc78e659..ced9ecfba18 100644 --- a/solr/core/src/java/org/apache/solr/metrics/prometheus/core/SolrCoreCacheMetric.java +++ b/solr/core/src/java/org/apache/solr/metrics/prometheus/core/SolrCoreCacheMetric.java @@ -33,17 +33,15 @@ public SolrCoreCacheMetric( public SolrCoreMetric parseLabels() { String[] parsedMetric = metricName.split("\\."); if (dropwizardMetric instanceof Gauge) { - String cacheType = parsedMetric[2]; - labels.put("cacheType", cacheType); + labels.put("cacheType", parsedMetric[2]); } return this; } @Override - public void toPrometheus(SolrPrometheusCoreExporter solrPrometheusCoreExporter) { + public void toPrometheus(SolrPrometheusCoreExporter exporter) { if (dropwizardMetric instanceof Gauge) { - solrPrometheusCoreExporter.exportGauge( - CORE_CACHE_SEARCHER_METRICS, (Gauge) dropwizardMetric, getLabels()); + exporter.exportGauge(CORE_CACHE_SEARCHER_METRICS, (Gauge) dropwizardMetric, getLabels()); } } } diff --git a/solr/core/src/java/org/apache/solr/metrics/prometheus/core/SolrCoreHandlerMetric.java b/solr/core/src/java/org/apache/solr/metrics/prometheus/core/SolrCoreHandlerMetric.java index b972a567e95..d6fa97678e8 100644 --- a/solr/core/src/java/org/apache/solr/metrics/prometheus/core/SolrCoreHandlerMetric.java +++ b/solr/core/src/java/org/apache/solr/metrics/prometheus/core/SolrCoreHandlerMetric.java @@ -21,7 +21,6 @@ import com.codahale.metrics.Meter; import com.codahale.metrics.Metric; import com.codahale.metrics.Timer; -import java.util.Map; import org.apache.solr.metrics.prometheus.SolrPrometheusCoreExporter; /** Dropwizard metrics of name ADMIN/QUERY/UPDATE/REPLICATION.* */ @@ -39,38 +38,33 @@ public SolrCoreHandlerMetric( @Override public SolrCoreMetric parseLabels() { String[] parsedMetric = metricName.split("\\."); - String category = parsedMetric[0]; - String handler = parsedMetric[1]; - String type = parsedMetric[2]; - labels.putAll(Map.of("category", category, "type", type, "handler", handler)); + labels.put("category", parsedMetric[0]); + labels.put("handler", parsedMetric[1]); + labels.put("type", parsedMetric[2]); return this; } @Override - public void toPrometheus(SolrPrometheusCoreExporter solrPrometheusCoreExporter) { + public void toPrometheus(SolrPrometheusCoreExporter exporter) { if (dropwizardMetric instanceof Meter) { - solrPrometheusCoreExporter.exportMeter( - CORE_REQUESTS_TOTAL, (Meter) dropwizardMetric, getLabels()); + exporter.exportMeter(CORE_REQUESTS_TOTAL, (Meter) dropwizardMetric, getLabels()); } else if (dropwizardMetric instanceof Counter) { if (metricName.endsWith("requests")) { - solrPrometheusCoreExporter.exportCounter( - CORE_REQUESTS_TOTAL, (Counter) dropwizardMetric, getLabels()); + exporter.exportCounter(CORE_REQUESTS_TOTAL, (Counter) dropwizardMetric, getLabels()); } else if (metricName.endsWith("totalTime")) { // Do not need type label for total time labels.remove("type"); - solrPrometheusCoreExporter.exportCounter( - CORE_REQUESTS_TOTAL_TIME, (Counter) dropwizardMetric, getLabels()); + exporter.exportCounter(CORE_REQUESTS_TOTAL_TIME, (Counter) dropwizardMetric, getLabels()); } } else if (dropwizardMetric instanceof Gauge) { if (!metricName.endsWith("handlerStart")) { - solrPrometheusCoreExporter.exportGauge( + exporter.exportGauge( CORE_REQUESTS_UPDATE_HANDLER, (Gauge) dropwizardMetric, getLabels()); } } else if (dropwizardMetric instanceof Timer) { // Do not need type label for request times labels.remove("type"); - solrPrometheusCoreExporter.exportTimer( - CORE_REQUEST_TIMES, (Timer) dropwizardMetric, getLabels()); + exporter.exportTimer(CORE_REQUEST_TIMES, (Timer) dropwizardMetric, getLabels()); } } } diff --git a/solr/core/src/java/org/apache/solr/metrics/prometheus/core/SolrCoreHighlighterMetric.java b/solr/core/src/java/org/apache/solr/metrics/prometheus/core/SolrCoreHighlighterMetric.java index 9f772de4421..b5ab3a99332 100644 --- a/solr/core/src/java/org/apache/solr/metrics/prometheus/core/SolrCoreHighlighterMetric.java +++ b/solr/core/src/java/org/apache/solr/metrics/prometheus/core/SolrCoreHighlighterMetric.java @@ -18,7 +18,6 @@ import com.codahale.metrics.Counter; import com.codahale.metrics.Metric; -import java.util.Map; import org.apache.solr.metrics.prometheus.SolrPrometheusCoreExporter; /** Dropwizard metrics of name HIGHLIGHTER.* */ @@ -33,17 +32,15 @@ public SolrCoreHighlighterMetric( @Override public SolrCoreMetric parseLabels() { String[] parsedMetric = metricName.split("\\."); - String type = parsedMetric[1]; - String item = parsedMetric[2]; - labels.putAll(Map.of("type", type, "item", item)); + labels.put("type", parsedMetric[1]); + labels.put("item", parsedMetric[2]); return this; } @Override - public void toPrometheus(SolrPrometheusCoreExporter solrPrometheusCoreExporter) { + public void toPrometheus(SolrPrometheusCoreExporter exporter) { if (dropwizardMetric instanceof Counter) { - solrPrometheusCoreExporter.exportCounter( - CORE_HIGHLIGHER_METRICS, (Counter) dropwizardMetric, getLabels()); + exporter.exportCounter(CORE_HIGHLIGHER_METRICS, (Counter) dropwizardMetric, getLabels()); } } } diff --git a/solr/core/src/java/org/apache/solr/metrics/prometheus/core/SolrCoreIndexMetric.java b/solr/core/src/java/org/apache/solr/metrics/prometheus/core/SolrCoreIndexMetric.java index 18a5c4c9df9..13c4578514d 100644 --- a/solr/core/src/java/org/apache/solr/metrics/prometheus/core/SolrCoreIndexMetric.java +++ b/solr/core/src/java/org/apache/solr/metrics/prometheus/core/SolrCoreIndexMetric.java @@ -35,11 +35,10 @@ public SolrCoreMetric parseLabels() { } @Override - public void toPrometheus(SolrPrometheusCoreExporter solrPrometheusCoreExporter) { + public void toPrometheus(SolrPrometheusCoreExporter exporter) { if (dropwizardMetric instanceof Gauge) { if (metricName.endsWith("sizeInBytes")) { - solrPrometheusCoreExporter.exportGauge( - CORE_INDEX_METRICS, (Gauge) dropwizardMetric, getLabels()); + exporter.exportGauge(CORE_INDEX_METRICS, (Gauge) dropwizardMetric, getLabels()); } } } diff --git a/solr/core/src/java/org/apache/solr/metrics/prometheus/core/SolrCoreMetric.java b/solr/core/src/java/org/apache/solr/metrics/prometheus/core/SolrCoreMetric.java index 4e1b59d549f..9c3424d3237 100644 --- a/solr/core/src/java/org/apache/solr/metrics/prometheus/core/SolrCoreMetric.java +++ b/solr/core/src/java/org/apache/solr/metrics/prometheus/core/SolrCoreMetric.java @@ -16,13 +16,14 @@ */ package org.apache.solr.metrics.prometheus.core; +import static org.apache.solr.metrics.prometheus.PrometheusCoreExporterInfo.PROMETHEUS_CLOUD_CORE_PATTERN; + import com.codahale.metrics.Metric; import io.prometheus.metrics.model.snapshots.Labels; import java.util.ArrayList; import java.util.HashMap; import java.util.Map; import java.util.regex.Matcher; -import java.util.regex.Pattern; import org.apache.solr.common.SolrException; import org.apache.solr.metrics.prometheus.SolrPrometheusCoreExporter; @@ -56,16 +57,14 @@ public Labels getLabels() { public abstract SolrCoreMetric parseLabels(); - public abstract void toPrometheus(SolrPrometheusCoreExporter solrPrometheusCoreExporter); + public abstract void toPrometheus(SolrPrometheusCoreExporter exporter); private void appendCloudModeLabels() { - Pattern p = Pattern.compile("^core_(.*)_(shard[0-9]+)_(replica_n[0-9]+)"); - Matcher m = p.matcher(coreName); + Matcher m = PROMETHEUS_CLOUD_CORE_PATTERN.matcher(coreName); if (m.find()) { - String collectionName = m.group(1); - String shard = m.group(2); - String replica = m.group(3); - labels.putAll(Map.of("collection", collectionName, "shard", shard, "replica", replica)); + labels.put("collection", m.group(1)); + labels.put("shard", m.group(2)); + labels.put("replica", m.group(3)); } else { throw new SolrException( SolrException.ErrorCode.SERVER_ERROR, diff --git a/solr/core/src/java/org/apache/solr/metrics/prometheus/core/SolrCoreNoOpMetric.java b/solr/core/src/java/org/apache/solr/metrics/prometheus/core/SolrCoreNoOpMetric.java index 47c980e03cb..8265a7566ed 100644 --- a/solr/core/src/java/org/apache/solr/metrics/prometheus/core/SolrCoreNoOpMetric.java +++ b/solr/core/src/java/org/apache/solr/metrics/prometheus/core/SolrCoreNoOpMetric.java @@ -32,5 +32,5 @@ public SolrCoreMetric parseLabels() { } @Override - public void toPrometheus(SolrPrometheusCoreExporter solrPrometheusCoreExporter) {} + public void toPrometheus(SolrPrometheusCoreExporter exporter) {} } diff --git a/solr/core/src/java/org/apache/solr/metrics/prometheus/core/SolrCoreSearcherMetric.java b/solr/core/src/java/org/apache/solr/metrics/prometheus/core/SolrCoreSearcherMetric.java index a8be62edf53..23a3cd92b07 100644 --- a/solr/core/src/java/org/apache/solr/metrics/prometheus/core/SolrCoreSearcherMetric.java +++ b/solr/core/src/java/org/apache/solr/metrics/prometheus/core/SolrCoreSearcherMetric.java @@ -38,25 +38,21 @@ public SolrCoreSearcherMetric( public SolrCoreMetric parseLabels() { String[] parsedMetric = metricName.split("\\."); if (!(dropwizardMetric instanceof Counter)) { - String type = parsedMetric[2]; - labels.put("type", type); + labels.put("type", parsedMetric[2]); } return this; } @Override - public void toPrometheus(SolrPrometheusCoreExporter solrPrometheusCoreExporter) { + public void toPrometheus(SolrPrometheusCoreExporter exporter) { if (dropwizardMetric instanceof Gauge) { if (metricName.endsWith("liveDocsCache")) { - solrPrometheusCoreExporter.exportGauge( - CORE_CACHE_SEARCHER_METRICS, (Gauge) dropwizardMetric, getLabels()); + exporter.exportGauge(CORE_CACHE_SEARCHER_METRICS, (Gauge) dropwizardMetric, getLabels()); } else { - solrPrometheusCoreExporter.exportGauge( - CORE_SEARCHER_METRICS, (Gauge) dropwizardMetric, getLabels()); + exporter.exportGauge(CORE_SEARCHER_METRICS, (Gauge) dropwizardMetric, getLabels()); } } else if (dropwizardMetric instanceof Timer) { - solrPrometheusCoreExporter.exportTimer( - CORE_SEARCHER_TIMES, (Timer) dropwizardMetric, getLabels()); + exporter.exportTimer(CORE_SEARCHER_TIMES, (Timer) dropwizardMetric, getLabels()); } } } diff --git a/solr/core/src/java/org/apache/solr/metrics/prometheus/core/SolrCoreTlogMetric.java b/solr/core/src/java/org/apache/solr/metrics/prometheus/core/SolrCoreTlogMetric.java index 73b9f18c470..e2b2db439fb 100644 --- a/solr/core/src/java/org/apache/solr/metrics/prometheus/core/SolrCoreTlogMetric.java +++ b/solr/core/src/java/org/apache/solr/metrics/prometheus/core/SolrCoreTlogMetric.java @@ -33,17 +33,15 @@ public SolrCoreTlogMetric( public SolrCoreMetric parseLabels() { String[] parsedMetric = metricName.split("\\."); if (dropwizardMetric instanceof Meter) { - String item = parsedMetric[1]; - labels.put("item", item); + labels.put("item", parsedMetric[1]); } return this; } @Override - public void toPrometheus(SolrPrometheusCoreExporter solrPrometheusCoreExporter) { + public void toPrometheus(SolrPrometheusCoreExporter exporter) { if (dropwizardMetric instanceof Meter) { - solrPrometheusCoreExporter.exportMeter( - CORE_TLOG_METRICS, (Meter) dropwizardMetric, getLabels()); + exporter.exportMeter(CORE_TLOG_METRICS, (Meter) dropwizardMetric, getLabels()); } } } diff --git a/solr/core/src/java/org/apache/solr/response/PrometheusResponseWriter.java b/solr/core/src/java/org/apache/solr/response/PrometheusResponseWriter.java index 4cca2160fe4..150f73f0153 100644 --- a/solr/core/src/java/org/apache/solr/response/PrometheusResponseWriter.java +++ b/solr/core/src/java/org/apache/solr/response/PrometheusResponseWriter.java @@ -54,11 +54,11 @@ public void write(OutputStream out, SolrQueryRequest request, SolrQueryResponse throws IOException { NamedList prometheusRegistries = (NamedList) response.getValues().get("metrics"); - Iterator> it = prometheusRegistries.iterator(); var prometheusTextFormatWriter = new PrometheusTextFormatWriter(false); - while (it.hasNext()) { - Map.Entry entry = it.next(); - SolrPrometheusCoreExporter prometheusExporter = (SolrPrometheusCoreExporter) entry.getValue(); + for (Iterator> iter = prometheusRegistries.iterator(); + iter.hasNext(); ) { + SolrPrometheusCoreExporter prometheusExporter = + (SolrPrometheusCoreExporter) iter.next().getValue(); prometheusTextFormatWriter.write(out, prometheusExporter.collect()); } } diff --git a/solr/core/src/test/org/apache/solr/metrics/SolrCoreMetricTest.java b/solr/core/src/test/org/apache/solr/metrics/SolrCoreMetricTest.java index dbea7a21d0c..c904d4a99a0 100644 --- a/solr/core/src/test/org/apache/solr/metrics/SolrCoreMetricTest.java +++ b/solr/core/src/test/org/apache/solr/metrics/SolrCoreMetricTest.java @@ -76,6 +76,6 @@ public SolrCoreMetric parseLabels() { } @Override - public void toPrometheus(SolrPrometheusCoreExporter solrPrometheusCoreExporter) {} + public void toPrometheus(SolrPrometheusCoreExporter exporter) {} } } From b8475f80b16f44e4801269004043de8495db804a Mon Sep 17 00:00:00 2001 From: mbiscocho Date: Thu, 23 May 2024 17:00:40 -0400 Subject: [PATCH 19/32] Simplified loop and var names --- .../metrics/prometheus/PrometheusCoreExporterInfo.java | 3 +-- .../solr/metrics/prometheus/core/SolrCoreMetric.java | 4 ++-- .../org/apache/solr/response/PrometheusResponseWriter.java | 7 ++----- 3 files changed, 5 insertions(+), 9 deletions(-) diff --git a/solr/core/src/java/org/apache/solr/metrics/prometheus/PrometheusCoreExporterInfo.java b/solr/core/src/java/org/apache/solr/metrics/prometheus/PrometheusCoreExporterInfo.java index 2481bfda4c3..74c10db0179 100644 --- a/solr/core/src/java/org/apache/solr/metrics/prometheus/PrometheusCoreExporterInfo.java +++ b/solr/core/src/java/org/apache/solr/metrics/prometheus/PrometheusCoreExporterInfo.java @@ -33,6 +33,5 @@ enum CoreCategory { CORE } - String PROMETHEUS_CLOUD_CORE_REGEX = "^core_(.*)_(shard[0-9]+)_(replica_n[0-9]+)$"; - Pattern PROMETHEUS_CLOUD_CORE_PATTERN = Pattern.compile(PROMETHEUS_CLOUD_CORE_REGEX); + Pattern CLOUD_CORE_PATTERN = Pattern.compile("^core_(.*)_(shard[0-9]+)_(replica_n[0-9]+)$"); } diff --git a/solr/core/src/java/org/apache/solr/metrics/prometheus/core/SolrCoreMetric.java b/solr/core/src/java/org/apache/solr/metrics/prometheus/core/SolrCoreMetric.java index 9c3424d3237..8d0cff183c4 100644 --- a/solr/core/src/java/org/apache/solr/metrics/prometheus/core/SolrCoreMetric.java +++ b/solr/core/src/java/org/apache/solr/metrics/prometheus/core/SolrCoreMetric.java @@ -16,7 +16,7 @@ */ package org.apache.solr.metrics.prometheus.core; -import static org.apache.solr.metrics.prometheus.PrometheusCoreExporterInfo.PROMETHEUS_CLOUD_CORE_PATTERN; +import static org.apache.solr.metrics.prometheus.PrometheusCoreExporterInfo.CLOUD_CORE_PATTERN; import com.codahale.metrics.Metric; import io.prometheus.metrics.model.snapshots.Labels; @@ -60,7 +60,7 @@ public Labels getLabels() { public abstract void toPrometheus(SolrPrometheusCoreExporter exporter); private void appendCloudModeLabels() { - Matcher m = PROMETHEUS_CLOUD_CORE_PATTERN.matcher(coreName); + Matcher m = CLOUD_CORE_PATTERN.matcher(coreName); if (m.find()) { labels.put("collection", m.group(1)); labels.put("shard", m.group(2)); diff --git a/solr/core/src/java/org/apache/solr/response/PrometheusResponseWriter.java b/solr/core/src/java/org/apache/solr/response/PrometheusResponseWriter.java index 150f73f0153..d496aa8c353 100644 --- a/solr/core/src/java/org/apache/solr/response/PrometheusResponseWriter.java +++ b/solr/core/src/java/org/apache/solr/response/PrometheusResponseWriter.java @@ -27,7 +27,6 @@ import java.lang.invoke.MethodHandles; import java.util.ArrayList; import java.util.Arrays; -import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.function.Consumer; @@ -55,10 +54,8 @@ public void write(OutputStream out, SolrQueryRequest request, SolrQueryResponse NamedList prometheusRegistries = (NamedList) response.getValues().get("metrics"); var prometheusTextFormatWriter = new PrometheusTextFormatWriter(false); - for (Iterator> iter = prometheusRegistries.iterator(); - iter.hasNext(); ) { - SolrPrometheusCoreExporter prometheusExporter = - (SolrPrometheusCoreExporter) iter.next().getValue(); + for (Map.Entry prometheusRegistry : prometheusRegistries) { + var prometheusExporter = (SolrPrometheusCoreExporter) prometheusRegistry.getValue(); prometheusTextFormatWriter.write(out, prometheusExporter.collect()); } } From acde9880d3ba8ae51260d54e1c6d2c4790fcd713 Mon Sep 17 00:00:00 2001 From: mbiscocho Date: Mon, 10 Jun 2024 14:11:58 -0400 Subject: [PATCH 20/32] Export jetty/jvm/node registry metrics --- .../solr/handler/admin/MetricsHandler.java | 27 +- .../solr/metrics/prometheus/SolrMetric.java | 51 ++ ...oreNoOpMetric.java => SolrNoOpMetric.java} | 17 +- .../prometheus/SolrPrometheusExporter.java | 25 +- .../PrometheusCoreExporterInfo.java | 2 +- .../prometheus/core/SolrCoreCacheMetric.java | 4 +- .../core/SolrCoreHandlerMetric.java | 4 +- .../core/SolrCoreHighlighterMetric.java | 4 +- .../prometheus/core/SolrCoreIndexMetric.java | 4 +- .../prometheus/core/SolrCoreMetric.java | 32 +- .../core/SolrCoreSearcherMetric.java | 4 +- .../prometheus/core/SolrCoreTlogMetric.java | 4 +- .../SolrPrometheusCoreExporter.java | 33 +- .../metrics/prometheus/core/package-info.java | 4 +- .../jetty/SolrJettyDispatchesMetric.java | 43 ++ .../prometheus/jetty/SolrJettyMetric.java | 27 + .../jetty/SolrJettyReqRespMetric.java | 61 +++ .../jetty/SolrPrometheusJettyExporter.java | 49 ++ .../prometheus/jetty/package-info.java | 22 + .../jvm/PrometheusJvmExporterInfo.java | 30 ++ .../prometheus/jvm/SolrJvmBuffersMetric.java | 52 ++ .../prometheus/jvm/SolrJvmGcMetrics.java | 49 ++ .../prometheus/jvm/SolrJvmMemoryMetric.java | 59 ++ .../metrics/prometheus/jvm/SolrJvmMetric.java | 27 + .../prometheus/jvm/SolrJvmOsMetric.java | 58 ++ .../jvm/SolrPrometheusJvmExporter.java | 61 +++ .../metrics/prometheus/jvm/package-info.java | 22 + .../node/PrometheusNodeExporterInfo.java | 27 + .../node/SolrNodeContainerMetric.java | 53 ++ .../node/SolrNodeHandlerMetric.java | 64 +++ .../prometheus/node/SolrNodeMetric.java | 29 + .../node/SolrPrometheusNodeExporter.java | 99 ++++ .../metrics/prometheus/node/package-info.java | 22 + .../solr/metrics/prometheus/package-info.java | 4 +- .../response/PrometheusResponseWriter.java | 59 +- .../handler/admin/MetricsHandlerTest.java | 505 +++++++++++------- .../solr/metrics/SolrCoreMetricTest.java | 4 +- .../metrics/SolrPrometheusExporterTest.java | 6 + .../TestPrometheusResponseWriter.java | 2 +- 39 files changed, 1355 insertions(+), 294 deletions(-) create mode 100644 solr/core/src/java/org/apache/solr/metrics/prometheus/SolrMetric.java rename solr/core/src/java/org/apache/solr/metrics/prometheus/{core/SolrCoreNoOpMetric.java => SolrNoOpMetric.java} (62%) rename solr/core/src/java/org/apache/solr/metrics/prometheus/{ => core}/PrometheusCoreExporterInfo.java (96%) rename solr/core/src/java/org/apache/solr/metrics/prometheus/{ => core}/SolrPrometheusCoreExporter.java (67%) create mode 100644 solr/core/src/java/org/apache/solr/metrics/prometheus/jetty/SolrJettyDispatchesMetric.java create mode 100644 solr/core/src/java/org/apache/solr/metrics/prometheus/jetty/SolrJettyMetric.java create mode 100644 solr/core/src/java/org/apache/solr/metrics/prometheus/jetty/SolrJettyReqRespMetric.java create mode 100644 solr/core/src/java/org/apache/solr/metrics/prometheus/jetty/SolrPrometheusJettyExporter.java create mode 100644 solr/core/src/java/org/apache/solr/metrics/prometheus/jetty/package-info.java create mode 100644 solr/core/src/java/org/apache/solr/metrics/prometheus/jvm/PrometheusJvmExporterInfo.java create mode 100644 solr/core/src/java/org/apache/solr/metrics/prometheus/jvm/SolrJvmBuffersMetric.java create mode 100644 solr/core/src/java/org/apache/solr/metrics/prometheus/jvm/SolrJvmGcMetrics.java create mode 100644 solr/core/src/java/org/apache/solr/metrics/prometheus/jvm/SolrJvmMemoryMetric.java create mode 100644 solr/core/src/java/org/apache/solr/metrics/prometheus/jvm/SolrJvmMetric.java create mode 100644 solr/core/src/java/org/apache/solr/metrics/prometheus/jvm/SolrJvmOsMetric.java create mode 100644 solr/core/src/java/org/apache/solr/metrics/prometheus/jvm/SolrPrometheusJvmExporter.java create mode 100644 solr/core/src/java/org/apache/solr/metrics/prometheus/jvm/package-info.java create mode 100644 solr/core/src/java/org/apache/solr/metrics/prometheus/node/PrometheusNodeExporterInfo.java create mode 100644 solr/core/src/java/org/apache/solr/metrics/prometheus/node/SolrNodeContainerMetric.java create mode 100644 solr/core/src/java/org/apache/solr/metrics/prometheus/node/SolrNodeHandlerMetric.java create mode 100644 solr/core/src/java/org/apache/solr/metrics/prometheus/node/SolrNodeMetric.java create mode 100644 solr/core/src/java/org/apache/solr/metrics/prometheus/node/SolrPrometheusNodeExporter.java create mode 100644 solr/core/src/java/org/apache/solr/metrics/prometheus/node/package-info.java diff --git a/solr/core/src/java/org/apache/solr/handler/admin/MetricsHandler.java b/solr/core/src/java/org/apache/solr/handler/admin/MetricsHandler.java index a7328e2bbba..73da8a818e4 100644 --- a/solr/core/src/java/org/apache/solr/handler/admin/MetricsHandler.java +++ b/solr/core/src/java/org/apache/solr/handler/admin/MetricsHandler.java @@ -190,21 +190,18 @@ private NamedList handlePrometheusExport(SolrParams params) { for (String registryName : requestedRegistries) { MetricRegistry dropwizardRegistry = metricManager.registry(registryName); - // Currently only export Solr Core registries - if (registryName.startsWith("solr.core")) { - PrometheusResponseWriter.toPrometheus( - dropwizardRegistry, - registryName, - metricFilters, - mustMatchFilter, - propertyFilter, - false, - false, - true, - (registry) -> { - response.add(registryName, registry); - }); - } + PrometheusResponseWriter.toPrometheus( + dropwizardRegistry, + registryName, + metricFilters, + mustMatchFilter, + propertyFilter, + false, + false, + true, + (registry) -> { + response.add(registryName, registry); + }); } return response; } diff --git a/solr/core/src/java/org/apache/solr/metrics/prometheus/SolrMetric.java b/solr/core/src/java/org/apache/solr/metrics/prometheus/SolrMetric.java new file mode 100644 index 00000000000..59bbfadd4bb --- /dev/null +++ b/solr/core/src/java/org/apache/solr/metrics/prometheus/SolrMetric.java @@ -0,0 +1,51 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.solr.metrics.prometheus; + +import com.codahale.metrics.Metric; +import io.prometheus.metrics.model.snapshots.Labels; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.Map; + +/** + * Base class is a wrapper to categorize and export {@link com.codahale.metrics.Metric} to {@link + * io.prometheus.metrics.model.snapshots.DataPointSnapshot} and register to a {@link + * SolrPrometheusExporter}. {@link com.codahale.metrics.MetricRegistry} does not support tags unlike + * prometheus. Metrics registered to the registry need to be parsed out from the metric name to be + * exported to {@link io.prometheus.metrics.model.snapshots.DataPointSnapshot} + */ +public abstract class SolrMetric { + public Metric dropwizardMetric; + public String metricName; + public Map labels = new HashMap<>(); + + public SolrMetric() {} + + public SolrMetric(Metric dropwizardMetric, String metricName) { + this.dropwizardMetric = dropwizardMetric; + this.metricName = metricName; + } + + public abstract SolrMetric parseLabels(); + + public abstract void toPrometheus(SolrPrometheusExporter exporter); + + public Labels getLabels() { + return Labels.of(new ArrayList<>(labels.keySet()), new ArrayList<>(labels.values())); + } +} diff --git a/solr/core/src/java/org/apache/solr/metrics/prometheus/core/SolrCoreNoOpMetric.java b/solr/core/src/java/org/apache/solr/metrics/prometheus/SolrNoOpMetric.java similarity index 62% rename from solr/core/src/java/org/apache/solr/metrics/prometheus/core/SolrCoreNoOpMetric.java rename to solr/core/src/java/org/apache/solr/metrics/prometheus/SolrNoOpMetric.java index 8265a7566ed..0be1761dc51 100644 --- a/solr/core/src/java/org/apache/solr/metrics/prometheus/core/SolrCoreNoOpMetric.java +++ b/solr/core/src/java/org/apache/solr/metrics/prometheus/SolrNoOpMetric.java @@ -14,23 +14,16 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.apache.solr.metrics.prometheus.core; +package org.apache.solr.metrics.prometheus; -import com.codahale.metrics.Metric; -import org.apache.solr.metrics.prometheus.SolrPrometheusCoreExporter; - -public class SolrCoreNoOpMetric extends SolrCoreMetric { - - public SolrCoreNoOpMetric( - Metric dropwizardMetric, String coreName, String metricName, boolean cloudMode) { - super(dropwizardMetric, coreName, metricName, cloudMode); - } +public class SolrNoOpMetric extends SolrMetric { + public SolrNoOpMetric() {} @Override - public SolrCoreMetric parseLabels() { + public SolrMetric parseLabels() { return this; } @Override - public void toPrometheus(SolrPrometheusCoreExporter exporter) {} + public void toPrometheus(SolrPrometheusExporter exporter) {} } diff --git a/solr/core/src/java/org/apache/solr/metrics/prometheus/SolrPrometheusExporter.java b/solr/core/src/java/org/apache/solr/metrics/prometheus/SolrPrometheusExporter.java index 5b3844b5c1f..fd4a2cafa74 100644 --- a/solr/core/src/java/org/apache/solr/metrics/prometheus/SolrPrometheusExporter.java +++ b/solr/core/src/java/org/apache/solr/metrics/prometheus/SolrPrometheusExporter.java @@ -46,13 +46,21 @@ public SolrPrometheusExporter() { /** * Export {@link Metric} to {@link io.prometheus.metrics.model.snapshots.MetricSnapshot} and - * registers the Snapshot + * register the Snapshot * * @param dropwizardMetric the {@link Metric} to be exported * @param metricName Dropwizard metric name */ public abstract void exportDropwizardMetric(Metric dropwizardMetric, String metricName); + /** + * Categorize {@link Metric} based on the metric name + * + * @param dropwizardMetric the {@link Metric} to be exported + * @param metricName Dropwizard metric name + */ + public abstract SolrMetric categorizeMetric(Metric dropwizardMetric, String metricName); + /** * Export {@link Meter} to {@link * io.prometheus.metrics.model.snapshots.CounterSnapshot.CounterDataPointSnapshot} and collect @@ -99,6 +107,21 @@ public void exportTimer(String metricName, Timer dropwizardMetric, Labels labels collectGaugeDatapoint(metricName, dataPoint); } + /** + * Export {@link Timer} ands its Count to {@link + * io.prometheus.metrics.model.snapshots.CounterSnapshot.CounterDataPointSnapshot} and collect + * datapoint + * + * @param metricName name of prometheus metric + * @param dropwizardMetric the {@link Timer} to be exported + * @param labels label names and values to record + */ + public void exportTimerCount(String metricName, Timer dropwizardMetric, Labels labels) { + CounterSnapshot.CounterDataPointSnapshot dataPoint = + createCounterDatapoint(dropwizardMetric.getCount(), labels); + collectCounterDatapoint(metricName, dataPoint); + } + /** * Export {@link com.codahale.metrics.Gauge} to {@link * io.prometheus.metrics.model.snapshots.GaugeSnapshot.GaugeDataPointSnapshot} and collect to diff --git a/solr/core/src/java/org/apache/solr/metrics/prometheus/PrometheusCoreExporterInfo.java b/solr/core/src/java/org/apache/solr/metrics/prometheus/core/PrometheusCoreExporterInfo.java similarity index 96% rename from solr/core/src/java/org/apache/solr/metrics/prometheus/PrometheusCoreExporterInfo.java rename to solr/core/src/java/org/apache/solr/metrics/prometheus/core/PrometheusCoreExporterInfo.java index 74c10db0179..32ed8104276 100644 --- a/solr/core/src/java/org/apache/solr/metrics/prometheus/PrometheusCoreExporterInfo.java +++ b/solr/core/src/java/org/apache/solr/metrics/prometheus/core/PrometheusCoreExporterInfo.java @@ -14,7 +14,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.apache.solr.metrics.prometheus; +package org.apache.solr.metrics.prometheus.core; import java.util.regex.Pattern; diff --git a/solr/core/src/java/org/apache/solr/metrics/prometheus/core/SolrCoreCacheMetric.java b/solr/core/src/java/org/apache/solr/metrics/prometheus/core/SolrCoreCacheMetric.java index ced9ecfba18..587939655c0 100644 --- a/solr/core/src/java/org/apache/solr/metrics/prometheus/core/SolrCoreCacheMetric.java +++ b/solr/core/src/java/org/apache/solr/metrics/prometheus/core/SolrCoreCacheMetric.java @@ -18,7 +18,7 @@ import com.codahale.metrics.Gauge; import com.codahale.metrics.Metric; -import org.apache.solr.metrics.prometheus.SolrPrometheusCoreExporter; +import org.apache.solr.metrics.prometheus.SolrPrometheusExporter; /** Dropwizard metrics of name CACHE.* */ public class SolrCoreCacheMetric extends SolrCoreMetric { @@ -39,7 +39,7 @@ public SolrCoreMetric parseLabels() { } @Override - public void toPrometheus(SolrPrometheusCoreExporter exporter) { + public void toPrometheus(SolrPrometheusExporter exporter) { if (dropwizardMetric instanceof Gauge) { exporter.exportGauge(CORE_CACHE_SEARCHER_METRICS, (Gauge) dropwizardMetric, getLabels()); } diff --git a/solr/core/src/java/org/apache/solr/metrics/prometheus/core/SolrCoreHandlerMetric.java b/solr/core/src/java/org/apache/solr/metrics/prometheus/core/SolrCoreHandlerMetric.java index d6fa97678e8..e8bf725edb2 100644 --- a/solr/core/src/java/org/apache/solr/metrics/prometheus/core/SolrCoreHandlerMetric.java +++ b/solr/core/src/java/org/apache/solr/metrics/prometheus/core/SolrCoreHandlerMetric.java @@ -21,7 +21,7 @@ import com.codahale.metrics.Meter; import com.codahale.metrics.Metric; import com.codahale.metrics.Timer; -import org.apache.solr.metrics.prometheus.SolrPrometheusCoreExporter; +import org.apache.solr.metrics.prometheus.SolrPrometheusExporter; /** Dropwizard metrics of name ADMIN/QUERY/UPDATE/REPLICATION.* */ public class SolrCoreHandlerMetric extends SolrCoreMetric { @@ -45,7 +45,7 @@ public SolrCoreMetric parseLabels() { } @Override - public void toPrometheus(SolrPrometheusCoreExporter exporter) { + public void toPrometheus(SolrPrometheusExporter exporter) { if (dropwizardMetric instanceof Meter) { exporter.exportMeter(CORE_REQUESTS_TOTAL, (Meter) dropwizardMetric, getLabels()); } else if (dropwizardMetric instanceof Counter) { diff --git a/solr/core/src/java/org/apache/solr/metrics/prometheus/core/SolrCoreHighlighterMetric.java b/solr/core/src/java/org/apache/solr/metrics/prometheus/core/SolrCoreHighlighterMetric.java index b5ab3a99332..a1cf3128aae 100644 --- a/solr/core/src/java/org/apache/solr/metrics/prometheus/core/SolrCoreHighlighterMetric.java +++ b/solr/core/src/java/org/apache/solr/metrics/prometheus/core/SolrCoreHighlighterMetric.java @@ -18,7 +18,7 @@ import com.codahale.metrics.Counter; import com.codahale.metrics.Metric; -import org.apache.solr.metrics.prometheus.SolrPrometheusCoreExporter; +import org.apache.solr.metrics.prometheus.SolrPrometheusExporter; /** Dropwizard metrics of name HIGHLIGHTER.* */ public class SolrCoreHighlighterMetric extends SolrCoreMetric { @@ -38,7 +38,7 @@ public SolrCoreMetric parseLabels() { } @Override - public void toPrometheus(SolrPrometheusCoreExporter exporter) { + public void toPrometheus(SolrPrometheusExporter exporter) { if (dropwizardMetric instanceof Counter) { exporter.exportCounter(CORE_HIGHLIGHER_METRICS, (Counter) dropwizardMetric, getLabels()); } diff --git a/solr/core/src/java/org/apache/solr/metrics/prometheus/core/SolrCoreIndexMetric.java b/solr/core/src/java/org/apache/solr/metrics/prometheus/core/SolrCoreIndexMetric.java index 13c4578514d..e0d43e5aa9d 100644 --- a/solr/core/src/java/org/apache/solr/metrics/prometheus/core/SolrCoreIndexMetric.java +++ b/solr/core/src/java/org/apache/solr/metrics/prometheus/core/SolrCoreIndexMetric.java @@ -18,7 +18,7 @@ import com.codahale.metrics.Gauge; import com.codahale.metrics.Metric; -import org.apache.solr.metrics.prometheus.SolrPrometheusCoreExporter; +import org.apache.solr.metrics.prometheus.SolrPrometheusExporter; /** Dropwizard metrics of name INDEX.* */ public class SolrCoreIndexMetric extends SolrCoreMetric { @@ -35,7 +35,7 @@ public SolrCoreMetric parseLabels() { } @Override - public void toPrometheus(SolrPrometheusCoreExporter exporter) { + public void toPrometheus(SolrPrometheusExporter exporter) { if (dropwizardMetric instanceof Gauge) { if (metricName.endsWith("sizeInBytes")) { exporter.exportGauge(CORE_INDEX_METRICS, (Gauge) dropwizardMetric, getLabels()); diff --git a/solr/core/src/java/org/apache/solr/metrics/prometheus/core/SolrCoreMetric.java b/solr/core/src/java/org/apache/solr/metrics/prometheus/core/SolrCoreMetric.java index 8d0cff183c4..d977106d241 100644 --- a/solr/core/src/java/org/apache/solr/metrics/prometheus/core/SolrCoreMetric.java +++ b/solr/core/src/java/org/apache/solr/metrics/prometheus/core/SolrCoreMetric.java @@ -16,49 +16,27 @@ */ package org.apache.solr.metrics.prometheus.core; -import static org.apache.solr.metrics.prometheus.PrometheusCoreExporterInfo.CLOUD_CORE_PATTERN; +import static org.apache.solr.metrics.prometheus.core.PrometheusCoreExporterInfo.CLOUD_CORE_PATTERN; import com.codahale.metrics.Metric; -import io.prometheus.metrics.model.snapshots.Labels; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.Map; import java.util.regex.Matcher; import org.apache.solr.common.SolrException; -import org.apache.solr.metrics.prometheus.SolrPrometheusCoreExporter; +import org.apache.solr.metrics.prometheus.SolrMetric; -/** - * Base class is a wrapper to categorize and export {@link com.codahale.metrics.Metric} to {@link - * io.prometheus.metrics.model.snapshots.DataPointSnapshot} and register to a {@link - * SolrPrometheusCoreExporter}. {@link com.codahale.metrics.MetricRegistry} does not support tags - * unlike prometheus. Metrics registered to the registry need to be parsed out from the metric name - * to be exported to {@link io.prometheus.metrics.model.snapshots.DataPointSnapshot} - */ -public abstract class SolrCoreMetric { - public Metric dropwizardMetric; +/** Base class is a wrapper to export a solr.core {@link com.codahale.metrics.Metric} */ +public abstract class SolrCoreMetric extends SolrMetric { public String coreName; - public String metricName; - public Map labels = new HashMap<>(); public SolrCoreMetric( Metric dropwizardMetric, String coreName, String metricName, boolean cloudMode) { - this.dropwizardMetric = dropwizardMetric; + super(dropwizardMetric, metricName); this.coreName = coreName; - this.metricName = metricName; labels.put("core", coreName); if (cloudMode) { appendCloudModeLabels(); } } - public Labels getLabels() { - return Labels.of(new ArrayList<>(labels.keySet()), new ArrayList<>(labels.values())); - } - - public abstract SolrCoreMetric parseLabels(); - - public abstract void toPrometheus(SolrPrometheusCoreExporter exporter); - private void appendCloudModeLabels() { Matcher m = CLOUD_CORE_PATTERN.matcher(coreName); if (m.find()) { diff --git a/solr/core/src/java/org/apache/solr/metrics/prometheus/core/SolrCoreSearcherMetric.java b/solr/core/src/java/org/apache/solr/metrics/prometheus/core/SolrCoreSearcherMetric.java index 23a3cd92b07..470fae35081 100644 --- a/solr/core/src/java/org/apache/solr/metrics/prometheus/core/SolrCoreSearcherMetric.java +++ b/solr/core/src/java/org/apache/solr/metrics/prometheus/core/SolrCoreSearcherMetric.java @@ -22,7 +22,7 @@ import com.codahale.metrics.Gauge; import com.codahale.metrics.Metric; import com.codahale.metrics.Timer; -import org.apache.solr.metrics.prometheus.SolrPrometheusCoreExporter; +import org.apache.solr.metrics.prometheus.SolrPrometheusExporter; /** Dropwizard metrics of name SEARCHER.* */ public class SolrCoreSearcherMetric extends SolrCoreMetric { @@ -44,7 +44,7 @@ public SolrCoreMetric parseLabels() { } @Override - public void toPrometheus(SolrPrometheusCoreExporter exporter) { + public void toPrometheus(SolrPrometheusExporter exporter) { if (dropwizardMetric instanceof Gauge) { if (metricName.endsWith("liveDocsCache")) { exporter.exportGauge(CORE_CACHE_SEARCHER_METRICS, (Gauge) dropwizardMetric, getLabels()); diff --git a/solr/core/src/java/org/apache/solr/metrics/prometheus/core/SolrCoreTlogMetric.java b/solr/core/src/java/org/apache/solr/metrics/prometheus/core/SolrCoreTlogMetric.java index e2b2db439fb..80aab10df9f 100644 --- a/solr/core/src/java/org/apache/solr/metrics/prometheus/core/SolrCoreTlogMetric.java +++ b/solr/core/src/java/org/apache/solr/metrics/prometheus/core/SolrCoreTlogMetric.java @@ -18,7 +18,7 @@ import com.codahale.metrics.Meter; import com.codahale.metrics.Metric; -import org.apache.solr.metrics.prometheus.SolrPrometheusCoreExporter; +import org.apache.solr.metrics.prometheus.SolrPrometheusExporter; /** Dropwizard metrics of name TLOG.* */ public class SolrCoreTlogMetric extends SolrCoreMetric { @@ -39,7 +39,7 @@ public SolrCoreMetric parseLabels() { } @Override - public void toPrometheus(SolrPrometheusCoreExporter exporter) { + public void toPrometheus(SolrPrometheusExporter exporter) { if (dropwizardMetric instanceof Meter) { exporter.exportMeter(CORE_TLOG_METRICS, (Meter) dropwizardMetric, getLabels()); } diff --git a/solr/core/src/java/org/apache/solr/metrics/prometheus/SolrPrometheusCoreExporter.java b/solr/core/src/java/org/apache/solr/metrics/prometheus/core/SolrPrometheusCoreExporter.java similarity index 67% rename from solr/core/src/java/org/apache/solr/metrics/prometheus/SolrPrometheusCoreExporter.java rename to solr/core/src/java/org/apache/solr/metrics/prometheus/core/SolrPrometheusCoreExporter.java index 507743a66d9..99066acea32 100644 --- a/solr/core/src/java/org/apache/solr/metrics/prometheus/SolrPrometheusCoreExporter.java +++ b/solr/core/src/java/org/apache/solr/metrics/prometheus/core/SolrPrometheusCoreExporter.java @@ -14,18 +14,13 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.apache.solr.metrics.prometheus; +package org.apache.solr.metrics.prometheus.core; -import com.codahale.metrics.Meter; import com.codahale.metrics.Metric; -import org.apache.solr.metrics.prometheus.core.SolrCoreCacheMetric; -import org.apache.solr.metrics.prometheus.core.SolrCoreHandlerMetric; -import org.apache.solr.metrics.prometheus.core.SolrCoreHighlighterMetric; -import org.apache.solr.metrics.prometheus.core.SolrCoreIndexMetric; -import org.apache.solr.metrics.prometheus.core.SolrCoreMetric; -import org.apache.solr.metrics.prometheus.core.SolrCoreNoOpMetric; -import org.apache.solr.metrics.prometheus.core.SolrCoreSearcherMetric; -import org.apache.solr.metrics.prometheus.core.SolrCoreTlogMetric; +import com.google.common.base.Enums; +import org.apache.solr.metrics.prometheus.SolrMetric; +import org.apache.solr.metrics.prometheus.SolrNoOpMetric; +import org.apache.solr.metrics.prometheus.SolrPrometheusExporter; /** * This class maintains a {@link io.prometheus.metrics.model.snapshots.MetricSnapshot}s exported @@ -42,21 +37,19 @@ public SolrPrometheusCoreExporter(String coreName, boolean cloudMode) { this.cloudMode = cloudMode; } - /** - * Export {@link Metric} to {@link io.prometheus.metrics.model.snapshots.MetricSnapshot} and - * registers the Snapshot - * - * @param dropwizardMetric the {@link Meter} to be exported - * @param metricName Dropwizard metric name - */ @Override public void exportDropwizardMetric(Metric dropwizardMetric, String metricName) { - SolrCoreMetric solrCoreMetric = categorizeCoreMetric(dropwizardMetric, metricName); + SolrMetric solrCoreMetric = categorizeMetric(dropwizardMetric, metricName); solrCoreMetric.parseLabels().toPrometheus(this); } - private SolrCoreMetric categorizeCoreMetric(Metric dropwizardMetric, String metricName) { + @Override + public SolrMetric categorizeMetric(Metric dropwizardMetric, String metricName) { String metricCategory = metricName.split("\\.", 2)[0]; + if (!Enums.getIfPresent(PrometheusCoreExporterInfo.CoreCategory.class, metricCategory) + .isPresent()) { + return new SolrNoOpMetric(); + } switch (CoreCategory.valueOf(metricCategory)) { case ADMIN: case QUERY: @@ -75,7 +68,7 @@ private SolrCoreMetric categorizeCoreMetric(Metric dropwizardMetric, String metr return new SolrCoreIndexMetric(dropwizardMetric, coreName, metricName, cloudMode); case CORE: default: - return new SolrCoreNoOpMetric(dropwizardMetric, coreName, metricName, cloudMode); + return new SolrNoOpMetric(); } } } diff --git a/solr/core/src/java/org/apache/solr/metrics/prometheus/core/package-info.java b/solr/core/src/java/org/apache/solr/metrics/prometheus/core/package-info.java index b419047dd18..701dcf9e3bf 100644 --- a/solr/core/src/java/org/apache/solr/metrics/prometheus/core/package-info.java +++ b/solr/core/src/java/org/apache/solr/metrics/prometheus/core/package-info.java @@ -16,7 +16,7 @@ */ /** - * The {@link org.apache.solr.metrics.prometheus.core.SolrCoreMetric} is a wrapper to export {@link - * com.codahale.metrics.Metric} to {@link io.prometheus.metrics.model.snapshots.DataPointSnapshot} + * The {@link org.apache.solr.metrics.prometheus.core.SolrPrometheusCoreExporter} is responsible for + * exporting solr.core registry metrics to Prometheus. */ package org.apache.solr.metrics.prometheus.core; diff --git a/solr/core/src/java/org/apache/solr/metrics/prometheus/jetty/SolrJettyDispatchesMetric.java b/solr/core/src/java/org/apache/solr/metrics/prometheus/jetty/SolrJettyDispatchesMetric.java new file mode 100644 index 00000000000..b4fbd90890e --- /dev/null +++ b/solr/core/src/java/org/apache/solr/metrics/prometheus/jetty/SolrJettyDispatchesMetric.java @@ -0,0 +1,43 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.solr.metrics.prometheus.jetty; + +import com.codahale.metrics.Metric; +import com.codahale.metrics.Timer; +import org.apache.solr.metrics.prometheus.SolrMetric; +import org.apache.solr.metrics.prometheus.SolrPrometheusExporter; + +/* Dropwizard metrics of name *.dispatches */ +public class SolrJettyDispatchesMetric extends SolrJettyMetric { + public static final String JETTY_DISPATCHES_TOTAL = "solr_metrics_jetty_dispatches"; + + public SolrJettyDispatchesMetric(Metric dropwizardMetric, String metricName) { + super(dropwizardMetric, metricName); + } + + @Override + public SolrMetric parseLabels() { + return this; + } + + @Override + public void toPrometheus(SolrPrometheusExporter exporter) { + if (dropwizardMetric instanceof Timer) { + exporter.exportTimerCount(JETTY_DISPATCHES_TOTAL, (Timer) dropwizardMetric, getLabels()); + } + } +} diff --git a/solr/core/src/java/org/apache/solr/metrics/prometheus/jetty/SolrJettyMetric.java b/solr/core/src/java/org/apache/solr/metrics/prometheus/jetty/SolrJettyMetric.java new file mode 100644 index 00000000000..95211f6d9eb --- /dev/null +++ b/solr/core/src/java/org/apache/solr/metrics/prometheus/jetty/SolrJettyMetric.java @@ -0,0 +1,27 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.solr.metrics.prometheus.jetty; + +import com.codahale.metrics.Metric; +import org.apache.solr.metrics.prometheus.SolrMetric; + +/** Base class is a wrapper to export a solr.jetty {@link com.codahale.metrics.Metric} */ +public abstract class SolrJettyMetric extends SolrMetric { + public SolrJettyMetric(Metric dropwizardMetric, String metricName) { + super(dropwizardMetric, metricName); + } +} diff --git a/solr/core/src/java/org/apache/solr/metrics/prometheus/jetty/SolrJettyReqRespMetric.java b/solr/core/src/java/org/apache/solr/metrics/prometheus/jetty/SolrJettyReqRespMetric.java new file mode 100644 index 00000000000..f5c7a165ed4 --- /dev/null +++ b/solr/core/src/java/org/apache/solr/metrics/prometheus/jetty/SolrJettyReqRespMetric.java @@ -0,0 +1,61 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.solr.metrics.prometheus.jetty; + +import com.codahale.metrics.Counter; +import com.codahale.metrics.Meter; +import com.codahale.metrics.Metric; +import com.codahale.metrics.Timer; +import org.apache.solr.metrics.prometheus.SolrMetric; +import org.apache.solr.metrics.prometheus.SolrPrometheusExporter; + +/* Dropwizard metrics of name requests and responses */ +public class SolrJettyReqRespMetric extends SolrJettyMetric { + public static final String JETTY_RESPONSES_TOTAL = "solr_metrics_jetty_response"; + public static final String JETTY_REQUESTS_TOTAL = "solr_metrics_jetty_requests"; + + public SolrJettyReqRespMetric(Metric dropwizardMetric, String metricName) { + super(dropwizardMetric, metricName); + } + + @Override + public SolrMetric parseLabels() { + String[] parsedMetric = metricName.split("\\."); + String label = parsedMetric[parsedMetric.length - 1].split("-")[0]; + if (metricName.endsWith("xx-responses")) { + labels.put("status", label); + } else { + labels.put("method", label); + } + return this; + } + + @Override + public void toPrometheus(SolrPrometheusExporter exporter) { + if (dropwizardMetric instanceof Meter) { + if (metricName.endsWith("xx-responses")) { + exporter.exportMeter(JETTY_RESPONSES_TOTAL, (Meter) dropwizardMetric, getLabels()); + } + } else if (metricName.endsWith("-requests")) { + if (dropwizardMetric instanceof Counter) { + exporter.exportCounter(JETTY_REQUESTS_TOTAL, (Counter) dropwizardMetric, getLabels()); + } else if (dropwizardMetric instanceof Timer) { + exporter.exportTimerCount(JETTY_REQUESTS_TOTAL, (Timer) dropwizardMetric, getLabels()); + } + } + } +} diff --git a/solr/core/src/java/org/apache/solr/metrics/prometheus/jetty/SolrPrometheusJettyExporter.java b/solr/core/src/java/org/apache/solr/metrics/prometheus/jetty/SolrPrometheusJettyExporter.java new file mode 100644 index 00000000000..0cfafb7f4cd --- /dev/null +++ b/solr/core/src/java/org/apache/solr/metrics/prometheus/jetty/SolrPrometheusJettyExporter.java @@ -0,0 +1,49 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.solr.metrics.prometheus.jetty; + +import com.codahale.metrics.Metric; +import org.apache.solr.metrics.prometheus.SolrMetric; +import org.apache.solr.metrics.prometheus.SolrNoOpMetric; +import org.apache.solr.metrics.prometheus.SolrPrometheusExporter; + +/** + * This class maintains a {@link io.prometheus.metrics.model.snapshots.MetricSnapshot}s exported + * from solr.jetty {@link com.codahale.metrics.MetricRegistry} + */ +public class SolrPrometheusJettyExporter extends SolrPrometheusExporter { + public SolrPrometheusJettyExporter() { + super(); + } + + @Override + public void exportDropwizardMetric(Metric dropwizardMetric, String metricName) { + SolrMetric solrJettyMetric = categorizeMetric(dropwizardMetric, metricName); + solrJettyMetric.parseLabels().toPrometheus(this); + } + + @Override + public SolrMetric categorizeMetric(Metric dropwizardMetric, String metricName) { + if (metricName.endsWith("xx-responses") || metricName.endsWith("-requests")) { + return new SolrJettyReqRespMetric(dropwizardMetric, metricName); + } else if (metricName.endsWith(".dispatches")) { + return new SolrJettyDispatchesMetric(dropwizardMetric, metricName); + } else { + return new SolrNoOpMetric(); + } + } +} diff --git a/solr/core/src/java/org/apache/solr/metrics/prometheus/jetty/package-info.java b/solr/core/src/java/org/apache/solr/metrics/prometheus/jetty/package-info.java new file mode 100644 index 00000000000..9f4123c13f1 --- /dev/null +++ b/solr/core/src/java/org/apache/solr/metrics/prometheus/jetty/package-info.java @@ -0,0 +1,22 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * The {@link org.apache.solr.metrics.prometheus.jetty.SolrPrometheusJettyExporter} is responsible + * for exporting solr.jetty registry metrics to Prometheus. + */ +package org.apache.solr.metrics.prometheus.jetty; diff --git a/solr/core/src/java/org/apache/solr/metrics/prometheus/jvm/PrometheusJvmExporterInfo.java b/solr/core/src/java/org/apache/solr/metrics/prometheus/jvm/PrometheusJvmExporterInfo.java new file mode 100644 index 00000000000..dfe9075eb17 --- /dev/null +++ b/solr/core/src/java/org/apache/solr/metrics/prometheus/jvm/PrometheusJvmExporterInfo.java @@ -0,0 +1,30 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.solr.metrics.prometheus.jvm; + +public interface PrometheusJvmExporterInfo { + /** Category of prefix Solr JVM dropwizard handler metric names */ + enum JvmCategory { + buffers, + gc, + memory, + os, + threads, + classes, + system + } +} diff --git a/solr/core/src/java/org/apache/solr/metrics/prometheus/jvm/SolrJvmBuffersMetric.java b/solr/core/src/java/org/apache/solr/metrics/prometheus/jvm/SolrJvmBuffersMetric.java new file mode 100644 index 00000000000..060a40fca29 --- /dev/null +++ b/solr/core/src/java/org/apache/solr/metrics/prometheus/jvm/SolrJvmBuffersMetric.java @@ -0,0 +1,52 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.solr.metrics.prometheus.jvm; + +import com.codahale.metrics.Gauge; +import com.codahale.metrics.Metric; +import org.apache.solr.metrics.prometheus.SolrPrometheusExporter; + +/* Dropwizard metrics of name buffers.* */ +public class SolrJvmBuffersMetric extends SolrJvmMetric { + public static final String JVM_BUFFERS = "solr_metrics_jvm_buffers"; + public static final String JVM_BUFFERS_BYTES = "solr_metrics_jvm_buffers_bytes"; + + public SolrJvmBuffersMetric(Metric dropwizardMetric, String metricName) { + super(dropwizardMetric, metricName); + } + + @Override + public SolrJvmMetric parseLabels() { + String[] parsedMetric = metricName.split("\\."); + labels.put("pool", parsedMetric[1]); + labels.put("item", parsedMetric[2]); + return this; + } + + @Override + public void toPrometheus(SolrPrometheusExporter exporter) { + if (dropwizardMetric instanceof Gauge) { + String[] parsedMetric = metricName.split("\\."); + String metricType = parsedMetric[parsedMetric.length - 1]; + if (metricType.equals("Count")) { + exporter.exportGauge(JVM_BUFFERS, (Gauge) dropwizardMetric, getLabels()); + } else if (metricType.equals(("MemoryUsed")) || metricType.equals(("TotalCapacity"))) { + exporter.exportGauge(JVM_BUFFERS_BYTES, (Gauge) dropwizardMetric, getLabels()); + } + } + } +} diff --git a/solr/core/src/java/org/apache/solr/metrics/prometheus/jvm/SolrJvmGcMetrics.java b/solr/core/src/java/org/apache/solr/metrics/prometheus/jvm/SolrJvmGcMetrics.java new file mode 100644 index 00000000000..713214d12eb --- /dev/null +++ b/solr/core/src/java/org/apache/solr/metrics/prometheus/jvm/SolrJvmGcMetrics.java @@ -0,0 +1,49 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.solr.metrics.prometheus.jvm; + +import com.codahale.metrics.Gauge; +import com.codahale.metrics.Metric; +import org.apache.solr.metrics.prometheus.SolrMetric; +import org.apache.solr.metrics.prometheus.SolrPrometheusExporter; + +public class SolrJvmGcMetrics extends SolrJvmMetric { + public static String JVM_GC = "solr_metrics_jvm_gc"; + public static String JVM_GC_SECONDS = "solr_metrics_jvm_gc_seconds"; + + public SolrJvmGcMetrics(Metric dropwizardMetric, String metricName) { + super(dropwizardMetric, metricName); + } + + @Override + public SolrMetric parseLabels() { + String[] parsedMetric = metricName.split("\\."); + labels.put("item", parsedMetric[1]); + return this; + } + + @Override + public void toPrometheus(SolrPrometheusExporter exporter) { + if (dropwizardMetric instanceof Gauge) { + if (metricName.endsWith(".count")) { + exporter.exportGauge(JVM_GC, (Gauge) dropwizardMetric, getLabels()); + } else if (metricName.endsWith(".time")) { + exporter.exportGauge(JVM_GC_SECONDS, (Gauge) dropwizardMetric, getLabels()); + } + } + } +} diff --git a/solr/core/src/java/org/apache/solr/metrics/prometheus/jvm/SolrJvmMemoryMetric.java b/solr/core/src/java/org/apache/solr/metrics/prometheus/jvm/SolrJvmMemoryMetric.java new file mode 100644 index 00000000000..97554d86a4e --- /dev/null +++ b/solr/core/src/java/org/apache/solr/metrics/prometheus/jvm/SolrJvmMemoryMetric.java @@ -0,0 +1,59 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.solr.metrics.prometheus.jvm; + +import com.codahale.metrics.Gauge; +import com.codahale.metrics.Metric; +import org.apache.solr.metrics.prometheus.SolrMetric; +import org.apache.solr.metrics.prometheus.SolrPrometheusExporter; + +/* Dropwizard metrics of name gc.* and memory.* */ +public class SolrJvmMemoryMetric extends SolrJvmMetric { + public static String JVM_MEMORY_POOL_BYTES = "solr_metrics_jvm_memory_pools_bytes"; + public static String JVM_MEMORY = "solr_metrics_jvm_heap"; + + public SolrJvmMemoryMetric(Metric dropwizardMetric, String metricName) { + super(dropwizardMetric, metricName); + } + + @Override + public SolrMetric parseLabels() { + String[] parsedMetric = metricName.split("\\."); + labels.put("item", parsedMetric[parsedMetric.length - 1]); + return this; + } + + @Override + public void toPrometheus(SolrPrometheusExporter exporter) { + String[] parsedMetric = metricName.split("\\."); + if (dropwizardMetric instanceof Gauge) { + String metricType = parsedMetric[1]; + switch (metricType) { + case "heap": + case "non-heap": + case "total": + labels.put("memory", parsedMetric[1]); + exporter.exportGauge(JVM_MEMORY, (Gauge) dropwizardMetric, getLabels()); + break; + case "pools": + labels.put("space", parsedMetric[2]); + exporter.exportGauge(JVM_MEMORY_POOL_BYTES, (Gauge) dropwizardMetric, getLabels()); + break; + } + } + } +} diff --git a/solr/core/src/java/org/apache/solr/metrics/prometheus/jvm/SolrJvmMetric.java b/solr/core/src/java/org/apache/solr/metrics/prometheus/jvm/SolrJvmMetric.java new file mode 100644 index 00000000000..75541640488 --- /dev/null +++ b/solr/core/src/java/org/apache/solr/metrics/prometheus/jvm/SolrJvmMetric.java @@ -0,0 +1,27 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.solr.metrics.prometheus.jvm; + +import com.codahale.metrics.Metric; +import org.apache.solr.metrics.prometheus.SolrMetric; + +/** Base class is a wrapper to export a solr.jvm {@link com.codahale.metrics.Metric} */ +public abstract class SolrJvmMetric extends SolrMetric { + public SolrJvmMetric(Metric dropwizardMetric, String metricName) { + super(dropwizardMetric, metricName); + } +} diff --git a/solr/core/src/java/org/apache/solr/metrics/prometheus/jvm/SolrJvmOsMetric.java b/solr/core/src/java/org/apache/solr/metrics/prometheus/jvm/SolrJvmOsMetric.java new file mode 100644 index 00000000000..3c959cab959 --- /dev/null +++ b/solr/core/src/java/org/apache/solr/metrics/prometheus/jvm/SolrJvmOsMetric.java @@ -0,0 +1,58 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.solr.metrics.prometheus.jvm; + +import com.codahale.metrics.Gauge; +import com.codahale.metrics.Metric; +import org.apache.solr.metrics.prometheus.SolrMetric; +import org.apache.solr.metrics.prometheus.SolrPrometheusExporter; + +public class SolrJvmOsMetric extends SolrJvmMetric { + public static final String JVM_OS_THREADS = "solr_metrics_jvm_threads"; + public static final String JVM_OS = "solr_metrics_os"; + + /* Dropwizard metrics of name os.* and threads.* */ + public SolrJvmOsMetric(Metric dropwizardMetric, String metricName) { + super(dropwizardMetric, metricName); + } + + @Override + public SolrMetric parseLabels() { + String[] parsedMetric = metricName.split("\\."); + if (parsedMetric[0].equals("threads")) { + labels.put("item", parsedMetric[1]); + } else { + labels.put("item", parsedMetric[parsedMetric.length - 1]); + } + return this; + } + + @Override + public void toPrometheus(SolrPrometheusExporter exporter) { + String exportName = ""; + if (dropwizardMetric instanceof Gauge) { + if (metricName.startsWith("threads.")) { + exportName = JVM_OS_THREADS; + } else { + exportName = JVM_OS; + } + } + if (!exportName.isEmpty()) { + exporter.exportGauge(exportName, (Gauge) dropwizardMetric, getLabels()); + } + } +} diff --git a/solr/core/src/java/org/apache/solr/metrics/prometheus/jvm/SolrPrometheusJvmExporter.java b/solr/core/src/java/org/apache/solr/metrics/prometheus/jvm/SolrPrometheusJvmExporter.java new file mode 100644 index 00000000000..91a5ef07229 --- /dev/null +++ b/solr/core/src/java/org/apache/solr/metrics/prometheus/jvm/SolrPrometheusJvmExporter.java @@ -0,0 +1,61 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.solr.metrics.prometheus.jvm; + +import com.codahale.metrics.Metric; +import com.google.common.base.Enums; +import org.apache.solr.metrics.prometheus.SolrMetric; +import org.apache.solr.metrics.prometheus.SolrNoOpMetric; +import org.apache.solr.metrics.prometheus.SolrPrometheusExporter; + +/** + * This class maintains a {@link io.prometheus.metrics.model.snapshots.MetricSnapshot}s exported + * from solr.jvm {@link com.codahale.metrics.MetricRegistry} + */ +public class SolrPrometheusJvmExporter extends SolrPrometheusExporter + implements PrometheusJvmExporterInfo { + public SolrPrometheusJvmExporter() { + super(); + } + + @Override + public void exportDropwizardMetric(Metric dropwizardMetric, String metricName) { + SolrMetric solrJvmMetric = categorizeMetric(dropwizardMetric, metricName); + solrJvmMetric.parseLabels().toPrometheus(this); + } + + @Override + public SolrMetric categorizeMetric(Metric dropwizardMetric, String metricName) { + String metricCategory = metricName.split("\\.", 2)[0]; + if (!Enums.getIfPresent(JvmCategory.class, metricCategory).isPresent()) { + return new SolrNoOpMetric(); + } + switch (JvmCategory.valueOf(metricCategory)) { + case gc: + return new SolrJvmGcMetrics(dropwizardMetric, metricName); + case memory: + return new SolrJvmMemoryMetric(dropwizardMetric, metricName); + case os: + case threads: + return new SolrJvmOsMetric(dropwizardMetric, metricName); + case buffers: + return new SolrJvmBuffersMetric(dropwizardMetric, metricName); + default: + return new SolrNoOpMetric(); + } + } +} diff --git a/solr/core/src/java/org/apache/solr/metrics/prometheus/jvm/package-info.java b/solr/core/src/java/org/apache/solr/metrics/prometheus/jvm/package-info.java new file mode 100644 index 00000000000..230f9576576 --- /dev/null +++ b/solr/core/src/java/org/apache/solr/metrics/prometheus/jvm/package-info.java @@ -0,0 +1,22 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * The {@link org.apache.solr.metrics.prometheus.jvm.SolrPrometheusJvmExporter} is responsible for + * exporting solr.jvm registry metrics to Prometheus. + */ +package org.apache.solr.metrics.prometheus.jvm; diff --git a/solr/core/src/java/org/apache/solr/metrics/prometheus/node/PrometheusNodeExporterInfo.java b/solr/core/src/java/org/apache/solr/metrics/prometheus/node/PrometheusNodeExporterInfo.java new file mode 100644 index 00000000000..67caa63ef24 --- /dev/null +++ b/solr/core/src/java/org/apache/solr/metrics/prometheus/node/PrometheusNodeExporterInfo.java @@ -0,0 +1,27 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.solr.metrics.prometheus.node; + +public interface PrometheusNodeExporterInfo { + /** Category of prefix Solr Node dropwizard handler metric names */ + enum NodeCategory { + ADMIN, + UPDATE, + CONTAINER, + CACHE + } +} diff --git a/solr/core/src/java/org/apache/solr/metrics/prometheus/node/SolrNodeContainerMetric.java b/solr/core/src/java/org/apache/solr/metrics/prometheus/node/SolrNodeContainerMetric.java new file mode 100644 index 00000000000..dde32f6441a --- /dev/null +++ b/solr/core/src/java/org/apache/solr/metrics/prometheus/node/SolrNodeContainerMetric.java @@ -0,0 +1,53 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.solr.metrics.prometheus.node; + +import com.codahale.metrics.Gauge; +import com.codahale.metrics.Metric; +import org.apache.solr.metrics.prometheus.SolrMetric; +import org.apache.solr.metrics.prometheus.SolrPrometheusExporter; + +/* Dropwizard metrics of name CONTAINER.* */ +public class SolrNodeContainerMetric extends SolrNodeMetric { + public static final String NODE_CORES = "solr_metrics_node_cores"; + public static final String NODE_CORE_FS_BYTES = "solr_metrics_node_core_root_fs_bytes"; + + public SolrNodeContainerMetric(Metric dropwizardMetric, String metricName) { + super(dropwizardMetric, metricName); + } + + @Override + public SolrMetric parseLabels() { + String[] parsedMetric = metricName.split("\\."); + labels.put("category", parsedMetric[0]); + return this; + } + + @Override + public void toPrometheus(SolrPrometheusExporter exporter) { + String[] parsedMetric = metricName.split("\\."); + if (dropwizardMetric instanceof Gauge) { + if (metricName.startsWith("CONTAINER.cores.")) { + labels.put("item", parsedMetric[2]); + exporter.exportGauge(NODE_CORES, (Gauge) dropwizardMetric, getLabels()); + } else if (metricName.startsWith("CONTAINER.fs.coreRoot.")) { + labels.put("item", parsedMetric[3]); + exporter.exportGauge(NODE_CORE_FS_BYTES, (Gauge) dropwizardMetric, getLabels()); + } + } + } +} diff --git a/solr/core/src/java/org/apache/solr/metrics/prometheus/node/SolrNodeHandlerMetric.java b/solr/core/src/java/org/apache/solr/metrics/prometheus/node/SolrNodeHandlerMetric.java new file mode 100644 index 00000000000..f5804ea5726 --- /dev/null +++ b/solr/core/src/java/org/apache/solr/metrics/prometheus/node/SolrNodeHandlerMetric.java @@ -0,0 +1,64 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.solr.metrics.prometheus.node; + +import com.codahale.metrics.Counter; +import com.codahale.metrics.Gauge; +import com.codahale.metrics.Meter; +import com.codahale.metrics.Metric; +import org.apache.solr.metrics.prometheus.SolrMetric; +import org.apache.solr.metrics.prometheus.SolrPrometheusExporter; + +/* Dropwizard metrics of name ADMIN.* and UPDATE.* */ +public class SolrNodeHandlerMetric extends SolrNodeMetric { + public static final String NODE_REQUESTS = "solr_metrics_node_requests"; + public static final String NODE_SECONDS_TOTAL = "solr_metrics_node_requests_time"; + public static final String NODE_CONNECTIONS = "solr_metrics_node_connections"; + + public SolrNodeHandlerMetric(Metric dropwizardMetric, String metricName) { + super(dropwizardMetric, metricName); + } + + @Override + public SolrMetric parseLabels() { + String[] parsedMetric = metricName.split("\\."); + labels.put("category", parsedMetric[0]); + labels.put("handler", parsedMetric[1]); + labels.put("type", parsedMetric[2]); + return this; + } + + @Override + public void toPrometheus(SolrPrometheusExporter exporter) { + String[] parsedMetric = metricName.split("\\."); + if (dropwizardMetric instanceof Meter) { + exporter.exportMeter(NODE_REQUESTS, (Meter) dropwizardMetric, getLabels()); + } else if (dropwizardMetric instanceof Counter) { + if (metricName.endsWith(".requests")) { + exporter.exportCounter(NODE_REQUESTS, (Counter) dropwizardMetric, getLabels()); + } else if (metricName.endsWith(".totalTime")) { + // Do not need type label for total time + labels.remove("type"); + exporter.exportCounter(NODE_SECONDS_TOTAL, (Counter) dropwizardMetric, getLabels()); + } + } else if (dropwizardMetric instanceof Gauge) { + if (metricName.endsWith("Connections")) { + exporter.exportGauge(NODE_CONNECTIONS, (Gauge) dropwizardMetric, getLabels()); + } + } + } +} diff --git a/solr/core/src/java/org/apache/solr/metrics/prometheus/node/SolrNodeMetric.java b/solr/core/src/java/org/apache/solr/metrics/prometheus/node/SolrNodeMetric.java new file mode 100644 index 00000000000..34795e240de --- /dev/null +++ b/solr/core/src/java/org/apache/solr/metrics/prometheus/node/SolrNodeMetric.java @@ -0,0 +1,29 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.solr.metrics.prometheus.node; + +import com.codahale.metrics.Metric; +import org.apache.solr.metrics.prometheus.SolrMetric; + +/** Base class is a wrapper to export a solr.node {@link com.codahale.metrics.Metric} */ +public abstract class SolrNodeMetric extends SolrMetric { + public static final String NODE_THREAD_POOL = "solr_metrics_node_thread_pool"; + + public SolrNodeMetric(Metric dropwizardMetric, String metricName) { + super(dropwizardMetric, metricName); + } +} diff --git a/solr/core/src/java/org/apache/solr/metrics/prometheus/node/SolrPrometheusNodeExporter.java b/solr/core/src/java/org/apache/solr/metrics/prometheus/node/SolrPrometheusNodeExporter.java new file mode 100644 index 00000000000..ed4316efb97 --- /dev/null +++ b/solr/core/src/java/org/apache/solr/metrics/prometheus/node/SolrPrometheusNodeExporter.java @@ -0,0 +1,99 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.solr.metrics.prometheus.node; + +import static org.apache.solr.metrics.prometheus.node.SolrNodeMetric.NODE_THREAD_POOL; + +import com.codahale.metrics.Counter; +import com.codahale.metrics.Meter; +import com.codahale.metrics.Metric; +import com.google.common.base.Enums; +import io.prometheus.metrics.model.snapshots.Labels; +import org.apache.solr.metrics.prometheus.SolrMetric; +import org.apache.solr.metrics.prometheus.SolrNoOpMetric; +import org.apache.solr.metrics.prometheus.SolrPrometheusExporter; + +/** + * This class maintains a {@link io.prometheus.metrics.model.snapshots.MetricSnapshot}s exported + * from solr.node {@link com.codahale.metrics.MetricRegistry} + */ +public class SolrPrometheusNodeExporter extends SolrPrometheusExporter + implements PrometheusNodeExporterInfo { + public SolrPrometheusNodeExporter() { + super(); + } + + @Override + public void exportDropwizardMetric(Metric dropwizardMetric, String metricName) { + if (metricName.contains(".threadPool.")) { + exportThreadPoolMetric(dropwizardMetric, metricName); + return; + } + + SolrMetric solrNodeMetric = categorizeMetric(dropwizardMetric, metricName); + solrNodeMetric.parseLabels().toPrometheus(this); + } + + @Override + public SolrMetric categorizeMetric(Metric dropwizardMetric, String metricName) { + String metricCategory = metricName.split("\\.", 2)[0]; + if (!Enums.getIfPresent(PrometheusNodeExporterInfo.NodeCategory.class, metricCategory) + .isPresent()) { + return new SolrNoOpMetric(); + } + switch (NodeCategory.valueOf(metricCategory)) { + case ADMIN: + case UPDATE: + return new SolrNodeHandlerMetric(dropwizardMetric, metricName); + case CONTAINER: + return new SolrNodeContainerMetric(dropwizardMetric, metricName); + default: + return new SolrNoOpMetric(); + } + } + + private void exportThreadPoolMetric(Metric dropwizardMetric, String metricName) { + Labels labels; + String[] parsedMetric = metricName.split("\\."); + if (parsedMetric.length >= 5) { + labels = + Labels.of( + "category", + parsedMetric[0], + "handler", + parsedMetric[1], + "executer", + parsedMetric[3], + "task", + parsedMetric[parsedMetric.length - 1]); + } else { + labels = + Labels.of( + "category", + parsedMetric[0], + "executer", + parsedMetric[2], + "task", + parsedMetric[parsedMetric.length - 1]); + } + if (dropwizardMetric instanceof Counter) { + exportCounter(NODE_THREAD_POOL, (Counter) dropwizardMetric, labels); + } else if (dropwizardMetric instanceof Meter) { + exportMeter(NODE_THREAD_POOL, (Meter) dropwizardMetric, labels); + } + } +} diff --git a/solr/core/src/java/org/apache/solr/metrics/prometheus/node/package-info.java b/solr/core/src/java/org/apache/solr/metrics/prometheus/node/package-info.java new file mode 100644 index 00000000000..31ca46347d0 --- /dev/null +++ b/solr/core/src/java/org/apache/solr/metrics/prometheus/node/package-info.java @@ -0,0 +1,22 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * The {@link org.apache.solr.metrics.prometheus.node.SolrPrometheusNodeExporter} is responsible for + * exporting solr.node registry metrics to Prometheus. + */ +package org.apache.solr.metrics.prometheus.node; diff --git a/solr/core/src/java/org/apache/solr/metrics/prometheus/package-info.java b/solr/core/src/java/org/apache/solr/metrics/prometheus/package-info.java index 8702fc1aefb..33da9290400 100644 --- a/solr/core/src/java/org/apache/solr/metrics/prometheus/package-info.java +++ b/solr/core/src/java/org/apache/solr/metrics/prometheus/package-info.java @@ -18,6 +18,8 @@ /** * The {@link org.apache.solr.metrics.prometheus.SolrPrometheusExporter} is responsible for * collecting Prometheus metrics from exporting {@link com.codahale.metrics.Metric}'s from {@link - * com.codahale.metrics.MetricRegistry} + * com.codahale.metrics.MetricRegistry} {@link org.apache.solr.metrics.prometheus.SolrMetric} is a + * wrapper to export {@link com.codahale.metrics.Metric} to {@link + * io.prometheus.metrics.model.snapshots.DataPointSnapshot} */ package org.apache.solr.metrics.prometheus; diff --git a/solr/core/src/java/org/apache/solr/response/PrometheusResponseWriter.java b/solr/core/src/java/org/apache/solr/response/PrometheusResponseWriter.java index d496aa8c353..84a5b1f2f20 100644 --- a/solr/core/src/java/org/apache/solr/response/PrometheusResponseWriter.java +++ b/solr/core/src/java/org/apache/solr/response/PrometheusResponseWriter.java @@ -34,7 +34,11 @@ import java.util.stream.Collectors; import org.apache.solr.common.util.NamedList; import org.apache.solr.metrics.AggregateMetric; -import org.apache.solr.metrics.prometheus.SolrPrometheusCoreExporter; +import org.apache.solr.metrics.prometheus.SolrPrometheusExporter; +import org.apache.solr.metrics.prometheus.core.SolrPrometheusCoreExporter; +import org.apache.solr.metrics.prometheus.jetty.SolrPrometheusJettyExporter; +import org.apache.solr.metrics.prometheus.jvm.SolrPrometheusJvmExporter; +import org.apache.solr.metrics.prometheus.node.SolrPrometheusNodeExporter; import org.apache.solr.request.SolrQueryRequest; import org.apache.solr.util.stats.MetricUtils; import org.slf4j.Logger; @@ -55,7 +59,7 @@ public void write(OutputStream out, SolrQueryRequest request, SolrQueryResponse (NamedList) response.getValues().get("metrics"); var prometheusTextFormatWriter = new PrometheusTextFormatWriter(false); for (Map.Entry prometheusRegistry : prometheusRegistries) { - var prometheusExporter = (SolrPrometheusCoreExporter) prometheusRegistry.getValue(); + var prometheusExporter = (SolrPrometheusExporter) prometheusRegistry.getValue(); prometheusTextFormatWriter.write(out, prometheusExporter.collect()); } } @@ -85,24 +89,13 @@ public static void toPrometheus( boolean skipHistograms, boolean skipAggregateValues, boolean compact, - Consumer consumer) { - String coreName; - boolean cloudMode = false; + Consumer consumer) { Map dropwizardMetrics = registry.getMetrics(); - String[] rawParsedRegistry = registryName.split("\\."); - List parsedRegistry = new ArrayList<>(Arrays.asList(rawParsedRegistry)); - - if (parsedRegistry.size() == 3) { - coreName = parsedRegistry.get(2); - } else if (parsedRegistry.size() == 5) { - coreName = parsedRegistry.stream().skip(1).collect(Collectors.joining("_")); - cloudMode = true; - } else { - coreName = registryName; + var exporter = getExporterType(registryName); + if (exporter == null) { + return; } - var solrPrometheusCoreExporter = new SolrPrometheusCoreExporter(coreName, cloudMode); - MetricUtils.toMaps( registry, shouldMatchFilters, @@ -115,13 +108,41 @@ public static void toPrometheus( (metricName, metric) -> { try { Metric dropwizardMetric = dropwizardMetrics.get(metricName); - solrPrometheusCoreExporter.exportDropwizardMetric(dropwizardMetric, metricName); + exporter.exportDropwizardMetric(dropwizardMetric, metricName); } catch (Exception e) { // Do not fail entirely for metrics exporting. Log and try to export next metric log.warn("Error occurred exporting Dropwizard Metric to Prometheus", e); } }); - consumer.accept(solrPrometheusCoreExporter); + consumer.accept(exporter); + } + + public static SolrPrometheusExporter getExporterType(String registryName) { + String coreName; + boolean cloudMode = false; + String[] rawParsedRegistry = registryName.split("\\."); + List parsedRegistry = new ArrayList<>(Arrays.asList(rawParsedRegistry)); + + switch (parsedRegistry.get(1)) { + case ("core"): + if (parsedRegistry.size() == 3) { + coreName = parsedRegistry.get(2); + } else if (parsedRegistry.size() == 5) { + coreName = parsedRegistry.stream().skip(1).collect(Collectors.joining("_")); + cloudMode = true; + } else { + coreName = registryName; + } + return new SolrPrometheusCoreExporter(coreName, cloudMode); + case ("jvm"): + return new SolrPrometheusJvmExporter(); + case ("jetty"): + return new SolrPrometheusJettyExporter(); + case ("node"): + return new SolrPrometheusNodeExporter(); + default: + return null; + } } } diff --git a/solr/core/src/test/org/apache/solr/handler/admin/MetricsHandlerTest.java b/solr/core/src/test/org/apache/solr/handler/admin/MetricsHandlerTest.java index 44ab23a7542..af053cb2bc8 100644 --- a/solr/core/src/test/org/apache/solr/handler/admin/MetricsHandlerTest.java +++ b/solr/core/src/test/org/apache/solr/handler/admin/MetricsHandlerTest.java @@ -18,6 +18,8 @@ package org.apache.solr.handler.admin; import com.codahale.metrics.Counter; +import com.codahale.metrics.Gauge; +import com.codahale.metrics.SettableGauge; import io.prometheus.metrics.model.snapshots.CounterSnapshot; import io.prometheus.metrics.model.snapshots.GaugeSnapshot; import io.prometheus.metrics.model.snapshots.Labels; @@ -26,7 +28,6 @@ import java.util.Arrays; import java.util.HashMap; import java.util.Map; -import java.util.Optional; import org.apache.solr.SolrTestCaseJ4; import org.apache.solr.common.MapWriter; import org.apache.solr.common.params.CommonParams; @@ -37,6 +38,7 @@ import org.apache.solr.core.SolrCore; import org.apache.solr.handler.RequestHandlerBase; import org.apache.solr.metrics.MetricsMap; +import org.apache.solr.metrics.SolrMetricManager; import org.apache.solr.metrics.SolrMetricsContext; import org.apache.solr.metrics.prometheus.SolrPrometheusExporter; import org.apache.solr.request.SolrQueryRequest; @@ -64,6 +66,26 @@ public static void beforeClass() throws Exception { // test escapes c = h.getCoreContainer().getMetricManager().counter(null, "solr.jetty", "solrtest_foo:bar"); c.inc(3); + + // Manually register for Prometheus exporter tests + registerGauge("solr.jvm", "gc.G1-Old-Generation.count"); + registerGauge("solr.jvm", "gc.G1-Old-Generation.time"); + registerGauge("solr.jvm", "memory.heap.committed"); + registerGauge("solr.jvm", "memory.pools.CodeHeap-'non-nmethods'.committed"); + registerGauge("solr.jvm", "threads.count"); + registerGauge("solr.jvm", "os.availableProcessors"); + registerGauge("solr.jvm", "buffers.direct.Count"); + registerGauge("solr.jvm", "buffers.direct.MemoryUsed"); + h.getCoreContainer() + .getMetricManager() + .meter(null, "solr.jetty", "org.eclipse.jetty.server.handler.DefaultHandler.2xx-responses"); + h.getCoreContainer() + .getMetricManager() + .counter( + null, "solr.jetty", "org.eclipse.jetty.server.handler.DefaultHandler.active-requests"); + h.getCoreContainer() + .getMetricManager() + .timer(null, "solr.jetty", "org.eclipse.jetty.server.handler.DefaultHandler.dispatches"); } @AfterClass @@ -686,7 +708,7 @@ public void testExprMetrics() throws Exception { @Test @SuppressWarnings("unchecked") - public void testPrometheusMetrics() throws Exception { + public void testPrometheusMetricsCore() throws Exception { MetricsHandler handler = new MetricsHandler(h.getCoreContainer()); SolrQueryResponse resp = new SolrQueryResponse(); @@ -708,199 +730,272 @@ public void testPrometheusMetrics() throws Exception { MetricSnapshots actualSnapshots = exporter.collect(); assertNotNull(actualSnapshots); - Optional actualSnapshot = - actualSnapshots.stream() - .filter( - ss -> - ss.getMetadata() - .getPrometheusName() - .equals("solr_metrics_core_average_request_time")) - .findAny(); - assertTrue(actualSnapshot.isPresent()); - Optional actualGaugeDataPoint = - (Optional) - actualSnapshot.get().getDataPoints().stream() - .filter( - ss -> - ss.getLabels() - .hasSameValues( - Labels.of( - "category", - "QUERY", - "core", - "collection1", - "handler", - "/select[shard]"))) - .findAny(); - assertTrue(actualGaugeDataPoint.isPresent()); - assertEquals(0, actualGaugeDataPoint.get().getValue(), 0); + MetricSnapshot actualSnapshot = + getMetricSnapshot(actualSnapshots, "solr_metrics_core_average_request_time"); + GaugeSnapshot.GaugeDataPointSnapshot actualGaugeDataPoint = + getGaugeDatapointSnapshot( + actualSnapshot, + Labels.of("category", "QUERY", "core", "collection1", "handler", "/select[shard]")); + assertEquals(0, actualGaugeDataPoint.getValue(), 0); + + actualSnapshot = getMetricSnapshot(actualSnapshots, "solr_metrics_core_requests"); + CounterSnapshot.CounterDataPointSnapshot actualCounterDataPoint = + getCounterDatapointSnapshot( + actualSnapshot, + Labels.of( + "category", + "QUERY", + "core", + "collection1", + "handler", + "/select[shard]", + "type", + "requests")); + assertEquals(0, actualCounterDataPoint.getValue(), 0); + + actualSnapshot = getMetricSnapshot(actualSnapshots, "solr_metrics_core_cache"); + actualGaugeDataPoint = + getGaugeDatapointSnapshot( + actualSnapshot, + Labels.of("cacheType", "fieldValueCache", "core", "collection1", "item", "hits")); + assertEquals(0, actualGaugeDataPoint.getValue(), 0); - actualSnapshot = - actualSnapshots.stream() - .filter(ss -> ss.getMetadata().getPrometheusName().equals("solr_metrics_core_requests")) - .findAny(); - assertTrue(actualSnapshot.isPresent()); - Optional actualCounterDataPoint = - (Optional) - actualSnapshot.get().getDataPoints().stream() - .filter( - ss -> - ss.getLabels() - .hasSameValues( - Labels.of( - "category", - "QUERY", - "core", - "collection1", - "handler", - "/select[shard]", - "type", - "requests"))) - .findAny(); - assertTrue(actualCounterDataPoint.isPresent()); - assertEquals(0, actualCounterDataPoint.get().getValue(), 0); + actualSnapshot = getMetricSnapshot(actualSnapshots, "solr_metrics_core_highlighter_requests"); + actualCounterDataPoint = + getCounterDatapointSnapshot( + actualSnapshot, + Labels.of("item", "default", "core", "collection1", "type", "SolrFragmenter")); + assertEquals(0, actualCounterDataPoint.getValue(), 0); - actualSnapshot = - actualSnapshots.stream() - .filter(ss -> ss.getMetadata().getPrometheusName().equals("solr_metrics_core_cache")) - .findAny(); - assertTrue(actualSnapshot.isPresent()); + actualSnapshot = getMetricSnapshot(actualSnapshots, "solr_metrics_core_requests_time"); + actualCounterDataPoint = + getCounterDatapointSnapshot( + actualSnapshot, + Labels.of("category", "QUERY", "core", "collection1", "handler", "/select[shard]")); + assertEquals(0, actualCounterDataPoint.getValue(), 0); + + actualSnapshot = getMetricSnapshot(actualSnapshots, "solr_metrics_core_searcher_documents"); actualGaugeDataPoint = - (Optional) - actualSnapshot.get().getDataPoints().stream() - .filter( - ss -> - ss.getLabels() - .hasSameValues( - Labels.of( - "cacheType", - "fieldValueCache", - "core", - "collection1", - "item", - "hits"))) - .findAny(); - assertTrue(actualGaugeDataPoint.isPresent()); - assertEquals(0, actualGaugeDataPoint.get().getValue(), 0); + getGaugeDatapointSnapshot( + actualSnapshot, Labels.of("core", "collection1", "type", "numDocs")); + assertEquals(0, actualGaugeDataPoint.getValue(), 0); + + actualSnapshot = getMetricSnapshot(actualSnapshots, "solr_metrics_core_update_handler"); + actualGaugeDataPoint = + getGaugeDatapointSnapshot( + actualSnapshot, + Labels.of( + "category", + "UPDATE", + "core", + "collection1", + "type", + "adds", + "handler", + "updateHandler")); + assertEquals(0, actualGaugeDataPoint.getValue(), 0); actualSnapshot = - actualSnapshots.stream() - .filter( - ss -> - ss.getMetadata() - .getPrometheusName() - .equals("solr_metrics_core_highlighter_requests")) - .findAny(); - assertTrue(actualSnapshot.isPresent()); + getMetricSnapshot(actualSnapshots, "solr_metrics_core_average_searcher_warmup_time"); + actualGaugeDataPoint = + getGaugeDatapointSnapshot( + actualSnapshot, Labels.of("core", "collection1", "type", "warmup")); + assertEquals(0, actualGaugeDataPoint.getValue(), 0); + + handler.close(); + } + + @Test + @SuppressWarnings("unchecked") + public void testPrometheusMetricsNode() throws Exception { + MetricsHandler handler = new MetricsHandler(h.getCoreContainer()); + + SolrQueryResponse resp = new SolrQueryResponse(); + handler.handleRequestBody( + req( + CommonParams.QT, + "/admin/metrics", + MetricsHandler.COMPACT_PARAM, + "false", + CommonParams.WT, + "prometheus"), + resp); + + NamedList values = resp.getValues(); + assertNotNull(values.get("metrics")); + values = (NamedList) values.get("metrics"); + SolrPrometheusExporter exporter = (SolrPrometheusExporter) values.get("solr.node"); + assertNotNull(exporter); + MetricSnapshots actualSnapshots = exporter.collect(); + assertNotNull(actualSnapshots); + + MetricSnapshot actualSnapshot = + getMetricSnapshot(actualSnapshots, "solr_metrics_node_requests"); + + CounterSnapshot.CounterDataPointSnapshot actualCounterDataPoint = + getCounterDatapointSnapshot( + actualSnapshot, + Labels.of("category", "ADMIN", "handler", "/admin/info", "type", "requests")); + assertEquals(0, actualCounterDataPoint.getValue(), 0); + + actualSnapshot = getMetricSnapshot(actualSnapshots, "solr_metrics_node_requests_time"); actualCounterDataPoint = - (Optional) - actualSnapshot.get().getDataPoints().stream() - .filter( - ss -> - ss.getLabels() - .hasSameValues( - Labels.of( - "item", - "default", - "core", - "collection1", - "type", - "SolrFragmenter"))) - .findAny(); - assertTrue(actualCounterDataPoint.isPresent()); - assertEquals(0, actualCounterDataPoint.get().getValue(), 0); + getCounterDatapointSnapshot( + actualSnapshot, Labels.of("category", "ADMIN", "handler", "/admin/info")); + assertEquals(0, actualCounterDataPoint.getValue(), 0); - actualSnapshot = - actualSnapshots.stream() - .filter( - ss -> - ss.getMetadata().getPrometheusName().equals("solr_metrics_core_requests_time")) - .findAny(); - assertTrue(actualSnapshot.isPresent()); + actualSnapshot = getMetricSnapshot(actualSnapshots, "solr_metrics_node_thread_pool"); actualCounterDataPoint = - (Optional) - actualSnapshot.get().getDataPoints().stream() - .filter( - ss -> - ss.getLabels() - .hasSameValues( - Labels.of( - "category", - "QUERY", - "core", - "collection1", - "handler", - "/select[shard]"))) - .findAny(); - assertTrue(actualCounterDataPoint.isPresent()); - assertEquals(0, actualCounterDataPoint.get().getValue(), 0); + getCounterDatapointSnapshot( + actualSnapshot, + Labels.of( + "category", + "ADMIN", + "executer", + "parallelCoreAdminExecutor", + "handler", + "/admin/cores", + "task", + "completed")); + assertEquals(0, actualCounterDataPoint.getValue(), 0); + + actualSnapshot = getMetricSnapshot(actualSnapshots, "solr_metrics_node_connections"); + GaugeSnapshot.GaugeDataPointSnapshot actualGaugeDataPoint = + getGaugeDatapointSnapshot( + actualSnapshot, + Labels.of( + "category", + "UPDATE", + "handler", + "updateShardHandler", + "item", + "availableConnections")); + assertEquals(0, actualGaugeDataPoint.getValue(), 0); + + actualSnapshot = getMetricSnapshot(actualSnapshots, "solr_metrics_node_core_root_fs_bytes"); + actualGaugeDataPoint = + getGaugeDatapointSnapshot( + actualSnapshot, Labels.of("category", "CONTAINER", "item", "totalSpace")); + assertNotNull(actualGaugeDataPoint); - actualSnapshot = - actualSnapshots.stream() - .filter( - ss -> - ss.getMetadata() - .getPrometheusName() - .equals("solr_metrics_core_searcher_documents")) - .findAny(); - assertTrue(actualSnapshot.isPresent()); + actualSnapshot = getMetricSnapshot(actualSnapshots, "solr_metrics_node_cores"); actualGaugeDataPoint = - (Optional) - actualSnapshot.get().getDataPoints().stream() - .filter( - ss -> - ss.getLabels() - .hasSameValues(Labels.of("core", "collection1", "type", "numDocs"))) - .findAny(); - assertTrue(actualGaugeDataPoint.isPresent()); - assertEquals(0, actualGaugeDataPoint.get().getValue(), 0); + getGaugeDatapointSnapshot( + actualSnapshot, Labels.of("category", "CONTAINER", "item", "lazy")); + assertEquals(0, actualGaugeDataPoint.getValue(), 0); - actualSnapshot = - actualSnapshots.stream() - .filter( - ss -> - ss.getMetadata().getPrometheusName().equals("solr_metrics_core_update_handler")) - .findAny(); - assertTrue(actualSnapshot.isPresent()); + handler.close(); + } + + @Test + @SuppressWarnings("unchecked") + public void testPrometheusMetricsJvm() throws Exception { + MetricsHandler handler = new MetricsHandler(h.getCoreContainer()); + + SolrQueryResponse resp = new SolrQueryResponse(); + handler.handleRequestBody( + req( + CommonParams.QT, + "/admin/metrics", + MetricsHandler.COMPACT_PARAM, + "false", + CommonParams.WT, + "prometheus"), + resp); + + NamedList values = resp.getValues(); + assertNotNull(values.get("metrics")); + values = (NamedList) values.get("metrics"); + SolrPrometheusExporter exporter = (SolrPrometheusExporter) values.get("solr.jvm"); + assertNotNull(exporter); + MetricSnapshots actualSnapshots = exporter.collect(); + assertNotNull(actualSnapshots); + + MetricSnapshot actualSnapshot = getMetricSnapshot(actualSnapshots, "solr_metrics_jvm_gc"); + GaugeSnapshot.GaugeDataPointSnapshot actualGaugeDataPoint = + getGaugeDatapointSnapshot(actualSnapshot, Labels.of("item", "G1-Old-Generation")); + assertEquals(0, actualGaugeDataPoint.getValue(), 0); + + actualSnapshot = getMetricSnapshot(actualSnapshots, "solr_metrics_jvm_threads"); + actualGaugeDataPoint = getGaugeDatapointSnapshot(actualSnapshot, Labels.of("item", "count")); + assertNotNull(actualGaugeDataPoint); + + actualSnapshot = getMetricSnapshot(actualSnapshots, "solr_metrics_jvm_memory_pools_bytes"); actualGaugeDataPoint = - (Optional) - actualSnapshot.get().getDataPoints().stream() - .filter( - ss -> - ss.getLabels() - .hasSameValues( - Labels.of( - "category", - "UPDATE", - "core", - "collection1", - "type", - "adds", - "handler", - "updateHandler"))) - .findAny(); - assertTrue(actualGaugeDataPoint.isPresent()); - assertEquals(0, actualGaugeDataPoint.get().getValue(), 0); + getGaugeDatapointSnapshot( + actualSnapshot, Labels.of("item", "committed", "space", "CodeHeap-'non-nmethods'")); + assertEquals(0, actualGaugeDataPoint.getValue(), 0); - actualSnapshot = - actualSnapshots.stream() - .filter( - ss -> - ss.getMetadata() - .getPrometheusName() - .equals("solr_metrics_core_average_searcher_warmup_time")) - .findAny(); - assertTrue(actualSnapshot.isPresent()); + actualSnapshot = getMetricSnapshot(actualSnapshots, "solr_metrics_os"); + actualGaugeDataPoint = + getGaugeDatapointSnapshot(actualSnapshot, Labels.of("item", "availableProcessors")); + assertEquals(0, actualGaugeDataPoint.getValue(), 0); + + actualSnapshot = getMetricSnapshot(actualSnapshots, "solr_metrics_jvm_buffers"); actualGaugeDataPoint = - (Optional) - actualSnapshot.get().getDataPoints().stream() - .filter( - ss -> - ss.getLabels() - .hasSameValues(Labels.of("core", "collection1", "type", "warmup"))) - .findAny(); - assertTrue(actualGaugeDataPoint.isPresent()); - assertEquals(0, actualGaugeDataPoint.get().getValue(), 0); + getGaugeDatapointSnapshot(actualSnapshot, Labels.of("item", "Count", "pool", "direct")); + assertEquals(0, actualGaugeDataPoint.getValue(), 0); + + actualSnapshot = getMetricSnapshot(actualSnapshots, "solr_metrics_jvm_heap"); + actualSnapshots.stream() + .filter(ss -> ss.getMetadata().getPrometheusName().equals("solr_metrics_jvm_heap")) + .findAny(); + actualGaugeDataPoint = + getGaugeDatapointSnapshot(actualSnapshot, Labels.of("item", "committed", "memory", "heap")); + assertEquals(0, actualGaugeDataPoint.getValue(), 0); + + actualSnapshot = getMetricSnapshot(actualSnapshots, "solr_metrics_jvm_buffers_bytes"); + actualGaugeDataPoint = + getGaugeDatapointSnapshot( + actualSnapshot, Labels.of("item", "MemoryUsed", "pool", "direct")); + assertEquals(0, actualGaugeDataPoint.getValue(), 0); + + actualSnapshot = getMetricSnapshot(actualSnapshots, "solr_metrics_jvm_gc_seconds"); + actualGaugeDataPoint = + getGaugeDatapointSnapshot(actualSnapshot, Labels.of("item", "G1-Old-Generation")); + assertEquals(0, actualGaugeDataPoint.getValue(), 0); + + handler.close(); + } + + @Test + @SuppressWarnings("unchecked") + public void testPrometheusMetricsJetty() throws Exception { + MetricsHandler handler = new MetricsHandler(h.getCoreContainer()); + + SolrQueryResponse resp = new SolrQueryResponse(); + handler.handleRequestBody( + req( + CommonParams.QT, + "/admin/metrics", + MetricsHandler.COMPACT_PARAM, + "false", + CommonParams.WT, + "prometheus"), + resp); + + NamedList values = resp.getValues(); + assertNotNull(values.get("metrics")); + values = (NamedList) values.get("metrics"); + SolrPrometheusExporter exporter = (SolrPrometheusExporter) values.get("solr.jetty"); + assertNotNull(exporter); + MetricSnapshots actualSnapshots = exporter.collect(); + assertNotNull(actualSnapshots); + + MetricSnapshot actualSnapshot = + getMetricSnapshot(actualSnapshots, "solr_metrics_jetty_response"); + CounterSnapshot.CounterDataPointSnapshot actualCounterDatapoint = + getCounterDatapointSnapshot(actualSnapshot, Labels.of("status", "2xx")); + assertEquals(0, actualCounterDatapoint.getValue(), 0); + + actualSnapshot = getMetricSnapshot(actualSnapshots, "solr_metrics_jetty_requests"); + actualCounterDatapoint = + getCounterDatapointSnapshot(actualSnapshot, Labels.of("method", "active")); + assertEquals(0, actualCounterDatapoint.getValue(), 0); + + actualSnapshot = getMetricSnapshot(actualSnapshots, "solr_metrics_jetty_dispatches"); + actualCounterDatapoint = getCounterDatapointSnapshot(actualSnapshot, Labels.of()); + assertEquals(0, actualCounterDatapoint.getValue(), 0); handler.close(); } @@ -1015,6 +1110,54 @@ public void testMetricsUnload() throws Exception { handler.close(); } + public static void registerGauge(String registry, String metricName) { + Gauge metric = + new SettableGauge<>() { + @Override + public void setValue(Number value) {} + + @Override + public Number getValue() { + return 0; + } + }; + h.getCoreContainer() + .getMetricManager() + .registerGauge( + null, + registry, + metric, + "", + SolrMetricManager.ResolutionStrategy.IGNORE, + metricName, + ""); + } + + private MetricSnapshot getMetricSnapshot(MetricSnapshots snapshots, String metricName) { + return snapshots.stream() + .filter(ss -> ss.getMetadata().getPrometheusName().equals(metricName)) + .findAny() + .get(); + } + + private GaugeSnapshot.GaugeDataPointSnapshot getGaugeDatapointSnapshot( + MetricSnapshot snapshot, Labels labels) { + return (GaugeSnapshot.GaugeDataPointSnapshot) + snapshot.getDataPoints().stream() + .filter(ss -> ss.getLabels().hasSameValues(labels)) + .findAny() + .get(); + } + + private CounterSnapshot.CounterDataPointSnapshot getCounterDatapointSnapshot( + MetricSnapshot snapshot, Labels labels) { + return (CounterSnapshot.CounterDataPointSnapshot) + snapshot.getDataPoints().stream() + .filter(ss -> ss.getLabels().hasSameValues(labels)) + .findAny() + .get(); + } + static class RefreshablePluginHolder extends PluginBag.PluginHolder { private DumpRequestHandler rh; diff --git a/solr/core/src/test/org/apache/solr/metrics/SolrCoreMetricTest.java b/solr/core/src/test/org/apache/solr/metrics/SolrCoreMetricTest.java index c904d4a99a0..3a8b6e58cd7 100644 --- a/solr/core/src/test/org/apache/solr/metrics/SolrCoreMetricTest.java +++ b/solr/core/src/test/org/apache/solr/metrics/SolrCoreMetricTest.java @@ -19,7 +19,7 @@ import com.codahale.metrics.Metric; import io.prometheus.metrics.model.snapshots.Labels; import org.apache.solr.SolrTestCaseJ4; -import org.apache.solr.metrics.prometheus.SolrPrometheusCoreExporter; +import org.apache.solr.metrics.prometheus.SolrPrometheusExporter; import org.apache.solr.metrics.prometheus.core.SolrCoreMetric; import org.junit.Test; @@ -76,6 +76,6 @@ public SolrCoreMetric parseLabels() { } @Override - public void toPrometheus(SolrPrometheusCoreExporter exporter) {} + public void toPrometheus(SolrPrometheusExporter exporter) {} } } diff --git a/solr/core/src/test/org/apache/solr/metrics/SolrPrometheusExporterTest.java b/solr/core/src/test/org/apache/solr/metrics/SolrPrometheusExporterTest.java index f0759c8fb75..445e02f326f 100644 --- a/solr/core/src/test/org/apache/solr/metrics/SolrPrometheusExporterTest.java +++ b/solr/core/src/test/org/apache/solr/metrics/SolrPrometheusExporterTest.java @@ -30,6 +30,7 @@ import java.util.Map; import java.util.concurrent.TimeUnit; import org.apache.solr.SolrTestCaseJ4; +import org.apache.solr.metrics.prometheus.SolrMetric; import org.apache.solr.metrics.prometheus.SolrPrometheusExporter; import org.junit.Test; @@ -144,6 +145,11 @@ static class TestSolrPrometheusExporter extends SolrPrometheusExporter { @Override public void exportDropwizardMetric(Metric dropwizardMetric, String metricName) {} + @Override + public SolrMetric categorizeMetric(Metric dropwizardMetric, String metricName) { + return null; + } + public Map> getMetricCounters() { return metricCounters; } diff --git a/solr/core/src/test/org/apache/solr/response/TestPrometheusResponseWriter.java b/solr/core/src/test/org/apache/solr/response/TestPrometheusResponseWriter.java index 26b3a6d356f..6154f9ed51f 100644 --- a/solr/core/src/test/org/apache/solr/response/TestPrometheusResponseWriter.java +++ b/solr/core/src/test/org/apache/solr/response/TestPrometheusResponseWriter.java @@ -25,7 +25,7 @@ import org.apache.solr.SolrTestCaseJ4; import org.apache.solr.common.util.NamedList; import org.apache.solr.common.util.SimpleOrderedMap; -import org.apache.solr.metrics.prometheus.SolrPrometheusCoreExporter; +import org.apache.solr.metrics.prometheus.core.SolrPrometheusCoreExporter; import org.apache.solr.request.SolrQueryRequest; import org.junit.BeforeClass; import org.junit.Test; From 060bb59ebddea4bb502f7afca7f305e7e658bf2b Mon Sep 17 00:00:00 2001 From: mbiscocho Date: Tue, 11 Jun 2024 13:32:01 -0400 Subject: [PATCH 21/32] Update broken tests --- .../solr/metrics/prometheus/SolrPrometheusExporter.java | 2 +- .../org/apache/solr/handler/admin/MetricsHandlerTest.java | 5 +---- 2 files changed, 2 insertions(+), 5 deletions(-) diff --git a/solr/core/src/java/org/apache/solr/metrics/prometheus/SolrPrometheusExporter.java b/solr/core/src/java/org/apache/solr/metrics/prometheus/SolrPrometheusExporter.java index fd4a2cafa74..6fbb4c0d8ed 100644 --- a/solr/core/src/java/org/apache/solr/metrics/prometheus/SolrPrometheusExporter.java +++ b/solr/core/src/java/org/apache/solr/metrics/prometheus/SolrPrometheusExporter.java @@ -118,7 +118,7 @@ public void exportTimer(String metricName, Timer dropwizardMetric, Labels labels */ public void exportTimerCount(String metricName, Timer dropwizardMetric, Labels labels) { CounterSnapshot.CounterDataPointSnapshot dataPoint = - createCounterDatapoint(dropwizardMetric.getCount(), labels); + createCounterDatapoint((double) dropwizardMetric.getCount(), labels); collectCounterDatapoint(metricName, dataPoint); } diff --git a/solr/core/src/test/org/apache/solr/handler/admin/MetricsHandlerTest.java b/solr/core/src/test/org/apache/solr/handler/admin/MetricsHandlerTest.java index af053cb2bc8..a7585938e0d 100644 --- a/solr/core/src/test/org/apache/solr/handler/admin/MetricsHandlerTest.java +++ b/solr/core/src/test/org/apache/solr/handler/admin/MetricsHandlerTest.java @@ -929,7 +929,7 @@ public void testPrometheusMetricsJvm() throws Exception { actualSnapshot = getMetricSnapshot(actualSnapshots, "solr_metrics_os"); actualGaugeDataPoint = getGaugeDatapointSnapshot(actualSnapshot, Labels.of("item", "availableProcessors")); - assertEquals(0, actualGaugeDataPoint.getValue(), 0); + assertNotNull(actualGaugeDataPoint); actualSnapshot = getMetricSnapshot(actualSnapshots, "solr_metrics_jvm_buffers"); actualGaugeDataPoint = @@ -937,9 +937,6 @@ public void testPrometheusMetricsJvm() throws Exception { assertEquals(0, actualGaugeDataPoint.getValue(), 0); actualSnapshot = getMetricSnapshot(actualSnapshots, "solr_metrics_jvm_heap"); - actualSnapshots.stream() - .filter(ss -> ss.getMetadata().getPrometheusName().equals("solr_metrics_jvm_heap")) - .findAny(); actualGaugeDataPoint = getGaugeDatapointSnapshot(actualSnapshot, Labels.of("item", "committed", "memory", "heap")); assertEquals(0, actualGaugeDataPoint.getValue(), 0); From 7359d7ce279fe544869fcb97200085e757bea002 Mon Sep 17 00:00:00 2001 From: mbiscocho Date: Tue, 11 Jun 2024 14:52:25 -0400 Subject: [PATCH 22/32] Update ref-guide with Prometheus metrics endpoint --- .../pages/metrics-reporting.adoc | 2 +- ...onitoring-with-prometheus-and-grafana.adoc | 41 ++++++++++++++++--- 2 files changed, 37 insertions(+), 6 deletions(-) diff --git a/solr/solr-ref-guide/modules/deployment-guide/pages/metrics-reporting.adoc b/solr/solr-ref-guide/modules/deployment-guide/pages/metrics-reporting.adoc index 75ce4974118..9da3960b1cd 100644 --- a/solr/solr-ref-guide/modules/deployment-guide/pages/metrics-reporting.adoc +++ b/solr/solr-ref-guide/modules/deployment-guide/pages/metrics-reporting.adoc @@ -879,7 +879,7 @@ The response will look like this: ]} ---- -Like other request handlers, the Metrics API can also take the `wt` parameter to define the output format. +Like other request handlers, the Metrics API can also take the `wt` parameter to define the output format. The Metrics API also provides an additional special `wt` parameter `prometheus` that will output metrics in Prometheus format. This can be used for xref:monitoring-with-prometheus-and-grafana.adoc#prometheus-metrics-api[Monitoring with Prometheus and Grafana] [[metrics_examples]] === Examples diff --git a/solr/solr-ref-guide/modules/deployment-guide/pages/monitoring-with-prometheus-and-grafana.adoc b/solr/solr-ref-guide/modules/deployment-guide/pages/monitoring-with-prometheus-and-grafana.adoc index 3e484647c5d..bb6b41dff85 100644 --- a/solr/solr-ref-guide/modules/deployment-guide/pages/monitoring-with-prometheus-and-grafana.adoc +++ b/solr/solr-ref-guide/modules/deployment-guide/pages/monitoring-with-prometheus-and-grafana.adoc @@ -16,13 +16,20 @@ // specific language governing permissions and limitations // under the License. -If you use https://prometheus.io[Prometheus] and https://grafana.com[Grafana] for metrics storage and data visualization, Solr includes a Prometheus exporter to collect metrics and other data. +If you use https://prometheus.io[Prometheus] and https://grafana.com[Grafana] for metrics storage and data visualization, Solr provides 2 solutions to collect metrics and other data: + +* Prometheus Exporter +* Prometheus Metrics API endpoint The Prometheus exporter is included with the full Solr distribution, and is located under `prometheus-exporter/`. It is not included in the `slim` Solr distribution. A Prometheus exporter (`solr-exporter`) allows users to monitor not only Solr metrics which come from the xref:metrics-reporting.adoc#metrics-api[Metrics API], but also facet counts which come from xref:query-guide:faceting.adoc[] and responses to xref:configuration-guide:collections-api.adoc[] commands and xref:ping.adoc[] requests. +The Metrics API provides a Prometheus Response Writer to output Solr metrics natively to be scraped. It is more efficient and drops the need of running the Prometheus Exporter but at the cost of a fixed output and not as flexiable in terms of configurability. + +== Prometheus Exporter + This graphic provides a more detailed view: .solr-exporter Diagram @@ -37,7 +44,7 @@ See the section below <>. * Modify your Prometheus configuration to listen on the correct port. See the section below <> -== Starting the Exporter +=== Starting the Exporter You can start `solr-exporter` by running `./bin/solr-exporter` (Linux) or `.\bin\solr-exporter.cmd` (Windows) from the `prometheus-exporter/` directory. The metrics exposed by `solr-exporter` can be seen at the metrics endpoint: `\http://localhost:8983/solr/admin/metrics`. @@ -274,7 +281,7 @@ NOTE:: The Exporter needs the `commons-codec` library for SSL/BasicAuth, but doe Therefore the example reuses it from the Solr web app. Of course, you can use a different source. -== Exporter Configuration +=== Exporter Configuration The configuration for the `solr-exporter` defines the data to get from Solr. This includes the metrics, but can also include queries to the PingRequestHandler, the Collections API, and a query to any query request handler. @@ -547,7 +554,7 @@ For example, `solr-exporter` converts the JSON in the previous section to the fo solr_ping{base_url="http://localhost:8983/solr",core="collection1"} 1.0 ---- -== Prometheus Configuration +=== Prometheus Configuration Prometheus is a separate server that you need to download and deploy. More information can be found at the Prometheus https://prometheus.io/docs/prometheus/latest/getting_started/[Getting Started] page. @@ -572,7 +579,7 @@ doing a query for `solr_ping` metric in the Prometheus GUI: .Prometheus Solr Ping expression image::monitoring-with-prometheus-and-grafana/prometheus-solr-ping.png[image,width=800] -== Sample Grafana Dashboard +=== Sample Grafana Dashboard To use Grafana for visualization, it must be downloaded and deployed separately. More information can be found on the Grafana https://grafana.com/docs/grafana/latest/[Documentation] site. @@ -587,3 +594,27 @@ This screenshot shows what it might look like: .Grafana Dashboard image::monitoring-with-prometheus-and-grafana/grafana-solr-dashboard.png[image,width=800] + +== Prometheus Metrics API + +Prometheus Metrics are available natively directly from Solr by leveraging the Metrics API and setting `wt` parameter to `prometheus`: + +[source,text] +localhost:8983/solr/admin/metrics?wt=prometheus + +The Prometheus Metrics API does not provide any configurability and the Prometheus output is fixed. Any metrics aggregations and/or filtering must be done on Grafana or the Prometheus server. + +=== Prometheus Configuration + +Like the Prometheus Exporter, the `prometheus.yml` needs to be configurated for the Prometheus Server to ingest metrics. The difference is it must instead scrape the Metrics API with the `wt=prometheus` parameter directly from each host/port Solr is running on as in this example: + +[source,plain] +---- +scrape_configs: + - job_name: 'solr' + metrics_path: "/solr/admin/metrics" + static_configs: + - targets: ['localhost:8983', 'localhost:7574'] + params: + wt: ['prometheus'] +---- From 835c946ecac04900f840ccd25cf278a6a6a2aef4 Mon Sep 17 00:00:00 2001 From: mbiscocho Date: Wed, 12 Jun 2024 10:48:39 -0400 Subject: [PATCH 23/32] Change test assertion for metrics affected by testing environment --- .../org/apache/solr/handler/admin/MetricsHandlerTest.java | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/solr/core/src/test/org/apache/solr/handler/admin/MetricsHandlerTest.java b/solr/core/src/test/org/apache/solr/handler/admin/MetricsHandlerTest.java index a7585938e0d..d8a5cdf1cd9 100644 --- a/solr/core/src/test/org/apache/solr/handler/admin/MetricsHandlerTest.java +++ b/solr/core/src/test/org/apache/solr/handler/admin/MetricsHandlerTest.java @@ -890,6 +890,8 @@ public void testPrometheusMetricsNode() throws Exception { @Test @SuppressWarnings("unchecked") public void testPrometheusMetricsJvm() throws Exception { + // Some JVM metrics are non-deterministic due to testing environment such as + // availableProcessors. We confirm snapshot exists and is nonNull instead. MetricsHandler handler = new MetricsHandler(h.getCoreContainer()); SolrQueryResponse resp = new SolrQueryResponse(); @@ -934,18 +936,18 @@ public void testPrometheusMetricsJvm() throws Exception { actualSnapshot = getMetricSnapshot(actualSnapshots, "solr_metrics_jvm_buffers"); actualGaugeDataPoint = getGaugeDatapointSnapshot(actualSnapshot, Labels.of("item", "Count", "pool", "direct")); - assertEquals(0, actualGaugeDataPoint.getValue(), 0); + assertNotNull(actualGaugeDataPoint); actualSnapshot = getMetricSnapshot(actualSnapshots, "solr_metrics_jvm_heap"); actualGaugeDataPoint = getGaugeDatapointSnapshot(actualSnapshot, Labels.of("item", "committed", "memory", "heap")); - assertEquals(0, actualGaugeDataPoint.getValue(), 0); + assertNotNull(actualGaugeDataPoint); actualSnapshot = getMetricSnapshot(actualSnapshots, "solr_metrics_jvm_buffers_bytes"); actualGaugeDataPoint = getGaugeDatapointSnapshot( actualSnapshot, Labels.of("item", "MemoryUsed", "pool", "direct")); - assertEquals(0, actualGaugeDataPoint.getValue(), 0); + assertNotNull(actualGaugeDataPoint); actualSnapshot = getMetricSnapshot(actualSnapshots, "solr_metrics_jvm_gc_seconds"); actualGaugeDataPoint = From 6cce9723e21d54d661a53c8e0dfedaf598416002 Mon Sep 17 00:00:00 2001 From: mbiscocho Date: Tue, 18 Jun 2024 11:08:41 -0400 Subject: [PATCH 24/32] Add additional java docs and integration test --- .../solr/metrics/prometheus/SolrMetric.java | 6 + .../prometheus/core/SolrCoreCacheMetric.java | 4 + .../core/SolrCoreHandlerMetric.java | 7 + .../core/SolrCoreHighlighterMetric.java | 5 + .../prometheus/core/SolrCoreIndexMetric.java | 4 + .../core/SolrCoreSearcherMetric.java | 5 + .../prometheus/core/SolrCoreTlogMetric.java | 4 + .../jetty/SolrJettyDispatchesMetric.java | 4 + .../jetty/SolrJettyReqRespMetric.java | 7 +- .../prometheus/jvm/SolrJvmBuffersMetric.java | 5 + .../prometheus/jvm/SolrJvmGcMetrics.java | 10 +- .../prometheus/jvm/SolrJvmMemoryMetric.java | 13 +- .../prometheus/jvm/SolrJvmOsMetric.java | 7 +- .../node/SolrNodeContainerMetric.java | 5 + .../node/SolrNodeHandlerMetric.java | 6 +- .../node/SolrPrometheusNodeExporter.java | 5 + .../response/PrometheusResponseWriter.java | 22 +- .../solr/solr-prometheus-output.txt | 452 ++++++++++++++++++ .../TestPrometheusResponseWriter.java | 51 +- .../pages/metrics-reporting.adoc | 2 +- ...onitoring-with-prometheus-and-grafana.adoc | 6 +- 21 files changed, 582 insertions(+), 48 deletions(-) create mode 100644 solr/core/src/test-files/solr/solr-prometheus-output.txt diff --git a/solr/core/src/java/org/apache/solr/metrics/prometheus/SolrMetric.java b/solr/core/src/java/org/apache/solr/metrics/prometheus/SolrMetric.java index 59bbfadd4bb..4668e615c85 100644 --- a/solr/core/src/java/org/apache/solr/metrics/prometheus/SolrMetric.java +++ b/solr/core/src/java/org/apache/solr/metrics/prometheus/SolrMetric.java @@ -41,8 +41,14 @@ public SolrMetric(Metric dropwizardMetric, String metricName) { this.metricName = metricName; } + /* + * Parse labels from the Dropwizard Metric name to be exported + */ public abstract SolrMetric parseLabels(); + /* + * Export metric to Prometheus with labels + */ public abstract void toPrometheus(SolrPrometheusExporter exporter); public Labels getLabels() { diff --git a/solr/core/src/java/org/apache/solr/metrics/prometheus/core/SolrCoreCacheMetric.java b/solr/core/src/java/org/apache/solr/metrics/prometheus/core/SolrCoreCacheMetric.java index 587939655c0..d5b646061e6 100644 --- a/solr/core/src/java/org/apache/solr/metrics/prometheus/core/SolrCoreCacheMetric.java +++ b/solr/core/src/java/org/apache/solr/metrics/prometheus/core/SolrCoreCacheMetric.java @@ -38,6 +38,10 @@ public SolrCoreMetric parseLabels() { return this; } + /* + * Metric examples being exported + * CACHE.searcher.documentCache + */ @Override public void toPrometheus(SolrPrometheusExporter exporter) { if (dropwizardMetric instanceof Gauge) { diff --git a/solr/core/src/java/org/apache/solr/metrics/prometheus/core/SolrCoreHandlerMetric.java b/solr/core/src/java/org/apache/solr/metrics/prometheus/core/SolrCoreHandlerMetric.java index e8bf725edb2..7546662b8cf 100644 --- a/solr/core/src/java/org/apache/solr/metrics/prometheus/core/SolrCoreHandlerMetric.java +++ b/solr/core/src/java/org/apache/solr/metrics/prometheus/core/SolrCoreHandlerMetric.java @@ -44,6 +44,13 @@ public SolrCoreMetric parseLabels() { return this; } + /* + * Metric examples being exported + * QUERY./select.requests + * QUERY./select.totalTime + * UPDATE./update.requests + * UPDATE./update.totalTime + */ @Override public void toPrometheus(SolrPrometheusExporter exporter) { if (dropwizardMetric instanceof Meter) { diff --git a/solr/core/src/java/org/apache/solr/metrics/prometheus/core/SolrCoreHighlighterMetric.java b/solr/core/src/java/org/apache/solr/metrics/prometheus/core/SolrCoreHighlighterMetric.java index a1cf3128aae..208d96babba 100644 --- a/solr/core/src/java/org/apache/solr/metrics/prometheus/core/SolrCoreHighlighterMetric.java +++ b/solr/core/src/java/org/apache/solr/metrics/prometheus/core/SolrCoreHighlighterMetric.java @@ -37,6 +37,11 @@ public SolrCoreMetric parseLabels() { return this; } + /* + * Metric examples being exported + * HIGHLIGHTER.SolrBoundaryScanner.default.requests + * HIGHLIGHTER.SolrFragmentsBuilder.colored.requests + */ @Override public void toPrometheus(SolrPrometheusExporter exporter) { if (dropwizardMetric instanceof Counter) { diff --git a/solr/core/src/java/org/apache/solr/metrics/prometheus/core/SolrCoreIndexMetric.java b/solr/core/src/java/org/apache/solr/metrics/prometheus/core/SolrCoreIndexMetric.java index e0d43e5aa9d..239e4f528bb 100644 --- a/solr/core/src/java/org/apache/solr/metrics/prometheus/core/SolrCoreIndexMetric.java +++ b/solr/core/src/java/org/apache/solr/metrics/prometheus/core/SolrCoreIndexMetric.java @@ -34,6 +34,10 @@ public SolrCoreMetric parseLabels() { return this; } + /* + * Metric examples being exported + * INDEX.sizeInBytes + */ @Override public void toPrometheus(SolrPrometheusExporter exporter) { if (dropwizardMetric instanceof Gauge) { diff --git a/solr/core/src/java/org/apache/solr/metrics/prometheus/core/SolrCoreSearcherMetric.java b/solr/core/src/java/org/apache/solr/metrics/prometheus/core/SolrCoreSearcherMetric.java index 470fae35081..fbc098fe612 100644 --- a/solr/core/src/java/org/apache/solr/metrics/prometheus/core/SolrCoreSearcherMetric.java +++ b/solr/core/src/java/org/apache/solr/metrics/prometheus/core/SolrCoreSearcherMetric.java @@ -43,6 +43,11 @@ public SolrCoreMetric parseLabels() { return this; } + /* + * Metric examples being exported + * SEARCHER.searcher.deletedDocs + * SEARCHER.new.time + */ @Override public void toPrometheus(SolrPrometheusExporter exporter) { if (dropwizardMetric instanceof Gauge) { diff --git a/solr/core/src/java/org/apache/solr/metrics/prometheus/core/SolrCoreTlogMetric.java b/solr/core/src/java/org/apache/solr/metrics/prometheus/core/SolrCoreTlogMetric.java index 80aab10df9f..b7d3ba2706d 100644 --- a/solr/core/src/java/org/apache/solr/metrics/prometheus/core/SolrCoreTlogMetric.java +++ b/solr/core/src/java/org/apache/solr/metrics/prometheus/core/SolrCoreTlogMetric.java @@ -38,6 +38,10 @@ public SolrCoreMetric parseLabels() { return this; } + /* + * Metric examples being exported + * TLOG.buffered.ops + */ @Override public void toPrometheus(SolrPrometheusExporter exporter) { if (dropwizardMetric instanceof Meter) { diff --git a/solr/core/src/java/org/apache/solr/metrics/prometheus/jetty/SolrJettyDispatchesMetric.java b/solr/core/src/java/org/apache/solr/metrics/prometheus/jetty/SolrJettyDispatchesMetric.java index b4fbd90890e..42f6af74f7f 100644 --- a/solr/core/src/java/org/apache/solr/metrics/prometheus/jetty/SolrJettyDispatchesMetric.java +++ b/solr/core/src/java/org/apache/solr/metrics/prometheus/jetty/SolrJettyDispatchesMetric.java @@ -34,6 +34,10 @@ public SolrMetric parseLabels() { return this; } + /* + * Metric examples being exported + * org.eclipse.jetty.server.handler.DefaultHandler.dispatches + */ @Override public void toPrometheus(SolrPrometheusExporter exporter) { if (dropwizardMetric instanceof Timer) { diff --git a/solr/core/src/java/org/apache/solr/metrics/prometheus/jetty/SolrJettyReqRespMetric.java b/solr/core/src/java/org/apache/solr/metrics/prometheus/jetty/SolrJettyReqRespMetric.java index f5c7a165ed4..3326d30bce3 100644 --- a/solr/core/src/java/org/apache/solr/metrics/prometheus/jetty/SolrJettyReqRespMetric.java +++ b/solr/core/src/java/org/apache/solr/metrics/prometheus/jetty/SolrJettyReqRespMetric.java @@ -23,7 +23,7 @@ import org.apache.solr.metrics.prometheus.SolrMetric; import org.apache.solr.metrics.prometheus.SolrPrometheusExporter; -/* Dropwizard metrics of name requests and responses */ +/* Dropwizard metrics of name *.xx-responses and *-requests */ public class SolrJettyReqRespMetric extends SolrJettyMetric { public static final String JETTY_RESPONSES_TOTAL = "solr_metrics_jetty_response"; public static final String JETTY_REQUESTS_TOTAL = "solr_metrics_jetty_requests"; @@ -44,6 +44,11 @@ public SolrMetric parseLabels() { return this; } + /* + * Metric examples being exported + * org.eclipse.jetty.server.handler.DefaultHandler.2xx-responses + * org.eclipse.jetty.server.handler.DefaultHandler.get-requests + */ @Override public void toPrometheus(SolrPrometheusExporter exporter) { if (dropwizardMetric instanceof Meter) { diff --git a/solr/core/src/java/org/apache/solr/metrics/prometheus/jvm/SolrJvmBuffersMetric.java b/solr/core/src/java/org/apache/solr/metrics/prometheus/jvm/SolrJvmBuffersMetric.java index 060a40fca29..3758f63b6e0 100644 --- a/solr/core/src/java/org/apache/solr/metrics/prometheus/jvm/SolrJvmBuffersMetric.java +++ b/solr/core/src/java/org/apache/solr/metrics/prometheus/jvm/SolrJvmBuffersMetric.java @@ -37,6 +37,11 @@ public SolrJvmMetric parseLabels() { return this; } + /* + * Metric examples being exported + * buffers.direct.MemoryUsed + * buffers.mapped.Count + */ @Override public void toPrometheus(SolrPrometheusExporter exporter) { if (dropwizardMetric instanceof Gauge) { diff --git a/solr/core/src/java/org/apache/solr/metrics/prometheus/jvm/SolrJvmGcMetrics.java b/solr/core/src/java/org/apache/solr/metrics/prometheus/jvm/SolrJvmGcMetrics.java index 713214d12eb..79ad2ca2777 100644 --- a/solr/core/src/java/org/apache/solr/metrics/prometheus/jvm/SolrJvmGcMetrics.java +++ b/solr/core/src/java/org/apache/solr/metrics/prometheus/jvm/SolrJvmGcMetrics.java @@ -21,9 +21,10 @@ import org.apache.solr.metrics.prometheus.SolrMetric; import org.apache.solr.metrics.prometheus.SolrPrometheusExporter; +/* Dropwizard metrics of name gc.* */ public class SolrJvmGcMetrics extends SolrJvmMetric { - public static String JVM_GC = "solr_metrics_jvm_gc"; - public static String JVM_GC_SECONDS = "solr_metrics_jvm_gc_seconds"; + public static final String JVM_GC = "solr_metrics_jvm_gc"; + public static final String JVM_GC_SECONDS = "solr_metrics_jvm_gc_seconds"; public SolrJvmGcMetrics(Metric dropwizardMetric, String metricName) { super(dropwizardMetric, metricName); @@ -36,6 +37,11 @@ public SolrMetric parseLabels() { return this; } + /* + * Metric examples being exported + * gc.G1-Old-Generation.time + * gc.G1-Young-Generation.count + */ @Override public void toPrometheus(SolrPrometheusExporter exporter) { if (dropwizardMetric instanceof Gauge) { diff --git a/solr/core/src/java/org/apache/solr/metrics/prometheus/jvm/SolrJvmMemoryMetric.java b/solr/core/src/java/org/apache/solr/metrics/prometheus/jvm/SolrJvmMemoryMetric.java index 97554d86a4e..3ac189117dc 100644 --- a/solr/core/src/java/org/apache/solr/metrics/prometheus/jvm/SolrJvmMemoryMetric.java +++ b/solr/core/src/java/org/apache/solr/metrics/prometheus/jvm/SolrJvmMemoryMetric.java @@ -21,10 +21,10 @@ import org.apache.solr.metrics.prometheus.SolrMetric; import org.apache.solr.metrics.prometheus.SolrPrometheusExporter; -/* Dropwizard metrics of name gc.* and memory.* */ +/* Dropwizard metrics of name memory.* */ public class SolrJvmMemoryMetric extends SolrJvmMetric { - public static String JVM_MEMORY_POOL_BYTES = "solr_metrics_jvm_memory_pools_bytes"; - public static String JVM_MEMORY = "solr_metrics_jvm_heap"; + public static final String JVM_MEMORY_POOL_BYTES = "solr_metrics_jvm_memory_pools_bytes"; + public static final String JVM_MEMORY = "solr_metrics_jvm_heap"; public SolrJvmMemoryMetric(Metric dropwizardMetric, String metricName) { super(dropwizardMetric, metricName); @@ -37,6 +37,13 @@ public SolrMetric parseLabels() { return this; } + /* + * Metric examples being exported + * memory.heap.usage + * memory.non-heap.committed + * memory.total.committed + * memory.pools.CodeHeap-'non-nmethods'.committed + */ @Override public void toPrometheus(SolrPrometheusExporter exporter) { String[] parsedMetric = metricName.split("\\."); diff --git a/solr/core/src/java/org/apache/solr/metrics/prometheus/jvm/SolrJvmOsMetric.java b/solr/core/src/java/org/apache/solr/metrics/prometheus/jvm/SolrJvmOsMetric.java index 3c959cab959..407a2fc3b3d 100644 --- a/solr/core/src/java/org/apache/solr/metrics/prometheus/jvm/SolrJvmOsMetric.java +++ b/solr/core/src/java/org/apache/solr/metrics/prometheus/jvm/SolrJvmOsMetric.java @@ -21,11 +21,11 @@ import org.apache.solr.metrics.prometheus.SolrMetric; import org.apache.solr.metrics.prometheus.SolrPrometheusExporter; +/* Dropwizard metrics of name os.* and threads.* */ public class SolrJvmOsMetric extends SolrJvmMetric { public static final String JVM_OS_THREADS = "solr_metrics_jvm_threads"; public static final String JVM_OS = "solr_metrics_os"; - /* Dropwizard metrics of name os.* and threads.* */ public SolrJvmOsMetric(Metric dropwizardMetric, String metricName) { super(dropwizardMetric, metricName); } @@ -41,6 +41,11 @@ public SolrMetric parseLabels() { return this; } + /* + * Metric examples being exported + * os.availableProcessors + * threads.peak.count + */ @Override public void toPrometheus(SolrPrometheusExporter exporter) { String exportName = ""; diff --git a/solr/core/src/java/org/apache/solr/metrics/prometheus/node/SolrNodeContainerMetric.java b/solr/core/src/java/org/apache/solr/metrics/prometheus/node/SolrNodeContainerMetric.java index dde32f6441a..10eb64d0539 100644 --- a/solr/core/src/java/org/apache/solr/metrics/prometheus/node/SolrNodeContainerMetric.java +++ b/solr/core/src/java/org/apache/solr/metrics/prometheus/node/SolrNodeContainerMetric.java @@ -37,6 +37,11 @@ public SolrMetric parseLabels() { return this; } + /* + * Metric examples being exported + * CONTAINER.fs.coreRoot.totalSpace + * CONTAINER.cores.loaded + */ @Override public void toPrometheus(SolrPrometheusExporter exporter) { String[] parsedMetric = metricName.split("\\."); diff --git a/solr/core/src/java/org/apache/solr/metrics/prometheus/node/SolrNodeHandlerMetric.java b/solr/core/src/java/org/apache/solr/metrics/prometheus/node/SolrNodeHandlerMetric.java index f5804ea5726..0cfd37bcc76 100644 --- a/solr/core/src/java/org/apache/solr/metrics/prometheus/node/SolrNodeHandlerMetric.java +++ b/solr/core/src/java/org/apache/solr/metrics/prometheus/node/SolrNodeHandlerMetric.java @@ -42,9 +42,13 @@ public SolrMetric parseLabels() { return this; } + /* + * Metric examples being exported + * ADMIN./admin/collections.requests + * UPDATE.updateShardHandler.maxConnections + */ @Override public void toPrometheus(SolrPrometheusExporter exporter) { - String[] parsedMetric = metricName.split("\\."); if (dropwizardMetric instanceof Meter) { exporter.exportMeter(NODE_REQUESTS, (Meter) dropwizardMetric, getLabels()); } else if (dropwizardMetric instanceof Counter) { diff --git a/solr/core/src/java/org/apache/solr/metrics/prometheus/node/SolrPrometheusNodeExporter.java b/solr/core/src/java/org/apache/solr/metrics/prometheus/node/SolrPrometheusNodeExporter.java index ed4316efb97..40a76bfd85c 100644 --- a/solr/core/src/java/org/apache/solr/metrics/prometheus/node/SolrPrometheusNodeExporter.java +++ b/solr/core/src/java/org/apache/solr/metrics/prometheus/node/SolrPrometheusNodeExporter.java @@ -66,6 +66,11 @@ public SolrMetric categorizeMetric(Metric dropwizardMetric, String metricName) { } } + /* + * Metric examples being exported + * ADMIN./admin/cores.threadPool.parallelCoreAdminExecutor.completed + * CONTAINER.threadPool.coreContainerWorkExecutor.completed + */ private void exportThreadPoolMetric(Metric dropwizardMetric, String metricName) { Labels labels; String[] parsedMetric = metricName.split("\\."); diff --git a/solr/core/src/java/org/apache/solr/response/PrometheusResponseWriter.java b/solr/core/src/java/org/apache/solr/response/PrometheusResponseWriter.java index 84a5b1f2f20..e67b20a0007 100644 --- a/solr/core/src/java/org/apache/solr/response/PrometheusResponseWriter.java +++ b/solr/core/src/java/org/apache/solr/response/PrometheusResponseWriter.java @@ -25,7 +25,6 @@ import java.io.IOException; import java.io.OutputStream; import java.lang.invoke.MethodHandles; -import java.util.ArrayList; import java.util.Arrays; import java.util.List; import java.util.Map; @@ -121,25 +120,24 @@ public static void toPrometheus( public static SolrPrometheusExporter getExporterType(String registryName) { String coreName; boolean cloudMode = false; - String[] rawParsedRegistry = registryName.split("\\."); - List parsedRegistry = new ArrayList<>(Arrays.asList(rawParsedRegistry)); + String[] parsedRegistry = registryName.split("\\."); - switch (parsedRegistry.get(1)) { - case ("core"): - if (parsedRegistry.size() == 3) { - coreName = parsedRegistry.get(2); - } else if (parsedRegistry.size() == 5) { - coreName = parsedRegistry.stream().skip(1).collect(Collectors.joining("_")); + switch (parsedRegistry[1]) { + case "core": + if (parsedRegistry.length == 3) { + coreName = parsedRegistry[2]; + } else if (parsedRegistry.length == 5) { + coreName = Arrays.stream(parsedRegistry).skip(1).collect(Collectors.joining("_")); cloudMode = true; } else { coreName = registryName; } return new SolrPrometheusCoreExporter(coreName, cloudMode); - case ("jvm"): + case "jvm": return new SolrPrometheusJvmExporter(); - case ("jetty"): + case "jetty": return new SolrPrometheusJettyExporter(); - case ("node"): + case "node": return new SolrPrometheusNodeExporter(); default: return null; diff --git a/solr/core/src/test-files/solr/solr-prometheus-output.txt b/solr/core/src/test-files/solr/solr-prometheus-output.txt new file mode 100644 index 00000000000..be6144a3f40 --- /dev/null +++ b/solr/core/src/test-files/solr/solr-prometheus-output.txt @@ -0,0 +1,452 @@ +# TYPE solr_metrics_jvm_buffers gauge +solr_metrics_jvm_buffers{item="Count",pool="direct"} +solr_metrics_jvm_buffers{item="Count",pool="mapped"} +solr_metrics_jvm_buffers{item="Count",pool="mapped - 'non-volatile memory'"} +# TYPE solr_metrics_jvm_buffers_bytes gauge +solr_metrics_jvm_buffers_bytes{item="MemoryUsed",pool="direct"} +solr_metrics_jvm_buffers_bytes{item="MemoryUsed",pool="mapped"} +solr_metrics_jvm_buffers_bytes{item="MemoryUsed",pool="mapped - 'non-volatile memory'"} +solr_metrics_jvm_buffers_bytes{item="TotalCapacity",pool="direct"} +solr_metrics_jvm_buffers_bytes{item="TotalCapacity",pool="mapped"} +solr_metrics_jvm_buffers_bytes{item="TotalCapacity",pool="mapped - 'non-volatile memory'"} +# TYPE solr_metrics_jvm_gc gauge +solr_metrics_jvm_gc{item="PS-MarkSweep"} +solr_metrics_jvm_gc{item="PS-Scavenge"} +# TYPE solr_metrics_jvm_gc_seconds gauge +solr_metrics_jvm_gc_seconds{item="PS-MarkSweep"} +solr_metrics_jvm_gc_seconds{item="PS-Scavenge"} +# TYPE solr_metrics_jvm_heap gauge +solr_metrics_jvm_heap{item="committed",memory="heap"} +solr_metrics_jvm_heap{item="committed",memory="non-heap"} +solr_metrics_jvm_heap{item="committed",memory="total"} +solr_metrics_jvm_heap{item="init",memory="heap"} +solr_metrics_jvm_heap{item="init",memory="non-heap"} +solr_metrics_jvm_heap{item="init",memory="total"} +solr_metrics_jvm_heap{item="max",memory="heap"} +solr_metrics_jvm_heap{item="max",memory="non-heap"} +solr_metrics_jvm_heap{item="max",memory="total"} +solr_metrics_jvm_heap{item="usage",memory="heap"} +solr_metrics_jvm_heap{item="usage",memory="non-heap"} +solr_metrics_jvm_heap{item="used",memory="heap"} +solr_metrics_jvm_heap{item="used",memory="non-heap"} +solr_metrics_jvm_heap{item="used",memory="total"} +# TYPE solr_metrics_jvm_memory_pools_bytes gauge +solr_metrics_jvm_memory_pools_bytes{item="committed",space="CodeCache"} +solr_metrics_jvm_memory_pools_bytes{item="committed",space="Compressed-Class-Space"} +solr_metrics_jvm_memory_pools_bytes{item="committed",space="Metaspace"} +solr_metrics_jvm_memory_pools_bytes{item="committed",space="PS-Eden-Space"} +solr_metrics_jvm_memory_pools_bytes{item="committed",space="PS-Old-Gen"} +solr_metrics_jvm_memory_pools_bytes{item="committed",space="PS-Survivor-Space"} +solr_metrics_jvm_memory_pools_bytes{item="init",space="CodeCache"} +solr_metrics_jvm_memory_pools_bytes{item="init",space="Compressed-Class-Space"} +solr_metrics_jvm_memory_pools_bytes{item="init",space="Metaspace"} +solr_metrics_jvm_memory_pools_bytes{item="init",space="PS-Eden-Space"} +solr_metrics_jvm_memory_pools_bytes{item="init",space="PS-Old-Gen"} +solr_metrics_jvm_memory_pools_bytes{item="init",space="PS-Survivor-Space"} +solr_metrics_jvm_memory_pools_bytes{item="max",space="CodeCache"} +solr_metrics_jvm_memory_pools_bytes{item="max",space="Compressed-Class-Space"} +solr_metrics_jvm_memory_pools_bytes{item="max",space="Metaspace"} +solr_metrics_jvm_memory_pools_bytes{item="max",space="PS-Eden-Space"} +solr_metrics_jvm_memory_pools_bytes{item="max",space="PS-Old-Gen"} +solr_metrics_jvm_memory_pools_bytes{item="max",space="PS-Survivor-Space"} +solr_metrics_jvm_memory_pools_bytes{item="usage",space="CodeCache"} +solr_metrics_jvm_memory_pools_bytes{item="usage",space="Compressed-Class-Space"} +solr_metrics_jvm_memory_pools_bytes{item="usage",space="Metaspace"} +solr_metrics_jvm_memory_pools_bytes{item="usage",space="PS-Eden-Space"} +solr_metrics_jvm_memory_pools_bytes{item="usage",space="PS-Old-Gen"} +solr_metrics_jvm_memory_pools_bytes{item="usage",space="PS-Survivor-Space"} +solr_metrics_jvm_memory_pools_bytes{item="used",space="CodeCache"} +solr_metrics_jvm_memory_pools_bytes{item="used",space="Compressed-Class-Space"} +solr_metrics_jvm_memory_pools_bytes{item="used",space="Metaspace"} +solr_metrics_jvm_memory_pools_bytes{item="used",space="PS-Eden-Space"} +solr_metrics_jvm_memory_pools_bytes{item="used",space="PS-Old-Gen"} +solr_metrics_jvm_memory_pools_bytes{item="used",space="PS-Survivor-Space"} +solr_metrics_jvm_memory_pools_bytes{item="used-after-gc",space="PS-Eden-Space"} +solr_metrics_jvm_memory_pools_bytes{item="used-after-gc",space="PS-Old-Gen"} +solr_metrics_jvm_memory_pools_bytes{item="used-after-gc",space="PS-Survivor-Space"} +# TYPE solr_metrics_jvm_threads gauge +solr_metrics_jvm_threads{item="blocked"} +solr_metrics_jvm_threads{item="count"} +solr_metrics_jvm_threads{item="daemon"} +solr_metrics_jvm_threads{item="deadlock"} +solr_metrics_jvm_threads{item="new"} +solr_metrics_jvm_threads{item="peak"} +solr_metrics_jvm_threads{item="runnable"} +solr_metrics_jvm_threads{item="terminated"} +solr_metrics_jvm_threads{item="timed_waiting"} +solr_metrics_jvm_threads{item="total_started"} +solr_metrics_jvm_threads{item="waiting"} +# TYPE solr_metrics_os gauge +solr_metrics_os{item="availableProcessors"} +solr_metrics_os{item="committedVirtualMemorySize"} +solr_metrics_os{item="cpuLoad"} +solr_metrics_os{item="freeMemorySize"} +solr_metrics_os{item="freePhysicalMemorySize"} +solr_metrics_os{item="freeSwapSpaceSize"} +solr_metrics_os{item="maxFileDescriptorCount"} +solr_metrics_os{item="openFileDescriptorCount"} +solr_metrics_os{item="processCpuLoad"} +solr_metrics_os{item="processCpuTime"} +solr_metrics_os{item="systemCpuLoad"} +solr_metrics_os{item="systemLoadAverage"} +solr_metrics_os{item="totalMemorySize"} +solr_metrics_os{item="totalPhysicalMemorySize"} +solr_metrics_os{item="totalSwapSpaceSize"} +# TYPE solr_metrics_node_connections gauge +solr_metrics_node_connections{category="UPDATE",handler="updateShardHandler",type="availableConnections"} +solr_metrics_node_connections{category="UPDATE",handler="updateShardHandler",type="leasedConnections"} +solr_metrics_node_connections{category="UPDATE",handler="updateShardHandler",type="maxConnections"} +solr_metrics_node_connections{category="UPDATE",handler="updateShardHandler",type="pendingConnections"} +# TYPE solr_metrics_node_core_root_fs_bytes gauge +solr_metrics_node_core_root_fs_bytes{category="CONTAINER",item="totalSpace"} +solr_metrics_node_core_root_fs_bytes{category="CONTAINER",item="usableSpace"} +# TYPE solr_metrics_node_cores gauge +solr_metrics_node_cores{category="CONTAINER",item="lazy"} +solr_metrics_node_cores{category="CONTAINER",item="loaded"} +solr_metrics_node_cores{category="CONTAINER",item="unloaded"} +# TYPE solr_metrics_node_requests_total counter +solr_metrics_node_requests_total{category="ADMIN",handler="/admin/authorization",type="clientErrors"} +solr_metrics_node_requests_total{category="ADMIN",handler="/admin/authorization",type="errors"} +solr_metrics_node_requests_total{category="ADMIN",handler="/admin/authorization",type="requests"} +solr_metrics_node_requests_total{category="ADMIN",handler="/admin/authorization",type="serverErrors"} +solr_metrics_node_requests_total{category="ADMIN",handler="/admin/authorization",type="timeouts"} +solr_metrics_node_requests_total{category="ADMIN",handler="/admin/collections",type="clientErrors"} +solr_metrics_node_requests_total{category="ADMIN",handler="/admin/collections",type="errors"} +solr_metrics_node_requests_total{category="ADMIN",handler="/admin/collections",type="requests"} +solr_metrics_node_requests_total{category="ADMIN",handler="/admin/collections",type="serverErrors"} +solr_metrics_node_requests_total{category="ADMIN",handler="/admin/collections",type="timeouts"} +solr_metrics_node_requests_total{category="ADMIN",handler="/admin/configs",type="clientErrors"} +solr_metrics_node_requests_total{category="ADMIN",handler="/admin/configs",type="errors"} +solr_metrics_node_requests_total{category="ADMIN",handler="/admin/configs",type="requests"} +solr_metrics_node_requests_total{category="ADMIN",handler="/admin/configs",type="serverErrors"} +solr_metrics_node_requests_total{category="ADMIN",handler="/admin/configs",type="timeouts"} +solr_metrics_node_requests_total{category="ADMIN",handler="/admin/cores",type="clientErrors"} +solr_metrics_node_requests_total{category="ADMIN",handler="/admin/cores",type="errors"} +solr_metrics_node_requests_total{category="ADMIN",handler="/admin/cores",type="requests"} +solr_metrics_node_requests_total{category="ADMIN",handler="/admin/cores",type="serverErrors"} +solr_metrics_node_requests_total{category="ADMIN",handler="/admin/cores",type="timeouts"} +solr_metrics_node_requests_total{category="ADMIN",handler="/admin/info",type="clientErrors"} +solr_metrics_node_requests_total{category="ADMIN",handler="/admin/info",type="errors"} +solr_metrics_node_requests_total{category="ADMIN",handler="/admin/info",type="requests"} +solr_metrics_node_requests_total{category="ADMIN",handler="/admin/info",type="serverErrors"} +solr_metrics_node_requests_total{category="ADMIN",handler="/admin/info",type="timeouts"} +solr_metrics_node_requests_total{category="ADMIN",handler="/admin/metrics",type="clientErrors"} +solr_metrics_node_requests_total{category="ADMIN",handler="/admin/metrics",type="errors"} +solr_metrics_node_requests_total{category="ADMIN",handler="/admin/metrics",type="requests"} +solr_metrics_node_requests_total{category="ADMIN",handler="/admin/metrics",type="serverErrors"} +solr_metrics_node_requests_total{category="ADMIN",handler="/admin/metrics",type="timeouts"} +solr_metrics_node_requests_total{category="ADMIN",handler="/admin/zookeeper",type="clientErrors"} +solr_metrics_node_requests_total{category="ADMIN",handler="/admin/zookeeper",type="errors"} +solr_metrics_node_requests_total{category="ADMIN",handler="/admin/zookeeper",type="requests"} +solr_metrics_node_requests_total{category="ADMIN",handler="/admin/zookeeper",type="serverErrors"} +solr_metrics_node_requests_total{category="ADMIN",handler="/admin/zookeeper",type="timeouts"} +solr_metrics_node_requests_total{category="ADMIN",handler="/admin/zookeeper/status",type="clientErrors"} +solr_metrics_node_requests_total{category="ADMIN",handler="/admin/zookeeper/status",type="errors"} +solr_metrics_node_requests_total{category="ADMIN",handler="/admin/zookeeper/status",type="requests"} +solr_metrics_node_requests_total{category="ADMIN",handler="/admin/zookeeper/status",type="serverErrors"} +solr_metrics_node_requests_total{category="ADMIN",handler="/admin/zookeeper/status",type="timeouts"} +# TYPE solr_metrics_node_requests_time_total counter +solr_metrics_node_requests_time_total{category="ADMIN",handler="/admin/authorization"} +solr_metrics_node_requests_time_total{category="ADMIN",handler="/admin/collections"} +solr_metrics_node_requests_time_total{category="ADMIN",handler="/admin/configs"} +solr_metrics_node_requests_time_total{category="ADMIN",handler="/admin/cores"} +solr_metrics_node_requests_time_total{category="ADMIN",handler="/admin/info"} +solr_metrics_node_requests_time_total{category="ADMIN",handler="/admin/metrics"} +solr_metrics_node_requests_time_total{category="ADMIN",handler="/admin/zookeeper"} +solr_metrics_node_requests_time_total{category="ADMIN",handler="/admin/zookeeper/status"} +# TYPE solr_metrics_node_thread_pool_total counter +solr_metrics_node_thread_pool_total{category="ADMIN",executer="parallelCoreAdminExecutor",handler="/admin/cores",task="completed"} +solr_metrics_node_thread_pool_total{category="ADMIN",executer="parallelCoreAdminExecutor",handler="/admin/cores",task="running"} +solr_metrics_node_thread_pool_total{category="ADMIN",executer="parallelCoreAdminExecutor",handler="/admin/cores",task="submitted"} +solr_metrics_node_thread_pool_total{category="ADMIN",executer="parallelCoreExpensiveAdminExecutor",handler="/admin/cores",task="completed"} +solr_metrics_node_thread_pool_total{category="ADMIN",executer="parallelCoreExpensiveAdminExecutor",handler="/admin/cores",task="running"} +solr_metrics_node_thread_pool_total{category="ADMIN",executer="parallelCoreExpensiveAdminExecutor",handler="/admin/cores",task="submitted"} +solr_metrics_node_thread_pool_total{category="QUERY",executer="httpShardExecutor",handler="httpShardHandler",task="completed"} +solr_metrics_node_thread_pool_total{category="QUERY",executer="httpShardExecutor",handler="httpShardHandler",task="running"} +solr_metrics_node_thread_pool_total{category="QUERY",executer="httpShardExecutor",handler="httpShardHandler",task="submitted"} +solr_metrics_node_thread_pool_total{category="UPDATE",executer="recoveryExecutor",handler="updateShardHandler",task="completed"} +solr_metrics_node_thread_pool_total{category="UPDATE",executer="recoveryExecutor",handler="updateShardHandler",task="running"} +solr_metrics_node_thread_pool_total{category="UPDATE",executer="recoveryExecutor",handler="updateShardHandler",task="submitted"} +solr_metrics_node_thread_pool_total{category="UPDATE",executer="updateOnlyExecutor",handler="updateShardHandler",task="completed"} +solr_metrics_node_thread_pool_total{category="UPDATE",executer="updateOnlyExecutor",handler="updateShardHandler",task="running"} +solr_metrics_node_thread_pool_total{category="UPDATE",executer="updateOnlyExecutor",handler="updateShardHandler",task="submitted"} +solr_metrics_node_thread_pool_total{category="CONTAINER",executer="coreContainerWorkExecutor",task="completed"} +solr_metrics_node_thread_pool_total{category="CONTAINER",executer="coreContainerWorkExecutor",task="running"} +solr_metrics_node_thread_pool_total{category="CONTAINER",executer="coreContainerWorkExecutor",task="submitted"} +solr_metrics_node_thread_pool_total{category="CONTAINER",executer="coreLoadExecutor",task="completed"} +solr_metrics_node_thread_pool_total{category="CONTAINER",executer="coreLoadExecutor",task="running"} +solr_metrics_node_thread_pool_total{category="CONTAINER",executer="coreLoadExecutor",task="submitted"} +# TYPE solr_metrics_core_average_request_time gauge +solr_metrics_core_average_request_time{category="ADMIN",core="collection1",handler="/admin/file"} +solr_metrics_core_average_request_time{category="ADMIN",core="collection1",handler="/admin/luke"} +solr_metrics_core_average_request_time{category="ADMIN",core="collection1",handler="/admin/mbeans"} +solr_metrics_core_average_request_time{category="ADMIN",core="collection1",handler="/admin/ping"} +solr_metrics_core_average_request_time{category="ADMIN",core="collection1",handler="/admin/plugins"} +solr_metrics_core_average_request_time{category="ADMIN",core="collection1",handler="/admin/segments"} +solr_metrics_core_average_request_time{category="ADMIN",core="collection1",handler="/admin/system"} +solr_metrics_core_average_request_time{category="ADMIN",core="collection1",handler="/config"} +solr_metrics_core_average_request_time{category="ADMIN",core="collection1",handler="/schema"} +solr_metrics_core_average_request_time{category="ADMIN",core="collection1",handler="/tasks/cancel"} +solr_metrics_core_average_request_time{category="ADMIN",core="collection1",handler="/tasks/list"} +solr_metrics_core_average_request_time{category="QUERY",core="collection1",handler="/debug/dump"} +solr_metrics_core_average_request_time{category="QUERY",core="collection1",handler="/export"} +solr_metrics_core_average_request_time{category="QUERY",core="collection1",handler="/export[shard]"} +solr_metrics_core_average_request_time{category="QUERY",core="collection1",handler="/get"} +solr_metrics_core_average_request_time{category="QUERY",core="collection1",handler="/get[shard]"} +solr_metrics_core_average_request_time{category="QUERY",core="collection1",handler="/graph"} +solr_metrics_core_average_request_time{category="QUERY",core="collection1",handler="/select"} +solr_metrics_core_average_request_time{category="QUERY",core="collection1",handler="/select[shard]"} +solr_metrics_core_average_request_time{category="QUERY",core="collection1",handler="/stream"} +solr_metrics_core_average_request_time{category="QUERY",core="collection1",handler="/terms"} +solr_metrics_core_average_request_time{category="QUERY",core="collection1",handler="/terms[shard]"} +solr_metrics_core_average_request_time{category="REPLICATION",core="collection1",handler="/replication"} +solr_metrics_core_average_request_time{category="UPDATE",core="collection1",handler="/update"} +solr_metrics_core_average_request_time{category="UPDATE",core="collection1",handler="/update/cbor"} +solr_metrics_core_average_request_time{category="UPDATE",core="collection1",handler="/update/csv"} +solr_metrics_core_average_request_time{category="UPDATE",core="collection1",handler="/update/json"} +solr_metrics_core_average_request_time{category="UPDATE",core="collection1",handler="/update/json/docs"} +solr_metrics_core_average_request_time{category="UPDATE",core="collection1",handler="update"} +# TYPE solr_metrics_core_average_searcher_warmup_time gauge +solr_metrics_core_average_searcher_warmup_time{core="collection1",type="time"} +solr_metrics_core_average_searcher_warmup_time{core="collection1",type="warmup"} +# TYPE solr_metrics_core_cache gauge +solr_metrics_core_cache{cacheType="fieldCache",core="collection1",item="entries_count"} +solr_metrics_core_cache{cacheType="fieldValueCache",core="collection1",item="cumulative_evictions"} +solr_metrics_core_cache{cacheType="fieldValueCache",core="collection1",item="cumulative_hitratio"} +solr_metrics_core_cache{cacheType="fieldValueCache",core="collection1",item="cumulative_hits"} +solr_metrics_core_cache{cacheType="fieldValueCache",core="collection1",item="cumulative_inserts"} +solr_metrics_core_cache{cacheType="fieldValueCache",core="collection1",item="cumulative_lookups"} +solr_metrics_core_cache{cacheType="fieldValueCache",core="collection1",item="evictions"} +solr_metrics_core_cache{cacheType="fieldValueCache",core="collection1",item="hitratio"} +solr_metrics_core_cache{cacheType="fieldValueCache",core="collection1",item="hits"} +solr_metrics_core_cache{cacheType="fieldValueCache",core="collection1",item="inserts"} +solr_metrics_core_cache{cacheType="fieldValueCache",core="collection1",item="lookups"} +solr_metrics_core_cache{cacheType="fieldValueCache",core="collection1",item="maxRamMB"} +solr_metrics_core_cache{cacheType="fieldValueCache",core="collection1",item="ramBytesUsed"} +solr_metrics_core_cache{cacheType="fieldValueCache",core="collection1",item="size"} +solr_metrics_core_cache{cacheType="fieldValueCache",core="collection1",item="warmupTime"} +solr_metrics_core_cache{cacheType="statsCache",core="collection1",item="lookups"} +solr_metrics_core_cache{cacheType="statsCache",core="collection1",item="mergeToGlobalStats"} +solr_metrics_core_cache{cacheType="statsCache",core="collection1",item="missingGlobalFieldStats"} +solr_metrics_core_cache{cacheType="statsCache",core="collection1",item="missingGlobalTermStats"} +solr_metrics_core_cache{cacheType="statsCache",core="collection1",item="receiveGlobalStats"} +solr_metrics_core_cache{cacheType="statsCache",core="collection1",item="retrieveStats"} +solr_metrics_core_cache{cacheType="statsCache",core="collection1",item="returnLocalStats"} +solr_metrics_core_cache{cacheType="statsCache",core="collection1",item="sendGlobalStats"} +solr_metrics_core_cache{cacheType="statsCache",core="collection1",item="useCachedGlobalStats"} +solr_metrics_core_cache{core="collection1",item="hits",type="liveDocsCache"} +solr_metrics_core_cache{core="collection1",item="inserts",type="liveDocsCache"} +solr_metrics_core_cache{core="collection1",item="naiveHits",type="liveDocsCache"} +# TYPE solr_metrics_core_highlighter_requests_total counter +solr_metrics_core_highlighter_requests_total{core="collection1",item="default",type="SolrBoundaryScanner"} +solr_metrics_core_highlighter_requests_total{core="collection1",item="default",type="SolrEncoder"} +solr_metrics_core_highlighter_requests_total{core="collection1",item="default",type="SolrFormatter"} +solr_metrics_core_highlighter_requests_total{core="collection1",item="default",type="SolrFragListBuilder"} +solr_metrics_core_highlighter_requests_total{core="collection1",item="default",type="SolrFragmenter"} +solr_metrics_core_highlighter_requests_total{core="collection1",item="default",type="SolrFragmentsBuilder"} +# TYPE solr_metrics_core_index_size_bytes gauge +solr_metrics_core_index_size_bytes{core="collection1"} +# TYPE solr_metrics_core_requests_total counter +solr_metrics_core_requests_total{category="ADMIN",core="collection1",handler="/admin/file",type="clientErrors"} +solr_metrics_core_requests_total{category="ADMIN",core="collection1",handler="/admin/file",type="errors"} +solr_metrics_core_requests_total{category="ADMIN",core="collection1",handler="/admin/file",type="requests"} +solr_metrics_core_requests_total{category="ADMIN",core="collection1",handler="/admin/file",type="serverErrors"} +solr_metrics_core_requests_total{category="ADMIN",core="collection1",handler="/admin/file",type="timeouts"} +solr_metrics_core_requests_total{category="ADMIN",core="collection1",handler="/admin/luke",type="clientErrors"} +solr_metrics_core_requests_total{category="ADMIN",core="collection1",handler="/admin/luke",type="errors"} +solr_metrics_core_requests_total{category="ADMIN",core="collection1",handler="/admin/luke",type="requests"} +solr_metrics_core_requests_total{category="ADMIN",core="collection1",handler="/admin/luke",type="serverErrors"} +solr_metrics_core_requests_total{category="ADMIN",core="collection1",handler="/admin/luke",type="timeouts"} +solr_metrics_core_requests_total{category="ADMIN",core="collection1",handler="/admin/mbeans",type="clientErrors"} +solr_metrics_core_requests_total{category="ADMIN",core="collection1",handler="/admin/mbeans",type="errors"} +solr_metrics_core_requests_total{category="ADMIN",core="collection1",handler="/admin/mbeans",type="requests"} +solr_metrics_core_requests_total{category="ADMIN",core="collection1",handler="/admin/mbeans",type="serverErrors"} +solr_metrics_core_requests_total{category="ADMIN",core="collection1",handler="/admin/mbeans",type="timeouts"} +solr_metrics_core_requests_total{category="ADMIN",core="collection1",handler="/admin/ping",type="clientErrors"} +solr_metrics_core_requests_total{category="ADMIN",core="collection1",handler="/admin/ping",type="errors"} +solr_metrics_core_requests_total{category="ADMIN",core="collection1",handler="/admin/ping",type="requests"} +solr_metrics_core_requests_total{category="ADMIN",core="collection1",handler="/admin/ping",type="serverErrors"} +solr_metrics_core_requests_total{category="ADMIN",core="collection1",handler="/admin/ping",type="timeouts"} +solr_metrics_core_requests_total{category="ADMIN",core="collection1",handler="/admin/plugins",type="clientErrors"} +solr_metrics_core_requests_total{category="ADMIN",core="collection1",handler="/admin/plugins",type="errors"} +solr_metrics_core_requests_total{category="ADMIN",core="collection1",handler="/admin/plugins",type="requests"} +solr_metrics_core_requests_total{category="ADMIN",core="collection1",handler="/admin/plugins",type="serverErrors"} +solr_metrics_core_requests_total{category="ADMIN",core="collection1",handler="/admin/plugins",type="timeouts"} +solr_metrics_core_requests_total{category="ADMIN",core="collection1",handler="/admin/segments",type="clientErrors"} +solr_metrics_core_requests_total{category="ADMIN",core="collection1",handler="/admin/segments",type="errors"} +solr_metrics_core_requests_total{category="ADMIN",core="collection1",handler="/admin/segments",type="requests"} +solr_metrics_core_requests_total{category="ADMIN",core="collection1",handler="/admin/segments",type="serverErrors"} +solr_metrics_core_requests_total{category="ADMIN",core="collection1",handler="/admin/segments",type="timeouts"} +solr_metrics_core_requests_total{category="ADMIN",core="collection1",handler="/admin/system",type="clientErrors"} +solr_metrics_core_requests_total{category="ADMIN",core="collection1",handler="/admin/system",type="errors"} +solr_metrics_core_requests_total{category="ADMIN",core="collection1",handler="/admin/system",type="requests"} +solr_metrics_core_requests_total{category="ADMIN",core="collection1",handler="/admin/system",type="serverErrors"} +solr_metrics_core_requests_total{category="ADMIN",core="collection1",handler="/admin/system",type="timeouts"} +solr_metrics_core_requests_total{category="ADMIN",core="collection1",handler="/config",type="clientErrors"} +solr_metrics_core_requests_total{category="ADMIN",core="collection1",handler="/config",type="errors"} +solr_metrics_core_requests_total{category="ADMIN",core="collection1",handler="/config",type="requests"} +solr_metrics_core_requests_total{category="ADMIN",core="collection1",handler="/config",type="serverErrors"} +solr_metrics_core_requests_total{category="ADMIN",core="collection1",handler="/config",type="timeouts"} +solr_metrics_core_requests_total{category="ADMIN",core="collection1",handler="/schema",type="clientErrors"} +solr_metrics_core_requests_total{category="ADMIN",core="collection1",handler="/schema",type="errors"} +solr_metrics_core_requests_total{category="ADMIN",core="collection1",handler="/schema",type="requests"} +solr_metrics_core_requests_total{category="ADMIN",core="collection1",handler="/schema",type="serverErrors"} +solr_metrics_core_requests_total{category="ADMIN",core="collection1",handler="/schema",type="timeouts"} +solr_metrics_core_requests_total{category="ADMIN",core="collection1",handler="/tasks/cancel",type="clientErrors"} +solr_metrics_core_requests_total{category="ADMIN",core="collection1",handler="/tasks/cancel",type="errors"} +solr_metrics_core_requests_total{category="ADMIN",core="collection1",handler="/tasks/cancel",type="requests"} +solr_metrics_core_requests_total{category="ADMIN",core="collection1",handler="/tasks/cancel",type="serverErrors"} +solr_metrics_core_requests_total{category="ADMIN",core="collection1",handler="/tasks/cancel",type="timeouts"} +solr_metrics_core_requests_total{category="ADMIN",core="collection1",handler="/tasks/list",type="clientErrors"} +solr_metrics_core_requests_total{category="ADMIN",core="collection1",handler="/tasks/list",type="errors"} +solr_metrics_core_requests_total{category="ADMIN",core="collection1",handler="/tasks/list",type="requests"} +solr_metrics_core_requests_total{category="ADMIN",core="collection1",handler="/tasks/list",type="serverErrors"} +solr_metrics_core_requests_total{category="ADMIN",core="collection1",handler="/tasks/list",type="timeouts"} +solr_metrics_core_requests_total{category="QUERY",core="collection1",handler="/debug/dump",type="clientErrors"} +solr_metrics_core_requests_total{category="QUERY",core="collection1",handler="/debug/dump",type="errors"} +solr_metrics_core_requests_total{category="QUERY",core="collection1",handler="/debug/dump",type="requests"} +solr_metrics_core_requests_total{category="QUERY",core="collection1",handler="/debug/dump",type="serverErrors"} +solr_metrics_core_requests_total{category="QUERY",core="collection1",handler="/debug/dump",type="timeouts"} +solr_metrics_core_requests_total{category="QUERY",core="collection1",handler="/export",type="clientErrors"} +solr_metrics_core_requests_total{category="QUERY",core="collection1",handler="/export",type="errors"} +solr_metrics_core_requests_total{category="QUERY",core="collection1",handler="/export",type="requests"} +solr_metrics_core_requests_total{category="QUERY",core="collection1",handler="/export",type="serverErrors"} +solr_metrics_core_requests_total{category="QUERY",core="collection1",handler="/export",type="timeouts"} +solr_metrics_core_requests_total{category="QUERY",core="collection1",handler="/export[shard]",type="clientErrors"} +solr_metrics_core_requests_total{category="QUERY",core="collection1",handler="/export[shard]",type="errors"} +solr_metrics_core_requests_total{category="QUERY",core="collection1",handler="/export[shard]",type="requests"} +solr_metrics_core_requests_total{category="QUERY",core="collection1",handler="/export[shard]",type="serverErrors"} +solr_metrics_core_requests_total{category="QUERY",core="collection1",handler="/export[shard]",type="timeouts"} +solr_metrics_core_requests_total{category="QUERY",core="collection1",handler="/get",type="clientErrors"} +solr_metrics_core_requests_total{category="QUERY",core="collection1",handler="/get",type="errors"} +solr_metrics_core_requests_total{category="QUERY",core="collection1",handler="/get",type="requests"} +solr_metrics_core_requests_total{category="QUERY",core="collection1",handler="/get",type="serverErrors"} +solr_metrics_core_requests_total{category="QUERY",core="collection1",handler="/get",type="timeouts"} +solr_metrics_core_requests_total{category="QUERY",core="collection1",handler="/get[shard]",type="clientErrors"} +solr_metrics_core_requests_total{category="QUERY",core="collection1",handler="/get[shard]",type="errors"} +solr_metrics_core_requests_total{category="QUERY",core="collection1",handler="/get[shard]",type="requests"} +solr_metrics_core_requests_total{category="QUERY",core="collection1",handler="/get[shard]",type="serverErrors"} +solr_metrics_core_requests_total{category="QUERY",core="collection1",handler="/get[shard]",type="timeouts"} +solr_metrics_core_requests_total{category="QUERY",core="collection1",handler="/graph",type="clientErrors"} +solr_metrics_core_requests_total{category="QUERY",core="collection1",handler="/graph",type="errors"} +solr_metrics_core_requests_total{category="QUERY",core="collection1",handler="/graph",type="requests"} +solr_metrics_core_requests_total{category="QUERY",core="collection1",handler="/graph",type="serverErrors"} +solr_metrics_core_requests_total{category="QUERY",core="collection1",handler="/graph",type="timeouts"} +solr_metrics_core_requests_total{category="QUERY",core="collection1",handler="/select",type="clientErrors"} +solr_metrics_core_requests_total{category="QUERY",core="collection1",handler="/select",type="errors"} +solr_metrics_core_requests_total{category="QUERY",core="collection1",handler="/select",type="requests"} +solr_metrics_core_requests_total{category="QUERY",core="collection1",handler="/select",type="serverErrors"} +solr_metrics_core_requests_total{category="QUERY",core="collection1",handler="/select",type="timeouts"} +solr_metrics_core_requests_total{category="QUERY",core="collection1",handler="/select[shard]",type="clientErrors"} +solr_metrics_core_requests_total{category="QUERY",core="collection1",handler="/select[shard]",type="errors"} +solr_metrics_core_requests_total{category="QUERY",core="collection1",handler="/select[shard]",type="requests"} +solr_metrics_core_requests_total{category="QUERY",core="collection1",handler="/select[shard]",type="serverErrors"} +solr_metrics_core_requests_total{category="QUERY",core="collection1",handler="/select[shard]",type="timeouts"} +solr_metrics_core_requests_total{category="QUERY",core="collection1",handler="/stream",type="clientErrors"} +solr_metrics_core_requests_total{category="QUERY",core="collection1",handler="/stream",type="errors"} +solr_metrics_core_requests_total{category="QUERY",core="collection1",handler="/stream",type="requests"} +solr_metrics_core_requests_total{category="QUERY",core="collection1",handler="/stream",type="serverErrors"} +solr_metrics_core_requests_total{category="QUERY",core="collection1",handler="/stream",type="timeouts"} +solr_metrics_core_requests_total{category="QUERY",core="collection1",handler="/terms",type="clientErrors"} +solr_metrics_core_requests_total{category="QUERY",core="collection1",handler="/terms",type="errors"} +solr_metrics_core_requests_total{category="QUERY",core="collection1",handler="/terms",type="requests"} +solr_metrics_core_requests_total{category="QUERY",core="collection1",handler="/terms",type="serverErrors"} +solr_metrics_core_requests_total{category="QUERY",core="collection1",handler="/terms",type="timeouts"} +solr_metrics_core_requests_total{category="QUERY",core="collection1",handler="/terms[shard]",type="clientErrors"} +solr_metrics_core_requests_total{category="QUERY",core="collection1",handler="/terms[shard]",type="errors"} +solr_metrics_core_requests_total{category="QUERY",core="collection1",handler="/terms[shard]",type="requests"} +solr_metrics_core_requests_total{category="QUERY",core="collection1",handler="/terms[shard]",type="serverErrors"} +solr_metrics_core_requests_total{category="QUERY",core="collection1",handler="/terms[shard]",type="timeouts"} +solr_metrics_core_requests_total{category="REPLICATION",core="collection1",handler="/replication",type="clientErrors"} +solr_metrics_core_requests_total{category="REPLICATION",core="collection1",handler="/replication",type="errors"} +solr_metrics_core_requests_total{category="REPLICATION",core="collection1",handler="/replication",type="requests"} +solr_metrics_core_requests_total{category="REPLICATION",core="collection1",handler="/replication",type="serverErrors"} +solr_metrics_core_requests_total{category="REPLICATION",core="collection1",handler="/replication",type="timeouts"} +solr_metrics_core_requests_total{category="UPDATE",core="collection1",handler="/update",type="clientErrors"} +solr_metrics_core_requests_total{category="UPDATE",core="collection1",handler="/update",type="errors"} +solr_metrics_core_requests_total{category="UPDATE",core="collection1",handler="/update",type="requests"} +solr_metrics_core_requests_total{category="UPDATE",core="collection1",handler="/update",type="serverErrors"} +solr_metrics_core_requests_total{category="UPDATE",core="collection1",handler="/update",type="timeouts"} +solr_metrics_core_requests_total{category="UPDATE",core="collection1",handler="/update/cbor",type="clientErrors"} +solr_metrics_core_requests_total{category="UPDATE",core="collection1",handler="/update/cbor",type="errors"} +solr_metrics_core_requests_total{category="UPDATE",core="collection1",handler="/update/cbor",type="requests"} +solr_metrics_core_requests_total{category="UPDATE",core="collection1",handler="/update/cbor",type="serverErrors"} +solr_metrics_core_requests_total{category="UPDATE",core="collection1",handler="/update/cbor",type="timeouts"} +solr_metrics_core_requests_total{category="UPDATE",core="collection1",handler="/update/csv",type="clientErrors"} +solr_metrics_core_requests_total{category="UPDATE",core="collection1",handler="/update/csv",type="errors"} +solr_metrics_core_requests_total{category="UPDATE",core="collection1",handler="/update/csv",type="requests"} +solr_metrics_core_requests_total{category="UPDATE",core="collection1",handler="/update/csv",type="serverErrors"} +solr_metrics_core_requests_total{category="UPDATE",core="collection1",handler="/update/csv",type="timeouts"} +solr_metrics_core_requests_total{category="UPDATE",core="collection1",handler="/update/json",type="clientErrors"} +solr_metrics_core_requests_total{category="UPDATE",core="collection1",handler="/update/json",type="errors"} +solr_metrics_core_requests_total{category="UPDATE",core="collection1",handler="/update/json",type="requests"} +solr_metrics_core_requests_total{category="UPDATE",core="collection1",handler="/update/json",type="serverErrors"} +solr_metrics_core_requests_total{category="UPDATE",core="collection1",handler="/update/json",type="timeouts"} +solr_metrics_core_requests_total{category="UPDATE",core="collection1",handler="/update/json/docs",type="clientErrors"} +solr_metrics_core_requests_total{category="UPDATE",core="collection1",handler="/update/json/docs",type="errors"} +solr_metrics_core_requests_total{category="UPDATE",core="collection1",handler="/update/json/docs",type="requests"} +solr_metrics_core_requests_total{category="UPDATE",core="collection1",handler="/update/json/docs",type="serverErrors"} +solr_metrics_core_requests_total{category="UPDATE",core="collection1",handler="/update/json/docs",type="timeouts"} +solr_metrics_core_requests_total{category="UPDATE",core="collection1",handler="update",type="clientErrors"} +solr_metrics_core_requests_total{category="UPDATE",core="collection1",handler="update",type="errors"} +solr_metrics_core_requests_total{category="UPDATE",core="collection1",handler="update",type="requests"} +solr_metrics_core_requests_total{category="UPDATE",core="collection1",handler="update",type="serverErrors"} +solr_metrics_core_requests_total{category="UPDATE",core="collection1",handler="update",type="timeouts"} +solr_metrics_core_requests_total{category="UPDATE",core="collection1",handler="updateHandler",type="commits"} +solr_metrics_core_requests_total{category="UPDATE",core="collection1",handler="updateHandler",type="cumulativeAdds"} +solr_metrics_core_requests_total{category="UPDATE",core="collection1",handler="updateHandler",type="cumulativeDeletesById"} +solr_metrics_core_requests_total{category="UPDATE",core="collection1",handler="updateHandler",type="cumulativeDeletesByQuery"} +solr_metrics_core_requests_total{category="UPDATE",core="collection1",handler="updateHandler",type="cumulativeErrors"} +solr_metrics_core_requests_total{category="UPDATE",core="collection1",handler="updateHandler",type="expungeDeletes"} +solr_metrics_core_requests_total{category="UPDATE",core="collection1",handler="updateHandler",type="merges"} +solr_metrics_core_requests_total{category="UPDATE",core="collection1",handler="updateHandler",type="optimizes"} +solr_metrics_core_requests_total{category="UPDATE",core="collection1",handler="updateHandler",type="rollbacks"} +solr_metrics_core_requests_total{category="UPDATE",core="collection1",handler="updateHandler",type="splits"} +# TYPE solr_metrics_core_requests_time_total counter +solr_metrics_core_requests_time_total{category="ADMIN",core="collection1",handler="/admin/file"} +solr_metrics_core_requests_time_total{category="ADMIN",core="collection1",handler="/admin/luke"} +solr_metrics_core_requests_time_total{category="ADMIN",core="collection1",handler="/admin/mbeans"} +solr_metrics_core_requests_time_total{category="ADMIN",core="collection1",handler="/admin/ping"} +solr_metrics_core_requests_time_total{category="ADMIN",core="collection1",handler="/admin/plugins"} +solr_metrics_core_requests_time_total{category="ADMIN",core="collection1",handler="/admin/segments"} +solr_metrics_core_requests_time_total{category="ADMIN",core="collection1",handler="/admin/system"} +solr_metrics_core_requests_time_total{category="ADMIN",core="collection1",handler="/config"} +solr_metrics_core_requests_time_total{category="ADMIN",core="collection1",handler="/schema"} +solr_metrics_core_requests_time_total{category="ADMIN",core="collection1",handler="/tasks/cancel"} +solr_metrics_core_requests_time_total{category="ADMIN",core="collection1",handler="/tasks/list"} +solr_metrics_core_requests_time_total{category="QUERY",core="collection1",handler="/debug/dump"} +solr_metrics_core_requests_time_total{category="QUERY",core="collection1",handler="/export"} +solr_metrics_core_requests_time_total{category="QUERY",core="collection1",handler="/export[shard]"} +solr_metrics_core_requests_time_total{category="QUERY",core="collection1",handler="/get"} +solr_metrics_core_requests_time_total{category="QUERY",core="collection1",handler="/get[shard]"} +solr_metrics_core_requests_time_total{category="QUERY",core="collection1",handler="/graph"} +solr_metrics_core_requests_time_total{category="QUERY",core="collection1",handler="/select"} +solr_metrics_core_requests_time_total{category="QUERY",core="collection1",handler="/select[shard]"} +solr_metrics_core_requests_time_total{category="QUERY",core="collection1",handler="/stream"} +solr_metrics_core_requests_time_total{category="QUERY",core="collection1",handler="/terms"} +solr_metrics_core_requests_time_total{category="QUERY",core="collection1",handler="/terms[shard]"} +solr_metrics_core_requests_time_total{category="REPLICATION",core="collection1",handler="/replication"} +solr_metrics_core_requests_time_total{category="UPDATE",core="collection1",handler="/update"} +solr_metrics_core_requests_time_total{category="UPDATE",core="collection1",handler="/update/cbor"} +solr_metrics_core_requests_time_total{category="UPDATE",core="collection1",handler="/update/csv"} +solr_metrics_core_requests_time_total{category="UPDATE",core="collection1",handler="/update/json"} +solr_metrics_core_requests_time_total{category="UPDATE",core="collection1",handler="/update/json/docs"} +solr_metrics_core_requests_time_total{category="UPDATE",core="collection1",handler="update"} +# TYPE solr_metrics_core_searcher_documents gauge +solr_metrics_core_searcher_documents{core="collection1",type="deletedDocs"} +solr_metrics_core_searcher_documents{core="collection1",type="fullSortCount"} +solr_metrics_core_searcher_documents{core="collection1",type="indexCommitSize"} +solr_metrics_core_searcher_documents{core="collection1",type="indexVersion"} +solr_metrics_core_searcher_documents{core="collection1",type="maxDoc"} +solr_metrics_core_searcher_documents{core="collection1",type="numDocs"} +solr_metrics_core_searcher_documents{core="collection1",type="skipSortCount"} +solr_metrics_core_searcher_documents{core="collection1",type="warmupTime"} +# TYPE solr_metrics_core_update_handler gauge +solr_metrics_core_update_handler{category="REPLICATION",core="collection1",handler="/replication",type="generation"} +solr_metrics_core_update_handler{category="UPDATE",core="collection1",handler="updateHandler",type="adds"} +solr_metrics_core_update_handler{category="UPDATE",core="collection1",handler="updateHandler",type="autoCommits"} +solr_metrics_core_update_handler{category="UPDATE",core="collection1",handler="updateHandler",type="deletesById"} +solr_metrics_core_update_handler{category="UPDATE",core="collection1",handler="updateHandler",type="deletesByQuery"} +solr_metrics_core_update_handler{category="UPDATE",core="collection1",handler="updateHandler",type="docsPending"} +solr_metrics_core_update_handler{category="UPDATE",core="collection1",handler="updateHandler",type="errors"} +solr_metrics_core_update_handler{category="UPDATE",core="collection1",handler="updateHandler",type="softAutoCommits"} diff --git a/solr/core/src/test/org/apache/solr/response/TestPrometheusResponseWriter.java b/solr/core/src/test/org/apache/solr/response/TestPrometheusResponseWriter.java index 6154f9ed51f..348e5b12e84 100644 --- a/solr/core/src/test/org/apache/solr/response/TestPrometheusResponseWriter.java +++ b/solr/core/src/test/org/apache/solr/response/TestPrometheusResponseWriter.java @@ -16,16 +16,14 @@ */ package org.apache.solr.response; -import io.prometheus.metrics.model.snapshots.CounterSnapshot; -import io.prometheus.metrics.model.snapshots.GaugeSnapshot; -import io.prometheus.metrics.model.snapshots.Labels; import java.io.ByteArrayOutputStream; -import java.io.IOException; +import java.io.File; import java.nio.charset.StandardCharsets; +import java.nio.file.Files; import org.apache.solr.SolrTestCaseJ4; +import org.apache.solr.common.params.CommonParams; import org.apache.solr.common.util.NamedList; -import org.apache.solr.common.util.SimpleOrderedMap; -import org.apache.solr.metrics.prometheus.core.SolrPrometheusCoreExporter; +import org.apache.solr.handler.admin.MetricsHandler; import org.apache.solr.request.SolrQueryRequest; import org.junit.BeforeClass; import org.junit.Test; @@ -35,33 +33,38 @@ public class TestPrometheusResponseWriter extends SolrTestCaseJ4 { @BeforeClass public static void beforeClass() throws Exception { - initCore("solrconfig.xml", "schema.xml"); + initCore("solrconfig-minimal.xml", "schema.xml"); + h.getCoreContainer().waitForLoadingCoresToFinish(30000); } @Test - public void testPrometheusOutput() throws IOException { + public void testPrometheusOutput() throws Exception { SolrQueryRequest req = req("dummy"); SolrQueryResponse rsp = new SolrQueryResponse(); PrometheusResponseWriter w = new PrometheusResponseWriter(); - NamedList registries = new SimpleOrderedMap<>(); ByteArrayOutputStream byteOut = new ByteArrayOutputStream(); - Labels expectedLabels = Labels.of("test", "test-value"); - SolrPrometheusCoreExporter exporter = new SolrPrometheusCoreExporter("collection1", false); - CounterSnapshot.CounterDataPointSnapshot counterDatapoint = - exporter.createCounterDatapoint(1.234, expectedLabels); - GaugeSnapshot.GaugeDataPointSnapshot gaugeDataPoint = - exporter.createGaugeDatapoint(9.876, expectedLabels); - exporter.collectCounterDatapoint("test_counter_metric_name", counterDatapoint); - exporter.collectGaugeDatapoint("test_gauge_metric_name", gaugeDataPoint); - registries.add("solr.core.collection1", exporter); - rsp.add("metrics", registries); + MetricsHandler handler = new MetricsHandler(h.getCoreContainer()); + SolrQueryResponse resp = new SolrQueryResponse(); + handler.handleRequestBody( + req( + CommonParams.QT, + "/admin/metrics", + MetricsHandler.COMPACT_PARAM, + "false", + CommonParams.WT, + "prometheus"), + resp); + NamedList values = resp.getValues(); + rsp.add("metrics", values.get("metrics")); w.write(byteOut, req, rsp); - String actual = byteOut.toString(StandardCharsets.UTF_8); - assertEquals( - "# TYPE test_counter_metric_name_total counter\ntest_counter_metric_name_total{test=\"test-value\"} 1.234\n# TYPE test_gauge_metric_name gauge\ntest_gauge_metric_name{test=\"test-value\"} 9.876\n", - actual); - req.close(); + String actualOutput = byteOut.toString(StandardCharsets.UTF_8).replaceAll("(?<=}).*", ""); + String expectedOutput = + Files.readString( + new File(TEST_PATH().toString(), "solr-prometheus-output.txt").toPath(), + StandardCharsets.UTF_8); + assertEquals(expectedOutput, actualOutput); + handler.close(); } } diff --git a/solr/solr-ref-guide/modules/deployment-guide/pages/metrics-reporting.adoc b/solr/solr-ref-guide/modules/deployment-guide/pages/metrics-reporting.adoc index 9da3960b1cd..f3309f65a6b 100644 --- a/solr/solr-ref-guide/modules/deployment-guide/pages/metrics-reporting.adoc +++ b/solr/solr-ref-guide/modules/deployment-guide/pages/metrics-reporting.adoc @@ -879,7 +879,7 @@ The response will look like this: ]} ---- -Like other request handlers, the Metrics API can also take the `wt` parameter to define the output format. The Metrics API also provides an additional special `wt` parameter `prometheus` that will output metrics in Prometheus format. This can be used for xref:monitoring-with-prometheus-and-grafana.adoc#prometheus-metrics-api[Monitoring with Prometheus and Grafana] +Like other request handlers, the Metrics API can also take the `wt` parameter to define the output format. The Metrics API also provides an additional special `wt` parameter `prometheus` that will output metrics in Prometheus format. This can be used for xref:monitoring-with-prometheus-and-grafana.adoc#metrics-api-with-prometheus-format[Monitoring with Prometheus and Grafana] [[metrics_examples]] === Examples diff --git a/solr/solr-ref-guide/modules/deployment-guide/pages/monitoring-with-prometheus-and-grafana.adoc b/solr/solr-ref-guide/modules/deployment-guide/pages/monitoring-with-prometheus-and-grafana.adoc index bb6b41dff85..670b43d5a52 100644 --- a/solr/solr-ref-guide/modules/deployment-guide/pages/monitoring-with-prometheus-and-grafana.adoc +++ b/solr/solr-ref-guide/modules/deployment-guide/pages/monitoring-with-prometheus-and-grafana.adoc @@ -19,7 +19,7 @@ If you use https://prometheus.io[Prometheus] and https://grafana.com[Grafana] for metrics storage and data visualization, Solr provides 2 solutions to collect metrics and other data: * Prometheus Exporter -* Prometheus Metrics API endpoint +* Metrics API with Prometheus format The Prometheus exporter is included with the full Solr distribution, and is located under `prometheus-exporter/`. It is not included in the `slim` Solr distribution. @@ -595,14 +595,14 @@ This screenshot shows what it might look like: .Grafana Dashboard image::monitoring-with-prometheus-and-grafana/grafana-solr-dashboard.png[image,width=800] -== Prometheus Metrics API +== Metrics API with Prometheus format Prometheus Metrics are available natively directly from Solr by leveraging the Metrics API and setting `wt` parameter to `prometheus`: [source,text] localhost:8983/solr/admin/metrics?wt=prometheus -The Prometheus Metrics API does not provide any configurability and the Prometheus output is fixed. Any metrics aggregations and/or filtering must be done on Grafana or the Prometheus server. +The Metrics API with the `prometheus` parameter does not provide any configurability and the Prometheus output is fixed. Any metrics aggregations and/or filtering must be done on Grafana or the Prometheus server. === Prometheus Configuration From bceb4fedb66332acacec9f93251b0327ec849300 Mon Sep 17 00:00:00 2001 From: mbiscocho Date: Fri, 21 Jun 2024 14:44:45 -0400 Subject: [PATCH 25/32] Change integration test to use SolrJettyTestRule --- .../solr/solr-prometheus-output.txt | 83 +++++++++++++++++++ .../TestPrometheusResponseWriter.java | 65 +++++++-------- 2 files changed, 115 insertions(+), 33 deletions(-) diff --git a/solr/core/src/test-files/solr/solr-prometheus-output.txt b/solr/core/src/test-files/solr/solr-prometheus-output.txt index be6144a3f40..cd11a690210 100644 --- a/solr/core/src/test-files/solr/solr-prometheus-output.txt +++ b/solr/core/src/test-files/solr/solr-prometheus-output.txt @@ -194,6 +194,8 @@ solr_metrics_core_average_request_time{category="QUERY",core="collection1",handl solr_metrics_core_average_request_time{category="QUERY",core="collection1",handler="/get"} solr_metrics_core_average_request_time{category="QUERY",core="collection1",handler="/get[shard]"} solr_metrics_core_average_request_time{category="QUERY",core="collection1",handler="/graph"} +solr_metrics_core_average_request_time{category="QUERY",core="collection1",handler="/query"} +solr_metrics_core_average_request_time{category="QUERY",core="collection1",handler="/query[shard]"} solr_metrics_core_average_request_time{category="QUERY",core="collection1",handler="/select"} solr_metrics_core_average_request_time{category="QUERY",core="collection1",handler="/select[shard]"} solr_metrics_core_average_request_time{category="QUERY",core="collection1",handler="/stream"} @@ -210,6 +212,20 @@ solr_metrics_core_average_request_time{category="UPDATE",core="collection1",hand solr_metrics_core_average_searcher_warmup_time{core="collection1",type="time"} solr_metrics_core_average_searcher_warmup_time{core="collection1",type="warmup"} # TYPE solr_metrics_core_cache gauge +solr_metrics_core_cache{cacheType="documentCache",core="collection1",item="cumulative_evictions"} +solr_metrics_core_cache{cacheType="documentCache",core="collection1",item="cumulative_hitratio"} +solr_metrics_core_cache{cacheType="documentCache",core="collection1",item="cumulative_hits"} +solr_metrics_core_cache{cacheType="documentCache",core="collection1",item="cumulative_inserts"} +solr_metrics_core_cache{cacheType="documentCache",core="collection1",item="cumulative_lookups"} +solr_metrics_core_cache{cacheType="documentCache",core="collection1",item="evictions"} +solr_metrics_core_cache{cacheType="documentCache",core="collection1",item="hitratio"} +solr_metrics_core_cache{cacheType="documentCache",core="collection1",item="hits"} +solr_metrics_core_cache{cacheType="documentCache",core="collection1",item="inserts"} +solr_metrics_core_cache{cacheType="documentCache",core="collection1",item="lookups"} +solr_metrics_core_cache{cacheType="documentCache",core="collection1",item="maxRamMB"} +solr_metrics_core_cache{cacheType="documentCache",core="collection1",item="ramBytesUsed"} +solr_metrics_core_cache{cacheType="documentCache",core="collection1",item="size"} +solr_metrics_core_cache{cacheType="documentCache",core="collection1",item="warmupTime"} solr_metrics_core_cache{cacheType="fieldCache",core="collection1",item="entries_count"} solr_metrics_core_cache{cacheType="fieldValueCache",core="collection1",item="cumulative_evictions"} solr_metrics_core_cache{cacheType="fieldValueCache",core="collection1",item="cumulative_hitratio"} @@ -225,6 +241,48 @@ solr_metrics_core_cache{cacheType="fieldValueCache",core="collection1",item="max solr_metrics_core_cache{cacheType="fieldValueCache",core="collection1",item="ramBytesUsed"} solr_metrics_core_cache{cacheType="fieldValueCache",core="collection1",item="size"} solr_metrics_core_cache{cacheType="fieldValueCache",core="collection1",item="warmupTime"} +solr_metrics_core_cache{cacheType="filterCache",core="collection1",item="cumulative_evictions"} +solr_metrics_core_cache{cacheType="filterCache",core="collection1",item="cumulative_hitratio"} +solr_metrics_core_cache{cacheType="filterCache",core="collection1",item="cumulative_hits"} +solr_metrics_core_cache{cacheType="filterCache",core="collection1",item="cumulative_inserts"} +solr_metrics_core_cache{cacheType="filterCache",core="collection1",item="cumulative_lookups"} +solr_metrics_core_cache{cacheType="filterCache",core="collection1",item="evictions"} +solr_metrics_core_cache{cacheType="filterCache",core="collection1",item="hitratio"} +solr_metrics_core_cache{cacheType="filterCache",core="collection1",item="hits"} +solr_metrics_core_cache{cacheType="filterCache",core="collection1",item="inserts"} +solr_metrics_core_cache{cacheType="filterCache",core="collection1",item="lookups"} +solr_metrics_core_cache{cacheType="filterCache",core="collection1",item="maxRamMB"} +solr_metrics_core_cache{cacheType="filterCache",core="collection1",item="ramBytesUsed"} +solr_metrics_core_cache{cacheType="filterCache",core="collection1",item="size"} +solr_metrics_core_cache{cacheType="filterCache",core="collection1",item="warmupTime"} +solr_metrics_core_cache{cacheType="perSegFilter",core="collection1",item="cumulative_evictions"} +solr_metrics_core_cache{cacheType="perSegFilter",core="collection1",item="cumulative_hitratio"} +solr_metrics_core_cache{cacheType="perSegFilter",core="collection1",item="cumulative_hits"} +solr_metrics_core_cache{cacheType="perSegFilter",core="collection1",item="cumulative_inserts"} +solr_metrics_core_cache{cacheType="perSegFilter",core="collection1",item="cumulative_lookups"} +solr_metrics_core_cache{cacheType="perSegFilter",core="collection1",item="evictions"} +solr_metrics_core_cache{cacheType="perSegFilter",core="collection1",item="hitratio"} +solr_metrics_core_cache{cacheType="perSegFilter",core="collection1",item="hits"} +solr_metrics_core_cache{cacheType="perSegFilter",core="collection1",item="inserts"} +solr_metrics_core_cache{cacheType="perSegFilter",core="collection1",item="lookups"} +solr_metrics_core_cache{cacheType="perSegFilter",core="collection1",item="maxRamMB"} +solr_metrics_core_cache{cacheType="perSegFilter",core="collection1",item="ramBytesUsed"} +solr_metrics_core_cache{cacheType="perSegFilter",core="collection1",item="size"} +solr_metrics_core_cache{cacheType="perSegFilter",core="collection1",item="warmupTime"} +solr_metrics_core_cache{cacheType="queryResultCache",core="collection1",item="cumulative_evictions"} +solr_metrics_core_cache{cacheType="queryResultCache",core="collection1",item="cumulative_hitratio"} +solr_metrics_core_cache{cacheType="queryResultCache",core="collection1",item="cumulative_hits"} +solr_metrics_core_cache{cacheType="queryResultCache",core="collection1",item="cumulative_inserts"} +solr_metrics_core_cache{cacheType="queryResultCache",core="collection1",item="cumulative_lookups"} +solr_metrics_core_cache{cacheType="queryResultCache",core="collection1",item="evictions"} +solr_metrics_core_cache{cacheType="queryResultCache",core="collection1",item="hitratio"} +solr_metrics_core_cache{cacheType="queryResultCache",core="collection1",item="hits"} +solr_metrics_core_cache{cacheType="queryResultCache",core="collection1",item="inserts"} +solr_metrics_core_cache{cacheType="queryResultCache",core="collection1",item="lookups"} +solr_metrics_core_cache{cacheType="queryResultCache",core="collection1",item="maxRamMB"} +solr_metrics_core_cache{cacheType="queryResultCache",core="collection1",item="ramBytesUsed"} +solr_metrics_core_cache{cacheType="queryResultCache",core="collection1",item="size"} +solr_metrics_core_cache{cacheType="queryResultCache",core="collection1",item="warmupTime"} solr_metrics_core_cache{cacheType="statsCache",core="collection1",item="lookups"} solr_metrics_core_cache{cacheType="statsCache",core="collection1",item="mergeToGlobalStats"} solr_metrics_core_cache{cacheType="statsCache",core="collection1",item="missingGlobalFieldStats"} @@ -238,12 +296,21 @@ solr_metrics_core_cache{core="collection1",item="hits",type="liveDocsCache"} solr_metrics_core_cache{core="collection1",item="inserts",type="liveDocsCache"} solr_metrics_core_cache{core="collection1",item="naiveHits",type="liveDocsCache"} # TYPE solr_metrics_core_highlighter_requests_total counter +solr_metrics_core_highlighter_requests_total{core="collection1",item="breakIterator",type="SolrBoundaryScanner"} +solr_metrics_core_highlighter_requests_total{core="collection1",item="colored",type="SolrFragmentsBuilder"} solr_metrics_core_highlighter_requests_total{core="collection1",item="default",type="SolrBoundaryScanner"} solr_metrics_core_highlighter_requests_total{core="collection1",item="default",type="SolrEncoder"} solr_metrics_core_highlighter_requests_total{core="collection1",item="default",type="SolrFormatter"} solr_metrics_core_highlighter_requests_total{core="collection1",item="default",type="SolrFragListBuilder"} solr_metrics_core_highlighter_requests_total{core="collection1",item="default",type="SolrFragmenter"} solr_metrics_core_highlighter_requests_total{core="collection1",item="default",type="SolrFragmentsBuilder"} +solr_metrics_core_highlighter_requests_total{core="collection1",item="gap",type="SolrFragmenter"} +solr_metrics_core_highlighter_requests_total{core="collection1",item="html",type="SolrEncoder"} +solr_metrics_core_highlighter_requests_total{core="collection1",item="html",type="SolrFormatter"} +solr_metrics_core_highlighter_requests_total{core="collection1",item="regex",type="SolrFragmenter"} +solr_metrics_core_highlighter_requests_total{core="collection1",item="simple",type="SolrFragListBuilder"} +solr_metrics_core_highlighter_requests_total{core="collection1",item="single",type="SolrFragListBuilder"} +solr_metrics_core_highlighter_requests_total{core="collection1",item="weighted",type="SolrFragListBuilder"} # TYPE solr_metrics_core_index_size_bytes gauge solr_metrics_core_index_size_bytes{core="collection1"} # TYPE solr_metrics_core_requests_total counter @@ -332,6 +399,16 @@ solr_metrics_core_requests_total{category="QUERY",core="collection1",handler="/g solr_metrics_core_requests_total{category="QUERY",core="collection1",handler="/graph",type="requests"} solr_metrics_core_requests_total{category="QUERY",core="collection1",handler="/graph",type="serverErrors"} solr_metrics_core_requests_total{category="QUERY",core="collection1",handler="/graph",type="timeouts"} +solr_metrics_core_requests_total{category="QUERY",core="collection1",handler="/query",type="clientErrors"} +solr_metrics_core_requests_total{category="QUERY",core="collection1",handler="/query",type="errors"} +solr_metrics_core_requests_total{category="QUERY",core="collection1",handler="/query",type="requests"} +solr_metrics_core_requests_total{category="QUERY",core="collection1",handler="/query",type="serverErrors"} +solr_metrics_core_requests_total{category="QUERY",core="collection1",handler="/query",type="timeouts"} +solr_metrics_core_requests_total{category="QUERY",core="collection1",handler="/query[shard]",type="clientErrors"} +solr_metrics_core_requests_total{category="QUERY",core="collection1",handler="/query[shard]",type="errors"} +solr_metrics_core_requests_total{category="QUERY",core="collection1",handler="/query[shard]",type="requests"} +solr_metrics_core_requests_total{category="QUERY",core="collection1",handler="/query[shard]",type="serverErrors"} +solr_metrics_core_requests_total{category="QUERY",core="collection1",handler="/query[shard]",type="timeouts"} solr_metrics_core_requests_total{category="QUERY",core="collection1",handler="/select",type="clientErrors"} solr_metrics_core_requests_total{category="QUERY",core="collection1",handler="/select",type="errors"} solr_metrics_core_requests_total{category="QUERY",core="collection1",handler="/select",type="requests"} @@ -420,6 +497,8 @@ solr_metrics_core_requests_time_total{category="QUERY",core="collection1",handle solr_metrics_core_requests_time_total{category="QUERY",core="collection1",handler="/get"} solr_metrics_core_requests_time_total{category="QUERY",core="collection1",handler="/get[shard]"} solr_metrics_core_requests_time_total{category="QUERY",core="collection1",handler="/graph"} +solr_metrics_core_requests_time_total{category="QUERY",core="collection1",handler="/query"} +solr_metrics_core_requests_time_total{category="QUERY",core="collection1",handler="/query[shard]"} solr_metrics_core_requests_time_total{category="QUERY",core="collection1",handler="/select"} solr_metrics_core_requests_time_total{category="QUERY",core="collection1",handler="/select[shard]"} solr_metrics_core_requests_time_total{category="QUERY",core="collection1",handler="/stream"} @@ -441,6 +520,10 @@ solr_metrics_core_searcher_documents{core="collection1",type="maxDoc"} solr_metrics_core_searcher_documents{core="collection1",type="numDocs"} solr_metrics_core_searcher_documents{core="collection1",type="skipSortCount"} solr_metrics_core_searcher_documents{core="collection1",type="warmupTime"} +# TYPE solr_metrics_core_tlog_total counter +solr_metrics_core_tlog_total{core="collection1",item="applyingBuffered"} +solr_metrics_core_tlog_total{core="collection1",item="copyOverOldUpdates"} +solr_metrics_core_tlog_total{core="collection1",item="replay"} # TYPE solr_metrics_core_update_handler gauge solr_metrics_core_update_handler{category="REPLICATION",core="collection1",handler="/replication",type="generation"} solr_metrics_core_update_handler{category="UPDATE",core="collection1",handler="updateHandler",type="adds"} diff --git a/solr/core/src/test/org/apache/solr/response/TestPrometheusResponseWriter.java b/solr/core/src/test/org/apache/solr/response/TestPrometheusResponseWriter.java index 348e5b12e84..de8a26345f2 100644 --- a/solr/core/src/test/org/apache/solr/response/TestPrometheusResponseWriter.java +++ b/solr/core/src/test/org/apache/solr/response/TestPrometheusResponseWriter.java @@ -16,55 +16,54 @@ */ package org.apache.solr.response; -import java.io.ByteArrayOutputStream; import java.io.File; import java.nio.charset.StandardCharsets; import java.nio.file.Files; +import org.apache.lucene.tests.util.LuceneTestCase; import org.apache.solr.SolrTestCaseJ4; -import org.apache.solr.common.params.CommonParams; +import org.apache.solr.client.solrj.SolrClient; +import org.apache.solr.client.solrj.impl.NoOpResponseParser; +import org.apache.solr.client.solrj.request.QueryRequest; +import org.apache.solr.common.params.ModifiableSolrParams; import org.apache.solr.common.util.NamedList; -import org.apache.solr.handler.admin.MetricsHandler; -import org.apache.solr.request.SolrQueryRequest; +import org.apache.solr.embedded.JettySolrRunner; +import org.apache.solr.util.ExternalPaths; +import org.apache.solr.util.SolrJettyTestRule; import org.junit.BeforeClass; +import org.junit.ClassRule; import org.junit.Test; /** Tests the {@link PrometheusResponseWriter} behavior */ public class TestPrometheusResponseWriter extends SolrTestCaseJ4 { + @ClassRule public static SolrJettyTestRule solrClientTestRule = new SolrJettyTestRule(); + public static JettySolrRunner jetty; + @BeforeClass public static void beforeClass() throws Exception { - initCore("solrconfig-minimal.xml", "schema.xml"); - h.getCoreContainer().waitForLoadingCoresToFinish(30000); + solrClientTestRule.startSolr(LuceneTestCase.createTempDir()); + jetty = solrClientTestRule.getJetty(); + solrClientTestRule.newCollection().withConfigSet(ExternalPaths.DEFAULT_CONFIGSET).create(); + jetty.getCoreContainer().waitForLoadingCoresToFinish(30000); } @Test public void testPrometheusOutput() throws Exception { - SolrQueryRequest req = req("dummy"); - SolrQueryResponse rsp = new SolrQueryResponse(); - PrometheusResponseWriter w = new PrometheusResponseWriter(); - ByteArrayOutputStream byteOut = new ByteArrayOutputStream(); - - MetricsHandler handler = new MetricsHandler(h.getCoreContainer()); - SolrQueryResponse resp = new SolrQueryResponse(); - - handler.handleRequestBody( - req( - CommonParams.QT, - "/admin/metrics", - MetricsHandler.COMPACT_PARAM, - "false", - CommonParams.WT, - "prometheus"), - resp); - NamedList values = resp.getValues(); - rsp.add("metrics", values.get("metrics")); - w.write(byteOut, req, rsp); - String actualOutput = byteOut.toString(StandardCharsets.UTF_8).replaceAll("(?<=}).*", ""); - String expectedOutput = - Files.readString( - new File(TEST_PATH().toString(), "solr-prometheus-output.txt").toPath(), - StandardCharsets.UTF_8); - assertEquals(expectedOutput, actualOutput); - handler.close(); + ModifiableSolrParams params = new ModifiableSolrParams(); + params.set("qt", "/admin/metrics"); + params.set("wt", "prometheus"); + QueryRequest req = new QueryRequest(params); + req.setResponseParser(new NoOpResponseParser("prometheus")); + try (SolrClient adminClient = getHttpSolrClient(jetty.getBaseUrl().toString()); ) { + NamedList res = adminClient.request(req); + assertNotNull("null response from server", res); + String actual = (String) res.get("response"); + System.out.println(actual.replaceAll("(?<=}).*", "")); + String expectedOutput = + Files.readString( + new File(TEST_PATH().toString(), "solr-prometheus-output.txt").toPath(), + StandardCharsets.UTF_8); + assertEquals(expectedOutput, actual.replaceAll("(?<=}).*", "")); + } } } From f1b410a1b821772f05bef5e693d74a6087fc169b Mon Sep 17 00:00:00 2001 From: Matthew Biscocho <54160956+mlbiscoc@users.noreply.github.com> Date: Fri, 21 Jun 2024 14:45:20 -0400 Subject: [PATCH 26/32] Update solr/solr-ref-guide/modules/deployment-guide/pages/monitoring-with-prometheus-and-grafana.adoc Co-authored-by: Christine Poerschke --- .../pages/monitoring-with-prometheus-and-grafana.adoc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/solr/solr-ref-guide/modules/deployment-guide/pages/monitoring-with-prometheus-and-grafana.adoc b/solr/solr-ref-guide/modules/deployment-guide/pages/monitoring-with-prometheus-and-grafana.adoc index 670b43d5a52..cce9aa0da6d 100644 --- a/solr/solr-ref-guide/modules/deployment-guide/pages/monitoring-with-prometheus-and-grafana.adoc +++ b/solr/solr-ref-guide/modules/deployment-guide/pages/monitoring-with-prometheus-and-grafana.adoc @@ -26,7 +26,7 @@ It is not included in the `slim` Solr distribution. A Prometheus exporter (`solr-exporter`) allows users to monitor not only Solr metrics which come from the xref:metrics-reporting.adoc#metrics-api[Metrics API], but also facet counts which come from xref:query-guide:faceting.adoc[] and responses to xref:configuration-guide:collections-api.adoc[] commands and xref:ping.adoc[] requests. -The Metrics API provides a Prometheus Response Writer to output Solr metrics natively to be scraped. It is more efficient and drops the need of running the Prometheus Exporter but at the cost of a fixed output and not as flexiable in terms of configurability. +The Metrics API provides a Prometheus Response Writer to output Solr metrics natively to be scraped. It is more efficient and drops the need of running the Prometheus Exporter but at the cost of a fixed output and not as flexible in terms of configurability. == Prometheus Exporter From a9ee37f80024e7d32a1ab011a816112ed7f2aa7b Mon Sep 17 00:00:00 2001 From: mbiscocho Date: Mon, 24 Jun 2024 10:51:02 -0400 Subject: [PATCH 27/32] Manually register metrics not initializing from JettyTestRule --- .../TestPrometheusResponseWriter.java | 36 ++++++++++++++++++- 1 file changed, 35 insertions(+), 1 deletion(-) diff --git a/solr/core/src/test/org/apache/solr/response/TestPrometheusResponseWriter.java b/solr/core/src/test/org/apache/solr/response/TestPrometheusResponseWriter.java index de8a26345f2..89a0b3ca05f 100644 --- a/solr/core/src/test/org/apache/solr/response/TestPrometheusResponseWriter.java +++ b/solr/core/src/test/org/apache/solr/response/TestPrometheusResponseWriter.java @@ -16,6 +16,8 @@ */ package org.apache.solr.response; +import com.codahale.metrics.Gauge; +import com.codahale.metrics.SettableGauge; import java.io.File; import java.nio.charset.StandardCharsets; import java.nio.file.Files; @@ -27,6 +29,7 @@ import org.apache.solr.common.params.ModifiableSolrParams; import org.apache.solr.common.util.NamedList; import org.apache.solr.embedded.JettySolrRunner; +import org.apache.solr.metrics.SolrMetricManager; import org.apache.solr.util.ExternalPaths; import org.apache.solr.util.SolrJettyTestRule; import org.junit.BeforeClass; @@ -45,6 +48,22 @@ public static void beforeClass() throws Exception { jetty = solrClientTestRule.getJetty(); solrClientTestRule.newCollection().withConfigSet(ExternalPaths.DEFAULT_CONFIGSET).create(); jetty.getCoreContainer().waitForLoadingCoresToFinish(30000); + // Manually register metrics not initializing from JettyTestRule + registerGauge( + jetty.getCoreContainer().getMetricManager(), + "solr.jvm", + "buffers.mapped - 'non-volatile memory'.Count"); + registerGauge( + jetty.getCoreContainer().getMetricManager(), + "solr.jvm", + "buffers.mapped - 'non-volatile memory'.MemoryUsed"); + registerGauge( + jetty.getCoreContainer().getMetricManager(), + "solr.jvm", + "buffers.mapped - 'non-volatile memory'.TotalCapacity"); + registerGauge(jetty.getCoreContainer().getMetricManager(), "solr.jvm", "os.cpuLoad"); + registerGauge(jetty.getCoreContainer().getMetricManager(), "solr.jvm", "os.freeMemorySize"); + registerGauge(jetty.getCoreContainer().getMetricManager(), "solr.jvm", "os.totalMemorySize"); } @Test @@ -58,7 +77,6 @@ public void testPrometheusOutput() throws Exception { NamedList res = adminClient.request(req); assertNotNull("null response from server", res); String actual = (String) res.get("response"); - System.out.println(actual.replaceAll("(?<=}).*", "")); String expectedOutput = Files.readString( new File(TEST_PATH().toString(), "solr-prometheus-output.txt").toPath(), @@ -66,4 +84,20 @@ public void testPrometheusOutput() throws Exception { assertEquals(expectedOutput, actual.replaceAll("(?<=}).*", "")); } } + + public static void registerGauge( + SolrMetricManager metricManager, String registry, String metricName) { + Gauge metric = + new SettableGauge<>() { + @Override + public void setValue(Number value) {} + + @Override + public Number getValue() { + return 0; + } + }; + metricManager.registerGauge( + null, registry, metric, "", SolrMetricManager.ResolutionStrategy.IGNORE, metricName, ""); + } } From 1d7b65a335ee778a990d30d7028989078ddd0441 Mon Sep 17 00:00:00 2001 From: mbiscocho Date: Mon, 1 Jul 2024 16:28:11 -0400 Subject: [PATCH 28/32] Changes from review for refactor and tests --- .../prometheus/core/SolrCoreCacheMetric.java | 9 ++-- .../core/SolrCoreHandlerMetric.java | 15 +++---- .../core/SolrCoreHighlighterMetric.java | 15 ++++--- .../prometheus/core/SolrCoreIndexMetric.java | 15 ++++--- .../core/SolrCoreSearcherMetric.java | 11 ++--- .../prometheus/core/SolrCoreTlogMetric.java | 9 ++-- .../jetty/SolrJettyDispatchesMetric.java | 13 +++--- .../jetty/SolrJettyReqRespMetric.java | 17 ++++---- .../prometheus/jvm/SolrJvmBuffersMetric.java | 25 ++++++----- .../prometheus/jvm/SolrJvmGcMetrics.java | 21 +++++----- .../prometheus/jvm/SolrJvmMemoryMetric.java | 41 +++++++++---------- .../prometheus/jvm/SolrJvmOsMetric.java | 25 +++++------ .../node/SolrNodeContainerMetric.java | 25 ++++++----- .../node/SolrNodeHandlerMetric.java | 30 ++++++-------- .../solr-prometheus-output.txt | 8 ++-- .../handler/admin/MetricsHandlerTest.java | 41 +++++++++++++++++++ .../TestPrometheusResponseWriter.java | 16 ++++---- 17 files changed, 183 insertions(+), 153 deletions(-) rename solr/core/src/test-files/{solr => prometheus}/solr-prometheus-output.txt (99%) diff --git a/solr/core/src/java/org/apache/solr/metrics/prometheus/core/SolrCoreCacheMetric.java b/solr/core/src/java/org/apache/solr/metrics/prometheus/core/SolrCoreCacheMetric.java index d5b646061e6..6c71664102e 100644 --- a/solr/core/src/java/org/apache/solr/metrics/prometheus/core/SolrCoreCacheMetric.java +++ b/solr/core/src/java/org/apache/solr/metrics/prometheus/core/SolrCoreCacheMetric.java @@ -29,6 +29,11 @@ public SolrCoreCacheMetric( super(dropwizardMetric, coreName, metricName, cloudMode); } + /* + * Metric examples being exported + * CACHE.searcher.documentCache + */ + @Override public SolrCoreMetric parseLabels() { String[] parsedMetric = metricName.split("\\."); @@ -38,10 +43,6 @@ public SolrCoreMetric parseLabels() { return this; } - /* - * Metric examples being exported - * CACHE.searcher.documentCache - */ @Override public void toPrometheus(SolrPrometheusExporter exporter) { if (dropwizardMetric instanceof Gauge) { diff --git a/solr/core/src/java/org/apache/solr/metrics/prometheus/core/SolrCoreHandlerMetric.java b/solr/core/src/java/org/apache/solr/metrics/prometheus/core/SolrCoreHandlerMetric.java index 7546662b8cf..3a05fbeb5b0 100644 --- a/solr/core/src/java/org/apache/solr/metrics/prometheus/core/SolrCoreHandlerMetric.java +++ b/solr/core/src/java/org/apache/solr/metrics/prometheus/core/SolrCoreHandlerMetric.java @@ -35,6 +35,14 @@ public SolrCoreHandlerMetric( super(dropwizardMetric, coreName, metricName, cloudMode); } + /* + * Metric examples being exported + * + * QUERY./select.totalTime + * UPDATE./update.requests + * UPDATE./update.totalTime + */ + @Override public SolrCoreMetric parseLabels() { String[] parsedMetric = metricName.split("\\."); @@ -44,13 +52,6 @@ public SolrCoreMetric parseLabels() { return this; } - /* - * Metric examples being exported - * QUERY./select.requests - * QUERY./select.totalTime - * UPDATE./update.requests - * UPDATE./update.totalTime - */ @Override public void toPrometheus(SolrPrometheusExporter exporter) { if (dropwizardMetric instanceof Meter) { diff --git a/solr/core/src/java/org/apache/solr/metrics/prometheus/core/SolrCoreHighlighterMetric.java b/solr/core/src/java/org/apache/solr/metrics/prometheus/core/SolrCoreHighlighterMetric.java index 208d96babba..3d0c57d6043 100644 --- a/solr/core/src/java/org/apache/solr/metrics/prometheus/core/SolrCoreHighlighterMetric.java +++ b/solr/core/src/java/org/apache/solr/metrics/prometheus/core/SolrCoreHighlighterMetric.java @@ -29,6 +29,12 @@ public SolrCoreHighlighterMetric( super(dropwizardMetric, coreName, metricName, cloudMode); } + /* + * Metric examples being exported + * HIGHLIGHTER.SolrBoundaryScanner.default.requests + * HIGHLIGHTER.SolrFragmentsBuilder.colored.requests + */ + @Override public SolrCoreMetric parseLabels() { String[] parsedMetric = metricName.split("\\."); @@ -37,15 +43,8 @@ public SolrCoreMetric parseLabels() { return this; } - /* - * Metric examples being exported - * HIGHLIGHTER.SolrBoundaryScanner.default.requests - * HIGHLIGHTER.SolrFragmentsBuilder.colored.requests - */ @Override public void toPrometheus(SolrPrometheusExporter exporter) { - if (dropwizardMetric instanceof Counter) { - exporter.exportCounter(CORE_HIGHLIGHER_METRICS, (Counter) dropwizardMetric, getLabels()); - } + exporter.exportCounter(CORE_HIGHLIGHER_METRICS, (Counter) dropwizardMetric, getLabels()); } } diff --git a/solr/core/src/java/org/apache/solr/metrics/prometheus/core/SolrCoreIndexMetric.java b/solr/core/src/java/org/apache/solr/metrics/prometheus/core/SolrCoreIndexMetric.java index 239e4f528bb..75a2457668a 100644 --- a/solr/core/src/java/org/apache/solr/metrics/prometheus/core/SolrCoreIndexMetric.java +++ b/solr/core/src/java/org/apache/solr/metrics/prometheus/core/SolrCoreIndexMetric.java @@ -29,21 +29,20 @@ public SolrCoreIndexMetric( super(dropwizardMetric, coreName, metricName, cloudMode); } + /* + * Metric examples being exported + * INDEX.sizeInBytes + */ + @Override public SolrCoreMetric parseLabels() { return this; } - /* - * Metric examples being exported - * INDEX.sizeInBytes - */ @Override public void toPrometheus(SolrPrometheusExporter exporter) { - if (dropwizardMetric instanceof Gauge) { - if (metricName.endsWith("sizeInBytes")) { - exporter.exportGauge(CORE_INDEX_METRICS, (Gauge) dropwizardMetric, getLabels()); - } + if (metricName.endsWith("sizeInBytes")) { + exporter.exportGauge(CORE_INDEX_METRICS, (Gauge) dropwizardMetric, getLabels()); } } } diff --git a/solr/core/src/java/org/apache/solr/metrics/prometheus/core/SolrCoreSearcherMetric.java b/solr/core/src/java/org/apache/solr/metrics/prometheus/core/SolrCoreSearcherMetric.java index fbc098fe612..13d53f38db5 100644 --- a/solr/core/src/java/org/apache/solr/metrics/prometheus/core/SolrCoreSearcherMetric.java +++ b/solr/core/src/java/org/apache/solr/metrics/prometheus/core/SolrCoreSearcherMetric.java @@ -34,6 +34,12 @@ public SolrCoreSearcherMetric( super(dropwizardMetric, coreName, metricName, cloudMode); } + /* + * Metric examples being exported + * SEARCHER.searcher.deletedDocs + * SEARCHER.new.time + */ + @Override public SolrCoreMetric parseLabels() { String[] parsedMetric = metricName.split("\\."); @@ -43,11 +49,6 @@ public SolrCoreMetric parseLabels() { return this; } - /* - * Metric examples being exported - * SEARCHER.searcher.deletedDocs - * SEARCHER.new.time - */ @Override public void toPrometheus(SolrPrometheusExporter exporter) { if (dropwizardMetric instanceof Gauge) { diff --git a/solr/core/src/java/org/apache/solr/metrics/prometheus/core/SolrCoreTlogMetric.java b/solr/core/src/java/org/apache/solr/metrics/prometheus/core/SolrCoreTlogMetric.java index b7d3ba2706d..8aba9cfd7ab 100644 --- a/solr/core/src/java/org/apache/solr/metrics/prometheus/core/SolrCoreTlogMetric.java +++ b/solr/core/src/java/org/apache/solr/metrics/prometheus/core/SolrCoreTlogMetric.java @@ -29,6 +29,11 @@ public SolrCoreTlogMetric( super(dropwizardMetric, coreName, metricName, cloudMode); } + /* + * Metric examples being exported + * TLOG.buffered.ops + */ + @Override public SolrCoreMetric parseLabels() { String[] parsedMetric = metricName.split("\\."); @@ -38,10 +43,6 @@ public SolrCoreMetric parseLabels() { return this; } - /* - * Metric examples being exported - * TLOG.buffered.ops - */ @Override public void toPrometheus(SolrPrometheusExporter exporter) { if (dropwizardMetric instanceof Meter) { diff --git a/solr/core/src/java/org/apache/solr/metrics/prometheus/jetty/SolrJettyDispatchesMetric.java b/solr/core/src/java/org/apache/solr/metrics/prometheus/jetty/SolrJettyDispatchesMetric.java index 42f6af74f7f..dbded5d36ac 100644 --- a/solr/core/src/java/org/apache/solr/metrics/prometheus/jetty/SolrJettyDispatchesMetric.java +++ b/solr/core/src/java/org/apache/solr/metrics/prometheus/jetty/SolrJettyDispatchesMetric.java @@ -29,19 +29,18 @@ public SolrJettyDispatchesMetric(Metric dropwizardMetric, String metricName) { super(dropwizardMetric, metricName); } + /* + * Metric examples being exported + * org.eclipse.jetty.server.handler.DefaultHandler.dispatches + */ + @Override public SolrMetric parseLabels() { return this; } - /* - * Metric examples being exported - * org.eclipse.jetty.server.handler.DefaultHandler.dispatches - */ @Override public void toPrometheus(SolrPrometheusExporter exporter) { - if (dropwizardMetric instanceof Timer) { - exporter.exportTimerCount(JETTY_DISPATCHES_TOTAL, (Timer) dropwizardMetric, getLabels()); - } + exporter.exportTimerCount(JETTY_DISPATCHES_TOTAL, (Timer) dropwizardMetric, getLabels()); } } diff --git a/solr/core/src/java/org/apache/solr/metrics/prometheus/jetty/SolrJettyReqRespMetric.java b/solr/core/src/java/org/apache/solr/metrics/prometheus/jetty/SolrJettyReqRespMetric.java index 3326d30bce3..51c1fd80b3a 100644 --- a/solr/core/src/java/org/apache/solr/metrics/prometheus/jetty/SolrJettyReqRespMetric.java +++ b/solr/core/src/java/org/apache/solr/metrics/prometheus/jetty/SolrJettyReqRespMetric.java @@ -32,6 +32,12 @@ public SolrJettyReqRespMetric(Metric dropwizardMetric, String metricName) { super(dropwizardMetric, metricName); } + /* + * Metric examples being exported + * org.eclipse.jetty.server.handler.DefaultHandler.2xx-responses + * org.eclipse.jetty.server.handler.DefaultHandler.get-requests + */ + @Override public SolrMetric parseLabels() { String[] parsedMetric = metricName.split("\\."); @@ -44,17 +50,10 @@ public SolrMetric parseLabels() { return this; } - /* - * Metric examples being exported - * org.eclipse.jetty.server.handler.DefaultHandler.2xx-responses - * org.eclipse.jetty.server.handler.DefaultHandler.get-requests - */ @Override public void toPrometheus(SolrPrometheusExporter exporter) { - if (dropwizardMetric instanceof Meter) { - if (metricName.endsWith("xx-responses")) { - exporter.exportMeter(JETTY_RESPONSES_TOTAL, (Meter) dropwizardMetric, getLabels()); - } + if (metricName.endsWith("xx-responses")) { + exporter.exportMeter(JETTY_RESPONSES_TOTAL, (Meter) dropwizardMetric, getLabels()); } else if (metricName.endsWith("-requests")) { if (dropwizardMetric instanceof Counter) { exporter.exportCounter(JETTY_REQUESTS_TOTAL, (Counter) dropwizardMetric, getLabels()); diff --git a/solr/core/src/java/org/apache/solr/metrics/prometheus/jvm/SolrJvmBuffersMetric.java b/solr/core/src/java/org/apache/solr/metrics/prometheus/jvm/SolrJvmBuffersMetric.java index 3758f63b6e0..2cd09ac64e8 100644 --- a/solr/core/src/java/org/apache/solr/metrics/prometheus/jvm/SolrJvmBuffersMetric.java +++ b/solr/core/src/java/org/apache/solr/metrics/prometheus/jvm/SolrJvmBuffersMetric.java @@ -29,6 +29,12 @@ public SolrJvmBuffersMetric(Metric dropwizardMetric, String metricName) { super(dropwizardMetric, metricName); } + /* + * Metric examples being exported + * buffers.direct.MemoryUsed + * buffers.mapped.Count + */ + @Override public SolrJvmMetric parseLabels() { String[] parsedMetric = metricName.split("\\."); @@ -37,21 +43,14 @@ public SolrJvmMetric parseLabels() { return this; } - /* - * Metric examples being exported - * buffers.direct.MemoryUsed - * buffers.mapped.Count - */ @Override public void toPrometheus(SolrPrometheusExporter exporter) { - if (dropwizardMetric instanceof Gauge) { - String[] parsedMetric = metricName.split("\\."); - String metricType = parsedMetric[parsedMetric.length - 1]; - if (metricType.equals("Count")) { - exporter.exportGauge(JVM_BUFFERS, (Gauge) dropwizardMetric, getLabels()); - } else if (metricType.equals(("MemoryUsed")) || metricType.equals(("TotalCapacity"))) { - exporter.exportGauge(JVM_BUFFERS_BYTES, (Gauge) dropwizardMetric, getLabels()); - } + String[] parsedMetric = metricName.split("\\."); + String metricType = parsedMetric[parsedMetric.length - 1]; + if (metricType.equals("Count")) { + exporter.exportGauge(JVM_BUFFERS, (Gauge) dropwizardMetric, getLabels()); + } else if (metricType.equals(("MemoryUsed")) || metricType.equals(("TotalCapacity"))) { + exporter.exportGauge(JVM_BUFFERS_BYTES, (Gauge) dropwizardMetric, getLabels()); } } } diff --git a/solr/core/src/java/org/apache/solr/metrics/prometheus/jvm/SolrJvmGcMetrics.java b/solr/core/src/java/org/apache/solr/metrics/prometheus/jvm/SolrJvmGcMetrics.java index 79ad2ca2777..50aca3bff27 100644 --- a/solr/core/src/java/org/apache/solr/metrics/prometheus/jvm/SolrJvmGcMetrics.java +++ b/solr/core/src/java/org/apache/solr/metrics/prometheus/jvm/SolrJvmGcMetrics.java @@ -30,6 +30,12 @@ public SolrJvmGcMetrics(Metric dropwizardMetric, String metricName) { super(dropwizardMetric, metricName); } + /* + * Metric examples being exported + * gc.G1-Old-Generation.time + * gc.G1-Young-Generation.count + */ + @Override public SolrMetric parseLabels() { String[] parsedMetric = metricName.split("\\."); @@ -37,19 +43,12 @@ public SolrMetric parseLabels() { return this; } - /* - * Metric examples being exported - * gc.G1-Old-Generation.time - * gc.G1-Young-Generation.count - */ @Override public void toPrometheus(SolrPrometheusExporter exporter) { - if (dropwizardMetric instanceof Gauge) { - if (metricName.endsWith(".count")) { - exporter.exportGauge(JVM_GC, (Gauge) dropwizardMetric, getLabels()); - } else if (metricName.endsWith(".time")) { - exporter.exportGauge(JVM_GC_SECONDS, (Gauge) dropwizardMetric, getLabels()); - } + if (metricName.endsWith(".count")) { + exporter.exportGauge(JVM_GC, (Gauge) dropwizardMetric, getLabels()); + } else if (metricName.endsWith(".time")) { + exporter.exportGauge(JVM_GC_SECONDS, (Gauge) dropwizardMetric, getLabels()); } } } diff --git a/solr/core/src/java/org/apache/solr/metrics/prometheus/jvm/SolrJvmMemoryMetric.java b/solr/core/src/java/org/apache/solr/metrics/prometheus/jvm/SolrJvmMemoryMetric.java index 3ac189117dc..180edae2100 100644 --- a/solr/core/src/java/org/apache/solr/metrics/prometheus/jvm/SolrJvmMemoryMetric.java +++ b/solr/core/src/java/org/apache/solr/metrics/prometheus/jvm/SolrJvmMemoryMetric.java @@ -30,13 +30,6 @@ public SolrJvmMemoryMetric(Metric dropwizardMetric, String metricName) { super(dropwizardMetric, metricName); } - @Override - public SolrMetric parseLabels() { - String[] parsedMetric = metricName.split("\\."); - labels.put("item", parsedMetric[parsedMetric.length - 1]); - return this; - } - /* * Metric examples being exported * memory.heap.usage @@ -44,23 +37,29 @@ public SolrMetric parseLabels() { * memory.total.committed * memory.pools.CodeHeap-'non-nmethods'.committed */ + + @Override + public SolrMetric parseLabels() { + String[] parsedMetric = metricName.split("\\."); + labels.put("item", parsedMetric[parsedMetric.length - 1]); + return this; + } + @Override public void toPrometheus(SolrPrometheusExporter exporter) { String[] parsedMetric = metricName.split("\\."); - if (dropwizardMetric instanceof Gauge) { - String metricType = parsedMetric[1]; - switch (metricType) { - case "heap": - case "non-heap": - case "total": - labels.put("memory", parsedMetric[1]); - exporter.exportGauge(JVM_MEMORY, (Gauge) dropwizardMetric, getLabels()); - break; - case "pools": - labels.put("space", parsedMetric[2]); - exporter.exportGauge(JVM_MEMORY_POOL_BYTES, (Gauge) dropwizardMetric, getLabels()); - break; - } + String metricType = parsedMetric[1]; + switch (metricType) { + case "heap": + case "non-heap": + case "total": + labels.put("memory", parsedMetric[1]); + exporter.exportGauge(JVM_MEMORY, (Gauge) dropwizardMetric, getLabels()); + break; + case "pools": + labels.put("space", parsedMetric[2]); + exporter.exportGauge(JVM_MEMORY_POOL_BYTES, (Gauge) dropwizardMetric, getLabels()); + break; } } } diff --git a/solr/core/src/java/org/apache/solr/metrics/prometheus/jvm/SolrJvmOsMetric.java b/solr/core/src/java/org/apache/solr/metrics/prometheus/jvm/SolrJvmOsMetric.java index 407a2fc3b3d..fc42c6ac8ef 100644 --- a/solr/core/src/java/org/apache/solr/metrics/prometheus/jvm/SolrJvmOsMetric.java +++ b/solr/core/src/java/org/apache/solr/metrics/prometheus/jvm/SolrJvmOsMetric.java @@ -30,6 +30,12 @@ public SolrJvmOsMetric(Metric dropwizardMetric, String metricName) { super(dropwizardMetric, metricName); } + /* + * Metric examples being exported + * os.availableProcessors + * threads.peak.count + */ + @Override public SolrMetric parseLabels() { String[] parsedMetric = metricName.split("\\."); @@ -41,23 +47,12 @@ public SolrMetric parseLabels() { return this; } - /* - * Metric examples being exported - * os.availableProcessors - * threads.peak.count - */ @Override public void toPrometheus(SolrPrometheusExporter exporter) { - String exportName = ""; - if (dropwizardMetric instanceof Gauge) { - if (metricName.startsWith("threads.")) { - exportName = JVM_OS_THREADS; - } else { - exportName = JVM_OS; - } - } - if (!exportName.isEmpty()) { - exporter.exportGauge(exportName, (Gauge) dropwizardMetric, getLabels()); + if (metricName.startsWith("threads.")) { + exporter.exportGauge(JVM_OS_THREADS, (Gauge) dropwizardMetric, getLabels()); + } else { + exporter.exportGauge(JVM_OS, (Gauge) dropwizardMetric, getLabels()); } } } diff --git a/solr/core/src/java/org/apache/solr/metrics/prometheus/node/SolrNodeContainerMetric.java b/solr/core/src/java/org/apache/solr/metrics/prometheus/node/SolrNodeContainerMetric.java index 10eb64d0539..bb48eea9790 100644 --- a/solr/core/src/java/org/apache/solr/metrics/prometheus/node/SolrNodeContainerMetric.java +++ b/solr/core/src/java/org/apache/solr/metrics/prometheus/node/SolrNodeContainerMetric.java @@ -30,6 +30,12 @@ public SolrNodeContainerMetric(Metric dropwizardMetric, String metricName) { super(dropwizardMetric, metricName); } + /* + * Metric examples being exported + * CONTAINER.fs.coreRoot.totalSpace + * CONTAINER.cores.loaded + */ + @Override public SolrMetric parseLabels() { String[] parsedMetric = metricName.split("\\."); @@ -37,22 +43,15 @@ public SolrMetric parseLabels() { return this; } - /* - * Metric examples being exported - * CONTAINER.fs.coreRoot.totalSpace - * CONTAINER.cores.loaded - */ @Override public void toPrometheus(SolrPrometheusExporter exporter) { String[] parsedMetric = metricName.split("\\."); - if (dropwizardMetric instanceof Gauge) { - if (metricName.startsWith("CONTAINER.cores.")) { - labels.put("item", parsedMetric[2]); - exporter.exportGauge(NODE_CORES, (Gauge) dropwizardMetric, getLabels()); - } else if (metricName.startsWith("CONTAINER.fs.coreRoot.")) { - labels.put("item", parsedMetric[3]); - exporter.exportGauge(NODE_CORE_FS_BYTES, (Gauge) dropwizardMetric, getLabels()); - } + if (metricName.startsWith("CONTAINER.cores.")) { + labels.put("item", parsedMetric[2]); + exporter.exportGauge(NODE_CORES, (Gauge) dropwizardMetric, getLabels()); + } else if (metricName.startsWith("CONTAINER.fs.coreRoot.")) { + labels.put("item", parsedMetric[3]); + exporter.exportGauge(NODE_CORE_FS_BYTES, (Gauge) dropwizardMetric, getLabels()); } } } diff --git a/solr/core/src/java/org/apache/solr/metrics/prometheus/node/SolrNodeHandlerMetric.java b/solr/core/src/java/org/apache/solr/metrics/prometheus/node/SolrNodeHandlerMetric.java index 0cfd37bcc76..2d28ce90703 100644 --- a/solr/core/src/java/org/apache/solr/metrics/prometheus/node/SolrNodeHandlerMetric.java +++ b/solr/core/src/java/org/apache/solr/metrics/prometheus/node/SolrNodeHandlerMetric.java @@ -33,6 +33,12 @@ public SolrNodeHandlerMetric(Metric dropwizardMetric, String metricName) { super(dropwizardMetric, metricName); } + /* + * Metric examples being exported + * ADMIN./admin/collections.requests + * UPDATE.updateShardHandler.maxConnections + */ + @Override public SolrMetric parseLabels() { String[] parsedMetric = metricName.split("\\."); @@ -42,27 +48,17 @@ public SolrMetric parseLabels() { return this; } - /* - * Metric examples being exported - * ADMIN./admin/collections.requests - * UPDATE.updateShardHandler.maxConnections - */ @Override public void toPrometheus(SolrPrometheusExporter exporter) { - if (dropwizardMetric instanceof Meter) { + if (metricName.endsWith(".totalTime")) { + labels.remove("type"); + exporter.exportCounter(NODE_SECONDS_TOTAL, (Counter) dropwizardMetric, getLabels()); + } else if (metricName.endsWith("Connections")) { + exporter.exportGauge(NODE_CONNECTIONS, (Gauge) dropwizardMetric, getLabels()); + } else if (dropwizardMetric instanceof Meter) { exporter.exportMeter(NODE_REQUESTS, (Meter) dropwizardMetric, getLabels()); } else if (dropwizardMetric instanceof Counter) { - if (metricName.endsWith(".requests")) { - exporter.exportCounter(NODE_REQUESTS, (Counter) dropwizardMetric, getLabels()); - } else if (metricName.endsWith(".totalTime")) { - // Do not need type label for total time - labels.remove("type"); - exporter.exportCounter(NODE_SECONDS_TOTAL, (Counter) dropwizardMetric, getLabels()); - } - } else if (dropwizardMetric instanceof Gauge) { - if (metricName.endsWith("Connections")) { - exporter.exportGauge(NODE_CONNECTIONS, (Gauge) dropwizardMetric, getLabels()); - } + exporter.exportCounter(NODE_REQUESTS, (Counter) dropwizardMetric, getLabels()); } } } diff --git a/solr/core/src/test-files/solr/solr-prometheus-output.txt b/solr/core/src/test-files/prometheus/solr-prometheus-output.txt similarity index 99% rename from solr/core/src/test-files/solr/solr-prometheus-output.txt rename to solr/core/src/test-files/prometheus/solr-prometheus-output.txt index cd11a690210..825381fe4e8 100644 --- a/solr/core/src/test-files/solr/solr-prometheus-output.txt +++ b/solr/core/src/test-files/prometheus/solr-prometheus-output.txt @@ -10,11 +10,11 @@ solr_metrics_jvm_buffers_bytes{item="TotalCapacity",pool="direct"} solr_metrics_jvm_buffers_bytes{item="TotalCapacity",pool="mapped"} solr_metrics_jvm_buffers_bytes{item="TotalCapacity",pool="mapped - 'non-volatile memory'"} # TYPE solr_metrics_jvm_gc gauge -solr_metrics_jvm_gc{item="PS-MarkSweep"} -solr_metrics_jvm_gc{item="PS-Scavenge"} +solr_metrics_jvm_gc{} +solr_metrics_jvm_gc{} # TYPE solr_metrics_jvm_gc_seconds gauge -solr_metrics_jvm_gc_seconds{item="PS-MarkSweep"} -solr_metrics_jvm_gc_seconds{item="PS-Scavenge"} +solr_metrics_jvm_gc_seconds{} +solr_metrics_jvm_gc_seconds{} # TYPE solr_metrics_jvm_heap gauge solr_metrics_jvm_heap{item="committed",memory="heap"} solr_metrics_jvm_heap{item="committed",memory="non-heap"} diff --git a/solr/core/src/test/org/apache/solr/handler/admin/MetricsHandlerTest.java b/solr/core/src/test/org/apache/solr/handler/admin/MetricsHandlerTest.java index d8a5cdf1cd9..f638e2cc68b 100644 --- a/solr/core/src/test/org/apache/solr/handler/admin/MetricsHandlerTest.java +++ b/solr/core/src/test/org/apache/solr/handler/admin/MetricsHandlerTest.java @@ -999,6 +999,47 @@ public void testPrometheusMetricsJetty() throws Exception { handler.close(); } + @Test + @SuppressWarnings("unchecked") + public void testPrometheusMetricsFilter() throws Exception { + MetricsHandler handler = new MetricsHandler(h.getCoreContainer()); + + SolrQueryResponse resp = new SolrQueryResponse(); + handler.handleRequestBody( + req( + CommonParams.QT, + "/admin/metrics", + CommonParams.WT, + "prometheus", + "group", + "core", + "type", + "counter", + "prefix", + "QUERY"), + resp); + + NamedList values = resp.getValues(); + assertNotNull(values.get("metrics")); + values = (NamedList) values.get("metrics"); + SolrPrometheusExporter exporter = (SolrPrometheusExporter) values.get("solr.core.collection1"); + assertNotNull(exporter); + MetricSnapshots actualSnapshots = exporter.collect(); + assertNotNull(actualSnapshots); + + actualSnapshots.forEach( + (k) -> { + k.getDataPoints() + .forEach( + (datapoint) -> { + assertTrue(datapoint instanceof CounterSnapshot.CounterDataPointSnapshot); + assertEquals("QUERY", datapoint.getLabels().get("category")); + }); + }); + + handler.close(); + } + @Test public void testMetricsUnload() throws Exception { diff --git a/solr/core/src/test/org/apache/solr/response/TestPrometheusResponseWriter.java b/solr/core/src/test/org/apache/solr/response/TestPrometheusResponseWriter.java index 89a0b3ca05f..f46f5a0f85d 100644 --- a/solr/core/src/test/org/apache/solr/response/TestPrometheusResponseWriter.java +++ b/solr/core/src/test/org/apache/solr/response/TestPrometheusResponseWriter.java @@ -18,8 +18,6 @@ import com.codahale.metrics.Gauge; import com.codahale.metrics.SettableGauge; -import java.io.File; -import java.nio.charset.StandardCharsets; import java.nio.file.Files; import org.apache.lucene.tests.util.LuceneTestCase; import org.apache.solr.SolrTestCaseJ4; @@ -78,14 +76,18 @@ public void testPrometheusOutput() throws Exception { assertNotNull("null response from server", res); String actual = (String) res.get("response"); String expectedOutput = - Files.readString( - new File(TEST_PATH().toString(), "solr-prometheus-output.txt").toPath(), - StandardCharsets.UTF_8); - assertEquals(expectedOutput, actual.replaceAll("(?<=}).*", "")); + Files.readString(getFile("prometheus/solr-prometheus-output.txt").toPath()); + // Expression to strip out ending numeric values and JVM item tag as we only want to test for + // Prometheus metric names + actual = + actual.replaceAll( + "(?<=}).*|(?<=solr_metrics_jvm_gc\\{)(.*)(?=})|(?<=solr_metrics_jvm_gc_seconds\\{)(.*)(?=})", + ""); + assertEquals(expectedOutput, actual); } } - public static void registerGauge( + private static void registerGauge( SolrMetricManager metricManager, String registry, String metricName) { Gauge metric = new SettableGauge<>() { From d6786ecab0cc219565de77028f2a6b6101b2e3c4 Mon Sep 17 00:00:00 2001 From: Matthew Biscocho Date: Mon, 1 Jul 2024 21:19:53 -0400 Subject: [PATCH 29/32] Add additional documentation to ref-guide --- .../deployment-guide/pages/metrics-reporting.adoc | 6 +++++- .../pages/monitoring-with-prometheus-and-grafana.adoc | 9 ++++++--- 2 files changed, 11 insertions(+), 4 deletions(-) diff --git a/solr/solr-ref-guide/modules/deployment-guide/pages/metrics-reporting.adoc b/solr/solr-ref-guide/modules/deployment-guide/pages/metrics-reporting.adoc index f3309f65a6b..8295050aa9f 100644 --- a/solr/solr-ref-guide/modules/deployment-guide/pages/metrics-reporting.adoc +++ b/solr/solr-ref-guide/modules/deployment-guide/pages/metrics-reporting.adoc @@ -879,7 +879,11 @@ The response will look like this: ]} ---- -Like other request handlers, the Metrics API can also take the `wt` parameter to define the output format. The Metrics API also provides an additional special `wt` parameter `prometheus` that will output metrics in Prometheus format. This can be used for xref:monitoring-with-prometheus-and-grafana.adoc#metrics-api-with-prometheus-format[Monitoring with Prometheus and Grafana] +Like other request handlers, the Metrics API can also take the `wt` parameter to define the output format. +The Metrics API also provides an additional special `wt` parameter `prometheus` that will output metrics in Prometheus format. +This can be used for xref:monitoring-with-prometheus-and-grafana.adoc#metrics-api-with-prometheus-format[Monitoring with Prometheus and Grafana] + +*Note: The `group`, `type`, and `prefix` query parameters are still available for filtering Prometheus metrics but `regex`, `property`, `key` and `compact` are not supported.* [[metrics_examples]] === Examples diff --git a/solr/solr-ref-guide/modules/deployment-guide/pages/monitoring-with-prometheus-and-grafana.adoc b/solr/solr-ref-guide/modules/deployment-guide/pages/monitoring-with-prometheus-and-grafana.adoc index 3cb92d5b31f..73db518efa9 100644 --- a/solr/solr-ref-guide/modules/deployment-guide/pages/monitoring-with-prometheus-and-grafana.adoc +++ b/solr/solr-ref-guide/modules/deployment-guide/pages/monitoring-with-prometheus-and-grafana.adoc @@ -26,7 +26,8 @@ It is not included in the `slim` Solr distribution. A Prometheus exporter (`solr-exporter`) allows users to monitor not only Solr metrics which come from the xref:metrics-reporting.adoc#metrics-api[Metrics API], but also facet counts which come from xref:query-guide:faceting.adoc[] and responses to xref:configuration-guide:collections-api.adoc[] commands and xref:ping.adoc[] requests. -The Metrics API provides a Prometheus Response Writer to output Solr metrics natively to be scraped. It is more efficient and drops the need of running the Prometheus Exporter but at the cost of a fixed output and not as flexible in terms of configurability. +The Metrics API provides a Prometheus Response Writer to output Solr metrics natively to be scraped. +It is more efficient and drops the need of running the Prometheus Exporter but at the cost of a fixed output and not as flexible in terms of configurability. == Prometheus Exporter @@ -613,11 +614,13 @@ Prometheus Metrics are available natively directly from Solr by leveraging the M [source,text] localhost:8983/solr/admin/metrics?wt=prometheus -The Metrics API with the `prometheus` parameter does not provide any configurability and the Prometheus output is fixed. Any metrics aggregations and/or filtering must be done on Grafana or the Prometheus server. +The Metrics API with the `prometheus` parameter does not provide any configurability and the Prometheus output is fixed. +Any metrics aggregations and/or filtering must be done on Grafana or the Prometheus server. === Prometheus Configuration -Like the Prometheus Exporter, the `prometheus.yml` needs to be configurated for the Prometheus Server to ingest metrics. The difference is it must instead scrape the Metrics API with the `wt=prometheus` parameter directly from each host/port Solr is running on as in this example: +Like the Prometheus Exporter, the `prometheus.yml` needs to be configurated for the Prometheus Server to ingest metrics. +The difference is it must instead scrape the Metrics API with the `wt=prometheus` parameter directly from each host/port Solr is running on as in this example: [source,plain] ---- From d6bd407bf66451ce1171984a4860f860dd1c27e6 Mon Sep 17 00:00:00 2001 From: Matthew Biscocho Date: Mon, 1 Jul 2024 21:20:31 -0400 Subject: [PATCH 30/32] Remove some JVM tests --- .../solr/handler/admin/MetricsHandlerTest.java | 18 ++---------------- 1 file changed, 2 insertions(+), 16 deletions(-) diff --git a/solr/core/src/test/org/apache/solr/handler/admin/MetricsHandlerTest.java b/solr/core/src/test/org/apache/solr/handler/admin/MetricsHandlerTest.java index f638e2cc68b..217c07433e4 100644 --- a/solr/core/src/test/org/apache/solr/handler/admin/MetricsHandlerTest.java +++ b/solr/core/src/test/org/apache/solr/handler/admin/MetricsHandlerTest.java @@ -913,13 +913,9 @@ public void testPrometheusMetricsJvm() throws Exception { MetricSnapshots actualSnapshots = exporter.collect(); assertNotNull(actualSnapshots); - MetricSnapshot actualSnapshot = getMetricSnapshot(actualSnapshots, "solr_metrics_jvm_gc"); + MetricSnapshot actualSnapshot = getMetricSnapshot(actualSnapshots, "solr_metrics_jvm_threads"); GaugeSnapshot.GaugeDataPointSnapshot actualGaugeDataPoint = - getGaugeDatapointSnapshot(actualSnapshot, Labels.of("item", "G1-Old-Generation")); - assertEquals(0, actualGaugeDataPoint.getValue(), 0); - - actualSnapshot = getMetricSnapshot(actualSnapshots, "solr_metrics_jvm_threads"); - actualGaugeDataPoint = getGaugeDatapointSnapshot(actualSnapshot, Labels.of("item", "count")); + getGaugeDatapointSnapshot(actualSnapshot, Labels.of("item", "count")); assertNotNull(actualGaugeDataPoint); actualSnapshot = getMetricSnapshot(actualSnapshots, "solr_metrics_jvm_memory_pools_bytes"); @@ -928,11 +924,6 @@ public void testPrometheusMetricsJvm() throws Exception { actualSnapshot, Labels.of("item", "committed", "space", "CodeHeap-'non-nmethods'")); assertEquals(0, actualGaugeDataPoint.getValue(), 0); - actualSnapshot = getMetricSnapshot(actualSnapshots, "solr_metrics_os"); - actualGaugeDataPoint = - getGaugeDatapointSnapshot(actualSnapshot, Labels.of("item", "availableProcessors")); - assertNotNull(actualGaugeDataPoint); - actualSnapshot = getMetricSnapshot(actualSnapshots, "solr_metrics_jvm_buffers"); actualGaugeDataPoint = getGaugeDatapointSnapshot(actualSnapshot, Labels.of("item", "Count", "pool", "direct")); @@ -949,11 +940,6 @@ public void testPrometheusMetricsJvm() throws Exception { actualSnapshot, Labels.of("item", "MemoryUsed", "pool", "direct")); assertNotNull(actualGaugeDataPoint); - actualSnapshot = getMetricSnapshot(actualSnapshots, "solr_metrics_jvm_gc_seconds"); - actualGaugeDataPoint = - getGaugeDatapointSnapshot(actualSnapshot, Labels.of("item", "G1-Old-Generation")); - assertEquals(0, actualGaugeDataPoint.getValue(), 0); - handler.close(); } From 9f1abbe33203fc0991ef540034c99cd864b6b798 Mon Sep 17 00:00:00 2001 From: Matthew Biscocho Date: Mon, 1 Jul 2024 21:20:44 -0400 Subject: [PATCH 31/32] Add entry into CHANGES.txt --- solr/CHANGES.txt | 2 ++ 1 file changed, 2 insertions(+) diff --git a/solr/CHANGES.txt b/solr/CHANGES.txt index 2ca207bbf42..07cb94cf273 100644 --- a/solr/CHANGES.txt +++ b/solr/CHANGES.txt @@ -115,6 +115,8 @@ New Features * SOLR-17335: New "vectorSimilarity" QParser for matching documents mased on a minimum vector similarity threshold. (hossman) +* SOLR-10654: Introduce output of Prometheus metrics directly from Solr + Improvements --------------------- * SOLR-17137: Enable Prometheus exporter to communicate with SSL protected Solr. (Eivind Bergstøl via Eric Pugh) From 5da678ce09adca7b5c542a46b5d40e966e2f4186 Mon Sep 17 00:00:00 2001 From: Matthew Biscocho <54160956+mlbiscoc@users.noreply.github.com> Date: Wed, 3 Jul 2024 09:40:57 -0400 Subject: [PATCH 32/32] Add names to CHANGES.txt --- solr/CHANGES.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/solr/CHANGES.txt b/solr/CHANGES.txt index 07cb94cf273..ed409c8214b 100644 --- a/solr/CHANGES.txt +++ b/solr/CHANGES.txt @@ -115,7 +115,7 @@ New Features * SOLR-17335: New "vectorSimilarity" QParser for matching documents mased on a minimum vector similarity threshold. (hossman) -* SOLR-10654: Introduce output of Prometheus metrics directly from Solr +* SOLR-10654: Introduce output of Prometheus metrics directly from Solr. (Matthew Biscocho via David Smiley) Improvements ---------------------