1 Logstash学习

1.1 Logstash是什么?

什么是Logstash.png

  • Logstash是一个数据抽取工具,将数据从一个地方转移到另一个地方。
  • Logstash值所以功能强大和流行,还和其丰富的过滤器插件是分不开的,过滤器提供的并不单单是过滤的功能,还可以对进入过滤器的原始数据进行复杂的逻辑处理,甚至添加独特的事件到后续流程中。
  • Logstash配置文件有三个部分组成,其中input、output部分是必须配置,filter部分是可选配置,而filter就是过滤器插件,可以在这部分实现各种日志过滤功能。

1.2 配置文件

  1. input{
  2. # 输入插件
  3. }
  4. filter{
  5. # 过滤匹配插件
  6. }
  7. output{
  8. # 输出插件
  9. }

1.3 启动操作

  • 启动命令(Windows下):表示输入源是控制台,输出源是控制台
  1. logstash.bat -e 'input{stdin{}} output{stdout{}}'
  • 启动命令(Windows下):将配置写入到配置文件中
  • Logstash/conf目录下新建test1.conf
  1. input {
  2. stdin {
  3. }
  4. }
  5. output {
  6. stdout {
  7. codec=>rubydebug
  8. }
  9. }
  • 启动:
  1. logstash.bat -f ../config/test1.conf

1.4 Logstash输入插件(input)

1.4.1 官网说明

1.4.2 标注输入(stdin)

  1. input{
  2. stdin{
  3. }
  4. }
  5. output{
  6. stdout {
  7. codec=>rubydebug
  8. }
  9. }

1.4.3 读取文件(file)

  • Logstash使用一个名为filewatch的ruby gem库来监听文件变化,并通过一个叫sincedb的数据库文件来记录被监听的日志文件的读取进度(时间戳),这个sincedb数据文件的默认路径在<path.data>/plugins/inputs/file下面,文件名类似于.sincedb_123456,而<path.data>表示logstash插件存储目录,默认是LOGSTASH_HOME/data。
  1. input {
  2. file {
  3. path => ["/var/*/*"]
  4. start_position => "beginning"
  5. }
  6. }
  7. output {
  8. stdout{
  9. codec=>rubydebug
  10. }
  11. }

默认情况下,Logstash会从文件的结束位置开始读取数据,也就是说Logstash进程会以类似tail -f命令的形式逐行获取数据。

1.4.4 读取TCP网络

  1. input {
  2. tcp {
  3. port => "1234"
  4. }
  5. }
  6. filter {
  7. grok {
  8. match => { "message" => "%{SYSLOGLINE}" }
  9. }
  10. }
  11. output {
  12. stdout{
  13. codec=>rubydebug
  14. }
  15. }

1.5 Logstash过滤器插件(filter)

1.5.1 官网说明

1.5.2 Grok正则捕获

  • Grok是一个非常强大的Logstash Filter插件,它可以通过正则解析任意文本,将非结构化的日志数据弄成结构化以方便查询,它是目前Logstash中解析非结构化日志数据的最好方式。
  • Grok的语法规则是:
  1. %{语法:语义}
  • 假设输入的内容如下:
  1. 172.16.213.132 [07/Feb/2019:16:24:19 +0800] "GET / HTTP/1.1" 403 5039

%{IP:clientip}匹配默认获取的结果为:clientip: 172.16.213.132。 %{HTTPDATE:timestamp}匹配模式将获得的结果为:timestamp: 07/Feb/2018:16:24:19 +0800。 %{QS:referrer}匹配模式将获得的结果为:referrer: “GET / HTTP/1.1”。

  • 下面是一组组合匹配默认,可以获取上面输入的内容:
  1. %{IP:clientip}\ \[%{HTTPDATE:timestamp}\]\ %{QS:referrer}\ %{NUMBER:response}\ %{NUMBER:bytes}
  • 通过上面的这个组合匹配模式,我们将输入的内容分为了5个部分,即5个字段,将输入内容分割为不同的数据字段,这对于日后解析和查询日志数据非常重要,这也是使用Grok的目的。
  1. input{
  2. stdin{}
  3. }
  4. filter{
  5. grok{
  6. match => ["message","%{IP:clientip}\ \[%{HTTPDATE:timestamp}\]\ %{QS:referrer}\ %{NUMBER:response}\ %{NUMBER:bytes}"]
  7. }
  8. }
  9. output{
  10. stdout{
  11. codec => "rubydebug"
  12. }
  13. }

