热门标签 | 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相关文章


推荐阅读
  • 本文介绍了如何使用Flume从Linux文件系统收集日志并存储到HDFS,然后通过MapReduce清洗数据,使用Hive进行数据分析,并最终通过Sqoop将结果导出到MySQL数据库。 ... [详细]
  • Hadoop的文件操作位于包org.apache.hadoop.fs里面,能够进行新建、删除、修改等操作。比较重要的几个类:(1)Configurati ... [详细]
  • 本文详细介绍了在 CentOS 7 系统中配置 fstab 文件以实现开机自动挂载 NFS 共享目录的方法,并解决了常见的配置失败问题。 ... [详细]
  • oracle c3p0 dword 60,web_day10 dbcp c3p0 dbutils
    createdatabasemydbcharactersetutf8;alertdatabasemydbcharactersetutf8;1.自定义连接池为了不去经常创建连接和释放 ... [详细]
  • MySQL 5.7 学习指南:SQLyog 中的主键、列属性和数据类型
    本文介绍了 MySQL 5.7 中主键(Primary Key)和自增(Auto-Increment)的概念,以及如何在 SQLyog 中设置这些属性。同时,还探讨了数据类型的分类和选择,以及列属性的设置方法。 ... [详细]
  • 如何在Java中使用DButils类
    这期内容当中小编将会给大家带来有关如何在Java中使用DButils类,文章内容丰富且以专业的角度为大家分析和叙述,阅读完这篇文章希望大家可以有所收获。D ... [详细]
  • 开发日志:高效图片压缩与上传技术解析 ... [详细]
  • 在PHP中如何正确调用JavaScript变量及定义PHP变量的方法详解 ... [详细]
  • 技术分享:使用 Flask、AngularJS 和 Jinja2 构建高效前后端交互系统
    技术分享:使用 Flask、AngularJS 和 Jinja2 构建高效前后端交互系统 ... [详细]
  • Web开发框架概览:Java与JavaScript技术及框架综述
    Web开发涉及服务器端和客户端的协同工作。在服务器端,Java是一种优秀的编程语言,适用于构建各种功能模块,如通过Servlet实现特定服务。客户端则主要依赖HTML进行内容展示,同时借助JavaScript增强交互性和动态效果。此外,现代Web开发还广泛使用各种框架和库,如Spring Boot、React和Vue.js,以提高开发效率和应用性能。 ... [详细]
  • 深入探索HTTP协议的学习与实践
    在初次访问某个网站时,由于本地没有缓存,服务器会返回一个200状态码的响应,并在响应头中设置Etag和Last-Modified等缓存控制字段。这些字段用于后续请求时验证资源是否已更新,从而提高页面加载速度和减少带宽消耗。本文将深入探讨HTTP缓存机制及其在实际应用中的优化策略,帮助读者更好地理解和运用HTTP协议。 ... [详细]
  • 使用Maven JAR插件将单个或多个文件及其依赖项合并为一个可引用的JAR包
    本文介绍了如何利用Maven中的maven-assembly-plugin插件将单个或多个Java文件及其依赖项打包成一个可引用的JAR文件。首先,需要创建一个新的Maven项目,并将待打包的Java文件复制到该项目中。通过配置maven-assembly-plugin,可以实现将所有文件及其依赖项合并为一个独立的JAR包,方便在其他项目中引用和使用。此外,该方法还支持自定义装配描述符,以满足不同场景下的需求。 ... [详细]
  • 在试用版软件中,为了提升用户体验并有效提醒用户剩余的使用次数,本文通过Java IO文件操作实现了一个试用版软件的使用次数提示机制。具体而言,每次启动软件时,程序会读取存储在文件中的剩余使用次数,并在每次执行后更新该数值。当用户启动软件时,系统会显示当前剩余的使用次数,确保用户清楚了解自己的试用状态。该机制不仅提高了软件的友好性,还增强了用户的购买意愿。 ... [详细]
  • Java能否直接通过HTTP将字节流绕过HEAP写入SD卡? ... [详细]
  • 在Android应用开发中,实现与MySQL数据库的连接是一项重要的技术任务。本文详细介绍了Android连接MySQL数据库的操作流程和技术要点。首先,Android平台提供了SQLiteOpenHelper类作为数据库辅助工具,用于创建或打开数据库。开发者可以通过继承并扩展该类,实现对数据库的初始化和版本管理。此外,文章还探讨了使用第三方库如Retrofit或Volley进行网络请求,以及如何通过JSON格式交换数据,确保与MySQL服务器的高效通信。 ... [详细]
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社区 版权所有