Interpolating values into the message produces a unique string per event, so an aggregator sees a million distinct messages rather than one with a million occurrences.
// unaggregatable
$logger->error("Payment failed for order {$id}: declined (code 51)");
// a constant message, and everything variable in context
$logger->error('payment.failed', [
'order_id' => (int) $id,
'reason' => 'card_declined',
'gateway_code' => 51,
]);
The message becoming a constant is the change developers resist because the line reads worse to a human tailing a file — and reads enormously better to anything that aggregates. Casting explicitly matters more than it looks: field types are fixed by whichever document reaches the index first, so an order_id that is an integer in one service and a string in another is rejected in the second, silently, in a counter nobody watches.