热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

JavaforWeb学习笔记(四九):Log(1)log很重要

为何要log如何写好log,是程序员的必修课。比较通用的方式是Apache的log4j2,和第一个版本log4j相比,log的等级更多,可以准实时在运行过程中修改log登记,适合在发现问题时提升等

为何要log

  如何写好log,是程序员的必修课。比较通用的方式是Apache的log4j2,和第一个版本log4j相比,log的等级更多,可以准实时在运行过程中修改log登记,适合在发现问题时提升等级,获取更详细的log,而平时采用一般等级。

  不推荐使用System.out的方式:

  1. 没有等级区分,很可能会影响程序的性能
  2. 不能提供类名,代码行(一般错误定位才打开,生产环节中缺省不打开)的额外信息
  3. System.out将输出在catalina.out中,如果tomcat运行若干个web app,这些信息会混在一起。

  我会要求在提交版本时,禁止System.out的方式。另外应该log哪些信息也很重要,有些开发人员会log某个对象的值,这些应该是开发调测时跟踪代码用的,在开发时可以使用IDE的断点调测,记录log或者System.out也可以,但是作为提交的版本,这就不是关键信息。再优秀的程序员有会犯错的,生产环节碰到的奇奇怪怪的情况,有时很难在代码阶段想到。不要将log等同于开发调测,还用于版本上线的异常/错误跟踪、重要数据变更记录(如配置变更),性能跟踪,记录与其他模块/接口的交换信息(这个很重要,常碰到一类开发人员,总认为自己的代码不会有错,错的都是别人,我会要求给出抓包证明,或者log信息,根据交互数据定位错误。)。

要log什么

  要log哪些信息,看项目需求,但是有些基本原则:

  • web app崩溃或者异常退出需要尽可能详细的信息,如 messages, stack traces, thread dumps, 甚至heap dumps;但问题在于如果crash了,我们加在程序中的log也就写不出来,这时需要JVM的工具。以OpenJDK JVM为例,可以在在运行命令中加入一下参数,例如-XX:+HeapDumpOnOutOfMemoryError,记录内存溢出的错误。
  • 出现error时,应记录error有关的任何信息(type,message, stack trace, app对error的处理)。注意,所有的重要信息记录在log,而显示给用户只是最小的错误信息,告知出错即可,不要泄漏任何的系统信息,如文件路径,SQL查询语句等等。Tomcat中500会给出详细的错误信息,这对我们调测很有作用,但是作为生产系统,hackers可以重中获取敏感信息。
  • 有时问题不会影响处理,可以继续,但需要提醒注意,作为warn,记录相关的状态,信息,和app的处理,甚至包括stack trace。
  • 重要事件,例如创建实体,启动部件,用户成功登陆,系统状态等等。
  • 当跟踪某个问题是,可能会希望看到相关的执行方法,参数等,但需要注意,我们并不需要总能看到这些信息,产生这些信息会影响性能。(这就是运行时可修改显示级别的意义,也就是为何log4j的版本为2。)极端的情况下,对每个方法的输入和输出进行尽量,一旦出现loop,就是极大的性能负担,我们应该减少这类log。
  • 审计(例如syslog)就是某种方式的log。

Log在哪里

  log不一定在文件,还有很多方式,也可以同时log在多个地方,采用同步或者异步的方式,甚至有时如果log失败就不继续执行动作。Log输出一般有以下几种方式(我们可以同时采用某些)

  1. Console:实时调测机制,输出在stdout,等同System.out.println(),在tomcat中,也同时输出到catalina.out文件。就单纯console而言,console buffer满后,相关信息我们就看不到,因此通常在开发过程中使用,又或者其他的log输出方式失效时,即在log故障时采用。
  2. Flat Files:可以看历史记录,但是很难做信息过滤或筛选。这些记录格式可以采用XML(但会造成文件很大),JSON,syslog(在Windows则为Windows Event Log)。一般文件可以滚动存放,以tomcat自己的log为例,按日期存储。
  3. Sockets:比较少用,通过socket输出到其他地方。(以前一个项目通过socket直接输出到图形界面中,提供给运维人员,通常只限于交互消息或协议消息跟踪,例如SIP)
  4. SMTP和SMS:通过邮件和短信发送。在之前一个项目中,申请了一个微信公众号,将认为重要的告警信息推送到公众号上,通知运维人员赶紧上去看看出啥事,另外也定期将业务的统计信息推送过来。我是觉得挺方便的。
  5. 数据库:是一种常用方式,优点是容易进行过滤,缺点是写数据库比写文件性能要差点,存储要多点,如果部署在云端,云数据库要贵点,为了log不太值得,解决这些缺点,可以采用非关系型数据库,例如MongoDB,以二进制JSON(BSON)格式来节省空间。此外MongoDB以牺牲读性能(在大量数据中过滤慢)来换取高的写性能(insert数据比SQL要快),减少对程序性能的影响。

