I want this library I'm working on to have logging support, but Android and SE have their own ways of logging. In SE you can use System.out.println methods or the java.util.logging.Logger class. Android uses android.util.Log to log on logcat. At first I used reflection to check if android was usable, then reflectively call the log methods in Log.class; but that wasn't a good idea.
My solution is to have the developers using my library handle logs themselves. There will be a Handler interface they set and has an onLog method
public void onLog(int level, String tag, String msg);
The library will call the onLog method on the handlers in my custom Logger class. Is it a good idea to have developers handle the logs instead of the library itself? Seems to be the best solution so far and if I document it good then it should't be an issue.
I agree with you that logging should be delegated to clients, and your homegrown approach is indeed sensible.
IMO, the SLF4J facade would be ideal for your situation. Your library would include the slf4j-api jar and contain SLF4J logging statements. If clients wanted logging, they'd just drop in a logging backend (and an optional config file) into their application's classpath to capture/view your log statements.
The advantages to this approach are that it grants clients the most control with zero coding required to get logging; and that it allows the client to choose among many available backends.
I would use logback as the backend for J2SE apps and logback-android for Android.
You can try microlog
http://code.google.com/p/microlog4android/
It can help you use a consistent logging mechanism across android and java. If you use slf4j, it can be used as a wrapper both for microlog (in case of your android project) and log4j (for your java projects)
Related
I'am developing simple Java event library and I want to support more than one logging system.
I have an idea with using own class named LoggerBridge.
public void setLogger(LoggerBridge bridge){
}
public class LoggerBridge{
public void log(Level, String){}
...
}
But this solution is not practical at all, is there some other option how to achieve this result ?
Some bridge, which it supports all types of logging system ?
This is an age old problem and several logging facades were made to allow you to log things in for example libraries, without forcing the user to use the same logging framework you chose (or try to make multiple logging frameworks work nicely together).
One of the earliest ones was commons-logging which is considered outdated these days, but there are a lot of older libraries that use it. It can be bridged to your actual logging system (see below).
Newer ones include SLF4J. These should be used when you're writing a library, so you'd be programming to the SLF4J API instead of an actual logging implementation.
A logging bridge is when you have a library that uses for example log4J, but your other code is using let's say SLF4J with Logback (a quite common combination). The bridge "fakes" being the log4J library, when it actually just redirects the logging to your SLF4J+Logback combination.
I want to provide a client-library for wrapping rest-request to a server and log errors, so that a client can use it in his app and also see the logs. (There is also a question if i should just log the errors or rethrow it. When i use an asynchronized call (multithreaded) this might be quite tricky..)
I read that slf4j might help, because the client, who is using the library, can choose which logging framework he prefers.
Somethings puzzles me about this slf4j-thing. If he gets my library and i just provide, let's say the slf4j-api, errors will be thrown, cause the SLF4J bindings aren't included. The solution might be that he has to include the binding on his own, and the question is if he is willing to read the README for this crucial information.
If i include one "standard"-slf4j binding (e.g. the simple one), the app can't "override" this, because there is just one binding allowed on the classpath. It won't be flexible anymoe
So i am thinking to just use log4j and forget every other logging-framework. I may think to complicated on this subject, maybe someone might help me out on this?
You have to remember, your library does not set the wrapping application's classpath. The wrapping application will set a classpath that includes your library, the slf4j API library and the implementing library.
The wrapping application will take care of what slf4j implementation to use and setup all of the logging parameters. You just need to worry about logging your libraries events with the slf4j API. This is common practice, don't worry about the wrapping application.
By packaging log4j within your library, you are defeating the purpose of a logging facade. Doing so will not allow the user to pick the slf4j implementation.
I've using SLF4j as my logging framework, backed by log4j. My problem is that I am looking for a way to change the logging level for my logger at runtime.
I understand that slf4j does not permit this directly through its own API, and hence, I have to access the logging provider directly. Personally, I find this to be a huge deficiency in slf4j. So now my question is how can I determine programatically through slf4j which provider I am using? The biggest purpose of using slf4j is that you become provider agnostic - you can easily switch between your favourite logging system without having to recode anything. But now, if I have to make direct calls to log4j, I am losing that ability.
At the very least, I would like to be able to determine if I am using log4j as the provider and if so, then allow the user to switch log levels.
If I do LoggerFactory.getLogger(Logger.ROOT_LOGGER_NAME), the result is an instance of org.slf4j.impl.Log4jLoggerAdapter and not even org.apache.log4j.Logger (as I would have hoped/expected).
Is there any way to find this out?
Thanks,
Eric
SLF4J is designed as an abstraction for libraries, not applications (of course, you can and should still use SLF4J in your own app's logging calls, for consistency). In your own app, you choose the underlying logger framework, so it's fine to access the log4j API in the logging-config-specific parts.
No way should a library be mucking about with changing the logging config, IMHO, so it's not appropriate for it to be on the SLF4J API.
If I've to distribute a certain framework like a customized validation framework which can be used in many projects, how do I handle logging within this framework so that it uses the same logging method as the project in which it is being used? i.e I've written a logger interface with the usual debug,warn,info... methods and the implementation of this interface can implement those methods using log4j or any other logging methods. If I distribute this as a jar, how can different projects use this jar with their logging framework?
I would strongly suggest that instead of writing yet another logging framework you recode your application to use the SLF4J logging API instead. All the work of interfacing to other logging implementations have been done, and is well known in the industry.
An added benefit is that you get {}-placeholders, which allow you to just do
log.debug("a={}, b={}", a, b);
and the a.toString() and b.toString() are only called when the string will actually be logged. This allows for a lot of log statements which will not actually be executed unless you need them to run in a debug setting.
There are some libraries that provide an abstraction layer over log4j, java.util.logging etc. They act as the 'interface' and then the person using your project can use the implementation of their choosing. Have a look at Apache Commons Logging and SLF4J.
I am developing a java application for which i have to use a logging mechanism. And now i am confused to choose either java libraries logger or to go for Log4j logger.
So i want to know when i can go for java logger
and when i can go for log4j logger.
I'd suggest you go with SLF4J instead to decouple your application from specific logging frameworks. It has adapters for various popular logging frameworks such as Jakarta Logging, JDK1.4 logging, log4j etc. making it a good abstraction for logging needs.
Logger class was not part of jdk earlier on, so several library implementations sprung up. The Log4j library has one of the most comprehensive set of logging utilities (Formatters, Appenders etc). However, for most developers this would be an overkill and the simple java.util.Logger would suffice.
I personally use a custom wrapper over my logger implementation. This enables me to define custom calls to carry out functional logging/auditing.
There are the Apache Commoms Logging project and SLF4J, either of which abstracts the underlying logging library.
In practice I tend to use Log4J over the built in logging classes. Mainly because Log4J can be configured per web-app in an application server, whereas JDK logging is configured per JVM.
The approach I would currently recommend is to use SLF4J as the logging API. You can then pick your logging framework depending on your needs as you discover them.
I did a writeup on what I consider to be best practice in getting started with SLF4J and a simple "log to System.out" which is currently placed at. http://runjva.appspot.com/logging101/index.html
Hopefully it is helpful.
I find Log4j more flexible when it comes to tweaking the logging cfg without re-compiling code in production environment.