• Java的标准日志


    虽然开源社区有很多优秀的日志框架,但我们学习标准的java日志框架是为了更好的理解其他框架啊(近期项目要用ELK)

    看自己以前写的Log4J简直不忍直视啊啊啊啊,那时还感觉自我良好



    1. 为什么要使用日志

    我们都试过在代码中插入System.out.println方法来进行调试吧,当找出问题根源后就把插入的print语句删除,若又出现问题则需再次插入这些语句,如此反复。那么日志API就是为了解决这个问题而设计的,使用日志的优势:

    • 可随时开闭日志记录,还能分级别筛选日志,并且保留日志代码开销很小
    • 日志可简单地被定向到控制台显示,文件保存,或者网络传输
    • 日志可格式化其记录的格式
    • 日志可由配置文件控制
    • 日志利于日后错误的定位






    2. Logger

    java有标准的日志系统,在java.util.logging包下。因为它不太好用,就出现了各种补充的日志框架,其实我看着也还行,能够应付我的日常使用了


    2.1 示例

    看不懂没关系,码入下面的程序就可以看到日志记录的情况了

    public class loggerTest {
        public static void main(String[] args) {
            
            // 1. 获得一个全局的日志记录器
            Logger global = Logger.getGlobal();
            
            // 2. 日志有七个级别,从高到低分别是:Sever、Warning、Info、Config、Fine、Finer、Finest
            // 	  默认级别为INFO,意思只输出前三个级别的记录
            global.info("INFO MSG");
            global.warning("WARNING MSG");
            global.severe("SERVE MSG");
            
             // 3. 可通过setLevel来设置日志级别,来限制其他级别的记录
            global.setLevel(Level.WARNING);
        }
    }
    
    // 控制台输出
    // 七月 23, 2021 8:57:17 下午 logging.loggerTest main
    // 信息: INFO MSG
    // 七月 23, 2021 8:57:17 下午 logging.loggerTest main
    // 警告: WARNING MSG
    // 七月 23, 2021 8:57:17 下午 logging.loggerTest main
    // 严重: SERVE MSG
    


    2.2 日志的记录器

    记录器是用来 "记录"、定位日志记录的,一般我们不想把所有的日志都记录到一个全局记录器上,那么我们就可以自定义一个记录器


    public class loggerTest {
    
        // 未被任何变量引用的日志记录器可能被垃圾回收掉,所以采用了静态变量的方式
        private static  final Logger myLogger = Logger.getLogger("com.howl.logger.loggerTest");;
    
        public static void main(String[] args) {
             myLogger.info("this is my logger msg");
        }
    }
    

    日志的记录器有类似于包名继承的层次结构,父记录器设置了日志级别,那么子记录器就会继承这个级别,所以日志框架的记录器命名都以类名限定



    2.3 日志配置

    java有个叫日志管理器的东西专门来管配置的,java9的配置文件是在 jre/conf/logging.properties。日志管理器在虚拟机启动时就初始化,就是在main方法执行之前


    我们可以在启动项目时就指定日志的配置文件:java -Djava.util.logging.config.file=新文件名

    也可在项目运行时用System.setProperty("java.util.logging.config.file", file)指定配置文件,并LogManager.getLogManager().readConfiguration()重新初始化日志管理器生效配置(食用配置文件形式不好,其他日志框架的配置在项目根目录,会自动读取的)



    2.4 日志的处理器

    处理器是用于处理记录的(也有日志级别),记录器有ConsoleHandler、FileHandler、SocketHandler。默认情况下记录器将记录发到ConsoleHandler然后输出,如想输出到其他地方就添加其他的处理器。具体流程的话,就是记录器将记录发给自己的处理器和父记录器的处理器,全部记录器的最终祖先是名为 "" 的一个记录器,它有一个ConsoleHandler,所以默认的日志记录都输出到控制台


    public class loggerTest {
    
        // 静态变量放垃圾回收
        private static  final Logger myLogger = Logger.getLogger("com.howl.logger.loggerTest");;
    
        public static void main(String[] args) throws IOException {
    
            // 文件、控制台处理器
            FileHandler fileHandler = new FileHandler();
            ConsoleHandler consoleHandler = new ConsoleHandler();
            
            myLogger.addHandler(consoleHandler);	// 这条语句在控制台输出了两次
            myLogger.addHandler(fileHandler);
    
            myLogger.info("add two handler");
        }
    }
    
    // 控制台输出
    // 七月 23, 2021 9:31:26 下午 logging.loggerTest main
    // 信息: add two handler
    // 七月 23, 2021 9:31:26 下午 logging.loggerTest main
    // 信息: add two handler
    

    怎么会有两条记录?

    • fileHander是输出文件的(不在控制台输出),日志文件默认保存在用户目录下的javaN.log中,其中N是唯一编号,默认格式为XML

    • 上面说的myLogger发给自己处理器consoleHandler输出,也会发给父处理器输出,所以有两条,可配置userParentHandlers = false,取消使用父处理器



    2.5 日志的过滤器

    记录器,处理器只能根据日志级别来过滤,而过滤器则更加自由多样化。我们需要实现Filter接口(注意是Logger下的接口)然后将其交给记录器(是记录器啊,下面标题2.6的才是交给处理器)


    public class loggerTest {
    
        private static  final Logger myLogger = Logger.getLogger("com.howl.logger.loggerTest");;
    
        public static void main(String[] args) throws IOException {
    
            // 过滤器
            Filter filter = new Filter() {
                @Override
                public boolean isLoggable(LogRecord record) {
                    return record.getMessage().contains("HAHA");    // 记录包含了HAHA就不过滤
                }
            };
    
            myLogger.setFilter(filter);
            myLogger.info("add two handler");
            myLogger.info("i am HAHA");
        }
    }
    
    // 控制台输出
    // 七月 23, 2021 9:43:27 下午 logging.loggerTest main
    // 信息: i am HAHA
    


    2.6 日志的格式化器

    格式化器顾名思义是用来格式化记录的,看需要生成什么样格式的记录,我的话就在日志前加点东西就好了。也是需要实现format接口的,当然记录的格式化操作是交给处理器的


    public class loggerTest {
    
        private static  final Logger myLogger = Logger.getLogger("com.howl.logger.loggerTest");;
    
        public static void main(String[] args) throws IOException {
    
            // 格式化器
            Formatter formatter = new Formatter() {
                @Override
                public String format(LogRecord record) {
                    return "这里是格式化器: "+ record.getMessage() + "
    
    ";
                }
            };
    
            ConsoleHandler consoleHandler = new ConsoleHandler();
            consoleHandler.setFormatter(formatter);
    
            myLogger.addHandler(consoleHandler);
            myLogger.info("i am HAHA");
        }
    }
    
    // 控制台输出
    // 这里是格式化器: i am HAHA
    // 
    // 七月 23, 2021 9:52:58 下午 logging.loggerTest main
    // 信息: i am HAHA
    






    3. java日志的发展史

    • Apache 的 log4j 日志框架最早出现(可用配置文件管理日志,并动态加载)
    • java1.4 后面才添加的标准日志库 java.util.logging(JUL)
    • Apache 推出日志门面Apache Commons Logging(JCL,提供了一套日志接口,兼容上面二者)
    • 再然后 JCL 的作者弄了个新的日志门面 slf4j,并提供了其组件实现 logback
    • 最后 Apache 重写log4j,推出 log4j2
    • 因为 slf4j 门面后面才出现,所以推出了各种补丁使其兼容 JCL 的接口,看着好复杂

    日志门面 组件实现
    JCL、slf4j log4j、log4j、logback、JUL

    使用框架需选一个日志门面,然后再选择个门面的实现,不选择实现的话默认使用 java 的标准库







    4. 项目中为什么不使用JUL

    笔者还没在项目中实际用过日志框架,体会到的不多,目前只知道 JUL 的配置管理器实属败笔~ 。等笔者搭完这次项目用到的ELK之后再慢慢体会把



  • 相关阅读:
    add custom attribute to standard windows controls
    产生0到1之间均匀分布的一个随机数与随机数序列
    (HDOJ 1002)A + B Problem II
    递推问题系列1幂积序列
    杭电题目分类解答
    (HDOJ 1003)Max Sum
    快排序(递归算法)
    (HDOJ 1004)Let the Balloon Rise
    (HDOJ 1005)Number Sequence
    一个关于去除数组重复元素的问题(C语言实现)
  • 原文地址:https://www.cnblogs.com/Howlet/p/15056623.html
Copyright © 2020-2023  润新知