This is an old revision of the document!
Table of Contents
Logstash setup
Download and install
wget https://artifacts.opensearch.org/logstash/logstash-oss-with-opensearch-output-plugin-8.9.0-linux-x64.tar.gz tar xf logstash-oss-with-opensearch-output-plugin-8.9.0-linux-x64.tar.gz cd logstash-8.9.0/ && bin/logstash-plugin install logstash-output-opensearch
Examples
nginx logs
input {
file {
path => "/var/log/nginx/nginx_logs*_access.log"
}
}
filter {
grok {
patterns_dir => "/etc/logstash.d/patterns"
match => { "message" => "%{NGINX_ACCESS}" }
remove_field => ["message"]
}
useragent {
source => "user_agent"
target => "useragent"
remove_field => "user_agent"
}
}
output {
opensearch {
hosts => "https://{{ opensearch_host }}:9200"
user => "logstash"
password => "mypassword"
index => "logstash-nginx-access-logs-${HOSTNAME}"
manage_template => true
template_overwrite => true
template => "/etc/logstash.d/nginx_access_index_map.json"
ssl_certificate_verification => false
}
}
Above we're using a grok pattern named NGINX_ACCESS stored in patterns directory. Example of pattern:
METHOD (OPTIONS|GET|HEAD|POST|PUT|DELETE|TRACE|CONNECT)
CACHED (HIT|MISS|BYPASS|EXPIRED|STALE|UPDATING|REVALIDATED)
NGINX_ACCESS "%{HTTPDATE:time_local}" client=%{IP:client} country=%{GREEDYDATA:country} method=%{METHOD:method} request="%{METHOD} %{URIPATHPARAM:request} HTTP/%{BASE16FLOAT:http_version}" request_length=%{INT:request_length} status=%{INT:status} bytes_sent=%{INT:bytes_sent} body_bytes_sent=%{INT:body_bytes_sent} referer=(%{URI:referer}|-) user_agent=%{GREEDYDATA:user_agent} upstream_addr=(%{HOSTPORT:upstream_addr}|-) upstream_status=(%{INT:upstream_status}|-) request_time=(%{ISO8601_SECOND:request_time}|-) upstream_response_time=(%{ISO8601_SECOND:upstream_response_time}|-) upstream_connect_time=(%{ISO8601_SECOND:upstream_connect_time}|-) upstream_header_time=(%{ISO8601_SECOND:upstream_header_time}|-) upstream_cache_status=(%{CACHED:upstream_cache_status}|-) is_bot=%{INT:is_bot} cookie_mbbauth_present=(%{GREEDYDATA:cookie_mbbauth_present}|-)
For testing the pattern use http://grokconstructor.appspot.com. Copy a few log lines there and adjust above pattern until you get a match.
manage_template ⇒ true creates the pattern in opensearch (elasticsearch) DB automatically, just make sure the logstash user has the permissions to create the indices with specified names. Index pattern is described in template ⇒ “/etc/logstash.d/nginx_access_index_map.json”. This must match the grok pattern above i.e.
{
"version" : 50001,
"template" : "logstash-nginx-access*",
"settings" : {
"index" : {
"refresh_interval" : "5s"
}
},
"mappings" : {
"properties" : {
"@timestamp" : {
"type" : "date"
},
"client": {
"type" : "ip"
},
"country" : {
"type" : "keyword"
},
"method" : {
"type" : "keyword"
},
"request" : {
"type" : "keyword"
},
"request_length" : {
"type" : "integer"
},
"status" : {
"type" : "integer"
},
"bytes_sent": {
"type" : "integer"
},
"body_bytes_sent": {
"type" : "integer"
},
"referer" : {
"type" : "keyword"
},
"useragent" : {
"dynamic" : true,
"properties" : {
"device" : {
"properties" : {
"name" : {
"type" : "keyword"
}
}
},
"name" : {
"type" : "keyword"
},
"os" : {
"properties" : {
"name" : {
"type" : "keyword"
},
"version" : {
"type" : "keyword"
},
"full" : {
"type" : "keyword"
}
}
},
"version" : {
"type" : "keyword"
}
}
},
"upstream_addr" : {
"type" : "keyword"
},
"upstream_status" : {
"type" : "keyword"
},
"request_time" : {
"type" : "float"
}
}
},
"aliases" : {}
}
${HOSTNAME} is an environment variable which must be defined (via .bashrc or with systemd unit which starts logstash service etc.)
# /etc/systemd/system/logstash.service
[Unit]
Description=Massage various logs and forward them to opensearch/elasticsearch
After=network.target
[Service]
Type=simple
ExecStart=/usr/local/bin/logstash -f /etc/logstash.d/nginx_logs.conf
Environment="HOSTNAME={{ hostname }}"
Restart=on-failure
[Install]
WantedBy=multi-user.target
referer=(%{URI:referer}|-) construct means the referer in this case might be empty (-).
