1616
1717package io .grpc ;
1818
19+ import static com .google .common .base .Preconditions .checkArgument ;
20+ import static com .google .common .base .Preconditions .checkNotNull ;
21+
22+ import com .google .common .annotations .VisibleForTesting ;
23+ import com .google .common .base .Strings ;
24+ import java .util .Arrays ;
1925import java .util .Collections ;
26+ import java .util .HashSet ;
2027import java .util .List ;
2128import java .util .Set ;
22- import java .util .concurrent .CopyOnWriteArrayList ;
23- import java .util .concurrent .CopyOnWriteArraySet ;
29+ import javax .annotation .concurrent .GuardedBy ;
2430
2531/**
2632 * A registry for globally registered metric instruments.
2733 */
2834@ Internal
2935public final class MetricInstrumentRegistry {
36+ static final int INITIAL_INSTRUMENT_CAPACITY = 5 ;
3037 private static MetricInstrumentRegistry instance ;
31- private final List <MetricInstrument > metricInstruments ;
32- private final Set <String > registeredMetricNames ;
38+ private final Object lock = new Object ();
39+ @ GuardedBy ("lock" )
40+ private final Set <String > registeredMetricNames = new HashSet <>();
41+ @ GuardedBy ("lock" )
42+ private MetricInstrument [] metricInstruments =
43+ new MetricInstrument [INITIAL_INSTRUMENT_CAPACITY ];
44+ @ GuardedBy ("lock" )
45+ private int nextAvailableMetricIndex ;
3346
34- private MetricInstrumentRegistry () {
35- this .metricInstruments = new CopyOnWriteArrayList <>();
36- this .registeredMetricNames = new CopyOnWriteArraySet <>();
37- }
47+ @ VisibleForTesting
48+ MetricInstrumentRegistry () {}
3849
3950 /**
4051 * Returns the default metric instrument registry.
@@ -50,7 +61,10 @@ public static synchronized MetricInstrumentRegistry getDefaultRegistry() {
5061 * Returns a list of registered metric instruments.
5162 */
5263 public List <MetricInstrument > getMetricInstruments () {
53- return Collections .unmodifiableList (metricInstruments );
64+ synchronized (lock ) {
65+ return Collections .unmodifiableList (
66+ Arrays .asList (Arrays .copyOfRange (metricInstruments , 0 , nextAvailableMetricIndex )));
67+ }
5468 }
5569
5670 /**
@@ -65,20 +79,30 @@ public List<MetricInstrument> getMetricInstruments() {
6579 * @return the newly created DoubleCounterMetricInstrument
6680 * @throws IllegalStateException if a metric with the same name already exists
6781 */
68- // TODO(dnvindhya): Evaluate locks over synchronized methods and update if needed
69- public synchronized DoubleCounterMetricInstrument registerDoubleCounter (String name ,
82+ public DoubleCounterMetricInstrument registerDoubleCounter (String name ,
7083 String description , String unit , List <String > requiredLabelKeys ,
7184 List <String > optionalLabelKeys , boolean enableByDefault ) {
72- if (registeredMetricNames .contains (name )) {
73- throw new IllegalStateException ("Metric with name " + name + " already exists" );
85+ checkArgument (!Strings .isNullOrEmpty (name ), "missing metric name" );
86+ checkNotNull (description , "description" );
87+ checkNotNull (unit , "unit" );
88+ checkNotNull (requiredLabelKeys , "requiredLabelKeys" );
89+ checkNotNull (optionalLabelKeys , "optionalLabelKeys" );
90+ synchronized (lock ) {
91+ if (registeredMetricNames .contains (name )) {
92+ throw new IllegalStateException ("Metric with name " + name + " already exists" );
93+ }
94+ int index = nextAvailableMetricIndex ;
95+ if (index + 1 == metricInstruments .length ) {
96+ resizeMetricInstruments ();
97+ }
98+ DoubleCounterMetricInstrument instrument = new DoubleCounterMetricInstrument (
99+ index , name , description , unit , requiredLabelKeys , optionalLabelKeys ,
100+ enableByDefault );
101+ metricInstruments [index ] = instrument ;
102+ registeredMetricNames .add (name );
103+ nextAvailableMetricIndex += 1 ;
104+ return instrument ;
74105 }
75- long instrumentIndex = metricInstruments .size ();
76- DoubleCounterMetricInstrument instrument = new DoubleCounterMetricInstrument (
77- instrumentIndex , name , description , unit , requiredLabelKeys , optionalLabelKeys ,
78- enableByDefault );
79- metricInstruments .add (instrument );
80- registeredMetricNames .add (name );
81- return instrument ;
82106 }
83107
84108 /**
@@ -93,20 +117,30 @@ public synchronized DoubleCounterMetricInstrument registerDoubleCounter(String n
93117 * @return the newly created LongCounterMetricInstrument
94118 * @throws IllegalStateException if a metric with the same name already exists
95119 */
96- public synchronized LongCounterMetricInstrument registerLongCounter (String name ,
120+ public LongCounterMetricInstrument registerLongCounter (String name ,
97121 String description , String unit , List <String > requiredLabelKeys ,
98122 List <String > optionalLabelKeys , boolean enableByDefault ) {
99- if (registeredMetricNames .contains (name )) {
100- throw new IllegalStateException ("Metric with name " + name + " already exists" );
123+ checkArgument (!Strings .isNullOrEmpty (name ), "missing metric name" );
124+ checkNotNull (description , "description" );
125+ checkNotNull (unit , "unit" );
126+ checkNotNull (requiredLabelKeys , "requiredLabelKeys" );
127+ checkNotNull (optionalLabelKeys , "optionalLabelKeys" );
128+ synchronized (lock ) {
129+ if (registeredMetricNames .contains (name )) {
130+ throw new IllegalStateException ("Metric with name " + name + " already exists" );
131+ }
132+ int index = nextAvailableMetricIndex ;
133+ if (index + 1 == metricInstruments .length ) {
134+ resizeMetricInstruments ();
135+ }
136+ LongCounterMetricInstrument instrument = new LongCounterMetricInstrument (
137+ index , name , description , unit , requiredLabelKeys , optionalLabelKeys ,
138+ enableByDefault );
139+ metricInstruments [index ] = instrument ;
140+ registeredMetricNames .add (name );
141+ nextAvailableMetricIndex += 1 ;
142+ return instrument ;
101143 }
102- // Acquire lock?
103- long instrumentIndex = metricInstruments .size ();
104- LongCounterMetricInstrument instrument = new LongCounterMetricInstrument (
105- instrumentIndex , name , description , unit , requiredLabelKeys , optionalLabelKeys ,
106- enableByDefault );
107- metricInstruments .add (instrument );
108- registeredMetricNames .add (name );
109- return instrument ;
110144 }
111145
112146 /**
@@ -122,20 +156,32 @@ public synchronized LongCounterMetricInstrument registerLongCounter(String name,
122156 * @return the newly created DoubleHistogramMetricInstrument
123157 * @throws IllegalStateException if a metric with the same name already exists
124158 */
125- public synchronized DoubleHistogramMetricInstrument registerDoubleHistogram (String name ,
159+ public DoubleHistogramMetricInstrument registerDoubleHistogram (String name ,
126160 String description , String unit , List <Double > bucketBoundaries ,
127161 List <String > requiredLabelKeys , List <String > optionalLabelKeys , boolean enableByDefault ) {
128- if (registeredMetricNames .contains (name )) {
129- throw new IllegalStateException ("Metric with name " + name + " already exists" );
162+ checkArgument (!Strings .isNullOrEmpty (name ), "missing metric name" );
163+ checkNotNull (description , "description" );
164+ checkNotNull (unit , "unit" );
165+ checkNotNull (bucketBoundaries , "bucketBoundaries" );
166+ checkNotNull (requiredLabelKeys , "requiredLabelKeys" );
167+ checkNotNull (optionalLabelKeys , "optionalLabelKeys" );
168+ synchronized (lock ) {
169+ if (registeredMetricNames .contains (name )) {
170+ throw new IllegalStateException ("Metric with name " + name + " already exists" );
171+ }
172+ int index = nextAvailableMetricIndex ;
173+ if (index + 1 == metricInstruments .length ) {
174+ resizeMetricInstruments ();
175+ }
176+ DoubleHistogramMetricInstrument instrument = new DoubleHistogramMetricInstrument (
177+ index , name , description , unit , bucketBoundaries , requiredLabelKeys ,
178+ optionalLabelKeys ,
179+ enableByDefault );
180+ metricInstruments [index ] = instrument ;
181+ registeredMetricNames .add (name );
182+ nextAvailableMetricIndex += 1 ;
183+ return instrument ;
130184 }
131- long indexToInsertInstrument = metricInstruments .size ();
132- DoubleHistogramMetricInstrument instrument = new DoubleHistogramMetricInstrument (
133- indexToInsertInstrument , name , description , unit , bucketBoundaries , requiredLabelKeys ,
134- optionalLabelKeys ,
135- enableByDefault );
136- metricInstruments .add (instrument );
137- registeredMetricNames .add (name );
138- return instrument ;
139185 }
140186
141187 /**
@@ -151,20 +197,32 @@ public synchronized DoubleHistogramMetricInstrument registerDoubleHistogram(Stri
151197 * @return the newly created LongHistogramMetricInstrument
152198 * @throws IllegalStateException if a metric with the same name already exists
153199 */
154- public synchronized LongHistogramMetricInstrument registerLongHistogram (String name ,
200+ public LongHistogramMetricInstrument registerLongHistogram (String name ,
155201 String description , String unit , List <Long > bucketBoundaries , List <String > requiredLabelKeys ,
156202 List <String > optionalLabelKeys , boolean enableByDefault ) {
157- if (registeredMetricNames .contains (name )) {
158- throw new IllegalStateException ("Metric with name " + name + " already exists" );
203+ checkArgument (!Strings .isNullOrEmpty (name ), "missing metric name" );
204+ checkNotNull (description , "description" );
205+ checkNotNull (unit , "unit" );
206+ checkNotNull (bucketBoundaries , "bucketBoundaries" );
207+ checkNotNull (requiredLabelKeys , "requiredLabelKeys" );
208+ checkNotNull (optionalLabelKeys , "optionalLabelKeys" );
209+ synchronized (lock ) {
210+ if (registeredMetricNames .contains (name )) {
211+ throw new IllegalStateException ("Metric with name " + name + " already exists" );
212+ }
213+ int index = nextAvailableMetricIndex ;
214+ if (index + 1 == metricInstruments .length ) {
215+ resizeMetricInstruments ();
216+ }
217+ LongHistogramMetricInstrument instrument = new LongHistogramMetricInstrument (
218+ index , name , description , unit , bucketBoundaries , requiredLabelKeys ,
219+ optionalLabelKeys ,
220+ enableByDefault );
221+ metricInstruments [index ] = instrument ;
222+ registeredMetricNames .add (name );
223+ nextAvailableMetricIndex += 1 ;
224+ return instrument ;
159225 }
160- long indexToInsertInstrument = metricInstruments .size ();
161- LongHistogramMetricInstrument instrument = new LongHistogramMetricInstrument (
162- indexToInsertInstrument , name , description , unit , bucketBoundaries , requiredLabelKeys ,
163- optionalLabelKeys ,
164- enableByDefault );
165- metricInstruments .add (instrument );
166- registeredMetricNames .add (name );
167- return instrument ;
168226 }
169227
170228
@@ -180,18 +238,38 @@ public synchronized LongHistogramMetricInstrument registerLongHistogram(String n
180238 * @return the newly created LongGaugeMetricInstrument
181239 * @throws IllegalStateException if a metric with the same name already exists
182240 */
183- public synchronized LongGaugeMetricInstrument registerLongGauge (String name , String description ,
241+ public LongGaugeMetricInstrument registerLongGauge (String name , String description ,
184242 String unit , List <String > requiredLabelKeys , List <String > optionalLabelKeys , boolean
185243 enableByDefault ) {
186- if (registeredMetricNames .contains (name )) {
187- throw new IllegalStateException ("Metric with name " + name + " already exists" );
244+ checkArgument (!Strings .isNullOrEmpty (name ), "missing metric name" );
245+ checkNotNull (description , "description" );
246+ checkNotNull (unit , "unit" );
247+ checkNotNull (requiredLabelKeys , "requiredLabelKeys" );
248+ checkNotNull (optionalLabelKeys , "optionalLabelKeys" );
249+ synchronized (lock ) {
250+ if (registeredMetricNames .contains (name )) {
251+ throw new IllegalStateException ("Metric with name " + name + " already exists" );
252+ }
253+ int index = nextAvailableMetricIndex ;
254+ if (index + 1 == metricInstruments .length ) {
255+ resizeMetricInstruments ();
256+ }
257+ LongGaugeMetricInstrument instrument = new LongGaugeMetricInstrument (
258+ index , name , description , unit , requiredLabelKeys , optionalLabelKeys ,
259+ enableByDefault );
260+ metricInstruments [index ] = instrument ;
261+ registeredMetricNames .add (name );
262+ nextAvailableMetricIndex += 1 ;
263+ return instrument ;
188264 }
189- long indexToInsertInstrument = metricInstruments .size ();
190- LongGaugeMetricInstrument instrument = new LongGaugeMetricInstrument (
191- indexToInsertInstrument , name , description , unit , requiredLabelKeys , optionalLabelKeys ,
192- enableByDefault );
193- metricInstruments .add (instrument );
194- registeredMetricNames .add (name );
195- return instrument ;
265+ }
266+
267+ @ GuardedBy ("lock" )
268+ private void resizeMetricInstruments () {
269+ // Increase the capacity of the metricInstruments array by INITIAL_INSTRUMENT_CAPACITY
270+ int newInstrumentsCapacity = metricInstruments .length + INITIAL_INSTRUMENT_CAPACITY ;
271+ MetricInstrument [] resizedMetricInstruments = Arrays .copyOf (metricInstruments ,
272+ newInstrumentsCapacity );
273+ metricInstruments = resizedMetricInstruments ;
196274 }
197275}
0 commit comments