@@ -83,7 +83,7 @@ extension HistogramLabels {
83
83
public class PromHistogram < NumType: DoubleRepresentable , Labels: HistogramLabels > : PromMetric , PrometheusHandled {
84
84
/// Prometheus instance that created this Histogram
85
85
internal weak var prometheus : PrometheusClient ?
86
-
86
+
87
87
/// Name of this Histogram, required
88
88
public let name : String
89
89
/// Help text of this Histogram, optional
@@ -99,10 +99,10 @@ public class PromHistogram<NumType: DoubleRepresentable, Labels: HistogramLabels
99
99
internal let upperBounds : [ Double ]
100
100
101
101
/// Labels for this Histogram
102
- internal private ( set ) var labels : Labels
102
+ internal let labels : Labels
103
103
104
104
/// Sub Histograms for this Histogram
105
- fileprivate var subHistograms : [ PromHistogram < NumType , Labels > ] = [ ]
105
+ fileprivate var subHistograms : [ Labels : PromHistogram < NumType , Labels > ] = [ : ]
106
106
107
107
/// Total value of the Histogram
108
108
private let sum : PromCounter < NumType , EmptyLabels >
@@ -121,9 +121,9 @@ public class PromHistogram<NumType: DoubleRepresentable, Labels: HistogramLabels
121
121
internal init ( _ name: String , _ help: String ? = nil , _ labels: Labels = Labels ( ) , _ buckets: Buckets = . defaultBuckets, _ p: PrometheusClient ) {
122
122
self . name = name
123
123
self . help = help
124
-
124
+
125
125
self . prometheus = p
126
-
126
+
127
127
self . sum = . init( " \( self . name) _sum " , nil , 0 , p)
128
128
129
129
self . labels = labels
@@ -142,68 +142,76 @@ public class PromHistogram<NumType: DoubleRepresentable, Labels: HistogramLabels
142
142
/// - Returns:
143
143
/// Newline separated Prometheus formatted metric string
144
144
public func collect( ) -> String {
145
- return self . lock. withLock {
146
- var output = [ String] ( )
147
-
148
- if let help = self . help {
149
- output. append ( " # HELP \( self . name) \( help) " )
150
- }
151
- output. append ( " # TYPE \( self . name) \( self . _type) " )
152
-
153
- var acc : NumType = 0
154
- for (i, bound) in self . upperBounds. enumerated ( ) {
155
- acc += self . buckets [ i] . get ( )
156
- self . labels. le = bound. description
157
- let labelsString = encodeLabels ( self . labels)
158
- output. append ( " \( self . name) _bucket \( labelsString) \( acc) " )
159
- }
160
-
161
- let labelsString = encodeLabels ( self . labels, [ " le " ] )
162
- output. append ( " \( self . name) _count \( labelsString) \( acc) " )
163
-
164
- output. append ( " \( self . name) _sum \( labelsString) \( self . sum. get ( ) ) " )
165
-
166
- self . subHistograms. forEach { subHistogram in
167
- var acc : NumType = 0
168
- for (i, bound) in subHistogram. upperBounds. enumerated ( ) {
169
- acc += subHistogram. buckets [ i] . get ( )
170
- subHistogram. labels. le = bound. description
171
- let labelsString = encodeLabels ( subHistogram. labels)
172
- output. append ( " \( subHistogram. name) _bucket \( labelsString) \( acc) " )
173
- }
174
-
175
- let labelsString = encodeLabels ( subHistogram. labels, [ " le " ] )
176
- output. append ( " \( subHistogram. name) _count \( labelsString) \( acc) " )
177
-
178
- output. append ( " \( subHistogram. name) _sum \( labelsString) \( subHistogram. sum. get ( ) ) " )
179
-
180
- subHistogram. labels. le = " "
145
+ let ( buckets, subHistograms, labels) = self . lock. withLock {
146
+ ( self . buckets, self . subHistograms, self . labels)
147
+ }
148
+
149
+ var output = [ String] ( )
150
+
151
+ if let help = self . help {
152
+ output. append ( " # HELP \( self . name) \( help) " )
153
+ }
154
+ output. append ( " # TYPE \( self . name) \( self . _type) " )
155
+ collectBuckets ( buckets: buckets,
156
+ upperBounds: self . upperBounds,
157
+ name: self . name,
158
+ labels: labels,
159
+ sum: self . sum. get ( ) ,
160
+ into: & output)
161
+
162
+ subHistograms. forEach { subHistogram in
163
+ let ( subHistogramBuckets, subHistogramLabels) = self . lock. withLock {
164
+ ( subHistogram. value. buckets, subHistogram. value. labels)
181
165
}
182
-
183
- self . labels. le = " "
184
-
185
- return output. joined ( separator: " \n " )
166
+ collectBuckets ( buckets: subHistogramBuckets,
167
+ upperBounds: subHistogram. value. upperBounds,
168
+ name: subHistogram. value. name,
169
+ labels: subHistogramLabels,
170
+ sum: subHistogram. value. sum. get ( ) ,
171
+ into: & output)
186
172
}
173
+ return output. joined ( separator: " \n " )
187
174
}
188
-
175
+
176
+ private func collectBuckets( buckets: [ PromCounter < NumType , EmptyLabels > ] ,
177
+ upperBounds: [ Double ] ,
178
+ name: String ,
179
+ labels: Labels ,
180
+ sum: NumType ,
181
+ into output: inout [ String ] ) {
182
+ var labels = labels
183
+ var acc : NumType = 0
184
+ for (i, bound) in upperBounds. enumerated ( ) {
185
+ acc += buckets [ i] . get ( )
186
+ labels. le = bound. description
187
+ let labelsString = encodeLabels ( labels)
188
+ output. append ( " \( name) _bucket \( labelsString) \( acc) " )
189
+ }
190
+
191
+ let labelsString = encodeLabels ( labels, [ " le " ] )
192
+ output. append ( " \( name) _count \( labelsString) \( acc) " )
193
+
194
+ output. append ( " \( name) _sum \( labelsString) \( sum) " )
195
+ }
196
+
189
197
/// Observe a value
190
198
///
191
199
/// - Parameters:
192
200
/// - value: Value to observe
193
201
/// - labels: Labels to attach to the observed value
194
202
public func observe( _ value: NumType , _ labels: Labels ? = nil ) {
195
- self . lock. withLock {
196
- if let labels = labels, type ( of: labels) != type ( of: EmptySummaryLabels ( ) ) {
197
- guard let his = self . prometheus? . getOrCreateHistogram ( with: labels, for: self ) else { fatalError ( " Lingering Histogram " ) }
198
- his. observe ( value)
203
+ if let labels = labels, type ( of: labels) != type ( of: EmptySummaryLabels ( ) ) {
204
+ let his : PromHistogram < NumType , Labels > = self . lock. withLock {
205
+ self . getOrCreateHistogram ( with: labels)
199
206
}
200
- self . sum. inc ( value)
201
-
202
- for (i, bound) in self . upperBounds. enumerated ( ) {
203
- if bound >= value. doubleValue {
204
- self . buckets [ i] . inc ( )
205
- return
206
- }
207
+ his. observe ( value)
208
+ }
209
+ self . sum. inc ( value)
210
+
211
+ for (i, bound) in self . upperBounds. enumerated ( ) {
212
+ if bound >= value. doubleValue {
213
+ self . buckets [ i] . inc ( )
214
+ return
207
215
}
208
216
}
209
217
}
@@ -222,21 +230,16 @@ public class PromHistogram<NumType: DoubleRepresentable, Labels: HistogramLabels
222
230
}
223
231
return try body ( )
224
232
}
225
- }
226
233
227
- extension PrometheusClient {
228
234
/// Helper for histograms & labels
229
- fileprivate func getOrCreateHistogram< T: Numeric , U: HistogramLabels > ( with labels: U , for histogram: PromHistogram < T , U > ) -> PromHistogram < T , U > {
230
- let histograms = histogram. subHistograms. filter { ( metric) -> Bool in
231
- guard metric. name == histogram. name, metric. help == histogram. help, metric. labels == labels else { return false }
232
- return true
233
- }
234
- if histograms. count > 2 { fatalError ( " Somehow got 2 histograms with the same data type " ) }
235
- if let histogram = histograms. first {
235
+ fileprivate func getOrCreateHistogram( with labels: Labels ) -> PromHistogram < NumType , Labels > {
236
+ let histogram = self . subHistograms [ labels]
237
+ if let histogram = histogram, histogram. name == self . name, histogram. help == self . help {
236
238
return histogram
237
239
} else {
238
- let newHistogram = PromHistogram < T , U > ( histogram. name, histogram. help, labels, Buckets ( histogram. upperBounds) , self )
239
- histogram. subHistograms. append ( newHistogram)
240
+ guard let prometheus = prometheus else { fatalError ( " Lingering Histogram " ) }
241
+ let newHistogram = PromHistogram ( self . name, self . help, labels, Buckets ( self . upperBounds) , prometheus)
242
+ self . subHistograms [ labels] = newHistogram
240
243
return newHistogram
241
244
}
242
245
}
0 commit comments