logstash

logstash

logstash架构

logstash部署(二进制方式)

1.解压
tar -zxf logstash-7.xx.x-linux-x86_64.tar.gz -C /opt/software

2.软连接
cd /opt/software && ln -sv logstash-7.xx.x-linux-x86_64.tar.gz logstash

3.环境变量
cat <<EOF>> /etc/profile.d/elk.sh
export LOGSTASH_HOME=/opt/software/logstash
export PATH=$PATH:$LOGSTASH_HOME/bin
EOF
source /etc/profile.d/elk.sh

4.测试案例
vim 01-stdin-to-stdout.conf
input {
  stdin {}
}

output {
  stdout {}
}

5.运行案例
logstash -f 01-stdin-to-stdout.conf

yum 启动 logstash

logstash -t -f /path/to/logstash-conf-file
-t 测试,正常启动不指定
-f 指定文件
用于测试,在终端输入内容,查看输出是否正常
vim 01-stdin-to-stdout.conf
input {
  stdin {}
}

output {
  stdout {}
}
input
input-file
创建一个 Logstash 配置文件 logstash.conf
vim logstash.conf
# 从文件收集日志
input {
  # file插件
  file {
    # 类似打标签
    type => "file"
    # 指定收集的路径
    path => "/var/log/nginx/access.log"
    # 指定文件的读取位置,仅在“.sincedb*”文件中没有记录时生效。默认值end
    start_position => "beginning"
    sincedb_path => "/dev/null"
  }
}

input-file中常用的配置项
discover_interval
logstash 每隔多久去检查一次被监听的 path 下是否有新文件。默认值是 15 秒。

exclude
不想被监听的文件可以排除出去,这里跟 path 一样支持 glob 展开

close_older
一个已经监听中的文件,如果超过这个值的时间内没有更新内容,就关闭监听它的文件句柄。默认是 3600 秒,即一小时。

ignore_older
在每次检查文件列表的时候,如果一个文件的最后修改时间超过这个值,就忽略这个文件。默认是 86400 秒,即一天。

sincedb_path
如果你不想用默认的 $HOME/.sincedb。可以通过这个配置定义 sincedb 文件到其他位置。
logstash会将以读取的文件名和位置记录到sincedb中,避免重复处理文件


sincedb_write_interval
logstash 每隔多久写一次 sincedb 文件,默认是 15 秒。

stat_interval
logstash 每隔多久检查一次被监听文件状态(是否有更新),默认是 1 秒。

start_position
logstash 从什么位置开始读取文件数据,默认是结束位置,也就是说 logstash 进程会以类似 tail -F 的形式运行。如果你是要导入原有数据,把这个设定改成 “beginning”,logstash 进程就从头开始读取,类似 less +F 的形式运行。
将 sincedb_path 定义为 /dev/null,则每次重启自动从头开始读(适用于重复测试)


input-tcp

# 从tcp收集日志
# 与filebeat类似,可以收集交换机等的日志
input {
  tcp {
    # 类似打标签
    type => "tcp"
    port => 8000
  }
}

input-http

# 从http收集日志
input {
  http {
    # 类似打标签,指定类型
    type => "tcp"
    port => 8000
  }
}

input-redis

# 从redis收集日志
input {
  redis {
    # 类似打标签
    type => "redis"
    # 指定redis的key的类型
    data_type => "list"
    # redis数据库编号,默认0
    db => 5
    # 指定数据库IP,默认localhost
    host => "10.0.0.1"
    # 指定redis的端口
    port => 6379
    # 指定redis认证密码
    password => "password"
    # 指定从redis的哪个key取数据
    key => "hello"
  }
}

