Skip to content

Commit 5f345cd

Browse files
vjkoskelaBrandonArp
authored andcommitted
Allow any percentile to be computed or passed through CAGG if so requested by MAD. (#87)
1 parent 4545c09 commit 5f345cd

File tree

9 files changed

+48
-216
lines changed

9 files changed

+48
-216
lines changed

src/main/java/com/arpnetworking/tsdcore/statistics/StatisticFactory.java

Lines changed: 34 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -17,19 +17,18 @@
1717

1818
import com.arpnetworking.utility.InterfaceDatabase;
1919
import com.arpnetworking.utility.ReflectionsDatabase;
20-
import com.google.common.collect.ImmutableMap;
21-
import com.google.common.collect.ImmutableSet;
2220
import com.google.common.collect.Maps;
23-
import com.google.common.collect.Sets;
2421
import org.slf4j.Logger;
2522
import org.slf4j.LoggerFactory;
2623

2724
import java.lang.reflect.Constructor;
2825
import java.lang.reflect.InvocationTargetException;
2926
import java.lang.reflect.Modifier;
30-
import java.util.Map;
3127
import java.util.Optional;
3228
import java.util.Set;
29+
import java.util.concurrent.ConcurrentMap;
30+
import java.util.regex.Matcher;
31+
import java.util.regex.Pattern;
3332

3433
/**
3534
* Creates statistics.
@@ -60,31 +59,36 @@ public Statistic getStatistic(final String name) {
6059
* @return A new <code>Statistic</code>.
6160
*/
6261
public Optional<Statistic> tryGetStatistic(final String name) {
63-
return Optional.ofNullable(STATISTICS_BY_NAME_AND_ALIAS.get(name));
64-
}
65-
66-
/**
67-
* Get all registered <code>Statistic</code> instances.
68-
*
69-
* @return A new <code>Statistic</code>.
70-
*/
71-
public ImmutableSet<Statistic> getAllStatistics() {
72-
return ALL_STATISTICS;
62+
final Optional<Statistic> registeredStatistic =
63+
Optional.ofNullable(STATISTICS_BY_NAME_AND_ALIAS.get(name));
64+
if (!registeredStatistic.isPresent()) {
65+
final Matcher matcher = PERCENTILE_STATISTIC_PATTERN.matcher(name);
66+
if (matcher.matches()) {
67+
try {
68+
final String percentileString = matcher.group("percentile").replace('p', '.');
69+
final double percentile = Double.parseDouble(percentileString);
70+
final Statistic statistic = new TPStatistic(percentile);
71+
checkedPut(STATISTICS_BY_NAME_AND_ALIAS, statistic);
72+
return Optional.of(statistic);
73+
} catch (final NumberFormatException e) {
74+
LOGGER.error(String.format(
75+
"Invalid percentile statistic; name=%s",
76+
name));
77+
return registeredStatistic;
78+
}
79+
}
80+
}
81+
return registeredStatistic;
7382
}
7483

75-
/**
76-
* Creates a statistic from a name.
77-
*
78-
* @param statistic The name of the desired statistic.
79-
* @return A new <code>Statistic</code>.
80-
* @deprecated Use <code>getStatistic</code> instead.
81-
*/
82-
@Deprecated
83-
public Optional<Statistic> createStatistic(final String statistic) {
84-
return Optional.ofNullable(STATISTICS_BY_NAME_AND_ALIAS.get(statistic));
84+
private static void checkedPut(final ConcurrentMap<String, Statistic> map, final Statistic statistic) {
85+
checkedPut(map, statistic, statistic.getName());
86+
for (final String alias : statistic.getAliases()) {
87+
checkedPut(map, statistic, alias);
88+
}
8589
}
8690

87-
private static void checkedPut(final Map<String, Statistic> map, final Statistic statistic, final String key) {
91+
private static void checkedPut(final ConcurrentMap<String, Statistic> map, final Statistic statistic, final String key) {
8892
final Statistic existingStatistic = map.get(key);
8993
if (existingStatistic != null) {
9094
if (!existingStatistic.equals(statistic)) {
@@ -99,15 +103,14 @@ private static void checkedPut(final Map<String, Statistic> map, final Statistic
99103
map.put(key, statistic);
100104
}
101105

102-
private static final ImmutableMap<String, Statistic> STATISTICS_BY_NAME_AND_ALIAS;
103-
private static final ImmutableSet<Statistic> ALL_STATISTICS;
106+
private static final Pattern PERCENTILE_STATISTIC_PATTERN = Pattern.compile("^[t]?p(?<percentile>[0-9]+(?:(\\.|p)[0-9]+)?)$");
107+
private static final ConcurrentMap<String, Statistic> STATISTICS_BY_NAME_AND_ALIAS;
104108
private static final InterfaceDatabase INTERFACE_DATABASE = ReflectionsDatabase.newInstance();
105109
private static final Logger LOGGER = LoggerFactory.getLogger(StatisticFactory.class);
106110

107111
static {
108112
// NOTE: Do not put log messages in static blocks since they can lock the logger thread!
109-
final Map<String, Statistic> statisticByNameAndAlias = Maps.newHashMap();
110-
final Set<Statistic> allStatistics = Sets.newHashSet();
113+
final ConcurrentMap<String, Statistic> statisticByNameAndAlias = Maps.newConcurrentMap();
111114
final Set<Class<? extends Statistic>> statisticClasses = INTERFACE_DATABASE.findClassesWithInterface(Statistic.class);
112115
for (final Class<? extends Statistic> statisticClass : statisticClasses) {
113116
if (!statisticClass.isInterface() && !Modifier.isAbstract(statisticClass.getModifiers())) {
@@ -116,19 +119,13 @@ private static void checkedPut(final Map<String, Statistic> map, final Statistic
116119
if (!constructor.isAccessible()) {
117120
constructor.setAccessible(true);
118121
}
119-
final Statistic statistic = constructor.newInstance();
120-
allStatistics.add(statistic);
121-
checkedPut(statisticByNameAndAlias, statistic, statistic.getName());
122-
for (final String alias : statistic.getAliases()) {
123-
checkedPut(statisticByNameAndAlias, statistic, alias);
124-
}
122+
checkedPut(statisticByNameAndAlias, constructor.newInstance());
125123
} catch (final InvocationTargetException | NoSuchMethodException
126124
| InstantiationException | IllegalAccessException e) {
127125
LOGGER.warn(String.format("Unable to load statistic; class=%s", statisticClass), e);
128126
}
129127
}
130128
}
131-
STATISTICS_BY_NAME_AND_ALIAS = ImmutableMap.copyOf(statisticByNameAndAlias);
132-
ALL_STATISTICS = ImmutableSet.copyOf(allStatistics);
129+
STATISTICS_BY_NAME_AND_ALIAS = statisticByNameAndAlias;
133130
}
134131
}

src/main/java/com/arpnetworking/tsdcore/statistics/TP75Statistic.java

Lines changed: 0 additions & 33 deletions
This file was deleted.

src/main/java/com/arpnetworking/tsdcore/statistics/TP90Statistic.java

Lines changed: 0 additions & 33 deletions
This file was deleted.

src/main/java/com/arpnetworking/tsdcore/statistics/TP95Statistic.java

Lines changed: 0 additions & 33 deletions
This file was deleted.

src/main/java/com/arpnetworking/tsdcore/statistics/TP99Statistic.java

Lines changed: 0 additions & 33 deletions
This file was deleted.

src/main/java/com/arpnetworking/tsdcore/statistics/TP99p9Statistic.java

Lines changed: 0 additions & 33 deletions
This file was deleted.

src/main/java/com/arpnetworking/tsdcore/statistics/TPStatistic.java

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@
3636
*
3737
* @author Brandon Arp (brandon dot arp at inscopemetrics dot com)
3838
*/
39-
public abstract class TPStatistic extends BaseStatistic implements OrderedStatistic {
39+
public class TPStatistic extends BaseStatistic implements OrderedStatistic {
4040

4141
/**
4242
* Accessor for the percentile from 0 to 100 (inclusive).
@@ -85,11 +85,11 @@ public Quantity calculateAggregations(final List<AggregatedData> aggregations) {
8585
}
8686

8787
/**
88-
* Protected constructor.
88+
* Public constructor.
8989
*
90-
* @param percentile The percentile value to compute.
90+
* @param percentile the percentile value to compute
9191
*/
92-
protected TPStatistic(final double percentile) {
92+
public TPStatistic(final double percentile) {
9393
_percentile = percentile;
9494
_defaultName = "tp" + FORMAT.format(_percentile);
9595
_aliases = Sets.newHashSet();

src/test/java/com/arpnetworking/tsdcore/statistics/StatisticFactoryTest.java

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -47,11 +47,11 @@ public static Collection<Object[]> createParameters() {
4747
a(l("count", "n"), CountStatistic.class),
4848
a(l("p0", "tp0", "min"), MinStatistic.class),
4949
a(l("p50", "tp50", "median"), MedianStatistic.class),
50-
a(l("p75", "tp75"), TP75Statistic.class),
51-
a(l("p90", "tp90"), TP90Statistic.class),
52-
a(l("p95", "tp95"), TP95Statistic.class),
53-
a(l("p99", "tp99"), TP99Statistic.class),
54-
a(l("p99.9", "tp99.9", "p99p9", "tp99p9"), TP99p9Statistic.class),
50+
a(l("p75", "tp75"), TPStatistic.class),
51+
a(l("p90", "tp90"), TPStatistic.class),
52+
a(l("p95", "tp95"), TPStatistic.class),
53+
a(l("p99", "tp99"), TPStatistic.class),
54+
a(l("p99.9", "tp99.9", "p99p9", "tp99p9"), TPStatistic.class),
5555
a(l("p100", "tp100", "max"), MaxStatistic.class)
5656
);
5757
}

src/test/java/com/arpnetworking/tsdcore/statistics/TPStatisticTest.java

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -203,9 +203,9 @@ private boolean areClose(final Quantity expected, final Quantity actual) {
203203
private static final List<Double> ONE_TO_FIVE = Lists.newArrayList(1d, 2d, 3d, 4d, 5d);
204204
private static final StatisticFactory STATISTIC_FACTORY = new StatisticFactory();
205205
private static final Statistic HISTOGRAM_STATISTIC = STATISTIC_FACTORY.getStatistic("histogram");
206-
private static final TP75Statistic TP75_STATISTIC = (TP75Statistic) STATISTIC_FACTORY.getStatistic("tp75");
207-
private static final TP90Statistic TP90_STATISTIC = (TP90Statistic) STATISTIC_FACTORY.getStatistic("tp90");
208-
private static final TP95Statistic TP95_STATISTIC = (TP95Statistic) STATISTIC_FACTORY.getStatistic("tp95");
209-
private static final TP99Statistic TP99_STATISTIC = (TP99Statistic) STATISTIC_FACTORY.getStatistic("tp99");
210-
private static final TP99p9Statistic TP99P9_STATISTIC = (TP99p9Statistic) STATISTIC_FACTORY.getStatistic("tp99p9");
206+
private static final TPStatistic TP75_STATISTIC = (TPStatistic) STATISTIC_FACTORY.getStatistic("tp75");
207+
private static final TPStatistic TP90_STATISTIC = (TPStatistic) STATISTIC_FACTORY.getStatistic("tp90");
208+
private static final TPStatistic TP95_STATISTIC = (TPStatistic) STATISTIC_FACTORY.getStatistic("tp95");
209+
private static final TPStatistic TP99_STATISTIC = (TPStatistic) STATISTIC_FACTORY.getStatistic("tp99");
210+
private static final TPStatistic TP99P9_STATISTIC = (TPStatistic) STATISTIC_FACTORY.getStatistic("tp99p9");
211211
}

0 commit comments

Comments
 (0)