详解用ELK来分析Nginx服务器日志的方法_nginx

所有ELK的安装包都可以去官网下载,虽然速度稍慢,但还可以接受,官网地址:https://www.elastic.co/

logstash

在Logstash1.5.1版本,pattern的目录已经发生改变,存储在/logstash/vendor/bundle/jruby/1.9/gems/logstash-patterns-core-0.1.10/目录下,但是好在配置引用的时候是可以对patterns的目录进行配置的,所以本人在Logstash的根目录下新建了一个patterns目录。而配置目录在1.5.1版本中也不存在了,如果是rpm包安装的,可以在/etc/logstash/conf.d/下面进行配置,但个人测试多次,这样启动经常性的失败,目前还没有去分析原因(个人不推荐使用RPM包安装)。所以大家可以采用Nohup或者screen的方式进行启动
专属nginx的pattern配置:

复制代码 代码如下:

NGINXACCESS %{IP:client} %{USER:ident} %{USER:auth} \[%{HTTPDATE:timestamp}\] \"(?:%{WORD:verb} %{NOTSPACE:request}(?: HTTP/%{NUMBER:http_version})?|-)\" %{HOST:domain} %{NUMBER:response} (?:%{NUMBER:bytes}|-) %{QS:referrer} %{QS:useragent} "(%{IP:x_forwarder_for}|-)"

由于是测试环境,我这里使用logstash读取nginx日志文件的方式来获取nginx的日志,并且仅读取了nginx的access log,对于error log没有关心。

使用的logstash版本为2.2.0,在log stash程序目录下创建conf文件夹,用于存放解析日志的配置文件,并在其中创建文件test.conf,文件内容如下:

input {
  file {
    path => ["/var/log/nginx/access.log"]
  }
}
filter {
  grok {
    match => {
      "message" => "%{IPORHOST:clientip} \[%{HTTPDATE:time}\] \"%{WORD:verb} %{URIPATHPARAM:request} HTTP/%{NUMBER:httpversion}\" %{NUMBER:http_status_code} %{NUMBER:bytes} \"(?<http_referer>\S+)\" \"(?<http_user_agent>\S+)\" \"(?<http_x_forwarded_for>\S+)\""
    }
  }
}
output {
  elasticsearch {
    hosts => ["10.103.17.4:9200"]
    index => "logstash-nginx-test-%{+YYYY.MM.dd}"
    workers => 1
    flush_size => 1
    idle_flush_time => 1
    template_overwrite => true
  }
  stdout{codec => rubydebug}
}

需要说明的是,filter字段中的grok部分,由于nginx的日志是格式化的,logstash解析日志的思路为通过正则表达式来匹配日志,并将字段保存到相应的变量中。logstash中使用grok插件来解析日志,grok中message部分为对应的grok语法,并不完全等价于正则表达式的语法,在其中增加了变量信息。

具体grok语法不作过多介绍,可以通过logstash的官方文档中来了解。但grok语法中的变量类型如IPORHOST并未找到具体的文档,只能通过在logstash的安装目录下通过grep -nr "IPORHOST" .来搜索具体的含义。

配置文件中的stdout部分用于打印grok解析结果的信息,在调试阶段一定要打开。

可以通过这里来验证grok表达式的语法是否正确,编写grok表达式的时候可以在这里编写和测试。

对于elasticsearch部分不做过多介绍,网上容易找到资料。

elk收集分析nginx access日志

使用redis的push和pop做队列,然后有个logstash_indexer来从队列中pop数据分析插入elasticsearch。这样做的好处是可扩展,logstash_agent只需要收集log进入队列即可,比较可能会有瓶颈的log分析使用logstash_indexer来做,而这个logstash_indexer又是可以水平扩展的,我可以在单独的机器上跑多个indexer来进行日志分析存储。

好了,现在进一步配置了。

nginx中的日志存储格式

nginx由于有get请求,也有post请求,get请求的参数是会直接显示在日志的url中的,但是post请求的参数呢,却不会在access日志中体现出来。那么我想要post的参数也进行存储纪录下来。就需要自己定义一个log格式了。

