I am using Logstash and Filebeat to ship log files into a central repository.
Getting this set up is very easy, but I battled for a few hours to get the file name to be saved on the logstash server with the name the file had on the source server.
In my scenario, I have two sources of logs - a web site and an API. These are on load-balanced servers, so I want the log files copied to the central repository into specific folders, with their original file name prefixed with the host from where they came.
Filebeat
The Filebeat configuration was the easy part - nothing complex here in the filebeat.yml
file:
filebeat.inputs:
- type: filestream
id: site-logs
paths:
- E:\Web\site.co.za\logs\*.log
tags: ["site-logs"]
- type: filestream
id: api-logs
paths:
- E:\Web\api.co.za\logs\*.log
tags: ["api-logs"]
output.logstash:
hosts: ["MYSERVER:5044"]
The tags
are important - this is so you can differentiate them on the logstash side as different sources.
Run Filebeat as follows: filebeat -e -c filebeat.yml
Logstash
Now we know we are getting files shipped across to Logstash. Most references refer to the source
event field, but this is no longer available in the latest version of Filebeat that I could see. Instead, I noticed that the log.file.path
contained the full original path of the log file.
This value can then be mutated into a new field as follows:
input {
beats {
port => 5044
}
}
filter {
if "api-logs" in [tags] or "site-logs" in [tags] {
mutate {
copy => { "[log][file][path]" => "[@metadata][filepath]" }
}
mutate {
gsub => [ "[@metadata][filepath]", "[\\]", "|" ]
}
mutate {
split => { "[@metadata][filepath]" => '|' }
add_field => { "file_name" => '%{[@metadata][filepath][-1]}' }
}
}
}
output {
# stdout { codec => rubydebug }
if "site-logs" in [tags] {
file {
path => ["C:/LogStash/site/%{[host][name]}-%{[file_name]}"]
codec => line { format => "%{message}" }
}
}
if "api-logs" in [tags] {
file {
path => ["C:/LogStash/api/%{[host][name]}-%{[file_name]}"]
codec => line { format => "%{message}" }
}
}
}
The process is therefore as follows:
- List for file beats on port 5044
- If a beat comes in with the
api-logs
orsite-logs
tag, then run mutations on it - The mutations take the
log.file.path
value and split it by separator, using the ruby [-1] array index to get the last value in the array - The file is then written out to
C:\LogStash\<source>\<hostName>-<originalFileName>
e.g.C:\LogStash\api\MYSERVER-2023-11-14.log