Ability to filter and properly format logs received from Slf4J API
nartamonov opened this issue · 1 comments
I use zio-logging
with slf4j-bridge
so that any logs from legacy non-ZIO libraries which use Slf4j API go through zio-logging
stuff. So I expect the functionality of zio-logging
can be applied to logs received from legacy libraries.
Currently slf4j-bridge
stores original names of Slf4J loggers into log spans:
// Excerpts from org.slf4j.impl.ZioLogger
private def run(f: ZIO[Any, Nothing, Unit]): Unit =
factory.run {
ZIO.logSpan(name)(f)
}
// ...
// Any call to Slf4j API goes throught run()
override def info(msg: String): Unit =
run(ZIO.logInfo(msg))
This leads to significant limitations:
- We can't filter logs received from Slf4J API via standard
LogFilter.logLevelByName
because it depends on theLoggerNameExtractor.trace
that currently doesn't extract the original names of Slf4J loggers. In all cases the name of the logger will beorg.slf4j.impl.ZioLogger
. That's useless. - We can't make a
LogFormat
that extracts the name of the Slf4J logger for the same reason:LoggerNameExtractor.trace
can't do it.
Moreover, users of zio-logging
can't write their own version of LoggerNameExtractor
that can extract Slf4J logger names because LoggerNameExtractor
does not have access to attached log spans:
trait LoggerNameExtractor {
def apply(
trace: Trace,
context: FiberRefs,
annotations: Map[String, String]
): Option[String]
}
Proposals
I see two possible solutions:
- We can adjust interface
LoggerNameExtractor
to give it access to log spans. - We can store original name of the Slf4j logger in annotation instead of span, something like:
private def run(f: ZIO[Any, Nothing, Unit]): Unit =
factory.run {
ZIO.logAnnotation("slf4j-logger-name", name)(f)
}
@nartamonov, thank you for report and proposal,
yes, I think you are right, considering current design of zio-logging, LogAnnotation is probably better way for log name propagation
i created PR #599