Gili
Gili

Reputation: 90023

Android: How to change the default logging level?

According to the documentation there are only two ways to change the default logging level from INFO to lower levels (such as DEBUG):

  1. setprop log.tag.<YOUR_LOG_TAG> <LEVEL>, or
  2. log.tag.<YOUR_LOG_TAG>=<LEVEL> in /data/local.prop.

Is it possible to bundle the logging configuration within the application? I'm looking for the equivalent of logging.properties or logback.xml, configuration files that are bundled with the application and alter the logging behavior at load-time. The goal is to avoid manually configuring each device that the application will run on.

Upvotes: 8

Views: 10172

Answers (2)

Gili
Gili

Reputation: 90023

I ended up using logback-android. I will leave this question open a bit longer in case someone comes up with a better solution.

Upvotes: 3

Ishank Gupta
Ishank Gupta

Reputation: 223

You can use java logger also here with some customisations..

ConsoleLogHandler.java

package com.sony.evc.vis.system.util.logger;

import java.util.logging.Handler;
import java.util.logging.Level;
import java.util.logging.LogRecord;

import android.util.Log;

public class ConsoleLogHandler extends Handler
{

    @Override
    public void close()
    {}

    @Override
    public void flush()
    {}

    // filter logs and publish them
    @Override
    public void publish(LogRecord record)
    {
        String className = record.getLoggerName() + ": "
                + simplifyClassName(record.getSourceClassName());
        int threadID = record.getThreadID();
        String methodName = record.getSourceMethodName();
        String msg = record.getMessage();
        int level = record.getLevel().intValue();

        logMessage(className, threadID, methodName, msg, level, record.getThrown());
    }

    // simplify class name from full applied package name to simple class
    private String simplifyClassName(String sourceClassName)
    {
        String fullClassName[] = sourceClassName.split("\\.");
        return fullClassName[fullClassName.length - 1];
    }

    private void logMessage(String className, int threadID, String methodName, String msg,
            int level, Throwable throwable)
    {
        if (level == Level.FINE.intValue()) {
            Log.d(className, "ThreadID:" + threadID + "," + methodName + "()," + msg);
        }
        else if (level == Level.INFO.intValue()) {
            Log.i(className, "ThreadID:" + threadID + "," + methodName + "()," + msg);
        }
        else if (level == Level.WARNING.intValue()) {
            Log.w(className, "ThreadID:" + threadID + "," + methodName + "()," + msg, throwable);
        }
        else if (level == Level.SEVERE.intValue()) {
            Log.e(className, "ThreadID:" + threadID + "," + methodName + "()," + msg, throwable);
        }

    }

}

create class LoggerFactory.java

package com.sony.evc.vis.system.util.logger;

import java.util.logging.Handler;
import java.util.logging.Level;
import java.util.logging.Logger;

public class LoggerFactory {

    public static Logger Log;
    private static ConsoleLogHandler logHandler;
    // Global constants to give programmer choice to add if condition before
    // logging a code.
    public static boolean FINE;
    public static boolean INFO;
    public static boolean WARN;

    // initialise the logger
    public static void init(String version, String globalDebugLevel,
            String appDebugLevel) {

        Log = Logger.getLogger(version);

        // debug level settings
        Level debuglevel = LogLevel.setDebugLevel(globalDebugLevel,
                appDebugLevel);
        if (debuglevel.equals(Level.ALL) || debuglevel.equals(Level.FINE)
                || debuglevel.equals(Level.FINER)
                || debuglevel.equals(Level.FINEST)) {
            FINE = INFO = WARN = true;
        } else if (debuglevel.equals(Level.INFO)) {
            INFO = WARN = true;
        } else if (debuglevel.equals(Level.WARNING)) {
            WARN = true;
        }
        Log.setLevel(debuglevel);

        // logger send its msg to several handlers by default, we have to
        // disable that
        Log.setUseParentHandlers(false);

        // avoid recreation of handler in case activities onCreate() is called
        // again but logHandler is not
        // garbage collected
        if (logHandler == null)
            logHandler = new ConsoleLogHandler();

        // remove previously assigned handlers. This is very important and
        // failing to do so may result in
        // duplication of same logs
        for (Handler handler : Log.getHandlers())
            Log.removeHandler(handler);

        // set this loggers handler and make sure that only one instance is
        // associated with it
        Log.addHandler(logHandler);
    }
}

create enum LogLevel.java

package com.sony.evc.vis.system.util.logger;

import java.util.logging.Level;

public enum LogLevel {
    DEBUG, INFO, WARNING, ERROR, NO_LOG, DISABLE;
    /*
     * set log-debugLevel as per requirement. Global level is given preference
     * over app and service levels. If global level is disabled, other
     * levels are considered
     */
    public static Level setDebugLevel(String sGlobalDebugLevel,
            String sAppDebugLevel) {
        String strGlobalDebugLevel = sGlobalDebugLevel.trim().toUpperCase();
        String strAppDebugLevel = sAppDebugLevel.trim().toUpperCase();
        LogLevel globalDebugLevel = LogLevel.valueOf(strGlobalDebugLevel);
        LogLevel appDebugLevel = LogLevel.valueOf(strAppDebugLevel);
        LogLevel logLevel = globalDebugLevel == LogLevel.DISABLE ? appDebugLevel
                : globalDebugLevel;

        switch (logLevel) {
        case DEBUG:
            return Level.FINE;
        case INFO:
            return Level.INFO;
        case WARNING:
            return Level.WARNING;
        case ERROR:
            return Level.SEVERE;
        case NO_LOG:
            return Level.OFF;
        case DISABLE:
            return Level.OFF;
        default:
            return Level.INFO;
        }
    }
}

You will also need to update Strings.xml as

<!--
    :-Accepted values for global_debuglevel are: "debug", "info", "warning", "error"(in increasing order of priority),No_Log
      and Disable. 
    :-Setting any other value will set "info" level
    -->
    <string name="global_debuglevel">debug</string>

    <!--
    :-Accepted values for app_debuglevel are: "debug", "info", "warning", "error"(in increasing order of priority)
      and No_Log
    :-Setting any other value will set "info" level
    -->
    <string name="app_debuglevel">debug</string>

From the start of application just init the Logger as

    String service_version = getString(R.string.service_version);
    String global_debugLevel = getString(R.string.global_debuglevel);
    String service_debugLevel = getString(R.string.service_debuglevel);
    LoggerFactory.init(service_version, global_debugLevel,
            service_debugLevel);

For printing Logs write:

Log.info(" message ");
Log.fine(" message ");
Log.severe(" message ");
Log.warning(" message ");

Upvotes: 0

Related Questions