Java自带的log工具。
Table of Contents
入门
打印信息:
import java.util.logging.Logger;
public class MyClass {
private static final Logger LOGGER = Logger.getLogger(MyClass.class.getName());
public static void main(String[] args) {
System.out.println("main method starts");
LOGGER.info("in MyClass");
}
}
JUL的workflow
- Logger
A named entity to which user application sends messages. - Handler
A specific handler is typically tied to a specific logging destination. A destination is where final formatted messages are sent. A handler can apply any additional logic, e.g. to improve performance.
Examples: ConsoleHandler, FileHandler, SocketHandler, user defined ones. - Level
Used by Logger/Handler. To discard messages if the Level of a given message is less than the Level associated with the Logger/Handler. - Filter
Used by Logger/Handler. It can filter message which cannot be filtered based on Levels. A dynamic/programmatic way to filter messages. - Formatter
To display messages in a specific format.
Examples: SimpleFormatter, XMLFormatter or user defined ones - Resource Bundle
A Logger may have a ResourceBundle associated with it. It is used to map raw message strings with localized message strings.
Logger的层次结构:
root Logger(“”)
Logger1 > “com.logicbig”
Logger2 > “com.logicbig.MyClass2” > parent namespace= “com.logicbig”
Logger3 > “com.logicbig.MyClass3” > parent namespace= “com.logicbig”
推荐使用带有包名信息的类名作为Logger的名字。
配置日志的属性:
- 用JVM属性指定Config class:
java.util.logging.config.class=com.logicbig.example.MyConfigClass
Java会在启动时载入MyConfigClass。此类的构造函数可以使用下面的方法初始化日志属性:
LogManager.getLogManager().readConfiguration(InputStream);
在这个用于初始化日志属性的类里,也可以设置各种logger:
Logger mainLogger = Logger.getLogger("com.logicbig.example");
mainLogger.setLevel(Level.FINEST);
mainLogger.addHandler(....);
....
- 用JVM属性指定配置文件:
java.util.logging.config.file=D:\myApp\logging.properties
。 - 默认的日志属性文件(
C:\java\jdk1.8.0_111\jre\lib\logging.properties
):
############################################################
# Default Logging Configuration File
#
# You can use a different file by specifying a filename
# with the java.util.logging.config.file system property.
# For example java -Djava.util.logging.config.file=myfile
############################################################
############################################################
# Global properties
############################################################
# "handlers" specifies a comma separated list of log Handler
# classes. These handlers will be installed during VM startup.
# Note that these classes must be on the system classpath.
# By default we only configure a ConsoleHandler, which will only
# show messages at the INFO and above levels.
handlers= java.util.logging.ConsoleHandler
# To also add the FileHandler, use the following line instead.
#handlers= java.util.logging.FileHandler, java.util.logging.ConsoleHandler
# Default global logging level.
# This specifies which kinds of events are logged across
# all loggers. For any given facility this global level
# can be overriden by a facility specific level
# Note that the ConsoleHandler also has a separate level
# setting to limit messages printed to the console.
.level= INFO
############################################################
# Handler specific properties.
# Describes specific configuration info for Handlers.
############################################################
# default file output is in user's home directory.
java.util.logging.FileHandler.pattern = %h/java%u.log
java.util.logging.FileHandler.limit = 50000
java.util.logging.FileHandler.count = 1
java.util.logging.FileHandler.formatter = java.util.logging.XMLFormatter
# Limit the message that are printed on the console to INFO and above.
java.util.logging.ConsoleHandler.level = INFO
java.util.logging.ConsoleHandler.formatter = java.util.logging.SimpleFormatter
# Example to customize the SimpleFormatter output format
# to print one-line log message like this:
# <level>: <log message> [<date/time>]
#
# java.util.logging.SimpleFormatter.format=%4$s: %5$s [%1$tc]%n
############################################################
# Facility specific properties.
# Provides extra control for each logger.
############################################################
# For example, set the com.xyz.foo logger to only log SEVERE
# messages:
com.xyz.foo.level = SEVERE
在程序中配置日志属性的几种方法
按照绝对路径读取配置文件
public class MyClass {
private static Logger LOGGER;
static {
System.setProperty("java.util.logging.config.file",
"d:\\test-app\\logging.properties");
//must initialize loggers after setting above property
LOGGER = Logger.getLogger(MyClass.class.getName());
}
public static void main(String[] args) {
System.out.println("-- main method starts --");
LOGGER.info("an info msg");
LOGGER.warning("a warning msg");
LOGGER.severe("a severe msg");
}
}
按照classpath读取配置文件
public class MyClass2 {
private static Logger LOGGER;
static {
String path = MyClass2.class.getClassLoader()
.getResource("logging.properties")
.getFile();
System.setProperty("java.util.logging.config.file", path);
LOGGER = Logger.getLogger(MyClass2.class.getName());
}
public static void main(String[] args) {
System.out.println("-- main method starts --");
LOGGER.info("an info msg");
LOGGER.warning("a warning msg");
LOGGER.severe("a severe msg");
}
}
使用LogManager#readConfiguration()读取配置文件
public class MyClass3 {
private static Logger LOGGER;
static {
InputStream stream = MyClass3.class.getClassLoader().
getResourceAsStream("logging.properties");
try {
LogManager.getLogManager().readConfiguration(stream);
} catch (IOException e) {
e.printStackTrace();
}
LOGGER = Logger.getLogger(MyClass3.class.getName());
}
public static void main(String[] args) {
System.out.println("-- main method starts --");
LOGGER.info("an info msg");
LOGGER.warning("a warning msg");
LOGGER.severe("a severe msg");
}
}
设置日志格式
在使用SimpleFormatter设置日志输出格式时,默认调用以下方法输出日志:String.format(format, date, source, logger, level, message, thrown);
定义自己的输出格式有以下几种方法:
使用logging.properties
src/main/resources/logging.propertis:
handlers= java.util.logging.ConsoleHandler
.level= INFO
java.util.logging.ConsoleHandler.level = INFO
java.util.logging.ConsoleHandler.formatter = java.util.logging.SimpleFormatter
java.util.logging.SimpleFormatter.format=[%1$tF %1$tT] [%4$-7s] %5$s %n
public class MyClass {
private static Logger LOGGER = null;
static {
InputStream stream = MyClass.class.getClassLoader().
getResourceAsStream("logging.properties");
try {
LogManager.getLogManager().readConfiguration(stream);
LOGGER= Logger.getLogger(MyClass.class.getName());
} catch (IOException e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
System.out.println("-- main method starts --");
LOGGER.info("in MyClass");
LOGGER.warning("a test warning");
}
}
使用system property
public class MyClass2 {
private static Logger LOGGER = null;
static {
System.setProperty("java.util.logging.SimpleFormatter.format",
"[%1$tF %1$tT] [%4$-7s] %5$s %n");
LOGGER = Logger.getLogger(MyClass2.class.getName());
}
public static void main(String[] args) {
System.out.println("-- main method starts --");
LOGGER.info("in MyClass2");
LOGGER.warning("a test warning");
}
}
通过编程指定
package com.logicbig.example;
import java.util.Date;
import java.util.logging.ConsoleHandler;
import java.util.logging.LogRecord;
import java.util.logging.Logger;
import java.util.logging.SimpleFormatter;
public class MyClass3 {
private static Logger LOGGER = null;
static {
Logger mainLogger = Logger.getLogger("com.logicbig");
mainLogger.setUseParentHandlers(false);
ConsoleHandler handler = new ConsoleHandler();
handler.setFormatter(new SimpleFormatter() {
private static final String format = "[%1$tF %1$tT] [%2$-7s] %3$s %n";
@Override
public synchronized String format(LogRecord lr) {
return String.format(format,
new Date(lr.getMillis()),
lr.getLevel().getLocalizedName(),
lr.getMessage()
);
}
});
mainLogger.addHandler(handler);
LOGGER = Logger.getLogger(MyClass3.class.getName());
}
public static void main(String[] args) {
System.out.println("-- main method starts --");
LOGGER.info("in MyClass3");
LOGGER.warning("a test warning");
}
}
设置日志级别
api:Logger#setLevel()和Handler#setLevel()
在程序中设置日志级别
public class LogLevelExample {
private static Logger log = Logger.getLogger(LogLevelExample.class.getName());
static {
System.setProperty("java.util.logging.SimpleFormatter.format",
"[%1$tF %1$tT %1$tL] [%4$-7s] %5$s %n");
}
public static void main(String[] args) throws Exception {
setLevel(Level.ALL);
Set<Level> levels = getAllLevels();
int i = 1;
for (Level level : levels) {
log.log(level, level.getName() + " - " + (i++));
}
}
public static void setLevel(Level targetLevel) {
Logger root = Logger.getLogger("");
root.setLevel(targetLevel);
for (Handler handler : root.getHandlers()) {
handler.setLevel(targetLevel);
}
System.out.println("level set: " + targetLevel.getName());
}
public static Set<Level> getAllLevels() throws IllegalAccessException {
Class<Level> levelClass = Level.class;
Set<Level> allLevels = new TreeSet<>(
Comparator.comparingInt(Level::intValue));
for (Field field : levelClass.getDeclaredFields()) {
if (field.getType() == Level.class) {
allLevels.add((Level) field.get(null));
}
}
return allLevels;
}
}
在配置文件中设置日志级别
src/main/resources/logging.properties
handlers= java.util.logging.ConsoleHandler
.level= FINEST
java.util.logging.ConsoleHandler.level = FINEST
java.util.logging.ConsoleHandler.formatter = java.util.logging.SimpleFormatter
java.util.logging.SimpleFormatter.format=[%1$tF %1$tT] [%4$-7s] %5$s %n
public class LogLevelPropertiesExample {
private static Logger log;
static {
String path = LogLevelPropertiesExample.class
.getClassLoader()
.getResource("logging.properties")
.getFile();
System.setProperty("java.util.logging.config.file", path);
log = Logger.getLogger(LogLevelPropertiesExample.class.getName());
}
public static void main(String[] args) throws Exception {
Set<Level> levels = getAllLevels();
int i = 1;
for (Level level : levels) {
log.log(level, level.getName() + " - " + (i++));
}
}
.............
}
Java Util Logging,自定义如何处理log信息
通过自定义一个Log Handler,可以由开发者自行决定如何处理来自logger的日志消息。
自定义handler
package com.logicbig.example;
import java.util.logging.Handler;
import java.util.logging.LogRecord;
public class MyLogHandler extends Handler {
@Override
public void publish(LogRecord record) {
StringBuilder sb = new StringBuilder();
sb.append(record.getMillis())
.append(" - ")
.append(record.getSourceClassName())
.append("#")
.append(record.getSourceMethodName())
.append(" - ")
.append(record.getMessage());
System.out.println(sb.toString());
}
@Override
public void flush() {
}
@Override
public void close() throws SecurityException {
}
}
生成日志消息
package com.logicbig.example;
import java.util.logging.Logger;
public class AppClass {
private static final Logger LOGGER = Logger.getLogger(AppClass.class.getName());
public void doSomething(){
LOGGER.info("in AppClass");
}
}
注册handler
package com.logicbig.example;
import java.util.logging.Handler;
import java.util.logging.LogManager;
import java.util.logging.Logger;
public class ExampleMain {
public static void main(String[] args) {
//reset() will remove all default handlers
LogManager.getLogManager().reset();
Logger rootLogger = LogManager.getLogManager().getLogger("");
rootLogger.addHandler(new MyLogHandler());
AppClass appClass = new AppClass();
appClass.doSomething();
rootLogger.info("some message");
}
}
近期评论