Java日志详解:日志级别,优先级、配置文件、常见日志管理系统ELK、日志收集分析

2024-08-29 22:17:44 浏览数 (1)

作者平台

| CSDN:blog.csdn.net/qq_44700578…

| 掘金:juejin.cn/user/23745965…

| 阿里云:developer.aliyun.com/my…

| 腾讯云:cloud.tencent.com/developer/user/1092…

| 51CTO:https://blog.51cto.com/u_14971476…

| 华为云:devpress.csdn.net/user/qq_44700578…

| 百度智能云:cloud.baidu.com/qianfandev…

| GitHub:github.com/ywj123456-sys…

| 微信公众号:寻求出路的程序媛

文章目录

一、日志定义与作用

二、使用步骤

三、日志级别

  • 3.1 日志级别简介、优先级
  • 3.2 常见日志级别
    • 3.2.1 DEBUG(调试)
    • 3.2.2 INFO(信息)
    • 3.2.3 WARN(警告)
    • 3.2.4 ERROR(错误)
    • 3.2.5 FATAL(致命)

四、日志框架

五、配置文件

六、常见日志管理系统

七、日志收集分析

  • 7.1 记录日志
  • 7.2 日志采集
  • 7.3 日志收集和分析

在软件开发与运维过程中,日志是至关重要的部分,它记录了系统运行时的各种状态信息,包括错误、警告、调试信息等。不同的日志级别用于区分不同重要程度的信息,便于开发者和运维人员快速定位问题,优化系统性能,以及更好地理解系统的运行状况。对于常见的几种日志级别及其具体作用,介绍如下。

一、日志定义与作用

定义:程序执行过程中,记录程序运行情况的信息

作用

  • 记录程序运行的情况,以便于程序在部署之后的排错调试等。跟输出语句一样,可以把程序在运行过程中的详细信息都打印在控制台上。
  • 持久化。利用log日志还可以把这些详细信息保存到文件和数据库中,如果不将日志信息保存到文件或数据库,信息便会丢失

二、使用步骤

不是java的,也不是自己写的,是第三方提供的代码,所以我们要导入jar包。具体步骤要根据使用的框架来定,详情可查阅网上相关资料。

  • 把第三方的代码导入到当前的项目当中 新建lib文件夹,把jar粘贴到lib文件夹当中,全选后右键点击选择add as a .... 检测导入成功:导入成功后jar包可以展开。在项目重构界面可以看到导入的内容
  • 把配置文件粘贴到src/main/resource文件夹下
  • 在代码中获取日志对象
  • 调用方法打印日志

三、日志级别

3.1 日志级别简介、优先级

针对不同的场景,日志被分为五种不同的级别。

代码语言:shell复制
TRACE, DEBUG, INFO, WARN, ERROR

按照重要程度依次排序:

  • DEBUG 级别曰志记录对调试程序有帮助的信息。
  • INFO 级别日志用来记录程序运行现场,虽然此处并未发生错误,但是对排查其他错误具有指导意义。
  • WARN 级别日志也可以用来记录程序运行现场,但是更偏向于表明此处有出现潜在错误的可能。
  • ERROR 级别日志表明当前程序运行发生了错误,需要被关注。但是当前发生的错误,没有影响系统的继续运行。
  • FATAL 级别曰志表明当前程序运行出现了严重的错误事件,并且将会导致应用程序中断。

还有两个特殊的:

  • ALL:输出所有日志
  • OFF:关闭所有日志

日志级别从小到大的关系(优先级从低到高):

ALL < TRACE < DEBUG < INFO < WARN < ERROR < FATAL < OFF

低级别的会输出高级别的信息,高级别的不会输出低级别的信息。譬如等级设为Error的话,warn、info、debug的信息不会输出。

logger.debug、logger.info、logger.warn、logger.error、logger.fatal的区别:其作用都是把错误信息写到文本日志里,但它们表示的日志级别不同。日志级别由高到底是——fatal,error,warn,info,debug。低级别的会输出高级别的信息,高级别的不会输出低级别的信息。修改日志输出的级别要在log4j文件中进行配置

log.error() 一般是需要if()的;log.info()一般是在try catch 里面;log.debug() 做记录一般标志着方法的开始和结束。

比如,你在开发的时候,要验证一个方法有没有被调用到,为了方便调试,通常会在这个方法开始的时候加一些system.out。但是项目真正发布的时候这些代码通常是要移除掉的,所以通常更建议用logger来记录。

