首先记录异常的根本原因

Logback日志库的0.9.30版本带来了一个很棒的新功能:从根(最内部)异常而不是最外部异常开始记录堆栈跟踪。 当然,我的兴奋与我贡献了此功能无关。

用塞西尔·德·米勒(Cecil B. de Mille) 的话来解释:“撰写博客文章的方法是从堆栈跟踪开始,直到达到高潮 ” –在这里:

详细信息还不重要,但是从100英尺视图中您可以看到很长的堆栈跟踪,并且有多个相互包裹的异常( 引起 )。 我们将回到此堆栈跟踪,但首先要介绍一些基础知识。 如果抛出异常,则会以某种方式记录日志,以显示异常发生时瞬间堆栈的外观。 在最底部,您将看到静态的main()Thread.run() ,该方法通过调用直到第一个堆栈跟踪行的方法进行处理,该行指示实际抛出异常的位置。 这非常方便,因为您可以看到导致异常的整个控制流程:

public class BookController {private final BookService bookService = new BookService();public void alpha() { beta(); }private void beta() { gamma(); }private void gamma() { bookService.delta(); }public static void main(String[] args) {new BookController().alpha();}
}class BookService {private final BookDao bookDao = new BookDao();public void delta() { epsilon(); }private void epsilon() { zeta(); }private void zeta() { bookDao.eta(); }
}class BookDao {public void eta() { theta(); }private void theta() { iota(); }public void iota() { throw new RuntimeException("Omega server not available"); }
}

如果您不知道希腊字母 ,则可以从堆栈跟踪中开始学习(请记住,控制流从底部开始并一直向上):

java.lang.RuntimeException: Omega server not availableat BookDao.iota(BookController.java:50)at BookDao.theta(BookController.java:48)at BookDao.eta(BookController.java:46)at BookService.zeta(BookController.java:41)at BookService.epsilon(BookController.java:39)at BookService.delta(BookController.java:37)at BookController.gamma(BookController.java:22)at BookController.beta(BookController.java:20)at BookController.alpha(BookController.java:18)at BookController.main(BookController.java:26)

太好了吧? 从上到下阅读时,您可以说: iota()由theta()调用,而eta()则调用…清晰而简单。 但是,如果有人决定包装原始异常并重新抛出该异常怎么办?

public class BookController {private static final Logger log = LoggerFactory.getLogger(BookController.class);private final BookService bookService = new BookService();public void alpha() { beta(); }private void beta() { gamma(); }private void gamma() {try {bookService.delta();} catch (Exception e) {throw new RuntimeException("Sorry, try again later", e);}}public static void main(String[] args) {try {new BookController().alpha();} catch (Exception e) {log.error("", e);}}
}class BookService {private final BookDao bookDao = new BookDao();public void delta() { epsilon(); }private void epsilon() { zeta(); }private void zeta() {try {bookDao.eta();} catch (Exception e) {throw new RuntimeException("Unable to save order", e);}}
}class BookDao {public void eta() { theta(); }private void theta() { iota(); }public void iota() {try {throw new RuntimeException("Omega server not available");} catch (Exception e) {throw new RuntimeException("Database problem", e);}}
}

现在快速:在堆栈跟踪中找到根本原因!

java.lang.RuntimeException: Sorry, try again laterat BookController.gamma(BookController.java:26)at BookController.beta(BookController.java:20)at BookController.alpha(BookController.java:18)at BookController.main(BookController.java:32)
Caused by: java.lang.RuntimeException: Unable to save orderat BookService.zeta(BookController.java:51)at BookService.epsilon(BookController.java:45)at BookService.delta(BookController.java:43)at BookController.gamma(BookController.java:24)... 8 common frames omitted
Caused by: java.lang.RuntimeException: Database problemat BookDao.iota(BookController.java:66)at BookDao.theta(BookController.java:60)at BookDao.eta(BookController.java:58)at BookService.zeta(BookController.java:49)... 11 common frames omitted
Caused by: java.lang.RuntimeException: Omega server not availableat BookDao.iota(BookController.java:64)... 14 common frames omitted