1.5.3 Date时间处理

  • Date是阿金是对于排序时间和回填就数据尤其重要,它可以用来转换日志记录中的时间字段,变成Logstatsh::Timestamp对象,然后转存到@Timestamp字段里面。
  1. filter {
  2. grok {
  3. match => ["message", "%{HTTPDATE:timestamp}"]
  4. }
  5. date {
  6. match => ["timestamp", "dd/MMM/yyyy:HH:mm:ss Z"]
  7. }
  8. }

1.5.4 Mutate数据修改

  • ELK06 - 图2gsub:gsub可以通过正则表达式替换字段中匹配到的值,只对字符串有效。
  1. filter {
  2. mutate {
  3. gsub => ["filed_name_1", "/" , "_"]
  4. }
  5. }
  • ELK06 - 图3split:split可以通过指定的分隔符分割字段中的字符串为数组。
  1. filter {
  2. mutate {
  3. split => ["filed_name_2", "|"]
  4. }
  5. }
  • ELK06 - 图4rename:可以实现重命名某个字段的功能。
  1. filter {
  2. mutate {
  3. rename => { "old_field" => "new_field" }
  4. }
  5. }
  • ELK06 - 图5remove_field:可以实现删除某个字段的功能。
  1. filter {
  2. mutate {
  3. remove_field => ["timestamp"]
  4. }
  5. }
  • ELK06 - 图6geoip:地址查询归类。
  1. filter {
  2. geoip {
  3. source => "ip_field"
  4. }
  5. }
  • 示例:
  1. input {
  2. stdin {}
  3. }
  4. filter {
  5. grok {
  6. match => { "message" => "%{IP:clientip}\ \[%{HTTPDATE:timestamp}\]\ %{QS:referrer}\ %{NUMBER:response}\ %{NUMBER:bytes}" }
  7. remove_field => [ "message" ]
  8. }
  9. date {
  10. match => ["timestamp", "dd/MMM/yyyy:HH:mm:ss Z"]
  11. }
  12. mutate {
  13. convert => [ "response","float" ]
  14. rename => { "response" => "response_new" }
  15. gsub => ["referrer","\"",""]
  16. split => ["clientip", "."]
  17. }
  18. }
  19. output {
  20. stdout {
  21. codec => "rubydebug"
  22. }
  23. }

1.6 Logstash输出插件(output)

1.6.1 官网说明

1.6.2 概述

  • output是Logstash的最后阶段,一个事件可以经过多个输出,而一旦所有输出处理完成,整个事件就执行完成。一些常用的输出包括:
  • file:表示将日志数据写入磁盘上的文件。
  • elasticsearch:表示将日志数据发送给ElasticSearch。ElasticSearch可以高效方便和易于查询的保存数据。

1.6.3 输出到标准输出(stdout)

  1. output {
  2. stdout {
  3. codec => rubydebug
  4. }
  5. }

1.6.4 保存到文件(file)

  1. output {
  2. file {
  3. path => "/data/log/%{+yyyy-MM-dd}/%{host}_%{+HH}.log"
  4. }
  5. }

1.6.5 输出到ElasticSearch

  1. output {
  2. elasticsearch {
  3. host => ["192.168.1.1:9200","172.16.213.77:9200"]
  4. index => "logstash-%{+YYYY.MM.dd}"
  5. }
  6. }
  • host:是一个数组类型的值,后面跟的值是elasticsearch节点的地址与端口,默认端口是9200。可添加多个地址。
  • index:写入elasticsearch的索引的名称,这里可以使用变量。Logstash提供了%{+YYYY.MM.dd}这种写法。在语法解析的时候,看到以+ 号开头的,就会自动认为后面是时间格式,尝试用时间格式来解析后续字符串。这种以天为单位分割的写法,可以很容易的删除老的数据或者搜索指定时间范围内的数据。此外,注意索引名中不能有大写字母。
  • manage_template:用来设置是否开启logstash自动管理模板功能,如果设置为false将关闭自动管理模板功能。如果我们自定义了模板,那么应该设置为false。
  • template_name:这个配置项用来设置在Elasticsearch中模板的名称。

