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