原来main()不再是最后一行。 更糟糕的是,一切似乎都出现了乱码,请尝试再次阅读希腊字母…现在让我们回到原始的堆栈跟踪中。 它来自Spring框架启动失败,想象它可能长达数页。

为了方便起见,我添加了箭头来标记您重构控制流所应遵循的路径:从红色箭头的尾部( Thread.run() )开始,在中间的某个位置向上,然后…跳至橙色箭头的尾部。 从橙色箭头的头部跳到绿色箭头的尾巴,依此类推...不是很直观,您不觉得吗? 这个红色的椭圆显示了什么? 是的,这是失败的根本原因(最内部的异常)。 另一方面,在最开始打印的异常(通常是您一开始就读到的异常 )说明了创建DefaultAnnotationHandlerMapping#0时发生的错误 (是什么?)真正的错误( 没有匹配的bean类型…… )被巧妙地隐藏了……

那么这个新功能到底是什么呢? 还是我们的简单例子。 升级到0.9.30之后,只需在日志记录模式的末尾添加%rEx (或等效的%rootException ):

<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender"><encoder><pattern>%d{ISO8601} | %-5level | %thread | %logger{1} | %m%n%rEx</pattern></encoder>
</appender>

这将用我亲自贡献的默认堆栈跟踪打印路由代替。 现在将打印相同的希腊程序:

java.lang.RuntimeException: Omega server not availableat BookDao.iota(BookController.java:64)
Wrapped by: java.lang.RuntimeException: Database problemat BookDao.iota(BookController.java:66)at BookDao.theta(BookController.java:60)at BookDao.eta(BookController.java:58)at BookService.zeta(BookController.java:49)
Wrapped by: java.lang.RuntimeException: Unable to save orderat BookService.zeta(BookController.java:51)at BookService.epsilon(BookController.java:45)at BookService.delta(BookController.java:43)at BookController.gamma(BookController.java:24)
Wrapped by: java.lang.RuntimeException: Sorry, try again laterat BookController.gamma(BookController.java:26)at BookController.beta(BookController.java:20)at BookController.alpha(BookController.java:18)at BookController.main(BookController.java:32)

请仔细将其与先前的输出进行比较。 首先,第一行指出了问题所在。 在大多数情况下,您可能都不会跳过“ 由...引起的 ”例外,因此可能会跳过其余部分。 其次,控制流是不间断且连续的–您仍然可以从上至下阅读,反之亦然。 最后但并非最不重要的一点是–同时保留了异常被包裹的事实,但不会使堆栈跟踪混乱。

现在您应该看到利用%rEx打印的原始Spring异常:

观察结果完全相同:问题的根本原因从一开始就出现,从而缩短了需要研究问题的时间。 同样,在分析控制流时,不会跳跃-Thread.main()位于底部,您可以连续读取底部到顶部的轨迹。

如果您使用堆栈跟踪(在开发中或在生产/支持中)进行大量工作–请考虑切换到根本原因优先日志记录。 每次您分析特定异常时,它将节省您几秒钟的时间。 但是我还注意到,经验不足的开发人员有时甚至不知道“ 由...引起的 ”规则: 找到第一个异常并查看最后一个“由...引起的” –仍然不清楚问题到底是什么,仅查看最外部,最不具体,最通用的错误。 这也将对他们有帮助。

顺便说一下,如果您完全避免包装和重新抛出异常,则可以避免所有这些麻烦。 我知道,我们经常会因检查异常而被迫这么做……

参考: 日志异常的根源首先来自我们的JCG合作伙伴Tomek Nurkiewicz,位于NoBlogDefFound

编码愉快! 不要忘记分享!

相关文章:

  • Java日志混乱
  • 正确记录应用程序的10个技巧
  • 使用AspectJ,Javassist和Java Proxy进行代码注入的实用介绍
  • Java最佳实践系列
  • 每个程序员都应该知道的事情
  • 生存在狂野西部开发过程中的9条提示
  • 软件设计法则