所以你可能会加logger.debug。 为什么是debug而不是info、error或者其他呢?因为通常项目发布的时候都会把日志等级设置为error 或者info之类的等级,在这两个等级下debug的内容是输出不了的,所以就可以做到不需要修改代码就不会输出你只有在调试的时候才需要输出的内容

各个等级都是有它的含义的,虽然在写代码的时候你用debug info error都可以,但为了方便管理,在开发调试阶段需要查看特定数据 用debug,一些信息类的日志记录通常会用info(比如你想看一天有几个用户登录),一些错误的、或者异常信息会用error,比如某个时刻数据库连接出了问题,如果分析日志,直接搜索error开头的就能直接定位到了

修改日志输出的级别要在log4j文件中进行配置。项目正式发布后,一般会把日志级别设置为fatal或者error或者info。

代码语言:java复制
if(log.isDebugEnabled()){
    log.debug(“develop test!”);
}
  • 意思是:如果log4j的配置中开启debug级别日志,那么我们就打印输出debug日志,其在输出日志中会被标记为DEBUG
  • 这样做的好处是:在我们开发阶段有时候需要查看特定数据,我们可以把日志级别定为DEBUG级别,调试信息会输出在日志里便于调试和跟踪修改bug。当产品发布上线之后,可以在log4j配置中去掉DEBUG级别,这时调试信息就不会输出在日志里,日志会只显示运行的相关信息。如此一来,控制输出什么日志 不需要修改代码,只需修改配置文件的参数而已。
  • 推荐使用log日志输出调试信息而不要使用System.out.println()方法,主要是因为println()使用了同步锁,会影响程序的并发性能和系统的吞吐量。

3.2 常见日志级别

3.2.1 DEBUG(调试)

  • 标签:DEBUG
  • 描述:这是最详细的日志级别,主要用于开发阶段的调试。当开启DEBUG级别日志时,会记录程序运行过程中的所有详细信息,包括函数调用、变量值变化等。
  • 作用:对于排查代码逻辑问题、了解程序运行流程非常有帮助。但在生产环境中一般不建议长期开启,因为会产生大量的日志数据,影响性能并可能导致存储空间不足。

3.2.2 INFO(信息)

  • 标签:INFO
  • 描述:INFO级别的日志通常用来记录系统运行的关键事件或正常流程信息,例如服务启动、停止、配置加载成功等。
  • 作用:用于了解系统的基本运行状态和关键操作,是日常运维中最常用的一种日志级别。

3.2.3 WARN(警告)

  • 标签:WARN
  • 描述:WARN级别的日志用于记录可能潜在的问题或者非预期情况,但不影响系统整体运行的情况,比如资源占用过高、请求超时等。
  • 作用:通过监控WARN级别的日志,可以提前发现并预防可能存在的风险,避免小问题逐渐恶化成严重故障。

3.2.4 ERROR(错误)

  • 标签:ERROR
  • 描述:ERROR级别的日志用于记录系统出现错误或异常情况,如业务处理失败、数据库连接断开等,这些情况可能会导致功能无法正常使用或部分服务中断。
  • 作用:ERROR日志是问题定位的关键线索,一旦发生此类日志,意味着系统出现了严重的故障或错误,需要立即进行排查修复。

3.2.5 FATAL(致命)

  • 标签:FATAL 或 CRITICAL
  • 描述:FATAL级别的日志是最严重的等级,表示系统发生了灾难性错误,通常会导致系统崩溃或无法提供服务,如宕机、核心组件失效等。
  • 作用:这类日志对保障系统稳定运行至关重要,一旦出现,应立即触发告警通知,并迅速展开问题应急响应。

总结来说,日志级别为开发者和运维人员提供了从细粒度到粗粒度的不同观察窗口,通过合理设置和查看日志级别,能有效提高问题定位和系统维护效率。

四、日志框架

不同的Java日志框架对应的jar包会有所不同,下面是常用日志框架:

  • Logback:org.slf4j.Logger、ch.qos.logback.classic.Logger和ch.qos.logback.core.spi.LifeCycle。
  • Log4j 2:org.apache.logging.log4j.LogManager、org.apache.logging.log4j.Logger和org.apache.logging.log4j.core.config.Configurator。
  • java.util.logging:java.util.logging.Logger、java.util.logging.Handler和java.util.logging.Formatter。
  • SLF4J:org.slf4j.Logger、org.slf4j.LoggerFactory和org.slf4j.Marker。
  • Log4j:org.apache.log4j.Logger和org.apache.log4j.Level。
  • Logback Classic:ch.qos.logback.classic.Logger、ch.qos.logback.classic.Level和ch.qos.logback.classic.spi.ILoggingEvent。
  • Log4j-to-SLF4J:org.slf4j.bridge.SLF4JBridgeHandler。

