平易なJava SE 6環境:
Logger l = Logger.getLogger("nameless");
l.setLevel(Level.ALL);
l.fine("somemessage");
Eclipseコンソールには何も表示されません。 l.info( "")以上は問題なく動作しますが、以下の項目はfine動作しないようです。何が間違っているのでしょうか? TIA。
ロガーレベルがALLに設定されていても、ConsoleHandler(ロガーのデフォルトハンドラー)のデフォルトレベルはINFOです。これはJava_HOME/jre/libのデフォルトのlogging.propertiesに由来します
すべてのハンドラーをループしてログレベルを設定する代わりに、コンソールハンドラーのレベルのみを設定することを好みます。
//get the top Logger
Logger topLogger = Java.util.logging.Logger.getLogger("");
// Handler for console (reuse it if it already exists)
Handler consoleHandler = null;
//see if there is already a console handler
for (Handler handler : topLogger.getHandlers()) {
if (handler instanceof ConsoleHandler) {
//found the console handler
consoleHandler = handler;
break;
}
}
if (consoleHandler == null) {
//there was no console handler found, create a new one
consoleHandler = new ConsoleHandler();
topLogger.addHandler(consoleHandler);
}
//set the console handler to fine:
consoleHandler.setLevel(Java.util.logging.Level.FINEST);
私の職場のある個人は、次のことがうまくいくことを発見しました。
_public class Foo {
private final static Logger logger = Logger.getLogger(Foo.class.getName());
public static final void main(String[] args) {
ConsoleHandler ch = new ConsoleHandler();
ch.setLevel(Level.FINEST);
Foo.logger.addHandler(ch);
Foo.logger.setLevel(Level.FINEST);
Foo.logger.finest("test");
}
}
_
ルートまたはハンドラーを最高の(排他的に)設定しただけでは機能しませんでした。両方をFINEST
に設定すると動作します。彼の説明は:
ロガーとそのハンドラーの両方にログレベルがあります…フィルタリングの順序はロガー、次にハンドラーです。つまり、ログメッセージがロガーフィルターを最初に通過するかどうかを確認し、次にフィルタリングのためにメッセージを個々のハンドラーに送信します。
彼はさらに、次の例を使用して説明しました。
_Logger myLogger
_のレベルはFINEST
であり、単一の_ConsoleHandler myHandler
_はINFO
のレベルです
myLogger.fine("foo")
àメッセージはロガーのフィルターを通過しますが、ハンドラーのフィルターによって停止されます...何も出力されません。
myLogger.info("foo")
àは両方のフィルターを通過し、foo
が出力されます。
今…
_Logger myLogger
_のレベルはINFO
であり、単一の_ConsoleHandler myHandler
_はFINEST
のレベルです
myLogger.fine("foo")
àメッセージはロガーのフィルターによって停止され、ハンドラーに送信されることはありません...何も出力されません。
myLogger.info("foo")
àは両方のフィルターを通過し、foo
が出力されます。
今…
_Logger myLogger
_のレベルはFINEST
であり、単一の_ConsoleHandler myHandler
_はFINEST
のレベルです
myLogger.fine("foo")
àは両方のフィルターを通過し、「foo
」が出力されます。
myLogger.info("foo")
àは両方のフィルターを通過し、foo
が出力されます。
他のユーザーは、なぜそれが起こったのかについて適切な回答を既に与えています(ConsoleHandlerには個別のレベル変数があります)。アプリケーションロガーのレベルを再利用して、親階層にコピーします。また、実行時にいつでもレベルを簡単に更新する方法を提供します。
// Set same level all loggers and handlers up to the parent level
// OFF,SEVERE,WARNING,INFO,CONFIG,FINE,FINER,FINEST,ALL
Logger logger = Logger.getLogger(this.getClass().getPackage().getName());
//Level level = Level.parse("FINEST");
Level level = logger.getLevel();
Logger tempLogger = logger;
while(tempLogger != null) {
tempLogger.setLevel(level);
for(Handler handler : tempLogger.getHandlers())
handler.setLevel(level);
tempLogger = tempLogger.getParent();
}
ロガーのハンドラーとロガー自体の両方でログレベルを設定する必要があります。ロギングは、2つのレベルの「最も粗い」レベルでのみ実行されます。ジョブを実行するロギングクラスを次に示します。
import Java.io.PrintWriter;
import Java.io.StringWriter;
import Java.time.Instant;
import Java.time.ZoneId;
import Java.time.ZonedDateTime;
import Java.time.format.DateTimeFormatter;
import Java.util.logging.ConsoleHandler;
import Java.util.logging.Formatter;
import Java.util.logging.Handler;
import Java.util.logging.Level;
import Java.util.logging.LogRecord;
import Java.util.logging.Logger;
public class Log {
private static final Logger logger = Logger.getGlobal();
private static Level logLevel = Level.INFO;
static {
// Remove all the default handlers (usually just one console handler)
Logger rootLogger = Logger.getLogger("");
Handler[] rootHandlers = rootLogger.getHandlers();
for (Handler handler : rootHandlers) {
rootLogger.removeHandler(handler);
}
// Add our own handler
ConsoleHandler handler = new ConsoleHandler();
handler.setLevel(logLevel);
handler.setFormatter(new LogFormatter());
logger.addHandler(handler);
logger.setLevel(logLevel);
}
public static class LogFormatter extends Formatter {
@Override
public String format(LogRecord record) {
String stackTrace = "";
Throwable thrown = record.getThrown();
if (thrown != null) {
StringWriter stacktraceWriter = new StringWriter();
try (PrintWriter writer = new PrintWriter(stacktraceWriter)) {
thrown.printStackTrace(writer);
}
stackTrace = stacktraceWriter.toString();
}
return ZonedDateTime.ofInstant(Instant.ofEpochMilli(record.getMillis()), ZoneId.of("UTC")).format(DateTimeFormatter.ISO_ZONED_DATE_TIME) + "\t" + record.getLevel()
+ "\t" + record.getMessage() + "\n" + stackTrace;
}
}
private static final String classname = Log.class.getName();
private static String callerRef() {
StackTraceElement[] stackTraceElements = Thread.currentThread().getStackTrace();
if (stackTraceElements.length < 4) {
return "";
} else {
int i = 1;
for (; i < stackTraceElements.length; i++) {
if (stackTraceElements[i].getClassName().equals(classname)) {
break;
}
}
for (; i < stackTraceElements.length; i++) {
if (!stackTraceElements[i].getClassName().equals(classname)) {
break;
}
}
if (i < stackTraceElements.length) {
return stackTraceElements[i].toString();
} else {
return "[in unknown method]";
}
}
}
public static void setLogLevel(Level newLogLevel) {
logLevel = newLogLevel;
for (Handler handler : logger.getHandlers()) {
handler.setLevel(newLogLevel);
}
Log.logger.setLevel(newLogLevel);
}
public static int getLevelNum() {
return logLevel.intValue();
}
public static int getLevelNum(Level level) {
return level.intValue();
}
public static void fine(String msg) {
logger.log(Level.FINE, msg);
}
public static void info(String msg) {
logger.log(Level.INFO, msg);
}
public static void warning(String msg) {
logger.log(Level.WARNING, msg + "\t " + callerRef());
}
public static void error(String msg) {
logger.log(Level.SEVERE, msg + "\t " + callerRef());
}
public static void exception(String msg, Throwable cause) {
logger.log(Level.SEVERE, msg + "\t " + callerRef(), cause);
}
}
private final static Logger LOGGER = Logger.getLogger(WoTServer.class.getName());
for(Handler h : LOGGER.getParent().getHandlers()){
if(h instanceof ConsoleHandler){
h.setLevel(Level.ALL);
}
}