日志记录原则以及logback高级用法

日志记录原则以及logback高级用法

阅读引导

1、良好的日志有助于快速定位问题,但是记录日志很容易臃肿膨胀,记录无用信息。

2、良好的日志,也是后续进行全链路跟踪的分析介质。

3、为自己工作,为自己的系统工作,做自己的老板,形成正循环:打磨当前工作的核心关键能力——>高效能工作——>更多时间打磨自己的系统——>更高效能工作——>打磨下个层次工作的核心关键能力……

4、核心竞争力,是指你拥有的(独特的)知识经验组合,经过你思维逻辑的组织梳理,在实践中产生无可替代的价值。打造自己的TMS系统(T:专业技术;M:沟通管理、S:行业解决方案),利用复利效应,让系统为自己工作。

目前常用的日志框架是logback、log4j2这两个。

logback是在log4j的基础上进行的升级,而log4j2是参考logback的长处进行的升级。

log4j2号称性能提升巨大。

不过目前还是选择logback框架,首先是目前记录日志并没有影响TPS,另外springboot等开源框架都在使用logback,如果不是极端情况还是使用logback。

logback的基础用法,不再赘述,请读者自行搜索。

当然,为了很快的替换,应用中应该使用SLF4J这个日志facade模式框架,而不是具体的实现。

具体来说,Logger的声明,使用SLF4J的类声明。

日志记录原则

日志,是用来查找问题的。

应用日志的核心目标,就是发现问题时,进行查询搜索。

以此定位的话,有下面几个原则

日志内容,尽量少而完整

首先是通过配置,日志框架就可以记录的静态内容:时间、日志级别、线程、class路径等。

最主要的是:上下文信息

例如,如果报错error日志,要记录入参、详细的报错异常堆栈、核心中间数据等。

达到一个目标,就是通过日志信息,可以很快的还原现场,不需要再人工去梳理推断流转到此处代码的逻辑信息。

初级程序员往往直接把Exception扔打印方法里面,导致日志中只有报错现象,而没有数据。

难以分析。

日志时机

首先是:异常、错误等地方使用error级别日志。

其次,核心组件的关键动作使用info级别日志。

第三,可以容错的处理,记录warn级别日志。

日志格式

格式一般是在logback.xml配置文件中配置。

可以按照企业内部要求,或者结合应用接口汇总涉及到的字段来记录。

日志分析

日志要经常分析。对于error级别日志,重点考虑,分析原因;对于warn级别日志,查看容错处理的情况,是否可以避免;对于info级别的日志,是否有必要,是否可以不记录?目前日志的读写到文件,需要占用I/O资源,最好尽可能的少。

log高级用法

介绍一些logback提供的功能,借以封装实现个性化需求。

​ logback的contextListener日志系统初始化

我们需要在logback中做一些动态配置,比如日志等级、输出路径等,这些信息可以存放在数据库中,启动时加载,可以用logback自带的contextListener。

public class LoggerStartupListener extends ContextAwareBase implements LoggerContextListener, LifeCycle

然后配置到logback.xml中,日志系统初始化之前就会使用这个个性化的listener

<contextListener class="com.…….LoggerStartupListener" />

logback的封装使用(如果性能要求高,不推荐)

下面是普通的日志方式:

private final static Logger logger = LoggerFactory.getLogger(App.class);
logger.debug("what")

但是每一个类都这么写,真是非常繁琐。

可以做一下如下的封装,logger做一个静态工具类使用:

class LogToolFactory {
	/**
	 * 获取Logger
	 * @param clazz LoggerTool的 class
	 * @return
	 */
	public static Logger getLogger(Class clazz) {
		String invokerClassName = getInvokerClassName(clazz);

		// 获取前一个stackTrace,即LoggerTool的调用者类
		try {
			return LoggerFactory.getLogger(Class.forName(invokerClassName));
		} catch (ClassNotFoundException e) {
			throw new RuntimeException("找不到:" + invokerClassName + ",初始化logger失败: " + e.getStackTrace());
		}
	}

	/**
	 * 通过堆栈,获取调用者类名
	 * @param clazz 被调用者class
	 * @return 调用者类名
	 */
	private static String getInvokerClassName(Class clazz) {
		StackTraceElement[] stackTrace = Thread.currentThread().getStackTrace();

		// 获取LoggerTool 在堆栈中的索引
		int loggerToolIndex = 0;
		for (int i=0; i<stackTrace.length; i++) {
			String className = stackTrace[i].getClassName();
			if(clazz.getName().equals(className)) {
				loggerToolIndex= i;
			}
		}
		String invokerClassName = stackTrace[loggerToolIndex + 1].getClassName();
		return invokerClassName;
	}

	private LogToolFactory() {
	}

}
public class LogTool {
	private static final Class clazz = LogTool.class;

	public static String getName() {
		Logger logger = LogToolFactory.getLogger(clazz);
		return logger.getName();
	}

	public static void trace(String msg) {
		Logger logger = LogToolFactory.getLogger(clazz);
		logger.trace(msg);
	}
    ……

但是,使用了StackTraceElement[] stackTrace = Thread.currentThread().getStackTrace();

在交易量非常大的情况下,会有性能问题。

对于普通的应用可以尝试。

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值