PluginProbe
DecaLog / 4.4.0
DecaLog v4.4.0
3.0.2 3.1.0 3.10.0 3.2.0 3.3.0 3.4.0 3.4.1 3.5.0 3.5.1 3.6.0 3.6.1 3.6.2 3.6.3 3.7.0 3.7.1 3.8.0 3.9.0 3.9.1 4.0.0 4.1.0 4.2.0 4.3.0 4.3.1 4.4.0 4.5.0 All 75 releases
decalog / includes / features / class-dmonitor.php

class-dmonitor.php in DecaLog 4.4.0, at includes/features/class-dmonitor.php

792 lines 24.5 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * DecaLog monitor definition.
4 *
5 * @package Features
6 * @author Pierre Lannoy <https://pierre.lannoy.fr/>.
7 * @since 3.0.0
8 */
9
10 namespace Decalog\Plugin\Feature;
11
12 use Prometheus\CollectorRegistry;
13 use Prometheus\Exception\MetricNotFoundException;
14 use Prometheus\Storage\InMemory;
15 use Decalog\System\Option;
16 use Decalog\System\Environment;
17 use Decalog\Logger;
18 use Decalog\Plugin\Feature\ClassTypes;
19 use Decalog\System\Markdown;
20 use Decalog\Listener\AbstractListener;
21
22 /**
23 * Main DecaLog monitor class.
24 *
25 * This class defines all code necessary to monitor metrics with DecaLog.
26 *
27 * @package Features
28 * @author Pierre Lannoy <https://pierre.lannoy.fr/>.
29 * @since 3.0.0
30 */
31 class DMonitor {
32
33 /**
34 * The class of the component.
35 *
36 * @since 3.0.0
37 * @var string $class Maintains the class of the component.
38 */
39 protected $class = 'unknwon';
40
41 /**
42 * The name of the component.
43 *
44 * @since 3.0.0
45 * @var string $class Maintains the name of the component.
46 */
47 protected $name = 'unknown';
48
49 /**
50 * The version of the component.
51 *
52 * @since 3.0.0
53 * @var string $version Maintains the version of the component.
54 */
55 protected $version = '-';
56
57 /**
58 * Is metrics mode active?
59 *
60 * @since 3.7.0
61 * @var boolean $active True if there is at least one running metrics logger.
62 */
63 public static $active = false;
64
65 /**
66 * The metrics registry.
67 *
68 * @since 3.0.0
69 * @var array $metrics_registry Maintains the metrics definitions.
70 */
71 private static $metrics_registry = [];
72
73 /**
74 * The "production" CollectorRegistry instance.
75 *
76 * @since 3.0.0
77 * @var \Prometheus\CollectorRegistry $production Maintains the internal CollectorRegistry instance.
78 */
79 private static $production = null;
80
81 /**
82 * The "development" CollectorRegistry instance.
83 *
84 * @since 3.0.0
85 * @var \Prometheus\CollectorRegistry $development Maintains the internal CollectorRegistry instance.
86 */
87 private static $development = null;
88
89 /**
90 * The internal logger.
91 *
92 * @since 3.0.0
93 * @var \Decalog\Logger $logger Maintains the logger.
94 */
95 private static $logger = null;
96
97 /**
98 * The technical metrics labels names.
99 *
100 * @since 3.0.0
101 * @var array $label_names The names list.
102 */
103 private $label_names = [
104 'prod' => [ 'channel', 'environment' ],
105 'dev' => [ 'channel', 'environment' ],
106 ];
107
108 /**
109 * The metrics labels values.
110 *
111 * @since 3.0.0
112 * @var array $label_values The values list.
113 */
114 private $label_values = [];
115
116 /**
117 * Is logger allowed to run.
118 *
119 * @since 3.0.0
120 * @var boolean $allowed Maintains the allowed status of the monitor.
121 */
122 private $allowed = true;
123
124 /**
125 * Is the first initialization done?
126 *
127 * @since 3.0.0
128 * @var boolean $self_initialized Is the first initialization done?
129 */
130 private static $self_initialized = false;
131
132 /**
133 * Initialize the class and set its properties.
134 *
135 * @param string $class The class identifier, must be in ClassTypes::$classes.
136 * @param string $name Optional. The name of the component.
137 * @param string $version Optional. The version of the component.
138 * @since 3.0.0
139 */
140 public function __construct( $class, $name = null, $version = null ) {
141 if ( ! isset( self::$logger ) && class_exists( '\Decalog\Logger' ) ) {
142 self::$logger = new \Decalog\Logger( 'plugin', DECALOG_PRODUCT_NAME, DECALOG_VERSION );
143 }
144 if ( ! isset( self::$logger ) && ! class_exists( '\Decalog\Logger' ) ) {
145 self::$logger = new \Psr\Log\NullLogger();
146 }
147 if ( ! Option::network_get( 'autolisteners' ) ) {
148 $this->allowed = in_array( 'prom', Option::network_get( 'listeners' ), true );
149 }
150 if ( $this->allowed ) {
151 if ( in_array( $class, ClassTypes::$classes, true ) ) {
152 $this->class = $class;
153 }
154 if ( $name && is_string( $name ) ) {
155 $this->name = $name;
156 }
157 if ( $version && is_string( $version ) ) {
158 $this->version = $version;
159 }
160 if ( ! isset( self::$production ) ) {
161 self::$production = new CollectorRegistry( new InMemory(), false );
162 }
163 if ( ! isset( self::$development ) ) {
164 self::$development = new CollectorRegistry( new InMemory(), false );
165 }
166 $this->label_values = [
167 'prod' => [ $this->normalize_string( $this->current_channel_tag() ), $this->normalize_string( Environment::stage() ) ],
168 'dev' => [ $this->normalize_string( $this->current_channel_tag() ), $this->normalize_string( Environment::stage() ) ],
169 ];
170 self::$logger->debug( 'A new instance of DecaLog monitor is initialized and operational.' );
171 } else {
172 self::$logger->debug( 'Skipped initialization of a DecaLog monitor.' );
173 }
174 if ( ! self::$self_initialized ) {
175 self::$self_initialized = true;
176 $this->class = 'plugin';
177 $this->name = DECALOG_PRODUCT_NAME;
178 $this->version = DECALOG_VERSION;
179 foreach ( EventTypes::$levels as $key => $level ) {
180 $this->create_dev_counter( 'event_' . $key, 'Number of handled ' . $key . ' events per request - [count]' );
181 }
182 $this->create_prod_counter( 'metric_prod', 'Number of handled `production` metrics - [count]' );
183 $this->create_dev_counter( 'metric_dev', 'Number of handled `development` metrics - [count]' );
184 add_action( 'shutdown', [ $this, 'before_close' ], AbstractListener::$monitor_priority + 1, 0 );
185 $this->class = $class;
186 $this->name = $name;
187 $this->version = $version;
188 }
189 }
190
191 /**
192 * Self-metrics handling..
193 *
194 * @since 3.0.0
195 */
196 public function before_close() {
197 if ( $this->allowed ) {
198 $class = $this->class;
199 $name = $this->name;
200 $version = $this->version;
201 $this->class = 'plugin';
202 $this->name = DECALOG_PRODUCT_NAME;
203 $this->version = DECALOG_VERSION;
204 foreach ( EventTypes::$levels as $key => $level ) {
205 $this->inc_dev_counter( 'event_' . $key, DLogger::count( $key ) );
206 }
207 $this->inc_prod_counter( 'metric_prod', count( self::$production->getMetricFamilySamples() ) );
208 $this->inc_dev_counter( 'metric_dev', count( self::$development->getMetricFamilySamples() ) );
209 $this->class = $class;
210 $this->name = $name;
211 $this->version = $version;
212 }
213 }
214
215 /**
216 * Get the metrics registry.
217 *
218 * @return array The registry;
219 * @since 3.0.0
220 */
221 public static function registry() {
222 $allowed = true;
223 if ( ! Option::network_get( 'autolisteners' ) ) {
224 $allowed = in_array( 'prom', Option::network_get( 'listeners' ), true );
225 }
226 if ( $allowed ) {
227 return self::$metrics_registry;
228 }
229 return [];
230 }
231
232 /**
233 * Register the metrics.
234 *
235 * @param boolean $prod True if it's production profile, false if it's development profile.
236 * @param string $type The type of the metrics (counter, gauge or histogram).
237 * @param string $name The unique name of the metrics.
238 * @param string $help The help string associated with this metrics.
239 * @since 3.0.0
240 */
241 private function register( $prod, $type, $name, $help ) {
242 $prod = $prod ? 'production' : 'development';
243 if ( ! array_key_exists( $this->class, self::$metrics_registry ) ) {
244 self::$metrics_registry[ $this->class ] = [];
245 }
246 if ( ! array_key_exists( $prod, self::$metrics_registry[ $this->class ] ) ) {
247 self::$metrics_registry[ $this->class ][ $prod ] = [];
248 }
249 if ( ! array_key_exists( $type, self::$metrics_registry[ $this->class ][ $prod ] ) ) {
250 self::$metrics_registry[ $this->class ][ $prod ][ $type ] = [];
251 }
252 $idx = $this->current_namespace() . '_' . $name;
253 if ( ! array_key_exists( $idx, self::$metrics_registry[ $this->class ][ $prod ][ $type ] ) ) {
254 self::$metrics_registry[ $this->class ][ $prod ][ $type ][ $this->current_namespace() . '_' . $name ] = [
255 'name' => $this->name,
256 'version' => $this->version,
257 'help' => $help,
258 ];
259 }
260 }
261
262 /**
263 * Normalizes the metrics name.
264 *
265 * @param string $name The unique name of the metrics.
266 * @@return string The normalized name.
267 * @since 3.0.0
268 */
269 private function normalize( $name ) {
270 return ( preg_replace( '/[^a-zA-Z0-9_]/', '', $name ) ?? 'unknown_' . md5( (string) $name ) );
271 }
272
273 /**
274 * Creates the named counter, in the right profile.
275 *
276 * @param boolean $prod True if it's production profile, false if it's development profile.
277 * @param string $name The unique name of the counter.
278 * @param string $help The help string associated with this counter.
279 * @since 3.0.0
280 */
281 private function create_counter( $prod, $name, $help ) {
282 if ( ! $this->allowed ) {
283 return;
284 }
285 if ( '' === $name ) {
286 self::$logger->error( 'A metric must be named.' );
287 }
288 $name = $this->normalize( $name );
289 try {
290 $registry = ( $prod ? self::$production : self::$development );
291 $registry->registerCounter( $this->current_namespace(), $name, $help, $this->label_names[ ( $prod ? 'prod' : 'dev' ) ] );
292 $this->register( $prod, 'counter', $name, $help );
293 $this->init_counter( $prod, $name );
294 } catch ( \Throwable $e ) {
295 self::$logger->error( $e->getMessage(), [ 'code' => $e->getCode() ] );
296 }
297 }
298
299 /**
300 * Creates and sets the named gauge, in the right profile.
301 *
302 * @param boolean $prod True if it's production profile, false if it's development profile.
303 * @param string $name The unique name of the gauge.
304 * @param int|float $value The initial value to set.
305 * @param string $help The help string associated with this gauge.
306 * @since 3.0.0
307 */
308 private function create_gauge( $prod, $name, $value, $help ) {
309 if ( ! $this->allowed ) {
310 return;
311 }
312 if ( '' === $name ) {
313 self::$logger->error( 'A metric must be named.' );
314 }
315 $name = $this->normalize( $name );
316 try {
317 $registry = ( $prod ? self::$production : self::$development );
318 $registry->registerGauge( $this->current_namespace(), $name, $help, $this->label_names[ ( $prod ? 'prod' : 'dev' ) ] );
319 $this->register( $prod, 'gauge', $name, $help );
320 $this->set_gauge( $prod, $name, $value );
321 } catch ( \Throwable $e ) {
322 self::$logger->error( $e->getMessage(), [ 'code' => $e->getCode() ] );
323 }
324 }
325
326 /**
327 * Creates the named histogram, in the right profile.
328 *
329 * @param boolean $prod True if it's production profile, false if it's development profile.
330 * @param string $name The unique name of the histogram.
331 * @param null|array $buckets The buckets.
332 * @param string $help The help string associated with this histogram.
333 * @since 3.0.0
334 */
335 private function create_histogram( $prod, $name, $buckets, $help ) {
336 if ( ! $this->allowed ) {
337 return;
338 }
339 if ( '' === $name ) {
340 self::$logger->error( 'A metric must be named.' );
341 }
342 $name = $this->normalize( $name );
343 try {
344 $registry = ( $prod ? self::$production : self::$development );
345 $registry->registerHistogram( $this->current_namespace(), $name, $help, $this->label_names[ ( $prod ? 'prod' : 'dev' ) ], $buckets );
346 $this->register( $prod, 'histogram', $name, $help );
347 } catch ( \Throwable $e ) {
348 self::$logger->error( $e->getMessage(), [ 'code' => $e->getCode() ] );
349 }
350 }
351
352 /**
353 * Inits the named counter, in the right profile.
354 *
355 * @param boolean $prod True if it's production profile, false if it's development profile.
356 * @param string $name The unique name of the counter.
357 * @since 3.0.0
358 */
359 private function init_counter( $prod, $name ) {
360 if ( ! $this->allowed ) {
361 return;
362 }
363 if ( '' === $name ) {
364 self::$logger->error( 'A metric must be named.' );
365 }
366 $name = $this->normalize( $name );
367 try {
368 $registry = ( $prod ? self::$production : self::$development );
369 $counter = $registry->getCounter( $this->current_namespace(), $name );
370 $counter->incBy( 0, $this->label_values[ ( $prod ? 'prod' : 'dev' ) ] );
371 } catch ( \Throwable $e ) {
372 if ( $e instanceof MetricNotFoundException ) {
373 if ( Option::network_get( 'unknown_metrics_warn', true ) ) {
374 self::$logger->error( $e->getMessage(), [ 'code' => $e->getCode() ] );
375 }
376 } else {
377 self::$logger->error( $e->getMessage(), [ 'code' => $e->getCode() ] );
378 }
379 }
380 }
381
382 /**
383 * Sets the named gauge, in the right profile.
384 *
385 * @param boolean $prod True if it's production profile, false if it's development profile.
386 * @param string $name The unique name of the gauge.
387 * @param int|float $value The value to set.
388 * @since 3.0.0
389 */
390 private function set_gauge( $prod, $name, $value ) {
391 if ( ! $this->allowed ) {
392 return;
393 }
394 if ( '' === $name ) {
395 self::$logger->error( 'A metric must be named.' );
396 }
397 $name = $this->normalize( $name );
398 try {
399 $registry = ( $prod ? self::$production : self::$development );
400 $gauge = $registry->getGauge( $this->current_namespace(), $name );
401 $gauge->set( $value, $this->label_values[ ( $prod ? 'prod' : 'dev' ) ] );
402 } catch ( \Throwable $e ) {
403 if ( $e instanceof MetricNotFoundException ) {
404 if ( Option::network_get( 'unknown_metrics_warn', true ) ) {
405 self::$logger->error( $e->getMessage(), [ 'code' => $e->getCode() ] );
406 }
407 } else {
408 self::$logger->error( $e->getMessage(), [ 'code' => $e->getCode() ] );
409 }
410 }
411 }
412
413 /**
414 * Increments the named counter, in the right profile.
415 *
416 * @param boolean $prod True if it's production profile, false if it's development profile.
417 * @param string $name The unique name of the counter.
418 * @param int|float $value The value of how much to increment.
419 * @since 3.0.0
420 */
421 private function inc_counter( $prod, $name, $value ) {
422 if ( ! $this->allowed ) {
423 return;
424 }
425 if ( '' === $name ) {
426 self::$logger->error( 'A metric must be named.' );
427 }
428 $name = $this->normalize( $name );
429 try {
430 $registry = ( $prod ? self::$production : self::$development );
431 $counter = $registry->getCounter( $this->current_namespace(), $name );
432 $counter->incBy( $value, $this->label_values[ ( $prod ? 'prod' : 'dev' ) ] );
433 } catch ( \Throwable $e ) {
434 if ( $e instanceof MetricNotFoundException ) {
435 if ( Option::network_get( 'unknown_metrics_warn', true ) ) {
436 self::$logger->error( $e->getMessage(), [ 'code' => $e->getCode() ] );
437 }
438 } else {
439 self::$logger->error( $e->getMessage(), [ 'code' => $e->getCode() ] );
440 }
441 }
442 }
443
444 /**
445 * Increments the named gauge, in the right profile.
446 *
447 * @param boolean $prod True if it's production profile, false if it's development profile.
448 * @param string $name The unique name of the gauge.
449 * @param int|float $value The value of how much to increment.
450 * @since 3.0.0
451 */
452 private function inc_gauge( $prod, $name, $value ) {
453 if ( ! $this->allowed ) {
454 return;
455 }
456 if ( '' === $name ) {
457 self::$logger->error( 'A metric must be named.' );
458 }
459 $name = $this->normalize( $name );
460 try {
461 $registry = ( $prod ? self::$production : self::$development );
462 $gauge = $registry->getGauge( $this->current_namespace(), $name );
463 $gauge->incBy( $value, $this->label_values[ ( $prod ? 'prod' : 'dev' ) ] );
464 } catch ( \Throwable $e ) {
465 if ( $e instanceof MetricNotFoundException ) {
466 if ( Option::network_get( 'unknown_metrics_warn', true ) ) {
467 self::$logger->error( $e->getMessage(), [ 'code' => $e->getCode() ] );
468 }
469 } else {
470 self::$logger->error( $e->getMessage(), [ 'code' => $e->getCode() ] );
471 }
472 }
473 }
474
475 /**
476 * Adds an observation to the named histogram, in the right profile.
477 *
478 * @param boolean $prod True if it's production profile, false if it's development profile.
479 * @param string $name The unique name of the histogram.
480 * @param int|float $value The value to add.
481 * @since 3.0.0
482 */
483 private function observe_histogram( $prod, $name, $value ) {
484 if ( ! $this->allowed ) {
485 return;
486 }
487 if ( '' === $name ) {
488 self::$logger->error( 'A metric must be named.' );
489 }
490 $name = $this->normalize( $name );
491 try {
492 $registry = ( $prod ? self::$production : self::$development );
493 $histogram = $registry->getHistogram( $this->current_namespace(), $name );
494 $histogram->observe( $value, $this->label_values[ ( $prod ? 'prod' : 'dev' ) ] );
495 } catch ( \Throwable $e ) {
496 if ( $e instanceof MetricNotFoundException ) {
497 if ( Option::network_get( 'unknown_metrics_warn', true ) ) {
498 self::$logger->error( $e->getMessage(), [ 'code' => $e->getCode() ] );
499 }
500 } else {
501 self::$logger->error( $e->getMessage(), [ 'code' => $e->getCode() ] );
502 }
503 }
504 }
505
506 /**
507 * Create the named counter, in production profile.
508 *
509 * @param string $name The unique name of the counter.
510 * @param string $help Optional. The help string associated with this counter.
511 * @since 3.0.0
512 */
513 public function create_prod_counter( $name, $help = '' ) {
514 $this->create_counter( true, $name, $help );
515 }
516
517 /**
518 * Increments the named counter, in production profile.
519 *
520 * @param string $name The unique name of the counter.
521 * @param int|float $value The value of how much to increment.
522 * @since 3.0.0
523 */
524 public function inc_prod_counter( $name, $value ) {
525 $this->inc_counter( true, $name, $value );
526 }
527
528 /**
529 * Create the named counter, in development profile.
530 *
531 * @param string $name The unique name of the counter.
532 * @param string $help Optional. The help string associated with this counter.
533 * @since 3.0.0
534 */
535 public function create_dev_counter( $name, $help = '' ) {
536 $this->create_counter( false, $name, $help );
537 }
538
539 /**
540 * Increments the named counter, in development profile.
541 *
542 * @param string $name The unique name of the counter.
543 * @param int|float $value The value of how much to increment.
544 * @since 3.0.0
545 */
546 public function inc_dev_counter( $name, $value ) {
547 $this->inc_counter( false, $name, $value );
548 }
549
550 /**
551 * Create and set the named gauge, in production profile.
552 *
553 * @param string $name The unique name of the gauge.
554 * @param int|float $value Optional. The initial value to set.
555 * @param string $help Optional. The help string associated with this gauge.
556 * @since 3.0.0
557 */
558 public function create_prod_gauge( $name, $value = 0, $help = '' ) {
559 $this->create_gauge( true, $name, $value, $help );
560 }
561
562 /**
563 * Sets the named gauge, in production profile.
564 *
565 * @param string $name The unique name of the gauge.
566 * @param int|float $value The value to set.
567 * @since 3.0.0
568 */
569 public function set_prod_gauge( $name, $value ) {
570 $this->set_gauge( true, $name, $value );
571 }
572
573 /**
574 * Increments the named gauge, in production profile.
575 *
576 * @param string $name The unique name of the gauge.
577 * @param int|float $value The value of how much to increment.
578 * @since 3.0.0
579 */
580 public function inc_prod_gauge( $name, $value ) {
581 $this->inc_gauge( true, $name, $value );
582 }
583
584 /**
585 * Create and set the named gauge, in development profile.
586 *
587 * @param string $name The unique name of the gauge.
588 * @param int|float $value Optional. The initial value to set.
589 * @param string $help Optional. The help string associated with this gauge.
590 * @since 3.0.0
591 */
592 public function create_dev_gauge( $name, $value = 0, $help = '' ) {
593 $this->create_gauge( false, $name, $value, $help );
594 }
595
596 /**
597 * Sets the named gauge, in development profile.
598 *
599 * @param string $name The unique name of the gauge.
600 * @param int|float $value The value to set.
601 * @since 3.0.0
602 */
603 public function set_dev_gauge( $name, $value ) {
604 $this->set_gauge( false, $name, $value );
605 }
606
607 /**
608 * Increments the named gauge, in development profile.
609 *
610 * @param string $name The unique name of the gauge.
611 * @param int|float $value The value of how much to increment.
612 * @since 3.0.0
613 */
614 public function inc_dev_gauge( $name, $value ) {
615 $this->inc_gauge( false, $name, $value );
616 }
617
618 /**
619 * Creates the named histogram, in production profile.
620 *
621 * @param string $name The unique name of the histogram.
622 * @param null|array $buckets Optional. The buckets.
623 * @param string $help Optional. The help string associated with this histogram.
624 * @since 3.0.0
625 */
626 public function create_prod_histogram( $name, $buckets = null, $help = '' ) {
627 $this->create_histogram( true, $name, $buckets, $help );
628 }
629
630 /**
631 * Adds an observation to the named histogram, in production profile.
632 *
633 * @param string $name The unique name of the histogram.
634 * @param int|float $value The value to add.
635 * @since 3.0.0
636 */
637 public function observe_prod_histogram( $name, $value ) {
638 $this->observe_histogram( true, $name, $value );
639 }
640
641 /**
642 * Creates the named histogram, in development profile.
643 *
644 * @param string $name The unique name of the histogram.
645 * @param null|array $buckets Optional. The buckets.
646 * @param string $help Optional. The help string associated with this histogram.
647 * @since 3.0.0
648 */
649 public function create_dev_histogram( $name, $buckets = null, $help = '' ) {
650 $this->create_histogram( false, $name, $buckets, $help );
651 }
652
653 /**
654 * Adds an observation to the named histogram, in development profile.
655 *
656 * @param string $name The unique name of the histogram.
657 * @param int|float $value The value to add.
658 * @since 3.0.0
659 */
660 public function observe_dev_histogram( $name, $value ) {
661 $this->observe_histogram( false, $name, $value );
662 }
663
664 /**
665 * Get the current namespace.
666 *
667 * @return string The current namespace.
668 * @since 3.0.0
669 */
670 private function current_namespace() {
671 $class = strtolower( $this->class );
672 $name = strtolower( str_replace( ' ', '', $this->name ) ); // TODO : replace all non /w char
673 return 'wordpress_' . $class . '_' . $name;
674 }
675
676 /**
677 * Get the current channel tag.
678 *
679 * @return string The current channel tag.
680 * @since 3.0.0
681 */
682 private function current_channel_tag() {
683 return $this->channel_tag( Environment::exec_mode() );
684 }
685
686 /**
687 * Get the channel tag.
688 *
689 * @param integer $id Optional. The channel id (execution mode).
690 * @return string The channel tag.
691 * @since 3.0.0
692 */
693 private function channel_tag( $id = 0 ) {
694 if ( $id >= count( ChannelTypes::$channels ) ) {
695 $id = 0;
696 }
697 return strtolower( ChannelTypes::$channels[ $id ] );
698 }
699
700 /**
701 * Normalize a string.
702 *
703 * @param string $string The string.
704 * @return string The normalized string.
705 * @since 1.10.0+
706 */
707 private function normalize_string( $string ) {
708 $string = str_replace( '"', '', $string );
709 $string = str_replace( '\'', '`', $string );
710 return decalog_filter_string( $string );
711 }
712
713 /**
714 * Get the collector registry for production profile.
715 *
716 * @return \Prometheus\CollectorRegistry The production registry.
717 * @since 3.0.0
718 */
719 public function prod_registry() {
720 return self::$production;
721 }
722
723 /**
724 * Get the collector registry for development profile.
725 *
726 * @return \Prometheus\CollectorRegistry The development registry.
727 * @since 3.0.0
728 */
729 public function dev_registry() {
730 return self::$development;
731 }
732
733 /**
734 * Get the metrics definitions.
735 *
736 * @return array The output of the shortcode, ready to print.
737 * @since 3.0.0
738 */
739 public static function get_metrics_definition() {
740 $content = [];
741 foreach ( self::$metrics_registry as $class => $class_detail ) {
742 foreach ( $class_detail as $env => $env_detail ) {
743 foreach ( $env_detail as $type => $type_detail ) {
744 foreach ( $type_detail as $metrics => $detail ) {
745 $content[ $metrics ] = [
746 'class' => $class,
747 'profile' => $env,
748 'type' => $type,
749 'name' => $metrics,
750 'source' => $detail['name'],
751 'version' => $detail['version'],
752 'description' => $detail['help'],
753 ];
754 }
755 }
756 }
757 }
758 return $content;
759 }
760
761 /**
762 * Get the metrics definitions.
763 *
764 * @param array $attributes 'style' => 'markdown', 'html'.
765 * 'mode' => 'raw', 'clean'.
766 * @return string The output of the shortcode, ready to print.
767 * @since 3.0.0
768 */
769 public static function sc_get_metrics( $attributes ) {
770 $content = '<div class="markdown">';
771 foreach ( self::$metrics_registry as $class => $class_detail ) {
772 $content .= '<p><br/></p>';
773 $content .= '<h2>' . strtoupper( $class ) . ' CLASS</h2>';
774 foreach ( $class_detail as $env => $env_detail ) {
775 $content .= '<h3 style="margin:0;">' . ucfirst( $env ) . ' Profile</h3>';
776 foreach ( $env_detail as $type => $type_detail ) {
777 $content .= '<ul>';
778 foreach ( $type_detail as $metrics => $detail ) {
779 $content .= '<li>' . ucfirst( $type ) . ' <code>' . $metrics . '</code> from ' . $detail['name'] . ' ' . $detail['version'] . ' - ' . $detail['help'] . '.</li>';
780 }
781 $content .= '</ul>';
782 }
783 }
784 }
785 $content .= '</div>';
786 return $content;
787 }
788
789 }
790
791 add_shortcode( 'decalog-metrics', [ 'Decalog\Plugin\Feature\DMonitor', 'sc_get_metrics' ] );
792