{"id":1565,"date":"2023-03-25T17:39:21","date_gmt":"2023-03-25T09:39:21","guid":{"rendered":"https:\/\/www.appblog.cn\/?p=1565"},"modified":"2023-04-27T21:34:46","modified_gmt":"2023-04-27T13:34:46","slug":"implement-nginx-log-monitoring-with-filebeat-elasticsearch-grafana","status":"publish","type":"post","link":"https:\/\/www.appblog.cn\/index.php\/2023\/03\/25\/implement-nginx-log-monitoring-with-filebeat-elasticsearch-grafana\/","title":{"rendered":"Filebeat+ElasticSearch+Grafana\u5b9e\u73b0Nginx\u65e5\u5fd7\u76d1\u63a7"},"content":{"rendered":"<h2>Filebeat\u5b89\u88c5<\/h2>\n<p>\u5b98\u7f51\uff1a<a target=\"_blank\" rel=\"noopener\" href=\"https:\/\/www.elastic.co\/downloads\/beats\/filebeat\">https:\/\/www.elastic.co\/downloads\/beats\/filebeat<\/a><\/p>\n<p><!-- more --><\/p>\n<pre><code># wget https:\/\/artifacts.elastic.co\/downloads\/beats\/filebeat\/filebeat-7.1.0-linux-x86_64.tar.gz\n# tar -zxf filebeat-7.1.0-linux-x86_64.tar.gz -C \/usr\/local\/\n# mv \/usr\/local\/filebeat-7.1.0-linux-x86_64 \/usr\/local\/filebeat\n# cd \/usr\/local\/filebeat\/ \n# vim filebeat.yml<\/code><\/pre>\n<h2>Filebeat\u914d\u7f6e<\/h2>\n<h3>filebeat.yml<\/h3>\n<p>\u53c2\u8003\uff1a<a target=\"_blank\" rel=\"noopener\" href=\"https:\/\/github.com\/elastic\/beats\/issues\/11866\">https:\/\/github.com\/elastic\/beats\/issues\/11866<\/a><br \/>\n\u53c2\u8003\uff1a<a target=\"_blank\" rel=\"noopener\" href=\"https:\/\/iminto.github.io\/post\/filebeat\u4fee\u6539index\u7684\u4e00\u4e2a\u5751\/\">https:\/\/iminto.github.io\/post\/filebeat\u4fee\u6539index\u7684\u4e00\u4e2a\u5751\/<\/a><\/p>\n<pre><code class=\"language-yml\">#=========================== Filebeat inputs =============================\nfilebeat.inputs:\n- type: log\n  enabled: false\n  paths:\n    - \/usr\/local\/nginx\/logs\/access.log\n  #scan_frequency: 10s\n\n#============================= Filebeat modules ===============================\nfilebeat.config.modules:\n  path: ${path.config}\/modules.d\/*.yml\n  reload.enabled: false\n\n#==================== Elasticsearch template setting ==========================\n# 7.x\u7684\u7248\u672c\u4e2d\u9700\u8981\u7981\u7528\u6b64\u7d22\u5f15\u751f\u547d\u5468\u671f\uff0c\u5426\u5219\u5728\u6307\u5b9aes\u7d22\u5f15\u540d\u5b57\u7684\u65f6\u5019\u4f1a\u6709\u95ee\u9898\nsetup.ilm.enabled: false\n# \u6dfb\u52a0\u6a21\u677f\u914d\u7f6e\uff0c\u5426\u5219\u65e0\u6cd5\u6307\u5b9aes\u7684\u7d22\u5f15\u540d\nsetup.template.enabled: true\nsetup.template.name: &quot;nginx-log&quot;\nsetup.template.pattern: &quot;nginx-log-*&quot;\nsetup.template.overwrite: true\n\nsetup.template.settings:\n  index.number_of_shards: 1\n  index.number_of_replicas: 1\n\n#============================== Kibana =====================================\nsetup.kibana:\n  host: &quot;192.168.165.239:5601&quot;\n\n#================================ Outputs =====================================\noutput.elasticsearch:\n  hosts: [&quot;192.168.16.20:9200&quot;]  # [&quot;192.168.16.21:9200&quot;, &quot;192.168.16.22:9200&quot;, &quot;192.168.16.23:9200&quot;]\n  index: &quot;nginx-log-%{+yyyy.MM.dd}&quot;\n\n#================================ Processors =====================================\nprocessors:\n  #- add_host_metadata: ~\n  #- add_cloud_metadata: ~\n  - drop_fields:\n        fields: [&quot;beat.name&quot;, &quot;beat.version&quot;, &quot;host.architecture&quot;,&quot;host.architecture&quot;,&quot;host.name&quot;,&quot;beat.hostname&quot;,&quot;log.file.path&quot;]<\/code><\/pre>\n<p>\u65e0\u6cd5\u81ea\u5b9a\u4e49\u7d22\u5f15\u540d\u79f0\u662f\u56e0\u4e3a\uff0c\u7d22\u5f15\u751f\u547d\u5468\u671f\u7ba1\u7406ilm\u529f\u80fd\u9ed8\u8ba4\u5f00\u542f\uff0c\u5f00\u542f\u7684\u60c5\u51b5\u4e0b\u7d22\u5f15\u540d\u79f0\u53ea\u80fd\u4e3a<code>filebeat-*<\/code>\uff0c \u901a\u8fc7<code>setup.ilm.enabled: false<\/code>\u8fdb\u884c\u5173\u95ed\uff1b\u5982\u679c\u8981\u4f7f\u7528\u81ea\u5b9a\u4e49\u7684\u7d22\u5f15\u540d\u79f0\uff0c\u540c\u65f6\u53c8\u9700\u8981\u542f\u7528ilm\uff0c\u53ef\u4ee5\u4fee\u6539filebeat\u7684\u6a21\u677f<\/p>\n<p>\u914d\u7f6e\u6a21\u677f\uff1a<a target=\"_blank\" rel=\"noopener\" href=\"https:\/\/www.elastic.co\/guide\/en\/beats\/filebeat\/current\/ilm.html\">https:\/\/www.elastic.co\/guide\/en\/beats\/filebeat\/current\/ilm.html<\/a><\/p>\n<pre><code class=\"language-yml\">setup.ilm.enabled: auto\nsetup.ilm.rollover_alias: &quot;filebeat&quot;\nsetup.ilm.pattern: &quot;{now\/d}-000001&quot;<\/code><\/pre>\n<h3>\u542f\u7528\u6a21\u5757nginx<\/h3>\n<pre><code># cp modules.d\/nginx.yml.disabled modules.d\/nginx.yml\n# vim modules.d\/nginx.yml<\/code><\/pre>\n<pre><code class=\"language-yml\"># Module: nginx\n# Docs: https:\/\/www.elastic.co\/guide\/en\/beats\/filebeat\/7.1\/filebeat-module-nginx.html\n\n- module: nginx\n  # Access logs\n  access:\n    enabled: true\n\n    # Set custom paths for the log files. If left empty,\n    # Filebeat will choose the paths depending on your OS.\n    var.paths: [&quot;\/usr\/local\/nginx\/logs\/access.log&quot;]\n\n    # Convert the timestamp to UTC. Requires Elasticsearch &gt;= 6.1.\n    #var.convert_timezone: true\n\n  # Error logs\n  error:\n    enabled: true\n\n    # Set custom paths for the log files. If left empty,\n    # Filebeat will choose the paths depending on your OS.\n    var.paths: [&quot;\/usr\/local\/nginx\/logs\/error.log&quot;]\n\n    # Convert the timestamp to UTC. Requires Elasticsearch &gt;= 6.1.\n    #var.convert_timezone: true<\/code><\/pre>\n<h3>Nginx\u914d\u7f6e<\/h3>\n<pre><code>http {\n    log_format   main   &#039;$remote_addr -&#039;\n                        &#039; $remote_user&#039;\n                        &#039; [$time_local]&#039;\n                        &#039; &quot;$request&quot;&#039;\n                        &#039; $status&#039;\n                        &#039; $body_bytes_sent&#039;\n                        &#039; &quot;$http_referer&quot;&#039;\n                        &#039; &quot;$http_user_agent&quot;&#039;\n                        &#039; &quot;$http_x_forwarded_for&quot;&#039;\n                        &#039; $upstream_response_time&#039;\n                        &#039; $upstream_addr&#039;;\n\n    access_log  logs\/access.log  main;\n}<\/code><\/pre>\n<h3>ingest\u914d\u7f6e<\/h3>\n<pre><code># cp module\/nginx\/access\/ingest\/default.json module\/nginx\/access\/ingest\/default.json.bak\n# vim module\/nginx\/access\/ingest\/default.json<\/code><\/pre>\n<pre><code class=\"language-json\">{\n  &quot;description&quot;: &quot;Pipeline for parsing Nginx access logs. Requires the geoip and user_agent plugins.&quot;,\n  &quot;processors&quot;: [{\n    &quot;grok&quot;: {\n      &quot;field&quot;: &quot;message&quot;,\n      &quot;patterns&quot;:[\n        &quot;\\&quot;?%{IP_LIST:nginx.access.remote_ip_list} - %{DATA:nginx.access.user_name} \\\\[%{HTTPDATE:nginx.access.time}\\\\] \\&quot;%{GREEDYDATA:nginx.access.info}\\&quot; %{NUMBER:nginx.access.response_code} %{NUMBER:nginx.access.body_sent.bytes} \\&quot;%{DATA:nginx.access.referrer}\\&quot; \\&quot;%{DATA:nginx.access.agent}\\&quot; \\&quot;%{GREEDYDATA:nginx.access.xforwardedfor}\\&quot; %{GREEDYDATA:nginx.access.upstream_response_time} %{GREEDYDATA:nginx.access.upstream_addr}&quot;\n        ],\n      &quot;pattern_definitions&quot;: {\n        &quot;IP_LIST&quot;: &quot;%{IP}(\\&quot;?,?\\\\s*%{IP})*&quot;\n      },\n      &quot;ignore_missing&quot;: true\n    }\n  }, {\n    &quot;grok&quot;: {\n      &quot;field&quot;: &quot;nginx.access.info&quot;,\n      &quot;patterns&quot;: [\n          &quot;%{WORD:nginx.access.method} %{DATA:nginx.access.url} HTTP\/%{NUMBER:nginx.access.http_version}&quot;,\n          &quot;&quot;\n      ],\n      &quot;ignore_missing&quot;: true\n    }\n  }, {\n    &quot;remove&quot;: {\n      &quot;field&quot;: &quot;nginx.access.info&quot;\n    }\n  }, {\n    &quot;split&quot;: {\n      &quot;field&quot;: &quot;nginx.access.remote_ip_list&quot;,\n      &quot;separator&quot;: &quot;\\&quot;?,?\\\\s+&quot;\n    }\n  }, {\n    &quot;script&quot;: {\n      &quot;lang&quot;: &quot;painless&quot;,\n      &quot;inline&quot;: &quot;boolean isPrivate(def ip) { try { StringTokenizer tok = new StringTokenizer(ip, &#039;.&#039;); int firstByte = Integer.parseInt(tok.nextToken());       int secondByte = Integer.parseInt(tok.nextToken());       if (firstByte == 10) {         return true;       }       if (firstByte == 192 &amp;&amp; secondByte == 168) {         return true;       }       if (firstByte == 172 &amp;&amp; secondByte &gt;= 16 &amp;&amp; secondByte &lt;= 31) {         return true;       }       if (firstByte == 127) {         return true;       }       return false;     } catch (Exception e) {       return false;     }   }   def found = false;   for (def item : ctx.nginx.access.remote_ip_list) {     if (!isPrivate(item)) {       ctx.nginx.access.remote_ip = item;       found = true;       break;     }   }   if (!found) {     ctx.nginx.access.remote_ip = ctx.nginx.access.remote_ip_list[0];   }&quot;\n      }\n  }, {\n    &quot;remove&quot;:{\n      &quot;field&quot;: &quot;message&quot;\n    }\n  }, {\n    &quot;rename&quot;: {\n      &quot;field&quot;: &quot;@timestamp&quot;,\n      &quot;target_field&quot;: &quot;read_timestamp&quot;\n    }\n  }, {\n    &quot;date&quot;: {\n      &quot;field&quot;: &quot;nginx.access.time&quot;,\n      &quot;target_field&quot;: &quot;@timestamp&quot;,\n      &quot;formats&quot;: [&quot;dd\/MMM\/YYYY:H:m:s Z&quot;]\n    }\n  },{\n    &quot;remove&quot;: {\n      &quot;field&quot;: &quot;nginx.access.time&quot;\n    }\n  }, {\n    &quot;user_agent&quot;: {\n      &quot;field&quot;: &quot;nginx.access.agent&quot;,\n      &quot;target_field&quot;: &quot;nginx.access.user_agent&quot;\n    }\n  }, {\n    &quot;rename&quot;: {\n      &quot;field&quot;: &quot;nginx.access.agent&quot;,\n      &quot;target_field&quot;: &quot;nginx.access.user_agent.original&quot;\n    }\n  }, {\n    &quot;geoip&quot;: {\n      &quot;field&quot;: &quot;nginx.access.remote_ip&quot;,\n      &quot;target_field&quot;: &quot;nginx.access.geoip&quot;\n    }\n  }, {\n    &quot;script&quot;: {\n      &quot;lang&quot;: &quot;painless&quot;,\n      &quot;inline&quot;: &quot;String tmp=ctx.nginx.access.upstream_response_time; if (tmp==&#039;-&#039;){ctx.nginx.access.upstream_response_time=-1.0}else{ctx.nginx.access.upstream_response_time=Float.parseFloat(tmp)}&quot;\n      }\n  }],\n  &quot;on_failure&quot; : [{\n    &quot;set&quot; : {\n      &quot;field&quot; : &quot;error.message&quot;,\n      &quot;value&quot; : &quot;{{ _ingest.on_failure_message }}&quot;\n    }\n  }]\n}<\/code><\/pre>\n<h2>Filebeat\u542f\u52a8<\/h2>\n<pre><code>nohup .\/filebeat -e -c filebeat.yml &gt;&amp;\/dev\/null &amp;<\/code><\/pre>\n<h2>Grafana\u914d\u7f6e<\/h2>\n<h3>Data Source<\/h3>\n<p>![es-nginx\u65e5\u5fd7](<a target=\"_blank\" rel=\"noopener\" href=\"http:\/\/www.yezhou.me\/AppBlog\/images\/\u8fd0\u7ef4\/Grafana\">http:\/\/www.yezhou.me\/AppBlog\/images\/\u8fd0\u7ef4\/Grafana<\/a> Data Sources &#8211; es-nginx\u65e5\u5fd7.png)<\/p>\n<h3>Dashboard<\/h3>\n<p>![NGINX \u8bbf\u95ee\u91cf\u7edf\u8ba1](<a target=\"_blank\" rel=\"noopener\" href=\"http:\/\/www.yezhou.me\/AppBlog\/images\/\u8fd0\u7ef4\/Grafana\">http:\/\/www.yezhou.me\/AppBlog\/images\/\u8fd0\u7ef4\/Grafana<\/a> Dashboard &#8211; NGINX \u8bbf\u95ee\u91cf\u7edf\u8ba1.png)<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Filebeat\u5b89\u88c5 \u5b98\u7f51\uff1ahttps:\/\/www.elastic.co\/downloads\/beats\/fi [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[386],"tags":[180,390,385,25],"class_list":["post-1565","post","type-post","status-publish","format-standard","hentry","category-monitor","tag-elasticsearch","tag-filebeat","tag-grafana","tag-nginx"],"_links":{"self":[{"href":"https:\/\/www.appblog.cn\/index.php\/wp-json\/wp\/v2\/posts\/1565","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.appblog.cn\/index.php\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.appblog.cn\/index.php\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.appblog.cn\/index.php\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.appblog.cn\/index.php\/wp-json\/wp\/v2\/comments?post=1565"}],"version-history":[{"count":0,"href":"https:\/\/www.appblog.cn\/index.php\/wp-json\/wp\/v2\/posts\/1565\/revisions"}],"wp:attachment":[{"href":"https:\/\/www.appblog.cn\/index.php\/wp-json\/wp\/v2\/media?parent=1565"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.appblog.cn\/index.php\/wp-json\/wp\/v2\/categories?post=1565"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.appblog.cn\/index.php\/wp-json\/wp\/v2\/tags?post=1565"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}