The logging system
Starting with qooxdoo 0.6 a new logging API was introduced to qooxdoo. The logging API allows for a flexible and powerful definition of what is logged and where it is logged while trying to keep usage as simple as possible.
Writing log messages
Every qooxdoo object has four logging methods debug(), info(), warn() and error(). Each method takes two parameters: The log message (String) and an error object (Error). The latter is optional.
The name of the method defines the log level your log message will get. If you want to log a message that is interesting for debugging, then use debug(). If you want to log a general information, use info(). If you want to log a warning, use warn(). Errors should be logged with error(). Have a look to the API documentation of the class qx.core.Object for more information.
So for writing a log message just call:
this.info("Hello world");
If you want to log an error, then you can pass a catched exception, too. The logging API will then show all available information about the exception. E.g. in Firefox a whole stack trace is shown.
try { ... } catch (ex) { this.error("Creating stuff failed", ex); }
Defining what is logged where
Before you can define what is to be logged and where, you have to understand the meaning of the base classes Logger, Appender and Filter.
Loggers
A Logger is responsible for the log messages of exactly one class. You get the logger of a class by calling myobject.getLogger().
Loggers build a hierarchy which is similar to the class/package hierarchy: The parent logger of a class is the logger of the package the class belongs to. The parent logger of a package is the logger of the parent package. You may retreive these parent loggers using the myobject.getLogger().getParentLogger() idiom. The top-most logger (the so-called “root logger”) is stored in the constant qx.log.Logger.ROOT_LOGGER.
Appenders
An Appender is an object that actually writes the log message somewhere. A WindowAppender for example shows log messages in an extra window (this is the default Appender). A DivAppender shows the messages in a div element somewhere in the page (it is used in the demos). You can define your own appenders, if you want to log messages somewhere else (on the server for instance).
A logger may have zero or more appenders.
Filters
A simple means to filter log messages is to adjust the log level on loggers and/or appenders. This is achieved using the setMinLevel method. Currently, there are 7 log levels available, all, debug, info, warn, error, fatal, off. The log levels are ordered and increasingly narrow, all being the lowest and most permissive and off the hightest and most restrictive log level. That is, specifying a log level will allow all messages of that level and above to pass, e.g. a log level of warn allows all messages of log level warn, error and fatal to pass. off is the highest level and does not allow any message to pass, i.e. it effectively turns off logging.
If you want more fine-grained control of what is being logged, a Filter object can be used to decide whether a log message should be logged or not. You can add filters to loggers or to appenders. A Filter object can implement arbitrary filter logic (e.g. based on the log message content) using the decide method. See the documentation for qx.log.Filter for more details.
Using these tools you can achieve that the debug messages of some classes are logged and from other classes are not, simply by adding a filter to the logger of a class or a package.
Or you can specify that all information messages are shown to the user, while errors are logged to the server, simply by adding appropriate filters to your WindowAppender or ServerAppender, respectively.
How all this works together
When you tell a logger to log some message, then it asks its filter whether the message should be logged. If it has no filter, then the filter of the parent logger is used and so on.
When the filter does not reject the log message, it is passed to the logger’s appenders. And again: If the logger has no appender, then the appenders of the parent logger are used and so on. For any appender found filters are applied if the appender has defined filters.
Some examples
By default all log messages are logged to a WindowAppender.
If you want to turn off logging except for errors in your built script, you can put this in your main html page:
// // Set up logging as appropriate // if (qx.IS_SOURCE) // only supplied for in source version { qx.log.Logger.ROOT_LOGGER.setMinLevel(qx.log.Logger.LEVEL_DEBUG); } else { qx.log.Logger.ROOT_LOGGER.setMinLevel(qx.log.Logger.LEVEL_ERROR); };
If you want all log messages to be logged into a div element having the id logging-div somewhere in your page, add the following code at the beginning of your application:
// First remove the existing WindowAppender qx.log.Logger.ROOT_LOGGER.removeAllAppenders(); // Then add the DivAppender var divAppender = new qx.log.DivAppender("logging-div"); qx.log.Logger.ROOT_LOGGER.addAppender(divAppender);
If you only want warnings and errors to be logged, do the following:
qx.log.Logger.ROOT_LOGGER.setMinLevel(qx.log.Logger.LEVEL_WARN);
If you want to log debug messages of the class qx.blubb.MyClass, do this:
var logger = qx.blubb.MyClass.getLogger(); logger.setMinLevel(qx.log.Logger.LEVEL_DEBUG);
If you want to log debug messages of all classes in the package qx.ui.table, do this:
var logger = qx.log.Logger.getClassLogger(qx.ui.table); logger.setMinLevel(qx.log.Logger.LEVEL_DEBUG);
If you have written your own appender and want all errors to be logged there, do the following:
// Create an instance of your appender var myAppender = new qx.bla.MyAppender(); // Add a filter to it that only allows error messages myAppender.setMinLevel(qx.log.Logger.LEVEL_ERROR); // Add your appender to the root logger qx.log.Logger.ROOT_LOGGER.addAppender(myAppender);