filter
filter-gork
filter {
  # grok将非结构化日志数据解析为结构化和可查询的数据
  grok {
    # 指定正则
    match => { 
      # message字段中的日志行将应用默认的apache日志
      "message" => "%{COMBINEDAPACHELOG}"
    }

    # 移除指定字段
    remove_field => [ "host", "log", "@version", "agent" ]

    # 添加指定字段
    add_fielad => {
      # 在新字段和其内容中均引用现有日志中的字段,生成新的内容
      "foo_%{somefield}" => "Hello world, from %{host}"
      # 添加新的字段"new_field",其内容为"some_new_text"
      "new_field" => "some_new_text"
    }
    
    # 添加tag,即添加字段tag
    add_tag => [ "tag1", "tag2" ]

    # 移除tag
    remove_tag => ["tag1"]

    # 创建插件的唯一ID,不创建系统自动生成
    # 用于在系统中有多个grok时做区分
    id => "sometext"

  }

filter-date
  # 修改@timestamp的时间为为日志的实际生成时间  
  date {
    # 用日志中的logdate字段记录的时间,覆盖@timestamp的时间
    # logstash的输出时间可能会错8小时,但写入es的时间是准确的
    match => ["logdate", "dd/MMM/yyyy:HH:mm:ss +0800"]
    # 将时区字段设置为UTC,写入es的时间不准确
    timezone => "UTS"
    # 这样准确
    timezone => "Asia/Shanghai" 
    # 将匹配到的时间字段解析后存储到目标字段,若不指定,默认字段为"@timestamp"
    target => "my-timestamp"
  }

filter-geoip 分析日志中IP来源
  geoip {
    # 指定基于哪个字段分析IP地址
    source => "clientip"
    # 只显示指定字段
    fields => ["city_name", "country_name", "ip"]
    # 自定义geoip字段名称,默认字段是geoip
    # 当日志中有源IP和目标IP时,可以分开记录
    target => "my-src_ip"
  }

filter-useragent 分析日志中的设备类型
  useragent {
    # 指定要分析的包含设备信息的字段
    source => "http_user_agent"
    # 将分析后的数据存储在指定字段中,不指定,则存储在tartget字段中
    target => "my-useragent"
}

filter-mutate  对字段执行转变,可以重命名、移除、替换和修改日志中的字段
转变要按顺序进行,通过使用单独的mutate块来控制顺序
有修改的选项尽量写下边
  mutate {
    # 分割字段
    split => { "message" => "|" }
    # 添加字段,其中引用的变量
    add_field => {
      "user_id" => "%{[message][1]}"
      "action" => "%{[message][2]}"
      "svip" => "%{[message][3]}"
      }
  }
 
  mutate {
    # 去除字段前后的空格
    strip => ["svip"]
  }

  mutate {
    # 将指定字段转换为相应的数据类型
    convert => {
      "user_id" => "integer"
      "svip" => "boolean"
    }
  }

  mutate {
    # 重命名字段
    rename => {"shortHostname" => "hostname"}
  }  

  # 根据type值执行分支
  if [type] == "sometext" {
    mutate {
      ...
    }
    geoip {
      ...
    }
    useragent {
      ...
    }
  }

}

output
output-elasticsearch
# 输出到es
output {
  elasticsearch {
    hosts => ["http://esIP:9200"]
    # 指定索引,该索引与kibana中的索引模板匹配,则会引用模板中的规则
    index => "sometext-%{+YYYY.MM.dd}"
  }
}

output-redis

# 输出到redis
output {
  redis {
    host => ["http://esIP:9200"]
    port => "6379"
    db => 10
    password => "password"
    # 指定写入数据的key的类型
    data_type => "list"
    # 指定写入的key的名称
    key => "my-key"
  }
}

outpu-file

# 输出到file
output {
  file {
    path => "/path/to/file"
  }
}

grok语法说明

grok是一个文本解析工具,用于从非结构化的日志数据中提取字段,并将其转换为结构化的数据
grok使用正则和模式来匹配日志行,内置120种匹配模式

语法
%{PATTERN:fieldName}
PATTERN 是用于匹配日志行的正则表达式模式,fieldName 是您要将匹配部分提取为的字段名。

