« Return to Thread: logging the Scala way and named varargs

Re: logging the Scala way and named varargs

by Ivan Todoroski-2 :: Rate this Message:

Reply to Author | View in Thread

Oh, sorry if I came across as feeling disdain for implicits as a
feature. To the contrary, implicits are one of the things I love most
about Scala. I just didn't feel it was appropriate to use implicits in
this particular case, that's all.

Maybe I'm too used to the logger.warn() pattern... it just looked to me
that a method call like warn() without any context could mean any number
of things, including popping up a message dialog in a GUI, whereas
logger.warn() is pretty self-describing without further ado.

You increase confusion ever so slightly, yet you don't really gain much.


On 18.06.2009 10:13, Ricky Clarkson wrote:

> You seem to consider implicit values as hoops; I do not.
>
> I would generally rather write warn("We assumed that x will never be
> greater than y, and that assumption is incorrect") than
> logger.warn("We assumed that..."), simply because the logger bit is
> irrelevant to understanding that code.
>
> Scala lets us do that without our code gaining bindings to global
> variables/state, which is an improvement over other languages.  Then
> you call it jumping through hoops, and start talking about "a time and
> a place.".  It's now, and here.
>
> I feel more strongly about your disdain for the feature than I do
> about actually typing logger.warn(s) though.
>
> 2009/6/18 Ivan Todoroski <grnch_lists@...>:
>> 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!
>>>>>
>>>>> 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)?
>>>> The point of slf4j's format string, i.e. "The foobar's value is {}", is
>>>> to
>>>> 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