网站首页 > java教程 正文
为什么打印
通过打印日志可以了解系统当前的运行状况以及定位线上问题,所以日志打印的时机非常重要。日志打印过多,会导致日志内容过多,影响问题定位的效率和系统性能;日志打印过少缺少关键日志,导致不能在线上定位问题。因此把握日志打印的时机至关重要。
打印日志的时机
1)程序入口、出口(http或者rpc)
在程序调用其他服务或者系统的时候,需要打印接口调用参数、调用结果(成功/失败)、返回结果明细、RT。便于统计和问题排查。
2)程序异常
在程序出现异常的时候,要么选择向上抛出异常,要么必须在catch块中打印异常堆栈信息。有个需要特别注意的地方最好不要重复打印异常日志,比如在catch块里既向上抛出了异常,又去打印错误日志。大量打印堆栈会占用较多的资源。
3)条件分支
程序进入到一些特殊的条件分支时,比如特殊的else或者switch分支。必须打印程序走的流程
public double calcMoneyByAge(int age) {
if (age < 0) {
//理论上年龄不可能小于0,所以需要打印出这种非预期情况或者抛出异常。
logger.("错误的年龄, age:{}", age);
return 0;
}
// ..
}
4)关键执行路径及中间状态
在一些关键的执行路径以及中间状态也需要记录下关键日志信息,比如一个算法可能分为很多步骤,每个步骤的中间输出结果是什么,需要记录下来,以方便后续定位跟踪算法执行状态。
5)调用服务
尤其是写数据的服务,在调用其他服务的请求参数、结果、耗时必须记录。
日志内容与格式
日志打印时机决定了能够根据日志去进行问题定位,而日志的内容决定了是否能够根据日志快速找出问题原因。通常来说,一行日志应该至少包括以下几个组成部分:日志分类标记(场景或者原因)、调用参数(param)、异常堆栈。
话不多说,下面介绍项目中该如何正确的打日志
正确的定义日志
1、使用参数化形式{}占位,[] 进行参数隔离 LOG.debug("Save order with order no:[{}], and order amount:[{}]");
2、输出不同级别的日志 项目中最常用有日志级别是ERROR、WARN、INFO、DEBUG。
几个错误的打日志方式
1、不要使用 System.out.print..
必须通过日志框架来输出日志,而不能使用 System.out.print… 来打印日志,因为这个会打印到 tomcat 控制台,而不会记录到日志文件中,不方便管理日志,会造成磁盘占满、不能查找等问题。
2、不要使用 e.printStackTrace()
它其实也是利用 System.err 输出到了 tomcat 控制台。
3、不要抛出异常后又输出日志
如捕获异常后又抛出了自定义业务异常,此时无需记录错误日志,由最终捕获方进行异常处理。否则会造成重复输出日志。
try {
// ...
} catch (Exception e) {
// 错误
LOG.error("xxx", e);
throw new RuntimeException();
}
4、没有输出全部错误信息
看以下代码,这样不会记录详细的堆栈异常信息,不利于排查问题。
try {
// ...
} catch (Exception e) {
// 错误
LOG.error('XX 发生异常', e.getMessage());
// 正确
LOG.error('XX 发生异常', e);
}
5、使用错误的日志级别
曾经在线上定位一个问题,明明输出了日志啊,为什么找不到…后来排查发现,是这样的:
try {
// ...
} catch (Exception e) {
// 错误
LOG.info("XX 发生异常...", e);
//用 info 记录 error 日志,线上打印ERROR级别的日志,肯定找不到,而且会大量占用性能
}
6、不要在千层循环中打印日志
不要在上千个 for循环中打印日志,这样可能会拖垮你的应用程序,或者严重影响性能。
for(int i=0; i<2000; i++){
LOG.info("XX");
LOG.info(JSON.toJson(obj));
}
7、高性能应用验证日志级别在打印日志(高并发应用重点)、
if(LOG.isInfoEnabled())
{
LOG.info("....");
LOG.info(JSON.toJson(obj));//如果不提前判断,此处序列化仍然执行,但是日志中不输出
}
猜你喜欢
- 2024-10-31 阿里经典面试-java三线程轮流打印A、B、C的ReentrantLock实现
- 2024-10-31 学习廖雪峰的JAVA教程---反射(名叫Class的类、动态加载)
- 2024-10-31 Java案例-求和与打印九九乘法表(用java打印九九乘法口诀)
- 2024-10-31 Java面试题:怎么让两个线程交替打印1和2(生产者消费者问题)
- 2024-10-31 第九章:Java输入输出流和文件操作
- 2024-10-31 Java 自定义注解+AOP 实现日志打印
- 2024-10-31 Java基础学习:java输出整数类型(java分别输出整数和小数)
- 2024-10-31 不懂这些,你敢说自己知道Java标准输入输出流?
- 2024-10-31 Java高阶面试:如何实现三个线程交替循环打印
- 2024-10-31 字节流的输入输出,JAVA基础知识笔记
你 发表评论:
欢迎- 07-15采用Oracle OSB总线进行服务注册和接入
- 07-15javaEE 新闻管理系统 oracle11+tomcat6
- 07-15从Oracle演进看数据库技术的发展(oracle数据库发展史)
- 07-15如何升级oracle数据库安全补丁(oraclepsu补丁升级)
- 07-15【权威发布】关于Oracle WebLogic Server未授权远程代码执行高危漏洞的预警通报
- 07-15【mykit-data】 数据库同步工具(数据库表同步工具)
- 07-15[Java速成] 数据库基础,Connector/J、JDBC、JPA的关系(day 7)
- 07-15Google前工程主管“入住”Oracle(google浏览器找不到以前的书签)
- 最近发表
-
- 采用Oracle OSB总线进行服务注册和接入
- javaEE 新闻管理系统 oracle11+tomcat6
- 从Oracle演进看数据库技术的发展(oracle数据库发展史)
- 如何升级oracle数据库安全补丁(oraclepsu补丁升级)
- 【权威发布】关于Oracle WebLogic Server未授权远程代码执行高危漏洞的预警通报
- 【mykit-data】 数据库同步工具(数据库表同步工具)
- [Java速成] 数据库基础,Connector/J、JDBC、JPA的关系(day 7)
- Google前工程主管“入住”Oracle(google浏览器找不到以前的书签)
- Oracle数据库云服务系列新增前所未有的企业级功能
- 直播预告丨如何实现Oracle存储过程到java的一键转化
- 标签列表
-
- java反编译工具 (77)
- java反射 (57)
- java接口 (61)
- java随机数 (63)
- java7下载 (59)
- java数据结构 (61)
- java 三目运算符 (65)
- java对象转map (63)
- Java继承 (69)
- java字符串替换 (60)
- 快速排序java (59)
- java并发编程 (58)
- java api文档 (60)
- centos安装java (57)
- java调用webservice接口 (61)
- java深拷贝 (61)
- 工厂模式java (59)
- java代理模式 (59)
- java.lang (57)
- java连接mysql数据库 (67)
- java重载 (68)
- java 循环语句 (66)
- java反序列化 (58)
- java时间函数 (60)
- java是值传递还是引用传递 (62)
本文暂时没有评论,来添加一个吧(●'◡'●)