In a world where System.out.println() and printf() are still serious methods of debugging code, the idea that you could just have a class library FILTER YOUR DEBUG OUTPUT and do it with minimal fuss was just incredible. Even more attractive was the idea that I could write code and simply leave the debug statements in if I ever needed to debug the code again. I think all computer science departments should teach students to know, use and love a logging library and only use println as it's intended.
I used to only put debug statements in when I was trying to debug my code. Eventually I got smart, and started preemptively debugging my code. These days, as soon as I write a method, I add a logging statement saying "hey, I'm in the method now." I write out what data I'm going through in a loop. And I write out what my return status is.
Some people argue that this is what a debugger is for, but there are two things I don't like about debuggers -- they're big and they're slow. I'd rather write the debugging code myself than have to trawl through a GUI interface to find it.
But there are other advantages. It's pretty much impossible to turn a debugger on a live site. You can always turn on verbose debugging to figure out what's going on, and it's persistent. You don't have to remember the data flow afterwards, because it's written down. Moreover, log statements act as a useful sidenote to comments and variables. There's no doubt about what the important bits of the code are and the intermediate steps, because they're the bits you cared enough about to want written down in the event something went wrong.
The one annoying thing about logs was that I'd have to tail through them, and they weren't very easy to read. But I got used to that and never really thought about it.
Ganymede is a Log4J server that plugs into Eclipse. Log messages just pop up in Eclipse.

Together with the log4j plugin to Dynamo, I never have to even leave Eclipse. Funny how work just keeps getting easier.