五、配置文件

logback.xml示例

代码语言:xml复制
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
    <!-- CONSOLE :表示当前的日志信息是可以输出到控制台的 -->
    <appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
        <!--输出流对象 默认 System.out 改为 System.err-->
        <target>System.out</target>
        <encoder>
            <!--格式化输出:%d表示日期,%thread表示线程名,%-5level:级别从左显示5个字符宽度
                %msg:日志消息,%n是换行符-->
            <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%-5level]  %c [%thread] : %msg%n</pattern>
        </encoder>
    </appender>

    <!-- File是输出的方向通向文件的 -->
    <appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <encoder>
            <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern>
            <charset>utf-8</charset>
        </encoder>
        <!--日志输出路径-->
        <file>C:/code/wj-data.log</file>
        <!--指定日志文件拆分和压缩规则-->
        <rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
            <!--通过指定压缩文件名称,来确定分割文件方式-->
            <fileNamePattern>C:/code/itheima-data2-%d{yyyy-MMdd}.log%i.gz</fileNamePattern>
            <!--文件拆分大小-->
            <maxFileSize>1MB</maxFileSize>
        </rollingPolicy>
    </appender>

    <!-- level:用来设置打印级别,大小写无关:TRACE, DEBUG, INFO, WARN, ERROR, ALL 和 OFF, 默认debug
    <root>可以包含零个或多个<appender-ref>元素,标识这个输出位置将会被本日志级别控制。
    -->
    <root level="info">
        <appender-ref ref="CONSOLE"/>
        <appender-ref ref="FILE" />
    </root>
</configuration>
代码语言:xml复制
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
    <!-- 日志存放路径 -->
    <property name="log.path" value="logs"/>
    <!-- 日志输出格式 -->
    <property name="log.pattern" value="%d{HH:mm:ss.SSS} %-5level %logger{20}:%line | %msg%n"/>

    <!-- 控制台输出 -->
    <appender name="console" class="ch.qos.logback.core.ConsoleAppender">
        <encoder>
            <pattern>${log.pattern}</pattern>
            <charset>UTF-8</charset>
        </encoder>
    </appender>

    <!-- 系统日志输出 -->
    <appender name="file_info" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <file>${log.path}/sys-info.log</file>
        <!-- 循环政策:基于时间创建日志文件 -->
        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
            <!-- 日志文件名格式 -->
            <fileNamePattern>${log.path}/sys-info.%d{yyyy-MM-dd}.log</fileNamePattern>
            <!-- 日志最大的历史 60天 -->
            <maxHistory>60</maxHistory>
        </rollingPolicy>
        <encoder>
            <pattern>${log.pattern}</pattern>
            <charset>UTF-8</charset>
        </encoder>
        <filter class="ch.qos.logback.classic.filter.LevelFilter">
            <!-- 过滤的级别 -->
            <level>INFO</level>
            <!-- 匹配时的操作:接收(记录) -->
            <onMatch>ACCEPT</onMatch>
            <!-- 不匹配时的操作:拒绝(不记录) -->
            <onMismatch>DENY</onMismatch>
        </filter>
    </appender>

    <appender name="file_error" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <file>${log.path}/sys-error.log</file>
        <!-- 循环政策:基于时间创建日志文件 -->
        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
            <!-- 日志文件名格式 -->
            <fileNamePattern>${log.path}/sys-error.%d{yyyy-MM-dd}.log</fileNamePattern>
            <!-- 日志最大的历史 60天 -->
            <maxHistory>60</maxHistory>
        </rollingPolicy>
        <encoder>
            <pattern>${log.pattern}</pattern>
        </encoder>
        <filter class="ch.qos.logback.classic.filter.LevelFilter">
            <!-- 过滤的级别 -->
            <level>ERROR</level>
            <!-- 匹配时的操作:接收(记录) -->
            <onMatch>ACCEPT</onMatch>
            <!-- 不匹配时的操作:拒绝(不记录) -->
            <onMismatch>DENY</onMismatch>
        </filter>
    </appender>

    <!-- 用户访问日志输出  -->
    <appender name="sys-user" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <file>${log.path}/sys-user.log</file>
        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
            <!-- 按天回滚 daily -->
            <fileNamePattern>${log.path}/sys-user.%d{yyyy-MM-dd}.log</fileNamePattern>
            <!-- 日志最大的历史 60天 -->
            <maxHistory>60</maxHistory>
        </rollingPolicy>
        <encoder>
            <pattern>${log.pattern}</pattern>
        </encoder>
    </appender>

    <!-- 系统模块日志级别控制  -->
    <logger name="com.gk" level="info"/>
    <!-- Spring日志级别控制  -->
    <logger name="org.springframework" level="warn"/>
    <!--Kafka日志级别控制-->
    <logger name="org.apache.kafka" level="error"/>

    <root level="info">
        <appender-ref ref="console"/>
    </root>

    <!--系统操作日志-->
    <root level="info">
        <appender-ref ref="file_info"/>
        <appender-ref ref="file_error"/>
    </root>

    <!--系统用户操作日志-->
    <logger name="sys-user" level="info">
        <appender-ref ref="sys-user"/>
    </logger>