例子
假设日志行如下,我们希望从日志行中提取日期时间和日志级别,并将它们作为字段存储。
2023-07-19 10:30:01,123 - INFO - This is a log message.

可以使用以下 Grok 模式:
%{DATESTAMP:timestamp} - %{LOGLEVEL:logLevel} - %{GREEDYDATA:message}

解释:
* %{DATESTAMP:timestamp} 匹配日期时间格式,将匹配部分存储为 timestamp 字段。
* - 匹配短横线 - 字符。
* %{LOGLEVEL:logLevel} 匹配日志级别,将匹配部分存储为 logLevel 字段。
* - 匹配短横线 - 字符。
* %{GREEDYDATA:message} 匹配剩余的任意文本,并将匹配部分存储为 message 字段。

最终,Logstash 将解析日志行并将提取的字段存储为结构化数据,类似于以下格式:
{ 
"timestamp": "2023-07-19 10:30:01,123", 
"logLevel": "INFO", 
message": "This is a log message." 
}

在 Logstash 的配置文件中,您可以使用 grok 过滤器插件来应用 Grok 模式。例如:
filter { 
  grok { 
    match => { 
      "message" => "%{DATESTAMP:timestamp} - %{LOGLEVEL:logLevel} - %{GREEDYDATA:message}" 
    }
  } 
}

自定义grok匹配模式

filter { 
  grok { 
    # 自定义匹配模式目录,名称随意
    # 具体的匹配模式写在该目录下的文件中
    patterns_dir => "/path/to/patterns" 

    # 将日志行中的字段提取为新的字段 
    match => { 
      "message" => "%{SYSLOGBASE} %{POSTFIX_QUEUEID:queue_id}: %{GREEDYDATA:syslog_message}"
    } 
  } 
}

vim /path/to/patterns/custom-pattern
# 匹配的字段名和具体的匹配正则
POSTFIX_QUEUEID [0-9A-F]{10,11}

logstash内置匹配模式位置

/usr/share/logstash/vendor/bundle/jruby/2.5.0/gems/logstash-patterns-core-4.3.1/patterns/legacy/grok-patterns

filebeat和logstash打通,input模块基于beats插件

filebeat配置
filebeat.inputs:
- type: tcp
  # filebeat开启9000端口,接收日志
  host: "0.0.0.0:9000"

output.logstash:
  # 输出到logstash的5044端口
  hosts: ["10.0.0.101:5044"]

logstash配置
input{
  # 从elastic beats框架接收事件
  beats {
    # logstash从本机的5044端口接收filebeat传来的日志
    port => 5044
  }
}

output {
  stdout {}
}

logstash多实例案例

logstash -f /path/to/logstash.conf --path.data /other/path/to/logstash.conf

--path.data   指定不同的配置文件启动

mutate 数据准备

脚本模拟日志生成

vim generate_log.py

#!/usr/bin/env python
# _*_ coding: UTF-8 _*_

import datetime
import random
import logging
import time
import sys

LOG_FORMAT = "%{levelname}s %{asctime}s [com.hello.%{module}s] - %{message}s"
DATE_FORMAT = "%Y-%m-%d %H:%M:%S"

logging.basicConfig(level=logging.INFO, format=LOG_FORMAT, datefmt=DATE_FORMAT, filename=sys.argv[1], filemode='a',)
actions = ["浏览商品", "加购物车", "提交订单", "领券", "用券", "搜索"]

while True:
  time.sleep(random.randint(1, 5))
  user_id = random.randint(1, 10000)
  # 取浮点数
  price = round(random.uniform(1000,300000),2)
  action = random.choice(actions)
  svip = random.choice([0,1])
  logging.info("DAU|{0}|{1}|{2}|{3}".format(user_id, action, svip, price))

python generate_log.py /tmp/my.log
posted @ 2024-05-24 11:38  立勋  阅读(1)  评论(0编辑  收藏  举报