复制代码 代码如下:

log_format logstash '$http_host $server_addr $remote_addr [$time_local] "$request" $request_body $status $body_bytes_sent "$http_referer" "$http_user_agent" $request_time $upstream_response_time';

这里的requestbody里面存放的就是POST请求的body了,然后GET请求的参数在requestbody里面存放的就是POST请求的body了,然后GET请求的参数在request里面。具体怎么分析,我们在indexer中再想。

这里的server_addr存放的是当前web机器的IP,存这个IP是为了分析日志的时候可以分析日志的原始来源。

下面是一个GET请求的例子:

复制代码 代码如下:

api.yejianfeng.com 10.171.xx.xx 100.97.xx.xx [10/Jun/2015:10:53:24 +0800] "GET /api1.2/qa/getquestionlist/?limit=10&source=ios&token=12343425324&type=1&uid=304116&ver=1.2.379 HTTP/1.0" - 200 2950 "-" "TheMaster/1.2.379 (iPhone; iOS 8.3; Scale/2.00)" 0.656 0.654

下面是一个POST请求的例子:

复制代码 代码如下:

api.yejianfeng.com 10.171.xx.xx 100.97.xx.xx [10/Jun/2015:10:53:24 +0800] "POST /api1.2/user/mechanicupdate/ HTTP/1.0" start_time=1276099200&lng=110.985723&source=android&uid=328910&lat=35.039471&city=140800 200 754 "-" "-" 0.161 0.159

顺便说下,这里知识在nginx.conf中定义了一个日志格式,还要记得在具体的服务中加入日志存储。比如

listen    80;
server_name api.yejianfeng.com;
access_log /mnt/logs/api.yejianfeng.com.logstash.log logstash;

log_agent的配置

这个配置就是往redis队列中塞入日志就行。output的位置设置为redis就行。

input {
        file {
                type => "nginx_access"
                path => ["/mnt/logs/api.yejianfeng.com.logstash.log"]
        }
}
output {
        redis {
                host => "10.173.xx.xx"
                port => 8001
                password => pass
                data_type => "list"
                key => "logstash:redis"
        }
}
log_indexer的配置

log_indexer的配置就比较麻烦了,需要配置的有三个部分

input: 负责从redis中获取日志数据
filter: 负责对日志数据进行分析和结构化
output: 负责将结构化的数据存储进入elasticsearch
input部分

input {
    redis {
        host => "10.173.xx.xx"
        port => 8001
        password => pass
        data_type => "list"
        key => "logstash:redis"
    }
}

其中的redis配置当然要和agent的一致了。

filter部分
解析文本可以使用grokgrok debug进行分析,参照着之前的log格式,需要一个个进行日志分析比对。这个grok语法写的还是比较复杂的,还好有在线grok比对工具可以使用。比对前面的GET和POST的日志格式,修改出来的grok语句如下:

复制代码 代码如下:

%{IPORHOST:http_host} %{IPORHOST:server_ip} %{IPORHOST:client_ip} \[%{HTTPDATE:timestamp}\] \"%{WORD:http_verb} (?:%{PATH:baseurl}\?%{NOTSPACE:params}(?: HTTP/%{NUMBER:http_version})?|%{DATA:raw_http_request})\" (%{NOTSPACE:params})?|- %{NUMBER:http_status_code} (?:%{NUMBER:bytes_read}|-) %{QS:referrer} %{QS:agent} %{NUMBER:time_duration:float} %{NUMBER:time_backend_response:float}

这里使用了一点小技巧,params的使用,为了让GET和POST的参数都反映在一个参数上,在对应的GET和POST的参数的地方,都设计使用params这个参数进行对应。

好了,现在params中是请求的参数。比如source=ios&uid=123。但是呢,最后做统计的时候,我希望得出的是“所有source值为ios的调用”,那么就需要对参数进行结构化了。而且我们还希望如果接口中新加入了一个参数,不用修改logstash_indexer就可以直接使用,方法就是使用kv,kv能实现对一个字符串的结构进行k=v格式的拆分。其中的参数prefix可以为这个key在统计的时候增加一个前缀,include_keys可以设置有哪些key包含在其中,exclude_keys可以设置要排除哪些key。

