001package io.prometheus.metrics.instrumentation.dropwizard5;
002
003import io.dropwizard.metrics5.Counter;
004import io.dropwizard.metrics5.Gauge;
005import io.dropwizard.metrics5.Histogram;
006import io.dropwizard.metrics5.Meter;
007import io.dropwizard.metrics5.Metric;
008import io.dropwizard.metrics5.MetricFilter;
009import io.dropwizard.metrics5.MetricName;
010import io.dropwizard.metrics5.MetricRegistry;
011import io.dropwizard.metrics5.Snapshot;
012import io.dropwizard.metrics5.Timer;
013import io.prometheus.metrics.instrumentation.dropwizard5.internal.AbstractDropwizardExports;
014import io.prometheus.metrics.instrumentation.dropwizard5.labels.CustomLabelMapper;
015import io.prometheus.metrics.model.registry.PrometheusRegistry;
016import io.prometheus.metrics.model.snapshots.MetricSnapshots;
017import javax.annotation.Nullable;
018
019/**
020 * Collect Dropwizard 5.x metrics from a MetricRegistry.
021 *
022 * <p>This is a thin wrapper around {@link AbstractDropwizardExports} that handles the Dropwizard
023 * 5.x specific API where metric names are {@link MetricName} objects.
024 */
025public class DropwizardExports
026    extends AbstractDropwizardExports<
027        MetricRegistry,
028        MetricFilter,
029        Counter,
030        Gauge<?>,
031        Histogram,
032        Timer,
033        Meter,
034        Metric,
035        Snapshot> {
036
037  /**
038   * Creates a new DropwizardExports with {@link MetricFilter#ALL}.
039   *
040   * @param registry a metric registry to export in prometheus.
041   */
042  public DropwizardExports(MetricRegistry registry) {
043    this(registry, MetricFilter.ALL, null, InvalidMetricHandler.ALWAYS_THROW);
044  }
045
046  /**
047   * Creates a new DropwizardExports with a custom {@link MetricFilter}.
048   *
049   * @param registry a metric registry to export in prometheus.
050   * @param metricFilter a custom metric filter.
051   */
052  public DropwizardExports(MetricRegistry registry, MetricFilter metricFilter) {
053    this(registry, metricFilter, null, InvalidMetricHandler.ALWAYS_THROW);
054  }
055
056  /**
057   * @param registry a metric registry to export in prometheus.
058   * @param metricFilter a custom metric filter.
059   * @param labelMapper a labelMapper to use to map labels.
060   */
061  public DropwizardExports(
062      MetricRegistry registry, MetricFilter metricFilter, @Nullable CustomLabelMapper labelMapper) {
063    this(registry, metricFilter, labelMapper, InvalidMetricHandler.ALWAYS_THROW);
064  }
065
066  /**
067   * @param registry a metric registry to export in prometheus.
068   * @param metricFilter a custom metric filter.
069   * @param labelMapper a labelMapper to use to map labels.
070   * @param invalidMetricHandler handler for invalid metrics.
071   */
072  private DropwizardExports(
073      MetricRegistry registry,
074      MetricFilter metricFilter,
075      @Nullable CustomLabelMapper labelMapper,
076      InvalidMetricHandler invalidMetricHandler) {
077    super(registry, metricFilter, labelMapper, invalidMetricHandler);
078  }
079
080  @Override
081  protected MetricSnapshots collectMetricSnapshots() {
082    MetricSnapshots.Builder metricSnapshots = MetricSnapshots.builder();
083    collectMetricKind(
084        metricSnapshots,
085        registry.getGauges(metricFilter),
086        this::fromGauge,
087        this::extractMetricName);
088    collectMetricKind(
089        metricSnapshots,
090        registry.getCounters(metricFilter),
091        this::fromCounter,
092        this::extractMetricName);
093    collectMetricKind(
094        metricSnapshots,
095        registry.getHistograms(metricFilter),
096        this::fromHistogram,
097        this::extractMetricName);
098    collectMetricKind(
099        metricSnapshots,
100        registry.getTimers(metricFilter),
101        this::fromTimer,
102        this::extractMetricName);
103    collectMetricKind(
104        metricSnapshots,
105        registry.getMeters(metricFilter),
106        this::fromMeter,
107        this::extractMetricName);
108    return metricSnapshots.build();
109  }
110
111  private String extractMetricName(MetricName metricName) {
112    return metricName.getKey();
113  }
114
115  @Override
116  protected long getCounterCount(Counter counter) {
117    return counter.getCount();
118  }
119
120  @Override
121  protected Object getGaugeValue(Gauge<?> gauge) {
122    return gauge.getValue();
123  }
124
125  @Override
126  protected Snapshot getHistogramSnapshot(Histogram histogram) {
127    return histogram.getSnapshot();
128  }
129
130  @Override
131  protected long getHistogramCount(Histogram histogram) {
132    return histogram.getCount();
133  }
134
135  @Override
136  protected Snapshot getTimerSnapshot(Timer timer) {
137    return timer.getSnapshot();
138  }
139
140  @Override
141  protected long getTimerCount(Timer timer) {
142    return timer.getCount();
143  }
144
145  @Override
146  protected long getMeterCount(Meter meter) {
147    return meter.getCount();
148  }
149
150  @Override
151  protected double getMedian(Snapshot snapshot) {
152    return snapshot.getMedian();
153  }
154
155  @Override
156  protected double get75thPercentile(Snapshot snapshot) {
157    return snapshot.get75thPercentile();
158  }
159
160  @Override
161  protected double get95thPercentile(Snapshot snapshot) {
162    return snapshot.get95thPercentile();
163  }
164
165  @Override
166  protected double get98thPercentile(Snapshot snapshot) {
167    return snapshot.get98thPercentile();
168  }
169
170  @Override
171  protected double get99thPercentile(Snapshot snapshot) {
172    return snapshot.get99thPercentile();
173  }
174
175  @Override
176  protected double get999thPercentile(Snapshot snapshot) {
177    return snapshot.get999thPercentile();
178  }
179
180  public static Builder builder() {
181    return new Builder();
182  }
183
184  // Builder class for DropwizardExports
185  public static class Builder {
186    @Nullable private MetricRegistry registry;
187    private MetricFilter metricFilter;
188    @Nullable private CustomLabelMapper labelMapper;
189    private InvalidMetricHandler invalidMetricHandler;
190
191    private Builder() {
192      this.metricFilter = MetricFilter.ALL;
193      this.invalidMetricHandler = InvalidMetricHandler.ALWAYS_THROW;
194    }
195
196    public Builder dropwizardRegistry(MetricRegistry registry) {
197      this.registry = registry;
198      return this;
199    }
200
201    public Builder metricFilter(MetricFilter metricFilter) {
202      this.metricFilter = metricFilter;
203      return this;
204    }
205
206    public Builder customLabelMapper(CustomLabelMapper labelMapper) {
207      this.labelMapper = labelMapper;
208      return this;
209    }
210
211    public Builder invalidMetricHandler(InvalidMetricHandler invalidMetricHandler) {
212      this.invalidMetricHandler = invalidMetricHandler;
213      return this;
214    }
215
216    DropwizardExports build() {
217      if (registry == null) {
218        throw new IllegalArgumentException("MetricRegistry must be set");
219      }
220      return new DropwizardExports(registry, metricFilter, labelMapper, invalidMetricHandler);
221    }
222
223    public void register() {
224      register(PrometheusRegistry.defaultRegistry);
225    }
226
227    public void register(PrometheusRegistry registry) {
228      DropwizardExports dropwizardExports = build();
229      registry.register(dropwizardExports);
230    }
231  }
232}