nginx 之 grok 过滤
简介
前面我们的nginx日志编码使用的json,logstash直接输入预定义好的 JSON 数据,这样就可以省略掉 filter/grok 配置,但是在我们的生产环境中,日志格式往往使用的是普通的格式,因此就不得不使用logstash的filter/grok进行过滤,下面我们就来讲下如何配置。
配置
1.nginx日志格式
为了帮助我们有效的理解grok的正则表达式,因此在这我们将日志格式定义的复杂一些,基本是各个使用的字段都涉及到了,google上好多都是套用的默认格式,我费好大劲才弄明白。
log_format main '$time_local - $upstream_addr $server_addr:$server_port '
'$request_method $uri $args '
'- $remote_addr $server_protocol [$http_user_agent] [$http_cookie] $http_referer '
'$host $status 0 0 $bytes_sent $request_length 0'
'"$upstream_cache_status" $request_time $upstream_response_time';
- 1
- 2
- 3
- 4
- 5
对应的日志如下:
08/Jan/2016:08:27:43 +0800 - 10.10.6.212:8088 10.10.6.110:80 GET /vvv/test/stat/index proptype=11&level=2&srtype=2&city=dz®ion=XJ&begindate=2016-01-08&enddate=2016-01-08&apiKey=c2c959b203d669a9a21861379cb4523c&test=2 - 10.10.6.10 HTTP/1.1 [Mozilla/5.0 (Windows NT 6.3; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/39.0.2171.99 Safari/537.36] [JSESSIONID=kq3v6xi2b74j1a9yxvfvcq131] http://10.10.6.110/test www.test.com 200 0 0 485 209 0"-" 1.642 1.642
- 1
2.编写正则表达式
logstash中默认存在一部分正则表达式来让我们套用,在如下的文件中我们可以看到:
ls /usr/local/logstash/vendor/bundle/jruby/1.9/gems/logstash-patterns-core-2.0.2/patterns
aws bacula bro exim firewalls grok-patterns haproxy java junos linux-syslog mcollective mcollective-patterns mongodb nagios postgresql rails redis ruby
- 1
- 2
- 3
其中最基本的定义是在grok-patterns中,但是某些正则不适合我们的nginx字段,此时就需要我们来自定义,然后grok通过patterns_dir来调用即可。
另外,我们可以通过http://grokconstructor.appspot.com/do/match或http://grokdebug.herokuapp.com/这两个站点来查看我们的正则是否正确。(ps:个人觉得第一个好用)
下面我们来通过分解日志中的各个字段来一一对应下正则:
| nginx日志字段定义 | nginx访问字段 | 正则表达式 |
|---|---|---|
| $time_local | 08/Jan/2016:08:27:43 +0800 | %{HTTPDATE:timestamp} |
| - | - | - |
| $upstream_addr | 10.10.6.212:8088 | %{HOSTPORT:upstream} |
| serveraddr:server_port | 10.10.6.110:80 | %{HOSTPORT:request_server} |
| $request_method | GET | %{WORD:request_method} |
| $uri | /vvv/test/stat/index | %{URIPATH:uri} |
| $args | proptype=11&level=2&srtype=2&city=dz®ion=XJ&begindate=2016-01-08&enddate=2016-01-08&apiKey=c2c959b203d669a9a21861379cb4523c&test=2 | %{URIPARAM1:args} |
| - | - | - |
| $remote_addr | 10.10.6.10 | %{IP:clientip} |
| $server_protocol | HTTP/1.1 | HTTP/%{NUMBER:httpversion} |
| [$http_user_agent] | [Mozilla/5.0 (Windows NT 6.3; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/39.0.2171.99 Safari/537.36] | \ [%{GREEDYDATA:agent}\ ] |
| [$http_cookie] | [JSESSIONID=kq3v6xi2b74j1a9yxvfvcq131] | \ [%{GREEDYDATA:cookie}\ ] |
| $http_referer | http://10.10.6.110/test | (?:%{URI:referrer}|-) |
| $host | www.test.com | %{HOSTNAME:domain} |
| $status | 200 | %{NUMBER:status:int} |
| 0 | 0 | 0 |
| 0 | 0 | 0 |
| $bytes_sent | 485 | %{NUMBER:body_sent:int} |
| $request_length | 209 | %{NUMBER:request_length:int} |
| 0”$upstream_cache_status” | 0”-“ | 0\”-\” |
| $request_time | 1.642 | %{NUMBER:request_time:float} |
| $upstream_response_time | 1.642 | %{NUMBER:response_time:float} |
ok,我们nginx日志的所有字段都已经定义完毕,我们可以到http://grokconstructor.appspot.com/do/match看下是否有问题: 
注意要点:
(1)上图中URIPARAM1 [A-Za-z0-9$.+!‘|(){},~@#%&/=:;_?-[]]是我们自定义的个一个正则,由%{URIPARAM1:args}调用,
它和默认正则库/usr/local/logstash/vendor/bundle/jruby/1.9/gems/logstash-patterns-core-2.0.2/patterns/grok-patterns中的URIPARAM \?[A-Za-z0-9$.+!‘|(){},~@#%&/=:;_?-[]<>]是不一样的,可以看到默认的URIPARAM是以?开头,我们自定义的URIPARAM1而不是,也可通过https://github.com/elastic/logstash/blob/v1.4.2/patterns/grok-patterns查看(这个规则是更新的,可能由于版本的问题和你使用的不一样),正是由于这点差别导致我们在使用默认正则会出现“Longest prefix that matches”的提示,“after matche”会显示日志中未匹配的剩余内容,如下图:
也就是说我们的匹配是异常的,一旦有这样的提示,就说明我们的正则有问题。
(2)httpuseragent字段和http_cookie字段使用http://grokdebug.herokuapp.com/patterns#中“nginx-access”生成的规则“%{QS:agent}”以及类似“%{QS:cookie}”也会出现“Longest prefix that matches”提示,因此这两个正则是不正确的,我就使用了%{GREEDYDATA:agent}和%{GREEDYDATA:cookie},在/usr/local/logstash/vendor/bundle/jruby/1.9/gems/logstash-patterns-core-2.0.2/patterns/grok-patterns或https://github.com/elastic/logstash/blob/v1.4.2/patterns/grok-patterns我们可以查到“GREEDYDATA .*”,匹配的所有字符,注意和“QS %{QUOTEDSTRING}”的区别。
(3)?:%{URI:referrer}|-)正则表示如果$referer字段为空,则用-表示,若不为空则显示referer的内容,经测试如果直接设置成%{URI:referrer},过滤时当referer为空时,导致grokfailure,因此需要注意此字段的正则表达式。
某些字段为“-”,可能导致grokfailure,此时我们可以通过(?:%{XX:XX}|-)的方式进行匹配,即为空时显示“-”。
(4)可能你想知道所有的正则是如何定义的,我们可以查看https://github.com/kkos/oniguruma/blob/master/doc/RE
3.logstash调用
(1)在logstash中定义正则目录并定义规则
mkdir -p /usr/local/logstash/patterns
vim /usr/local/logstash/patterns/nginx
URIPARAM1 [A-Za-z0-9$.+!*'|(){},~@#%&/=:;_?\-\[\]]*
NGINXACCESS %{HTTPDATE:timestamp} - %{HOSTPORT:upstream} %{HOSTPORT:request_server} %{WORD:request_method} %{URIPATH:uri} %{URIPARAM1:args} - %{IP:clientip} HTTP/%{NUMBER:httpversion} \[%{GREEDYDATA:agent}\] \[%{GREEDYDATA:cookie}\] %{URI:referer} %{HOSTNAME:host} %{NUMBER:status:int} 0 0 %{NUMBER:body_sent:int} %{NUMBER:request_length:int} 0\"-\" %{NUMBER:request_time:float} %{NUMBER:response_time:float}
- 1
- 2
- 3
- 4
其中URIPARAM1是我们自定义的部分,而NGINXACCESS也是我们自定的正则,其中又调用了URIPARAM1。
(2)配置文件logstash.conf
input {
file {
path => "/data/nginx/logs/api.creprice.log"
type => "nginx-access"
start_position => "beginning"
sincedb_path => "/usr/local/logstash/sincedb"
}
}
filter {
if [type] == "nginx-access" {
grok {
patterns_dir => "/usr/local/logstash/patterns"
match => {
"message" => "%{NGINXACCESS}"
}
}
date {
match => [ "timestamp" , "dd/MMM/YYYY:HH:mm:ss Z" ]
}
}
}
output {
if [type] == "nginx-access" {
elasticsearch {
hosts => ["10.10.10.16:9200"]
manage_template => true
index => "logstash-nginx-access-%{+YYYY-MM}"
}
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
其中:patterns_dir定义的是我们自定义的正则存放目录
(3)重启logstash,查看kibana,我们的字段就显示出来了,如果我们的字段前面是?,请刷新下我们的“Setting”——“indices”——“Index Patterns”——“logstash-nginx-access-%{+YYYY-MM}”即可。
总结
通过上面对正则的了解,即使是在复杂的日志,我们只要对应规则也可以一一解开,下面的工作就是让我们应用到生产环境吧。
nginx 之 grok 过滤的更多相关文章
- Logstash收集nginx日志之使用grok过滤插件解析日志
grok作为一个logstash的过滤插件,支持根据模式解析文本日志行,拆成字段. nginx日志的配置: log_format main '$remote_addr - $remote_user [ ...
- Logstash使用grok过滤nginx日志(二)
在生产环境中,nginx日志格式往往使用的是自定义的格式,我们需要把logstash中的message结构化后再存储,方便kibana的搜索和统计,因此需要对message进行解析. 本文采用grok ...
- Nginx 返回响应过滤响应内容
陶辉94课 过滤模块 从下到上顺序 ngx_http_proxy_module 模块 Syntax: proxy_ignore_headers field ...; Default: — Contex ...
- 使用Logstash filter grok过滤日志文件
Logstash提供了一系列filter过滤plugin来处理收集到的log event,根据log event的特征去切分所需要的字段,方便kibana做visualize和dashboard的da ...
- Nginx之HTTP过滤模块
1. HTTP 过滤模块 ngx_http_not_modified_module 仅对 HTTP 头部做处理.在返回 200 成功时,根据请求中 If-Modified-Since 或者 If-Un ...
- 《深入理解Nginx》阅读与实践(四):简单的HTTP过滤模块
一.Nginx的HTTP过滤模块特征 一个请求可以被任意个HTTP模块处理: 在普通HTTP模块处理请求完毕并调用ngx_http_send_header()发送HTTP头部或调用ngx_http_o ...
- Nginx模块开发(5)————开发简单的HTTP过滤模块
该模块可实现如下的功能,在浏览器输入http://你的IP/lcw.text,能够读出你在根目录下创建的lcw.txt里面的内容,并在前面加上一句字符串where there is a will,th ...
- ELK 6安装配置 nginx日志收集 kabana汉化
#ELK 6安装配置 nginx日志收集 kabana汉化 #环境 centos 7.4 ,ELK 6 ,单节点 #服务端 Logstash 收集,过滤 Elasticsearch 存储,索引日志 K ...
- ELK实践(二):收集Nginx日志
Nginx访问日志 这里补充下Nginx访问日志使用的说明.一般在nginx.conf主配置文件里需要定义一种格式: log_format main '$remote_addr - $remote_u ...
随机推荐
- jquery触屏幻灯片
一.前言 去年接触了移动Web开发,做了些手机端的网站及应用,还有些小的微信游戏和活动页面.每个项目里或多或少的都会有一些触屏事件等.其中有两个用到了jquery触屏幻灯片.刚开始的时候也在百度上搜索 ...
- JVM 平台上的各种语言的开发指南
JVM 平台上的各种语言的开发指南 为什么我们需要如此多的JVM语言? 在2013年你可以有50中JVM语言的选择来用于你的下一个项目.尽管你可以说出一大打的名字,你会准备为你的下一个项目选择一种新的 ...
- 在 Linux 上配置一个 syslog 服务器
syslog服务器可以用作一个网络中的日志监控中心,所有能够通过网络来发送日志的设施(包含了Linux或Windows服务器,路由器,交换机以及其他主机)都可以把日志发送给它. 通过设置一个syslo ...
- JSON简单介绍
//JSON是一种数据格式//JSON比较像php里面的关联数组,它里面存的内容也是key和value成对存在的 JSON写法格式 var js = { "one":"h ...
- [WebServer] Tomcat 配置访问限制:访问白名单和访问黑名单
前言: 昨天配置了 Tomcat 服务器运行 PHP 的环境,但是通过观察 Tomcat 这几天的日志发现,有很多莫名其妙的 IP 访问主机下莫名其妙的地址,如:/80./testproxy.php. ...
- WebView 的使用----android和html的交互
一.主布局文件 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xml ...
- php翻页
<?php$conn = mysql_connect("localhost","root","") or die("连接数据 ...
- Cookie与Session用法
以下是Cookie的完整实例 MyEclipse新建web Project工程,建两个jsp文件,如下 1.login.jsp <%@ page language="java" ...
- 【66测试20161115】【树】【DP_LIS】【SPFA】【同余最短路】【递推】【矩阵快速幂】
还有3天,今天考试又崩了.状态还没有调整过来... 第一题:小L的二叉树 勤奋又善于思考的小L接触了信息学竞赛,开始的学习十分顺利.但是,小L对数据结构的掌握实在十分渣渣.所以,小L当时卡在了二叉树. ...
- break continue 区别 以及实例
不论是MATLAB.c/c++.c#还是其他类型的编程语言,我们总是避免不了和for循环以及switch语句打交道,而对循环进行优化的时候,又总是避免不了用到break以及continue来控制循环, ...