How to add host name for beats input in logstash - elasticsearch

Let me explain my existing structure, I have 4 servers (Web Server, API Server, Database server, SSIS Severs) and installed filebeat and winlog in all four servers and from there I am getting all logs in my logstash, but here is the thing every log I am getting in message body, and for some messages I am getting difficulty to write correct GROK pattern, is there anyway I can get the pattern from Kibana (FYI as of now I am storing all logs in elasticsearch which I can see through Kibana.)
My Logstash config is look like -
1. Api-Pipeline
input {
beats {
host => "IP Address where my filebeat (API Server) is running"
port => 5044
}
}
2. DB Pipeline
input {
beats {
host => "IP Address where my filebeat (Database Server) is running"
port => 5044
}
}
It's working when I used only port and the moment I add host it stopped working. Can anyone help me here.
Below I am trying to achieve
Here I made change, Does it work because I need to write lengthy filters and that's why I wanted to have in separate files
Filebeat.yml on API Server
-----------------------------------------------------------------------------------------
filebeat.inputs:
- type: log
source: 'ApiServerName' // MyAPIServerName(Same Server Where I have installed filebeat)
enabled: true
paths:
- C:\Windows\System32\LogFiles\SMTPSVC1\*.log
- E:\AppLogs\*.json
scan_frequency: 10s
ignore_older: 24h
filebeat.config.modules:
path: C:\Program Files\Filebeat\modules.d\iis.yml
reload.enabled: false
setup.template.settings:
index.number_of_shards: 3
setup.kibana:
host: "kibanaServerName:5601"
output.logstash:
hosts: ["logstashServerName:5044"]
Logstash Configuration
----------------------------------------------------------------
Pipeline.yml
- pipeline.id: beats-server
config.string: |
input { beats { port => 5044 } }
output {
if [source] == 'APISERVERNAME' {
pipeline { send_to => apilog }
} else if [source] == 'DBSERVERNAME' {
pipeline { send_to => dblog }
}
else{
pipeline { send_to => defaultlog }
}
}
- pipeline.id: apilog-processing
path.config: "/Logstash/config/pipelines/apilogpipeline.conf"
- pipeline.id: dblog-processing
path.config: "/Logstash/config/pipelines/dblogpipeline.conf"
- pipeline.id: defaultlog-processing
path.config: "/Logstash/config/pipelines/defaultlogpipeline.conf"
1. apilogpipeline.conf
----------------------------------------------------------
input {
pipeline {
address => apilog
}
}
output {
file {
path => ["C:/Logs/apilog_%{+yyyy_MM_dd}.log"]
}
}
2. dbilogpipeline.conf
---------------------------------------------------------
input {
pipeline {
address => dblog
}
}
output {
file {
path => ["C:/Logs/dblog_%{+yyyy_MM_dd}.log"]
}
}
3. defaultlogpipeline.conf
---------------------------------------------------------
input {
pipeline {
address => defaultlog
}
}
output {
file {
path => ["C:/Logs/defaultlog_%{+yyyy_MM_dd}.log"]
}
}

It works the other way around, i.e. it's not Logstash that connects to Filebeat but Filebeat that sends data to Logstash. So in your input section, the host needs to be the name of the host where Logstash is running.
beats {
host => "logstash-host"
port => 5044
}
Then in your Filebeat configuration, you need to configure the Logstash output like this:
output.logstash:
hosts: ["logstash-host:5044"]
Since you have multiple Filebeat sources and want to apply a dedicated pipeline to each, what you can do is to define one custom field or tag in each Filebeat config (e.g. source: db, source: api-server, etc) and then in Logstash you can apply a different logic based on those values.
filebeat.inputs:
- type: log
fields:
source: 'APISERVERNAME'
fields_under_root: true
In Logstash, you can either leverage conditionals or pipeline to pipeline communication in order to apply a different logic based on event data.
On the latest link, you can see an example of the distributor pattern which is pretty much what you're after.

Related

Multiple filebeat to one logstash. How to optimize the configuration