Log等级和类别

  log等级相当于相对重要程度或者详细程度,log类型则与内容有关,我们不仅需要等级,很多时候也会需要类别对log内容进行筛选。

Log level

  log等级定义log的相对重要程度。有时是整数,有时是明确语义的字符串。等级的定义并没有什么标准,下面是java.util.logging.Level的规定:

常用名字 Level常量 说明
Fatal Error / Crash -- 最严重的错误。通常那些可以导致崩溃或者过早中断程序
Error SEVERE 表明有严重问题的产生
Warning WARNING 表明有某事件发生,有可能导致问题,需要查看
Information INFO 对程序监控或者调测有用的信息。
Configuration Details CONFIG 详细的配置信息,通常在应用或者器件启动时出现。
Debug FINE 给出调测信息,通常包括变量的值
Trace Level 1
Trace Level 2
FINER
FINEST
不通级别的应用跟踪。很多log框架只有1个trace级别。
例如FINER用来记录执行SQL语句,而FINEST用来记录调用的方法或方法结束。

  在Apache HTTPD 2.2中log等级为emerg, alert, crit, error, warn, notice, info和debug,在2.4中增加trace1~trace8。如何划分等级视乎项目的需要。

Log分类和筛选

  在绝大部的java log场景中,log分类同时就是log实例的名字,例如java class的名字,一个类一个log实例。使用不同的log分类可以有不同的log呈现级别,例如一个是trace,一个是warn。

  对于一些log系统,可以有层次结构,一个log可以继承另一个log,添加一些级别。

  和log分类的比较相似,log筛选将不同类型和产生源的时间可以log在不同的位置。而log分类通常定义不同的log级别而非不同的位置。其实也没有必要对着两者太严格区分,都是有助于我们过滤。

选择Logging framework

  如果我们不打算重新造轮子,可以选择第三方的logging framework。我们希望能有灵活的输出,例如不需要改动我们的程序,就可以将输出从文件变更为数据库,换言之,API固定,而可以有不同的实现。java.util.logging就是这样的好例子,可以写文件,流,socket,console,设置memory。然而我们很少使用java.util.logging,它最大的缺点是,配置是通过系统,而不是在classpath,这导致在同一web容器的两个web app不能有不同的log设置,除非浏览器扩展了基础的log实现。Tomcat进行了扩展,但是不是所有的容器都这样,但我们最好能在自己的app中解决问题。

  选择的另一个考虑是性能。调用一个debug的log不应消耗毫秒级时间,而应该是纳秒级别,我们可以通过关闭所有的log,来审视性能的影响。

  有两个比较好的开源logging framework:

  • Log4j:http://commons.apache.org/proper/commons-logging/ 或者http://logging.apache.org/log4j/2.x/ ,Apache Commons Logging
  • Slf4j:http://www.slf4j.org/ ,Simple Logging Facade for java。

  对于Maven,建议对API使用compile,而实现使用runtime,这样避免应用直接使用底层的实现,在运行时,根据配置采用具体的实现。


相关链接: 我的Professional Java for Web Applications相关文章


