日志技术

日志文件

  • 调试日志:软件开发中,我们经常需要去调试程序,做一些信息,状态的输出便于我们查询程序的运行状况。为了让我们能够更加灵活和方便的控制这些调试的信息,所有我们需要专业的日志技术。java中寻找bug会需要重现。调试也就是debug可以在程序运行中暂停程序运行,可以查看程序在运行中的情况。日志主要是为了更方便的去重现问题。
  • 系统日志:系统日志是记录系统中硬件、软件和系统问题的信息,同时还可以监视系统中发生的事件。用户可以通过它来检查错误发生的原因,或者寻找受到攻击时攻击者留下的痕迹。系统日志包括系统日志、应用程序日志和安全日志。

JAVA日志框架使用需要解决的问题

  1. 控制日志输出的内容和格式
  2. 控制日志输出的位置
  3. 日志优化
  4. 日志系统的维护
  5. 面向接口开发(日志的门面)

日志框架

1.JUL

  • Java util logging是java原生的日志框架,不需要引用第三方类库
  • JUL日志级别:
    1. SEVERE
    2. WARNING
    3. INFO (默认级别)
    4. CONFIG
    5. FINE
    6. FINER
    7. FINEST
    • JUL日志特殊级别:
    1. OFF,可用来关闭日志记录。
    2. ALL,启用所有消息的日志记录。
package com.pang;

import org.junit.Test;
import java.util.logging.Level;
import java.util.logging.Logger;

public class JULTest {

    @Test
    public void test() throws Exception{
        //获取日志记录器对象,com.pang.Test是一个唯一标识
        Logger logger = Logger.getLogger("com.pang.Test");
        //日志记录输出
        logger.info("pangjian");

        //通用方法进行日志记录
        logger.log(Level.INFO,"pangjian222");

        //占位符方式输出变量值
        String name = "pang";
        Integer age = 18;
        logger.log(Level.INFO,"我的姓名和年龄:{0},{1}",new Object[]{name,age});

    }
    
    @Test
    public void Test1() throws Exception{

        Logger logger = Logger.getLogger("Test1");

        // 2.日志记录输出
        logger.severe("severe");
        logger.warning("warning");
        logger.info("info");//JUL默认级别,当启动info级别,它以下的级别就不会进行输出
        logger.config("cofnig");
        logger.fine("fine");
        logger.finer("finer");
        logger.finest("finest");
        }
}

自定义JUL日志级别和自定义输出位置

    @Test
    public void Test2() throws Exception{

        Logger logger = Logger.getLogger("Test2");
        //关闭默认的日志级别
        logger.setUseParentHandlers(false);

        //自定义配置日志级别

        //创建ConsoleHandler对象
        ConsoleHandler consoleHandler = new ConsoleHandler();
        //创建简单格式转换对象
        SimpleFormatter simpleFormatter = new SimpleFormatter();

        //关联
        consoleHandler.setFormatter(simpleFormatter);
        logger.addHandler(consoleHandler);
        
        //要输出到一个文件中
        FileHandler fileHandler = new FileHandler("D:\springboot-study\JUL\jul.log");
        fileHandler.setFormatter(simpleFormatter);
        logger.addHandler(fileHandler);

        //控制台日志级别会受logger的日志级别的限制
        logger.setLevel(Level.ALL);
        //控制台要输出的日志级别
        consoleHandler.setLevel(Level.FINEST);

        logger.severe("severe");
        logger.warning("warning");
        logger.info("info");
        logger.config("cofnig");
        logger.fine("fine");
        logger.finer("finer");
        logger.finest("finest");

    }

通过读取配置文件去自定义JUL日志级别和自定义输出位置

#为 Handler 指定默认的级别(默认为 Level.INFO)。 
java.util.logging.ConsoleHandler.level=INFO
# 指定要使用的 Formatter 类的名称(默认为 java.util.logging.SimpleFormatter)。 
java.util.logging.ConsoleHandler.formatter=java.util.logging.SimpleFormatter

