首先自定义一下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}'
最终结果