当前位置: 首页 > 科技观察

别小看Log日志,难倒我们组架构师

时间:2023-03-15 20:59:11 科技观察

本文转载自微信公众号《Asana的IT小屋》,作者EricAsagi。转载本文请联系浅叶IT之家公众号。祝大家新年快乐!在最近的会议中,讨论了一些异常处理和日志输出。是的,这些看似微不足道的事情,都发散了。因为大家一般只了解Log4j,而其余的基本没用过。我们的Leader也说他对ELK这样的大型原木有点生疏,因为好久没用了。所以今天总结一下关于日志的介绍。日志对于程序员来说是必不可少的。在我们的开发过程中,如果写完代码需要调试,那么日志是必不可少的。日志可以帮助我们定位问题,从而更好的帮助我们解决bug。本期小鱼就给大家详细了解一下我们常用的四种日志类型,帮助大家提高开发效率。好了,让我们进入正文。Slf4jslf4j的全称是SimpleLoggingFacadeForJava。它只是一个为Java程序提供日志输出的统一接口。不是具体的日志实现方案。就像JDBC一样,只是一个规则。所以单独使用slf4j是不行的,必须结合其他具体的日志实现方案,比如apache的org.apache.log4j.Logger,jdk的java.util.logging.Logger等。Log4J因为很多开发者熟悉Log4J但不知道SLF4J,或者不关注SLF4J而死守Log4J。我们先来看看Log4J的例子:Logger.debug("Hello"+name);由于字符串拼接的问题,使用上面的语句会先拼接字符串,然后根据当前级别是否低于debug来决定是否输出这条日志,即使不输出日志,字符串拼接操作也会也会执行,所以很多公司都强制使用下面的语句,这样只会在当前级别为DEBUG时才进行字符串拼接:if(logger.isDebugEnabled()){LOGGER.debug(“Hello”+name);它避免了字符串连接的问题,但是有点太麻烦了,不是吗?相对地,SLF4J提供了如下简单的语法:LOGGER.debug("Hello{}",name);它的形式类似于第一个例如,没有字符串拼接的问题,也没有第二种那么麻烦日志级别LevelSlf4j有四种级别的日志级别可以选择,级别从上到下,从低到高,优先级高的会打印出来.debug:简单的说,任何有利于的信息程序调试可以是debugoutputinfo:对用户有用的信息warn:可能出错的信息error:顾名思义就是使用出现错误的地方,因为是强制规范,所以直接使用LoggerFactory创建importorg.slf4j.Logger;importorg.slf4j.LoggerFactory;publicclassTest{privatestaticfinalLoggerlogger=LoggerFactory.getLogger(Test.class);//...}配置方式SpringBoot对slf4j的支持很好,内部已经集成了slf4j。使用时会配置slf4j。application.yml文件是唯一需要在SpringBoot中配置的文件。最初创建项目时,它是application.properties文件。我个人比较详细使用yml文件,因为yml文件的层次感特别好,看起来比较直观,但是yml文件对格式要求比较高。比如英文冒号后面必须有一个空格,否则项目可能无法启动,也不会报错。是用properties还是yml看个人习惯。我们看一下application.yml文件中日志的配置:logging:config:classpath:logback.xmllevel:com.bowen.dao:tracelogging.config用于指定项目启动时读取哪个配置文件,这里指定的日志配置文件是classpath:logback.xml文件,日志的相关配置信息放在logback.xml文件中。logging.level用于指定日志在具体mapper中的输出级别。上面的配置表示com.bowen.dao包下所有mapper的日志输出级别都是trace,会打印出操作数据库的sql,开发时设置为trace,方便定位问题。在生产环境中,将日志级别设置为错误级别。常用的日志级别从高到低依次为:ERROR、WARN、INFO、DEBUG。Log4jLog4j是Apache的一个开源项目。通过使用Log4j,我们可以控制日志信息传输的目的地是控制台、文件、GUI组件,甚至是socket服务器、NT事件记录器、UNIXSyslog守护进程等;我们还可以控制每条日志的输出格??式;通过定义每条日志信息的级别,我们可以更详细地控制日志的生成过程。CompositionArchitectureLog4j由三个重要组件组成:记录器(Loggers)、输出终端(Appenders)和日志格式化器(Layout)。Logger:控制启用或禁用哪些日志语句,并限制日志信息的级别Appenders:指定日志是打印到控制台还是文件Layout:控制日志信息的显示格式Log信息要输出到Log4j定义了5个级别,依次为DEBUG、INFO、WARN、ERROR和FATAL。输出时,只有级别高于配置中指定级别的信息才能真正输出,因此在不同情况下配置输出内容非常方便。无需更改代码。日志级别LevelLog4j主要有以下几种日志级别:off:注销,最高级别,没有日志可以输出fatal:灾难性错误,所有级别中最高的可以输出日志error:error,一般用于异常信息warn:Warning,一般用于不规则引用等信息info:一般信息debug:调试信息,一般用于程序执行过程trace:堆栈信息,一般不用在核心类中,除了off/all之外,每个日志级别对应一组重载的方法,用于记录不同级别的日志。当且仅当该方法对应的日志级别大于等于设置的日志级别时,才会记录该日志。使用Log4j只需要导入一个jar包org.log4jlog4j1.2.9的配置方法在Resources根目录下创建log4j.properties配置文件,一定要注意:文件的位置和文件名不能错,然后添加配置信息log4j.rootLogger=debug,conslog4j.appender.cons=org.apache.log4j在属性文件中。ConsoleAppenderlog4j.appender.cons.target=System.outlog4j.appender.cons.layout=org.apache.log4j.PatternLayoutlog4j.appender.cons.layout.ConversionPattern=%m%n属性文件是最常用的配置方式。在实际开发过程中,基本都是使用properties文件。pripertis配置文件的配置方法为:#配置日志级别,指定有效的Appender名称,AppenderA为定义的Appender名称log4j.rootLogger=loglevel,AppenderA,AppenderB,...#---------------Defineanappender------------------------#Defineanappender,appender名称可以任意,#如果要使用appender生效,必须在rootLogger的上一行加上,后面加上对应的Appender类log4j.appender.appendername=org.apache.log4j.ConsoleAppenderlog4j.appender.appendername.target=System.out#定义Appender的布局log4j.appender.appendername.layout=org.apache.log4j.SimpleLayoutLogback简单来说,Logback是Java领域的一个日志框架。它被认为是Log4J的继承者。logback是log4j的升级,所以logback自然比log4j有很多优势。模块组成Logback主要由三个模块组成:logback-core、logback-classic和logback-access。logback-core是其他模块构建的基础设施,显然,logback-core提供了一些关键的通用机制。logback-classic的地位和作用相当于Log4J,也算是Log4J的改进版,实现了简单的日志门面SLF4J;logback-access主要作为与Servlet容器交互的模块,如tomcat或jetty,提供一些HTTP访问相关的功能。三个模块Logback组件Logback的主要组件如下:Logger:日志记录器;将他与应用程序的相应上下文相关联;主要用于存储日志对象;日志类型级别可自定义Appender:用于指定日志输出的目的地;目的地可以是控制台、文件、数据库等。Layout:负责将事件转化为字符串;输出格式化日志信息;在logback中,Layout对象被封装在编码器中。Logback优势Logback的主要优势如下:相同的代码路径,Logback执行速度更快,测试更充分原生实现SLF4JAPI(Log4J还需要一个中间转换层)更丰富的文档支持XML或Groovy配置配置文件自动热加载优雅恢复fromIOerrors自动删除日志Archiving自动将日志压缩成归档文件支持Prudent模式,可以让多个JVM进程记录同一个日志文件支持在配置文件中加入条件判断以适应不同的环境更强大的过滤器支持SiftingAppender(可过滤的Appender)异常堆栈信息带有包信息标签属性Logback主要标签属性如下:configuration:配置根节点配置结构scan:为true时,如果配置文件属性发生变化,将扫描并重新加载,默认为truescanPeriod:监听配置文件是否有修改时间Interval,如果不给出时间单位,默认单位为毫秒;默认时间为1分钟;当scan="true"debug:为true时,会显示logback的内部日志信息,可以实时查看logback的运行状态;默认值falsecontextName:上下文名称,默认为“default”,该标签可以设置为其他名称,用于区分不同应用的记录;一旦设置,不可修改appender:configuration的子节点,负责写日志的组件,有name和class两个必备属性name:addender的名称class:appender的全限定名,对应具体的Appender类名,比如ConsoleAppender,FileAppenderappend:为true时,日志追加到文件末尾。如果为假,则清除现有文件。默认值是true。配置方式logback框架默认会加载classpath下名为logback-spring或logback的配置文件:[%d{yyyy-MM-dd''HH:mm:ss.sss}][%C][%t][%L][%-5p]%m%n错误拒绝接受[%d{yyyy-MM-dd''HH:mm:ss。sss}][%C][%t][%L][%-5p]%m%n${LOG_INFO_HOME}//%d.log30错误/过滤器><编码器><模式>[%d{yyyy-MM-dd''HH:mm:ss.sss}][%C][%t][%L][%-5p]%m%n${LOG_ERROR_HOME}//%d.log30ELKELK是软件集合Elasticsearch、Logstash、Kibana的简称,这三个软件及其相关组件可以创建一个大规模的日志实时处理系统,新增了FileBeat,是一个轻量级的日志收集处理工具(Agent).Filebeat占用资源少,适合收集各个服务器上的日志,然后传输到Logstash,官方也推荐这个工具Elasticsearch:是一个基于Lucene的分布式存储和索引引擎,支持全文indexing,主要负责日志的索引和存储,方便业务方搜索查询Logstash:日志收集、过滤、转发的中间件,可视化工具,主要负责Elasticsearch数据的查询并直观地展示给业务端,比如各种饼图、直方图、面积图等。Filebeat:属于Beats,是一款轻量级的日志采集和处理工具。Beats目前包括四个工具:Packetbeat(收集网络流量数据)、Topbeat(收集系统、进程和文件系统级别的CPU和内存使用数据)、Filebeat(收集文件数据)、Winlogbeat(收集Windows事件日志数据)的主要特点架构图一个完整的集中式日志系统需要包括以下主要功能:采集:能够从多个来源收集日志数据传输:能够稳定地将日志数据传输到中心系统存储:如何存储日志数据分析:可以支持UI分析和警告:它可以提供错误报告。监控机制ELK提供了一套完整的解决方案,并且都是开源软件。日志系统。应用场景在海量日志系统的运维中,以下几个方面必不可少:分布式日志数据的集中查询和管理;系统监控,包括系统硬件和应用组件的监控;故障排除;安全信息和事件管理;报告功能;ELK运行在分布式系统上,通过对海量系统和组件日志的收集、过滤、传输、存储、集中管理和准实时的搜索分析,使用搜索、监控、事件消息和报表等方式,简单易行-易用功能帮助运维人员实时监控在线业务,及时定位业务异常原因,排查问题,跟踪分析程序开发过程中的BUG,业务趋势分析,安全合规审计,日志深度挖掘数据值。同时,Elasticsearch提供了多种API(RESTJAVAPYTHON等API)供用户扩展和开发,以满足不同的需求。配置方法filebeat配置,打开filebeat.yml,配置如下:#输入源,可以写多个filebeat.input:-type:logenabled:true#输入源文件地址path:-/data/logs/tomcat/*。log#多行正则匹配,匹配规则示例:2020-09-29,如果不是这样,则与上一条消息合并multiline:pattern:'\s*\['negate:truematch:after#Createanametags:["tomcat"]#Outputtarget,可以将logstash改为esoutput.logstash:hosts:[172.29.12.35:5044]logstash配置,新建一个.conf为后缀的文件,或者打开.conf下的文件config文件夹,这里的配置文件可以同时启动多个,还有一个强大的过滤功能,可以过滤原始数据,如下:#Inputsource(required)input{#Consoletypestdin{}#Filereadfile{#类似给定名称类型=>"info"#文件路径,可以用*表示所有路径=>['/usr/local/logstash-7.9.1/config/data-my.log']#第一次从t开始阅读从头开始,下次从上一个位置继续读取start_position=>"beginning"}file{type=>"error"path=>['/usr/local/logstash-7.9.1/config/data-my2.log']start_position=>"beginning"codec=>multiline{pattern=>"\s*\["negate=>truewhat=>"previous"}}#Usewithfilebatesbeats{port=>5044}}#OutputTarget(required)output{#判断类型是否相同if[type]=="error"{#如果是,则写入这个eselasticsearch{hosts=>"172.29.12.35:9200"#kibana根据索引名称查询,其中YYYY为动态获取的日期索引=>"log-error-%{+YYYY.MM.dd}"}}if[type]=="info"{elasticsearch{hosts=>"172.29.12.35:9200"#kibana通过索引index的名字查询=>"log-info-%{+YYYY.MM.dd}"}}#判断这里是filebates中给出的标签是否是tomcatif"tomcat"in[tags]{elasticsearch{hosts=>"172.29.12.35:9200"#kibana通过索引index=>"tomcat"}}#控制台查询还将打印关于我的信息stdout{codec=>rubydebug{}}}