001package io.prometheus.metrics.instrumentation.dropwizard;
002
003import com.codahale.metrics.Counter;
004import com.codahale.metrics.Gauge;
005import com.codahale.metrics.Histogram;
006import com.codahale.metrics.Meter;
007import com.codahale.metrics.Metric;
008import com.codahale.metrics.MetricFilter;
009import com.codahale.metrics.MetricRegistry;
010import com.codahale.metrics.Snapshot;
011import com.codahale.metrics.Timer;
012import io.prometheus.metrics.annotations.StableApi;
013import io.prometheus.metrics.instrumentation.dropwizard5.InvalidMetricHandler;
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 4.x metrics from a MetricRegistry.
022 *
023 * <p>This is a thin wrapper around {@link AbstractDropwizardExports} that handles the Dropwizard
024 * 4.x specific API where metric names are Strings.
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 and {@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    // For Dropwizard 4.x, map keys are Strings, so we just use identity function
086    collectMetricKind(
087        metricSnapshots, registry.getGauges(metricFilter), this::fromGauge, key -> key);
088    collectMetricKind(
089        metricSnapshots, registry.getCounters(metricFilter), this::fromCounter, key -> key);
090    collectMetricKind(
091        metricSnapshots, registry.getHistograms(metricFilter), this::fromHistogram, key -> key);
092    collectMetricKind(
093        metricSnapshots, registry.getTimers(metricFilter), this::fromTimer, key -> key);
094    collectMetricKind(
095        metricSnapshots, registry.getMeters(metricFilter), this::fromMeter, key -> key);
096    return metricSnapshots.build();
097  }
098
099  @Override
100  protected long getCounterCount(Counter counter) {
101    return counter.getCount();
102  }
103
104  @Override
105  protected Object getGaugeValue(Gauge<?> gauge) {
106    return gauge.getValue();
107  }
108
109  @Override
110  protected Snapshot getHistogramSnapshot(Histogram histogram) {
111    return histogram.getSnapshot();
112  }
113
114  @Override
115  protected long getHistogramCount(Histogram histogram) {
116    return histogram.getCount();
117  }
118
119  @Override
120  protected Snapshot getTimerSnapshot(Timer timer) {
121    return timer.getSnapshot();
122  }
123
124  @Override
125  protected long getTimerCount(Timer timer) {
126    return timer.getCount();
127  }
128
129  @Override
130  protected long getMeterCount(Meter meter) {
131    return meter.getCount();
132  }
133
134  @Override
135  protected double getMedian(Snapshot snapshot) {
136    return snapshot.getMedian();
137  }
138
139  @Override
140  protected double get75thPercentile(Snapshot snapshot) {
141    return snapshot.get75thPercentile();
142  }
143
144  @Override
145  protected double get95thPercentile(Snapshot snapshot) {
146    return snapshot.get95thPercentile();
147  }
148
149  @Override
150  protected double get98thPercentile(Snapshot snapshot) {
151    return snapshot.get98thPercentile();
152  }
153
154  @Override
155  protected double get99thPercentile(Snapshot snapshot) {
156    return snapshot.get99thPercentile();
157  }
158
159  @Override
160  protected double get999thPercentile(Snapshot snapshot) {
161    return snapshot.get999thPercentile();
162  }
163
164  public static Builder builder() {
165    return new Builder();
166  }
167
168  // Builder class for DropwizardExports
169  public static class Builder {
170    @Nullable private MetricRegistry registry;
171    private MetricFilter metricFilter;
172    @Nullable private CustomLabelMapper labelMapper;
173    private InvalidMetricHandler invalidMetricHandler;
174
175    private Builder() {
176      this.metricFilter = MetricFilter.ALL;
177      this.invalidMetricHandler = InvalidMetricHandler.ALWAYS_THROW;
178    }
179
180    public Builder dropwizardRegistry(MetricRegistry registry) {
181      this.registry = registry;
182      return this;
183    }
184
185    public Builder metricFilter(MetricFilter metricFilter) {
186      this.metricFilter = metricFilter;
187      return this;
188    }
189
190    public Builder customLabelMapper(CustomLabelMapper labelMapper) {
191      this.labelMapper = labelMapper;
192      return this;
193    }
194
195    public Builder invalidMetricHandler(InvalidMetricHandler invalidMetricHandler) {
196      this.invalidMetricHandler = invalidMetricHandler;
197      return this;
198    }
199
200    DropwizardExports build() {
201      if (registry == null) {
202        throw new IllegalArgumentException("MetricRegistry must be set");
203      }
204      return new DropwizardExports(registry, metricFilter, labelMapper, invalidMetricHandler);
205    }
206
207    public void register() {
208      register(PrometheusRegistry.defaultRegistry);
209    }
210
211    public void register(PrometheusRegistry registry) {
212      DropwizardExports dropwizardExports = build();
213      registry.register(dropwizardExports);
214    }
215  }
216}