elasticsearch Logstash中的节拍输入正在丢失字段,elasticsearch,nginx,logstash,filebeat,elastic-beats,elasticsearch,Nginx,Logstash,Filebeat,Elastic Beats" /> elasticsearch Logstash中的节拍输入正在丢失字段,elasticsearch,nginx,logstash,filebeat,elastic-beats,elasticsearch,Nginx,Logstash,Filebeat,Elastic Beats" />

elasticsearch Logstash中的节拍输入正在丢失字段

elasticsearch Logstash中的节拍输入正在丢失字段,elasticsearch,nginx,logstash,filebeat,elastic-beats,elasticsearch,Nginx,Logstash,Filebeat,Elastic Beats,我拥有以下基础设施: 麋鹿作为码头集装箱安装,每个集装箱都有自己的集装箱。在运行CentOS的虚拟机上,我安装了nginx web服务器和Filebeat来收集日志。 我在filebeat中启用了nginx模块 > filebeat modules enable nginx 在开始filebeat之前,我用elasticsearch设置了它,并在kibana上安装了它的仪表盘 配置文件(我已从文件中删除了不必要的注释): 然后在elasticsearch和kibana中进行设置 >

我拥有以下基础设施:

麋鹿作为码头集装箱安装,每个集装箱都有自己的集装箱。在运行CentOS的虚拟机上,我安装了nginx web服务器和Filebeat来收集日志。 我在filebeat中启用了nginx模块

> filebeat modules enable nginx
在开始filebeat之前,我用elasticsearch设置了它,并在kibana上安装了它的仪表盘

配置文件(我已从文件中删除了不必要的注释):

然后在elasticsearch和kibana中进行设置

> filebeat setup -e --dashboards
这个很好用。事实上,如果我保持这种方式,一切都会很完美。我可以使用kibana中收集的日志,并使用使用上述命令安装的NGinX I仪表盘

不过我想把日志传给Logstash。 下面是我的日志存储配置,它使用以下管道:

- pipeline.id: filebeat
  path.config: "config/filebeat.conf"
filebeat.conf:

input {
  beats {
    port => 5044
  }
}


#filter {
#  mutate {
#    add_tag => ["filebeat"]
#  }
#}


output {
  elasticsearch {
    hosts => ["elasticsearch0:9200"]
    index => "%{[@metadata][beat]}-%{[@metadata][version]}-%{+YYYY.MM.dd}"
  }

  stdout { }
}
使日志通过Logstash生成的日志只是:

{
        "offset" => 6655,
      "@version" => "1",
    "@timestamp" => 2019-02-20T13:34:06.886Z,
       "message" => "10.0.2.2 - - [20/Feb/2019:08:33:58 -0500] \"GET / HTTP/1.1\" 304 0 \"-\" \"Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Ubuntu Chromium/71.0.3578.98 Chrome/71.0.3578.98 Safari/537.36\" \"-\"",
          "beat" => {
         "version" => "6.5.4",
            "name" => "localhost.localdomain",
        "hostname" => "localhost.localdomain"
    },
        "source" => "/var/log/nginx/access.log",
          "host" => {
                   "os" => {
             "version" => "7 (Core)",
            "codename" => "Core",
              "family" => "redhat",
            "platform" => "centos"
        },
                 "name" => "localhost.localdomain",
                   "id" => "18e7cb2506624fb6ae2dc3891d5d7172",
        "containerized" => true,
         "architecture" => "x86_64"
    },
       "fileset" => {
          "name" => "access",
        "module" => "nginx"
    },
          "tags" => [
        [0] "beats_input_codec_plain_applied"
    ],
         "input" => {
        "type" => "log"
    },
    "prospector" => {
        "type" => "log"
    }
}
我的对象中缺少很多字段。应该有更多的结构化信息

更新:这正是我所期待的
从您的日志存储配置来看,您似乎没有解析日志消息

logstash文档中有一个关于如何解析nginx日志的示例:

Nginx日志

本例中的Logstash管道配置显示了如何发送和解析nginx Filebeat模块收集的访问和错误日志

  input {
    beats {
      port => 5044
      host => "0.0.0.0"
    }
  }
  filter {
    if [fileset][module] == "nginx" {
      if [fileset][name] == "access" {
        grok {
          match => { "message" => ["%{IPORHOST:[nginx][access][remote_ip]} - %{DATA:[nginx][access][user_name]} \[%{HTTPDATE:[nginx][access][time]}\] \"%{WORD:[nginx][access][method]} %{DATA:[nginx][access][url]} HTTP/%{NUMBER:[nginx][access][http_version]}\" %{NUMBER:[nginx][access][response_code]} %{NUMBER:[nginx][access][body_sent][bytes]} \"%{DATA:[nginx][access][referrer]}\" \"%{DATA:[nginx][access][agent]}\""] }
          remove_field => "message"
        }
        mutate {
          add_field => { "read_timestamp" => "%{@timestamp}" }
        }
        date {
          match => [ "[nginx][access][time]", "dd/MMM/YYYY:H:m:s Z" ]
          remove_field => "[nginx][access][time]"
        }
        useragent {
          source => "[nginx][access][agent]"
          target => "[nginx][access][user_agent]"
          remove_field => "[nginx][access][agent]"
        }
        geoip {
          source => "[nginx][access][remote_ip]"
          target => "[nginx][access][geoip]"
        }
      }
      else if [fileset][name] == "error" {
        grok {
          match => { "message" => ["%{DATA:[nginx][error][time]} \[%{DATA:[nginx][error][level]}\] %{NUMBER:[nginx][error][pid]}#%{NUMBER:[nginx][error][tid]}: (\*%{NUMBER:[nginx][error][connection_id]} )?%{GREEDYDATA:[nginx][error][message]}"] }
          remove_field => "message"
        }
        mutate {
          rename => { "@timestamp" => "read_timestamp" }
        }
        date {
          match => [ "[nginx][error][time]", "YYYY/MM/dd H:m:s" ]
          remove_field => "[nginx][error][time]"
        }
      }
    }
  }

我知道它不涉及filebeat为什么不向logstash发送完整对象,但它应该开始分析logstash中的nginx日志。

由@baudsp提供的答案基本正确,但不完整。我有完全相同的问题,我也有完全相同的问题(在@baudsp的答案中),但弹性搜索中的文档仍然不包含任何预期字段

我最终发现了问题:因为我将Filebeat配置为通过而不是通过发送Nginx日志,所以来自Logbeat的数据与示例Logstash筛选器的预期不完全匹配

本例中的条件是
if[fileset][module]==“nginx”
,如果Filebeat从日志输入发送数据,则该条件是正确的。但是,由于日志数据来自Nginx模块,因此
文件集
属性不包含
模块
属性

为了使过滤器能够处理来自Nginx模块的日志数据,需要修改条件以查找其他内容。我发现
[event][module]
替代了
[fileset][module]

工作过滤器:

filter {
  if [event][module] == "nginx" {
    if [fileset][name] == "access" {
      grok {
        match => { "message" => ["%{IPORHOST:[nginx][access][remote_ip]} - %{DATA:[nginx][access][user_name]} \[%{HTTPDATE:[nginx][access][time]}\] \"%{WORD:[nginx][access][method]} %{DATA:[nginx][access][url]} HTTP/%{NUMBER:[nginx][access][http_version]}\" %{NUMBER:[nginx][access][response_code]} %{NUMBER:[nginx][access][body_sent][bytes]} \"%{DATA:[nginx][access][referrer]}\" \"%{DATA:[nginx][access][agent]}\""] }
        remove_field => "message"
      }
      mutate {
        add_field => { "read_timestamp" => "%{@timestamp}" }
      }
      date {
        match => [ "[nginx][access][time]", "dd/MMM/YYYY:H:m:s Z" ]
        remove_field => "[nginx][access][time]"
      }
      useragent {
        source => "[nginx][access][agent]"
        target => "[nginx][access][user_agent]"
        remove_field => "[nginx][access][agent]"
      }
      geoip {
        source => "[nginx][access][remote_ip]"
        target => "[nginx][access][geoip]"
      }
    }
    else if [fileset][name] == "error" {
      grok {
        match => { "message" => ["%{DATA:[nginx][error][time]} \[%{DATA:[nginx][error][level]}\] %{NUMBER:[nginx][error][pid]}#%{NUMBER:[nginx][error][tid]}: (\*%{NUMBER:[nginx][error][connection_id]} )?%{GREEDYDATA:[nginx][error][message]}"] }
        remove_field => "message"
      }
      mutate {
        rename => { "@timestamp" => "read_timestamp" }
      }
      date {
        match => [ "[nginx][error][time]", "YYYY/MM/dd H:m:s" ]
        remove_field => "[nginx][error][time]"
      }
    }
  }
}
现在,弹性搜索中的文档具有所有预期字段:

注意:其他人也会有同样的问题。只需使用
[event][module]
代替
[fileset][module]


