@leandrojmp @Christian_Dahlqvist
(Kindly Note I've replaced some sensitive information from config and logs and replaced it with some random words.)
Thanks in advance.
Just to give you an idea, this is how logs are populated on ELK cluster.
On source we have Filebeat servers running which forward their logs to array of Logstash servers, from Logstash these logs are further forwarded to Elasticsearch.
Based on the your questions and comments I believe that the filed "@timestamp" gets added at Logstash Layer.
I am attempting to add the config files on this post hopefully I am allowed to do so considering the size if it doesn't work I will try to use classic pastebin to share the templates of my config files.
Given below is the content of filebeat.yml
filebeat.inputs:
- type: log
paths:
- /var/log/nginx/foo.access.log
fields:
log_type: foo-access
filebeat.config.modules:
path: ${path.config}/modules.d/*.yml
reload.enabled: false
output.logstash:
hosts: ["host01:5044", "host02:5044", "host03:5044"]
loadbalance: true
index: foo-access
processors:
- add_host_metadata:
when.not.contains.tags: forwarded
- add_cloud_metadata: ~
- add_docker_metadata: ~
- add_kubernetes_metadata: ~
This is how my logstash.yml looks like :
path.data: /var/lib/ELK/logstash
pipeline.workers: 16
queue.type: persisted
queue.page_capacity: 1024mb
queue.max_bytes: 40gb
path.logs: /var/log/logstash
logstash-fileter.conf:
filter {
if [fields][log_type] == "foo-access" {
grok {
patterns_dir => "/etc/logstash/patterns"
match => { "message" => "%{FOO_GROK}" }
}
mutate {
convert => [ "[response]", "integer"]
convert => [ "[bytes_read]", "integer"]
convert => [ "[request_duration]", "float"]
convert => [ "[upstream_request_duration]", "float"]
}
mutate {add_field => { "hostname" => "%{[host][hostname]}"}}
mutate {add_field => { "src_log_file" => "%{[log][file][path]}"}}
mutate {add_field => { "src_log_type" => "%{[fields][log_type]}"}}
if ![api_param] {
mutate {add_field => {"api_param" => " "}}
}
if ![request] {
mutate {add_field => { "request" => "%{api}%{api_param}"}}
}
prune {
whitelist_names => ["x_forwarder_for","x_forwarded_for","xforwardedfor","auth","user","timestamp","method","request","httpversion","response","bytes_read","request_header_referer","request_header_agent","clientip","request_duration","upstream_request_duration","message","hostname","host_ip","timestamp","Country","source","host.hostname","src_log_file","_type_new","src_log_type","api","api_param"]
}
}
}
This is how my GROK looks like
FOO_GROK (%{IPORHOST:clientip}|-)\s+(%{NGUSER:ident}|-)\s+(%{NGUSER:auth}|%{USERNAME:user}|-)\s+\[%{HTTPDATE:timestamp}\]\s+"(?:%{WORD:method})\s+((?<api>\/([^\ \?]*))(?<api_param>(\?.+?)|-|))(\s+HTTP/%{BASE10NUM:httpversion}|)"\s+%{NUMBER:response}\s+(%{NOTSPACE:bytes_read}|-)\s+"(%{DATA:request_header_referer}|-)"\s+"(%{DATA:request_header_agent}|-)"\s+"(?<x_forwarder_for>:?%{IP}(,\s+%{IP})*|-)"\s+(?:%{BASE10NUM:request_duration}|-)\s+(?:%{BASE10NUM:upstream_request_duration}|-)
Finally output of the document fetched from Kibana ( @RainTown )
{
"_index": "foo-access-2025.03.07",
"_id": "76t7g7gkjgi76tiuh8yoih",
"_version": 1,
"_score": 0,
"_ignored": [
"message.keyword"
],
"_source": {
"@timestamp": "2025-03-07T11:14:45.126Z",
"request_header_agent": "-",
"response": 200,
"auth": "-",
"httpversion": "1.1",
"api_param": "?e=P&mid=9262007&ownerinfo=1&jdlite=&meowmeow=&wap=1&module=&version=1537&source=1&meow=1&app_version=&udid=&meowsc=007m1991prof",
"hostname": "21-175-dc.foo.com",
"api": "/foo_srv/jd_user.php",
"upstream_request_duration": 0.057,
"method": "GET",
"src_log_type": "foo-access",
"x_forwarder_for": "10.0.31.107",
"clientip": "10.0.20.201",
"timestamp": "07/Mar/2025:16:44:44 +0530",
"message": "10.0.20.201 - - [07/Mar/2025:16:44:44 +0530] \"GET /foo_srv/jd_user.php?e=P&mid=9262007&ownerinfo=1&jdlite=&meowmeow=&wap=1&module=&version=1537&source=1&meow=1&app_version=&udid=&meowsc=007m1991prof HTTP/1.1\" 200 673 \"-\" \"-\" \"10.0.31.107\" 0.057 0.057 \"DSP : 10.0.20.201:9001\" .",
"request_duration": 0.057,
"request_header_referer": "-",
"request": "/foo_srv/foo_user.php?e=P&mid=9262007&ownerinfo=1&jdlite=&meowmeow=&wap=1&module=&version=1537&source=1&meow=1&app_version=&udid=&meowsc=007m1991prof",
"bytes_read": 673,
"src_log_file": "/var/log/nginx/foo.access.log"
},
"fields": {
"request_header_agent": [
"-"
],
"request": [
"/foo_srv/jd_user.php?e=P&mid=9262007&ownerinfo=1&jdlite=&meowmeow=&wap=1&module=&version=1537&source=1&meow=1&app_version=&udid=&meowsc=007m1991prof"
],
"auth": [
"-"
],
"src_log_file.keyword": [
"/var/log/nginx/foo.access.log"
],
"timestamp.keyword": [
"07/Mar/2025:16:44:44 +0530"
],
"api.keyword": [
"/foo_srv/jd_user.php"
],
"hostname": [
"21-175-dc.foo.com"
],
"request_duration": [
0.057
],
"httpversion.keyword": [
"1.1"
],
"clientip": [
"10.0.20.201"
],
"method.keyword": [
"GET"
],
"api": [
"/foo_srv/jd_user.php"
],
"request_header_referer": [
"-"
],
"timestamp": [
"07/Mar/2025:16:44:44 +0530"
],
"src_log_file": [
"/var/log/nginx/foo.access.log"
],
"method": [
"GET"
],
"x_forwarder_for.keyword": [
"10.0.31.107"
],
"src_log_type": [
"foo-access"
],
"request.keyword": [
"/foo_srv/jd_user.php?e=P&mid=9262007&ownerinfo=1&jdlite=&meowmeow=&wap=1&module=&version=1537&source=1&meow=1&app_version=&udid=&meowsc=007m1991prof"
],
"bytes_read": [
673
],
"message": [
"10.0.20.201 - - [07/Mar/2025:16:44:44 +0530] \"GET /foo_srv/jd_user.php?e=P&mid=9262007&ownerinfo=1&jdlite=&meowmeow=&wap=1&module=&version=1537&source=1&meow=1&app_version=&udid=&meowsc=007m1991prof HTTP/1.1\" 200 673 \"-\" \"-\" \"10.0.31.107\" 0.057 0.057 \"DSP : 10.0.20.201:9001\" ."
],
"request_header_agent.keyword": [
"-"
],
"@timestamp": [
"2025-03-07T11:14:45.126Z"
],
"api_param.keyword": [
"?e=P&mid=9262007&ownerinfo=1&jdlite=&meowmeow=&wap=1&module=&version=1537&source=1&meow=1&app_version=&udid=&meowsc=007m1991prof"
],
"response": [
200
],
"upstream_request_duration": [
0.057
],
"auth.keyword": [
"-"
],
"x_forwarder_for": [
"10.0.31.107"
],
"clientip.keyword": [
"10.0.20.201"
],
"src_log_type.keyword": [
"foo-access"
],
"request_header_referer.keyword": [
"-"
],
"httpversion": [
"1.1"
],
"hostname.keyword": [
"21-175-dc.foo.com"
],
"api_param": [
"?e=P&mid=9262007&ownerinfo=1&jdlite=&meowmeow=&wap=1&module=&version=1537&source=1&meow=1&app_version=&udid=&meowsc=007m1991prof"
]
},
"ignored_field_values": {
"message.keyword": [
"10.0.20.201 - - [07/Mar/2025:16:44:44 +0530] \"GET /foo_srv/jd_user.php?e=P&mid=9262007&ownerinfo=1&jdlite=&meowmeow=&wap=1&module=&version=1537&source=1&meow=1&app_version=&udid=&meowsc=007m1991prof HTTP/1.1\" 200 673 \"-\" \"-\" \"10.0.31.107\" 0.057 0.057 \"DSP : 10.0.20.201:9001\" ."
]
}
}
Once again Thank you, and let me know if you need any additional input from my end.
I will be trying to dig into Logstash documentation if I can find any thing related to this.
Regards