33namespace Prometheus \Storage ;
44
55
6- use Prometheus \Collector ;
76use Prometheus \MetricFamilySamples ;
87use Prometheus \Sample ;
98
109class InMemory implements Adapter
1110{
12- /**
13- * @var Collector[]
14- */
15- private $ metrics = array ();
16- /**
17- * @var array
18- */
19- private $ samples = array ();
11+
12+ private $ counters = [];
13+ private $ gauges = [];
14+ private $ histograms = [];
2015
2116 /**
2217 * @return MetricFamilySamples[]
2318 */
2419 public function collect ()
2520 {
26- $ responses = array ();
27- foreach ($ this ->metrics as $ metric ) {
28- $ samples = $ this ->samples [$ metric ->getKey ()];
29- array_multisort ($ samples );
30- $ responses [] = new MetricFamilySamples (
31- array (
32- 'name ' => $ metric ->getName (),
33- 'type ' => $ metric ->getType (),
34- 'help ' => $ metric ->getHelp (),
35- 'samples ' => $ samples ,
36- 'labelNames ' => $ metric ->getLabelNames ()
37- )
21+ $ metrics = $ this ->internalCollect ($ this ->counters );
22+ $ metrics = array_merge ($ metrics , $ this ->internalCollect ($ this ->gauges ));
23+ $ metrics = array_merge ($ metrics , $ this ->collectHistograms ());
24+ return $ metrics ;
25+ }
26+
27+ public function flushMemory ()
28+ {
29+ $ this ->counters = [];
30+ $ this ->gauges = [];
31+ $ this ->histograms = [];
32+ }
33+
34+ private function collectHistograms ()
35+ {
36+ $ histograms = array ();
37+ foreach ($ this ->histograms as $ histogram ) {
38+ $ metaData = $ histogram ['meta ' ];
39+ $ data = array (
40+ 'name ' => $ metaData ['name ' ],
41+ 'help ' => $ metaData ['help ' ],
42+ 'type ' => $ metaData ['type ' ],
43+ 'labelNames ' => $ metaData ['labelNames ' ],
44+ 'buckets ' => $ metaData ['buckets ' ]
3845 );
46+
47+ // Add the Inf bucket so we can compute it later on
48+ $ data ['buckets ' ][] = '+Inf ' ;
49+
50+ $ histogramBuckets = array ();
51+ foreach ($ histogram ['samples ' ] as $ key => $ value ) {
52+ $ parts = explode (': ' , $ key );
53+ $ labelValues = $ parts [2 ];
54+ $ bucket = $ parts [3 ];
55+ // Key by labelValues
56+ $ histogramBuckets [$ labelValues ][$ bucket ] = $ value ;
57+ }
58+
59+ // Compute all buckets
60+ $ labels = array_keys ($ histogramBuckets );
61+ sort ($ labels );
62+ foreach ($ labels as $ labelValues ) {
63+ $ acc = 0 ;
64+ $ decodedLabelValues = json_decode ($ labelValues );
65+ foreach ($ data ['buckets ' ] as $ bucket ) {
66+ $ bucket = (string ) $ bucket ;
67+ if (!isset ($ histogramBuckets [$ labelValues ][$ bucket ])) {
68+ $ data ['samples ' ][] = array (
69+ 'name ' => $ metaData ['name ' ] . '_bucket ' ,
70+ 'labelNames ' => array ('le ' ),
71+ 'labelValues ' => array_merge ($ decodedLabelValues , array ($ bucket )),
72+ 'value ' => $ acc
73+ );
74+ } else {
75+ $ acc += $ histogramBuckets [$ labelValues ][$ bucket ];
76+ $ data ['samples ' ][] = array (
77+ 'name ' => $ metaData ['name ' ] . '_ ' . 'bucket ' ,
78+ 'labelNames ' => array ('le ' ),
79+ 'labelValues ' => array_merge ($ decodedLabelValues , array ($ bucket )),
80+ 'value ' => $ acc
81+ );
82+ }
83+ }
84+
85+ // Add the count
86+ $ data ['samples ' ][] = array (
87+ 'name ' => $ metaData ['name ' ] . '_count ' ,
88+ 'labelNames ' => array (),
89+ 'labelValues ' => $ decodedLabelValues ,
90+ 'value ' => $ acc
91+ );
92+
93+ // Add the sum
94+ $ data ['samples ' ][] = array (
95+ 'name ' => $ metaData ['name ' ] . '_sum ' ,
96+ 'labelNames ' => array (),
97+ 'labelValues ' => $ decodedLabelValues ,
98+ 'value ' => $ histogramBuckets [$ labelValues ]['sum ' ]
99+ );
100+
101+ }
102+ $ histograms [] = new MetricFamilySamples ($ data );
103+ }
104+ return $ histograms ;
105+ }
106+
107+ private function internalCollect (array $ metrics )
108+ {
109+ $ result = [];
110+ foreach ($ metrics as $ metric ) {
111+ $ metaData = $ metric ['meta ' ];
112+ $ data = array (
113+ 'name ' => $ metaData ['name ' ],
114+ 'help ' => $ metaData ['help ' ],
115+ 'type ' => $ metaData ['type ' ],
116+ 'labelNames ' => $ metaData ['labelNames ' ],
117+ );
118+ foreach ($ metric ['samples ' ] as $ key => $ value ) {
119+ $ parts = explode (': ' , $ key );
120+ $ labelValues = $ parts [2 ];
121+ $ data ['samples ' ][] = array (
122+ 'name ' => $ metaData ['name ' ],
123+ 'labelNames ' => array (),
124+ 'labelValues ' => json_decode ($ labelValues ),
125+ 'value ' => $ value
126+ );
127+ }
128+ $ this ->sortSamples ($ data ['samples ' ]);
129+ $ result [] = new MetricFamilySamples ($ data );
39130 }
40- array_multisort ($ responses );
41- return $ responses ;
131+ return $ result ;
42132 }
43133
44134 /**
@@ -54,18 +144,133 @@ function ($data) { return new Sample($data); },
54144
55145 public function updateHistogram (array $ data )
56146 {
57- // TODO: Implement incrementByFloat() method.
147+ // Initialize the sum
148+ $ metaKey = $ this ->metaKey ($ data );
149+ if (array_key_exists ($ metaKey , $ this ->histograms ) === false ) {
150+ $ this ->histograms [$ metaKey ] = [
151+ 'meta ' => $ this ->metaData ($ data ),
152+ 'samples ' => []
153+ ];
154+ }
155+ $ sumKey = $ this ->histogramBucketValueKey ($ data , 'sum ' );
156+ if (array_key_exists ($ sumKey , $ this ->histograms [$ metaKey ]['samples ' ]) === false ) {
157+ $ this ->histograms [$ metaKey ]['samples ' ][$ sumKey ] = 0 ;
158+ }
159+
160+ $ this ->histograms [$ metaKey ]['samples ' ][$ sumKey ] += $ data ['value ' ];
161+
162+
163+ $ bucketToIncrease = '+Inf ' ;
164+ foreach ($ data ['buckets ' ] as $ bucket ) {
165+ if ($ data ['value ' ] <= $ bucket ) {
166+ $ bucketToIncrease = $ bucket ;
167+ break ;
168+ }
169+ }
170+
171+ $ bucketKey = $ this ->histogramBucketValueKey ($ data , $ bucketToIncrease );
172+ if (array_key_exists ($ bucketKey , $ this ->histograms [$ metaKey ]['samples ' ]) === false ) {
173+ $ this ->histograms [$ metaKey ]['samples ' ][$ bucketKey ] = 0 ;
174+ }
175+ $ this ->histograms [$ metaKey ]['samples ' ][$ bucketKey ] += 1 ;
58176 }
59177
60178 public function updateGauge (array $ data )
61179 {
62- // TODO: Implement updateGauge() method.
180+ $ metaKey = $ this ->metaKey ($ data );
181+ $ valueKey = $ this ->valueKey ($ data );
182+ if (array_key_exists ($ metaKey , $ this ->gauges ) === false ) {
183+ $ this ->gauges [$ metaKey ] = [
184+ 'meta ' => $ this ->metaData ($ data ),
185+ 'samples ' => []
186+ ];
187+ }
188+ if (array_key_exists ($ valueKey , $ this ->gauges [$ metaKey ]['samples ' ]) === false ) {
189+ $ this ->gauges [$ metaKey ]['samples ' ][$ valueKey ] = 0 ;
190+ }
191+ if ($ data ['command ' ] === Adapter::COMMAND_SET ) {
192+ $ this ->gauges [$ metaKey ]['samples ' ][$ valueKey ] = $ data ['value ' ];
193+ } else {
194+ $ this ->gauges [$ metaKey ]['samples ' ][$ valueKey ] += $ data ['value ' ];
195+ }
63196 }
64197
65198 public function updateCounter (array $ data )
66199 {
67- // TODO: Implement updateCounter() method.
200+ $ metaKey = $ this ->metaKey ($ data );
201+ $ valueKey = $ this ->valueKey ($ data );
202+ if (array_key_exists ($ metaKey , $ this ->counters ) === false ) {
203+ $ this ->counters [$ metaKey ] = [
204+ 'meta ' => $ this ->metaData ($ data ),
205+ 'samples ' => []
206+ ];
207+ }
208+ if (array_key_exists ($ valueKey , $ this ->counters [$ metaKey ]['samples ' ]) === false ) {
209+ $ this ->counters [$ metaKey ]['samples ' ][$ valueKey ] = 0 ;
210+ }
211+ if ($ data ['command ' ] === Adapter::COMMAND_SET ) {
212+ $ this ->counters [$ metaKey ]['samples ' ][$ valueKey ] = 0 ;
213+ } else {
214+ $ this ->counters [$ metaKey ]['samples ' ][$ valueKey ] += $ data ['value ' ];
215+ }
216+ }
217+
218+ /**
219+ * @param array $data
220+ *
221+ * @param $bucket
222+ *
223+ * @return string
224+ */
225+ private function histogramBucketValueKey (array $ data , $ bucket )
226+ {
227+ return implode (': ' , array (
228+ $ data ['type ' ],
229+ $ data ['name ' ],
230+ json_encode ($ data ['labelValues ' ]),
231+ $ bucket
232+ ));
233+ }
234+
235+ /**
236+ * @param array $data
237+ *
238+ * @return string
239+ */
240+ private function metaKey (array $ data )
241+ {
242+ return implode (': ' , array ($ data ['type ' ], $ data ['name ' ], 'meta ' ));
243+ }
244+
245+ /**
246+ * @param array $data
247+ *
248+ * @return string
249+ */
250+ private function valueKey (array $ data )
251+ {
252+ return implode (': ' ,
253+ array ($ data ['type ' ], $ data ['name ' ], json_encode ($ data ['labelValues ' ]), 'value ' ));
68254 }
69255
256+ /**
257+ * @param array $data
258+ *
259+ * @return array
260+ */
261+ private function metaData (array $ data )
262+ {
263+ $ metricsMetaData = $ data ;
264+ unset($ metricsMetaData ['value ' ]);
265+ unset($ metricsMetaData ['command ' ]);
266+ unset($ metricsMetaData ['labelValues ' ]);
267+ return $ metricsMetaData ;
268+ }
70269
270+ private function sortSamples (array &$ samples )
271+ {
272+ usort ($ samples , function ($ a , $ b ) {
273+ return strcmp (implode ("" , $ a ['labelValues ' ]), implode ("" , $ b ['labelValues ' ]));
274+ });
275+ }
71276}
0 commit comments