java LogUtil输出日志打日志的class文件内具体方法和行号

最近琢磨怎么把日志打的更清晰,方便查找问题,又不需要在每个class内都创建Logger对象;利用堆栈的方向顺序拿到日志的class问题。看效果,直接上代码。

1、demo test

2、输出效果

3、完整的LogUtil文件
import org.jetbrains.annotations.NotNull;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class LogUtil {

    public static void trace(String msg) {
        getLogger().trace(msg);
    }

    public static void debug(String msg) {
        getLogger().debug(msg);
    }

    public static void info(String msg) {
        getLogger().info(msg);
    }

    public static void warning(String msg) {
        getLogger().warn(msg);
    }

    public static void error(String msg) {
        getLogger().error(msg);
    }

    public static void error(String msg, Throwable t) {
        getLogger().error(msg, t);
    }

    private static Logger getLogger() {
        return LoggerFactory.getLogger(findCaller());
    }

    /**
     * 查找调用者的方法。
     * 通过分析当前线程的堆栈跟踪,找到第一个不是LogUtil类的方法作为调用者。
     * 这个方法主要用于在日志记录时,确定日志的来源,以便更好地定位问题。
     *
     * @return 调用者的类路径和方法名。
     */
    private static String findCaller() {
        // 获取当前线程的堆栈跟踪元素
        // 获取堆栈信息
        StackTraceElement[] callStack = Thread.currentThread().getStackTrace();

        // 初始化调用者堆栈元素为null
        // 最原始被调用的堆栈信息
        StackTraceElement caller = null;

        // 获取LogUtil类的全限定名
        // 日志类名称
        String logClassName = LogUtil.class.getName();

        // 遍历堆栈跟踪元素,找到第一个不是LogUtil类的元素
        // 循环遍历到日志类标识
        int i = 0;
        for (int len = callStack.length; i < len; i++) {
            if (logClassName.equals(callStack[i].getClassName())) {
                break;
            }
        }

        // 调用者位于LogUtil类元素之后的第三个元素(考虑到findCaller自身和getStackTrace的调用)
        caller = callStack[i + 3];

        // 获取调用者的类路径和方法名
        String fullPath = getPath(caller);

        // 返回调用者的类路径和方法名
        return fullPath;
    }


    /**
     * 获取调用者堆栈跟踪元素的详细路径。
     *
     * 本方法用于生成调用者方法的详细路径,包括类名、方法名和行号。这样生成的路径可以帮助定位代码中调用此方法的位置,
     * 对于调试和跟踪代码执行流程非常有用。
     *
     * @param caller 调用者堆栈跟踪元素,通过StackTraceElement获取。
     * @return 返回一个字符串,包含调用者类名、方法名和行号的详细路径。
     */
    @NotNull
    private static String getPath(StackTraceElement caller) {
        // 格式化类名,去除包名,只保留类名部分。
        String formatClassName = caller.getClassName();
        // 获取调用者方法名。
        String methodName = caller.getMethodName();
        // 获取调用者方法所在的行号。
        int lineNumber = caller.getLineNumber();
        // 拼接类名、方法名和行号,生成详细的路径。
        String fullPath = formatClassName + "." + methodName + "." + lineNumber;
        return fullPath;
    }


    /**
     * 格式化类名。
     * 将带有包名的类名转换为首字母大写的形式,去除包名并连接类名。
     * 例如,输入 "com.example.MyClass",输出 "MyClass"。
     * 如果类名本身不包含包名,直接返回原类名。
     *
     * @param name 完整的类名,包括包名。
     * @return 格式化后的类名,不包含包名。
     */
    private static String simpleClassName(String name) {
        // 使用正则表达式按点号分割类名和包名
        String[] split = name.split("\\.");
        // 使用 StringBuffer 来构建最终的类名,以确保线程安全和效率
        StringBuffer buf = new StringBuffer();
        for (int i = 0; i < split.length; i++) {
            // 如果当前元素不是最后一个元素,说明它是包名的一部分
            // 取出每个包名部分的第二个字符(即首字母)并连接到缓冲区
            // 如果是最后一个元素,直接添加到缓冲区,以保留类名的完整性
            if (i != split.length - 1) {
                buf.append(split[i].charAt(1));
                buf.append(".");
            } else {
                buf.append(split[i]);
            }
        }
        // 将缓冲区转换为字符串并返回
        return buf.toString();
    }

}
4、springboot 日志收集配置logback-spring.xml文件,这个文件根据需求编辑
<?xml version="1.0" encoding="UTF-8"?>
<configuration scan="ture" scanPeriod="60 seconds" debug="false">
    <!-- 定义日志的根目录 -->
    <property name="LOG_HOME" value="./logs"/>
    <!-- 定义日志文件名称 -->
    <property name="APP_NAME" value="myApp"/>
    <!-- 控制台输出 -->
    <appender name="console" class="ch.qos.logback.core.ConsoleAppender">
        <filter class="ch.qos.logback.classic.filter.ThresholdFilter">
            <level>INFO</level>
        </filter>

        <encoder>
            <charset>UTF-8</charset>
            <!-- <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n</pattern>-->
            <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %highlight(%-5level) %green(%logger{50}) - %msg%n</pattern>
        </encoder>
    </appender>

    <!-- 滚动记录文件,先将日志记录到指定文件,当符合某个条件时,将日志记录到其他文件 -->
    <appender name="appLogAppender" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <!-- 指定日志文件的名称 -->
        <file>${LOG_HOME}/${APP_NAME}.log</file>
        <!-- 当发生滚动时,决定 RollingFileAppender 的行为,涉及文件移动和重命名 -->
        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
            <!-- 滚动时产生的文件的存放位置及文件名称 %d{yyyy-MM-dd}:按天进行日志滚动 -->
            <fileNamePattern>${LOG_HOME}/${APP_NAME}-%d{yyyy-MM-dd}.log</fileNamePattern>
            <!-- 只保存最近30天的文件 -->
            <MaxHistory>30</MaxHistory>
            <!--用来指定日志文件的上限大小 -->
            <totalSizeCap>10GB</totalSizeCap>-->
        </rollingPolicy>
        <!-- 日志输出编码格式化 -->
        <encoder>
            <charset>UTF-8</charset>
            <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50}:%line - %msg%n</pattern>
        </encoder>
    </appender>


    <root level="INFO">
        <appender-ref ref="console"/>
        <appender-ref ref="appLogAppender"/>
    </root>
