场景
适用于采集spring-boot微服务日志,并将日志统一保存到ES数据库中
准备工作
1. fluent-bit方案
首先确定我们的方案,fluent-bit会部署在每一台运行java微服务的机器上,监听服务生成的日志文件,采集日志后转发到专门负责写入ES的FluentBit服务器上去。
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(${PID:- }){magenta} %clr(---){faint} %clr([%15.15t]){faint} %clr(%-40.40logger{39}){cyan} %clr(:){faint} %m%n${LOG_EXCEPTION_CONVERSION_WORD:-%wEx}}"/>
<property name="LOG_PATTERN"
value="${LOG_PATTERN:-%d{yyyy-MM-dd'T'HH:mm:ss.SSSZ} ${LOG_LEVEL_PATTERN:-%5p} ${PID:- } --- [%15.15t] %-40.40logger{39} : %m%n${LOG_EXCEPTION_CONVERSION_WORD:-%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 的配置需要注意几点:
- 多行日志的读取
- 日志的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”
自动解析日志
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
然后配置我们需要监听的文件,这里使用到了我们的多行转换和字段提取文章来源:https://www.toymoban.com/news/detail-810486.html
# 开启 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数据库文章来源地址https://www.toymoban.com/news/detail-810486.html
[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
到了这里,关于Fluent-Bit 微服务日志采集实战(开箱即用)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!