@@ -17,15 +17,15 @@ public class Summary<NumType: DoubleRepresentable, Labels: SummaryLabels>: Metri
17
17
public let name : String
18
18
public let help : String ?
19
19
20
- private var labels : Labels
20
+ internal private( set ) var labels : Labels
21
21
22
22
private let sum : Counter < NumType , EmptyCodable >
23
23
24
24
private let count : Counter < NumType , EmptyCodable >
25
25
26
26
private var values : [ NumType ] = [ ]
27
27
28
- private var quantiles : [ Double ]
28
+ internal let quantiles : [ Double ]
29
29
30
30
internal init ( _ name: String , _ help: String ? = nil , _ quantiles: [ Double ] = defaultQuantiles, _ labels: Labels = Labels ( ) , _ p: Prometheus ) {
31
31
self . name = name
@@ -45,10 +45,12 @@ public class Summary<NumType: DoubleRepresentable, Labels: SummaryLabels>: Metri
45
45
public func getMetric( ) -> String {
46
46
var output = [ String] ( )
47
47
48
- if let help = help {
49
- output. append ( " # HELP \( name) \( help) " )
48
+ if self . labels == Labels ( ) {
49
+ if let help = help {
50
+ output. append ( " # HELP \( name) \( help) " )
51
+ }
52
+ output. append ( " # TYPE \( name) summary " )
50
53
}
51
- output. append ( " # TYPE \( name) summary " )
52
54
53
55
calculateQuantiles ( quantiles: quantiles, values: values. map { $0. doubleValue } ) . sorted { $0. key < $1. key } . forEach { ( arg) in
54
56
let ( q, v) = arg
@@ -60,17 +62,40 @@ public class Summary<NumType: DoubleRepresentable, Labels: SummaryLabels>: Metri
60
62
let labelsString = encodeLabels ( self . labels, [ " quantile " ] )
61
63
output. append ( " \( name) _count \( labelsString) \( count. get ( ) ) " )
62
64
output. append ( " \( name) _sum \( labelsString) \( sum. get ( ) ) " )
63
-
65
+
66
+ self . labels. quantile = " "
67
+
64
68
return output. joined ( separator: " \n " )
65
69
}
66
70
67
- public func observe( _ value: NumType ) {
71
+ public func observe( _ value: NumType , _ labels: Labels ? = nil ) {
72
+ if let labels = labels, type ( of: labels) != type ( of: EmptySummaryCodable ( ) ) {
73
+ let sum = self . prometheus. getOrCreateSummary ( withLabels: labels, forSummary: self )
74
+ sum. observe ( value)
75
+ return
76
+ }
68
77
self . count. inc ( 1 )
69
78
self . sum. inc ( value)
70
79
self . values. append ( value)
71
80
}
72
81
}
73
82
83
+ extension Prometheus {
84
+ fileprivate func getOrCreateSummary< T: Numeric , U: SummaryLabels > ( withLabels labels: U , forSummary sum: Summary < T , U > ) -> Summary < T , U > {
85
+ let summary = metrics. filter { ( metric) -> Bool in
86
+ guard let metric = metric as? Summary < T , U > else { return false }
87
+ guard metric. name == sum. name, metric. help == sum. help, metric. labels == labels else { return false }
88
+ return true
89
+ } as? [ Summary < T , U > ] ?? [ ]
90
+ if summary. count > 2 { fatalError ( " Somehow got 2 summaries with the same data type " ) }
91
+ if let summary = summary. first {
92
+ return summary
93
+ } else {
94
+ return createSummary ( forType: T . self, named: sum. name, helpText: sum. help, quantiles: sum. quantiles, labels: labels)
95
+ }
96
+ }
97
+ }
98
+
74
99
func calculateQuantiles( quantiles: [ Double ] , values: [ Double ] ) -> [ Double : Double ] {
75
100
let values = values. sorted ( )
76
101
var quantilesMap : [ Double : Double ] = [ : ]
@@ -81,6 +106,9 @@ func calculateQuantiles(quantiles: [Double], values: [Double]) -> [Double: Doubl
81
106
}
82
107
83
108
func quantile( _ q: Double , _ values: [ Double ] ) -> Double {
109
+ if values. count == 0 {
110
+ return 0
111
+ }
84
112
if values. count == 1 {
85
113
return values [ 0 ]
86
114
}
0 commit comments