Skip to content

Instantly share code, notes, and snippets.

@paulRbr
Forked from mudge/logstash.conf
Last active January 17, 2022 04:22
Show Gist options
  • Save paulRbr/b8b31b769fc8c4039034 to your computer and use it in GitHub Desktop.
Save paulRbr/b8b31b769fc8c4039034 to your computer and use it in GitHub Desktop.
Logstash configuration to parse Rails logs in a multi-process environment. Assume your logs are prepend by logtags as seen in the RLOGTAGS pattern.
input {
file {
type => "rails"
path => "/log/development.log"
tags => ["development"]
}
}
filter {
if [type] == "rails" {
# First match all lines and identify each file with a "uuid" field
grok{
match => ['message',"%{RLOGTAGS} ?(?<content>.*)"]
}
if [content] =~ /.+/ {
mutate {
replace => [ "message", "[%{uuid}]%{content}" ] #replace the message field with the content field ( so it auto append later in it )
remove_field => ["content"] # we no longer need this field
}
# Merge all lines with same "uuid"
railsparallelrequest {}
# Join all messages per event with spaces
mutate {
join => [ "message", " " ]
}
# Match Rails log in extracted fields
grok {
match => ["message", "%{RUUID}\W*%{RAILS3}"]
}
# Convert the timeformat into something sensible.
date {
match => ["timestamp", "yyyy-MM-dd HH:mm:ss Z"]
}
} else {
drop { }
}
}
if [type] == "apache" {
# This will extract the different metadata in the log message, like timestamp, IP, method, etc.
grok {
match => ["message", "%{COMBINEDTTAKEN}"]
}
# Convert the timeformat into something sensible.
date {
match => ["timestamp", "dd/MMM/yyyy:HH:mm:ss Z"]
}
# Annotate log with approximate geo-information.
geoip {
source => "clientip"
}
}
if [type] == "nginx-error" {
# This will extract the different metadata in the log message, like timestamp, IP, method, etc.
grok {
patterns_dir => "./patterns"
match => {
"message" => [
"%{NGINXERROR}",
"%{NGINXDATE:timestamp} \[%{DATA:severity}\] (%{NUMBER:pid:int}#%{NUMBER}: \*%{NUMBER}|\*%{NUMBER}) %{GREEDYDATA:mymessage}",
"%{NGINXDATE:timestamp} \[%{DATA:severity}\] %{GREEDYDATA:mymessage}",
"%{NGINXDATE:timestamp} %{GREEDYDATA:mymessage}"
]
}
}
# Convert the timeformat into something sensible.
date {
match => ["timestamp", "yyyy/MM/dd HH:mm:ss"]
}
# Annotate log with approximate geo-information.
geoip {
source => "clientip"
}
}
}
output {
stdout {
codec => rubydebug
}
elasticsearch {
embedded => true
}
}
RUUID \[(?<uuid>\h{11})\]
RSESSIONID \[(?<sessionid>[a-zA-Z0-9\-_]{11})\]
RHOST \[%{IPORHOST:host}\]
RCLIENTIP \[%{IPORHOST:clientip}\]
RLOGTAGS %{RHOST} %{RCLIENTIP} (?:%{RSESSIONID} )?%{RUUID}
RCONTROLLER (?<controller>[^#]+)#(?<action>\w+)
RAILS3HEAD Started %{WORD:verb} "%{URIPATHPARAM:request}" for %{IPORHOST:clientip} at %{RTIMESTAMP}
RTIMESTAMP (?<timestamp>[0-9]{4}-%{MONTHNUM}-%{MONTHDAY} %{HOUR}:%{MINUTE}:%{SECOND} %{ISO8601_TIMEZONE})
RPROCESSING \W*Processing by %{RCONTROLLER} as (?<format>\S+)(?:\W*Parameters: {%{GREEDYDATA:params}}\W*)?
RAILS3FOOT Completed %{NUMBER:response}%{DATA} in %{NUMBER:totalms}ms %{RAILS3PROFILE}%{GREEDYDATA}
RAILS3PROFILE (?:\(Views: %{NUMBER:viewms}ms \| ActiveRecord: %{NUMBER:activerecordms}ms|\(ActiveRecord: %{NUMBER:activerecordms}ms)?
RAILS3 %{RAILS3HEAD}(?:%{RPROCESSING})?(?<context>(?:(?!Completed ).)*)(?:%{RAILS3FOOT})?
[dev.example.com] [172.17.42.1] [tj4aP3Ou63q] [6c90f8266f9] Processing by ProController#manifest as HTML
[dev.example.com] [172.17.42.1] [tj4aP3Ou63q] [6c90f8266f9] Pro Load (4.2ms) SELECT `pros`.* FROM `pros` WHERE `pros`.`id` = 1 LIMIT 1
[dev.example.com] [172.17.42.1] [tj4aP3Ou63q] [6c90f8266f9] Rendered pro/manifest (10.4ms)
[dev.example.com] [172.17.42.1] [tj4aP3Ou63q] [6c90f8266f9] Completed 200 OK in 347.6ms (Views: 12.7ms | ActiveRecord: 6.3ms)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment