Loggingtools in Scala
UPDATE: As John pointed out in the comments the trait did not really work as expected. I updated it with the code I actually have in my project. How I ended up posting a different thing on my blog I don’t know but it sort of has to be me :). This code is tested with slf4j-api-1.5.0. I think some newer version makes it possible to do this without the temporary objects involved in the form of arrays. I will look into that later.
My pet-project is becoming more and more Scalafied and I’m starting to wonder why I ever thought it was important that I should be able to use it from java-applications. Given my detachment from Java some mental barriers are falling and I am adding new strategies to my active toolbox. Today I created some simple traits that I thought would be worth exploring in a blog.
Here we go, logging with slf4j is something I’ve done a lot. I found myself sprinkling a lot of this around in my code:
import org.slf4j.{Logger, LoggerFactory}
...
class SomeClass {
private val log = LoggerFactory.getLogger(getClass)
def aMethodThatLogs {
log.debug("This is a value: {}", 4711)
}
}
Nothing new (unless you never saw slf4j before in which case you should check it out now wether you program in Scala or Java. The code so far is not dependent on scala other than syntax-wise.)
What I keep forgetting about
Scala has traits, it’s easy to forget that traits are more than just interfaces. Over the years I’ve gotten pretty used to not being able to add any generic functionality other than via composition or inheritance.
Thinking out of the java-box I created this little trait:
import org.slf4j.{Logger, LoggerFactory}
trait Log {
private val log = LoggerFactory.getLogger(getClass)
def trace(message:String, values:Any*) =
log.trace(message, values.map(_.asInstanceOf[Object]).toArray)
def trace(message:String, error:Throwable) = log.trace(message, error)
def trace(message:String, error:Throwable, values:Any*) =
log.trace(message, error, values.map(_.asInstanceOf[Object]).toArray)
def debug(message:String, values:Any*) =
log.debug(message, values.map(_.asInstanceOf[Object]).toArray)
def debug(message:String, error:Throwable) = log.debug(message, error)
def debug(message:String, error:Throwable, values:Any*) =
log.debug(message, error, values.map(_.asInstanceOf[Object]).toArray)
def info(message:String, values:Any*) =
log.info(message, values.map(_.asInstanceOf[Object]).toArray)
def info(message:String, error:Throwable) = log.info(message, error)
def info(message:String, error:Throwable, values:Any*) =
log.info(message, error, values.map(_.asInstanceOf[Object]).toArray)
def warn(message:String, values:Any*) =
log.warn(message, values.map(_.asInstanceOf[Object]).toArray)
def warn(message:String, error:Throwable) = log.warn(message, error)
def warn(message:String, error:Throwable, values:Any*) =
log.warn(message, error, values.map(_.asInstanceOf[Object]).toArray)
def error(message:String, values:Any*) =
log.error(message, values.map(_.asInstanceOf[Object]).toArray)
def error(message:String, error:Throwable) = log.error(message, error)
def error(message:String, error:Throwable, values:Any*) =
log.error(message, error, values.map(_.asInstanceOf[Object]).toArray)
}
Using it is now a matter of:
import johlrogge.Logging
...
class SomeClass extends Object with Logging {
def aMethodThatLogs {
debug("This is a value: {}", 4711)
}
}
It’s not a huge difference but I kind of like the with Logging and the lack of boilerplate code in the class-body.
I also like that I can drop the log. part of the logging.
Traits are on the menu
Of course this my wetted my appetite for traits. And it didn’t take long before an opportunity arose. How often have you written code like this in java:
long startTime = System.currentTimeMillis();
AValue value = doSomethingTimeConsuming(parameter);
log.debug("SomethingTimeConsuming took {}ms to complete", System.currentTimeMillis()-startTime);
return value;
I was about to repeat the process in Scala when I thought: function… pass by name… and then… TRAIT!
To make a long story short: Enter Timing:
trait Timing {
def time[T, R](f: => T, res:(T, Long) => R):R = {
val startTime = System.currentTimeMillis
res(f, System.currentTimeMillis - startTime)
}
}
How this beast came to be:
- I realized that the timing-code in the java-example could measure anything given that anything given that anything was executable. And thats what pass by name is for.
- I realized that sometimes you want to have the timed value, sometimes you want to log it as a side effect. So, a second pass by name function made sense. The res-function that takes the timing-value and does whatever it likes with it.
- You may want to return the timervalue, the result of the timed function, both or something completely different. So I made the result type generic and different from the result-type of the timed function.
How to use it:
import johlrogge.Logging
...
class SomeClass extends Object with Logging
with Timing {
def aMethodThatTimesAndReturns = {
time(timeConsumingMethod(4711),
debugMs("The timeConsumingMethod generated {} in {}ms", _:SomeValue, _))
}
def debugMs[T](message:String, result:T, spent:Long):T = {
debug(message, result, spent)
result
}
def timeConsumingMethod(interval:Int):SomeValue = {
Thread.sleep(interval);
new SomeValue
}
}
Pretty neat. Of course you can compose all kinds of pre-packaged res-methods. The point is that time becomes reusable and you don’t have to log. You could for instance update and return a data-set for a graph that you’re plotting somewhere else in your code. We have abstracted away timing.
Just so you know
If I would mind that anyone cut and pasted the code I wrote in this post and even make money from it (like thats going to happen) I wouldn’t post it on the net. I hope that the code is useful and/or inspires someone in some way. So use it however you want and have fun!
Do you dampen or amplify?
Today I rediscovered a thought I had months ago and forgot about. I was talking to a team-member about software development in general and frameworks and processes in particular. What I’m about to write is just a theory and a thought model that seems useful to me. If you are looking for hard facts then this post is not for you (sorry).
I have this idea that all practices we apply are somewhere on a scale from dampening to amplifying. Did I hear a WTF? I’ll try to explain…
More Scala and SWT
In general when you have a good idea you’re not alone. I started getting traffic from another blog. Dave Orme has developed an interesting framework: XScalaWT. According to the acknowledgements in his blog he found some of my ideas useful to his framework. I haven’t tried it yet, it looks similar to my DSL but his framework is much more complete and he solved the interaction part too. Check it out, it looks very promising!
Also, to my great surprise someone uploaded my source to github here. There is even a Maven pom now to build and run the thing.
I thought I’d share the links since the showed up in my statistics. Enjoy :)
Update: Randin pointed out that the link to xscalawt was broken so I changed the destination. Also Randin thought this link seemed interestong so I provide it here aswell.
Buy me a Beer :)
/* * The file is licenced under Revision 42 of the Beerware Licence. * <joakim.ohlrogge[at]agical.com> wrote this file. As long as you retain this * notice you can do whatever you want with this stuff. If we meet some day, * and you think this stuff is worth it, you can buy me a beer in return. * -- Joakim Ohlrogge */
Drying up widget creation
I continue to be amazed how Scala lets me keep my code DRY (if I care to do it the tools are there, I just need to look for them). One of the reasons that Scala allows this more than Java is that Scala supports functional programming. One thing that makes Scala interesting is that Scala blends Functional Programming and Object Oriented programming. This is often overwhelming but it really keeps the tools you need close at hand.
To start with I had to be torn kicking and screaming from my beloved object orientation. I was told I suffer from the Stockholm syndrome which was quite a hilarious way to put it. Especially since I live in Stockholm and was immediately comforted by the same person with the words “I suffer from it too, I still love C++”. So I thought maybe leaving my comfort zone is not so bad?
Yesterday it payed off and I experienced a kind of flow that was new to me in Scala. I thought I’d share that experience here step by step. Don’t expect to be blown away by my Scala-skills, If you want to be impressed in that way there are other blogs :) What follows is a real world example of things coming together into a moment of productiveness. I guess another real world example of applying Scala to a problem could not harm? Read the rest of this entry »
Making SWT shine with Scala
At Agile 2008 I was calmly coding together with Daniel Brolund in the open space area. We were interrupted by a guy that asked us if we did any coding in Ruby and if we did he will hold a lightning-talk about a framework he had put together to create SWT-gui:s using JRuby. Interestingly enough I had thought about how GUI-coding could probably be improved in a language such as Ruby so I reluctantly stopped what I was doing and watched the lightning talk. This was the first time I ever saw Glimmer and it totally blew me away!
Scala Nugget – Pattern matching and Lists
I was whining recently about how my scala-code is java in poor disguise. I started reading the scala by example pdf that also comes with the scala installation. I just read some interesting things about lists and pattern-matching that gave me an idea how to “scalafy” the following scjava-code:
Phasing over from java to scala, retrospect
I have written quite a few posts, 4 to be exact, about my experiences with phasing over from java to scala in my pet-project. I thought it is about time to take a look in the rear-view mirror now when some time has passed and I am more comfortable with Scala.
Phasing over from java to scala pt. 4 – Writing specs with specs
In the last part I figured out how to make Buildr run specs that are also runnable from Eclipse via JUnit. I started writing my first spec and we are now in the position to make it fail. What we are trying to acomplish is to make directories behave as nodes in a graph, at the moment, only the files show up as nodes.
The spec I wrote currently looks like this:
class PublishSiteGraphSpecTest extends JUnit4(PublishSiteGraphSpec)
object PublishSiteGraphSpec extends Specification {
"directories are nodes" in {
}
}
Let us fill in the details about what we actually mean when we say that directories should be nodes:
Buildr – Keeping up with the latest and greatest
In a previous post I ran into some problems with Buildr’s support for Specs in combination with JUnit. I googled a bit and came up with nothing so I did what all newbies do. Ask the pros on the mailinglist :) (I stayed away from “plz help” and “could you plz send me a patch”). I was (of course) suggested to try the latest from head and I felt an unpleasant resistance towards downloading archives, figuring out how to point gems to the latest version etc. All of those things are probably simple but I just want to develop some Scala code and did not look forward to it.
Well, boy was I worrying in vain!

Stumble It!