@@ -307,6 +307,155 @@ public function updateCounter(array $data): void
307307 );
308308 }
309309
310+ /**
311+ * @param mixed[] $data
312+ * @throws StorageException
313+ */
314+ public function initHistogram (array $ data ): void
315+ {
316+ $ this ->ensureOpenConnection ();
317+
318+ $ metricKey = $ this ->toMetricKey ($ data );
319+
320+ // If hash exists, we skip init
321+ if ((bool ) $ this ->redis ->hLen ($ metricKey )) {
322+ return ;
323+ }
324+
325+ $ bucketsToSet = $ data ['buckets ' ];
326+ array_unshift ($ bucketsToSet , 'sum ' );
327+ $ bucketsToSet [] = '+Inf ' ;
328+
329+ $ labelsCartesian = $ this ->cartesian ($ data ['labelValuesSet ' ]);
330+
331+ $ values = [];
332+ foreach ($ bucketsToSet as $ bucket ) {
333+ foreach ($ labelsCartesian as $ labelValues ) {
334+ $ values [] = json_encode (['b ' => $ bucket , 'labelValues ' => array_values ($ labelValues )]);
335+ }
336+ }
337+
338+ $ valuesString = $ this ->makeLuaValuesString ($ values );
339+
340+ // metadata
341+ unset($ data ['labelValuesSet ' ]);
342+
343+ $ this ->redis ->eval (
344+ <<<LUA
345+ redis.call('hSet', KEYS[1], '__meta', ARGV[1])
346+
347+ for _, subKey in pairs({ {$ valuesString }}) do
348+ redis.call('hIncrBy', KEYS[1], subKey, 0)
349+ end
350+
351+ redis.call('sAdd', KEYS[2], KEYS[1])
352+ LUA
353+ ,
354+ [
355+ $ metricKey , // key1
356+ self ::$ prefix . Histogram::TYPE . self ::PROMETHEUS_METRIC_KEYS_SUFFIX , // key2
357+ json_encode ($ data ), // arg1
358+ ],
359+ 2
360+ );
361+ }
362+
363+ /**
364+ * @param mixed[] $data
365+ *
366+ * @throws StorageException
367+ */
368+ public function initGauge (array $ data ): void
369+ {
370+ $ this ->ensureOpenConnection ();
371+
372+ $ metricKey = $ this ->toMetricKey ($ data );
373+
374+ // If hash exists, we skip init
375+ if ($ this ->redis ->hLen ($ metricKey )) {
376+ return ;
377+ }
378+
379+ $ labelsCartesian = $ this ->cartesian ($ data ['labelValuesSet ' ]);
380+
381+ $ values = [];
382+ foreach ($ labelsCartesian as $ labelValues ) {
383+ $ values [] = json_encode (array_values ($ labelValues ));
384+ }
385+
386+ $ valuesString = $ this ->makeLuaValuesString ($ values );
387+
388+ // metadata
389+ unset($ data ['labelValuesSet ' ]);
390+
391+ $ this ->redis ->eval (
392+ <<<LUA
393+ redis.call('hMSet', KEYS[1], '__meta', ARGV[1])
394+
395+ for _, subKey in pairs({ {$ valuesString }}) do
396+ redis.call('hIncrBy', KEYS[1], subKey, 0)
397+ end
398+
399+ redis.call('sAdd', KEYS[2], KEYS[1])
400+ LUA
401+ ,
402+ [
403+ $ metricKey , // key1
404+ self ::$ prefix . Gauge::TYPE . self ::PROMETHEUS_METRIC_KEYS_SUFFIX , // key2
405+ json_encode ($ data ), // arg1
406+ ],
407+ 2
408+ );
409+ }
410+
411+ /**
412+ * @param mixed[] $data
413+ *
414+ * @throws StorageException
415+ */
416+ public function initCounter (array $ data ): void
417+ {
418+ $ this ->ensureOpenConnection ();
419+
420+ $ metricKey = $ this ->toMetricKey ($ data );
421+
422+ // If hash exists, we skip init
423+ if ($ this ->redis ->hLen ($ metricKey )) {
424+ return ;
425+ }
426+
427+ $ labelsCartesian = $ this ->cartesian ($ data ['labelValuesSet ' ]);
428+
429+ $ values = [];
430+ foreach ($ labelsCartesian as $ labelValues ) {
431+ $ values [] = json_encode (array_values ($ labelValues ));
432+ }
433+
434+ $ valuesString = $ this ->makeLuaValuesString ($ values );
435+
436+ // metadata
437+ unset($ data ['labelValuesSet ' ]);
438+
439+ $ this ->redis ->eval (
440+ <<<LUA
441+ redis.call('hMSet', KEYS[1], '__meta', ARGV[1])
442+
443+ for _, subKey in pairs({ {$ valuesString }}) do
444+ redis.call('hIncrBy', KEYS[1], subKey, 0)
445+ end
446+
447+ redis.call('sAdd', KEYS[2], KEYS[1])
448+ LUA
449+ ,
450+ [
451+ $ metricKey , // key1
452+ self ::$ prefix . Counter::TYPE . self ::PROMETHEUS_METRIC_KEYS_SUFFIX , // key2
453+ json_encode ($ data ), // arg1
454+ ],
455+ 2
456+ );
457+ }
458+
310459 /**
311460 * @return mixed[]
312461 */
@@ -468,4 +617,44 @@ private function toMetricKey(array $data): string
468617 {
469618 return implode (': ' , [self ::$ prefix , $ data ['type ' ], $ data ['name ' ]]);
470619 }
620+
621+ /**
622+ * @param mixed[] $input
623+ * @return mixed[]
624+ */
625+ private function cartesian (array $ input ): array
626+ {
627+ $ result = [[]];
628+
629+ foreach ($ input as $ key => $ values ) {
630+ $ append = [];
631+
632+ foreach ($ result as $ product ) {
633+ foreach ($ values as $ item ) {
634+ $ product [$ key ] = $ item ;
635+ $ append [] = $ product ;
636+ }
637+ }
638+
639+ $ result = $ append ;
640+ }
641+
642+ return $ result ;
643+ }
644+
645+ /**
646+ * @param mixed[] $values
647+ * @return string
648+ */
649+ private function makeLuaValuesString (array $ values ): string
650+ {
651+ $ values = array_map (
652+ static function (string $ value ): string {
653+ return '" ' . addslashes ($ value ) . '" ' ;
654+ },
655+ $ values
656+ );
657+
658+ return implode (', ' , $ values );
659+ }
471660}
0 commit comments