A formatted message is a string a machine has to parse back, and every parser is a regular expression somebody will break.
// a person can read it; nothing can query it
Log::info("Order {$order->id} failed for user {$user->id}: {$e->getMessage()}");
// queryable
Log::warning('order.sync.failed', [
'order_id' => $order->id,
'user_id' => $user->id,
'trace_id' => $trace->id(),
'exception' => $e->getMessage(),
'attempt' => $attempt,
]);
The message becomes a stable event name rather than a sentence, which is what makes counting occurrences possible — a message with an interpolated id is a unique string and cannot be grouped. Everything variable moves into fields. The cost is a log that is harder to read on a terminal, which a formatter for local development solves and which is a real objection worth answering rather than dismissing.