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