首先自定義一下nginx日志格式
①、方式一 log_format log_json '{"@timestamp": "$time_iso8601","remote_addr": "$remote_addr","remote_user": "$remote_user","request_method": "$request_met hod","uri": "$uri","query_string": "$query_string","status": "$status","body_bytes_sent": "$body_bytes_sent","http_referrer": "$http_referer","upstr eam_status": "$upstream_status","upstream_addr" : "$upstream_addr","request_time": "$request_time","upstream_response_time": "$upstream_response_tim e","request": "$request","http_user_agent": "$http_user_agent","http_x_forwarded_for": "$http_x_forwarded_for"}'; ②、方式二 log_format json '{"@timestamp":"$time_iso8601",''"host":"$server_addr",''"clientip":"$remote_addr",''"remote_user":"$remote_user",''"request_method":"$request_method",''"request":"$request",''"uri":"$uri",''"query_string":"$query_string",''"http_user_agent":"$http_user_agent",''"size":$body_bytes_sent,''"responsetime":$request_time,''"upstreamtime":"$upstream_response_time",''"upstreamhost":"$upstream_addr",''"url":"$uri",''"domain":"$host",''"client_realip":"$http_x_forwarded_for",''"referer":"$http_referer",''"status":"$status"}'; access_log logs/access.log log_json(json); #紅色字體部分的值取決於定義日志時log_format后面值的設定
注:使用json日志格式,可自定義要寫入到elasticsearch中的字段,不必在進行過濾,在寫入es之前,可先打印到屏幕進行測試,看是否是自己想要的數據結構
非json數據
其他完整格式
//日志格式
1.1.1.1 - - [06/Jun/2016:00:00:01 +0800] www.test.com GET "/api/index" "?cms=0&rnd=1692442321" 200 4 "http://www.test.com/?cp=sfwefsc" 200 192.168.0.122:80 0.004 0.004 "Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/45.0.2454.101 Safari/537.36" "-"
//自定義匹配規則 URIPARM1 [A-Za-z0-9$.+!*'|(){},~@#%&/=:;_?\-\[\]]* URIPATH1 (?:/[A-Za-z0-9$.+!*'(){},~:;=@#%&_\- ]*)+ URI1 (%{URIPROTO}://)?(?:%{USER}(?::[^@]*)?@)?(?:%{URIHOST})?(?:%{URIPATHPARAM})? NGINXACCESS %{IPORHOST:remote_addr} - (%{USERNAME:user}|-) \[%{HTTPDATE:log_timestamp}\] %{HOSTNAME:http_host} %{WORD:request_method} \"%{URIPATH1:uri}\" \"%{URIPARM1:param}\" %{BASE10NUM:http_status} (?:%{BASE10NUM:body_bytes_sent}|-) \"(?:%{URI1:http_referrer}|-)\" (%{BASE10NUM:upstream_status}|-) (?:%{HOSTPORT:upstream_addr}|-) (%{BASE16FLOAT:upstream_response_time}|-) (%{BASE16FLOAT:request_time}|-) (?:%{QUOTEDSTRING:user_agent}|-) \"(%{IPV4:client_ip}|-)\" \"(%{WORD:x_forword_for}|-)\"
默認自帶的apache日志相對於nginx只是少了一個x_forward_for
//log_format配置 log_format main '$remote_addr - $remote_user [$time_local] $http_host $request_method "$uri" "$query_string" ' '$status $body_bytes_sent "$http_referer" $upstream_status $upstream_addr $request_time $upstream_response_time ' '"$http_user_agent" "$http_x_forwarded_for"' ; //日志格式 1.1.1.1 - - [06/Jun/2016:00:00:01 +0800] www.test.com GET "/api/index" "?cms=0&rnd=1692442321" 200 4 "http://www.test.com/?cp=sfwefsc" 200 192.168.0.122:80 0.004 0.004 "Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/45.0.2454.101 Safari/537.36" "-" //apache匹配規則 COMMONAPACHELOG %{IPORHOST:clientip} %{HTTPDUSER:ident} %{USER:auth} \[%{HTTPDATE:timestamp}\] "(?:%{WORD:verb} %{NOTSPACE:request}(?: HTTP/%{NUMBER:httpversion})?|%{DATA:rawrequest})" %{NUMBER:response} (?:%{NUMBER:bytes}|-) COMBINEDAPACHELOG %{COMMONAPACHELOG} %{QS:referrer} %{QS:agent} //修改后的nginx匹配規則 MAINNGINXLOG %{COMBINEDAPACHELOG} %{QS:x_forwarded_for}
本示例日志格式
103.77.56.226 - - [23/Aug/2018:16:04:54 +0800] "GET /favicon.ico HTTP/1.1" 404 0 "-" "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/55.0.2883.87 Safari/537.36"
filebeats設置
[root@nginx filebeat-5.4.3-linux-x86_64]# cat filebeat.yml|grep -v "^$\|^#\|^ #"
filebeat.prospectors: - input_type: log paths: - /root/test.log #- c:\programdata\elasticsearch\logs\* fields: service: nginx_access output.logstash: hosts: ["10.20.200.107:5044"]
//啟動方法
./filebeat -e -c filebeat.yml
Logstash設置
input { beats { port => "5044" codec => json } } filter { if [fields][service] == "nginx_access" { #① grok { match => { "message" => "%{NGINXACCESS}" #② } } geoip { source => "remote_ip" #③ target => "geoip" #database => "/root/logstash-6.3.2/GeoLiteCity.dat" database => "/root/logstash-6.3.2/GeoLite2-City_20180807/GeoLite2-City.mmdb" #④ add_field => [ "[geoip][coordinates]", "%{[geoip][longitude]}" ] add_field => [ "[geoip][coordinates]", "%{[geoip][latitude]}" ] }
if "_geoip_lookup_failure" in [tags] { drop { } } #有無法解析的地址就刪除
mutate { convert => [ "[geoip][coordinates]", "float" ] #⑤ #convert => [ "status","integer" ] #convert => [ "bytes","integer" ] remove_field => [ "host","tags","beat","@version","prospector","fields","input","timestamp","message"] #⑥ } } } output { if [fields][service] == "nginx_access" { elasticsearch { hosts => ["10.20.200.107:9200"] index => "logstash-nginx_access-%{+YYYY.MM.dd}" #如果要做map圖形展示,這里索引必須以logstash開頭 } } #stdout { codec => rubydebug } #這里表示將過濾的日志信息打印到屏幕輸出,測試專用 }
//啟動方法
bin/logstgash -f config/log.conf
說明:
上述中①表示 從filebeat配置文件中選擇[fields][service] == "nginx_access" 的日志進行過濾
上述中②表示 對日志的過濾規則為NGINXACCESS,此過濾規則默認不存在,需要自己根據日志實際情況進行匹配規則編寫,logststash默認從${LOGSTASH_HOME}/vendor/bundle/jruby/2.3.0/gems/logstash-patterns-core-4.1.2/patterns/目錄進行匹配規則的查找與使用,這里我將匹配規則放在了 grok-patterns 文件中,如下
//匹配規則
WZ ([^ ]*) NGINXACCESS %{IP:remote_ip} \- \- \[%{HTTPDATE:timestamp}\] "%{WORD:method} %{WZ:request} HTTP/%{NUMBER:httpversion}" %{NUMBER:status} %{NUMBER:bytes} %{QS:referer} %{QS:agent}
//如果自定義了patterns的目錄文件,可使用如下方法指定(grok下與match下message同級)
parttens_dir="/../../xxx" #xxx為定義的parttens的文件
上述中③表示 根據remote_ip(匹配規則里已經指定,如果有cdn,最好用x_forward_for)進行地理位置判定
上述中④表示 免費的IP地理位置數據庫,下載地址(https://dev.maxmind.com/geoip/geoip2/geolite2/),詳細信息看這里
上述中⑤表示 修改指定字段的內容的類型
上述中⑥表示 移除不需要的字段
檢測配置文件是否有問題
bin/logstash -t -f config/log.conf #檢測配置文件是否正確
kibana匹配索引並繪圖
注意:下圖中方框內索引名(在es中創建索引時定義的)必須以logstash開頭(要過要做map圖形的話)
否則會報錯
報錯“No Compatible Fields: The “[nginx-access-]YYYY-MM” index pattern does not contain any of the following field types: geo_point”
解釋說明:
在 elasticsearch 中,所有的數據都有一個類型,什么樣的類型,就可以在其上做一些對應類型的特殊操作。geo信息中的 location字段是經緯度,我們需要使用經緯度來定位地理位置;在 elasticsearch 中,對於經緯度來說,要想使用 elasticsearch 提供的地理位置查詢相關的功能,就需要構造一個結構,並且將其類型屬性設置為geo_point,此錯誤明顯是由於我們的geo的location字段類型不是geo_point。
**解決方法:**Elasticsearch 支持給索引預定義設置和 mapping(前提是你用的 elasticsearch 版本支持這個 API,不過估計應該都支持)。其實ES中已經有一個默認預定義的模板,只要使用預定的模板即可,默認預定義的模板必須只有匹配 logstash-* 的索引才會應用這個模板,所以需要修改索引名字以logstash開頭
默認情況下的地圖顯示為英文,要使其轉化為英文,需要修改kibana.yml配置文件
#在文件底部加上下面一句話 tilemap.url: 'http://webrd02.is.autonavi.com/appmaptile?lang=zh_cn&size=1&scale=1&style=7&x={x}&y={y}&z={z}'
最終結果