日志系统可以看作时System.out.println的替代品,而且可以控制日志的输出目的地,输出的格式,可以更方便的记录程序的运行情况。
ELK
ELK 是软件集合 Elasticsearch、 Logstash、 Kibana 的简称,由这三个软件及其相关的组件可以打造大规模日志实时处理系统。
- Elasticsearch 是一个基于 Lucene 的、支持全文索引的分布式存储和索引引擎,主要负责将日志索引并存储起来,方便业务方检索查询。
- Logstash 是一个日志收集、过滤、转发的中间件,主要负责将各条业务线的各类日志统一收集、过滤后,转发给 Elasticsearch 进行下一步处理。
- Kibana 是一个可视化工具,主要负责查询 Elasticsearch 的数据并以可视化的方式展现给业务方,比如各类饼图、直方图、区域图等。
日志工具
JDK Logging
java标准库中内置了日志系统,可以使用java.util.logging
来使用。JDK的Logging定义了7个日志级别,从严重到普通:
- SEVERE
- WARNING
- INFO
- CONFIG
- FINE
- FINER
- FINEST
JDK的Logging的默认输出级别是INFO,因此,INFO级别以下的日志,不会被打印出来。配置文件需在启动JVM时加参数来指定-Djava.util.logging.config.file=<config-file-name>
。
import java.util.logging.Logger;
public class JdkLogging {
public static void main(String[] args) {
Logger logger = Logger.getGlobal();
logger.info("start process...");
logger.warning("memory is running out...");
logger.fine("ignored.");
logger.severe("process will be terminated...");
}
}
Log4j
log4j分别分为3个组件,分别为Logger(控制日志输出的级别),Appender(输出日志的目的地),Layouts(日志输出的形式),这3个组件都是由配置文件来进行控制的。log4j采用synchronized锁来并发输出日志,在日志较多的情况下可能会影响程序性能。
log4j会默认寻找log4j.properties作为当前目录下的配置文件,实例如下:
log4j.rootLogger=ERROR,stdout
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss,SSS} [%p] %c{1}(%L) - %m%n
log4j.appender.file=org.apache.log4j.DailyRollingFileAppender
log4j.appender.file.append=true
log4j.appender.file.File=/usr/local/web/log/logs
log4j.appender.file.DatePattern='.'yyyy-MM-dd
log4j.appender.file.layout=org.apache.log4j.PatternLayout
log4j.appender.file.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss,SSS} [%p] %c{1}(%L) - %m%n
log4j.logger.org.hibernate=DEBUG,stdout
log4j.logger.com.ibatis=DEBUG,stdout
log4j.logger.java.sql.Connection=DEBUG
log4j.logger.java.sql.Statement=DEBUG
log4j.logger.java.sql.PreparedStatement=DEBUG
Logger
负责产生日志,能够对日志进行筛选,控制什么样的日志可以被输出,什么样的日志应该被忽略,logger输出的日志类型分为以下级别,由低到高分别为
- ALL 所有日志
- DEBUG
- INFO
- WARN
- ERROR
- FATAL
- OFF 关闭日志
当定义logger组件输出级别为INFO时,比此级别低的信息(也就是DEBUG/ALL级别)将不会输出。用户可以定义多个Logger组件,每个Logger组件都有唯一的名字,logger组件之间有彼此的隶属关系。最高层次的Logger组件是:org.apache.log4j.Logger类中。
import org.apache.log4j.Logger;
import org.apache.log4j.Level;
public class Test {
private static final Logger logger = Logger.getLogger(Test.class);
logger.setLevel(Level.INFO); //设置logger的级别。通常不在程序中设置logger的级别。一般在配置文件中设置。
logger.info("infoTest");/
}
Appenders
在Log4j中,日志信息通过Appender组件输出到目的地,如控制台(Console)、文件(Files)、根据天数或者文件大小产生新的文件、以流的形式发送到其它地方等等。一个Appender实例就代表了一个目的地。一个记录器(Logger)可以拥有多个Appender
- ConsoleAppender 将日志输出到控制台
- FileAppender 将日志输出到文件中
- DailyRollingFileAppender 将日志输出到一个日志文件,并且每天输出到一个新的文件
- RollingFileAppender 将日志信息输出到一个日志文件,并且指定文件的尺寸,当文件大 小达到指定尺寸时,会自动把文件改名,同时产生一个新的文件
- JDBCAppender 把日志信息保存到数据库中
Layouts
Layouts提供了四种日志输出样式,如根据HTML样式、自由指定样式、包含日志级别与信息的样式和包含日志时间、线程、类别等信息的样式等等。Layout组件负责格式化输出日志信息,一个Appender只能有一个Layout组件。
Logback
logback的使用方式与log4j很相似,但是效率要比log4j高,相当于log4j的改进版。spring-boot默认使用了logback+Slf4J。
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-core</artifactId>
<version>1.2.3</version>
</dependency>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<version>1.2.3</version>
</dependency>
Commons Logging
Commons Logging是一个第三方日志库,它是由Apache创建的日志模块。它可以挂接不同的日志系统,并通过配置文件指定挂接的日志系统。默认情况下,Commons Loggin自动搜索并使用Log4j,如果没有找到Log4j,再搜索stl4j,如果都没有则使用JDK Logging。也就是说Commons Logging操作日志的API,并不负责日志系统的实现。
使用Commons Logging只需要和两个类打交道,并且只有两步:
- 通过
LogFactory
获取Log
类的实例; - 使用
Log
实例的方法打日志。 ```java import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory;
public class CommonsLogging { public static void main(String[] args) { Log log = LogFactory.getLog(CommonsLogging.class); log.info(“start…”); log.warn(“end.”); } }
<a name="sTORz"></a>
## SLF4J
Slf4j的全称是Simple Loging Facade For Java,类似Commons Logging提供日志输出的统一接口,并不是一个具体的日志实现方案。Slf4j有默认五种日志级别:
- trace
- Debug
- info
- warn
- error
Slf4j打印日志使用了{}占位符,这样就不会有字符串拼接操作,节省了内存,也提高了时间效率,同时编码更加方便。
```java
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class Slf4JLogging {
private static Logger log = LoggerFactory.getLogger(Slf4JLogging.class);
public static void main(String[] args) {
log.info("Hello {}!", "World");
log.warn("end.");
}
}
**