zio / zio-logging

Powerful logging for ZIO 2.0 applications, with compatibility with many logging backends out-of-the-box.
https://zio.dev/zio-logging/
Apache License 2.0
174 stars 81 forks source link

slf4j bridge modules "enable" all log levels, causing performance issues #809

Closed ghostdogpr closed 7 months ago

ghostdogpr commented 8 months ago

The slf4j bridge modules hardcode all methods such as isTraceEnabled and isDebugEnabled to true, regardless of the actual log level. The problem is that many libraries that use slf4j for logging rely on these to avoid computing potential expensive operations before logging.

A good example can be found with zio-quill, that contains this code:

private def bindsEnabled = io.getquill.util.Messages.logBinds || underlying.underlying.isTraceEnabled

def logQuery(query: String, params: Seq[Any]): Unit =
  if (!bindsEnabled || params.isEmpty) underlying.debug(query.trimTooLong)
  else {
    underlying.debug("{} - binds: {}", query.trimTooLong, prepareParams(params))
  }

Because isTraceEnabled is hardcoded to true in zio-logging, prepareParams is executed for every query, and it ends up doing a potentially costly toString on all parameters even though the result won't even be logged.

Quill is just an example, there are plenty on libraries that rely on this to avoid useless computations so the hardcoding doesn't seem fit for production usage. Even if we get the level from the current fiber, it seems like it will be too expensive performance-wise (some libraries like Kafka or Netty are very noisy). Maybe a way to override the levels for all slf4j logs with fixed values (e.g. disable all trace/debugs logs without even going to zio) could be a solution.

justcoon commented 8 months ago

hi @ghostdogpr, thank you for report, will take a look, what can be done in this case