1
1
package io .prometheus .client ;
2
2
3
3
import java .util .ArrayList ;
4
- import java .util .concurrent .ConcurrentHashMap ;
5
- import java .util .concurrent .ConcurrentMap ;
6
4
import java .util .Arrays ;
7
5
import java .util .List ;
6
+ import io .prometheus .client .ConcurrentChildMap .ConcurrentChildHashMap ;
8
7
9
8
/**
10
9
* Common functionality for {@link Gauge}, {@link Counter}, {@link Summary} and {@link Histogram}.
46
45
* by each. If the cardinality is in the hundreds, you may wish to consider removing the breakout
47
46
* by one of the dimensions altogether.
48
47
*/
49
- public abstract class SimpleCollector <Child > extends Collector {
48
+ public abstract class SimpleCollector <Child > extends Collector implements ConcurrentChildMap . ChildFactory < Child > {
50
49
protected final String fullname ;
51
50
protected final String help ;
52
51
protected final List <String > labelNames ;
53
52
54
- protected final ConcurrentMap < List < String >, Child > children = new ConcurrentHashMap < List < String >, Child >() ;
53
+ protected final ConcurrentChildMap < Child > children ;
55
54
protected Child noLabelsChild ;
56
55
57
56
/**
@@ -60,22 +59,39 @@ public abstract class SimpleCollector<Child> extends Collector {
60
59
* Must be passed the same number of labels are were passed to {@link #labelNames}.
61
60
*/
62
61
public Child labels (String ... labelValues ) {
63
- if (labelValues .length != labelNames .size ()) {
62
+ validateCount (labelValues .length );
63
+ return children .labels (this , labelValues );
64
+ }
65
+
66
+ public Child labels () {
67
+ validateCount (0 );
68
+ return noLabelsChild ;
69
+ }
70
+
71
+ public Child labels (String lv1 ) {
72
+ validateCount (1 );
73
+ return children .labels (this , lv1 );
74
+ }
75
+
76
+ public Child labels (String lv1 , String lv2 ) {
77
+ validateCount (2 );
78
+ return children .labels (this , lv1 , lv2 );
79
+ }
80
+
81
+ public Child labels (String lv1 , String lv2 , String lv3 ) {
82
+ validateCount (3 );
83
+ return children .labels (this , lv1 , lv2 , lv3 );
84
+ }
85
+
86
+ public Child labels (String lv1 , String lv2 , String lv3 , String lv4 ) {
87
+ validateCount (4 );
88
+ return children .labels (this , lv1 , lv2 , lv3 , lv4 );
89
+ }
90
+
91
+ private void validateCount (int count ) {
92
+ if (count != labelNames .size ()) {
64
93
throw new IllegalArgumentException ("Incorrect number of labels." );
65
94
}
66
- for (String label : labelValues ) {
67
- if (label == null ) {
68
- throw new IllegalArgumentException ("Label cannot be null." );
69
- }
70
- }
71
- List <String > key = Arrays .asList (labelValues );
72
- Child c = children .get (key );
73
- if (c != null ) {
74
- return c ;
75
- }
76
- Child c2 = newChild ();
77
- Child tmp = children .putIfAbsent (key , c2 );
78
- return tmp == null ? c2 : tmp ;
79
95
}
80
96
81
97
/**
@@ -84,7 +100,7 @@ public Child labels(String... labelValues) {
84
100
* Any references to the Child are invalidated.
85
101
*/
86
102
public void remove (String ... labelValues ) {
87
- children .remove (Arrays . asList ( labelValues ) );
103
+ children .remove (labelValues );
88
104
initializeNoLabelsChild ();
89
105
}
90
106
@@ -104,7 +120,7 @@ public void clear() {
104
120
protected void initializeNoLabelsChild () {
105
121
// Initialize metric if it has no labels.
106
122
if (labelNames .size () == 0 ) {
107
- noLabelsChild = labels ();
123
+ noLabelsChild = labels (new String [ 0 ] );
108
124
}
109
125
}
110
126
@@ -132,10 +148,8 @@ protected void initializeNoLabelsChild() {
132
148
* A metric should be either all callbacks, or none.
133
149
*/
134
150
public <T extends Collector > T setChild (Child child , String ... labelValues ) {
135
- if (labelValues .length != labelNames .size ()) {
136
- throw new IllegalArgumentException ("Incorrect number of labels." );
137
- }
138
- children .put (Arrays .asList (labelValues ), child );
151
+ validateCount (labelValues .length );
152
+ children .setChild (child , labelValues );
139
153
return (T )this ;
140
154
}
141
155
@@ -144,6 +158,11 @@ public <T extends Collector> T setChild(Child child, String... labelValues) {
144
158
*/
145
159
protected abstract Child newChild ();
146
160
161
+ @ Override
162
+ public Child newChild (String [] labels ) {
163
+ return newChild ();
164
+ }
165
+
147
166
protected List <MetricFamilySamples > familySamplesList (Collector .Type type , List <MetricFamilySamples .Sample > samples ) {
148
167
MetricFamilySamples mfs = new MetricFamilySamples (fullname , type , help , samples );
149
168
List <MetricFamilySamples > mfsList = new ArrayList <MetricFamilySamples >(1 );
@@ -152,6 +171,11 @@ protected List<MetricFamilySamples> familySamplesList(Collector.Type type, List<
152
171
}
153
172
154
173
protected SimpleCollector (Builder b ) {
174
+ try {
175
+ children = (ConcurrentChildMap ) b .childMapClass .newInstance ();
176
+ } catch (ReflectiveOperationException e ) {
177
+ throw new RuntimeException ("Error instantiating child map class" , e );
178
+ }
155
179
if (b .name .isEmpty ()) throw new IllegalStateException ("Name hasn't been set." );
156
180
String name = b .name ;
157
181
if (!b .subsystem .isEmpty ()) {
@@ -187,6 +211,15 @@ public abstract static class Builder<B extends Builder<B, C>, C extends SimpleCo
187
211
String [] labelNames = new String []{};
188
212
// Some metrics require additional setup before the initialization can be done.
189
213
boolean dontInitializeNoLabelsChild ;
214
+ Class <? extends ConcurrentChildMap > childMapClass = ConcurrentChildHashMap .class ;
215
+
216
+ /**
217
+ * Set a custom implementation for the internal labels-to-Child map.
218
+ */
219
+ public B childMap (Class <? extends ConcurrentChildMap > childMapClass ) {
220
+ this .childMapClass = childMapClass ;
221
+ return (B )this ;
222
+ }
190
223
191
224
/**
192
225
* Set the name of the metric. Required.
0 commit comments