input { file { path => "~/solr.log" } } filter { # Extract event severity and timestamp grok { match => { "message" => "%{WORD:level}.+?- %{DATA:LogTime};" } tag_on_failure => [] } # Combine commit events into single message multiline { pattern => "^\t(commit\{)" what => "previous" } # INFO level events treated differently than ERROR if "INFO" in [level] { grok { match => { "message" => ".+?; ((([a-zA-Z]+(\.|;|:))+) )+?\[%{WORD:collection}\].+?path=%{DATA:endpoint} params=\{%{DATA:params}\}.+?\{%{WORD:action}=\[%{DATA:docId}" } tag_on_failure => [] } if [params] { kv { field_split => "&" source => "params" } } else { grok { match => { "message" => ".+?; ((([a-zA-Z]+(\.|;|:))+) )+?commits" } tag_on_failure => [ "drop" ] add_field => { "action" => "commit" } } if "drop" in [tags] { drop {} } } } # Error event implies stack track, which requires multiline parsing if "ERROR" in [level] { multiline { pattern => "^\s" what => "previous" add_tag => [ "multiline_pre" ] } multiline { pattern => "^Caused by" what => "previous" add_tag => [ "multiline_post" ] } if "multiline_post" in [tags] { grok { match => { "message" => ".+?; ((([a-zA-Z]+(\.|;|:))+) )+%{DATA:reason}(\n\t)((.+?Caused by: ((([a-zA-Z]+(\.|;|:))+) )+)%{DATA:reason}(\n\t))+" } tag_on_failure => [] } } } # Remove intermediate tags, and multiline added randomly by multiline stage mutate { remove_tag => [ "multiline_pre", "multiline_post", "multiline" ] } # Drop empty lines if [message] =~ /^\s*$/ { drop {} } } output { # Send directly to local Elasticsearch elasticsearch_http { host => "localhost" template => "~/logstash/bin/logstash_solr_template.json" index => "solr-%{+YYYY.MM.dd}" template_overwrite => true } }