分布式系统日志收集ELK
ELK简介
-
ELK是ElasticSearch+Logstash+Kibana三个部分组成,对于各种日志进行收集,过滤,清洗,然后进行集中存放,并且可以实时搜索,分析。
-
LogsTash是轻量级,开源的日志处理框架,可以把分散的日志收集起来然后进行统一的处理或者输出到指定的位置,比如日志处理服务器获得文件
-
logsTash主要三个功能如下:
- input:数据收集
- filter:数据加工
- output:数据输出
-
-
shipper:对于日志进行收集
-
broker:链接shipper与indexer,作为缓冲区
-
indexer:对于文件进行加工处理输出到指定介质
-
ElasticSearch倒排索引便于插叙
-
Kibana对于ES中的数据进行可视化的展示
LogsTash安装
-
下载地址:
-
解压
-
配置文件
# Sample Logstash configuration for creating a simple # Beats -> Logstash -> Elasticsearch pipeline. input { file { # 配置文件的绝对路径 path => "D:/myLog/springBootLog/log_debug.log" # 作为日志归纳字段使用,后面也可以作为变量去进行一个判断 type => "debuglog" start_position => "beginning" # logstash 每隔多久检查一次被监听文件状态(是否有更新),默认是 1 秒 stat_interval => "3" } # 配置多个收集地址 file { # 配置文件的绝对路径 path => "D:/myLog/springBootLog/log_error.log" # 作为日志归纳字段使用,后面也可以作为变量去进行一个判断 type => "errorlog" start_position => "beginning" # logstash 每隔多久检查一次被监听文件状态(是否有更新),默认是 1 秒 stat_interval => "3" } file { # 配置文件的绝对路径 path => "D:/myLog/springBootLog/log_info.log" # 作为日志归纳字段使用,后面也可以作为变量去进行一个判断 type => "infolog" start_position => "beginning" # logstash 每隔多久检查一次被监听文件状态(是否有更新),默认是 1 秒 stat_interval => "3" } } # 输出到es中 #output { # elasticsearch { # hosts => ["http://192.168.200.128:9200"] # index => "logstash-%{+yyyy.MM.dd}" #user => "elastic" #password => "changeme" #} #} output{ # 对于不同的日志输出到不同的索引中 if[type] == "debuglog" { elasticsearch{ hosts=>["192.168.200.128:9200"] index => "debuglog-%{+YYYY.MM.dd}" } } if[type] == "errorlog" { elasticsearch{ hosts=>["192.168.200.128:9200"] index => "errorlog-%{+YYYY.MM.dd}" } } if[type] == "infolog" { elasticsearch{ hosts=>["192.168.200.128:9200"] index => "infolog-%{+YYYY.MM.dd}" } } }
-
启动logstash
.\logstash -f logstash-test.conf;
springboot集成slf4j日志系统
-
引入依赖
<!-- 日志框架--> <dependency> <groupId>ch.qos.logback</groupId> <artifactId>logback-classic</artifactId> <version>1.2.3</version> <scope>compile</scope> </dependency> <dependency> <groupId>org.apache.logging.log4j</groupId> <artifactId>log4j-to-slf4j</artifactId> <version>2.10.0</version> <scope>compile</scope> </dependency> <dependency> <groupId>org.slf4j</groupId> <artifactId>jul-to-slf4j</artifactId> <version>1.7.25</version> <scope>compile</scope> </dependency> <!--使用--> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <version>1.18.8</version> <scope>provided</scope> </dependency>
-
在idea中下载lombok插件
-
配置日志文件
<?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"> <!--<include resource="org/springframework/boot/logging/logback/base.xml" />--> <contextName>logback</contextName> <!-- name的值是变量的名称,value的值时变量定义的值。通过定义的值会被插入到logger上下文中。定义变量后,可以使“${}”来使用变量。 --> <property name="log.path" value="D:/myLog/springBootLog" /> <!-- 彩色日志 --> <!-- 彩色日志依赖的渲染类 --> <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="CONSOLE_LOG_PATTERN" value="${CONSOLE_LOG_PATTERN:-%clr(%d{yyyy-MM-dd HH:mm:ss.SSS}){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}}"/> <!--输出到控制台--> <appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender"> <!--此日志appender是为开发使用,只配置最底级别,控制台输出的日志级别是大于或等于此级别的日志信息--> <filter class="ch.qos.logback.classic.filter.ThresholdFilter"> <level>debug</level> </filter> <encoder> <Pattern>${CONSOLE_LOG_PATTERN}</Pattern> <!-- 设置字符集 --> <charset>UTF-8</charset> </encoder> </appender> <!--输出到文件--> <!-- 时间滚动输出 level为 DEBUG 日志 --> <appender name="DEBUG_FILE" class="ch.qos.logback.core.rolling.RollingFileAppender"> <!-- 正在记录的日志文件的路径及文件名 --> <file>${log.path}/log_debug.log</file> <!--日志文件输出格式--> <encoder> <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n</pattern> <charset>UTF-8</charset> <!-- 设置字符集 --> </encoder> <!-- 日志记录器的滚动策略,按日期,按大小记录 --> <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy"> <!-- 日志归档 --> <fileNamePattern>${log.path}/debug/log-debug-%d{yyyy-MM-dd}.%i.log</fileNamePattern> <timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP"> <maxFileSize>100MB</maxFileSize> </timeBasedFileNamingAndTriggeringPolicy> <!--日志文件保留天数--> <maxHistory>15</maxHistory> </rollingPolicy> <!-- 此日志文件只记录debug级别的 --> <filter class="ch.qos.logback.classic.filter.LevelFilter"> <level>debug</level> <onMatch>ACCEPT</onMatch> <onMismatch>DENY</onMismatch> </filter> </appender> <!-- 时间滚动输出 level为 INFO 日志 --> <appender name="INFO_FILE" class="ch.qos.logback.core.rolling.RollingFileAppender"> <!-- 正在记录的日志文件的路径及文件名 --> <file>${log.path}/log_info.log</file> <!--日志文件输出格式--> <encoder> <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n</pattern> <charset>UTF-8</charset> </encoder> <!-- 日志记录器的滚动策略,按日期,按大小记录 --> <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy"> <!-- 每天日志归档路径以及格式 --> <fileNamePattern>${log.path}/info/log-info-%d{yyyy-MM-dd}.%i.log</fileNamePattern> <timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP"> <maxFileSize>100MB</maxFileSize> </timeBasedFileNamingAndTriggeringPolicy> <!--日志文件保留天数--> <maxHistory>15</maxHistory> </rollingPolicy> <!-- 此日志文件只记录info级别的 --> <filter class="ch.qos.logback.classic.filter.LevelFilter"> <level>info</level> <onMatch>ACCEPT</onMatch> <onMismatch>DENY</onMismatch> </filter> </appender> <!-- 时间滚动输出 level为 WARN 日志 --> <appender name="WARN_FILE" class="ch.qos.logback.core.rolling.RollingFileAppender"> <!-- 正在记录的日志文件的路径及文件名 --> <file>${log.path}/log_warn.log</file> <!--日志文件输出格式--> <encoder> <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n</pattern> <charset>UTF-8</charset> <!-- 此处设置字符集 --> </encoder> <!-- 日志记录器的滚动策略,按日期,按大小记录 --> <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy"> <fileNamePattern>${log.path}/warn/log-warn-%d{yyyy-MM-dd}.%i.log</fileNamePattern> <timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP"> <maxFileSize>100MB</maxFileSize> </timeBasedFileNamingAndTriggeringPolicy> <!--日志文件保留天数--> <maxHistory>15</maxHistory> </rollingPolicy> <!-- 此日志文件只记录warn级别的 --> <filter class="ch.qos.logback.classic.filter.LevelFilter"> <level>warn</level> <onMatch>ACCEPT</onMatch> <onMismatch>DENY</onMismatch> </filter> </appender> <!-- 时间滚动输出 level为 ERROR 日志 --> <appender name="ERROR_FILE" class="ch.qos.logback.core.rolling.RollingFileAppender"> <!-- 正在记录的日志文件的路径及文件名 --> <file>${log.path}/log_error.log</file> <!--日志文件输出格式--> <encoder> <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n</pattern> <charset>UTF-8</charset> <!-- 此处设置字符集 --> </encoder> <!-- 日志记录器的滚动策略,按日期,按大小记录 --> <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy"> <fileNamePattern>${log.path}/error/log-error-%d{yyyy-MM-dd}.%i.log</fileNamePattern> <timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP"> <maxFileSize>100MB</maxFileSize> </timeBasedFileNamingAndTriggeringPolicy> <!--日志文件保留天数--> <maxHistory>15</maxHistory> </rollingPolicy> <!-- 此日志文件只记录ERROR级别的 --> <filter class="ch.qos.logback.classic.filter.LevelFilter"> <level>ERROR</level> <onMatch>ACCEPT</onMatch> <onMismatch>DENY</onMismatch> </filter> </appender> <!-- <logger>用来设置某一个包或者具体的某一个类的日志打印级别、 以及指定<appender>。<logger>仅有一个name属性, 一个可选的level和一个可选的addtivity属性。 name:用来指定受此logger约束的某一个包或者具体的某一个类。 level:用来设置打印级别,大小写无关:TRACE, DEBUG, INFO, WARN, ERROR, ALL 和 OFF, 还有一个特俗值INHERITED或者同义词NULL,代表强制执行上级的级别。 如果未设置此属性,那么当前logger将会继承上级的级别。 addtivity:是否向上级logger传递打印信息。默认是true。 --> <!--<logger name="org.springframework.web" level="info"/>--> <!--<logger name="org.springframework.scheduling.annotation.ScheduledAnnotationBeanPostProcessor" level="INFO"/>--> <!-- 使用mybatis的时候,sql语句是debug下才会打印,而这里我们只配置了info,所以想要查看sql语句的话,有以下两种操作: 第一种把<root level="info">改成<root level="DEBUG">这样就会打印sql,不过这样日志那边会出现很多其他消息 第二种就是单独给dao下目录配置debug模式,代码如下,这样配置sql语句会打印,其他还是正常info级别: --> <!-- root节点是必选节点,用来指定最基础的日志输出级别,只有一个level属性 level:用来设置打印级别,大小写无关:TRACE, DEBUG, INFO, WARN, ERROR, ALL 和 OFF, 不能设置为INHERITED或者同义词NULL。默认是DEBUG 可以包含零个或多个元素,标识这个appender将会添加到这个logger。 --> <!--开发环境:打印控制台--> <springProfile name="dev"> <logger name="com.nmys.view" level="debug"/> </springProfile> <root level="INFO"> <appender-ref ref="CONSOLE" /> <appender-ref ref="DEBUG_FILE" /> <appender-ref ref="INFO_FILE" /> <appender-ref ref="WARN_FILE" /> <appender-ref ref="ERROR_FILE" /> </root> <!--生产环境:输出到文件--> <!--<springProfile name="pro">--> <!--<root level="info">--> <!--<appender-ref ref="CONSOLE" />--> <!--<appender-ref ref="DEBUG_FILE" />--> <!--<appender-ref ref="INFO_FILE" />--> <!--<appender-ref ref="ERROR_FILE" />--> <!--<appender-ref ref="WARN_FILE" />--> <!--</root>--> <!--</springProfile>--> </configuration>
-
在yml配置文件中引入xml日志文件
# 配置日志相关信息 logging: # 日志配置文件的路径 config: classpath:logback-spring.xml # 配置日志输出路径 path: D:/myLog/springBootLog
-
使用注解自己定义输出日志的内容
package com.eazyshop.goods.controller; import lombok.extern.slf4j.Slf4j; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @RequestMapping("/brand") @RestController // 开启跨域支持 @CrossOrigin @Slf4j public class BrandController { @Autowired private BrandService brandService; private Logger logger= LoggerFactory.getLogger(BrandController.class); @GetMapping public Result<List<Brand>> findList(){ // 自己定义日志输出的级别与类容 log.info("牛逼的的一笔呀"); List<Brand> list = brandService.findList(); Result<List<Brand>> result = new Result<>(true, StatusCode.OK, "查询成功", list); return result; } }
Kibana中查看日志
- 在management中添加需要查看的索引
- 监控日志对应索引
// 自己定义日志输出的级别与类容
log.info("牛逼的的一笔呀");
List<Brand> list = brandService.findList();
Result<List<Brand>> result = new Result<>(true, StatusCode.OK, "查询成功", list);
return result;
}
}
## Kibana中查看日志
- 在management中添加需要查看的索引
![在这里插入图片描述](https://img-blog.csdnimg.cn/2020091810124138.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl80NjY2ODIyNQ==,size_16,color_FFFFFF,t_70#pic_center)
- 监控日志对应索引
![在这里插入图片描述](https://img-blog.csdnimg.cn/20200918101329493.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl80NjY2ODIyNQ==,size_16,color_FFFFFF,t_70#pic_center)