# 为 Handler 指定默认的级别(默认为 Level.ALL)。 
java.util.logging.FileHandler.level=INFO
# 指定要使用的 Formatter 类的名称(默认为 java.util.logging.XMLFormatter)。 
java.util.logging.FileHandler.formatter=java.util.logging.SimpleFormatter
# 指定要写入到任意文件的近似最大量(以字节为单位)。如果该数为 0,则没有限制(默认为无限制)。 
java.util.logging.FileHandler.limit=50000
# 指定有多少输出文件参与循环(默认为 1)。 
java.util.logging.FileHandler.count=1
# 为生成的输出文件名称指定一个模式。有关细节请参见以下内容(默认为 "%h/java%u.log")。 
java.util.logging.FileHandler.pattern=C:/SSLog%u.log
# 指定是否应该将 FileHandler 追加到任何现有文件上(默认为 false)。 
java.util.logging.FileHandler.append=true


handlers= java.util.logging.ConsoleHandler,java.util.logging.FileHandler
    @Test
    public void Test3() throws Exception{
        //读取配置文件,通过类加载器
        InputStream inputStream = JULTest.class.getClassLoader().getResourceAsStream("logging.properties");
        //创建LogManager
        LogManager logManager = LogManager.getLogManager();
        //通过LogManager加载配置文件
        logManager.readConfiguration(inputStream);
        //创建日志记录器
        Logger logger = Logger.getLogger("Test3");
    }

JUL日志原理

  1. 应用要进行日志记录要调用logger对象
  2. logger对象要调用logManager对象去加载配置文件进行初始化
  3. 设置日志级别Level
  4. Filter提供了日志级别之外更细粒度的控制
  5. Handle是用来处理文件的输出位置的
  6. Formatter是用来格式化LogRecord的

2.Log4j

<!--需要导入的依赖-->
<dependency>
       <groupId>log4j</groupId>
       <artifactId>log4j</artifactId>
       <version>1.2.12</version>
</dependency>
  • Log4j日志级别:
  1. FATAL (严重错误,一般会造成系统崩溃并终止运行)
  2. ERROR (错误信息,不会影响系统运行)
  3. WARN(警告信息,可能会发生问题)
  4. INFO (运行信息,数据库连接,IO操作等)
  5. Debug(默认级别,调试信息,一般在开发中使用,记录程序变量参数变化和传递)
  6. Trace(追踪信息)
public class Log4jTest {

    @Test
    public void test() throws Exception{

        //初始化配置信息
        BasicConfigurator.configure();
        //获取日志记录器对象
        Logger logger = Logger.getLogger(Log4jTest.class);
		//日志记录输出
        logger.info("pangjian");

    }
}

Log4j中有三个主要的组件,它们分别是 Loggers、Appender和Layout。

  1. Loggers是日志记录器,描述它可以改变日志记录的表现。 Log4j 允许开发人员定义多个Loggers,每个Loggers拥有自己的名字。有一个Loggers称为Root,可以通过Logger.getRootLogger()方法获得。 其它Logger通过Logger.getLogger(String name)方法获得。
  2. Appender是输出端,用来指明将所有的log信息存放到什么地方,Log4j中支持多种appender,如 console、files、GUI components、NT Event Loggers等。一个Logger可以拥有多个Appender。
  3. Layout是日志格式化器,作用是控制Log信息的输出方式,也就是格式化输出的信息。

使用配置文件加载

public class Log4jTest {

    @Test
    public void test() throws Exception{

		//开启内置的日志对象
        //LogLog.setInternalDebugging(true);

        //获取日志记录器对象
        Logger logger = Logger.getLogger(Log4jTest.class);
        logger.fatal("fatal");
        logger.error("error");
        logger.warn("warn");
        logger.debug("debug");
        logger.trace("trace");

    }
}

配置文件 log4j.properties

# 指定RootLogger 顶级父元素默认的配置信息
# 指定日志级别=trace,使用 apeender 为console
log4j.rootLogger = trace,console

# 指定log4j.appender.(输出端对象)
log4j.appender.console= org.apache.log4j.ConsoleAppender

# 指定输出格式log4j.appender.console.layout
# 值还有(org.apache.log4j.HTMLLayout或org.apache.log4j.xml.XMLLayout或org.apache.log4j.PatternLayout或org.apache.log4j.SimpleLayout)
log4j.appender.console.layout = org.apache.log4j.PatternLayout

