当前位置: 首页 > 后端技术 > Java

日志别再乱了,这份Java日志规范应有尽有,推荐收藏!!

时间:2023-04-01 18:00:28 Java

1简介在程序中写日志非常重要,但很容易被开发者忽视。把程序的日志写下来,可以帮助我们大大减轻后期维护的压力。在实际工作中,开发人员往往承受着巨大的时间压力,而编写日志是一项非常繁琐的工作,往往没有引起足够的重视。开发者应从一开始就养成良好的日志写入习惯,在实际开发工作中应预留足够的日志写入时间。1.1日志的作用一般的程序日志来源于以下需求:审计日志记录用户操作,有时甚至是监管部门的需求。快速定位问题根源,跟踪程序执行过程。跟踪数据变化数据统计和性能分析收集和运行环境数据一般是在程序上线之后。一旦出现异常,首先要做的就是搞清楚当时发生了什么。用户当时做了什么操作,环境有没有受到影响,数据有什么变化,是否反复发生等等,再进一步判断是哪方面的问题。确定是程序问题后,交由开发者重现、研究、提出解决方案。这个时候,日志就为我们提供了第一手的信息。1.2写日志的要求既然写日志是必须的,可以帮助我们以后提高工作效率,从长远来看是非常有好处的。所以我们在开发的程序中应该按照规范来写日志,在写日志的时候要注意以下问题。1.2.1日志的可读性日志被别人看的时候,不仅仅是为了让自己看懂,也是为了让其他没有接触过我们源码的程序员一目了然。有的同事在日志中打印出特殊的标识符号,比如“++++++++++”、“===========”、“————”,这些符号让人眼花缭乱。这是一种糟糕的编程习惯。另外,将日志分类输出到不同的文件中,也有助于我们排除干扰,快速找到自己需要的信息。而且打印日志的时候最好输出英文,防止不支持中文的时候打印出乱码。1.2.2日志性能无论我们将日志写入文件还是数据库,都需要消耗IO资源。适当控制日志的输出也有利于提高程序的性能。例如:尽量避免在大循环中打印无意义的日志内容。最好在输出日志之前先判断日志级别(比如调试前调用isDebugEnabled()进行判断)。1.2.3占用磁盘空间通常,我们将日志写到磁盘上的日志文件中。正确使用滚动日志和定期清除旧文件是有益的。我见过这样的例子,程序运行几次就跑不起来了,前几次都是正常的。想不通程序哪里出了问题,最后发现是日志文件占用了磁盘空间。G日志文件在实际应用中并不少见。在这么大的日志文件中找到解决问题的有用信息也是一个很大的挑战。1.2.4日志的时效性有时我们不能及时发现问题。需要追溯之前的日志。所以我们需要在一段时间内保留日志,以便于追溯。1.2.5日志级别通常我们生产环境中的日志级别在INFO以上,所以我们必须保证在这种情况下程序仍然能够输出足够的信息供我们进行判断。例如,常见系统有以下日志级别://定义FATAL级别输出宏#defineDRV_LOG_FATAL(fmt,...)hlog_format(HLOG_LEVEL_FATAL,"PluginDriver","[%s(%d)]"fmt,__FUNCTION__,__LINE__,##__VA_ARGS__)//定义ERROR级输出宏__VA_ARGS__)//定义WARN级输出宏#defineDRV_LOG_WARN(fmt,...)hlog_format(HLOG_LEVEL_WARN,"PluginDriver","[%s(%d)]"fmt,__FUNCTION__,__LINE__,##__VA_ARGS__)//定义INFO级输出宏#defineDRV_LOG_INFO(fmt,...)hlog_format(HLOG_LEVEL_INFO,"PluginDriver","[%s(%d)]"fmt,__FUNCTION__,__LINE__,##__VA_ARGS__)//定义DEBUG级输出宏#defineDRV_LOG_DEBUG(fmt,...)hlog_format(HLOG_LEVEL_DEBUG,"PluginDriver","[%s(%d)]"fmt,__FUNCTION__,__LINE__,##__VA_ARGS__)//定义TRACE级输出宏#defineDRV_LOG_TRACE(fmt,...)hlog_format(HLOG_LEVEL_TRACE,"PluginDriver","[%s(%d)]"fmt,__FUNCTION__,__LINE__,##__VA_ARGS__)上面的日志文件中定义了6个日志级别,分别代表的含义不同级别下面详细介绍,我们要明白,在一个程序开发的过程中,需要维护不同的日志内容,分别是FATAL、ERROR、EARN、INFO、DEBUG、TRACE1.2.6。在写日志的时候,需要注意输出合适的内容。首先,尝试使用与业务相关的描述。我们的程序是为了实现某个业务,所以此时最好描述清楚我们到达了业务流程的哪一步。其次,避免在日志中输出一些敏感信息,比如用户名和密码。并且,保持编码一致。如果不能保证,尽量用英文,不要用中文。这样我们拿到日志的时候就不会因为看到一堆乱码而迷糊了。1.2.7日志格式通用日志格式应包含每条日志的信息,包括日期、时间、日志级别、代码位置、日志内容、错误代码等信息。下面是一个工作中的日志文件的一部分内容:2018-05-2215:35:53.850TRACETDWZLog[0x00001b10]<36>,TDWZProtocol::Init2018-05-22:53.850TRACETDWZLog[0x00001b10]<89>,结束处理TDWZProtocol::Init2018-05-2215:35:53.853TRACETDWZLog[0x00001b10]<142>,ConnectExecutefinish2018-05-2215:35:53.853TRACETDWZLog[0x00002f10]<149>,输入GetAlarmEventProfunc2018-05-2215:39:36.382WARNTrackLog[0x000029fc]-[内部WARNhtrace_server_convert_msgstring_to_context3输入错误],trace_idspan_id,可能无法跟踪此链。2018-05-2215:39:36.383WARNTrackLog[0x000029fc]-[内部警告htrace_server_receive(195)]无法在上下文中检测到trace_id,可能无法跟踪此链。2018-05-2215:39:36.383跟踪TDWZLog[0x000029fc]<231>,TDWZProtocol::DisConnect2018-05-2215:39:37.502TRACETDWZLog[0x00002f10]<225>,EndGetAlarmEventProFunc2018-05-2215:39:37.503TRACETDWZLog[0x000029fc]<241>,执行DisConnect功能成功。从这个文件可以看出,一般的日志文件应该包含信息2日志级别含义Log4j是Apache的一个开源项目。通过使用Log4j,我们可以控制日志信息的输出目的地是控制台、文件、GUI组件甚至socket服务器;我们还可以控制每条日志的输出格??式;通过定义每条日志信息的级别,我们可以更详细地控制日志的生成过程。最有趣的是,这些可以通过配置文件灵活配置,无需修改应用代码。2.1Log4j的组成Log4j由三个重要的组件组成:记录器(Loggers)、输出终端(Appenders)和日志格式化器(Layout)。2.1.1Logger控制启用或禁用哪些日志语句,并限制日志信息的级别。2.1.2Appenders指定日志是打印到控制台还是文件中。2.1.3Layout控制日志信息的显示格式。2.2日志级别Log4j输出的日志信息定义了6个级别,分别是TRACE、DEBUG、INFO、WARN、ERROR和FATAL。输出时,只有级别高于配置中指定级别的信息才能真正输出。这样就可以很方便的配置不同情况下输出的内容,不用改代码,非常方便快捷。2.2.1TRACETRACE指定比DEBUG更细粒度的信息事件。因为:1.2.12,非常低的日志级别,一般不使用。TRACE一般跟踪函数调用,TRACE不应包含可变参数,只能提示函数的调用关系。2.2.2DEBUG一般用于细粒度级别,对调试应用程序很有帮助。主要用于开发过程中打印一些运行信息。2.2.3INFOINFO消息在粗粒度上突出了应用程序的运行过程。打印一些您感兴趣或重要的信息。这可以用来在生产环境中输出程序运行的一些重要信息,但不能滥用,以免打印过多的日志。2.2.4WARNWARN表示可能会出现错误。有些信息不是错误信息,但应该给程序员一些提示。这个级别表示程序会自动调整到正常状态。没有传入类似的参数,使用默认参数,还是符合程序员预期的情况。2.2.5ERRORERROR表示虽然发生错误事件,但不影响系统的继续运行。打印错误和异常信息,如果不想输出过多的log,可以使用这个级别。一般在WARN之后的级别打印错误时,应该同时打印错误码。2.2.6FATALFATAL指出每一个严重的错误事件都会导致应用程序的退出。这个等级比较高,程序出现重大错误无法恢复。它必须通过重新启动程序来解决。2.3日志级别大小关系日志级别就像一个开关,决定哪些日志方法被调用,哪些不被调用。在log4j中,日志级别之间的关系如下:ALL其他错误",DRV_ERROR,iGetResult);DRV_LOG_WARN("[0x%08x]-[DWSdk.errorcode=0x%08x>其他错误",DRV_ERROR,iGetResult);DRV_LOG_WARN("[0x%08x]-SetEventCallBackshouldbecalledfirst",DRV_ERROR);3.5ERROR日志记录示例DRV_LOG_ERROR("InitDwSDKfilded;",initRet);DRV_LOG_ERROR("连接设备失败");DRV_LOG_ERROR("创建线程失败");DRV_LOG_ERROR("dw_start_receive失败");DRV_LOG_ERROR("通信失败,socketrecv错误");DRV_LOG_ERROR("其他错误",iGetResult);DRV_LOG_ERROR("SetEventCallBack应该首先调用");DRV_LOG_ERROR("[0x%08x]-[DWSdk.errorcode=0x%08x]InitDwSDKfilded",DRV_INIT_FAILED,initRet);DRV_LOG_ERROR("-[HPR.errorcode=0x%08x]Createthreadfailed",HPR_GetLastError());在上面code[0x%08x]的作用如下:该语句以“0x%08x”的形式出现在格式化输出的格式串中,其中0x为普通字符,当为0x时输出为0xoutput.%08x是一个整数十六进制格式输出的格式字符串会以十六进制输出参数对应的后续整数数字,08的意思是输出的十六进制值占8位,不足部分左边为填充为0。因此,执行printf("0x%08x",0x1234);会输出0x00001234。版权声明:本文为CSDN博主“丝莹莹丝”原创文章,转自CC4.0BY-SA版权协议,请附上原文链接和本声明。