001package io.prometheus.metrics.model.registry;
002
003import io.prometheus.metrics.model.snapshots.MetricSnapshot;
004import io.prometheus.metrics.model.snapshots.MetricSnapshots;
005import java.util.Collections;
006import java.util.List;
007import java.util.function.Predicate;
008import javax.annotation.Nullable;
009
010/** Like {@link Collector}, but collecting multiple Snapshots at once. */
011@FunctionalInterface
012public interface MultiCollector {
013
014  /** Called when the Prometheus server scrapes metrics. */
015  MetricSnapshots collect();
016
017  /**
018   * Provides Collector with the details of the request issued by Prometheus to allow multi-target
019   * pattern implementation Override to implement request dependent logic to provide MetricSnapshot
020   */
021  default MetricSnapshots collect(PrometheusScrapeRequest scrapeRequest) {
022    return collect();
023  }
024
025  /**
026   * Like {@link #collect()}, but returns only the snapshots where {@code includedNames.test(name)}
027   * is {@code true}.
028   *
029   * <p>Override this if there is a more efficient way than first collecting all snapshot and then
030   * discarding the excluded ones.
031   */
032  default MetricSnapshots collect(Predicate<String> includedNames) {
033    return collect(includedNames, null);
034  }
035
036  /**
037   * Like {@link #collect(Predicate)}, but with support for multi-target pattern.
038   *
039   * <p>Override this if there is a more efficient way than first collecting the snapshot and then
040   * discarding it.
041   */
042  default MetricSnapshots collect(
043      Predicate<String> includedNames, @Nullable PrometheusScrapeRequest scrapeRequest) {
044    MetricSnapshots allSnapshots = scrapeRequest == null ? collect() : collect(scrapeRequest);
045    MetricSnapshots.Builder result = MetricSnapshots.builder();
046    for (MetricSnapshot snapshot : allSnapshots) {
047      if (includedNames.test(snapshot.getMetadata().getPrometheusName())) {
048        result.metricSnapshot(snapshot);
049      }
050    }
051    return result.build();
052  }
053
054  /**
055   * This is called in two places:
056   *
057   * <ol>
058   *   <li>During registration to check if a metric with that name already exists.
059   *   <li>During scrape to check if the collector can be skipped because a name filter is present
060   *       and all names are excluded.
061   * </ol>
062   *
063   * Returning an empty list means checks are omitted (registration metric always succeeds), and the
064   * collector is always scraped (if a name filter is present and all names are excluded the result
065   * is dropped).
066   *
067   * <p>If your collector returns a constant list of metrics that have names that do not change at
068   * runtime it is a good idea to overwrite this and return the names.
069   */
070  default List<String> getPrometheusNames() {
071    return Collections.emptyList();
072  }
073}