日志文件是用于记录系统操做事件的文件集合,可分为事件日志和消息日志。具备处理历史数据、诊断问题的追踪以及理解系统的活动等重要做用。java
在计算机中,日志文件是记录在操做系统或其余软件运行中发生的事件或在通讯软件的不一样用户之间的消息的文件。记录是保持日志的行为。在最简单的状况下,消息被写入单个日志文件。mysql
许多操做系统,软件框架和程序包括日志系统。普遍使用的日志记录标准是在因特网工程任务组(IETF)RFC5424中定义的syslog。 syslog标准使专用的标准化子系统可以生成,过滤,记录和分析日志消息。sql
软件开发中,咱们常常须要去调试程序,作一些信息,状态的输出便于咱们查询程序的运行情况。为了
让咱们可以更加灵活和方便的控制这些调试的信息,全部咱们须要专业的日志技术。java中寻找bug会
须要重现。调试也就是debug 能够在程序运行中暂停程序运行,能够查看程序在运行中的状况。日志主
要是为了更方便的去重现问题。数据库
系统日志是记录系统中硬件、软件和系统问题的信息,同时还能够监视系统中发生的事件。用户能够经过它来检查错误发生的缘由,或者寻找受到攻击时攻击者留下的痕迹。系统日志包括系统日志、应用程序日志和安全日志。apache
系统日志的价值
系统日志策略能够在故障刚刚发生时就向你发送警告信息,系统日志帮助你在最短的时间内发现问题。数组
系统日志是一种很是关键的组件,由于系统日志可让你充分了解本身的环境。这种系统日志信息对于决定故障的根本缘由或者缩小系统攻击范围来讲是很是关键的,由于系统日志可让你了解故障或者袭击发生以前的全部事件。为虚拟化环境制定一套良好的系统日志策略也是相当重要的,由于系统日志须要和许多不一样的外部组件进行关联。良好的系统日志能够防止你从错误的角度分析问题,避免浪费宝贵的排错时间。另一种缘由是借助于系统日志,管理员颇有可能会发现一些以前从未意识到的问题,在几乎全部刚刚部署系统日志的环境当中。安全
问题:服务器
由于软件系统发展到今天已经很复杂了,特别是服务器端软件,涉及到的知识,内容,问题太多。在某些方面使用别人成熟的框架,就至关于让别人帮你完成一些基础工做,你只须要集中精力完成系统的业务逻辑设计。并且框架通常是成熟,稳健的,他能够处理系统不少细节问题,好比,事务处理,安全性,数据流控制等问题。还有框架通常都通过不少人使用,因此结构很好,因此扩展性也很好,并且它是不断升级的,你能够直接享受别人升级代码带来的好处。网络
JUL(java util logging)、logback、log4j、log4j2
JCL(Jakarta Commons Logging)、slf4j( Simple Logging Facade for Java)架构
日志门面
JCL、slf4j
日志实现
JUL、logback、log4j、log4j2
JUL全称Java util Logging是java原生的日志框架,使用时不须要另外引用第三方类库,相对其余日志框架使用方便,学习简单,可以在小型应用中灵活使用。
总结一下就是:
用户使用Logger来进行日志记录,Logger持有若干个Handler,日志的输出操做是由Handler完成的。在Handler在输出日志前,会通过Filter的过滤,判断哪些日志级别过滤放行哪些拦截,Handler会将日志内容输出到指定位置(日志文件、控制台等)。Handler在输出日志时会使用Layout,将输出内容进行排版。
public class JULTest { @Test public void testQuick() throws Exception { // 1.建立日志记录器对象 Logger logger = Logger.getLogger("com.itheima.log.JULTest"); // 2.日志记录输出 logger.info("hello jul"); logger.log(Level.INFO, "info msg"); String name = "jack"; Integer age = 18; logger.log(Level.INFO, "用户信息:{0},{1}", new Object[]{name, age}); } }
jul中定义的日志级别
虽然咱们测试了7个日志级别可是默认只实现info以上的级别
@Test public void testLogLevel() throws Exception { // 1.获取日志对象 Logger logger = Logger.getLogger("com.itheima.log.QuickTest"); // 2.日志记录输出 logger.severe("severe"); logger.warning("warning"); logger.info("info"); logger.config("cofnig"); logger.fine("fine"); logger.finer("finer"); logger.finest("finest"); }
自定义日志级别配置
@Test public void testLogConfig() throws Exception { // 1.建立日志记录器对象 Logger logger = Logger.getLogger("com.itheima.log.JULTest"); // 1、自定义日志级别 // a.关闭系统默认配置 logger.setUseParentHandlers(false); // b.建立handler对象 ConsoleHandler consoleHandler = new ConsoleHandler(); // c.建立formatter对象 SimpleFormatter simpleFormatter = new SimpleFormatter(); // d.进行关联 consoleHandler.setFormatter(simpleFormatter); logger.addHandler(consoleHandler); // e.设置日志级别 logger.setLevel(Level.ALL); consoleHandler.setLevel(Level.ALL); // 2、输出到日志文件 FileHandler fileHandler = new FileHandler("d:/logs/jul.log"); fileHandler.setFormatter(simpleFormatter); logger.addHandler(fileHandler); // 2.日志记录输出 logger.severe("severe"); logger.warning("warning"); logger.info("info"); logger.config("config"); logger.fine("fine"); logger.finer("finer"); logger.finest("finest"); }
JUL中Logger之间存在父子关系,这种父子关系经过树状结构存储,JUL在初始化时会建立一个顶层RootLogger做为全部Logger父Logger,存储上做为树状结构的根节点。并父子关系经过路径来关联。
@Test public void testLogParent() throws Exception { // 日志记录器对象父子关系 Logger logger1 = Logger.getLogger("com.itheima.log"); Logger logger2 = Logger.getLogger("com.itheima"); System.out.println(logger1.getParent() == logger2); // 全部日志记录器对象的顶级父元素 class为java.util.logging.LogManager$RootLogger name为"" System.out.println("logger2 parent:" + logger2.getParent() + ",name:" + logger2.getParent().getName()); // 1、自定义日志级别 // a.关闭系统默认配置 logger2.setUseParentHandlers(false); // b.建立handler对象 ConsoleHandler consoleHandler = new ConsoleHandler(); // c.建立formatter对象 SimpleFormatter simpleFormatter = new SimpleFormatter(); // d.进行关联 consoleHandler.setFormatter(simpleFormatter); logger2.addHandler(consoleHandler); // e.设置日志级别 logger2.setLevel(Level.ALL); consoleHandler.setLevel(Level.ALL); // 测试日志记录器对象父子关系 logger1.severe("severe"); logger1.warning("warning"); logger1.info("info"); logger1.config("config"); logger1.fine("fine"); logger1.finer("finer"); logger1.finest("finest"); }
默认配置文件路径$JAVAHOME\jre\lib\logging.properties
@Test public void testProperties() throws Exception { // 读取自定义配置文件 InputStream in = JULTest.class.getClassLoader().getResourceAsStream("logging.properties"); // 获取日志管理器对象 LogManager logManager = LogManager.getLogManager(); // 经过日志管理器加载配置文件 logManager.readConfiguration(in); Logger logger = Logger.getLogger("com.itheima.log.JULTest"); logger.severe("severe"); logger.warning("warning"); logger.info("info"); logger.config("config"); logger.fine("fine"); logger.finer("finer"); logger.finest("finest"); }
配置文件:
## RootLogger使用的处理器(获取时设置) handlers= java.util.logging.ConsoleHandler # RootLogger日志等级 .level= INFO ## 自定义Logger com.itheima.handlers= java.util.logging.FileHandler # 自定义Logger日志等级 com.itheima.level= INFO # 忽略父日志设置 com.itheima.useParentHandlers=false ## 控制台处理器 # 输出日志级别 java.util.logging.ConsoleHandler.level = INFO # 输出日志格式 java.util.logging.ConsoleHandler.formatter = java.util.logging.SimpleFormatter ## 文件处理器 # 输出日志级别 java.util.logging.FileHandler.level=INFO # 输出日志格式 java.util.logging.FileHandler.formatter = java.util.logging.SimpleFormatter # 输出日志文件路径 java.util.logging.FileHandler.pattern = /java%u.log # 输出日志文件限制大小(50000字节) java.util.logging.FileHandler.limit = 50000 # 输出日志文件限制个数 java.util.logging.FileHandler.count = 10 # 输出日志文件 是不是追加 java.util.logging.FileHandler.append=true
Log4j是Apache下的一款开源的日志框架,经过在项目中使用 Log4J,咱们能够控制日志信息输出到控制台、文件、甚至是数据库中。咱们能够控制每一条日志的输出格式,经过定义日志的输出级别,能够更灵活的控制日志的输出过程。方便项目的调试。
官方网站: http://logging.apache.org/log4j/1.2/
添加依赖
<dependencies> <dependency> <groupId>log4j</groupId> <artifactId>log4j</artifactId> <version>1.2.17</version> </dependency> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.12</version> </dependency> </dependencies>
java代码
public class Log4jTest { @Test public void testQuick() throws Exception { // 初始化系统配置,不须要配置文件 BasicConfigurator.configure(); // 建立日志记录器对象 Logger logger = Logger.getLogger(Log4jTest.class); // 日志记录输出 logger.info("hello log4j"); // 日志级别 logger.fatal("fatal"); // 严重错误,通常会形成系统崩溃和终止运行 logger.error("error"); // 错误信息,但不会影响系统运行 logger.warn("warn"); // 警告信息,可能会发生问题 logger.info("info"); // 程序运行信息,数据库的链接、网络、IO操做等 logger.debug("debug"); // 调试信息,通常在开发阶段使用,记录程序的变量、参数等 logger.trace("trace"); // 追踪信息,记录程序的全部流程信息 } }
还有两个特殊的级别:
OFF,可用来关闭日志记录。
ALL,启用全部消息的日志记录。
注:通常只使用4个级别,优先级从高到低为 ERROR > WARN > INFO > DEBUG
Log4J 主要由 Loggers (日志记录器)、Appenders(输出端)和 Layout(日志格式化器)组成。其中Loggers 控制日志的输出级别与日志是否输出;Appenders 指定日志的输出方式(输出到控制台、文件等);Layout 控制日志信息的输出格式。
日志记录器,负责收集处理日志记录,实例的命名就是类“XX”的full quailied name(类的全限定名),Logger的名字大小写敏感,其命名有继承机制:例如:name为org.apache.commons的logger会继承name为org.apache的logger。
Log4J中有一个特殊的logger叫作“root”,他是全部logger的根,也就意味着其余全部的logger都会直接或者间接地继承自root。root logger能够用Logger.getRootLogger()方法获取。
可是,自log4j 1.2版以来, Logger 类已经取代了 Category 类。对于熟悉早期版本的log4j的人来讲,
Logger 类能够被视为 Category 类的别名。
Appender 用来指定日志输出到哪一个地方,能够同时指定日志的输出目的地。Log4j 经常使用的输出目的地有如下几种:
输出端类型 | 做用 |
---|---|
ConsoleAppender | 将日志输出到控制台 |
FileAppender | 将日志输出到文件中 |
DailyRollingFileAppender | 将日志输出到一个日志文件,而且天天输出到一个新的文件 |
RollingFileAppender | 将日志信息输出到一个日志文件,而且指定文件的尺寸,当文件大小达到指定尺寸时,会自动把文件更名,同时产生一个新的文件 |
JDBCAppender | 把日志信息保存到数据库中 |
4.2.3 Layouts
布局器 Layouts用于控制日志输出内容的格式,让咱们可使用各类须要的格式输出日志。Log4j经常使用的Layouts:
格式化器类型 | 做用 |
---|---|
HTMLLayout | 格式化日志输出为HTML表格形式 |
SimpleLayout | 简单的日志输出格式化,打印的日志格式为(info - message) |
PatternLayout | 最强大的格式化期,能够根据自定义格式输出日志,若是没有指定转换格式,就是用默认的转换格式 |
4.3 Layout的格式
在 log4j.properties 配置文件中,咱们定义了日志输出级别与输出端,在输出端中分别配置日志的输出
格式。
控制台,文件,数据库
#指定日志的输出级别与输出端 log4j.rootLogger=INFO,Console # 控制台输出配置 log4j.appender.Console=org.apache.log4j.ConsoleAppender log4j.appender.Console.layout=org.apache.log4j.PatternLayout log4j.appender.Console.layout.ConversionPattern=%d [%t] %-5p [%c] - %m%n # 文件输出配置 log4j.appender.A = org.apache.log4j.DailyRollingFileAppender #指定日志的输出路径 log4j.appender.A.File = D:/log.txt log4j.appender.A.Append = true #使用自定义日志格式化器 log4j.appender.A.layout = org.apache.log4j.PatternLayout #指定日志的输出格式 log4j.appender.A.layout.ConversionPattern = %-d{yyyy-MM-dd HH:mm:ss} [%t:%r] -[%p] %m%n #指定日志的文件编码 log4j.appender.A.encoding=UTF-8 #mysql log4j.appender.logDB=org.apache.log4j.jdbc.JDBCAppender log4j.appender.logDB.layout=org.apache.log4j.PatternLayout log4j.appender.logDB.Driver=com.mysql.jdbc.Driver log4j.appender.logDB.URL=jdbc:mysql://localhost:3306/test log4j.appender.logDB.User=root log4j.appender.logDB.Password=root log4j.appender.logDB.Sql=INSERT INTO log(project_name,create_date,level,category,file_name,thread_name,line,all_category,message) values('itcast','%d{yyyy-MM-dd HH:mm:ss}','%p','%c','%F','%t','%L','%l','%m')
CREATE TABLE `log` ( `log_id` int(11) NOT NULL AUTO_INCREMENT, `project_name` varchar(255) DEFAULT NULL COMMENT '目项名', `create_date` varchar(255) DEFAULT NULL COMMENT '建立时间', `level` varchar(255) DEFAULT NULL COMMENT '优先级', `category` varchar(255) DEFAULT NULL COMMENT '所在类的全名', `file_name` varchar(255) DEFAULT NULL COMMENT '输出日志消息产生时所在的文件名称 ', `thread_name` varchar(255) DEFAULT NULL COMMENT '日志事件的线程名', `line` varchar(255) DEFAULT NULL COMMENT '号行', `all_category` varchar(255) DEFAULT NULL COMMENT '日志事件的发生位置', `message` varchar(4000) DEFAULT NULL COMMENT '输出代码中指定的消息', PRIMARY KEY (`log_id`) );
# RootLogger配置 log4j.rootLogger = trace,console # 自定义Logger log4j.logger.com.itheima = info,file log4j.logger.org.apache = error
@Test public void testCustomLogger() throws Exception { // 自定义 com.itheima Logger logger1 = Logger.getLogger(Log4jTest.class); logger1.fatal("fatal"); // 严重错误,通常会形成系统崩溃和终止运行 logger1.error("error"); // 错误信息,但不会影响系统运行 logger1.warn("warn"); // 警告信息,可能会发生问题 logger1.info("info"); // 程序运行信息,数据库的链接、网络、IO操做等 logger1.debug("debug"); // 调试信息,通常在开发阶段使用,记录程序的变量、参数等 logger1.trace("trace"); // 追踪信息,记录程序的全部流程信息 // 自定义 org.apache Logger logger2 = Logger.getLogger(Logger.class); logger2.fatal("fatal logger2"); // 严重错误,通常会形成系统崩溃和终止运行 logger2.error("error logger2"); // 错误信息,但不会影响系统运行 logger2.warn("warn logger2"); // 警告信息,可能会发生问题 logger2.info("info logger2"); // 程序运行信息,数据库的链接、网络、IO操做等 logger2.debug("debug logger2"); // 调试信息,通常在开发阶段使用,记录程序的变量、参数等 logger2.trace("trace logger2"); // 追踪信息,记录程序的全部流程信息 }
全称为Jakarta Commons Logging,是Apache提供的一个通用日志API。
它是为“全部的Java日志实现”提供一个统一的接口,它自身也提供一个日志的实现,可是功能很是常弱(SimpleLog)。因此通常不会单独使用它。他容许开发人员使用不一样的具体日志实现工具: Log4j, Jdk自带的日志(JUL)
JCL 有两个基本的抽象类:Log(基本记录器)和LogFactory(负责建立Log实例)。
添加依赖
<dependency> <groupId>commons-logging</groupId> <artifactId>commons-logging</artifactId> <version>1.2</version> </dependency>
入门代码
public class JULTest { @Test public void testQuick() throws Exception { // 建立日志对象 Log log = LogFactory.getLog(JULTest.class); // 日志记录输出 log.fatal("fatal"); log.error("error"); log.warn("warn"); log.info("info"); log.debug("debug"); } }
咱们为何要使用日志门面:
日志门面支持的日志实现数组
private static final String[] classesToDiscover = new String[]{"org.apache.commons.logging.impl.Log4JLogger", "org.apache.commons.logging.impl.Jdk14Logger", "org.apache.commons.logging.impl.Jdk13LumberjackLogger", "org.apache.commons.logging.impl.SimpleLog"};
获取具体的日志实现
for(int i = 0; i < classesToDiscover.length && result == null; ++i) { result = this.createLogFromClass(classesToDiscover[i], logCategory, true); }