A PSR-3 context array is not a string interpolation

Building the message with the values in it produces a unique string per event, which means an aggregator sees a million distinct messages instead of one with a million occurrences.

// unaggregatable
$logger->error("Payment failed for order {$id}: declined");

// a constant message, and structured context
$logger->error('payment.failed', [
    'order_id' => $id,
    'reason'   => 'declined',
]);

// PSR-3 also allows placeholders, which are filled by the handler:
$logger->error('Payment failed for order {order_id}', ['order_id' => $id]);

The placeholder form is the compromise that keeps the line readable to a human tailing a file while keeping the values addressable as fields — the handler decides whether to substitute. Context keys must be strings and values should be scalars or objects with a __toString; passing an entire model in serialises whatever it holds, which is how personal data ends up in a log index. Deciding the key names once and writing them down is worth more than any handler configuration.