o11y-8.x-1.x-dev/modules/o11y_metrics/src/Traits/FormWithBuckets.php
modules/o11y_metrics/src/Traits/FormWithBuckets.php
<?php
namespace Drupal\o11y_metrics\Traits;
use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\Render\Markup;
use Drupal\Core\Config\ConfigFactoryInterface;
use Drupal\o11y_metrics\Bridge\PrometheusBridgeInterface;
use Symfony\Component\DependencyInjection\ContainerInterface;
/**
* Trait for config form classes.
*/
trait FormWithBuckets {
/**
* The promphp bridge.
*
* @var \Drupal\o11y_metrics\Bridge\PrometheusBridgeInterface
*/
protected $promBridge;
/**
* {@inheritdoc}
*/
final public function __construct(
ConfigFactoryInterface $config_factory,
PrometheusBridgeInterface $promBridge
) {
parent::__construct($config_factory);
$this->promBridge = $promBridge;
}
/**
* {@inheritdoc}
*/
public static function create(ContainerInterface $container) {
return new static(
$container->get('config.factory'),
$container->get('o11y_metrics.prometheus_bridge')
);
}
/**
* Get an exclude_admin_paths form element.
*/
protected function getExcludeAdminPathsFormElement(bool $exclude_admin_paths): array {
return [
'#type' => 'checkbox',
'#title' => $this->t('Exclude admin paths'),
'#description' => $this->t('Whether the metrics exclude admin paths'),
'#default_value' => $exclude_admin_paths,
];
}
/**
* Get a histogram textarea element.
*/
protected function getBucketsFormElement(
string $label,
string $unitsOfBuckets,
string $metricsSourceClassName,
array $defaultBuckets,
array $bucketsFromConf = []
) {
$hasData = $this->promBridge->hasMetricsOfSource($metricsSourceClassName);
if ($hasData) {
$warning = Markup::create($this->t('<strong>Warning: Not possible to modify since metrics have been created.</strong>'));
}
else {
$warning = Markup::create($this->t('<strong>Warning: Buckets MUST NOT be changed once the metrics are created.</strong>'));
}
$default_histograms = implode(PHP_EOL, array_map(function ($v) {
return '<li>' . $v . '</li>';
}, $defaultBuckets));
$description = $this->t('@warning<br/>
Buckets used for the prometheus histograms metrics of the <strong>@label</strong> (units for buckets are <strong>@units</strong>).<br/>
If empty the following defaults will be used:
<ul>
@default_histograms
</ul>',
[
'@label' => $label,
'@units' => $unitsOfBuckets,
'@warning' => Markup::create($warning),
'@default_histograms' => Markup::create($default_histograms),
]
);
return [
'#type' => 'textarea',
'#title' => $this->t('Buckets for @label histograms', ['@label' => $label]),
'#description' => $description,
'#default_value' => implode("\r\n", $bucketsFromConf),
'#disabled' => $hasData,
];
}
/**
* Parse the textarea input to an array.
*/
protected function parseEolSeparatedValue(string $value): array {
return array_values(array_filter(array_map('trim', preg_split('/\r\n|\r|\n/', $value))));
}
/**
* Validation logic for buckets.
*/
protected function validateBucketsValue(FormStateInterface $form_state, string $formElementName) {
$inputSplit = $this->parseEolSeparatedValue($form_state->getValue($formElementName) ?? '');
$invalid_buckets = array_filter(array_map(function ($v) {
return (filter_var($v, FILTER_VALIDATE_FLOAT) === FALSE) ? $v : FALSE;
}, $inputSplit));
if (!empty($invalid_buckets)) {
$form_state->setErrorByName($formElementName, $this->t('Please input only floats'));
}
$sortedInput = $inputSplit;
sort($sortedInput);
if ($sortedInput != array_values($inputSplit)) {
$form_state->setErrorByName($formElementName, $this->t('Please sort the numbers in increasing order'));
}
}
}