1.7 综合案例

  1. input {
  2. file {
  3. path => ["D:/ES/logstash-7.3.0/nginx.log"]
  4. start_position => "beginning"
  5. }
  6. }
  7. filter {
  8. grok {
  9. match => { "message" => "%{IP:clientip}\ \[%{HTTPDATE:timestamp}\]\ %{QS:referrer}\ %{NUMBER:response}\ %{NUMBER:bytes}" }
  10. remove_field => [ "message" ]
  11. }
  12. date {
  13. match => ["timestamp", "dd/MMM/yyyy:HH:mm:ss Z"]
  14. }
  15. mutate {
  16. rename => { "response" => "response_new" }
  17. convert => [ "response","float" ]
  18. gsub => ["referrer","\"",""]
  19. remove_field => ["timestamp"]
  20. split => ["clientip", "."]
  21. }
  22. }
  23. output {
  24. stdout {
  25. codec => "rubydebug"
  26. }
  27. elasticsearch {
  28. host => ["localhost:9200"]
  29. index => "logstash-%{+YYYY.MM.dd}"
  30. }
  31. }

2 集群部署

2.1 集群部署图

集群部署图.png

2.2 节点的三个角色

  • 主节点:Master节点主要用于集群的管理及索引,比如新增节点、分配分片、新增和删除索引等。
  • 数据节点:数据节点上保存了数据分片,它负责索引和搜索的操作。
  • 客户端节点:客户端节点仅作为请求客户端存在,客户端节点的作用也作为负责均衡器,客户端节点不保存数据,只是将请求均衡发送到其他的节点。
  • 通过下面的参数来配置节点的功能:
  1. node.master: true/fase; #是否允许为主结点
  2. node.data: true/fase;#允许存储数据作为数据结点
  3. node.ingest: true/fase;#是否允许成为协调节点
  • 四种组合方式:
  1. master=truedata=true:即是主结点又是数据结点
  2. master=falsedata=true:仅是数据结点
  3. master=truedata=false:仅是主结点,不存储数据
  4. master=falsedata=false:即不是主结点也不是数据结点,此时可设置ingesttrue表示它是一个客户端。

3 附录

