15
15
*/
16
16
package com .arpnetworking .tsdcore .statistics ;
17
17
18
+ import com .arpnetworking .steno .Logger ;
19
+ import com .arpnetworking .steno .LoggerFactory ;
18
20
import com .arpnetworking .utility .InterfaceDatabase ;
19
21
import com .arpnetworking .utility .ReflectionsDatabase ;
22
+ import com .google .common .collect .ImmutableList ;
20
23
import com .google .common .collect .Maps ;
21
- import org .slf4j .Logger ;
22
- import org .slf4j .LoggerFactory ;
23
24
24
25
import java .lang .reflect .Constructor ;
25
26
import java .lang .reflect .InvocationTargetException ;
@@ -62,25 +63,33 @@ public Optional<Statistic> tryGetStatistic(final String name) {
62
63
final Optional <Statistic > registeredStatistic =
63
64
Optional .ofNullable (STATISTICS_BY_NAME_AND_ALIAS .get (name ));
64
65
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
- }
66
+ final Optional <Statistic > statistic = getPercentileStatistic (name );
67
+ if (statistic .isPresent ()) {
68
+ checkedPut (STATISTICS_BY_NAME_AND_ALIAS , statistic .get ());
69
+ return statistic ;
79
70
}
80
71
}
81
72
return registeredStatistic ;
82
73
}
83
74
75
+ private static Optional <Statistic > getPercentileStatistic (final String name ) {
76
+ final Matcher matcher = PERCENTILE_STATISTIC_PATTERN .matcher (name );
77
+ if (matcher .matches ()) {
78
+ try {
79
+ final String percentileString = matcher .group ("percentile" ).replace ('p' , '.' );
80
+ final double percentile = Double .parseDouble (percentileString );
81
+ final Statistic statistic = new TPStatistic (percentile );
82
+ return Optional .of (statistic );
83
+ } catch (final NumberFormatException e ) {
84
+ LOGGER .error ()
85
+ .setMessage ("Invalid percentile statistic" )
86
+ .addData ("name" , name )
87
+ .log ();
88
+ }
89
+ }
90
+ return Optional .empty ();
91
+ }
92
+
84
93
private static void checkedPut (final ConcurrentMap <String , Statistic > map , final Statistic statistic ) {
85
94
checkedPut (map , statistic , statistic .getName ());
86
95
for (final String alias : statistic .getAliases ()) {
@@ -106,14 +115,16 @@ private static void checkedPut(final ConcurrentMap<String, Statistic> map, final
106
115
private static final Pattern PERCENTILE_STATISTIC_PATTERN = Pattern .compile ("^[t]?p(?<percentile>[0-9]+(?:(\\ .|p)[0-9]+)?)$" );
107
116
private static final ConcurrentMap <String , Statistic > STATISTICS_BY_NAME_AND_ALIAS ;
108
117
private static final InterfaceDatabase INTERFACE_DATABASE = ReflectionsDatabase .newInstance ();
118
+ private static final ImmutableList <String > PERCENTILE_STATISTICS_TO_PRELOAD = ImmutableList .of ("p75" , "p90" , "p95" , "p99" , "p99.9" );
109
119
private static final Logger LOGGER = LoggerFactory .getLogger (StatisticFactory .class );
110
120
111
121
static {
112
122
// NOTE: Do not put log messages in static blocks since they can lock the logger thread!
113
123
final ConcurrentMap <String , Statistic > statisticByNameAndAlias = Maps .newConcurrentMap ();
114
124
final Set <Class <? extends Statistic >> statisticClasses = INTERFACE_DATABASE .findClassesWithInterface (Statistic .class );
115
125
for (final Class <? extends Statistic > statisticClass : statisticClasses ) {
116
- if (!statisticClass .isInterface () && !Modifier .isAbstract (statisticClass .getModifiers ())) {
126
+ if (!statisticClass .isInterface () && !Modifier .isAbstract (statisticClass .getModifiers ())
127
+ && !TPStatistic .class .equals (statisticClass )) {
117
128
try {
118
129
final Constructor <? extends Statistic > constructor = statisticClass .getDeclaredConstructor ();
119
130
if (!constructor .isAccessible ()) {
@@ -126,6 +137,17 @@ private static void checkedPut(final ConcurrentMap<String, Statistic> map, final
126
137
}
127
138
}
128
139
}
140
+ for (final String percentileStatisticName : PERCENTILE_STATISTICS_TO_PRELOAD ) {
141
+ final Optional <Statistic > statistic = getPercentileStatistic (percentileStatisticName );
142
+ if (statistic .isPresent ()) {
143
+ checkedPut (statisticByNameAndAlias , statistic .get ());
144
+ } else {
145
+ LOGGER .warn ()
146
+ .setMessage ("Unable to load statistic" )
147
+ .addData ("name" , percentileStatisticName )
148
+ .log ();
149
+ }
150
+ }
129
151
STATISTICS_BY_NAME_AND_ALIAS = statisticByNameAndAlias ;
130
152
}
131
153
}
0 commit comments