</configuration>
5、springboot项目log4j配置

log4j.rootLogger=WARN, stdout, R
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}] [%5p] [%t] [%l] - %m%n

log4j.appender.R=org.apache.log4j.RollingFileAppender
log4j.appender.R.File=ai.log
log4j.appender.R.MaxFileSize=10240KB
log4j.appender.R.MaxBackupIndex=10
log4j.appender.R.layout=org.apache.log4j.PatternLayout
log4j.appender.R.layout.ConversionPattern=[%d{yyyy-MM-dd HH:mm:ss}] [%5p] [%t] [%l] - %m%n

log4j.logger.org.springframework=WARN
log4j.logger.com.lagooo.as=INFO
log4j.logger.org.apache=INFO
log4j.logger.org.apache.log4j.Logger=error

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

导入项目,JAVA文件是咖啡杯图标

问题 从图中可以看到&#xff0c;JAVA文件是咖啡杯图标 原因 项目没有识别为MAVEN项目 解决办法 进入pom.xml文件&#xff0c;右键点击Add as Maven Project即可

详解Linux的shell脚本基础指令

一、shell简介 是Linux系统的用户界面&#xff0c;它提供用户与内核的一种交互方式。它接收用户输入的命令&#xff0c;并把它送入内核去执行&#xff0c;是一个命令解释器。 脚本&#xff1a;本质是一个文件&#xff0c;文件里面存放的是 特定格式的指令&#xff0c;系统可以…