3.1 Grok内置类型

  1. USER %{USERNAME}
  2. INT (?:[+-]?(?:[0-9]+))
  3. BASE10NUM (?<![0-9.+-])(?>[+-]?(?:(?:[0-9]+(?:\.[0-9]+)?)|(?:\.[0-9]+)))
  4. NUMBER (?:%{BASE10NUM})
  5. BASE16NUM (?<![0-9A-Fa-f])(?:[+-]?(?:0x)?(?:[0-9A-Fa-f]+))
  6. BASE16FLOAT \b(?<![0-9A-Fa-f.])(?:[+-]?(?:0x)?(?:(?:[0-9A-Fa-f]+(?:\.[0-9A-Fa-f]*)?)|(?:\.[0-9A-Fa-f]+)))\b
  7. POSINT \b(?:[1-9][0-9]*)\b
  8. NONNEGINT \b(?:[0-9]+)\b
  9. WORD \b\w+\b
  10. NOTSPACE \S+
  11. SPACE \s*
  12. DATA .*?
  13. GREEDYDATA .*
  14. QUOTEDSTRING (?>(?<!\\)(?>"(?>\\.|[^\\"]+)+"|""|(?>'(?>\\.|[^\\']+)+')|''|(?>`(?>\\.|[^\\`]+)+`)|``))
  15. UUID [A-Fa-f0-9]{8}-(?:[A-Fa-f0-9]{4}-){3}[A-Fa-f0-9]{12}
  16. # Networking
  17. MAC (?:%{CISCOMAC}|%{WINDOWSMAC}|%{COMMONMAC})
  18. CISCOMAC (?:(?:[A-Fa-f0-9]{4}\.){2}[A-Fa-f0-9]{4})
  19. WINDOWSMAC (?:(?:[A-Fa-f0-9]{2}-){5}[A-Fa-f0-9]{2})
  20. COMMONMAC (?:(?:[A-Fa-f0-9]{2}:){5}[A-Fa-f0-9]{2})
  21. IPV6 ((([0-9A-Fa-f]{1,4}:){7}([0-9A-Fa-f]{1,4}|:))|(([0-9A-Fa-f]{1,4}:){6}(:[0-9A-Fa-f]{1,4}|((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3})|:))|(([0-9A-Fa-f]{1,4}:){5}(((:[0-9A-Fa-f]{1,4}){1,2})|:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3})|:))|(([0-9A-Fa-f]{1,4}:){4}(((:[0-9A-Fa-f]{1,4}){1,3})|((:[0-9A-Fa-f]{1,4})?:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){3}(((:[0-9A-Fa-f]{1,4}){1,4})|((:[0-9A-Fa-f]{1,4}){0,2}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){2}(((:[0-9A-Fa-f]{1,4}){1,5})|((:[0-9A-Fa-f]{1,4}){0,3}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){1}(((:[0-9A-Fa-f]{1,4}){1,6})|((:[0-9A-Fa-f]{1,4}){0,4}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(:(((:[0-9A-Fa-f]{1,4}){1,7})|((:[0-9A-Fa-f]{1,4}){0,5}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:)))(%.+)?
  22. IPV4 (?<![0-9])(?:(?:25[0-5]|2[0-4][0-9]|[0-1]?[0-9]{1,2})[.](?:25[0-5]|2[0-4][0-9]|[0-1]?[0-9]{1,2})[.](?:25[0-5]|2[0-4][0-9]|[0-1]?[0-9]{1,2})[.](?:25[0-5]|2[0-4][0-9]|[0-1]?[0-9]{1,2}))(?![0-9])
  23. IP (?:%{IPV6}|%{IPV4})
  24. HOSTNAME \b(?:[0-9A-Za-z][0-9A-Za-z-]{0,62})(?:\.(?:[0-9A-Za-z][0-9A-Za-z-]{0,62}))*(\.?|\b)
  25. HOST %{HOSTNAME}
  26. IPORHOST (?:%{HOSTNAME}|%{IP})
  27. HOSTPORT %{IPORHOST}:%{POSINT}
  28. # paths
  29. PATH (?:%{UNIXPATH}|%{WINPATH})
  30. UNIXPATH (?>/(?>[\w_%!$@:.,-]+|\\.)*)+
  31. TTY (?:/dev/(pts|tty([pq])?)(\w+)?/?(?:[0-9]+))
  32. WINPATH (?>[A-Za-z]+:|\\)(?:\\[^\\?*]*)+
  33. URIPROTO [A-Za-z]+(\+[A-Za-z+]+)?
  34. URIHOST %{IPORHOST}(?::%{POSINT:port})?
  35. # uripath comes loosely from RFC1738, but mostly from what Firefox
  36. # doesn't turn into %XX
  37. URIPATH (?:/[A-Za-z0-9$.+!*'(){},~:;=@#%_\-]*)+
  38. #URIPARAM \?(?:[A-Za-z0-9]+(?:=(?:[^&]*))?(?:&(?:[A-Za-z0-9]+(?:=(?:[^&]*))?)?)*)?
  39. URIPARAM \?[A-Za-z0-9$.+!*'|(){},~@#%&/=:;_?\-\[\]]*
  40. URIPATHPARAM %{URIPATH}(?:%{URIPARAM})?
  41. URI %{URIPROTO}://(?:%{USER}(?::[^@]*)?@)?(?:%{URIHOST})?(?:%{URIPATHPARAM})?
  42. # Months: January, Feb, 3, 03, 12, December
  43. MONTH \b(?:Jan(?:uary)?|Feb(?:ruary)?|Mar(?:ch)?|Apr(?:il)?|May|Jun(?:e)?|Jul(?:y)?|Aug(?:ust)?|Sep(?:tember)?|Oct(?:ober)?|Nov(?:ember)?|Dec(?:ember)?)\b
  44. MONTHNUM (?:0?[1-9]|1[0-2])
  45. MONTHNUM2 (?:0[1-9]|1[0-2])
  46. MONTHDAY (?:(?:0[1-9])|(?:[12][0-9])|(?:3[01])|[1-9])
  47. # Days: Monday, Tue, Thu, etc...
  48. DAY (?:Mon(?:day)?|Tue(?:sday)?|Wed(?:nesday)?|Thu(?:rsday)?|Fri(?:day)?|Sat(?:urday)?|Sun(?:day)?)
  49. # Years?
  50. YEAR (?>\d\d){1,2}
  51. HOUR (?:2[0123]|[01]?[0-9])
  52. MINUTE (?:[0-5][0-9])
  53. # '60' is a leap second in most time standards and thus is valid.
  54. SECOND (?:(?:[0-5]?[0-9]|60)(?:[:.,][0-9]+)?)
  55. TIME (?!<[0-9])%{HOUR}:%{MINUTE}(?::%{SECOND})(?![0-9])
  56. # datestamp is YYYY/MM/DD-HH:MM:SS.UUUU (or something like it)
  57. DATE_US %{MONTHNUM}[/-]%{MONTHDAY}[/-]%{YEAR}
  58. DATE_EU %{MONTHDAY}[./-]%{MONTHNUM}[./-]%{YEAR}
  59. ISO8601_TIMEZONE (?:Z|[+-]%{HOUR}(?::?%{MINUTE}))
  60. ISO8601_SECOND (?:%{SECOND}|60)
  61. TIMESTAMP_ISO8601 %{YEAR}-%{MONTHNUM}-%{MONTHDAY}[T ]%{HOUR}:?%{MINUTE}(?::?%{SECOND})?%{ISO8601_TIMEZONE}?
  62. DATE %{DATE_US}|%{DATE_EU}
  63. DATESTAMP %{DATE}[- ]%{TIME}
  64. TZ (?:[PMCE][SD]T|UTC)
  65. DATESTAMP_RFC822 %{DAY} %{MONTH} %{MONTHDAY} %{YEAR} %{TIME} %{TZ}
  66. DATESTAMP_RFC2822 %{DAY}, %{MONTHDAY} %{MONTH} %{YEAR} %{TIME} %{ISO8601_TIMEZONE}
  67. DATESTAMP_OTHER %{DAY} %{MONTH} %{MONTHDAY} %{TIME} %{TZ} %{YEAR}
  68. DATESTAMP_EVENTLOG %{YEAR}%{MONTHNUM2}%{MONTHDAY}%{HOUR}%{MINUTE}%{SECOND}
  69. # Syslog Dates: Month Day HH:MM:SS
  70. SYSLOGTIMESTAMP %{MONTH} +%{MONTHDAY} %{TIME}
  71. PROG (?:[\w._/%-]+)
  72. SYSLOGPROG %{PROG:program}(?:\[%{POSINT:pid}\])?
  73. SYSLOGHOST %{IPORHOST}
  74. SYSLOGFACILITY <%{NONNEGINT:facility}.%{NONNEGINT:priority}>
  75. HTTPDATE %{MONTHDAY}/%{MONTH}/%{YEAR}:%{TIME} %{INT}
  76. # Shortcuts
  77. QS %{QUOTEDSTRING}
  78. # Log formats
  79. SYSLOGBASE %{SYSLOGTIMESTAMP:timestamp} (?:%{SYSLOGFACILITY} )?%{SYSLOGHOST:logsource} %{SYSLOGPROG}:
  80. COMMONAPACHELOG %{IPORHOST:clientip} %{USER:ident} %{USER:auth} \[%{HTTPDATE:timestamp}\] "(?:%{WORD:verb} %{NOTSPACE:request}(?: HTTP/%{NUMBER:httpversion})?|%{DATA:rawrequest})" %{NUMBER:response} (?:%{NUMBER:bytes}|-)
  81. COMBINEDAPACHELOG %{COMMONAPACHELOG} %{QS:referrer} %{QS:agent}
  82. # Log Levels
  83. LOGLEVEL ([Aa]lert|ALERT|[Tt]race|TRACE|[Dd]ebug|DEBUG|[Nn]otice|NOTICE|[Ii]nfo|INFO|[Ww]arn?(?:ing)?|WARN?(?:ING)?|[Ee]rr?(?:or)?|ERR?(?:OR)?|[Cc]rit?(?:ical)?|CRIT?(?:ICAL)?|[Ff]atal|FATAL|[Ss]evere|SEVERE|EMERG(?:ENCY)?|[Ee]merg(?:ency)?)

4 ELK用于分析日志

4.1 logback-spring.xml

  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <configuration>
  3. <!--定义日志文件的存储地址,使用绝对路径-->
  4. <property name="LOG_HOME" value="d:/logs"/>
  5. <!-- Console 输出设置 -->
  6. <appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
  7. <encoder>
  8. <!--格式化输出:%d表示日期,%thread表示线程名,%-5level:级别从左显示5个字符宽度%msg:日志消息,%n是换行符-->
  9. <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern>
  10. <charset>utf8</charset>
  11. </encoder>
  12. </appender>
  13. <!-- 按照每天生成日志文件 -->
  14. <appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
  15. <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
  16. <!--日志文件输出的文件名-->
  17. <fileNamePattern>${LOG_HOME}/log-%d{yyyy-MM-dd}.log</fileNamePattern>
  18. </rollingPolicy>
  19. <encoder>
  20. <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern>
  21. </encoder>
  22. </appender>
  23. <!-- 异步输出 -->
  24. <appender name="ASYNC" class="ch.qos.logback.classic.AsyncAppender">
  25. <!-- 不丢失日志.默认的,如果队列的80%已满,则会丢弃TRACT、DEBUG、INFO级别的日志 -->
  26. <discardingThreshold>0</discardingThreshold>
  27. <!-- 更改默认的队列的深度,该值会影响性能.默认值为256 -->
  28. <queueSize>512</queueSize>
  29. <!-- 添加附加的appender,最多只能添加一个 -->
  30. <appender-ref ref="FILE"/>
  31. </appender>
  32. <logger name="org.apache.ibatis.cache.decorators.LoggingCache" level="DEBUG" additivity="false">
  33. <appender-ref ref="CONSOLE"/>
  34. </logger>
  35. <logger name="org.springframework.boot" level="DEBUG"/>
  36. <root level="info">
  37. <!--<appender-ref ref="ASYNC"/>-->
  38. <appender-ref ref="FILE"/>
  39. <appender-ref ref="CONSOLE"/>
  40. </root>
  41. </configuration>

4.2 逻辑程序块输出日志

  • 示例:
  1. package com.sunxiaping.elk;
  2. import org.junit.jupiter.api.Test;
  3. import org.slf4j.Logger;
  4. import org.slf4j.LoggerFactory;
  5. import org.springframework.boot.test.context.SpringBootTest;
  6. import java.util.Random;
  7. @SpringBootTest
  8. public class TestLog {
  9. private static final Logger LOGGER = LoggerFactory.getLogger(TestLog.class);
  10. @Test
  11. public void test() {
  12. Random random = new Random();
  13. while (true) {
  14. int userId = random.nextInt(10);
  15. LOGGER.info("userId:{},send:{}", userId, "hello world.I am " + userId);
  16. try {
  17. Thread.sleep(500);
  18. } catch (InterruptedException e) {
  19. e.printStackTrace();
  20. }
  21. }
  22. }
  23. }

4.3 Logstash收集日志到ES中

  • logstash.conf
  1. input {
  2. file {
  3. path => ["D:/logs/log-x.log"]
  4. start_position => "beginning"
  5. }
  6. }
  7. filter {
  8. grok {
  9. match => { "message" => "%{DATA:datetime}\ \[%{DATA:thread}\]\ %{DATA:level}\ \ %{DATA:class} - %{GREEDYDATA:logger}" }
  10. remove_field => [ "message" ]
  11. }
  12. date {
  13. match => ["timestamp", "dd/MMM/yyyy:HH:mm:ss Z"]
  14. }
  15. if "_grokparsefailure" in [tags] {
  16. drop { }
  17. }
  18. }
  19. output {
  20. elasticsearch {
  21. hosts => ["127.0.0.1:9200"]
  22. index => "logstash-%{+YYYY.MM.dd}"
  23. }
  24. }
  • 启动Logstash:
  1. logstash.bat -f ../config/logstash.conf