【日志框架-笔记】JUL日志框架的介绍及其使用

news2024/10/6 20:33:10

日志框架

  • JUL日志框架
    • 入门程序
    • Logger直接的父子继承关系
    • Formatters
    • 独立的配置文件进行编写日志
    • 使用日志打印异常

学习日志无非就是为了四大目的:

  1. 问题诊断,调试程序;
  2. 错误定位,定位数据问题、网络问题、内存问题等错误位置;
  3. 数据分析,点击行为、兴趣爱好等构成日志,方便下次基于推荐。

主流日志框架:

  • 日志实现(具体干活的):JUL(Java Util Logging)、Logback、log4j、log4j2.
  • 日志门面(指定规则的):JCL(Jakarta Commons Logging)、slf4j(Simple Logging Facade For Java).

JUL日志框架

JUL 全称 Java Util Logging 是Java原生的日志框架,使用时不需要另外引入第三方类库,相对于其他日志框架来说使用方便,学习简单,能够在小型应用中灵活使用。

在这里插入图片描述

JUL 的实现架构在这里插入图片描述

在 JUL 中有以下关键组件:

  1. Loggers(日志):被称为记录器,应用程序通过获取 Logger 对象,调用其API来发布日志信息,用于记录系统或应用程序组件的消息;

在这里插入图片描述

  1. Appenders(输出源):也被称为 Handlers(处理器),每个Logger都会关联一组Handlers,Logger会将日志交给关联的 Haderler 处理,由 Handler 负责将日志做记录,Handlers 在此是一个抽象,其具体的实现决定了日志记录的位置可以是控制台、文件、网络上的其他日志服务或操作系统日志等。

在这里插入图片描述

  1. Layouts(布局):也被称为 Formatters,它负责对日志事件中的数据进行转换和格式化。Layout 决定了数据在一条日志记录中的最终形式。

在这里插入图片描述

  1. Level(级别):每条日志消息都有一个关联的日志级别。该级别粗略指导了日志消息的重要性和紧迫,可以将 Level 和 Loggers 联系,Appenders 做关联以便我们过滤消息。

在这里插入图片描述

  1. Filters(过滤器):根据需要定制哪些信息会被记录,哪些信息会被放过。

在这里插入图片描述

入门程序

有关日志对应的配置信息在所使用的 jdk 的 conf 目录下的 logging.properties 文件中。

在这里插入图片描述

    // 获取一个 logger 对象
    private static final Logger LOGGER = Logger.getLogger("mylog");

    @Test
    public void testJUL() throws IOException {

        // 去掉默认配置
        LOGGER.setUseParentHandlers(false);

		//创建一个控制台处理器,并设置输出形式和设置日志级别
        Handler handler = new ConsoleHandler();
        handler.setFormatter(new SimpleFormatter());
        handler.setLevel(Level.ALL);
		
		// 创建一个文件处理器,并设置输出形式和设置日志级别
        Handler fileHandler = new FileHandler("D://logs/jul-001.log",true);
        fileHandler.setLevel(Level.WARNING);
        fileHandler.setFormatter(new SimpleFormatter());

		// 添加日志处理器,可以添加多个,多个都会执行。
        LOGGER.addHandler(fileHandler);
        LOGGER.addHandler(handler);
        LOGGER.setLevel(Level.ALL);

        LOGGER.severe("This is a severe message");
        LOGGER.warning("This is a warning message");
        LOGGER.info("This is a info message");
        LOGGER.fine("This is a fine message");
        LOGGER.finer("This is a finer message");
    }

注意:任何一个 logger 都是单例的,前提是名字相同。如下所测试:

在这里插入图片描述

Logger直接的父子继承关系

Logger 之间存在父子继承关系,由上面可以知道,Logger 对象是根据传进去的名字而创建的,是单例的。

在这里插入图片描述
默认条件下,子Logger 会继承父 Logger 中的属性(配置)。
使用下面语句可以不继承父类的配置:

logger.setUseParentHandlers(false);

下面代码举例看看如何继承的父类配置:

    @Test
    public void testPrarent(){
        Logger logger = Logger.getLogger(TestJUL.class.getName());// com.ncpowernode.test.TestJUL
        Logger ncLogger = Logger.getLogger("com.ncpowernode.test");

        // 不使用 parent 的配置
        ncLogger.setUseParentHandlers(false);
		
		// 创建一个新的控制台处理器,并配置输出格式和级别
        Handler handler = new ConsoleHandler();
        handler.setFormatter(new SimpleFormatter());
        handler.setLevel(Level.ALL);
		
		// 父类进行配置,子类没有配置
        ncLogger.addHandler(handler);
        ncLogger.setLevel(Level.FINE);


        ncLogger.info("info");
        ncLogger.fine("fine");
		
		// 子类没有配置,按理说输出不了这条信息
        logger.fine("This is a fine message of son");
    }

输出结果:

221, 2023 7:38:58 下午 com.ncpowernode.test.TestJUL testPrarent
信息: info
221, 2023 7:38:58 下午 com.ncpowernode.test.TestJUL testPrarent
详细: fine
221, 2023 7:38:58 下午 com.ncpowernode.test.TestJUL testPrarent
详细: This is a fine message of son

Formatters

可以看 Formatter 的一个实现类 SimpleFormatter类中的 format 方法的返回,可推测其如何实现的格式转换。

return String.format(format,
                             zdt,
                             source,
                             record.getLoggerName(),
                             record.getLevel().getLocalizedLevelName(),
                             message,
                             throwable);

看其返回值可以知道,无非是通过掉用 String 类中的 format 静态方法进行字符串转换的。

日期处理格式,%tx,其中x代表着日期转换符,以下是一些日期转换符的一些标志:

在这里插入图片描述

测试:

在这里插入图片描述

独立的配置文件进行编写日志

库中自行的配置是在 jdk 的主目录下的 conf 目录下的 logging.properties 配置文件中进行配置的,那能否进行自行编写配置文件进行配置呢?

通过源码可以发现,配置文件的读取和解析是通过 LogManager 对象进行实现的,然后通过读取的配置文件对 Logger 进行基本的管理配置。

下面是源码中 LogManager 对象的创建方式

LogManager manager = LogManager.getLogManager();

在这里插入图片描述

在这里插入图片描述

了解了源码,可以自行写配置文件然后自己读取了。

首先咱自己建一个配置文件,下面是文件内容:
在这里插入图片描述

以下是测试代码:

    @Test
    public void testLogManager() throws IOException {
        LogManager logManager = LogManager.getLogManager();
        //logManager.readConfiguration(new BufferedInputStream(TestJUL.class.getClassLoader().getResourceAsStream("logstudy.properties")));
        logManager.readConfiguration(new BufferedInputStream(new FileInputStream("src/main/resources/logstudy.properties")));

        Logger logger = Logger.getLogger(TestJUL.class.getName());
        logger.fine("This is a fine message!!!");
    }

结果展示:

在这里插入图片描述

使用日志打印异常

通过 Logger 类中的 throwing 方法的源码可以知道,如果需要打印异常日志,级别必须是FINER,否则直接返回结束该方法。

在这里插入图片描述

所以我们自行配置文件:

# RootHandler
# 开始清楚一个Logger可以搭配多个处理器handler
handlers= java.util.logging.ConsoleHandler,java.util.logging.FileHandler


.level= FINER


java.util.logging.FileHandler.pattern = D://logs/java%u.log
java.util.logging.FileHandler.append = true # 是追加还是覆盖,true则是追加,false则是覆盖
java.util.logging.FileHandler.limit = 50000
java.util.logging.FileHandler.count = 1
java.util.logging.FileHandler.maxLocks = 100
java.util.logging.FileHandler.formatter = java.util.logging.XMLFormatter