kv {
  prefix => "params."
  field_split => "&"
  source => "params"
}

好了,现在还有一个问题,如果请求中有中文,那么日志中的中文是被urlencode之后存储的。我们具体分析的时候,比如有个接口是/api/search?keyword=我们,需要统计的是keyword被查询的热门顺序,那么就需要解码了。logstash牛逼的也有urldecode命令,urldecode可以设置对某个字段,也可以设置对所有字段进行解码。

urldecode {
  all_fields => true
}

看起来没事了,但是实际上在运行的时候,你会发现一个问题,就是存储到elasticsearch中的timestamp和请求日志中的请求时间不一样。原因是es中的请求日志使用的是日志结构存放进入es的时间,而不是timestamp的时间,这里想要吧es中的时间和请求日志中的时间统一怎么办呢?使用date命令。具体设置如下:

date {
    locale => "en"
    match => ["timestamp" , "dd/MMM/YYYY:HH:mm:ss Z"]
}

具体的logstash_indexer中的全部配置如下:

filter {
    grok {
      match => [
            "message", "%{IPORHOST:http_host} %{IPORHOST:server_ip} %{IPORHOST:client_ip} \[%{HTTPDATE:timestamp}\] \"%{WORD:http_verb} (?:%{PATH:baseurl}\?%{NOTSPACE:params}(?: HTTP/%{NUMBER:http_version})?|%{DATA:raw_http_request})\" (%{NOTSPACE:params})?|- %{NUMBER:http_status_code} (?:%{NUMBER:bytes_read}|-) %{QS:referrer} %{QS:agent} %{NUMBER:time_duration:float} %{NUMBER:time_backend_response:float}"
      ]
    }
    kv {
      prefix => "params."
      field_split => "&"
      source => "params"
    }
    urldecode {
         all_fields => true
    }
    date {
        locale => "en"
        match => ["timestamp" , "dd/MMM/YYYY:HH:mm:ss Z"]
    }

}

output部分
这里就是很简单往es中发送数据

output {
    elasticsearch {
        embedded => false
        protocol => "http"
        host => "localhost"
        port => "9200"
        user => "yejianfeng"
        password => "yejianfeng"
    }
}

这里有个user和password,其实elasticsearch加上shield就可以强制使用用户名密码登录了。这里的output就是配置这个使用的。

查询elasticsearch

比如上面的例子,我要查询某段时间的params.source(其实是source参数,但是前面的params是前缀)调用情况

$url = 'http://xx.xx.xx.xx:9200/logstash-*/_search';
$filter = '
{
 "query": {
    "range" : {
      "@timestamp" : {
        "gt" : 123213213213,
        "lt" : 123213213213
      }
    }
  },
  "aggs" : {
    "group_by_source" : {"terms" : {"field" : "params.source"}}
  },
  "size": 0
}';

以上是小编为您精心准备的的内容,在的博客、问答、公众号、人物、课程等栏目也有的相关内容,欢迎继续使用右上角搜索按钮进行搜索日志
, nginx
elk
elk nginx日志分析、elk收集nginx日志、elk nginx 日志、nginx web服务器详解、nginx 远程日志服务器,以便于您获取更多的相关知识。

时间: 2024-09-13 16:42:07

详解用ELK来分析Nginx服务器日志的方法_nginx的相关文章

elk收集分析nginx access日志

elk收集分析nginx access日志 首先elk的搭建按照这篇文章使用elk+redis搭建nginx日志分析平台说的,使用redis的push和pop做队列,然后有个logstash_indexer来从队列中pop数据分析插入elasticsearch.这样做的好处是可扩展,logstash_agent只需要收集log进入队列即可,比较可能会有瓶颈的log分析使用logstash_indexer来做,而这个logstash_indexer又是可以水平扩展的,我可以在单独的机器上跑多个in