推荐阅读
  • Hadoop 2.6 主要由 HDFS 和 YARN 两大部分组成,其中 YARN 包含了运行在 ResourceManager 的 JVM 中的组件以及在 NodeManager 中运行的部分。本文深入探讨了 Hadoop 2.6 日志文件的解析方法,并详细介绍了 MapReduce 日志管理的最佳实践,旨在帮助用户更好地理解和优化日志处理流程,提高系统运维效率。 ... [详细]
  • 在尝试启动Java应用服务器Tomcat时,遇到了org.apache.catalina.LifecycleException异常。本文详细记录了异常的具体表现形式,并提供了有效的解决方案。 ... [详细]
  • 本文总结了一次针对大厂Java研发岗位的面试经历,探讨了面试中常见的问题及其背后的原因,并分享了一些实用的面试准备资料。 ... [详细]
  • Centos7 Tomcat9 安装笔记
    centos7,tom ... [详细]
  • 如何正确配置与使用日志组件:Log4j、SLF4J及Logback的连接与整合方法
    在当前的软件开发实践中,无论是开源项目还是日常工作中,日志框架都是不可或缺的工具之一。本文详细探讨了如何正确配置与使用Log4j、SLF4J及Logback这三个流行的日志组件,并深入解析了它们之间的连接与整合方法,旨在帮助开发者高效地管理和优化日志记录流程。 ... [详细]
  • Mybatis_04日志
    前几天临近期末考试,一直在准备考试,吐槽一下,这个学期的考试真是全背书,服了,背吐了。考完试到元旦又放肆了几天 ... [详细]
  • spring boot使用jetty无法启动 ... [详细]
  • 流处理中的计数挑战与解决方案
    本文探讨了在流处理中进行计数的各种技术和挑战,并基于作者在2016年圣何塞举行的Hadoop World大会上的演讲进行了深入分析。文章不仅介绍了传统批处理和Lambda架构的局限性,还详细探讨了流处理架构的优势及其在现代大数据应用中的重要作用。 ... [详细]
  • 每种编程语言都有其独特的完成任务的方式,这也说明了为什么有这么多语言可供选择。在JimHall的《不同的编程语言如何完成相同的事情》文章中,他演示了13种不同的语言如何使用不同的语 ... [详细]
  • 在Effective Java第三版中,建议在方法返回类型中优先考虑使用Collection而非Stream,以提高代码的灵活性和兼容性。 ... [详细]
  • 提升工作效率:掌握15个键盘快捷键
    在日常工作中,熟练掌握计算机操作技巧能够显著提升工作效率。本文将介绍15个常用的键盘快捷键,帮助用户更加高效地完成工作任务。 ... [详细]
  • 本文总结了近年来在实际项目中使用消息中间件的经验和常见问题,旨在为Java初学者和中级开发者提供实用的参考。文章详细介绍了消息中间件在分布式系统中的作用,以及如何通过消息中间件实现高可用性和可扩展性。 ... [详细]
  • Eclipse 编译错误:无法解析为类型,详细解决方法与常见原因分析
    在Eclipse开发环境中,编译错误“无法解析为类型”通常出现在以下情况:1. 之前运行正常的Eclipse项目,原始JDK版本为1.6;2. 系统中安装了新的JDK版本。本文将详细分析该错误的常见原因,并提供有效的解决方法,帮助开发者快速定位和解决问题。 ... [详细]
  • 在Java应用程序中调用`response.getStatus()`方法时遇到了`NoSuchMethodError`异常,经过分析,初步判断为依赖冲突问题。通过检查项目依赖树发现,当前项目版本与某些库的版本不兼容,导致该方法无法被正确识别。建议通过更新相关依赖版本或使用依赖管理工具(如Maven或Gradle)来解决此问题,确保所有依赖项版本一致且兼容。 ... [详细]
  • 深入解析MyBatis的高级映射技术
    在前一章节中,我们探讨了MyBatis的基本对象映射方法,其中对象属性与数据库表字段之间实现了直接的一对一映射。然而,在实际开发中,这种简单的映射方式往往难以满足复杂业务需求。本文将深入分析MyBatis的高级映射技术,介绍如何通过配置和注解实现更为灵活的对象与数据库表之间的映射关系,包括嵌套结果、联合查询和动态SQL等高级功能,以提高开发效率和代码可维护性。 ... [详细]
author-avatar
手机用户2502853267
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有