CC4利用链分析

我的Github主页Java反序列化学习同步更新&#xff0c;有简单的利用链图 分析版本 Commons Collections 4.0 JDK 8u65 环境配置参考JAVA安全初探(三):CC1链全分析 分析过程 在Commons Collections 4.0中&#xff0c;TransformingComparator类变为可序列化类&#xff0c;增…

myeclipse开发ssm框架项目图书管理系统 mysql数据库web计算机毕业设计项目

摘 要 随着计算机的广泛应用&#xff0c;其逐步成为现代化的标志。图书馆的信息量也会越来越大&#xff0c;因此需要对图书信息、借书信息、还书信息等进行管理&#xff0c;及时了解各个环节中信息的变更&#xff0c;要对因此而产生的单据进行及时的处理&#xff0c;为了提高高…

吴恩达老师推荐的大模型分析网站 Artificial Analysis

是吴恩达老师推荐的一个提供各大模型的质量、输出速度、价格对比等多维度分析的网站。 比起 LMSYS Chatbot Arena 或者 HF 上的其他竞技场&#xff0c;它们更注重的输出的质量而这个网站其实更利于我们选择一个合适的大模型 API&#xff0c;强烈安利&#xff01;

千帆大模型平台升级十大能力,企业级 RAG 全面升级

7 月 5 日&#xff0c;2024 世界人工智能大会&#xff08;WAIC&#xff09;期间&#xff0c;百度智能云大模型助力新质生产力发展论坛在在上海世博展览馆举办。会上&#xff0c;百度智能云宣布文心大模型 4.0 Turbo&#xff08;ERNIE 4.0 Turbo&#xff09;面向企业客户全面开放…

人工智能在三级淋巴结:肿瘤浸润淋巴细胞领域的系统研究进展|顶刊速递·24-07-08

小罗碎碎念 本期文献主题&#xff1a;人工智能在三级淋巴结/肿瘤浸润淋巴细胞领域的系统分析 关于三级淋巴结和肿瘤浸润淋巴细胞的文献&#xff0c;会是接下来的分析重点&#xff0c;期间也会穿插临床文献&项目复现的推文。 另外再说点科研道路上的题外话&#xff0c;也算是…

GitLab CI/CD实现项目自动化部署

1 GitLab CI/CD介绍 GitLab CI/CD 是 GitLab 中集成的一套用于软件开发的持续集成&#xff08;Continuous Integration&#xff09;、持续交付&#xff08;Continuous Delivery&#xff09;和持续部署&#xff08;Continuous Deployment&#xff09;工具。这套系统允许开发团队…

一手洞悉泰国slot线上游戏投放本土网盟CPI计费广告优势

一手洞悉泰国slot线上游戏投放本土网盟CPI计费广告优势 ​在泰国这个拥有独特文化背景和审美观念的国家&#xff0c;Slots游戏以其丰富的玩法和刺激的体验迅速赢得了玩家们的喜爱。然而&#xff0c;要在竞争激烈的市场中脱颖而出&#xff0c;有效的推广策略显得尤为重要。本土…

JVM专题之垃圾收集器