详解Linux环境下使Nginx服务器支持中文url的配置流程_nginx

1:确定你的系统是UTF编码 [root@Tserver ~]# env|grep LANG LANG=en_US.UTF-8 2:NGINX配置文件里默认编码设置为utf-8 server { listen 80; server_name .inginx.com ; index index.html index.htm index.php; root /usr/local/nginx/html/inginx.com; charset utf-8; } 如果是用securecrt 上传文件,请选

在Ubuntu系统上安装Nginx服务器的简单方法_nginx

安装 Nginx sudo apt-get install nginx      如果你安装了 Apache ,并且此时 Apache 在运行,那么请先修改一下配置文件(没有的同学直接跳过): #打开配置文件 sudo vim /etc/nginx/sites-available/default      然后按以下两处修改(为了不和 Apache 冲突): server { #修改这里 我将 80 改为 88 listen 88 default_server; #还有这里 同样改为你想要的监听

通过浏览器查看nginx服务器状态配置方法_nginx

复制代码 代码如下: location /nginx-status { stub_status on; #access_log /var/log/nginx/mmt_nginx_status.log; access_log off; allow 192.168.0.10; deny all; #auth_basic "NginxStatus"; } 访问URL:http://192.168.0.11/nginx-status 结果: 复制代码 代码如下: Active connecti

详解房卡麻将分析系列 "牌局回放" 之 播放处理

详解房卡麻将分析系列 "牌局回放" 之 播放处理 昨天红孩儿给大伙讲了讲"牌局回放"的数据记录处理,有了数据的存储,下面就是数据的显示了. 实话讲,好久没用过 SQL Server 来做数据库了, 网狐的服务器是基于WIN,IOCP,  SQL Server 这套路子.配置好后,可以在QPTreasureDB数据库中看到三个牌局相关的表. 其中dbo.PrivateGameRecord是存储当前游戏的房间及玩家,最终胜负信息的. dbo.PrivateGameRec

Python 分析Nginx访问日志并保存到MySQL数据库实例_python

使用Python 分析Nginx access 日志,根据Nginx日志格式进行分割并存入MySQL数据库.一.Nginx access日志格式如下: 复制代码 代码如下: $remote_addr - $remote_user [$time_local] "$request" $status $body_bytes_sent "$http_referer" "$http_user_agent" "$http_x_forwarded_f

jQuery中deferred对象详解及源码分析

jQuery的deferred对象使用详解 jQuery的开发速度很快,几乎每半年一个大版本,每两个月一个小版本.每个版本都会引入一些新功能.今天我想介绍的,就是从jQuery 1.5.0版本开始引入的一个新功能--deferred对象.这个功能很重要,未来将成为jQuery的核心方法,它彻底改变了如何在jQuery中使用ajax.为了实现它,jQuery的全部ajax代码都被改写了.但是,它比较抽象,初学者很难掌握,网上的教程也不多.所以,我把自己的学习笔记整理出来了,希望对大家有用. 本文不

详解C# Socket简单例子(服务器与客户端通信)_C#教程

这个例子只是简单实现了如何使用 Socket 类实现面向连接的通信. 注意:此例子的目的只是为了说明用套接字写程序的大概思路,而不是实际项目中的使用程序.在这个例子中,实际上还有很多问题没有解决,如消息边界问题.端口号是否被占用.消息命令的解析问题等.. 下面是两个程序的代码,(两个程序均为控制台程序) 先发服务端的(Server)完整代码如下: 引入命名空间: using System.Net.Sockets; using SystemNet; using SystemThreading; 完

使用AWstats分析Nginx访问日志

软件下载地址:http://awstats.sourceforge.net/ 我下载的是稳定版本awstats-6.95.tar.gz 先上传下载文件到服务器上我习惯放在/opt下面 一.解压软件包: tar zxvf  awstats-6.95.tar.gz 然后放到/usr/local/下面 mv awstats-6.95 /usr/local/awstats 二.接着执行 tools 目录中的 awstats_configure.pl 配置向导,创建一个新的统计 [root@www too