</configuration> 

六、常见日志管理系统

  • ELK Stack (Elasticsearch, Logstash, Kibana):ELK Stack 是一个开源的日志管理解决方案,包括 Elasticsearch 用于存储和索引日志数据、Logstash 用于日志收集和处理、Kibana 用于日志可视化和分析。
    • Elasticsearch:分布式搜索和分析引擎,具有高可伸缩、高可靠和易管理等特点。基于 Apache Lucene 构建,能对大容量的数据进行接近实时的存储、搜索和分析操作。通常被用作某些应用的基础搜索引擎,使其具有复杂的搜索功能
    • Logstash:数据收集引擎。它支持动态的从各种数据源搜集数据,并对数据进行过滤、分析、丰富、统一格式等操作,然后存储到用户指定的位置
    • Kibana:数据分析和可视化平台。通常与 Elasticsearch 配合使用,对其中数据进行搜索、分析和以统计图表的方式展示
  • Splunk:Splunk 是一款商业化的日志管理和分析软件,提供了强大的搜索、监控和报告功能,适用于大型企业和复杂的日志管理需求。
  • Graylog:Graylog 是一个开源的日志管理系统,提供了实时日志分析、搜索和仪表板等功能,支持灵活的日志处理和警报机制。
  • Fluentd:Fluentd 是一个开源的日志收集工具,可以将不同数据源的日志集中到统一的地方进行存储和分析,支持丰富的插件和扩展功能。
  • Prometheus:Prometheus 是一个开源的监控和告警系统,也可以用于日志收集和分析,在结合 Grafana 等工具可以实现强大的日志管理功能。
  • Loggly:Loggly 是一款基于云的日志管理服务,提供了实时日志搜索、分析和可视化的功能,适用于快速部署和使用的场景。

以上列举的是一些比较常见的日志管理系统,每个系统都有其特点和适用场景,选择合适的日志管理系统需要根据实际需求和情况进行评估和比较。

七、日志收集分析

7.1 记录日志

在记录日志或实现追踪功能时,开发人员可以采用多种不同的方式,每种方式都有其特点和适用场景:

  • 手动添加代码:
    • 在关键的业务方法或代码块中,开发人员可以显式地插入记录日志或追踪信息的代码。
    • 这种方式操作简单直接,可以精确控制追踪的粒度和内容,但需要开发人员自己添加代码,比较繁琐。
  • AOP(面向切面编程):
    • 使用 AOP 技术,在方法调用的开始和结束时插入代码,记录相应的追踪信息。
    • 这种方式可以降低代码侵入性,提高代码的可维护性,使得追踪逻辑与业务逻辑分离。
  • 第三方库:
    • 许多第三方的分布式跟踪工具(如 Zipkin、Jaeger 等)提供了 Java 客户端库,能够自动收集、存储和展示链路追踪数据。
    • 开发人员只需引入相应的库并进行简单配置,即可实现链路追踪功能,无需手动添加大量代码。
  • 集成框架:
    • 一些流行的框架(如 Spring Cloud、Micronaut 等)提供了集成分布式追踪功能的支持。
    • 通过这些框架提供的配置和注解,开发人员可以轻松地实现链路追踪,并集成到微服务架构中。
    • 不论选择哪种方式,基本原则是在关键的业务逻辑中记录必要的信息(如调用时间、调用者、被调用者、调用参数等),将这些信息汇总存储在日志文件、数据库或专门的追踪系统中,以便后续分析和监控。不同的方式适用于不同的情境和需求,开发人员可以根据实际情况选择合适的方式来实现日志记录和追踪功能。

