-
Notifications
You must be signed in to change notification settings - Fork 3.8k
/
MetricInstrumentRegistry.java
275 lines (261 loc) · 11.2 KB
/
MetricInstrumentRegistry.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
/*
* Copyright 2024 The gRPC Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package io.grpc;
import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkNotNull;
import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.Strings;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import javax.annotation.concurrent.GuardedBy;
/**
* A registry for globally registered metric instruments.
*/
@Internal
public final class MetricInstrumentRegistry {
static final int INITIAL_INSTRUMENT_CAPACITY = 5;
private static MetricInstrumentRegistry instance;
private final Object lock = new Object();
@GuardedBy("lock")
private final Set<String> registeredMetricNames = new HashSet<>();
@GuardedBy("lock")
private MetricInstrument[] metricInstruments =
new MetricInstrument[INITIAL_INSTRUMENT_CAPACITY];
@GuardedBy("lock")
private int nextAvailableMetricIndex;
@VisibleForTesting
MetricInstrumentRegistry() {}
/**
* Returns the default metric instrument registry.
*/
public static synchronized MetricInstrumentRegistry getDefaultRegistry() {
if (instance == null) {
instance = new MetricInstrumentRegistry();
}
return instance;
}
/**
* Returns a list of registered metric instruments.
*/
public List<MetricInstrument> getMetricInstruments() {
synchronized (lock) {
return Collections.unmodifiableList(
Arrays.asList(Arrays.copyOfRange(metricInstruments, 0, nextAvailableMetricIndex)));
}
}
/**
* Registers a new Double Counter metric instrument.
*
* @param name the name of the metric
* @param description a description of the metric
* @param unit the unit of measurement for the metric
* @param requiredLabelKeys a list of required label keys
* @param optionalLabelKeys a list of optional label keys
* @param enableByDefault whether the metric should be enabled by default
* @return the newly created DoubleCounterMetricInstrument
* @throws IllegalStateException if a metric with the same name already exists
*/
public DoubleCounterMetricInstrument registerDoubleCounter(String name,
String description, String unit, List<String> requiredLabelKeys,
List<String> optionalLabelKeys, boolean enableByDefault) {
checkArgument(!Strings.isNullOrEmpty(name), "missing metric name");
checkNotNull(description, "description");
checkNotNull(unit, "unit");
checkNotNull(requiredLabelKeys, "requiredLabelKeys");
checkNotNull(optionalLabelKeys, "optionalLabelKeys");
synchronized (lock) {
if (registeredMetricNames.contains(name)) {
throw new IllegalStateException("Metric with name " + name + " already exists");
}
int index = nextAvailableMetricIndex;
if (index + 1 == metricInstruments.length) {
resizeMetricInstruments();
}
DoubleCounterMetricInstrument instrument = new DoubleCounterMetricInstrument(
index, name, description, unit, requiredLabelKeys, optionalLabelKeys,
enableByDefault);
metricInstruments[index] = instrument;
registeredMetricNames.add(name);
nextAvailableMetricIndex += 1;
return instrument;
}
}
/**
* Registers a new Long Counter metric instrument.
*
* @param name the name of the metric
* @param description a description of the metric
* @param unit the unit of measurement for the metric
* @param requiredLabelKeys a list of required label keys
* @param optionalLabelKeys a list of optional label keys
* @param enableByDefault whether the metric should be enabled by default
* @return the newly created LongCounterMetricInstrument
* @throws IllegalStateException if a metric with the same name already exists
*/
public LongCounterMetricInstrument registerLongCounter(String name,
String description, String unit, List<String> requiredLabelKeys,
List<String> optionalLabelKeys, boolean enableByDefault) {
checkArgument(!Strings.isNullOrEmpty(name), "missing metric name");
checkNotNull(description, "description");
checkNotNull(unit, "unit");
checkNotNull(requiredLabelKeys, "requiredLabelKeys");
checkNotNull(optionalLabelKeys, "optionalLabelKeys");
synchronized (lock) {
if (registeredMetricNames.contains(name)) {
throw new IllegalStateException("Metric with name " + name + " already exists");
}
int index = nextAvailableMetricIndex;
if (index + 1 == metricInstruments.length) {
resizeMetricInstruments();
}
LongCounterMetricInstrument instrument = new LongCounterMetricInstrument(
index, name, description, unit, requiredLabelKeys, optionalLabelKeys,
enableByDefault);
metricInstruments[index] = instrument;
registeredMetricNames.add(name);
nextAvailableMetricIndex += 1;
return instrument;
}
}
/**
* Registers a new Double Histogram metric instrument.
*
* @param name the name of the metric
* @param description a description of the metric
* @param unit the unit of measurement for the metric
* @param bucketBoundaries recommended set of explicit bucket boundaries for the histogram
* @param requiredLabelKeys a list of required label keys
* @param optionalLabelKeys a list of optional label keys
* @param enableByDefault whether the metric should be enabled by default
* @return the newly created DoubleHistogramMetricInstrument
* @throws IllegalStateException if a metric with the same name already exists
*/
public DoubleHistogramMetricInstrument registerDoubleHistogram(String name,
String description, String unit, List<Double> bucketBoundaries,
List<String> requiredLabelKeys, List<String> optionalLabelKeys, boolean enableByDefault) {
checkArgument(!Strings.isNullOrEmpty(name), "missing metric name");
checkNotNull(description, "description");
checkNotNull(unit, "unit");
checkNotNull(bucketBoundaries, "bucketBoundaries");
checkNotNull(requiredLabelKeys, "requiredLabelKeys");
checkNotNull(optionalLabelKeys, "optionalLabelKeys");
synchronized (lock) {
if (registeredMetricNames.contains(name)) {
throw new IllegalStateException("Metric with name " + name + " already exists");
}
int index = nextAvailableMetricIndex;
if (index + 1 == metricInstruments.length) {
resizeMetricInstruments();
}
DoubleHistogramMetricInstrument instrument = new DoubleHistogramMetricInstrument(
index, name, description, unit, bucketBoundaries, requiredLabelKeys,
optionalLabelKeys,
enableByDefault);
metricInstruments[index] = instrument;
registeredMetricNames.add(name);
nextAvailableMetricIndex += 1;
return instrument;
}
}
/**
* Registers a new Long Histogram metric instrument.
*
* @param name the name of the metric
* @param description a description of the metric
* @param unit the unit of measurement for the metric
* @param bucketBoundaries recommended set of explicit bucket boundaries for the histogram
* @param requiredLabelKeys a list of required label keys
* @param optionalLabelKeys a list of optional label keys
* @param enableByDefault whether the metric should be enabled by default
* @return the newly created LongHistogramMetricInstrument
* @throws IllegalStateException if a metric with the same name already exists
*/
public LongHistogramMetricInstrument registerLongHistogram(String name,
String description, String unit, List<Long> bucketBoundaries, List<String> requiredLabelKeys,
List<String> optionalLabelKeys, boolean enableByDefault) {
checkArgument(!Strings.isNullOrEmpty(name), "missing metric name");
checkNotNull(description, "description");
checkNotNull(unit, "unit");
checkNotNull(bucketBoundaries, "bucketBoundaries");
checkNotNull(requiredLabelKeys, "requiredLabelKeys");
checkNotNull(optionalLabelKeys, "optionalLabelKeys");
synchronized (lock) {
if (registeredMetricNames.contains(name)) {
throw new IllegalStateException("Metric with name " + name + " already exists");
}
int index = nextAvailableMetricIndex;
if (index + 1 == metricInstruments.length) {
resizeMetricInstruments();
}
LongHistogramMetricInstrument instrument = new LongHistogramMetricInstrument(
index, name, description, unit, bucketBoundaries, requiredLabelKeys,
optionalLabelKeys,
enableByDefault);
metricInstruments[index] = instrument;
registeredMetricNames.add(name);
nextAvailableMetricIndex += 1;
return instrument;
}
}
/**
* Registers a new Long Gauge metric instrument.
*
* @param name the name of the metric
* @param description a description of the metric
* @param unit the unit of measurement for the metric
* @param requiredLabelKeys a list of required label keys
* @param optionalLabelKeys a list of optional label keys
* @param enableByDefault whether the metric should be enabled by default
* @return the newly created LongGaugeMetricInstrument
* @throws IllegalStateException if a metric with the same name already exists
*/
public LongGaugeMetricInstrument registerLongGauge(String name, String description,
String unit, List<String> requiredLabelKeys, List<String> optionalLabelKeys, boolean
enableByDefault) {
checkArgument(!Strings.isNullOrEmpty(name), "missing metric name");
checkNotNull(description, "description");
checkNotNull(unit, "unit");
checkNotNull(requiredLabelKeys, "requiredLabelKeys");
checkNotNull(optionalLabelKeys, "optionalLabelKeys");
synchronized (lock) {
if (registeredMetricNames.contains(name)) {
throw new IllegalStateException("Metric with name " + name + " already exists");
}
int index = nextAvailableMetricIndex;
if (index + 1 == metricInstruments.length) {
resizeMetricInstruments();
}
LongGaugeMetricInstrument instrument = new LongGaugeMetricInstrument(
index, name, description, unit, requiredLabelKeys, optionalLabelKeys,
enableByDefault);
metricInstruments[index] = instrument;
registeredMetricNames.add(name);
nextAvailableMetricIndex += 1;
return instrument;
}
}
@GuardedBy("lock")
private void resizeMetricInstruments() {
// Increase the capacity of the metricInstruments array by INITIAL_INSTRUMENT_CAPACITY
int newInstrumentsCapacity = metricInstruments.length + INITIAL_INSTRUMENT_CAPACITY;
MetricInstrument[] resizedMetricInstruments = Arrays.copyOf(metricInstruments,
newInstrumentsCapacity);
metricInstruments = resizedMetricInstruments;
}
}