许可优化
许可优化
产品
产品
解决方案
解决方案
服务支持
服务支持
关于
关于
软件库
当前位置:服务支持 >  软件文章 >  Fluent-Bit微服务日志采集实战(开箱即用)

Fluent-Bit微服务日志采集实战(开箱即用)

阅读数 2
点赞 0
article_banner

场景

适用于采集 spring-boot  微服务日志,并将日志统一保存到ES数据库中

准备工作

1. fluent-bit方案

首先确定我们的方案,fluent-bit会部署在每一台运行java微服务的机器上,监听服务生成的 日志文件  ,采集日志后转发到专门负责写入ES的FluentBit服务器上去。
fluent-bit架构

2. 日志格式化

在采集日志之前,我们首先要确保微服务的日志采用统一格式,并且为了后面写入ES更好的识别数据,我们采用了如下的格式。

注意这里日期的输出,我们采用了ISO8601格式,保留了时区,这是为了最终写入ES能保留时区,避免出现时间偏差。

<?xml version="1.0" encoding="UTF-8"?>
<!-- 日志级别从低到高分为TRACE < DEBUG < INFO < WARN < ERROR < FATAL,如果设置为WARN,则低于WARN的信息都不会输出 -->
<!-- scan:当此属性设置为true时,配置文件如果发生改变,将会被重新加载,默认值为true -->
<!-- scanPeriod:设置监测配置文件是否有修改的时间间隔,如果没有给出时间单位,默认单位是毫秒。当scan为true时,此属性生效。默认的时间间隔为1分钟。 -->
<!-- debug:当此属性设置为true时,将打印出logback内部日志信息,实时查看logback运行状态。默认值为false。 -->
<configuration scan="true" scanPeriod="10 seconds">
    <!-- name的值是变量的名称,value的值时变量定义的值。通过定义的值会被插入到logger上下文中。定义变量后,可以使“${}”来使用变量。 -->
    <springProperty scope="context" name="applicationId" source="spring.application.name"
                    defaultValue="defaultApplication"/>
    <springProperty scope="context" name="log.path" source="nuzarsurf.tracer.log-path"
                    defaultValue="logs"/>
    <!-- 彩色日志 -->
    <!-- 彩色日志依赖的渲染类 -->
    <conversionRule conversionWord="clr" converterClass="org.springframework.boot.logging.logback.ColorConverter"/>
    <conversionRule conversionWord="wex"
                    converterClass="org.springframework.boot.logging.logback.WhitespaceThrowableProxyConverter"/>
    <conversionRule conversionWord="wEx"
                    converterClass="org.springframework.boot.logging.logback.ExtendedWhitespaceThrowableProxyConverter"/>
    <!-- 彩色日志格式 -->
    <property name="LOG_LEVEL_PATTERN"
              value="%5p [${applicationId:-},%X{traceId:-},%X{spanId:-}]"/>
    <property name="CONSOLE_LOG_PATTERN"
              value="${CONSOLE_LOG_PATTERN:-%clr(%d{yyyy-MM-dd'T'HH:mm:ss.SSSZ}){faint} %clr(${LOG_LEVEL_PATTERN:-%5p}) %clr(${PIhttps://www.gofarlic.com- }){magenta} %clr(---){faint} %clr([%15.15t]){faint} %clr(%-40.40logger{39}){cyan} %clr(:){faint} %m%n${LOG_EXCEPTION_CONVERSION_WORhttps://www.gofarlic.com-%wEx}}"/>
    <property name="LOG_PATTERN"
              value="${LOG_PATTERN:-%d{yyyy-MM-dd'T'HH:mm:ss.SSSZ} ${LOG_LEVEL_PATTERN:-%5p} ${PIhttps://www.gofarlic.com- } --- [%15.15t] %-40.40logger{39} : %m%n${LOG_EXCEPTION_CONVERSION_WORhttps://www.gofarlic.com-%wEx}}"/>

    <!-- 控制台输出日志 -->
    <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
        <encoder>
            <Pattern>${CONSOLE_LOG_PATTERN}</Pattern>
            <charset class="java.nio.charset.Charset">UTF-8</charset>
        </encoder>
    </appender>

    <!-- 时间滚动输出 level为 INFO 日志 -->
    <appender name="DEFAULT_FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <!-- 正在记录的日志文件的路径及文件名 -->
        <file>${log.path}/${applicationId}.log</file>
        <!--日志文件输出格式-->
        <encoder>
            <pattern>${LOG_PATTERN}</pattern>
            <charset>UTF-8</charset>
        </encoder>
        <!-- 日志记录器的滚动策略,按日期,按大小记录 -->
        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
            <!-- 每天日志归档路径以及格式 -->
            <fileNamePattern>${log.path}/${applicationId}-%d{yyyy-MM-dd}.%i.log</fileNamePattern>
            <timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
                <maxFileSize>100MB</maxFileSize>
            </timeBasedFileNamingAndTriggeringPolicy>
            <!--日志文件保留天数-->
            <maxHistory>2</maxHistory>
        </rollingPolicy>
        <!-- 此日志文件只记录info级别的 -->
        <filter class="ch.qos.logback.classic.filter.LevelFilter">
            <level>info</level>
            <onMatch>ACCEPT</onMatch>
            <onMismatch>ACCEPT</onMismatch>
        </filter>
    </appender>

    <!-- 时间滚动输出 level为 ERROR 日志 -->
    <appender name="ERROR_FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <!-- 正在记录的日志文件的路径及文件名 -->
        <file>${log.path}/${applicationId}_error.log</file>
        <!--日志文件输出格式-->
        <encoder>
            <pattern>${LOG_PATTERN}</pattern>
            <charset>UTF-8</charset>
        </encoder>
        <!-- 日志记录器的滚动策略,按日期,按大小记录 -->
        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
            <fileNamePattern>${log.path}/${applicationId}_error-%d{yyyy-MM-dd}.%i.log</fileNamePattern>
            <timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
                <maxFileSize>100MB</maxFileSize>
            </timeBasedFileNamingAndTriggeringPolicy>
            <!--日志文件保留天数-->
            <maxHistory>2</maxHistory>
        </rollingPolicy>
        <!-- 此日志文件只记录ERROR级别的 -->
        <filter class="ch.qos.logback.classic.filter.LevelFilter">
            <level>ERROR</level>
            <onMatch>ACCEPT</onMatch>
            <onMismatch>DENY</onMismatch>
        </filter>
    </appender>
    <!-- 日志输出级别 -->
    <root level="INFO">
        <appender-ref ref="STDOUT"/>
        <appender-ref ref="DEFAULT_FILE"/>
        <appender-ref ref="ERROR_FILE"/>
    </root>
