io.dropwizard.metrics.BaseReporterFactory Maven / Gradle / Ivy
package io.dropwizard.metrics;
import com.codahale.metrics.MetricFilter;
import com.codahale.metrics.ScheduledReporter;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.google.common.cache.CacheBuilder;
import com.google.common.cache.CacheLoader;
import com.google.common.cache.LoadingCache;
import com.google.common.collect.ImmutableSet;
import io.dropwizard.util.Duration;
import io.dropwizard.validation.MinDuration;
import org.hibernate.validator.valuehandling.UnwrapValidatedValue;
import javax.validation.Valid;
import javax.validation.constraints.NotNull;
import java.util.Optional;
import java.util.concurrent.TimeUnit;
import java.util.regex.Pattern;
/**
* A base {@link ReporterFactory} for configuring metric reporters.
*
* Configures options common to all {@link ScheduledReporter}s.
*
* Configuration Parameters:
*
*
* Name
* Default
* Description
*
*
* durationUnit
* milliseconds
* The unit to report durations as. Overrides per-metric duration units.
*
*
* rateUnit
* seconds
* The unit to report rates as. Overrides per-metric rate units.
*
*
* excludes
* No excluded metrics.
* Metrics to exclude from reports, by name. When defined, matching metrics will not be
* reported. See {@link #getFilter()}.
*
*
* includes
* All metrics included.
* Metrics to include in reports, by name. When defined, only these metrics will be
* reported. See {@link #getFilter()}. Exclusion rules (excludes) take precedence,
* so if a name matches both excludes and includes, it is excluded.
*
*
* useRegexFilters
* false
* Indicates whether the values of the 'includes' and 'excludes' fields should be
* treated as regular expressions or not.
*
*
* frequency
* none
* The frequency to report metrics. Overrides the {@link
* MetricsFactory#getFrequency() default}.
*
*
*/
public abstract class BaseReporterFactory implements ReporterFactory {
private static final DefaultStringMatchingStrategy DEFAULT_STRING_MATCHING_STRATEGY =
new DefaultStringMatchingStrategy();
private static final RegexStringMatchingStrategy REGEX_STRING_MATCHING_STRATEGY =
new RegexStringMatchingStrategy();
@NotNull
private TimeUnit durationUnit = TimeUnit.MILLISECONDS;
@NotNull
private TimeUnit rateUnit = TimeUnit.SECONDS;
@NotNull
private ImmutableSet excludes = ImmutableSet.of();
@NotNull
private ImmutableSet includes = ImmutableSet.of();
@Valid
@MinDuration(0)
@UnwrapValidatedValue
private Optional frequency = Optional.empty();
private boolean useRegexFilters = false;
public TimeUnit getDurationUnit() {
return durationUnit;
}
@JsonProperty
public void setDurationUnit(TimeUnit durationUnit) {
this.durationUnit = durationUnit;
}
@JsonProperty
public TimeUnit getRateUnit() {
return rateUnit;
}
@JsonProperty
public void setRateUnit(final TimeUnit rateUnit) {
this.rateUnit = rateUnit;
}
@JsonProperty
public ImmutableSet getIncludes() {
return includes;
}
@JsonProperty
public void setIncludes(ImmutableSet includes) {
this.includes = includes;
}
@JsonProperty
public ImmutableSet getExcludes() {
return excludes;
}
@JsonProperty
public void setExcludes(ImmutableSet excludes) {
this.excludes = excludes;
}
@JsonProperty
public Optional getFrequency() {
return frequency;
}
@JsonProperty
public void setFrequency(Optional frequency) {
this.frequency = frequency;
}
@JsonProperty
public boolean getUseRegexFilters() {
return useRegexFilters;
}
@JsonProperty
public void setUseRegexFilters(boolean useRegexFilters) {
this.useRegexFilters = useRegexFilters;
}
/**
* Gets a {@link MetricFilter} that specifically includes and excludes configured metrics.
*
* Filtering works in 4 ways:
*
* - unfiltered
* - All metrics are reported
* - excludes-only
* - All metrics are reported, except those whose name is listed in excludes.
* - includes-only
* - Only metrics whose name is listed in includes are reported.
* - mixed (both includes and excludes
* - Only metrics whose name is listed in includes and
* not listed in excludes are reported;
* excludes takes precedence over includes.
*
*
* @return the filter for selecting metrics based on the configured excludes/includes.
* @see #getIncludes()
* @see #getExcludes()
*/
@JsonIgnore
public MetricFilter getFilter() {
final StringMatchingStrategy stringMatchingStrategy = getUseRegexFilters() ?
REGEX_STRING_MATCHING_STRATEGY : DEFAULT_STRING_MATCHING_STRATEGY;
return (name, metric) -> {
// Include the metric if its name is not excluded and its name is included
// Where, by default, with no includes setting, all names are included.
return !stringMatchingStrategy.containsMatch(getExcludes(), name) &&
(getIncludes().isEmpty() || stringMatchingStrategy.containsMatch(getIncludes(), name));
};
}
private interface StringMatchingStrategy {
boolean containsMatch(ImmutableSet matchExpressions, String metricName);
}
private static class DefaultStringMatchingStrategy implements StringMatchingStrategy {
@Override
public boolean containsMatch(ImmutableSet matchExpressions, String metricName) {
return matchExpressions.contains(metricName);
}
}
private static class RegexStringMatchingStrategy implements StringMatchingStrategy {
private final LoadingCache patternCache;
private RegexStringMatchingStrategy() {
patternCache = CacheBuilder.newBuilder()
.expireAfterWrite(1, TimeUnit.HOURS)
.build(new CacheLoader() {
@Override
public Pattern load(String regex) throws Exception {
return Pattern.compile(regex);
}
});
}
@Override
public boolean containsMatch(ImmutableSet matchExpressions, String metricName) {
for (String regexExpression : matchExpressions) {
if (patternCache.getUnchecked(regexExpression).matcher(metricName).matches()) {
// just need to match on a single value - return as soon as we do
return true;
}
}
return false;
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy