简体   繁体   中英

Config file, logstash ruby filter event.get(“message”).match() Error

In the logstash config file I am trying to just get the XML data to parse.

This is my config file:


input {
    file {
        path => "/home/elastic-stack/logstash-7.3.2/event-data/telmetry.log"
        start_position => "beginning"
        type => "sandbox-out"
        codec => multiline {
            pattern => "^</datastore-contents-xml>"
            negate => "true"
            what => "next"
    }

    }
    http { 
        host => "127.0.0.1"
        port => 8080
        type => "sandbox-out"
    }
}
filter {
    grok {
        match => { "message" => "\[%{USER:host_name} %{IP:ip_address} %{USER:session-id} %{NUMBER:session-id-num}\]"}
    }
    grok {
        match => { "message" => "\Subscription Id     \: %{BASE16NUM:subcription-id:int}"}
    }    
    grok {
        match => { "message" => "\Event time      \: %{TIMESTAMP_ISO8601:event-time}"}
    }
    grok {
        match => {"message" => "\<%{USERNAME:Statistic}\>"}
    }
    mutate {
        remove_field => ["headers", "host_name", "session-id","message"]
    }
    date {
        match => ["timestamp","dd/MMM/yyyy:HH:mm:ss Z"]
    }
    ruby { code => 'event.set("justXml", event.get("message").match(/.+(<datastore-contents-xml.*)/m)[1])' }
    xml {
        #remove_namespaces => "true"
        #not even the namspace option is working to access the http link
        source => "justXml"
        target => "xml-content"
        #force_array => "false"
        xpath => [
            "//*[name()='datastore-contents-xml']/*[name()='memory-statistics']/*[name()='memory-statistic'][1]/*[name()='name']/text()" , "name" ,
            "//*[name()='datastore-contents-xml']/*[name()='memory-statistics']/*[name()='memory-statistic'][1]/*[name()='total-memory']/text()" , "total-memory",
            "//*[name()='datastore-contents-xml']/*[name()='memory-statistics']/*[name()='memory-statistic'][1]/*[name()='used-memory']/text()" , "used-memory",
            "//*[name()='datastore-contents-xml']/*[name()='memory-statistics']/*[name()='memory-statistic'][1]/*[name()='free-memory']/text()" , "free-memory" ,
            "//*[name()='datastore-contents-xml']/*[name()='memory-statistics']/*[name()='memory-statistic'][1]/*[name()='lowest-memory']/text()" , "lowest-memory" ,
            "//*[name()='datastore-contents-xml']/*[name()='memory-statistics']/*[name()='memory-statistic'][1]/*[name()='highest-memory']/text()" , "highest-memory" 
        ]
        #logstash is not dectecting any of these xpaths in the config  
    }
    mutate {
        convert => {
            "total-memory" => "integer"
            "used-memory" => "integer"
            "free-memory" => "integer"
            "lowest-memory" => "integer"
            "highest-memory" => "integer"
            }
    }


}
output {
    stdout {
        codec => rubydebug
    }

    file {
        path => "%{type}_%{+dd_MM_yyyy}.log"
    }
}

Desired output:

{
        "ip_address" => "10.10.20.30",
    "subcription-id" => 2147483650,
        "event-time" => "2019-09-12 13:13:30.290000+00:00",
              "host" => "127.0.0.1",
         "Statistic" => "memory-statistic",
              "type" => "sandbox-out",
          "@version" => "1",
        "@timestamp" => 2019-09-26T10:03:00.620Z,
    "session-id-num" => "35"
        "yang-model" => "http://cisco.com/ns/yang/Cisco-IOS-XE-memory-oper"
              "name" => "Processor"
      "total-memory" => 2238677360
       "used-memory" => 340449924
       "free-memory" => 1898227436
      "lowest-usage" => 1897220640
     "highest-usage" => 1264110388
}

ERROR:

[2019-09-27T09:18:55,622][ERROR][logstash.filters.ruby    ] Ruby exception occurred: undefined method `match' for nil:NilClass
/home/elastic-stack/logstash-7.3.2/vendor/bundle/jruby/2.5.0/gems/awesome_print-1.7.0/lib/awesome_print/formatters/base_formatter.rb:31: warning: constant ::Fixnum is deprecated
{
        "ip_address" => "10.10.20.30",
    "subcription-id" => 2147483650,
    "session-id-num" => "35",
              "tags" => [
        [0] "_rubyexception"
    ],
         "Statistic" => "memory-statistic",
        "event-time" => "2019-09-12 13:13:30.290000+00:00",
              "type" => "sandbox-out",
          "@version" => "1",
              "host" => "127.0.0.1",
        "@timestamp" => 2019-09-27T07:18:54.868Z

By the error I can already know that the problem is with the ruby filter but I do not know how to resolve it.

This data generate by Cisco Telemetry and I am trying to ingest it using Elastic Stack.

The error seems to be that the event has no message field, so you cannot call match on a non existing thing. I see you are calling match on the message field in this ruby code:

ruby { code => 'event.set("justXml", event.get("message").match(/.+(<datastore-contents-xml.*)/m)[1])' }

However you are removing the message field from the event a few lines earlier:

mutate {
  remove_field => ["headers", "host_name", "session-id","message"]
}

Solution is to remove the message field only when you don't need it anymore, I would move the remove_field mutate to the end of the filter block.

One more suggestion if I may add. You have multiple grok filters running on the same, message field:

grok {
  match => { "message" => "\[%{USER:host_name} %{IP:ip_address} %{USER:session-id} %{NUMBER:session-id-num}\]"}
}
grok {
  match => { "message" => "\Subscription Id     \: %{BASE16NUM:subcription-id:int}"}
}    
grok {
  match => { "message" => "\Event time      \: %{TIMESTAMP_ISO8601:event-time}"}
}
grok {
  match => {"message" => "\<%{USERNAME:Statistic}\>"}
}

This can be simplified into this (you can check to theGrok filter docs :

grok {
  break_on_match => false,
  match => {
    "message" => [
      "\[%{USER:host_name} %{IP:ip_address} %{USER:session-id} %{NUMBER:session-id-num}\]",
      "\Subscription Id     \: %{BASE16NUM:subcription-id:int}",
      "\Event time      \: %{TIMESTAMP_ISO8601:event-time}",
      "\<%{USERNAME:Statistic}\>"
    ]
  }
}

This way you need only one instance of the grok filter, as it will go through the patterns in the list and because of break_on_match=>false it will not finish after the first successful match, but will make sure to extract all fields it can based on all the patterns in the list.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM