Logstash 参考指南(在配置中访问事件数据和字段)

在配置中访问事件数据和字段

Logstash代理是一个包含三个阶段的处理管道:输入 → 过滤 → 输出,输入生成事件,过滤器修改事件,输出将事件发送到其余地方。html

全部事件都有属性,例如,apache访问日志包含状态代码(200,404)、请求路径(“/”,“index.html”)、HTTP动做(GET,POST)、客户端IP地址等,Logstash将这些属性称为“字段”。git

Logstash中的一些配置选项须要字段的存在来发挥做用,由于输入生成事件,在输入块中没有要衡量的字段 — 他们还不存在!github

由于它们依赖于事件和字段,如下配置选项将只在过滤器和输出块中工做。web

下面描述的字段引用、sprintf格式和条件在输入块中不起做用。

字段引用

可以经过名称引用字段一般颇有用,为此,你能够使用Logstash字段引用语法。正则表达式

访问字段的语法是[fieldname],若是你引用的是顶级字段,你能够省略[]并简单地使用fieldname,要引用嵌套字段,须要指定该字段的完整路径:[top-level field][nested field]apache

例如,如下事件有5个顶级字段(agent、ip、request、response、ua)和3个嵌套字段(status、bytes、os)。编程

{
  "agent": "Mozilla/5.0 (compatible; MSIE 9.0)",
  "ip": "192.168.24.44",
  "request": "/index.html"
  "response": {
    "status": 200,
    "bytes": 52353
  },
  "ua": {
    "os": "Windows 7"
  }
}

要引用os字段,你须要指定[ua][os],要引用顶级字段(如request),只需简单的指定字段名。segmentfault

sprintf格式

字段引用格式也被用在Logstash调用sprintf格式中,这种格式容许你从其余字符串引用字段值,例如,statsd输出有一个increment设置,能够根据状态码保存apache日志的计数:api

output {
  statsd {
    increment => "apache.%{[response][status]}"
  }
}

相似地,你能够将@timestamp字段中的时间戳转换为字符串,不是在花括号中指定字段名,而是使用+FORMAT语法,其中FORMAT时间格式ruby

例如,若是但愿使用文件输出根据事件的日期、小时和type字段写入日志:

output {
  file {
    path => "/var/log/%{type}.%{+yyyy.MM.dd.HH}"
  }
}

条件

有时,你只想在特定条件下过滤或输出事件,为此,你能够使用条件语句。

Logstash中的条件语句的外观和操做方式与编程语言中的相同,条件语句支持ifelse ifelse语句,而且能够嵌套。

条件语法是:

if EXPRESSION {
  ...
} else if EXPRESSION {
  ...
} else {
  ...
}

表达式是什么?比较测试,布尔逻辑,等等!

你能够使用如下比较运算符:

  • 等式:==!=<><=>=
  • 正则表达式:=~!~(检查右边的模式对立左边的字符串值)
  • 包含:innot in

支持的布尔运算符是:

  • andornandxor

支持的一元运算符是:

  • !

表达式能够很长很复杂,表达式能够包含其余表达式,能够用!来否认表达式,还能够用括号(…)对它们进行分组。

例如,若是字段action的值为login,下面的条件使用mutate过滤器来删除字段secret

filter {
  if [action] == "login" {
    mutate { remove_field => "secret" }
  }
}

能够在单个条件中指定多个表达式:

output {
  # Send production errors to pagerduty
  if [loglevel] == "ERROR" and [deployment] == "production" {
    pagerduty {
    ...
    }
  }
}

你能够使用in操做符来测试字段是否包含特定的字符串、键或(对于列表)元素:

filter {
  if [foo] in [foobar] {
    mutate { add_tag => "field in field" }
  }
  if [foo] in "foo" {
    mutate { add_tag => "field in string" }
  }
  if "hello" in [greeting] {
    mutate { add_tag => "string in field" }
  }
  if [foo] in ["hello", "world", "foo"] {
    mutate { add_tag => "field in list" }
  }
  if [missing] in [alsomissing] {
    mutate { add_tag => "shouldnotexist" }
  }
  if !("foo" in ["hello", "world"]) {
    mutate { add_tag => "shouldexist" }
  }
}

你也能够用一样的方式使用not in条件,例如,当grok成功时,你能够使用not in只将事件路由到Elasticsearch:

output {
  if "_grokparsefailure" not in [tags] {
    elasticsearch { ... }
  }
}

你能够检查特定字段是否存在,但目前还没法区分不存在的字段和不存在的字段,if [foo]表达式返回false时:

  • 事件中不存在[foo]
  • 事件中存在[foo],但为false
  • 事件中存在[foo],但为null

有关更复杂的示例,请参阅Logstash配置示例

@metadata字段

在Logstash 1.5和更高版本中,还有一个名为@metadata的特殊字段,@metadata的内容在输出时不会是你的任何事件的一部分,这使得它很好地用于条件,或使用字段引用和sprintf格式扩展和构建事件字段。

下面的配置文件将从STDIN生成事件,输入的内容将成为事件中的message字段,过滤器块中的mutate事件将添加一些字段,其中一些嵌套在@metadata字段中。

input { stdin { } }

filter {
  mutate { add_field => { "show" => "This data will be in the output" } }
  mutate { add_field => { "[@metadata][test]" => "Hello" } }
  mutate { add_field => { "[@metadata][no_show]" => "This data will not be in the output" } }
}

output {
  if [@metadata][test] == "Hello" {
    stdout { codec => rubydebug }
  }
}

让咱们看看结果是什么:

$ bin/logstash -f ../test.conf
Pipeline main started
asdf
{
    "@timestamp" => 2016-06-30T02:42:51.496Z,
      "@version" => "1",
          "host" => "example.com",
          "show" => "This data will be in the output",
       "message" => "asdf"
}

输入的“asdf”成为message字段内容,条件成功地评估了嵌套在@metadata字段中的test字段的内容,可是输出没有显示一个名为@metadata的字段,或者它的内容。

rubydebug编解码器容许你显示@metadata字段的内容,若是你添加一个配置标志,metadata => true

stdout { codec => rubydebug { metadata => true } }

让咱们看看这个更改后的输出是什么样子的:

$ bin/logstash -f ../test.conf
Pipeline main started
asdf
{
    "@timestamp" => 2016-06-30T02:46:48.565Z,
     "@metadata" => {
           "test" => "Hello",
        "no_show" => "This data will not be in the output"
    },
      "@version" => "1",
          "host" => "example.com",
          "show" => "This data will be in the output",
       "message" => "asdf"
}

如今能够看到@metadata字段及其子字段。

只有 rubydebug编解码器容许显示 @metadata字段的内容。

当你须要一个临时字段但不但愿它出如今最终输出中时,请使用@metadata字段。

也许这个新字段最多见的用例之一是使用date过滤器并具备一个临时的时间戳。

这个配置文件通过了简化,可是使用了Apache和Nginx web服务器经常使用的时间戳格式,在过去,你必须本身删除timestamp字段,而后使用它覆盖@timestamp字段,对于@metadata字段,这再也不是必要的:

input { stdin { } }

filter {
  grok { match => [ "message", "%{HTTPDATE:[@metadata][timestamp]}" ] }
  date { match => [ "[@metadata][timestamp]", "dd/MMM/yyyy:HH:mm:ss Z" ] }
}

output {
  stdout { codec => rubydebug }
}

注意,在grok过滤器中的这个配置将提取的日期放入[@metadata][timestamp]字段中,让咱们为这个配置提供一个示例日期字符串,看看会获得什么:

$ bin/logstash -f ../test.conf
Pipeline main started
02/Mar/2014:15:36:43 +0100
{
    "@timestamp" => 2014-03-02T14:36:43.000Z,
      "@version" => "1",
          "host" => "example.com",
       "message" => "02/Mar/2014:15:36:43 +0100"
}

就是这样!输出中没有额外的字段,并且配置文件更干净,由于在date过滤器中进行转换后,不须要删除“ timestamp”字段。

另外一个用例是CouchDB更改输入插件(参阅https://github.com/logstash-plugins/logstash-input-couchdb_changes),这个插件自动将CouchDB文档字段元数据捕获到输入插件自己的@metadata字段中。当事件经过Elasticsearch被索引时,Elasticsearch输出插件容许你指定action(删除、更新、插入等)和document_id,以下所示:

output {
  elasticsearch {
    action => "%{[@metadata][action]}"
    document_id => "%{[@metadata][_id]}"
    hosts => ["example.com"]
    index => "index_name"
    protocol => "http"
  }
}
相关文章
相关标签/搜索