JVM参数 3.1.1 标准参数 -version -help -server -cp 3.1.2 -X参数 非标准参数,也就是在JDK各个版本中可能会变动 ``` -Xint 解释执行 -Xcomp 第一次使用就编译成本地代码 -Xmixed 混合模式,JVM自己来决定 3.1.3 -XX参数 > 使用得最多的参数类型 > > 非…

Docassemble interview 未授权任意文件读取漏洞复现(CVE-2024-27292)

0x01 产品简介 Docassemble是一款强大的开源工具,主要用于自动化生成和定制复杂文档,特别是在法律文档处理领域表现出色。由Jonathan Pyle个人开发者开发,是一个免费的开源专家系统,用于指导访谈和文档组装。Docassemble基于Python编写,充分利用了Python的灵活性和广泛的…

【论文阅读】-- Visual Traffic Jam Analysis Based on Trajectory Data

基于轨迹数据的可视化交通拥堵分析 摘要1 引言2 相关工作2.1 交通事件检测2.2 交通可视化2.3 传播图可视化 3 概述3.1 设计要求3.2 输入数据说明3.3 交通拥堵数据模型3.4 工作流程 4 预处理4.1 路网处理4.2 GPS数据清理4.3 地图匹配4.4 道路速度计算4.5 交通拥堵检测4.6 传播图…

Spring Cloud: OpenFeign 超时重试机制

超时重试是一种用于网络通信的常用策略&#xff0c;目的是在请求未能在规定时间内获得响应或响应超时的情况下&#xff0c;重新发送请求。具体来说&#xff0c;当发起请求后&#xff0c;如果在设定的时间内未能收到预期的响应&#xff0c;就会启动超时重试机制&#xff0c;重新…

EPICS数据库示例

本文目标是使用EPICS数据库示例帮助新手理解如何使用不同的示例。 1、使用seq和mbbo的简单选择器 这个简单示例展示了如何使用一个mbbo和一个seq来旋转哪个值将被设置到一个PV。 # 这个mbbo记录将选择将运行seq的哪段 record(mbbo, "CHOOSE") {field(VAL, "…

LVS+Nginx高可用集群--基础篇(二)

1.虚拟主机-使用nginx为静态资源提供服务 静态资源服务器&#xff1a;主要包括两类资源&#xff0c;网页&#xff1b;图片&#xff0c;音频等&#xff1b; 也可以通过别名设置静态资源路径。 配置代码&#xff1a; server {listen 88;server_name localhost;locatio…

DFS回溯剪枝|KMP通过数组记录减少判断子字符串|思路

KMP|DFS回溯剪枝 #1、NC149kmp 初步思路&#xff1a; 两层for循环&#xff0c;一个T的字符开始与 S的字符比较&#xff0c;挨个比较&#xff0c;遇到不同就continue当前T的字符&#xff0c;重复步骤》效率太低&#xff0c;超时 eg: TABSABABABD SABABD S&#xff01;A时&#…

四川蔚澜时代电子商务有限公司持续领跑抖音电商

在当今这个数字化飞速发展的时代&#xff0c;电子商务已成为推动经济增长的重要引擎。而在众多电商平台中&#xff0c;抖音电商以其独特的社交属性和年轻化的用户群体&#xff0c;逐渐崭露头角。四川蔚澜时代电子商务有限公司正是这股潮流中的佼佼者&#xff0c;他们专注于抖音…

创建一个AXIS的初始IP核

参考自&#xff1a;https://www.cnblogs.com/milianke/p/17936380.html 以该博主文章为主&#xff0c;本文章做补充。 注意的点&#xff1a; edit ip 在导出axis的主机和从机的时候&#xff0c;记得选择edit ip&#xff0c;这样才能看到从机和主机的源代码&#xff0c;然后…

2024平价蓝牙耳机哪个牌子好?盘点热门平价蓝牙耳机推荐

2024年来&#xff0c;蓝牙耳机市场逐渐走向平价&#xff0c;这使得越来越多的消费者能够轻松拥有一副高性价比的蓝牙耳机。然而&#xff0c;在如此丰富的选择中&#xff0c;2024平价蓝牙耳机哪个牌子好&#xff1f;成为了许多人的烦恼。为了帮助大家更好地了解市场上的热门产品…

8、开发与大模型对话的独立语音设备

一、设计原理 该系统的核心部分主要由ESP32-WROVER开发板和ESP32-CAM摄像头、MAX9814麦克风放大器模块、MAX98357功放、声音传感器和SU-03T语音识别芯片构成。通过使用ESP32-WROVER开发板,用户可以实现通过语音与ai进行交互并进行人脸识别。 系统中,从外部输入电源中获取电源…