7.2 日志采集

日志采集是指从各种系统和应用程序中收集、汇总和存储日志信息的过程。以下是常见的日志采集方式:

  • 日志文件监控:
    • 实时监控文件:通过监控日志文件的变化,实时读取新增的日志内容。
    • 定时扫描文件:定期扫描指定目录下的日志文件,将新增内容进行采集。
  • 系统日志:
    • 操作系统日志:收集操作系统生成的日志,如 Windows Event Log、Syslog 等。
    • 应用服务器日志:收集应用服务器(如 Apache、Nginx)产生的日志信息。
  • 远程日志采集:
    • 远程 Syslog:通过 Syslog 协议从远程机器收集日志信息。
    • 远程 API:通过调用远程 API 接口获取日志数据。
  • 日志发送器:
    • Logstash:一个开源的数据收集引擎,可以从多种来源采集日志数据。
    • Fluentd:另一个流行的开源日志收集工具,支持多种日志源和输出。
    • Filebeat:轻量级的日志转发工具,专门用于将日志文件发送到 Elasticsearch 或 Logstash。
  • 应用日志集成:
    • 日志框架:在应用程序内部集成日志框架,将日志输出到指定目标(如文件、数据库、消息队列)。
    • 日志代理:使用专门的日志代理软件,收集应用程序输出的日志并统一管理。
  • 消息队列:
    • Kafka:利用 Kafka 等消息队列中间件进行日志数据的缓冲和传输。
    • RabbitMQ:另一个常用的消息队列工具,也可用于日志采集和传输。
  • 容器日志采集:
    • Docker 日志:通过 Docker 容器日志驱动将容器内的日志收集到宿主机或远程存储中。
    • Kubernetes Fluentd 插件:在 Kubernetes 集群中使用 Fluentd 进行日志收集和处理。
  • 自定义日志采集器:
    • 可以根据特定需求开发自定义的日志采集器,例如基于特定协议或定制化的数据格式。

以上是常见的日志采集方式,具体选择何种方式取决于系统架构、需求和预算等因素。有效的日志采集可以帮助监控系统运行状态、排查问题并进行分析,是系统运维和故障排除中的重要环节。

7.3 日志收集和分析

在Java中进行日志收集和分析有多种方式,下面是一些常用的方式:

  • 日志框架:Java中有许多优秀的日志框架可供选择,其中最流行的包括Log4j、Logback和java.util.logging等。这些框架提供了灵活的配置选项和丰富的功能,使得日志记录变得简单和高效。
  • 日志级别控制:日志框架通常支持不同的日志级别,如DEBUG、INFO、WARN、ERROR等。通过适当设置日志级别,可以控制日志输出的详细程度,以满足应用程序的需求。
  • 日志输出:日志可以输出到不同的目标,包括控制台、文件、数据库、远程服务器等。Java日志框架通常提供了各种Appenders或Handlers,用于指定日志的输出目标。
  • 日志格式化:日志框架允许开发人员定义日志的格式,包括时间戳、日志级别、类名、方法名、线程ID等信息。通过合适的格式化,可以使日志信息易于阅读和理解。
  • 异步日志:某些日志框架支持异步日志记录,这意味着日志消息可以在后台线程中处理,从而减少对主线程的影响,提高应用程序的性能。
  • 日志分析工具:除了记录日志外,还可以使用日志分析工具来对日志进行实时监控、搜索和分析。一些流行的日志分析工具包括ELK Stack(Elasticsearch、Logstash、Kibana)、Splunk、Graylog等。
  • AOP(面向切面编程):使用AOP技术可以将日志记录逻辑从业务代码中分离出来,从而降低代码的耦合度。Spring框架提供了方便的AOP支持,可以轻松地实现日志记录功能。
  • 错误日志记录:除了常规的日志记录外,还可以捕获和记录应用程序的错误信息。Java提供了Throwable类及其子类来表示异常和错误,可以通过try-catch块捕获异常,并将异常信息记录到日志中。

综上所述,Java中进行日志收集和分析的方式丰富多样,开发人员可以根据具体需求选择合适的工具和技术来实现日志记录和分析功能。

参考 黑马程序员相关笔记、Java日志详解、日志级别及其作用

0 人点赞