</configuration>

3. fluent-bit部署

# 安装
curl https://raw.githubusercontent.com/fluent/fluent-bit/master/install.sh | sh

# 运行
/opt/fluent-bit/bin/fluent-bit -c //etc/fluent-bit/fluent-bit.conf

4. fluent-bit配置

fluent-bit 的配置需要注意几点:

  1. 多行日志的读取
  2. 日志的regex匹配

特别注意fluent-bit最麻烦的地方其实就是日志的格式匹配了
^(?<time>[^ ]*)\s*(?<level>[^ ]*)\s\[(?<service>[^,]*),(?<traceId>[^,]*),(?<spanId>[^\]]*)\] (?<pid>[^ ]*) --- \[\s*(?<thread>[^\]]*)\] (?<logger>[^ ]*) *: (?<message>[^$]*)

   以上正则表达式可以匹配
2023-07-13T10:48:25.984+0800 INFO [demo-web,traceId111,spanId222] 13212 — [ main] com.xxx.demo.DemoApplication : No active profile set, falling back to 1 default profile: “default”

   自动解析日志

Rubular测试

fluent-bit我们需要把自定义的parser添加到/etc/fluent-bit/parsers.conf中去

[MULTILINE_PARSER]
    name          micro_mparser
    type          regex
    flush_timeout 1000
    #
    # rules |   state name  | regex pattern                                                                                      | next state
    # ------|---------------|---------------------------------------------------------------------------------------------------------------
    rule      "start_state"   "(?<time>[^ ]*)\s*(?<level>[^ ]*)\s\[(?<service>[^,]*),(?<traceId>[^,]*),(?<spanId>[^\]]*)\] (?<pid>[^ ]*) --- \[\s*(?<thread>[^\]]*)\] (?<logger>[^ ]*) *: (?<message>[^$]*)"            "stack"
    rule      "stack"         "^[a-zA-Z\s].*"                           "stack"

[PARSER]
    Name        micro_parser
    Format      regex
    Regex       (?<time>[^ ]*)\s*(?<level>[^ ]*)\s\[(?<service>[^,]*),(?<traceId>[^,]*),(?<spanId>[^\]]*)\] (?<pid>[^ ]*) --- \[\s*(?<thread>[^\]]*)\] (?<logger>[^ ]*) *: (?<message>[^$]*)
    Time_Key    time
    Time_Format %Y-%m-%dT%H:%M:%S.%L%z

然后配置我们需要监听的文件,这里使用到了我们的多行转换和字段提取

# 开启 multiline.parse 后,parser不生效,需要使用 filter 再次进行解析
[INPUT]
    Name              tail
    Path              /root/app/micro-test/logs/micro-test.log
    Tag               micro_test
    multiline.parser  micro_mparser
    db                micro.db
[FILTER]
    Name         parser
    Parser       micro_parser
    Match        micro_*
    Key_Name     log
    Reserve_Data On
    Preserve_Key Off

之后我们配置以下日志的输出output就行了,这里我放个简化的版本,直接输出到ES数据库

[OUTPUT]
    Name  es
    Match micro_*
    Host  xxx.xxx.xxx.xxx
    Port  9200
    Index micro.%Y.%m.%d
    tls On
    tls.verify Off
    HTTP_User elastic
    HTTP_Passwd xxxxxxxxxxxxxxxxxxxxxxxxx
    Suppress_Type_Name On



免责声明:本文系网络转载或改编,未找到原创作者,版权归原作者所有。如涉及版权,请联系删


相关文章
技术文档
QR Code
微信扫一扫,欢迎咨询~
customer

online

联系我们
武汉格发信息技术有限公司
湖北省武汉市经开区科技园西路6号103孵化器
电话:155-2731-8020 座机:027-59821821
邮件:tanzw@gofarlic.com
Copyright © 2023 Gofarsoft Co.,Ltd. 保留所有权利
遇到许可问题?该如何解决!?
评估许可证实际采购量? 
不清楚软件许可证使用数据? 
收到软件厂商律师函!?  
想要少购买点许可证,节省费用? 
收到软件厂商侵权通告!?  
有正版license,但许可证不够用,需要新购? 
联系方式 board-phone 155-2731-8020
close1
预留信息,一起解决您的问题
* 姓名:
* 手机:

* 公司名称:

姓名不为空

姓名不为空

姓名不为空
手机不正确

手机不正确

手机不正确
公司不为空

公司不为空

公司不为空