java.util.logging.ConsoleHandler.level = FINER
java.util.logging.ConsoleHandler.formatter = java.util.logging.SimpleFormatter
# 灵活进行转换
java.util.logging.ConsoleHandler.formatter.format = %4$s: %5$s [%1$tc] %6$s%n

然后编写代码测试:

	@Test
    public void testLogManager() throws IOException {
        LogManager logManager = LogManager.getLogManager();
        //logManager.readConfiguration(new BufferedInputStream(TestJUL.class.getClassLoader().getResourceAsStream("logstudy.properties")));
        logManager.readConfiguration(new BufferedInputStream(new FileInputStream("src/main/resources/logstudy.properties")));

        Logger logger = Logger.getLogger(TestJUL.class.getName());
        logger.finer("This is a finer message!!!");


        try{
            int i = 1/0;
        }catch(ArithmeticException e){
            logger.throwing(TestJUL.class.getName(),"testLogManager",e);
        }
    }

结果:

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/363090.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【进阶教程】Appium自动化测试,太详细了!

目录Appium环境搭建Mac iOS环境搭建Appium基础Appium进阶Monkey的使用Copyadb shell monkey -p com.lqr.wechat -v 500 > monkey.logadb shell monkey -p com.lqr.wechat -vvv 5000 > monkey2.logadb shell monkey -p com.lqr.wechat -vvv 5000--send1556166765229 --thr…

pdb文件删除杂原子 HETATM;保留或去除水分子

删除杂原子 HETATM;去除水分子 with open(r"C:*****\StructA.pdb", "r") as inputFile,open(r"C*****8\StructA_remove_HETATM.pdb","w") as outFile:for line in inputFile:if not line.startswith("HETATM"):…

C++复习笔记13

多态:具体点就是去完成某个行为,当不同的对象去完成时会产生出不同的状态。(同一个接口根据调用对象不同产生不同的行为)。两个条件: 1. 必须通过基类的指针或者引用调用虚函数。 2. 被调用的函数必须是虚函数&#x…

ESP32 Arduino FAT文件系统详细使用教程

ESP32 Arduino FAT文件系统详细使用教程📌参考1(在 Linux环境下创建二进制文件):https://github.com/marcmerlin/esp32_fatfsimage📌参考2 http://marc.merlins.org/perso/arduino/post_2019-03-30_Using-FatFS-FFat-o…

Scala函数式编程(第五章:函数基础、函数高级详解)

文章目录第 5 章 函数式编程5.1 函数基础5.1.1 函数基本语法5.1.2 函数和方法的区别5.1.3 函数定义5.1.4 函数参数5.1.5 函数至简原则(重点)5.2 函数高级5.2.1 高阶函数5.2.2 匿名函数5.2.3 高阶函数案例5.2.4 函数柯里化&闭包5.2.5 递归5.2.6 控制抽…

GooglePlay SSL Error Handler

应用上架GooglePlay 收到邮件提示 出现这个原因是因为我在app中使用webview加载Https的H5界面,在onReceivedSslError()中处理SslErrorHandler时,出现白屏现象,原因是webview默认在加载有证书验证的url时,会默认使用handler.cancel…

SPDK vhost target

SPDK vhost target主流的I/O设备虚拟化的方案1.virtio2.vhost加速1)QEMU virtio-scsiQemu 架构2)Kernel vhost-scsi3)SPDK vhost-user-scsi3.SPDK vhost-scsi加速4.SPDK vhost-NVMe加速主流的I/O设备虚拟化的方案 纯软件模拟:完全…

vTESTstudio - VT System CAPL Functions - VT7001(续1)

vtsSetInterconnectionMode - 设置VT7001的电源输出模式功能:设置电源模块VT7001的三个可能电源和两个电源输出的互连模式。注意:此函数不能在任何CAPL处理程序例程或ECU节点中调用。它只能在测试模块的MainTest方法上下文中调用;使用在测量开…

企业为什么需要数据可视化报表