看起来您没有解析日志消息。logstash文档中有一个例子:谢谢,伙计。这很有帮助。虽然我认为既然filebeat,如果直接发送到elasticsearch发送完整的对象,那么通过logstash也应该这样做。我在本地的电脑上工作,现在我无法让它工作。我没有在logstash做任何过滤,我让它工作了。这就是为什么它对我如此陌生@波德斯比不知道。我对filebeat几乎没有经验,我甚至不知道它可以自己进行一些解析。@如果有时间,请尝试直接将filebeat与elasticsearch和kibana结合使用。按如下方式安装仪表板和索引:filebeat安装程序--仪表板。启用某些模块,甚至系统模块:filebeat模块启用系统,然后运行它。尝试打开kibana上的一个系统仪表板。你的第一条评论几乎奏效了,这真是太好了。它正在解析数据,不足以使用预定义的kibana仪表盘,但我将从那里构建它们。把它作为答案贴出来,如果你愿意,我会接受的!在logstash中是否有类似于配置auditbeat的内容?我找不到任何示例。@500Servererror我在文档中没有找到任何内容。奇怪的是,auditbeat正在发送所有字段。我遇到的问题与原始问题中描述的完全相同:Filebeat通过Logstash发送Nginx日志,而不是直接发送到弹性搜索结果,几乎所有感兴趣的字段都丢失了(我想看到的一切仍然只是在消息字段中)。我的Logstash配置与上面完全相同(来自同一个源),因此,除非我遗漏了其他内容,否则这似乎不是解决方案。可能取决于ELK stack的版本。这几乎在1年前就已经得到了回答。
  input {
    beats {
      port => 5044
      host => "0.0.0.0"
    }
  }
  filter {
    if [fileset][module] == "nginx" {
      if [fileset][name] == "access" {
        grok {
          match => { "message" => ["%{IPORHOST:[nginx][access][remote_ip]} - %{DATA:[nginx][access][user_name]} \[%{HTTPDATE:[nginx][access][time]}\] \"%{WORD:[nginx][access][method]} %{DATA:[nginx][access][url]} HTTP/%{NUMBER:[nginx][access][http_version]}\" %{NUMBER:[nginx][access][response_code]} %{NUMBER:[nginx][access][body_sent][bytes]} \"%{DATA:[nginx][access][referrer]}\" \"%{DATA:[nginx][access][agent]}\""] }
          remove_field => "message"
        }
        mutate {
          add_field => { "read_timestamp" => "%{@timestamp}" }
        }
        date {
          match => [ "[nginx][access][time]", "dd/MMM/YYYY:H:m:s Z" ]
          remove_field => "[nginx][access][time]"
        }
        useragent {
          source => "[nginx][access][agent]"
          target => "[nginx][access][user_agent]"
          remove_field => "[nginx][access][agent]"
        }
        geoip {
          source => "[nginx][access][remote_ip]"
          target => "[nginx][access][geoip]"
        }
      }
      else if [fileset][name] == "error" {
        grok {
          match => { "message" => ["%{DATA:[nginx][error][time]} \[%{DATA:[nginx][error][level]}\] %{NUMBER:[nginx][error][pid]}#%{NUMBER:[nginx][error][tid]}: (\*%{NUMBER:[nginx][error][connection_id]} )?%{GREEDYDATA:[nginx][error][message]}"] }
          remove_field => "message"
        }
        mutate {
          rename => { "@timestamp" => "read_timestamp" }
        }
        date {
          match => [ "[nginx][error][time]", "YYYY/MM/dd H:m:s" ]
          remove_field => "[nginx][error][time]"
        }
      }
    }
  }
filter {
  if [event][module] == "nginx" {
    if [fileset][name] == "access" {
      grok {
        match => { "message" => ["%{IPORHOST:[nginx][access][remote_ip]} - %{DATA:[nginx][access][user_name]} \[%{HTTPDATE:[nginx][access][time]}\] \"%{WORD:[nginx][access][method]} %{DATA:[nginx][access][url]} HTTP/%{NUMBER:[nginx][access][http_version]}\" %{NUMBER:[nginx][access][response_code]} %{NUMBER:[nginx][access][body_sent][bytes]} \"%{DATA:[nginx][access][referrer]}\" \"%{DATA:[nginx][access][agent]}\""] }
        remove_field => "message"
      }
      mutate {
        add_field => { "read_timestamp" => "%{@timestamp}" }
      }
      date {
        match => [ "[nginx][access][time]", "dd/MMM/YYYY:H:m:s Z" ]
        remove_field => "[nginx][access][time]"
      }
      useragent {
        source => "[nginx][access][agent]"
        target => "[nginx][access][user_agent]"
        remove_field => "[nginx][access][agent]"
      }
      geoip {
        source => "[nginx][access][remote_ip]"
        target => "[nginx][access][geoip]"
      }
    }
    else if [fileset][name] == "error" {
      grok {
        match => { "message" => ["%{DATA:[nginx][error][time]} \[%{DATA:[nginx][error][level]}\] %{NUMBER:[nginx][error][pid]}#%{NUMBER:[nginx][error][tid]}: (\*%{NUMBER:[nginx][error][connection_id]} )?%{GREEDYDATA:[nginx][error][message]}"] }
        remove_field => "message"
      }
      mutate {
        rename => { "@timestamp" => "read_timestamp" }
      }
      date {
        match => [ "[nginx][error][time]", "YYYY/MM/dd H:m:s" ]
        remove_field => "[nginx][error][time]"
      }
    }
  }
}