the following patch has been also published on the issue tracker under Issue 829.But I would like to present the patch here in more detail for your feedback.

There are already some issues with similar patches (561, 625 and 724), why another one?

Well, first of all none of these patches have been accepted or even commented on. But as PMS becomes more popular on embedded systems, which basically run forever causing debug.log to also grow infinitively, there is a definite need for some more advanced logging.

Some highlights of my patch:

It is based on the SLF4J API and the Logback implementation.SLF4J/Logback is the (unofficial) successor to Log4j, which is currently not maintained anymore. Logback is actively developed (by the original Log4j developer) and has some much better 'Appenders' for rolling log files.I have chosen this Framework because it could do daily logfile rollovers without writing any additional code.

The patch does allow for a user modifiable configuration file. If the file 'logback.xml' exists in the PMS application directory, then it will be used instead of the build-in default config file.Users running headless can optionally use a file called 'logback.headless.xml'

With the default settings the logging output is exactly the same as before, including the endless growing debug.log in the same format. I gather that this is enough for most casual users who run and stop PMS with a GUI on Windows. But changing just two lines in logback.xml will change this to max 5x10MB.

Like Issue 625, the impact on PMS has been kept to a minimum. Only PMS.java and the build scripts are changed. All the advanced stuff is done in a few new classes under net.pms.logging and in the logback.xml file.

The patch has been tested with Windows and Linux (it is currently running on my NAS)

The patch requires the files

slf4j-api-1.6.x.jar

logback-core-0.9.xx.jar

logback-classic-0.9.xx.jar(tested with x=1 and xx=24)

to be present in lib directory. If you are using Eclipse then add all three jar files to the Build Path.

Here are the single pieces of the patch in detail for your review. For easier reading I have included all new files as is, not as patches and also I have abbreviated the copyright / license comments.Download the full patch from Issue 829 if you want to integrate logging capabilites in your codebase.

private String uuid;@@ -1166,7 +1095,13 @@ if (System.getProperty("noconsole") == null) //$NON-NLS-1$ System.setProperty("console", "true"); //$NON-NLS-1$ //$NON-NLS-2$ }+ configuration = new PmsConfiguration();++ // Load the (optional) logback config file. This has to be called after 'new PmsConfiguration'+ // as the logging starts immediately and some filters need the PmsConfiguration.+ LoggingConfigFileLoader.load(); + PMS.get(); try { // let's allow us time to show up serious errors in the GUI before quitting

In PMS.java the major changes are that the calls to the static methods debug(), info(), and minimal() now call a SLF4J logger. Other than that all code for the debugging output has been deleted. The only other addition is a call to LoggingConfigFileLoader.load(), which is a new class located in net.pms.logging.

This class will configure the logback logger from the 'logback.xml' config file if it exists. I thought about using a user supplied filename, but I think this is sufficient.

/** * Loads the (optional) Logback configuration file. * * It loads the file {@link #DEFAULT_CONFIGFILENAME} from the current * directory and (re-)initializes Logback with this file. If running * headless (<code>System.Property("console")</code> set), then the * alternative config file {@link #HEADLESS_CONFIGFILENAME} is tried first. * * If no config file can be found in the CWD, then nothing is loaded and * Logback will use the logback.xml file on the classpath as a default. If * this doesn't exist then a basic console appender is used as fallback. * * <strong>Note:</strong> Any error messages generated while parsing the * config file are dumped only to <code>stdout</code>. */ public static void load() {

// Note: Do not use any logging method in this method! // Any logging would cause PMS.get() to be called from the // FrameAppender, which in turn would start the PMS instance, which // would cause further log messages. This will lead to either lost // log messages or Deadlocks! // Any status output needs to go to the console.

/** * Logback PropertyDefiner to set the path for the <code>debug.log</code> file. * <p> * If the current working directory is writable it returns an empty string. If * not then the path to the system temp directory is returned. * </p> * <p> * This is equivalent to the old behavior of PMS. * </p> * * @see System.getProperty("java.io.tmpdir"); * @author thomas@innot.de * */public class DebugLogPathDefiner extends PropertyDefinerBase {

// Return path to temp folder, which should be writeable return System.getProperty("java.io.tmpdir"); }

}

net.pms.logging.FrameAppender is a special 'Appender' that will send all received logging messages to the PMS GUI (if it is open). Note that this appender is configured in 'logback.xml' to behave exactly as today, even with the same output format, but this could be easily changed if required, even by the user.

if (frame == null) { // TODO: somehow ensure that PMS.get() does not get called before // PMS has been instantiated. Otherwise PMS will be instantiated by // this call and any log messages generated during PMS startup will // be ignored. // Currently the PMS API does not have a method to check if it // has been instantiated.

/** * @return The encoder associated with this appender, or <code>null</code> * if no encoder has been set. */ public Encoder<E> getEncoder() { return encoder; }

/** * Set the logback Encoder for the appender. * * Needs to be called (via the <encoder class="..."> element in the * logback.xml config file) before the appender can be started. * * @param */ public void setEncoder(Encoder<E> encoder) { this.encoder = encoder; }}

The FrameAppender is used in conjunction with the PMSThresholdFilter. This class is basically just for being 100% compatible with the current behaviour of having an PMS.conf entry 'level=x' with x=[0..2] to limit the logging output on the GUI. I don't know if anyone has ever used this entry (it is not settable from the GUI), but hey -- it's still supported.On the other hand, together with some GUI code this class could be used to set the GUI logging level from the GUI itself.

/** * Special Logback Filter that filters according to the level set in the * PmsConfiguration. * * The threshold level is taken from {@link PmsConfiguration#getLoggingLevel()}, * and is an integer between 0 and 3. These levels are used historically be PMS * and have the following mappings: * * <table border="1"> * <tr><th>value</th><th>PMS</th><th>SLF4J</th></tr> * <tr><td>0</td><td>DEBUG</td><td>TRACE</td></tr> * <tr><td>1</td><td>INFO</td><td>DEBUG</td></tr> * <tr><td>2</td><td>TRACE</td><td>INFO</td></tr> * <tr><td>3</td><td>--</td><td>OFF</td></tr> * </table> * All logging events below the threshold are denied, all others are accepted. * * @author thomas@innot.de * */public class PMSThresholdFilter extends Filter<ILoggingEvent> {

// The old PMS logging levels. // Only used to convert from the old levels that might be used in some // pms.conf files to the SLF4J levels. private static final int PMS_DEBUG = 0; private static final int PMS_INFO = 1; private static final int PMS_MINIMAL = 2;

To show how powerful logback is, I included a second logback configuration file. This is targeted at users like me, who run PMS as a real server without any GUI. With this config file nothing goes to the console and the debug.log file is rolled over daily at midnight, while keeping the logs of the last 7 days.The patched PMS will use this file automatically when running in headless mode.

The final three files contain just housekeeping items for the build files. Basically its just the addition of 'logback.xml' to the generated pms.jar. As this copy is on the classpath logback will use it automatically as a default. The same file and its headless variant are again included in the distribution package as a template for user edits.