In my experience, even these situations tend to grow arms and legs pretty quickly, so you end up with a 'verbose' boolean that accepts four values: True, False, "superverbose" and "off". Then you notice that in some places the function is being called with an array as the value for 'verbose', because you're in a language where arrays are implicitly cast to Boolean (I'm looking at you python).
There are too many cases where the optional parameter is not really a boolean, but merely a sum type which coincidentally only has two members at the moment, but is likely to grow to more members.
logger.error("message")
or a log statement with a severity parameter logger.log(LOGLEVEL.ERROR, "message")
That lets you change the capture level based on the situation without the need to recompile your application, on a fine granularity (eg class-level). Getting errors in production? Edit one line of XML to turn up the capture level and go.High-performance logging frameworks like SLF4J handle the first case very intelligently, there's almost no overhead to skipping a logging call. If used wisely with a high-performance logging engine (Log4j2 or Logback) there shouldn't be many calls needed, and except in very narrow situations the performance impact (if you could find one) would be drastically outweighed by the improvements in maintainability. Code quality does have its costs at times - otherwise we'd all be writing assembly. It's not going to be the straw that breaks the camel's back when it comes to performance.
In an enterprise product, sure, I'd include a logging framework, but for smaller projects, more often than not, it may bring in unnecessary complexity.
I agree with the author that with flags in fn-signature, the code becomes tough to reason about at the call-site; but a preferred solution, IMO, is to use "named arguments" or "labeled arguments" in the languages that allow them and/or write proper doc-strings in languages that don't.
For instance in OCaml you'd do (note: specifying types is optional):
You'd call the above as: Optional arguments allow for a terser call-site syntax at the cost of implicit behaviour: You could then call the above fn: