Configuração do Nginx
O primeiro passo consiste em ajustar o formato de logs no nginx.conf. Definimos um formato personalizado para capturar os campos essenciais para a análise posterior.
http {
# ...
log_format grafana_monitor '$remote_addr - $remote_user [$time_local] '
'"$request" $status $body_bytes_sent '
'"$http_referer" "$http_user_agent"';
access_log /var/log/nginx/access.log grafana_monitor;
# ...
}
Configuração do Fielbeat
No arquivo filebeat.yml, configuramos o shipper para ler os arquivos de logs e enviá-los para o Logstash. É importante adicionar campos personalizados para identificar o tipo de serviço.
filebeat.inputs:
- type: log
enabled: true
paths:
- /var/log/nginx/access.log
fields:
service: nginx-web
fields_under_root: true
encoding: utf-8
output.logstash:
hosts: ["192.168.1.100:5044"]
processors:
- add_host_metadata: ~
- add_cloud_metadata: ~
Configuração do Logstash
O Logstash será responsável por filtrar e estruturar os dados. Primeiro, instale o plugin de geo-localização:
bin/logstash-plugin install logstash-filter-geoip
Em seguida, configure o pipeline (pipeline.conf). Utilizaremos o filtro grok para parsear a mensagem de log baseada no formato definido no Nginx e o geoip para obter dados de localização.
input {
beats {
port => 5044
}
}
filter {
if [service] == "nginx-web" {
grok {
match => {
"message" => "%{IP:client_ip} - %{DATA:user_id} \[%{HTTPDATE:access_timestamp}\] \"%{WORD:http_method} %{NOTSPACE:request_path} HTTP/%{NUMBER:http_version}\" %{NUMBER:response_code} %{NUMBER:bytes_sent} \"%{DATA:http_referrer}\" \"%{DATA:user_agent}\""
}
}
geoip {
source => "client_ip"
fields => ["city_name", "country_name", "region_name", "location"]
}
mutate {
convert => { "bytes_sent" => "integer" }
remove_field => ["host", "agent", "ecs", "log"]
}
}
}
output {
if [service] == "nginx-web" {
elasticsearch {
hosts => ["http://192.168.1.100:9200"]
index => "nginx-logs-%{+YYYY.MM.dd}"
user => "elastic"
password => "changeme"
}
}
}
Elasticsearch e Grafana
Certifique-se de que o cluster Elasticsearch esteja operacional para receber os índices. No Grafana, adicione o Elasticsearch como fonte de dados (Datasource), apontando para a URL da instância e configurando o padrão de índice como nginx-logs-*.
Configuração do Painel (JSON)
Abaixo está a configuração JSON para o painel do Grafana. Este exemplo foi adaptado para utilizar os novos nomes de campos definidos na configuração do Logstash (client_ip, response_code, etc.) e visualiza métricas como volume de logs, visitantes únicos e distribuição geográfica.
{
"annotations": {
"list": []
},
"editable": true,
"gnetId": null,
"graphTooltip": 0,
"id": null,
"links": [],
"panels": [
{
"datasource": {
"type": "elasticsearch",
"uid": "P8079B216C365C7D9"
},
"fieldConfig": {
"defaults": {
"color": {
"mode": "thresholds"
},
"mappings": [],
"thresholds": {
"mode": "absolute",
"steps": [
{
"color": "green",
"value": null
}
]
}
},
"overrides": []
},
"gridPos": {
"h": 8,
"w": 6,
"x": 0,
"y": 0
},
"id": 1,
"options": {
"colorMode": "value",
"graphMode": "area",
"justifyMode": "auto",
"orientation": "auto",
"reduceOptions": {
"calcs": ["lastNotNull"],
"fields": "",
"values": false
},
"textMode": "auto"
},
"pluginVersion": "8.3.0",
"targets": [
{
"alias": "Total de Solicitações",
"bucketAggs": [
{
"field": "@timestamp",
"id": "2",
"settings": {
"interval": "1h"
},
"type": "date_histogram"
}
],
"datasource": {
"type": "elasticsearch",
"uid": "P8079B216C365C7D9"
},
"metrics": [
{
"id": "1",
"type": "count"
}
],
"query": "",
"refId": "A",
"timeField": "@timestamp"
}
],
"title": "Volume de Logs",
"type": "stat"
},
{
"datasource": {
"type": "elasticsearch",
"uid": "P8079B216C365C7D9"
},
"fieldConfig": {
"defaults": {
"color": {
"mode": "thresholds"
},
"custom": {
"align": "auto",
"displayMode": "auto"
},
"mappings": []
},
"overrides": [
{
"matcher": {
"id": "byName",
"options": "response_code"
},
"properties": [
{
"id": "custom.width",
"value": 150
}
]
}
]
},
"gridPos": {
"h": 8,
"w": 18,
"x": 6,
"y": 0
},
"id": 2,
"options": {
"showHeader": true
},
"pluginVersion": "8.3.0",
"targets": [
{
"alias": "",
"bucketAggs": [
{
"field": "response_code",
"id": "2",
"settings": {
"size": "10"
},
"type": "terms"
}
],
"datasource": {
"type": "elasticsearch",
"uid": "P8079B216C365C7D9"
},
"metrics": [
{
"id": "1",
"type": "count"
}
],
"query": "",
"refId": "A"
}
],
"title": "Status HTTP",
"type": "table"
},
{
"datasource": {
"type": "elasticsearch",
"uid": "P8079B216C365C7D9"
},
"fieldConfig": {
"defaults": {
"color": {
"mode": "thresholds"
},
"mappings": [
{
"options": {
"from": 0,
"result": {
"text": "Baixo"
},
"to": 100
},
"type": "range"
}
]
}
},
"gridPos": {
"h": 9,
"w": 24,
"x": 0,
"y": 8
},
"id": 3,
"options": {
"basemap": {
"name": "Layer 0",
"type": "esri-xyz"
},
"view": {
"id": "min_zoom",
"lat": 0,
"lon": 0,
"zoom": 2
}
},
"targets": [
{
"bucketAggs": [],
"datasource": {
"type": "elasticsearch",
"uid": "P8079B216C365C7D9"
},
"metrics": [
{
"id": "1",
"settings": {
"size": "5000"
},
"type": "raw_data"
}
],
"query": "",
"refId": "A"
}
],
"title": "Mapa Geográfico de IPs",
"type": "geomap"
},
{
"datasource": {
"type": "elasticsearch",
"uid": "P8079B216C365C7D9"
},
"fieldConfig": {
"defaults": {
"color": {
"mode": "palette-classic"
},
"custom": {
"hideFrom": {
"tooltip": false,
"viz": false,
"legend": false
}
}
}
},
"gridPos": {
"h": 8,
"w": 12,
"x": 0,
"y": 17
},
"id": 4,
"targets": [
{
"alias": "Top 10 IPs",
"bucketAggs": [
{
"field": "client_ip",
"id": "2",
"settings": {
"size": "10"
},
"type": "terms"
}
],
"metrics": [
{
"id": "1",
"type": "count"
}
],
"refId": "A"
}
],
"title": "Origens por IP",
"type": "piechart"
},
{
"datasource": {
"type": "elasticsearch",
"uid": "P8079B216C365C7D9"
},
"fieldConfig": {
"defaults": {
"color": {
"mode": "palette-classic"
}
}
},
"gridPos": {
"h": 8,
"w": 12,
"x": 12,
"y": 17
},
"id": 5,
"targets": [
{
"alias": "User Agents",
"bucketAggs": [
{
"field": "user_agent",
"id": "2",
"settings": {
"size": "10"
},
"type": "terms"
}
],
"metrics": [
{
"id": "1",
"type": "count"
}
],
"refId": "A"
}
],
"title": "Principais User Agents",
"type": "bargauge"
}
],
"refresh": "5m",
"schemaVersion": 36,
"style": "dark",
"title": "Nginx Dashboard",
"uid": "nginx-analytics",
"version": 1
}