I have 10 servers that i have Filebeat installed in.
Each server monitors 2 applications, a total of 20 applications.
I have one Logstash server which collects all the above logs and passes it to Elasticsearch after filtering of these logs.
To read one file from one server, I use the below Logstash configuration:
input {
beats {
port => 5044
}
}
filter {
grok {
match => {"message" =>"\[%{TIMESTAMP_ISO8601:timestamp}\]%{SPACE}\[%{DATA:Severity}\]%{SPACE}\[%{DATA:Plugin}\]%{SPACE}\[%{DATA:Servername}\](?<short_message>(.|\r|\n)*)"}
}
}
output {
elasticsearch {
hosts => ["<ESserverip>:9200"]
index => "groklogs"
}
stdout { codec => rubydebug }
}
And this is the filebeat configuration:
paths:
- D:\ELK 7.1.0\elasticsearch-7.1.0-windows-x86_64\elasticsearch-7.1.0\logs\*.log
output.logstash:
hosts: ["<logstaship>:5044"]
Can anyone please give me an example of
How i should convert the above to receive from multiple applications
from multiple servers.
Should i configure multiple ports? How?
How should i use multiple Groks?
How can i optimize it in a single or minimal logstash configuration files?
How will a typical set up look. Please help me.
You can use tags in order to differentiate between applications (logs patterns).
As Filebeat provides metadata, the field beat.name will give you the ability to filter the server(s) you want.
Multiple inputs of type log and for each one a different tag should be sufficient.
See these examples in order to help you.
Logstash
filter {
if "APP1" in [tags] {
grok {
...
}
}
if "APP2" in [tags] {
grok {
...
}
}
}
Filebeat
filebeat.inputs:
- type: log
paths:
- /var/log/system.log
- /var/log/wifi.log
tags: ["APP1"]
- type: log
paths:
- "/var/log/apache2/*"
tags: ["APP2"]

ELK - How to use different source in logstash