数据可视化报表是在商业环境、市场环境已经改变之后,发展出来为当前企业提供替代解决办法的重要方案。而且信息化、数字化时代,很多企业已经进行了初步的信息化建设,沉淀了大量业务数据,这些数据作为企业的资产,是需要…

Logstash:在 Logstash 管道中的定制的 Elasticsearch update by query

我们知道 Elasticsearch output plugin 为我们在 Logstash 的 pipeline 中向 Elasticsearch 的写入提供了可能。我们可以使用如下的格式向 Elasticsearch 写入数据: elasticsearch {hosts > ["https://localhost:9200"]index > "data-%{YYYY.M…

ROS2手写自定义点云(PointCloud2)数据并发布

目录前言实现前言 继续学习ROS2,最近把navigation2的路径规划部分学习了一遍,但是还没有进行测试,于是先把这个部分先空出来后面再总结。先写一个与避障有关系的如何自己发点云数据。 在nav2里面有一个非常重要的部分就是costmap部分&#…

Python是未来的编程语言?学Python前景如何?薪资高吗?

Python是一种强大的语言,为世界各地的开发人员提供了多种用途。根据TIOBE指数,Python的排名还在继续攀升。开发人员和技术专业人员也不断发现Python的新用途,包括数据分析和机器学习等。 Python现在有着庞大的用户基础,并且它深深…

经纬度坐标点和距离之间的转换

1.纬度相同,经度不同 在纬度相同的情况下: 经度每隔0.00001度,距离相差约1米; 每隔0.0001度,距离相差约10米; 每隔0.001度,距离相差约100米; 每隔0.01度,距离相差约1000米…

Linux 远程登录

Linux 一般作为服务器使用,而服务器一般放在机房,你不可能在机房操作你的 Linux 服务器。 这时我们就需要远程登录到Linux服务器来管理维护系统。 Linux 系统中是通过 ssh 服务实现的远程登录功能,默认 ssh 服务端口号为 22。 Window 系统…

SpringCloud+Dubbo3 = 王炸 !

前言 全链路异步化的大趋势来了 随着业务的发展,微服务应用的流量越来越大,使用到的资源也越来越多。 在微服务架构下,大量的应用都是 SpringCloud 分布式架构,这种架构总体上是全链路同步模式。 全链路同步模式不仅造成了资源…

第二章 runtime-core初始化核心流程和runtime-core更新核心流程

runtime-core初始化核心流程 1 创建app 2 进行初始化 2.1 基于组件生成虚拟节点 2.2 进行render 调用patch 根据不同的vnode类型进行不同类型的组件处理 组件 2.2.1 创建component instance对象 2.2.2 setup component 初始化props slots 各种 2.2.3 setupRenderEffect…

通过Docker部署rancher

先创建k8s集群 https://blog.csdn.net/weixin_44371237/article/details/123974335 环境准备 一台linux主机,4G内存 通过Docker部署rancher 启动rancher docker run --privileged -d --restartunless-stopped -p 80:80 -p 443:443 rancher/rancher查看本地镜像…

python基础:简单实现从网页中获取小说名单列表并存入文件中

python基础:简单实现从网页中获取小说名单列表并存入文件中1.技术储备 requests:requests是使用Apache2 licensed 许可证的HTTP库,可以用于网页数据请求 requests.get():发起网络请求的一种方式,类似的还有post、 put、 delete、…

[MySQL]基本数据类型及表的基本操作

哈喽,大家好!我是保护小周ღ,本期为大家带来的是 MySQL 数据库常用的数据类型,数据表的基本操作:创建、删除、修改表,针对修改表的结构进行了讲解,随后是如何向数据表中添加数据,浅浅…

Vulnhub_Venom

目录 一 测试 (一)信息收集 1 端口服务探测 2 目录扫描 3 前端源码信息收集 (二)漏洞发现 1 前端注释敏感信息泄露 2 CVE-2018-19422-Subrion CMS v 4.2.1任意文件上传 (三)提权 1 sudo…