Experiment decorators
Decorators customise how experiments and arms are displayed in the RL reports interface. By default, experiments and arms show their raw IDs, but decorators can provide human-readable labels.
Creating a decorator
Implement the ExperimentDecoratorInterface:
namespace Drupal\my_module\Decorator;
use Drupal\Core\Entity\EntityTypeManagerInterface;
use Drupal\rl\Decorator\ExperimentDecoratorInterface;
/**
* Decorates experiments owned by my_module.
*/
class MyExperimentDecorator implements ExperimentDecoratorInterface {
/**
* Constructs a MyExperimentDecorator.
*/
public function __construct(
protected readonly EntityTypeManagerInterface $entityTypeManager,
) {}
/**
* {@inheritdoc}
*/
public function decorateExperiment(string $experiment_id): ?array {
if (!str_starts_with($experiment_id, 'my_module-')) {
return NULL;
}
return ['#markup' => 'My Custom Experiment Name'];
}
/**
* {@inheritdoc}
*/
public function decorateArm(string $experiment_id, string $arm_id): ?array {
if (!str_starts_with($experiment_id, 'my_module-')) {
return NULL;
}
$entity = $this->entityTypeManager->getStorage('node')->load($arm_id);
if ($entity) {
$label = htmlspecialchars($entity->label());
$id = htmlspecialchars($arm_id);
return [
'#markup' => $label . ' <small>(' . $id . ')</small>',
];
}
return NULL;
}
}
Registering the decorator
Add the decorator service to your module's *.services.yml with the
rl_experiment_decorator tag:
services:
my_module.experiment_decorator:
class: Drupal\my_module\Decorator\MyExperimentDecorator
arguments: ['@entity_type.manager']
tags:
- { name: rl_experiment_decorator }
The decorator manager automatically discovers all tagged services and calls them in order until one returns a non-NULL value.
Best practices
- Check experiment prefix: return
NULLearly for experiments your decorator does not handle. - Handle missing entities: entities may be deleted; return
NULLif the entity cannot be loaded. - Use render arrays: return proper Drupal render arrays for consistent theming and security.
- Escape output: use
htmlspecialchars()for any user-provided content.