翻译自: https://www.javacodegeeks.com/2011/09/logging-exceptions-root-cause-first.html

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

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

相关文章

Android 中的 Service 全面总结

1、Service的种类 按运行地点分类&#xff1a; 类别区别 优点缺点 应用本地服务&#xff08;Local&#xff09;该服务依附在主进程上&#xff0c; 服务依附在主进程上而不是独立的进程&#xff0c;这样在一定程度上节约了资源&#xff0c;另外Local服务因为是在同一进程因此不…

找出互联网类似以下图的实例

转载于:https://www.cnblogs.com/sghcjy/p/4978851.html

使用Spring MVC开发Restful Web服务

REST简介 摘自Wikipedia&#xff1a; REST风格的体系结构由客户端和服务器组成。 客户端向服务器发起请求&#xff1b; 服务器处理请求并返回适当的响应。 请求和响应围绕资源表示的传递而构建。 资源本质上可以是可以解决的任何连贯且有意义的概念。 正如您所阅读的&#xff0…

端到端测试的滥用–测试技术2

我的上一个博客是有关测试代码方法的一系列博客中的第一篇&#xff0c;概述了使用一种非常常见的模式从数据库检索地址的简单方案&#xff1a; …并描述了一种非常通用的测试技术&#xff1a; 不编写测试 &#xff0c; 而是手动进行所有操作。 今天的博客涵盖了另一种实践&…

那些年困扰我们的Linux 的蠕虫、病毒和木马

虽然针对Linux的恶意软件并不像针对Windows乃至OS X那样普遍&#xff0c;但是近些年来&#xff0c;Linux面临的安全威胁却变得越来越多、越来越严重。个中原因包括&#xff0c;手机爆炸性的普及意味着基于Linux的安卓成为恶意黑 客最具吸引力的目标之一&#xff0c;以及使用Lin…

(转)FPGA异步时序和多时钟模块

http://bbs.ednchina.com/BLOG_ARTICLE_3019907.HTM 第六章 时钟域 有一个有趣的现象&#xff0c;众多数字设计特别是与FPGA设计相关的教科书都特别强调整个设计最好采用唯一的时钟域。换句话说&#xff0c;只有一个独立的网络可以驱动一个设计中所有触发器的时钟端口。虽然…

怎么检测不到我的音频_Linux 上的最佳音频编辑工具推荐 | Linux 中国

在 Linux 上&#xff0c;有很多种音频编辑器可供你选用。不论你是一个专业的音乐制作人&#xff0c;还是只想学学怎么做出超棒的音乐的爱好者&#xff0c;这些强大的音频编辑器都是很有用的工具。-- Ankush Das(作者)在 Linux 上&#xff0c;有很多种音频编辑器可供你选用。不论…

具有GlassFish和一致性的高性能JPA –第3部分

在我的四部分系列的第三部分中&#xff0c;我将解释将Coherence与EclipseLink和GlassFish结合使用的第二种策略。 这就是通过EclipseLink使用Coherence作为二级缓存&#xff08;L2&#xff09;的全部内容。 一般的做法 这种方法将Coherence数据网格应用于依赖于无法完全预加载到…

精选30道Java笔试题解答(转)

都是一些非常非常基础的题&#xff0c;是我最近参加各大IT公司笔试后靠记忆记下来的&#xff0c;经过整理献给与我一样参加各大IT校园招聘的同学们&#xff0c;纯考Java基础功底&#xff0c; 老手们就不用进来了&#xff0c;免得笑话我们这些未出校门的孩纸们&#xff0c;但是I…

list取值_Redis中List及quicklist实现-2

上一篇中看了List的使用方式、quicklist中的各个结构体&#xff0c;这一篇来看看quicklist里面的几个核心函数&#xff0c;quicklistCreate函数、quicklistCreateNode函数、quicklistPush函数、quicklistPop函数。接下来我们通过源码看一下quicklist中是如何借鉴STL中deque的这…

通过示例休眠–第1部分(删除孤儿)