I have a so far running ELK installation that I want to use to analyse log files from differenct sources:
nginx-logs
auth-logs
and so on...
I am using filebeat to collect content from logfiles and sending it to logstash with this filebeat.yml:
filebeat.inputs:
- type: log
enabled: true
paths:
- /var/log/*.log
- /var/nginx/example_com/logs/
output.logstash:
hosts: ["localhost:5044"]
In logstash I alread configured a grok-section, but only for nginx-logs. This was the only working tutorial I found. So this config receives content from filebeat, filters is (that's what grok is for?) and sends it to elasticsearch.
input {
beats {
port => 5044
}
}
filter {
grok {
patterns_dir => "/etc/logstash/patterns"
match => { "message" => "%{NGINXACCESS}" }
}
}
output {
elasticsearch {
hosts => "localhost:9200"
manage_template => false
index => "%{[#metadata][beat]}-%{[#metadata][version]}-%{+YYYY.MM.dd}"
document_type => "%{[#metadata][type]}"
}
}
That's the content of the one nginx-pattern file I am referencing:
NGUSERNAME [a-zA-Z\.\#\-\+_%]+
NGUSER %{NGUSERNAME}
NGINXACCESS %{IPORHOST:clientip} (?:-|(%{WORD}.%{WORD})) %{USER:ident} \[%{HTTPDATE:timestamp}\] "(?:%{WORD:verb} %{NOTSPACE:request}(?: HTTP/%{NUMBER:httpversion})?|%{DATA:rawrequest})" %{NUMBER:response} (?:%{NUMBER:bytes}|-) %{QS:referrer} %{QS:agent} %{QS:forwarder}
But I have trouble understanding how to manage different log-data sources. Because now Kibana only displays log content from /var/log, but there is no log data from my particular nginx folder.
What is it, that I am doing wrong here?
Since you are running filebeat, you already have a module available, that process nginx logs filebeat nginx module
This way, you will not need logstash to process the logs, and you only have to point the output directly to elasticsearch.
But, since you are processing multiple paths with different logs, and because elastic stack don't allow to have multiple output forms (logstash + elasticserach), you can set logstash to only process logs that do not come from nginx. This way, and using the module (that comes with sample dashboards) , your logs will do:
Filebeat -> Logstash (from input plugin to output plugin - without any filtering) -> Elasticsearch
If you really want to process the logs on your own, you are in a good path to finish. But right now, all your logs are being process by the grok pattern. So maybe the problem is with your pattern, that processes logs from nginx, and not from nginx in the same way. You can filter the logs in the filter plugin, with something like this:
#if you are using the module
filter {
if [fileset][module] == "nginx" {
}
}
if not, please check different available examples at logstash docs
Another thing you can try, it's add this to you filter. This way, if the grok fails,you will see the log in kibana, but, with the "_grok_parse_error_nginx_error" failure tag.
grok {
patterns_dir => "/etc/logstash/patterns"
match => { "message" => "%{NGINXACCESS}" }
tag_on_failure => [ "_grok_parse_error_nginx_error" ]
}

Logstash Beats Input - multiple multiline codec

I am trying to send multiple types of logs with beats and parse them on the logstash server.
I have beats configured and working properly and almost have logstash working correctly.
Where I am having issues is that other-log.log has entries that start with a different format string.
In an ideal world I would like to be able to apply a different multiline codec depending on the type of entry.
I have tried
if [type] == "server.log" {
codec => multiline {
pattern => "^\d{2}:\d{2}:\d{2},\d+"
negate => true
what => "previous"
}
}
However that causes logstash to fail, my guess is that if is not allowed in the input block.
I have also tried to use the multiline filter plugin but it results in
"Couldn't find any filter plugin named 'multiline'. Are you sure this is correct? Trying to load the multiline filter plugin resulted in this error: LoadError"
Does anyone have an idea as to how to make this work?
filebeat.yml
- input_type: log
paths:
- /application/server.log
document_type: server.log
- input_type: log
paths:
- /tmp/other-log.log
document_type: other.log
pipeline.conf
input {
beats {
host => "0.0.0.0"
port => "5044"
codec => multiline {
pattern => "^\d{2}:\d{2}:\d{2},\d+"
negate => true
what => "previous"
}
}
}
filter {
if [type] == "server.log" {
grok {
match => { "message" => "(?<date>^\d{2}:\d{2}:\d{2},\d+)\s(?<level>[A-Z]+)\s+\[(?<class>.*?)\]\s+(?<message>(?m).*)" }
overwrite => ["message"]
add_tag => [ "server.log" ]
}
}
}
# The filter part of this file is commented out to indicate that it is
# optional.
# filter {
#
# }
output {
elasticsearch { hosts => ["localhost:9200"] }
}
I moved the multiline to filebeat.yml and that solved my issues :)
Configuration for moving multiline to filebeat.yaml is here. I captured multiline logs using the following configuration.
This is my filebeat.yaml configuration:
# ============================== Filebeat inputs ===============================
filebeat.inputs:
- type: log
enabled: true
paths:
- /var/log/nginx/access.log
- /var/log/nginx/error.log
multiline.pattern: '^[[:space:]]' // these
multiline.negate: false // three
multiline.match: after // lines are important for capturing multiline logs
------------------ Logstash Output -------------------------------
output.logstash:
# The Logstash hosts
hosts: ["localhost:5044"]
index: "my-index-name"
You can also take reference from this blog

Sending json format log to kibana using filebeat, logstash and elasticsearch?

I have logs like this:
{"logId":"57aaf6c8d32fb","clientIp":"127.0.0.1","time":"03:11:29 pm","uniqueSubId":"57aaf6c98963b","channelName":"JSPC","apiVersion":"v1","modulName":null,"actionName":"apiRequest","typeOfError":"","statusCode":"","message":"In Auth","exception":"In Auth","logType":"Info"}
{"logId":"57aaf6c8d32fb","clientIp":"127.0.0.1","time":"03:11:29 pm","uniqueSubId":"57aaf6c987206","channelName":"JSPC","apiVersion":"v2","modulName":null,"actionName":"performV2","typeOfError":"","statusCode":"","message":"in inbox api v2 5","exception":"in inbox api v2 5","logType":"Info"}
I want to push them to kibana. I am using filebeat to send data to logstash, using following configuration:
filebeat.yml
### Logstash as output
logstash:
# The Logstash hosts
hosts: ["localhost:5044"]
# Number of workers per Logstash host.
#worker: 1
Now using following configuration, I want to change codec type:
input {
beats {
port => 5000
tags => "beats"
codec => "json_lines"
#ssl => true
#ssl_certificate => "/opt/filebeats/logs.example.com.crt"
#ssl_key => "/opt/filebeats/logs.example.com.key"
}
syslog {
type => "syslog"
port => "5514"
}
}
But, still I get the logs in string format:
"message":
"{\"logId\":\"57aaf6c96224b\",\"clientIp\":\"127.0.0.1\",\"time\":\"03:11:29
pm\",\"channelName\":\"JSPC\",\"apiVersion\":null,\"modulName\":null,\"actionName\":\"404\",\"typeOfError\":\"EXCEPTION\",\"statusCode\":0,\"message\":\"404
page encountered
http:\/\/localjs.com\/uploads\/NonScreenedImages\/profilePic120\/16\/29\/15997002iicee52ad041fed55e952d4e4e163d5972ii4c41f8845105429abbd11cc184d0e330.jpeg\",\"logType\":\"Error\"}",
Please help me solve this.
To parse JSON log lines in Logstash that were sent from Filebeat you need to use a json filter instead of a codec. This is because Filebeat sends its data as JSON and the contents of your log line are contained in the message field.
Logstash config:
input {
beats {
port => 5044
}
}
filter {
if [tags][json] {
json {
source => "message"
}
}
}
output {
stdout { codec => rubydebug { metadata => true } }
}
Filebeat config:
filebeat:
prospectors:
- paths:
- my_json.log
fields_under_root: true
fields:
tags: ['json']
output:
logstash:
hosts: ['localhost:5044']
In the Filebeat config, I added a "json" tag to the event so that the json filter can be conditionally applied to the data.
Filebeat 5.0 is able to parse the JSON without the use of Logstash, but it is still an alpha release at the moment. This blog post titled Structured logging with Filebeat demonstrates how to parse JSON with Filebeat 5.0.
From FileBeat 5.x You can do it without using Logstash.
Filebeat config:
filebeat.prospectors:
- input_type: log
paths: ["YOUR_LOG_FILE_DIR/*"]
json.message_key: logId
json.keys_under_root: true
output.elasticsearch:
hosts: ["<HOSTNAME:PORT>"]
template.name: filebeat
template.path: filebeat.template.json
Filebeat is more lightweight then Logstash.
Also, even if you need to insert to elasticsearch version 2.x you can use this feature of FileBeat 5.x
Real example can be found here
I've scoured internet for the exact same problem you are having and tried various suggestions, including those above. However, none helped so I did it the old fashioned way. I went on elasticsearch documentation on filebeat configuration
and all that was required (no need for filters config in logstash)
Filebeat config:
filebeat.prospectors:
- input_type: log
document_type: #whatever your type is, this is optional
json.keys_under_root: true
paths:
- #your path goes here
keys_under_root
copies nested json keys to top level in the output document.
My filebeat version is 5.2.2.

logstash and x-forwarded-for on IIS

I just built an ELK server on Windows so I'm new to the process. I've read through the docs but am having trouble parsing out my IIS advanced logs, especially x-forwarded-for data as we're behind a load balancer..
My advanced logging is set up to output the data like this:
$date, $time, $s-ip, $cs-uri-stem, $cs-uri-query, $s-port, $cs-username, $c-ip, $X-Forwarded-For, $csUser-Agent, $cs-Referer, $sc-status, $sc-substatus, $sc-win32-status, $time-taken
I set up my logstash.conf like this:
input {
tcp {
host => "localhost"
type => "iis"
port => 5044
}
}
filter {
if [type] == "iis" {
grok {
match => {"message" => "%{TIMESTAMP_ISO8601:log_timestamp} %{IPORHOST:site} %{URIPATH:page} %{NOTSPACE:query_string} %{NUMBER:port} %{NOTSPACE:username} %{IPORHOST:client_host} %{NOTSPACE:useragent} %{NOTSPACE:referer} %{GREEDYDATA:response} %{NUMBER:httpStatusCode:int} %{NUMBER:scSubstatus:int} %{NUMBER:scwin32status:int} %{NUMBER:timeTakenMS:int}"}
}
}
}
output {
elasticsearch {
hosts => ["localhost:9200"]
index => "iis"
document_type => "main"
}
}
I don't think this is correct as I'm not getting data. I've scoured the docs but am still having issues and am not sure if there are other steps I need to take, like mapping the fields.
I'm currently using filebeat from one server to push data to my ELK server. I'm not sure if this is the best way as well (maybe nxlog?). We don't want to install logstash on the client machines.
Can someone lend me a hand? It would be GREATLY appreciated!!
Thanks,
George
Since you are using Filebeat then you need to use the beats input and not the tcp input. See the documentation on how to setup Logstash for Beats.
Essentially you need to replace your tcp input with:
input {
beats {
port => 5044
}
}
And inside your Filebeat configuration file, set the document_type to iis so that your filter condition will match.
filebeat:
prospectors:
- paths:
- 'C:\path\to\your\iis\logs\*.log'
document_type: iis

Resources