« Return to Thread: logging the Scala way and named varargs
The question is why should you go through extra hoops (however minor) to recognize a logging statement?
There is a time and place for implicits, and this is not it - the use case here seems pretty weak and contrived. There is nothing wrong with typing logger.warn(...), it clearly documents that it's a logging statement, and such statements are simply not frequent enough to save much typing by omitting the "logger" part. I know that implicits are cool, but there is no need to abuse them for every little thing.
On 18.06.2009 09:03, Ricky Clarkson wrote:
Surely you can find where warn is defined by searching for an import
containing 'warn'. Or jump to declaration in your IDE.
2009/6/18 Blair Zajac <blair@...>:
On Jun 17, 2009, at 9:57 PM, Walter Smith wrote:
Hi!The point of slf4j's format string, i.e. "The foobar's value is {}", is to
I think logging should be a part of the core libraries of a language... it
is such an unbeloved matter that at least the logging api to use should
not
be something to discuss about in every project.
There is one logging framework built into Java, but it is not very well
received. Especially in the Java enterprise world, log4j is used much more
often for some good reasons, but you can't deploy multiple configurations
for the same classes used in different enterprise applications within one
JVM, if it's part of the parent class loader, i.e. it's used by the
container itself. And there is a third comprehensive logging framework
competing: logback. So it's a good idea for frameworks to be able to use a
generic logging api, so that a customer can use *one* framework for all
the
frameworks in use. And generally Scala is right now in the role of such a
framework, isn't it?
I still see Apache commons logging being used a lot. I think this is not
much better than using prinln directly! It not only lacks important
features
like formatting messages only when needed, or MDCs; I understand that it
still causes perm gen memory leaks when hot deploying.
There is a much better solution, though: SLF4J... IMHO every Java or Scala
programmer should know it.
But SLF4J is a Java api, so I tried to wrap it in "the Scala way":
1. Logging is a trait that defines the logger using the name of the class
you mix it into; a common and regularly used pattern now easily provided
by
a library... that's what I love Scala for.
2. There is a sealed trait LogLevel with objects for error, info, etc.
that
you can pass around, e.g. into a library or to configure instances of a
class. To actually log at a LogLevel, you simply apply your parameters to
it; the logger can be passed in as a implicit argument.
3. The arguments that are used for your format are passed in by name, so
only get evaluated when the log level is enabled, i.e. it's ok to call
debug("client dns name {}", java.net.InetAddress.getByAddress(client));
the
lookup will only be made, if the debug log level is enabled... Scala
rules!
BTW: Is there a simpler way to get an Array[Byte] literal than
Array(192.byteValue,168.byteValue,178.byteValue,1.byteValue)?
avoid interpolation cost if the log message will not be used.
The Scala way of dealing with this is to use by-name arguments. So you end
up with
trait Logger
{
def warn(msg : => String) : Unit
}
trait Slf4jLogger extends Logger
{
private val myRealLogger = Logger.getLogger(this.getClass.getName)
private val isWarnEnabled = myRealLogger.isWarnEnabled
def warn(msg : => String) : Unit
{
if (isWarnEnabled) {
myRealLogger.warn(msg)
}
}
}
Then call it
logger.warn("The foobar's value is " + foobar + ".")
the string concatenation here won't be done unless
my_real_logger.isWarnEnabled is true.
BTW, I'm not a fan of implicits here. I'd much rather see a call
logger.warn("It blew up!")
than
warn("It blew up!")
It's clear I'm calling a logger and don't need to wonder where warn() is
defined.
Check out Lift's logger. It does this nicely and has a slf4j layer.
http://github.com/dpp/liftweb/blob/338119b8d7a76adcb9f45e9aa8a2b946d9c81118/lift-util/src/main/scala/net/liftweb/util/Log.scala
http://github.com/dpp/liftweb/blob/338119b8d7a76adcb9f45e9aa8a2b946d9c81118/lift-util/src/main/scala/net/liftweb/util/Slf4jLog.scala
Regards,
Blair
--
Blair Zajac, Ph.D.
CTO, OrcaWare Technologies
<blair@...>
Subversion training, consulting and support
http://www.orcaware.com/svn/
« Return to Thread: logging the Scala way and named varargs
| Free embeddable forum powered by Nabble | Forum Help |