Você declarou o plugin no di.xml, limpou cache, e o before continua sem disparar. Nem um error_log() na primeira linha aparece. Antes de reescrever o módulo, confirme se o Magento chegou a gerar o interceptor: isso já elimina metade das hipóteses.
O interceptor existe?
Toda classe interceptada ganha uma classe filha em generated/code/. Se o arquivo não existe, ou existe mas não traz o seu método, o Magento nem tentou chamar você:
cd /var/www/loja
ls generated/code/Magento/Catalog/Model/Product/Interceptor.php
sudo -u www-data php bin/magento dev:di:info 'MagentoCatalogModelProduct'
# em production mode nada é gerado em runtime
sudo -u www-data rm -rf generated/code generated/metadata
sudo -u www-data php bin/magento setup:di:compile
Rode o rm e o compile como o usuário do PHP e em janela de manutenção: arquivo gerado com dono errado derruba a loja com erro de permissão, e enquanto o compile roda a loja fica sem interceptor nenhum.
O dev:di:info devolve a preference aplicada, os parâmetros do construtor e uma tabela de plugins com as colunas Plugin, Method e Type. Repare no cabeçalho da saída: ele lê só a área GLOBAL. Plugin declarado em etc/frontend/di.xml ou etc/adminhtml/di.xml não aparece nessa lista, então a ausência sozinha não condena a sua declaração.
As três causas de sempre
- Método
final,private,protectedoustatic, ou a classe inteira marcada como final. O interceptor herda a classe e sobrescreve o método público; o que é final não dá pra sobrescrever. Construtor e destrutor também ficam de fora. - O objeto foi criado com
newno código que chama. Plugin só pega instância entregue pelo ObjectManager, ou seja, injetada no construtor ou vinda de uma factory gerada. - di.xml na área errada. Plugin em
etc/adminhtml/di.xmlnão roda no frontend nem em chamada REST. Se precisa valer em todo canto, o lugar éetc/di.xml.
Sobrou tudo certo e ainda passa reto? Procure por disabled="true" em outros módulos usando o mesmo valor de name no seu plugin: qualquer módulo carregado depois pode desligar o seu com uma linha só.