# 指定消息格式的内容
%n - 换行
%m - 日志内容
%p - 日志级别(FATAL, ERROR, WARN, INFO, DEBUG or custom)
%r - 程序启动到现在的毫秒数
%% - percent sign in output
%t - 当前线程名
%d - 日期和时间,常用的格式有 %d{DATE}, %d{ABSOLUTE}, %d{HH:mm:ss,SSS},
%F - java源文件名
%L - java源码行数
%C - java类名,%C{1} 输出最后一个元素
%M - java方法名
%l - 同 %F%L%C%M
log4j.appender.console.layout.conversionPattern = [%p]%r %c %t %F %L %d{yyyy年MM月dd日 HH:mm:ss.SSS} %m%n
# [FATAL]2 Log4jTest main Log4jTest.java 22 2020Äê12ÔÂ12ÈÕ 17:31:59.558 fatal

写入数据库的配置


log4j.rootLogger = trace,logDB
#写入mysql
log4j.appender.logDB = org.apache.log4j.jdbc.JDBCAppender


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 pang_log (create_time,log) VALUES ('%d{yyyy-MM-dd hh:mm:ss}', '%c %p %m %n')
log4j.appender.logDB.layout=org.apache.log4j.PatternLayout

3.Logback

Logback主要分为三个模块:

  • logback-core:其它两个模块的基础模块
  • logback-classic:它是log4j的一个改良版本,同时它完整实现了slf4j API
  • logback-access:访问模块与Servlet容器集成提供通过Http来访问日志的功能

logback会依次读取以下类型配置文件;

  • logback.groovy
  • logback-test.xml
  • logback.xml 如果均不存在会采用默认配置

日志门面

1.JCL

<!--需要导入的依赖-->
<dependency>
       <groupId>commons-logging</groupId>
       <artifactId>commons-logging</artifactId>
       <version>1.2</version>
</dependency>
  • 全称Jakarta commons logging,是Apache提供的一个通用日志API
  • 它是为所有的Java日志框架提供一个统一的接口,它自身也提供一个日志实现,但功能弱,一般不会单独使用它。
  • JCL有两个基本的抽象类:Log(基本记录器)和LogFactory(负责创建Log实例)
  • 作用是为了做到JUL升级到Log4j的统一

在这里插入图片描述


2.SLF4J

  • 当我们的系统变的更加复杂的时候,我们的日志就容易发生混乱。随着系统开发的进行,可能会更新不同的日志框架,造成当前系统中存在不同的日志依赖,让我们难以统一的管理和控制。就算我们强制要求所有的模块使用相同的日志框架,系统中也难以避免使用其他类似spring.mybatis等其他的第三方框架,它们依赖于我们规定不同的日志框架,而且他们自身的日志系统就有着不一致性,依然会出来日志体系的混乱。所以我们需要借鉴JDBC的思想,为日志系统也提供一套门面,那么我们就可以面向这些接口规范来开发,避免了直接依赖具体的日志框架。这样我们的系统在日志中,就存在了日志的门面和日志的实现。
  • 常见的日志门面:JCL,slf4j

如果使用log4j实现日志框架和slf4j日志门面,要导入适配器坐标

<!--绑定 log4j 日志实现,需要导入适配器-->
 <dependency>
     <groupId>org.slf4j</groupId>
     <artifactId>slf4j-log4j12</artifactId>
     <version>1.7.12</version>
</dependency>
package com.pang;

import org.apache.log4j.Logger;
import org.junit.Test;

public class LogTest {

    public static final Logger LOGGER = Logger.getLogger(LogTest.class);

    @Test
    public void test01(){

        LOGGER.info("hello log4j");
        /* 一开始我们用的是Log4j日志实现框架,
        现在我们要升级迭代成logback,
        首先我们要去除Maven的log4j坐标,
        加上logback的,然后导入桥接器坐标,(记得把适配器去掉,不然会报栈溢出异常)
        然后源代码不用变而日志实现框架变成了logback*/

    }

}

桥接解决的是项目中日志的遗留问题,当系统中存在之前的日志API,可以通过桥接转换到slf4j的实现

  • 1.先去除之前老的日志框架的依赖
  • 2.添加SLF4J]提供的桥接组件
  • 3.为项目添加SLF4J的具体实现
<!-- 桥接器 -->
<dependency>
    <groupId>org.slf4j</groupId>
    <artifactId>log4j-over-slf4j</artifactId>
    <version>1.7.25</version>
</dependency>
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值