所以我想做一系列的冬眠例子&#xff0c;展示冬眠的各种特征。 在第一部分中&#xff0c;我想展示有关删除孤儿功能及其在故事情节中的使用方法。 因此&#xff0c;让我们开始:) 先决条件 &#xff1a; 为了尝试以下示例&#xff0c;您将需要以下提到的JAR文件&#xff1a; …

Win10手记-IIS部署网站问题解决

最近在自己的Win10电脑上尝试部署ASP.NET网站时出现了问题&#xff0c;经过多方查找定位到IIS为问题来源。 开始之前 先描述下技术环境&#xff1a; 1.Windows 10 PC 2.Windows 自带的IIS 7 3.ASP.NET Web API项目网站 4.VS 2015 问题描述 首先我们为PC安装IIS&#xff0c;按照…

CentOS 7 安装记录

由于centos6.4版本有点老&#xff0c;所以换到centos7。 1.安装 CentOS 7.0系统安装配置图解教程 2.linux设置网卡开机启动 实质linux是看一个网卡文件的配置&#xff0c;就是/etc/sysconfig/network-scripts/ifcfg-eth0 (这个文件名看你网卡名称而异&#xff0c;具体你到该目录…

通知栏发送消息Notification(可以使用自定义的布局)

一个简单的应用场景&#xff1a;假如用户打开Activity以后&#xff0c;按Home键&#xff0c;此时Activity 进入-> onPause() -> onStop() 不可见。代码在此时机发送一个Notification到通知栏。当用户点击通知栏的Notification后&#xff0c;又重新onRestart() -> onSt…

退出页面删除cookie_Cookie 机制

欢迎关注公众号 学习资料不会少01「HTTP 协议是无状态的」对于浏览器的每一次请求&#xff0c;服务器都会独立处理&#xff0c;不与之前或之后的请求发生关联。这个过程如图 11-1 所示&#xff0c;3次“请求&#xff0f;响应”之间没有任何关系。即使是同一个浏览器发送了3个请…

Oracle WebLogic Java云服务–幕后花絮。

在开放世界方面&#xff0c;发生的一件大事可能是出乎意料的消息&#xff0c;那就是Oracle最终支持云计算发展并提供自己的公共云服务 。 除了官方公告之外&#xff0c;Aquarium上&#xff08; 此处和此处 &#xff09;的内容或多或少都没有多少内容&#xff0c;您找不到很多信…

QT子窗口及停靠实现

Demo的效果 头文件中的变量声明 //退出动作QAction* exit;//菜单栏菜单QMenu* filemenu;QMenu* actiona;//在状态栏的标签控件QLabel* label;//两个停靠窗口QDockWidget *dockwidget;QDockWidget *dockwidget_textbox; CPP源文件中的对象定义 //创建初始化按钮,将要放到第一个窗…

Html转Word文档,解决无法保存网络图片的问题

最近项目中需要这个功能&#xff0c;网上有很多word转html的方法&#xff0c;但是html转word的方法很少&#xff0c;因为html中的图片转换到本地比较麻烦&#xff1b; 开始的时候只能转换不带图片的html内容&#xff0c;但是不符合要求&#xff0c;将html页面中的图片改成绝对路…

Android实现推送方式解决方案

Android实现推送方式解决方案 本文介绍在Android中实现推送方式的基础知识及相关解决方案。推送功能在手机开发中应用的场景是越来起来了&#xff0c;不说别的&#xff0c;就我们手机上的新闻客户端就时不j时的推送过来新的消息&#xff0c;很方便的阅读最新的新闻信息。这种推…

java基础知识系列---垃圾收集

1 为什么要使用垃圾回收机制&#xff1f; “垃圾收集”暗示程序不再需要的对象就是垃圾&#xff0c;可以被丢弃。更精确&#xff0c;更新的说法是“内存回收”。 1.1 新对象的使用 当一个对象不再被程序所引用时&#xff0c;他所使用的堆空间可以被回收&#xff0c;以便于被后续…