Compare commits
No commits in common. "fb54294e0081c1026106cfba42e7e08466909e83" and "fc05977de07eea73a0a041c18d730ce45406384c" have entirely different histories.
fb54294e00
...
fc05977de0
|
|
@ -1,81 +0,0 @@
|
|||
import yaml
|
||||
import uuid
|
||||
import sys
|
||||
|
||||
def extract_nginx_config(input_file, output_file):
|
||||
print(f"Reading {input_file}...")
|
||||
with open(input_file, 'r', encoding='utf-8') as f:
|
||||
data = yaml.safe_load(f)
|
||||
|
||||
if 'zabbix_export' not in data or 'hosts' not in data['zabbix_export']:
|
||||
print("No hosts found in export file (checked under zabbix_export['hosts']).")
|
||||
return
|
||||
|
||||
# We assume we are extracting from the first host or all hosts,
|
||||
# but usually an export has one specific host of interest.
|
||||
# The user mentioned "srvproxy001".
|
||||
|
||||
extracted_discovery_rules = []
|
||||
extracted_items = []
|
||||
|
||||
for host in data['zabbix_export']['hosts']:
|
||||
print(f"Processing host: {host['host']}")
|
||||
|
||||
# Extract Discovery Rules related to Nginx
|
||||
if 'discovery_rules' in host:
|
||||
for dr in host['discovery_rules']:
|
||||
# Filter by name or key containing 'nginx'
|
||||
if 'nginx' in dr['key'].lower() or 'nginx' in dr['name'].lower() or 'insight' in dr['name'].lower():
|
||||
print(f" Found Discovery Rule: {dr['name']} ({dr['key']})")
|
||||
extracted_discovery_rules.append(dr)
|
||||
|
||||
# Extract Items related to Nginx (directly attached to host, not in LLD)
|
||||
if 'items' in host:
|
||||
for item in host['items']:
|
||||
if 'nginx' in item['key'].lower() or 'nginx' in item['name'].lower():
|
||||
print(f" Found Item: {item['name']} ({item['key']})")
|
||||
extracted_items.append(item)
|
||||
|
||||
if not extracted_discovery_rules and not extracted_items:
|
||||
print("No Nginx configurations found.")
|
||||
return
|
||||
|
||||
# Create Template Structure
|
||||
template_uuid = str(uuid.uuid4())
|
||||
group_uuid = "7df96b18c230490a9a0a9e2307226338" # Generic uuid for Templates group
|
||||
|
||||
template_export = {
|
||||
'zabbix_export': {
|
||||
'version': data['zabbix_export']['version'],
|
||||
'template_groups': [
|
||||
{
|
||||
'uuid': group_uuid,
|
||||
'name': 'Templates/Applications'
|
||||
}
|
||||
],
|
||||
'templates': [
|
||||
{
|
||||
'uuid': template_uuid,
|
||||
'template': 'Template Nginx Custom Insight',
|
||||
'name': 'Template Nginx Custom Insight',
|
||||
'description': 'Template extracted from host configuration containing custom Nginx Insight rules.',
|
||||
'groups': [
|
||||
{'name': 'Templates/Applications'}
|
||||
],
|
||||
'items': extracted_items,
|
||||
'discovery_rules': extracted_discovery_rules
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
print(f"Writing to {output_file}...")
|
||||
with open(output_file, 'w', encoding='utf-8') as f:
|
||||
yaml.dump(template_export, f, sort_keys=False, allow_unicode=True)
|
||||
print("Done.")
|
||||
|
||||
if __name__ == "__main__":
|
||||
if len(sys.argv) < 3:
|
||||
print("Usage: python extract_nginx_config.py <input_yaml> <output_yaml>")
|
||||
else:
|
||||
extract_nginx_config(sys.argv[1], sys.argv[2])
|
||||
|
|
@ -1,69 +0,0 @@
|
|||
import yaml
|
||||
import sys
|
||||
|
||||
def merge_templates(base_file, custom_file, output_file):
|
||||
print(f"Loading base template: {base_file}")
|
||||
with open(base_file, 'r', encoding='utf-8') as f:
|
||||
base_data = yaml.safe_load(f)
|
||||
|
||||
print(f"Loading custom template: {custom_file}")
|
||||
with open(custom_file, 'r', encoding='utf-8') as f:
|
||||
custom_data = yaml.safe_load(f)
|
||||
|
||||
# Assume standard Zabbix 6.0+ YAML export structure
|
||||
# zabbix_export -> templates -> [list]
|
||||
|
||||
if 'zabbix_export' not in base_data or 'templates' not in base_data['zabbix_export']:
|
||||
print("Invalid base template structure.")
|
||||
return
|
||||
|
||||
base_template = base_data['zabbix_export']['templates'][0]
|
||||
|
||||
if 'zabbix_export' in custom_data and 'templates' in custom_data['zabbix_export']:
|
||||
custom_template = custom_data['zabbix_export']['templates'][0]
|
||||
else:
|
||||
print("Invalid custom template structure.")
|
||||
return
|
||||
|
||||
print("Merging Discovery Rules...")
|
||||
if 'discovery_rules' in custom_template:
|
||||
if 'discovery_rules' not in base_template:
|
||||
base_template['discovery_rules'] = []
|
||||
|
||||
# Check for duplicates by name or key to avoid collision
|
||||
existing_keys = {dr['key'] for dr in base_template['discovery_rules']}
|
||||
|
||||
for dr in custom_template['discovery_rules']:
|
||||
if dr['key'] in existing_keys:
|
||||
print(f" Skipping duplicate key: {dr['key']}")
|
||||
else:
|
||||
print(f" Adding rule: {dr['name']}")
|
||||
base_template['discovery_rules'].append(dr)
|
||||
|
||||
print("Merging Items...")
|
||||
if 'items' in custom_template:
|
||||
if 'items' not in base_template:
|
||||
base_template['items'] = []
|
||||
|
||||
existing_item_keys = {item['key'] for item in base_template['items']}
|
||||
|
||||
for item in custom_template['items']:
|
||||
if item['key'] in existing_item_keys:
|
||||
print(f" Skipping duplicate item key: {item['key']}")
|
||||
else:
|
||||
print(f" Adding item: {item['name']}")
|
||||
base_template['items'].append(item)
|
||||
|
||||
# Update Template Name
|
||||
base_template['name'] = "Nginx by Zabbix agent (Gold)"
|
||||
|
||||
print(f"Writing merged template to {output_file}")
|
||||
with open(output_file, 'w', encoding='utf-8') as f:
|
||||
yaml.dump(base_data, f, sort_keys=False, allow_unicode=True)
|
||||
print("Merge Complete.")
|
||||
|
||||
if __name__ == "__main__":
|
||||
if len(sys.argv) < 4:
|
||||
print("Usage: python merge_nginx_templates.py <base_yaml> <custom_yaml> <output_yaml>")
|
||||
else:
|
||||
merge_templates(sys.argv[1], sys.argv[2], sys.argv[3])
|
||||
|
|
@ -1,749 +0,0 @@
|
|||
zabbix_export:
|
||||
version: '7.4'
|
||||
template_groups:
|
||||
- uuid: 7df96b18c230490a9a0a9e2307226338
|
||||
name: Templates/Applications
|
||||
templates:
|
||||
- uuid: cb591855-1b11-4789-9cdd-9f9aaeea5edb
|
||||
template: Template Nginx Custom Insight
|
||||
name: Template Nginx Custom Insight
|
||||
description: Template extracted from host configuration containing custom Nginx
|
||||
Insight rules.
|
||||
groups:
|
||||
- name: Templates/Applications
|
||||
items: []
|
||||
discovery_rules:
|
||||
- name: 'Insight: Log de Acesso'
|
||||
type: ZABBIX_ACTIVE
|
||||
key: nginx.access.logs.list
|
||||
delay: 1s
|
||||
enabled_lifetime_type: DISABLE_AFTER
|
||||
enabled_lifetime: 1h
|
||||
item_prototypes:
|
||||
- name: 'Insight: Acesso {#HOST_SITE}'
|
||||
type: ZABBIX_ACTIVE
|
||||
key: log[/var/log/nginx/{#HOST_SITE}.access.log]
|
||||
delay: 1s
|
||||
history: 91d
|
||||
value_type: LOG
|
||||
timeout: 120s
|
||||
tags:
|
||||
- tag: Insight
|
||||
value: access log
|
||||
- name: 'Insight: Bad-Bot {#HOST_SITE}'
|
||||
type: ZABBIX_ACTIVE
|
||||
key: log[/var/log/nginx/{#HOST_SITE}.bad-bot.log]
|
||||
delay: 1s
|
||||
value_type: LOG
|
||||
timeout: 120s
|
||||
tags:
|
||||
- tag: Insight
|
||||
value: bad-bot
|
||||
- name: 'Insight: Erros {#HOST_SITE}'
|
||||
type: ZABBIX_ACTIVE
|
||||
key: log[/var/log/nginx/{#HOST_SITE}.error.log]
|
||||
delay: 1s
|
||||
value_type: LOG
|
||||
timeout: 120s
|
||||
tags:
|
||||
- tag: Insight
|
||||
value: error log
|
||||
- name: 'Nginx: Cache HITs Flag for {#HOST_SITE}'
|
||||
type: DEPENDENT
|
||||
key: nginx.cache.hit.flag.[{#HOST_SITE}]
|
||||
preprocessing:
|
||||
- type: REGEX
|
||||
parameters:
|
||||
- upstream_cache_status":"HIT"
|
||||
- '1'
|
||||
error_handler: CUSTOM_VALUE
|
||||
error_handler_params: '0'
|
||||
master_item:
|
||||
key: log[/var/log/nginx/{#HOST_SITE}.access.log]
|
||||
tags:
|
||||
- tag: Insight
|
||||
value: performance
|
||||
- name: 'Insight: Cache Hit Ratio (Ultimo 1m) (%) {#HOST_SITE}'
|
||||
type: CALCULATED
|
||||
key: nginx.cache.hit.ratio.1m.[{#HOST_SITE}]
|
||||
value_type: FLOAT
|
||||
units: '%'
|
||||
params: (last(//nginx.cache.hits.1m.[{#HOST_SITE}]) * 100) / (last(//nginx.cache.hits.1m.[{#HOST_SITE}])
|
||||
+ last(//nginx.cache.miss.1m.[{#HOST_SITE}]) + (last(//nginx.cache.hits.1m.[{#HOST_SITE}])
|
||||
+ last(//nginx.cache.miss.1m.[{#HOST_SITE}]) = 0))
|
||||
tags:
|
||||
- tag: Insight
|
||||
value: carga
|
||||
- name: 'Insight: Cache HITs no Ultimo minuto {#HOST_SITE}'
|
||||
type: CALCULATED
|
||||
key: nginx.cache.hits.1m.[{#HOST_SITE}]
|
||||
units: hits
|
||||
params: sum(//nginx.cache.hit.flag.[{#HOST_SITE}],1m)
|
||||
tags:
|
||||
- tag: Insight
|
||||
value: cache
|
||||
- tag: Insight
|
||||
value: performance
|
||||
- name: 'Insight: Cache HITs nos Ultimos 5 minuto {#HOST_SITE}'
|
||||
type: CALCULATED
|
||||
key: nginx.cache.hits.5m.[{#HOST_SITE}]
|
||||
delay: 4m
|
||||
units: hits
|
||||
params: sum(//nginx.cache.hit.flag.[{#HOST_SITE}],5m)
|
||||
tags:
|
||||
- tag: Insight
|
||||
value: cache
|
||||
- tag: Insight
|
||||
value: performance
|
||||
- name: 'Insight: Cache HITs nos Ultimos 15 minuto {#HOST_SITE}'
|
||||
type: CALCULATED
|
||||
key: nginx.cache.hits.15m.[{#HOST_SITE}]
|
||||
delay: 14m
|
||||
units: hits
|
||||
params: sum(//nginx.cache.hit.flag.[{#HOST_SITE}],15m)
|
||||
tags:
|
||||
- tag: Insight
|
||||
value: cache
|
||||
- tag: Insight
|
||||
value: performance
|
||||
- name: 'Insight: Cache HITs nos Ultimos 24 hrs {#HOST_SITE}'
|
||||
type: CALCULATED
|
||||
key: nginx.cache.hits.24h.[{#HOST_SITE}]
|
||||
delay: 1h
|
||||
units: hits
|
||||
params: sum(//nginx.cache.hit.flag.[{#HOST_SITE}],24h)
|
||||
tags:
|
||||
- tag: Insight
|
||||
value: cache
|
||||
- tag: Insight
|
||||
value: performance
|
||||
- name: 'Insight: Cache MISS no Ultimo minuto {#HOST_SITE}'
|
||||
type: CALCULATED
|
||||
key: nginx.cache.miss.1m.[{#HOST_SITE}]
|
||||
units: miss
|
||||
params: sum(//nginx.cache.miss.flag.[{#HOST_SITE}],1m)
|
||||
tags:
|
||||
- tag: Insight
|
||||
value: cache
|
||||
- tag: Insight
|
||||
value: performance
|
||||
- name: 'Insight: Cache MISS no Ultimos 5 minuto {#HOST_SITE}'
|
||||
type: CALCULATED
|
||||
key: nginx.cache.miss.5m.[{#HOST_SITE}]
|
||||
delay: 4m
|
||||
units: miss
|
||||
params: sum(//nginx.cache.miss.flag.[{#HOST_SITE}],5m)
|
||||
tags:
|
||||
- tag: Insight
|
||||
value: cache
|
||||
- tag: Insight
|
||||
value: performance
|
||||
- name: 'Insight: Cache MISS no Ultimos 15 minuto {#HOST_SITE}'
|
||||
type: CALCULATED
|
||||
key: nginx.cache.miss.15m.[{#HOST_SITE}]
|
||||
delay: 14m
|
||||
units: miss
|
||||
params: sum(//nginx.cache.miss.flag.[{#HOST_SITE}],15m)
|
||||
tags:
|
||||
- tag: Insight
|
||||
value: cache
|
||||
- tag: Insight
|
||||
value: performance
|
||||
- name: 'Insight: Cache MISS no Ultimos 24 horas {#HOST_SITE}'
|
||||
type: CALCULATED
|
||||
key: nginx.cache.miss.24h.[{#HOST_SITE}]
|
||||
delay: 1h
|
||||
units: miss
|
||||
params: sum(//nginx.cache.miss.flag.[{#HOST_SITE}],24h)
|
||||
tags:
|
||||
- tag: Insight
|
||||
value: cache
|
||||
- tag: Insight
|
||||
value: performance
|
||||
- name: 'Nginx: Cache MISS Flag for {#HOST_SITE}'
|
||||
type: DEPENDENT
|
||||
key: nginx.cache.miss.flag.[{#HOST_SITE}]
|
||||
preprocessing:
|
||||
- type: REGEX
|
||||
parameters:
|
||||
- upstream_cache_status":"MISS"
|
||||
- '1'
|
||||
error_handler: DISCARD_VALUE
|
||||
master_item:
|
||||
key: log[/var/log/nginx/{#HOST_SITE}.access.log]
|
||||
tags:
|
||||
- tag: Insight
|
||||
value: cache
|
||||
- tag: Insight
|
||||
value: performance
|
||||
- name: 'Insight: Cache Miss Ratio (Ultimo 1m) (%) {#HOST_SITE}'
|
||||
type: CALCULATED
|
||||
key: nginx.cache.miss.ratio.1m.[{#HOST_SITE}]
|
||||
value_type: FLOAT
|
||||
units: '%'
|
||||
params: (last(//nginx.cache.miss.1m.[{#HOST_SITE}]) * 100) / (last(//nginx.cache.hits.1m.[{#HOST_SITE}])
|
||||
+ last(//nginx.cache.miss.1m.[{#HOST_SITE}]) + (last(//nginx.cache.hits.1m.[{#HOST_SITE}])
|
||||
+ last(//nginx.cache.miss.1m.[{#HOST_SITE}]) = 0))
|
||||
tags:
|
||||
- tag: Insight
|
||||
value: carga
|
||||
- name: 'Insight: {#HOST_SITE} Marcações Usuario Online'
|
||||
type: DEPENDENT
|
||||
key: nginx.log.user_status.list[{#HOST_SITE}}]
|
||||
value_type: TEXT
|
||||
preprocessing:
|
||||
- type: JAVASCRIPT
|
||||
parameters:
|
||||
- "// Versão compatível com JavaScript antigo (ES5) - Saída em Texto Puro\n\
|
||||
\ // Usamos um objeto para garantir que cada usuário seja único.\n\
|
||||
\ var uniqueUsers = {};\n\n var remoteUserRegex = /\"remote_user\"\
|
||||
:\"([a-zA-Z0-9._-]+)\"/g;\n var cookieUserRegex = /nc_username=([a-zA-Z0-9._-]+);/g;\n\
|
||||
\ var urlUserRegex = /\\/remote\\.php\\/dav\\/files\\/([a-zA-Z0-9._-]+)\\\
|
||||
//g;\n\n var lines = value.split('\\n');\n\n for (var i = 0; i <\
|
||||
\ lines.length; i++) {\n var line = lines[i];\n var match;\n\
|
||||
\n // Função auxiliar para adicionar usuários ao nosso objeto de\
|
||||
\ unicidade\n function findAndAdd(regex) {\n while ((match\
|
||||
\ = regex.exec(line)) !== null) {\n if (match[1] && match[1].length\
|
||||
\ > 0) {\n // Adiciona o usuário completo como uma\
|
||||
\ chave do objeto.\n uniqueUsers[match[1]] = true;\n\
|
||||
\ }\n }\n }\n \n findAndAdd(remoteUserRegex);\n\
|
||||
\ findAndAdd(cookieUserRegex);\n findAndAdd(urlUserRegex);\n\
|
||||
\ }\n\n // Pega todas as chaves do objeto para formar o array final\
|
||||
\ de usuários únicos.\n var userArray = Object.keys(uniqueUsers);\n\
|
||||
\n // --- LINHA ALTERADA ---\n // Une todos os elementos do array\
|
||||
\ em uma única string,\n // separando cada um com um caractere de quebra\
|
||||
\ de linha ('\\n').\n return userArray.join('\\n');\n"
|
||||
master_item:
|
||||
key: log[/var/log/nginx/{#HOST_SITE}.access.log]
|
||||
tags:
|
||||
- tag: Insight
|
||||
value: performance
|
||||
- name: 'Nginx: Requests Excelentes por minuto {#HOST_SITE}'
|
||||
type: CALCULATED
|
||||
key: nginx.requests.excellent.count.1m.[{#HOST_SITE}]
|
||||
units: reqs/min
|
||||
params: "last(//nginx.request_time.count.0-20ms.1m.[{#HOST_SITE}]) + \nlast(//nginx.request_time.count.21-50ms.1m.[{#HOST_SITE}])\
|
||||
\ + \nlast(//nginx.request_time.count.51-100ms.1m.[{#HOST_SITE}]) + \nlast(//nginx.request_time.count.101-200ms.1m.[{#HOST_SITE}])\n"
|
||||
tags:
|
||||
- tag: Insight
|
||||
value: cache
|
||||
- tag: Insight
|
||||
value: performance
|
||||
- name: 'Insight: Requisição nos Ultimos 5 Minuto em {#HOST_SITE}'
|
||||
type: CALCULATED
|
||||
key: nginx.requests.per_5minute[{#HOST_SITE}]
|
||||
delay: 4m
|
||||
units: requests
|
||||
params: count(//log[/var/log/nginx/{#HOST_SITE}.access.log],5m)
|
||||
tags:
|
||||
- tag: Insight
|
||||
value: carga
|
||||
- name: 'Insight: Requisição nos Ultimos 15 Minuto em {#HOST_SITE}'
|
||||
type: CALCULATED
|
||||
key: nginx.requests.per_15minute[{#HOST_SITE}]
|
||||
delay: 14m
|
||||
units: requests
|
||||
params: count(//log[/var/log/nginx/{#HOST_SITE}.access.log],15m)
|
||||
tags:
|
||||
- tag: Insight
|
||||
value: carga
|
||||
- name: 'Insight: Requisição nos Ultimos 24 horas em {#HOST_SITE}'
|
||||
type: CALCULATED
|
||||
key: nginx.requests.per_24h[{#HOST_SITE}]
|
||||
delay: 1h
|
||||
units: requests
|
||||
params: count(//log[/var/log/nginx/{#HOST_SITE}.access.log],24h)
|
||||
tags:
|
||||
- tag: Insight
|
||||
value: carga
|
||||
- name: 'Insight: Requisição no Ultimo 1 Minuto em {#HOST_SITE}'
|
||||
type: CALCULATED
|
||||
key: nginx.requests.per_minute[{#HOST_SITE}]
|
||||
units: requests
|
||||
params: count(//log[/var/log/nginx/{#HOST_SITE}.access.log],1m)
|
||||
tags:
|
||||
- tag: Insight
|
||||
value: carga
|
||||
- name: 'Insight: Média de Tempo de Resposta (1m) {#HOST_SITE}'
|
||||
type: CALCULATED
|
||||
key: nginx.request_time.avg.1m.[{#HOST_SITE}]
|
||||
value_type: FLOAT
|
||||
units: ms
|
||||
params: avg(//nginx.request_time.[{#HOST_SITE}],1m)
|
||||
tags:
|
||||
- tag: Insight
|
||||
value: carga
|
||||
- name: 'Insight: Média de Tempo de Resposta (5m) {#HOST_SITE}'
|
||||
type: CALCULATED
|
||||
key: nginx.request_time.avg.5m.[{#HOST_SITE}]
|
||||
delay: 4m
|
||||
value_type: FLOAT
|
||||
units: ms
|
||||
params: avg(//nginx.request_time.[{#HOST_SITE}],5m)
|
||||
tags:
|
||||
- tag: Insight
|
||||
value: carga
|
||||
- name: 'Insight: Média de Tempo de Resposta (15m) {#HOST_SITE}'
|
||||
type: CALCULATED
|
||||
key: nginx.request_time.avg.15m.[{#HOST_SITE}]
|
||||
value_type: FLOAT
|
||||
units: ms
|
||||
params: avg(//nginx.request_time.[{#HOST_SITE}],15m)
|
||||
tags:
|
||||
- tag: Insight
|
||||
value: carga
|
||||
- name: 'Nginx: RTime Flag (0-20ms) {#HOST_SITE}'
|
||||
type: DEPENDENT
|
||||
key: nginx.request_time.flag.0-20ms.[{#HOST_SITE}]
|
||||
preprocessing:
|
||||
- type: JAVASCRIPT
|
||||
parameters:
|
||||
- "try {\n // O valor chega em segundos (ex: 0.015), convertemos para\
|
||||
\ milissegundos.\n var value_ms = parseFloat(value) * 1000;\n\n \
|
||||
\ // Verifica se o valor está na faixa de 0 a 20ms.\n if (value_ms\
|
||||
\ >= 0 && value_ms <= 20) {\n return 1;\n }\n\n // Se não\
|
||||
\ estiver na faixa, retorna null para o Zabbix descartar.\n return\
|
||||
\ 0;\n} catch (e) {\n // Se der qualquer erro, também descarta.\n \
|
||||
\ return 0;\n}\n"
|
||||
master_item:
|
||||
key: nginx.request_time.[{#HOST_SITE}]
|
||||
tags:
|
||||
- tag: Insight
|
||||
value: cache
|
||||
- tag: Insight
|
||||
value: performance
|
||||
- name: 'Nginx: RTime Flag (21-50ms) {#HOST_SITE}'
|
||||
type: DEPENDENT
|
||||
key: nginx.request_time.flag.21-50ms.[{#HOST_SITE}]
|
||||
preprocessing:
|
||||
- type: JAVASCRIPT
|
||||
parameters:
|
||||
- "try {\n // O valor chega em segundos (ex: 0.015), convertemos para\
|
||||
\ milissegundos.\n var value_ms = parseFloat(value) * 1000;\n\n \
|
||||
\ // Verifica se o valor está na faixa de 0 a 20ms.\n if (value_ms\
|
||||
\ >= 21 && value_ms <= 50) {\n return 1;\n }\n\n // Se não\
|
||||
\ estiver na faixa, retorna null para o Zabbix descartar.\n return\
|
||||
\ 0;\n} catch (e) {\n // Se der qualquer erro, também descarta.\n \
|
||||
\ return 0;\n}\n"
|
||||
master_item:
|
||||
key: nginx.request_time.[{#HOST_SITE}]
|
||||
tags:
|
||||
- tag: Insight
|
||||
value: cache
|
||||
- tag: Insight
|
||||
value: performance
|
||||
- name: 'Nginx: RTime Flag (51-100ms) {#HOST_SITE}'
|
||||
type: DEPENDENT
|
||||
key: nginx.request_time.flag.51-100ms.[{#HOST_SITE}]
|
||||
preprocessing:
|
||||
- type: JAVASCRIPT
|
||||
parameters:
|
||||
- "try {\n // O valor chega em segundos (ex: 0.015), convertemos para\
|
||||
\ milissegundos.\n var value_ms = parseFloat(value) * 1000;\n\n \
|
||||
\ // Verifica se o valor está na faixa de 0 a 20ms.\n if (value_ms\
|
||||
\ >= 51 && value_ms <= 100) {\n return 1;\n }\n\n // Se não\
|
||||
\ estiver na faixa, retorna null para o Zabbix descartar.\n return\
|
||||
\ 0;\n} catch (e) {\n // Se der qualquer erro, também descarta.\n \
|
||||
\ return 0;\n}\n"
|
||||
master_item:
|
||||
key: nginx.request_time.[{#HOST_SITE}]
|
||||
tags:
|
||||
- tag: Insight
|
||||
value: cache
|
||||
- tag: Insight
|
||||
value: performance
|
||||
- name: 'Nginx: RTime Flag (201-300ms) {#HOST_SITE}'
|
||||
type: DEPENDENT
|
||||
key: nginx.request_time.flag.201-300ms.[{#HOST_SITE}]
|
||||
preprocessing:
|
||||
- type: JAVASCRIPT
|
||||
parameters:
|
||||
- "try {\n // O valor chega em segundos (ex: 0.015), convertemos para\
|
||||
\ milissegundos.\n var value_ms = parseFloat(value) * 1000;\n\n \
|
||||
\ // Verifica se o valor está na faixa de 0 a 20ms.\n if (value_ms\
|
||||
\ >= 201 && value_ms <= 300) {\n return 1;\n }\n\n // Se\
|
||||
\ não estiver na faixa, retorna null para o Zabbix descartar.\n return\
|
||||
\ 0;\n} catch (e) {\n // Se der qualquer erro, também descarta.\n \
|
||||
\ return 0;\n}\n"
|
||||
master_item:
|
||||
key: nginx.request_time.[{#HOST_SITE}]
|
||||
tags:
|
||||
- tag: Insight
|
||||
value: cache
|
||||
- tag: Insight
|
||||
value: performance
|
||||
- name: 'Nginx: RTime Flag (301-400ms) {#HOST_SITE}'
|
||||
type: DEPENDENT
|
||||
key: nginx.request_time.flag.301-400ms.[{#HOST_SITE}]
|
||||
preprocessing:
|
||||
- type: JAVASCRIPT
|
||||
parameters:
|
||||
- "try {\n // O valor chega em segundos (ex: 0.015), convertemos para\
|
||||
\ milissegundos.\n var value_ms = parseFloat(value) * 1000;\n\n \
|
||||
\ // Verifica se o valor está na faixa de 0 a 20ms.\n if (value_ms\
|
||||
\ >= 301 && value_ms <= 400) {\n return 1;\n }\n\n // Se\
|
||||
\ não estiver na faixa, retorna null para o Zabbix descartar.\n return\
|
||||
\ 0;\n} catch (e) {\n // Se der qualquer erro, também descarta.\n \
|
||||
\ return 0;\n}\n"
|
||||
master_item:
|
||||
key: nginx.request_time.[{#HOST_SITE}]
|
||||
tags:
|
||||
- tag: Insight
|
||||
value: cache
|
||||
- tag: Insight
|
||||
value: performance
|
||||
- name: 'Nginx: RTime Flag (401-500ms) {#HOST_SITE}'
|
||||
type: DEPENDENT
|
||||
key: nginx.request_time.flag.401-500ms.[{#HOST_SITE}]
|
||||
preprocessing:
|
||||
- type: JAVASCRIPT
|
||||
parameters:
|
||||
- "try {\n // O valor chega em segundos (ex: 0.015), convertemos para\
|
||||
\ milissegundos.\n var value_ms = parseFloat(value) * 1000;\n\n \
|
||||
\ // Verifica se o valor está na faixa de 0 a 20ms.\n if (value_ms\
|
||||
\ >= 401 && value_ms <= 500) {\n return 1;\n }\n\n // Se\
|
||||
\ não estiver na faixa, retorna null para o Zabbix descartar.\n return\
|
||||
\ 0;\n} catch (e) {\n // Se der qualquer erro, também descarta.\n \
|
||||
\ return 0;\n}\n"
|
||||
master_item:
|
||||
key: nginx.request_time.[{#HOST_SITE}]
|
||||
tags:
|
||||
- tag: Insight
|
||||
value: cache
|
||||
- tag: Insight
|
||||
value: performance
|
||||
- name: 'Nginx: RTime Flag (501-600ms) {#HOST_SITE}'
|
||||
type: DEPENDENT
|
||||
key: nginx.request_time.flag.501-600ms.[{#HOST_SITE}]
|
||||
preprocessing:
|
||||
- type: JAVASCRIPT
|
||||
parameters:
|
||||
- "try {\n // O valor chega em segundos (ex: 0.015), convertemos para\
|
||||
\ milissegundos.\n var value_ms = parseFloat(value) * 1000;\n\n \
|
||||
\ // Verifica se o valor está na faixa de 0 a 20ms.\n if (value_ms\
|
||||
\ >= 501 && value_ms <= 600) {\n return 1;\n }\n\n // Se\
|
||||
\ não estiver na faixa, retorna null para o Zabbix descartar.\n return\
|
||||
\ 0;\n} catch (e) {\n // Se der qualquer erro, também descarta.\n \
|
||||
\ return 0;\n}\n"
|
||||
master_item:
|
||||
key: nginx.request_time.[{#HOST_SITE}]
|
||||
tags:
|
||||
- tag: Insight
|
||||
value: cache
|
||||
- tag: Insight
|
||||
value: performance
|
||||
- name: 'Nginx: RTime Flag (601-700ms) {#HOST_SITE}'
|
||||
type: DEPENDENT
|
||||
key: nginx.request_time.flag.601-700ms.[{#HOST_SITE}]
|
||||
preprocessing:
|
||||
- type: JAVASCRIPT
|
||||
parameters:
|
||||
- "try {\n // O valor chega em segundos (ex: 0.015), convertemos para\
|
||||
\ milissegundos.\n var value_ms = parseFloat(value) * 1000;\n\n \
|
||||
\ // Verifica se o valor está na faixa de 0 a 20ms.\n if (value_ms\
|
||||
\ >= 601 && value_ms <= 700) {\n return 1;\n }\n\n // Se\
|
||||
\ não estiver na faixa, retorna null para o Zabbix descartar.\n return\
|
||||
\ 0;\n} catch (e) {\n // Se der qualquer erro, também descarta.\n \
|
||||
\ return 0;\n}\n"
|
||||
master_item:
|
||||
key: nginx.request_time.[{#HOST_SITE}]
|
||||
tags:
|
||||
- tag: Insight
|
||||
value: cache
|
||||
- tag: Insight
|
||||
value: performance
|
||||
- name: 'Nginx: RTime Flag (701-800ms) {#HOST_SITE}'
|
||||
type: DEPENDENT
|
||||
key: nginx.request_time.flag.701-800ms.[{#HOST_SITE}]
|
||||
preprocessing:
|
||||
- type: JAVASCRIPT
|
||||
parameters:
|
||||
- "try {\n // O valor chega em segundos (ex: 0.015), convertemos para\
|
||||
\ milissegundos.\n var value_ms = parseFloat(value) * 1000;\n\n \
|
||||
\ // Verifica se o valor está na faixa de 0 a 20ms.\n if (value_ms\
|
||||
\ >= 701 && value_ms <= 800) {\n return 1;\n }\n\n // Se\
|
||||
\ não estiver na faixa, retorna null para o Zabbix descartar.\n return\
|
||||
\ 0;\n} catch (e) {\n // Se der qualquer erro, também descarta.\n \
|
||||
\ return 0;\n}\n"
|
||||
master_item:
|
||||
key: nginx.request_time.[{#HOST_SITE}]
|
||||
tags:
|
||||
- tag: Insight
|
||||
value: cache
|
||||
- tag: Insight
|
||||
value: performance
|
||||
- name: 'Nginx: RTime Flag (801-900ms) {#HOST_SITE}'
|
||||
type: DEPENDENT
|
||||
key: nginx.request_time.flag.801-900ms.[{#HOST_SITE}]
|
||||
preprocessing:
|
||||
- type: JAVASCRIPT
|
||||
parameters:
|
||||
- "try {\n // O valor chega em segundos (ex: 0.015), convertemos para\
|
||||
\ milissegundos.\n var value_ms = parseFloat(value) * 1000;\n\n \
|
||||
\ // Verifica se o valor está na faixa de 0 a 20ms.\n if (value_ms\
|
||||
\ >= 801 && value_ms <= 900) {\n return 1;\n }\n\n // Se\
|
||||
\ não estiver na faixa, retorna null para o Zabbix descartar.\n return\
|
||||
\ 0;\n} catch (e) {\n // Se der qualquer erro, também descarta.\n \
|
||||
\ return 0;\n}\n"
|
||||
master_item:
|
||||
key: nginx.request_time.[{#HOST_SITE}]
|
||||
tags:
|
||||
- tag: Insight
|
||||
value: cache
|
||||
- tag: Insight
|
||||
value: performance
|
||||
- name: 'Nginx: RTime Flag (1001-2000ms) {#HOST_SITE}'
|
||||
type: DEPENDENT
|
||||
key: nginx.request_time.flag.1001-2000ms.[{#HOST_SITE}]
|
||||
preprocessing:
|
||||
- type: JAVASCRIPT
|
||||
parameters:
|
||||
- "try {\n // O valor chega em segundos (ex: 0.015), convertemos para\
|
||||
\ milissegundos.\n var value_ms = parseFloat(value) * 1000;\n\n \
|
||||
\ // Verifica se o valor está na faixa de 0 a 20ms.\n if (value_ms\
|
||||
\ >= 1001 && value_ms <= 2000) {\n return 1;\n }\n\n // Se\
|
||||
\ não estiver na faixa, retorna null para o Zabbix descartar.\n return\
|
||||
\ 0;\n} catch (e) {\n // Se der qualquer erro, também descarta.\n \
|
||||
\ return 0;\n}\n"
|
||||
master_item:
|
||||
key: nginx.request_time.[{#HOST_SITE}]
|
||||
tags:
|
||||
- tag: Insight
|
||||
value: cache
|
||||
- tag: Insight
|
||||
value: performance
|
||||
- name: 'Nginx: RTime Flag (>3001ms) {#HOST_SITE}'
|
||||
type: DEPENDENT
|
||||
key: nginx.request_time.flag.3001ms.[{#HOST_SITE}]
|
||||
preprocessing:
|
||||
- type: JAVASCRIPT
|
||||
parameters:
|
||||
- "try {\n // O valor chega em segundos (ex: 0.015), convertemos para\
|
||||
\ milissegundos.\n var value_ms = parseFloat(value) * 1000;\n\n \
|
||||
\ // Verifica se o valor está na faixa de 0 a 20ms.\n if (value_ms\
|
||||
\ >= 3001) {\n return 1;\n }\n\n // Se não estiver na faixa,\
|
||||
\ retorna null para o Zabbix descartar.\n return 0;\n} catch (e) {\n\
|
||||
\ // Se der qualquer erro, também descarta.\n return 0;\n}\n"
|
||||
master_item:
|
||||
key: nginx.request_time.[{#HOST_SITE}]
|
||||
tags:
|
||||
- tag: Insight
|
||||
value: cache
|
||||
- tag: Insight
|
||||
value: performance
|
||||
- name: 'Insight: Tempo de Resposta Total {#HOST_SITE}'
|
||||
type: DEPENDENT
|
||||
key: nginx.request_time.[{#HOST_SITE}]
|
||||
value_type: FLOAT
|
||||
units: s
|
||||
preprocessing:
|
||||
- type: JAVASCRIPT
|
||||
parameters:
|
||||
- "try {\n // A variável 'value' contém a linha de log completa.\n \
|
||||
\ // A regex procura por \"request_time\": e captura o número que vem\
|
||||
\ depois.\n var regex = /\"request_time\":(\\d+\\.?\\d*)/;\n var\
|
||||
\ match = value.match(regex);\n\n // Se encontrar, match[1] conterá\
|
||||
\ apenas o número (ex: \"0.282\").\n if (match && match[1]) {\n \
|
||||
\ return match[1];\n }\n\n // Se não encontrar, descarta o valor.\n\
|
||||
\ return null;\n} catch (e) {\n // Se houver qualquer erro, também\
|
||||
\ descarta.\n return null;\n}\n"
|
||||
master_item:
|
||||
key: log[/var/log/nginx/{#HOST_SITE}.access.log]
|
||||
tags:
|
||||
- tag: Insight
|
||||
value: access log
|
||||
- name: 'Nginx: URI da Requisição {#HOST_SITE}'
|
||||
type: DEPENDENT
|
||||
key: nginx.request_uri.[{#HOST_SITE}]
|
||||
value_type: TEXT
|
||||
preprocessing:
|
||||
- type: JAVASCRIPT
|
||||
parameters:
|
||||
- "try {\n var regex = /\"request_uri\":\"([^\"]+)\"/;\n var match\
|
||||
\ = value.match(regex);\n if (match && match[1]) {\n return\
|
||||
\ match[1];\n }\n return null;\n} catch (e) {\n return null;\n\
|
||||
}\n"
|
||||
master_item:
|
||||
key: log[/var/log/nginx/{#HOST_SITE}.access.log]
|
||||
tags:
|
||||
- tag: Insight
|
||||
value: cache
|
||||
- tag: Insight
|
||||
value: performance
|
||||
graph_prototypes:
|
||||
- name: 'Insight: Cache HITS {#HOST_SITE}'
|
||||
yaxismax: '0'
|
||||
percent_right: '20'
|
||||
ymin_type_1: FIXED
|
||||
graph_items:
|
||||
- color: 199C0D
|
||||
calc_fnc: ALL
|
||||
item:
|
||||
host: srvproxy001
|
||||
key: nginx.cache.hits.5m.[{#HOST_SITE}]
|
||||
- sortorder: '1'
|
||||
color: F63100
|
||||
calc_fnc: ALL
|
||||
item:
|
||||
host: srvproxy001
|
||||
key: nginx.cache.hits.15m.[{#HOST_SITE}]
|
||||
- sortorder: '2'
|
||||
color: 2774A4
|
||||
calc_fnc: ALL
|
||||
item:
|
||||
host: srvproxy001
|
||||
key: nginx.cache.hits.24h.[{#HOST_SITE}]
|
||||
- sortorder: '3'
|
||||
color: F7941D
|
||||
calc_fnc: ALL
|
||||
item:
|
||||
host: srvproxy001
|
||||
key: nginx.cache.hits.1m.[{#HOST_SITE}]
|
||||
- name: 'Insight: Cache HIT vs MISS {#HOST_SITE}'
|
||||
show_work_period: 'NO'
|
||||
show_triggers: 'NO'
|
||||
type: PIE
|
||||
graph_items:
|
||||
- color: F63100
|
||||
item:
|
||||
host: srvproxy001
|
||||
key: nginx.cache.miss.ratio.1m.[{#HOST_SITE}]
|
||||
- sortorder: '1'
|
||||
color: 199C0D
|
||||
item:
|
||||
host: srvproxy001
|
||||
key: nginx.cache.hit.ratio.1m.[{#HOST_SITE}]
|
||||
- name: 'Insight: Cache MISS {#HOST_SITE}'
|
||||
yaxismax: '0'
|
||||
percent_right: '20'
|
||||
ymin_type_1: FIXED
|
||||
graph_items:
|
||||
- color: 199C0D
|
||||
calc_fnc: ALL
|
||||
item:
|
||||
host: srvproxy001
|
||||
key: nginx.cache.miss.1m.[{#HOST_SITE}]
|
||||
- sortorder: '1'
|
||||
color: F63100
|
||||
calc_fnc: ALL
|
||||
item:
|
||||
host: srvproxy001
|
||||
key: nginx.cache.miss.5m.[{#HOST_SITE}]
|
||||
- sortorder: '2'
|
||||
color: 2774A4
|
||||
calc_fnc: ALL
|
||||
item:
|
||||
host: srvproxy001
|
||||
key: nginx.cache.miss.15m.[{#HOST_SITE}]
|
||||
- sortorder: '3'
|
||||
color: F7941D
|
||||
calc_fnc: ALL
|
||||
item:
|
||||
host: srvproxy001
|
||||
key: nginx.cache.miss.24h.[{#HOST_SITE}]
|
||||
- name: 'Insight: Requisições {#HOST_SITE}'
|
||||
yaxismax: '0'
|
||||
ymin_type_1: FIXED
|
||||
graph_items:
|
||||
- color: F63100
|
||||
yaxisside: RIGHT
|
||||
calc_fnc: ALL
|
||||
item:
|
||||
host: srvproxy001
|
||||
key: nginx.requests.per_minute[{#HOST_SITE}]
|
||||
- sortorder: '1'
|
||||
color: 199C0D
|
||||
calc_fnc: ALL
|
||||
item:
|
||||
host: srvproxy001
|
||||
key: nginx.requests.per_5minute[{#HOST_SITE}]
|
||||
- sortorder: '2'
|
||||
color: 2774A4
|
||||
calc_fnc: ALL
|
||||
item:
|
||||
host: srvproxy001
|
||||
key: nginx.requests.per_15minute[{#HOST_SITE}]
|
||||
- sortorder: '3'
|
||||
color: F7941D
|
||||
calc_fnc: ALL
|
||||
item:
|
||||
host: srvproxy001
|
||||
key: nginx.requests.per_24h[{#HOST_SITE}]
|
||||
- name: 'Insight: Saúde do Site {#HOST_SITE}'
|
||||
show_work_period: 'NO'
|
||||
graph_items:
|
||||
- color: 199C0D
|
||||
calc_fnc: ALL
|
||||
item:
|
||||
host: srvproxy001
|
||||
key: net.tcp.service[http,"{$NGINX.STUB_STATUS.HOST}","{$NGINX.STUB_STATUS.PORT}"]
|
||||
- sortorder: '1'
|
||||
color: F63100
|
||||
calc_fnc: ALL
|
||||
item:
|
||||
host: srvproxy001
|
||||
key: nginx.cache.hit.ratio.1m.[{#HOST_SITE}]
|
||||
- sortorder: '2'
|
||||
color: F7941D
|
||||
calc_fnc: ALL
|
||||
item:
|
||||
host: srvproxy001
|
||||
key: nginx.request_time.avg.1m.[{#HOST_SITE}]
|
||||
- name: 'Insight: Tempo de Resposta vs Requisições {#HOST_SITE}'
|
||||
ymin_type_1: FIXED
|
||||
graph_items:
|
||||
- sortorder: '1'
|
||||
color: F63100
|
||||
yaxisside: RIGHT
|
||||
calc_fnc: ALL
|
||||
item:
|
||||
host: srvproxy001
|
||||
key: nginx.requests.per_minute[{#HOST_SITE}]
|
||||
- sortorder: '2'
|
||||
drawtype: FILLED_REGION
|
||||
color: 199C0D
|
||||
calc_fnc: ALL
|
||||
item:
|
||||
host: srvproxy001
|
||||
key: nginx.request_time.[{#HOST_SITE}]
|
||||
- name: 'Insight: Tempos de Resposta {#HOST_SITE}'
|
||||
percent_right: '20'
|
||||
ymin_type_1: FIXED
|
||||
graph_items:
|
||||
- color: 199C0D
|
||||
calc_fnc: ALL
|
||||
item:
|
||||
host: srvproxy001
|
||||
key: nginx.request_time.avg.1m.[{#HOST_SITE}]
|
||||
- sortorder: '1'
|
||||
color: F63100
|
||||
calc_fnc: ALL
|
||||
item:
|
||||
host: srvproxy001
|
||||
key: nginx.request_time.avg.5m.[{#HOST_SITE}]
|
||||
- sortorder: '2'
|
||||
color: 2774A4
|
||||
calc_fnc: ALL
|
||||
item:
|
||||
host: srvproxy001
|
||||
key: nginx.request_time.avg.15m.[{#HOST_SITE}]
|
||||
preprocessing:
|
||||
- type: JAVASCRIPT
|
||||
parameters:
|
||||
- "// A variável 'value' é a string completa do UserParameter, contendo caminhos\n\
|
||||
// separados por vírgula, espaço e/ou quebra de linha.\n // A Regex /[\\\
|
||||
s,]+/ divide a string em:\n // - Vírgulas (,)\n // - Espaços (incluindo\
|
||||
\ múltiplos)\n // - Quebras de linha (\\n, \\r)\n // O filter(Boolean)\
|
||||
\ remove quaisquer entradas vazias que o split possa gerar.\n var full_paths\
|
||||
\ = value.trim().split(/[\\s,]+/).filter(Boolean);\n \n var lld_data\
|
||||
\ = [];\n \n // Regex para extrair o nome do site:\n // ^ -> Início\
|
||||
\ do item (após o split)\n // (.+) -> Captura o nome do site (o que for\
|
||||
\ que esteja lá)\n var regex = /^\\/var\\/log\\/nginx\\/(.+)\\.access\\\
|
||||
.log$/;\n \n // Itera sobre todos os caminhos.\n for (var i = 0;\
|
||||
\ i < full_paths.length; i++) {\n var path = full_paths[i];\n \
|
||||
\ \n // Aplica a regex em cada item.\n var match = path.match(regex);\n\
|
||||
\ \n // match[1] contém o nome do site capturado em (.+).\n\
|
||||
\ if (match && match[1]) { \n lld_data.push({\n \
|
||||
\ \"{#HOST_SITE}\": match[1]\n });\n }\n }\n\
|
||||
\ \n // Retorna o JSON LLD final.\n return JSON.stringify({ \"\
|
||||
data\": lld_data });\n"
|
||||
|
|
@ -1,75 +0,0 @@
|
|||
# Protocolo de Execução AI: Nginx Intelligence Suite (Clean Version)
|
||||
**Destino:** `templates_gold/nginx_agent/`
|
||||
**Objetivo:** Instruções diretivas para geração de código Zabbix 7.0 YAML.
|
||||
|
||||
---
|
||||
|
||||
## 🏗️ 1. Definição de Artefatos
|
||||
|
||||
O Agente deve gerar exatamente **três arquivos** com as especificações abaixo.
|
||||
|
||||
### 1.1 `template_nginx_manager_gold.yaml`
|
||||
**Função:** Monitoramento do Serviço Global (Pad), Discovery de Sites e Auditoria de Config.
|
||||
**Grupo:** `Templates/Applications`
|
||||
|
||||
| Item Key | Tipo | Trigger/Lógica |
|
||||
| :--- | :--- | :--- |
|
||||
| `nginx.workers.utilization` | Calculated | `(Active Conn / (Workers * Limit)) * 100`. Alerta > 80%. |
|
||||
| `proc.num[nginx,files_open]` | Agent | Trigger se próximo do `ulimit -n` do sistema. |
|
||||
| `nginx.uptime` | Agent | Trigger "Reload Storm" se uptime resetar > 3x/hora. |
|
||||
| `proc.cpu.util[nginx,user/system]` | Agent | Monitorar overhead de sistema (Context Switch). |
|
||||
| `nginx.requests.400` | Simple Check | Spike Detection (Indício de Fuzzing/Exploit). |
|
||||
| `vfs.file.cksum[/etc/nginx/nginx.conf]` | Agent | Trigger "Global Config Changed". |
|
||||
| `system.run[nginx -t 2>&1]` | Agent | Trigger "Configuração Inválida" (Retorno != successful). |
|
||||
| **Discovery Rules:** | | |
|
||||
| `nginx.site.discovery` | Script/UserParam | Lista arquivos em `/etc/nginx/sites-enabled/`. Cria Hosts. |
|
||||
| `nginx.compliance.audit` | `vfs.file.regexp` | Valida regras do `nginx_best_practices.md` em cada .conf. |
|
||||
|
||||
### 1.2 `template_nginx_site_satellite_gold.yaml`
|
||||
**Função:** Monitoramento detalhado por Site (Virtual Host). Vinculado via Discovery do Manager.
|
||||
**Grupo:** `Templates/Nginx Satellites`
|
||||
|
||||
#### A. Log Analytics (Passivo)
|
||||
**Item Mestre:** `log[{#SITE_LOG}]` (Type: Zabbix Active, Format: JSON).
|
||||
|
||||
| Feature | Métricas Derivadas (Dependent Items) |
|
||||
| :--- | :--- |
|
||||
| **Performance** | `request_time`, `upstream_response_time`, `hits`, `bytes_sent`. |
|
||||
| **Marketing** | Conversão Funil (`{$MATCH_START}` vs `{$MATCH_GOAL}`), Top Browsers. |
|
||||
| **Segurança** | Hits em Honeytokens (`/admin.bak`), WAF Blocks, Data Leak (>Avg Bytes). |
|
||||
| **Forensics** | Cache Status (HIT/MISS), GeoIP. |
|
||||
|
||||
#### B. Web Scenarios (Ativo)
|
||||
**Conceito:** O Zabbix Agent (ou Server) acessa a URL externamente.
|
||||
|
||||
1. **Health Check:** GET `http://{#SITE_NAME}/`. Espera CODE=200 e String="html".
|
||||
2. **Security Probe:** GET `http://{#SITE_NAME}/.env`. Espera CODE=403/404. Se 200 => CRITICAL.
|
||||
|
||||
#### C. Route Discovery (Crawler)
|
||||
**Regra LLD:** `nginx.route.discovery[{#SITE_CONF}]`.
|
||||
**Lógica:** Regex que extrai `location /path {` do arquivo de config.
|
||||
**Protótipos:**
|
||||
1. **Log Check:** % Erro 5xx na rota específica.
|
||||
2. **Web Check:** `web.page.get` na rota para validar disponibilidade.
|
||||
|
||||
### 1.3 `deploy_instructions.md`
|
||||
**Conteúdo Obrigatório:**
|
||||
1. **Log Format:** O snippet exato do `log_format structured_json` para colocar no `nginx.conf`.
|
||||
2. **UserParameters:** Os comandos bash para descoberta de sites e rotas.
|
||||
3. **Permissões:** Comandos `chmod/chown` para garantir leitura dos logs (`adm` group).
|
||||
4. **Macros:** Lista de macros obrigatórias (`{$NGINX.LOG.PATH}`, etc).
|
||||
|
||||
---
|
||||
|
||||
## 🧪 2. Validação & Gold Standard
|
||||
|
||||
O código gerado **DEVE** obedecer:
|
||||
1. **Nomes em PT-BR:** "Latência do Backend" (Não "Upstream Time").
|
||||
2. **Descrições Ricas:** Explicar O QUE é e O QUE FAZER na descrição da Trigger.
|
||||
3. **Tags:** Todo item deve ter Tags (`Component: Security`, `Layer: App`, etc).
|
||||
4. **UUIDs:** Gerar UUIDs v4 estáticos para evitar duplicação na importação.
|
||||
5. **Sem Scripts Externos desnecessários:** Usar funcionalidades nativas onde possível.
|
||||
|
||||
---
|
||||
|
||||
**Status:** Pronto para Execução.
|
||||
|
|
@ -1,138 +0,0 @@
|
|||
import yaml
|
||||
import uuid
|
||||
import sys
|
||||
|
||||
# Schema based on the user's 'detailed_proxy' log_format
|
||||
LOG_FIELDS = [
|
||||
# Group, Key, Type, Description, JSONPath
|
||||
("Timestamps", "timestamp", "TEXT", "Time ISO8601", "$.@timestamp"),
|
||||
("Timestamps", "request_id", "TEXT", "Unique Request ID", "$.request_id"),
|
||||
("Network", "remote_addr", "TEXT", "Client IP", "$.remote_addr"),
|
||||
("Network", "real_ip", "TEXT", "Real IP (X-Forwarded-For)", "$.real_ip"),
|
||||
("Network", "remote_user", "TEXT", "Authenticated User", "$.remote_user"),
|
||||
|
||||
("Request", "request_method", "TEXT", "HTTP Method", "$.request_method"),
|
||||
("Request", "host_header", "TEXT", "Host Header", "$.host_header"),
|
||||
("Request", "uri", "TEXT", "URI", "$.uri"),
|
||||
("Request", "request_length", "UNSIGNED", "Request Length (bytes)", "$.request_length"),
|
||||
|
||||
("Response", "status", "UNSIGNED", "HTTP Status Code", "$.status"),
|
||||
("Response", "body_bytes_sent", "UNSIGNED", "Body Bytes Sent", "$.body_bytes_sent"),
|
||||
("Response", "bytes_sent", "UNSIGNED", "Total Bytes Sent", "$.bytes_sent"),
|
||||
|
||||
("Performance", "request_time", "FLOAT", "Request Time (Total)", "$.request_time"),
|
||||
("Performance", "upstream_connect_time", "FLOAT", "Upstream Connect Time", "$.upstream_connect_time"),
|
||||
("Performance", "upstream_header_time", "FLOAT", "Upstream Header Time", "$.upstream_header_time"),
|
||||
("Performance", "upstream_response_time", "FLOAT", "Upstream Response Time", "$.upstream_response_time"),
|
||||
("Performance", "upstream_cache_status", "TEXT", "Cache Status", "$.upstream_cache_status"),
|
||||
|
||||
("GeoIP", "geoip_country_code", "TEXT", "GeoIP Country Code", "$.geoip_country_code"),
|
||||
("GeoIP", "geoip_city_name", "TEXT", "GeoIP City Name", "$.geoip_city_name"),
|
||||
("GeoIP", "geoip_isp", "TEXT", "GeoIP ISP", "$.geoip_isp"),
|
||||
|
||||
("Security", "is_bad_bot", "TEXT", "Bad Bot Flag", "$.is_bad_bot"),
|
||||
("Security", "block_request", "TEXT", "WAF Block Flag", "$.block_request"),
|
||||
("Security", "ssl_protocol", "TEXT", "SSL Protocol", "$.ssl_protocol"),
|
||||
("Security", "ssl_cipher", "TEXT", "SSL Cipher", "$.ssl_cipher"),
|
||||
]
|
||||
|
||||
def generate_satellite_template(output_file):
|
||||
template_uuid = "sat00000-0000-0000-0000-000000000001" # Fixed UUID for consistency
|
||||
group_uuid = "7df96b18c230490a9a0a9e2307226338" # Templates/Applications group
|
||||
|
||||
items = []
|
||||
|
||||
# MASTER ITEM
|
||||
# We assume the host is the site itself, so we might need a macro for the log path or
|
||||
# assume a standard path based on the host name.
|
||||
# The user said: "encontrar todos os arquivos .conf... e usar este nome para criar um novo host"
|
||||
# And "o caminho sempre vai ser o padrao".
|
||||
# We will use {$NGINX.SITE.LOG} macro which will be populated by the Discovery rule on the Manager level.
|
||||
|
||||
master_item_uuid = str(uuid.uuid4())
|
||||
master_item = {
|
||||
'uuid': master_item_uuid,
|
||||
'name': 'Access Log Stream',
|
||||
'type': 'ZABBIX_ACTIVE',
|
||||
'key': 'log[{$NGINX.SITE.LOG}]',
|
||||
'delay': '1s',
|
||||
'value_type': 'LOG',
|
||||
'history': '7d',
|
||||
'tags': [{'tag': 'component', 'value': 'log_stream'}]
|
||||
}
|
||||
items.append(master_item)
|
||||
|
||||
# DEPENDENT ITEMS
|
||||
for group, key_suffix, value_type, desc, path in LOG_FIELDS:
|
||||
# Some items might be strings in JSON but we want Numbers in Zabbix
|
||||
# If value_type is FLOAT/UNSIGNED, we should ensure preprocessing handles it correctly.
|
||||
|
||||
# Determine strict type
|
||||
zabbix_type = 'TEXT'
|
||||
if value_type == 'FLOAT':
|
||||
zabbix_type = 'FLOAT'
|
||||
elif value_type == 'UNSIGNED':
|
||||
zabbix_type = 'FLOAT' # Use Float for safety with numbers, standardizing
|
||||
|
||||
item = {
|
||||
'uuid': str(uuid.uuid4()),
|
||||
'name': f'Nginx Site: {desc}',
|
||||
'type': 'DEPENDENT',
|
||||
'key': f'nginx.site.{key_suffix}',
|
||||
'delay': '0',
|
||||
'value_type': zabbix_type,
|
||||
'description': desc,
|
||||
'history': '30d',
|
||||
'preprocessing': [
|
||||
{
|
||||
'type': 'JSONPATH',
|
||||
'parameters': [path],
|
||||
'error_handler': 'DISCARD_VALUE' # Discard if field missing
|
||||
}
|
||||
],
|
||||
'master_item': {'key': master_item['key']},
|
||||
'tags': [{'tag': 'component', 'value': group.lower()}]
|
||||
}
|
||||
items.append(item)
|
||||
|
||||
# Add calculated/special items (Trigger-based)
|
||||
# Example: Cache Hit Ratio calculation is best done in Grafana or via Calculated Item if we have aggregate data.
|
||||
# Since these are log-based, 'DEPENDENT' items are per-line.
|
||||
# To get "Ratio per minute", we need aggregate items (Calculated from Discovery rules on the Manager, OR separate calculated items here).
|
||||
# BUT, dependent items only fire on each log line. You can't calculate "Ratio of last minute" easily from a stream of dependent items without using "Trend/History" functions in Calculated Items.
|
||||
# We will add simple Calculated Items for Stats.
|
||||
|
||||
# 5XX Errors Rate
|
||||
items.append({
|
||||
'uuid': str(uuid.uuid4()),
|
||||
'name': 'Nginx Site: HTTP 5xx Rate',
|
||||
'type': 'CALCULATED',
|
||||
'key': 'nginx.site.status.5xx.rate',
|
||||
'params': 'count(//nginx.site.status, 1m, "ge", 500)',
|
||||
'value_type': 'FLOAT',
|
||||
'units': 'rps',
|
||||
'delay': '1m',
|
||||
'tags': [{'tag': 'component', 'value': 'availability'}]
|
||||
})
|
||||
|
||||
template = {
|
||||
'zabbix_export': {
|
||||
'version': '7.0',
|
||||
'template_groups': [{'uuid': group_uuid, 'name': 'Templates/Applications'}],
|
||||
'templates': [{
|
||||
'uuid': template_uuid,
|
||||
'template': 'Template Nginx Custom Site Analysis',
|
||||
'name': 'Template Nginx Custom Site Analysis',
|
||||
'description': 'Analyzes JSON logs for a specific Nginx site host.',
|
||||
'groups': [{'name': 'Templates/Applications'}],
|
||||
'items': items,
|
||||
}]
|
||||
}
|
||||
}
|
||||
|
||||
with open(output_file, 'w', encoding='utf-8') as f:
|
||||
yaml.dump(template, f, sort_keys=False, allow_unicode=True)
|
||||
print(f"Generated {output_file}")
|
||||
|
||||
if __name__ == "__main__":
|
||||
generate_satellite_template("template_nginx_site_analysis.yaml")
|
||||
|
|
@ -1,316 +0,0 @@
|
|||
# Guia Definitivo de Configuração e Boas Práticas NGINX
|
||||
**Autor:** Gemini (AI Specialist)
|
||||
**Data:** 04 de Janeiro de 2026
|
||||
**Contexto:** Padrões de segurança, performance e manutenção para infraestrutura web.
|
||||
|
||||
---
|
||||
|
||||
## 1. Princípios Fundamentais
|
||||
|
||||
Antes de qualquer configuração, estas são as regras de ouro que devem ser aplicadas a **todos** os arquivos `.conf`.
|
||||
|
||||
### 1.1 Organização e Formatação
|
||||
* **Sem Snippets:** Evite `include snippets/ssl-params.conf;`. Todas as diretivas devem ser declaradas explicitamente no arquivo do site (`/etc/nginx/sites-available/exemplo.conf`). Isso facilita a auditoria e evita que uma alteração global quebre sites específicos.
|
||||
* **Cabeçalho Obrigatório:** Todo arquivo deve começar com comentários explicando o propósito, autor e data da última alteração.
|
||||
* **Indentação:** Use 4 espaços (ou consistência total com tabs). Nunca misture.
|
||||
* **Comentários:** Use comentários para separar blocos lógicos (`# Segurança`, `# Cache`, `# Upstream`).
|
||||
|
||||
### 1.2 Logs e Auditoria
|
||||
* **Isolamento:** Cada site/app deve ter seus próprios logs. Nunca use o `access.log` global.
|
||||
* **Caminho:** `/var/log/nginx/dominio_access.log` e `/var/log/nginx/dominio_error.log`.
|
||||
* **Retenção:** Configure o `logrotate` (sistema operacional) para manter 30 dias de histórico e compactar o dia anterior automaticamente (`delaycompress`).
|
||||
* **Fail2Ban:** As regras do Fail2Ban devem apontar para esses logs exclusivos.
|
||||
|
||||
### 1.3 Segurança (SSL/TLS e Headers)
|
||||
* **Protocolos:** Suporte a TLSv1.2 e TLSv1.3.
|
||||
* **Compatibilidade Apple:** Garantir ciphers que funcionem bem com dispositivos Apple antigos e novos, sem comprometer a segurança.
|
||||
* **HSTS:** Sempre habilitar `Strict-Transport-Security` em produção.
|
||||
* **Ocultação:** `server_tokens off;` para não revelar a versão do NGINX.
|
||||
|
||||
---
|
||||
|
||||
## 2. Configuração Base (Modelo SSL e Headers)
|
||||
|
||||
*Copie e adapte este bloco para dentro de cada `server { ... }` listado nos exemplos abaixo.*
|
||||
|
||||
```nginx
|
||||
# =========================================
|
||||
# CONFIGURAÇÃO SSL/TLS (Diretiva Direta)
|
||||
# =========================================
|
||||
ssl_certificate /caminho/para/certificado/fullchain.pem;
|
||||
ssl_certificate_key /caminho/para/certificado/privkey.pem;
|
||||
|
||||
# Otimização baseada no guia Mozilla/SSLLabs
|
||||
ssl_protocols TLSv1.2 TLSv1.3;
|
||||
ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384;
|
||||
ssl_prefer_server_ciphers off;
|
||||
|
||||
# Performance SSL
|
||||
ssl_session_timeout 1d;
|
||||
ssl_session_cache shared:MozSSL:10m; # Aprox 40k sessões
|
||||
ssl_session_tickets off;
|
||||
|
||||
# OCSP Stapling (Melhora performance e privacidade)
|
||||
ssl_stapling on;
|
||||
ssl_stapling_verify on;
|
||||
resolver 8.8.8.8 1.1.1.1 valid=300s;
|
||||
resolver_timeout 5s;
|
||||
|
||||
# =========================================
|
||||
# HEADERS DE SEGURANÇA (Hardening)
|
||||
# =========================================
|
||||
add_header Strict-Transport-Security "max-age=63072000; includeSubDomains; preload" always;
|
||||
add_header X-Frame-Options SAMEORIGIN always;
|
||||
add_header X-Content-Type-Options nosniff always;
|
||||
add_header X-XSS-Protection "1; mode=block" always;
|
||||
add_header Referrer-Policy no-referrer-when-downgrade always;
|
||||
# Content-Security-Policy (CSP) deve ser ajustada por aplicação
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 3. Exemplos de Configuração por Categoria
|
||||
|
||||
### 3.1 Site Estático HTML
|
||||
Foco: Cache agressivo para assets, compressão Gzip/Brotli.
|
||||
|
||||
```nginx
|
||||
server {
|
||||
listen 443 ssl http2;
|
||||
server_name www.meusiteestatico.com;
|
||||
root /var/www/meusiteestatico;
|
||||
index index.html;
|
||||
|
||||
# Logs Exclusivos
|
||||
access_log /var/log/nginx/meusiteestatico_access.log;
|
||||
error_log /var/log/nginx/meusiteestatico_error.log;
|
||||
|
||||
# [INSERIR AQUI O BLOCO SSL E HEADERS DA SEÇÃO 2]
|
||||
|
||||
# Compressão
|
||||
gzip on;
|
||||
gzip_types text/plain text/css application/json application/javascript text/xml application/xml application/xml+rss text/javascript;
|
||||
|
||||
location / {
|
||||
try_files $uri $uri/ =404;
|
||||
}
|
||||
|
||||
# Cache de Arquivos Estáticos (Longa duração)
|
||||
location ~* \.(jpg|jpeg|png|gif|ico|css|js|svg|woff|woff2|ttf|eot)$ {
|
||||
expires 365d;
|
||||
add_header Cache-Control "public, no-transform";
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 3.2 WordPress / CMS
|
||||
Foco: Processamento PHP (FastCGI), segurança contra acesso direto a arquivos sensíveis.
|
||||
|
||||
```nginx
|
||||
server {
|
||||
listen 443 ssl http2;
|
||||
server_name blog.meusite.com;
|
||||
root /var/www/wordpress;
|
||||
index index.php index.html;
|
||||
|
||||
# Logs Exclusivos
|
||||
access_log /var/log/nginx/wordpress_access.log;
|
||||
error_log /var/log/nginx/wordpress_error.log;
|
||||
|
||||
# [INSERIR AQUI O BLOCO SSL E HEADERS DA SEÇÃO 2]
|
||||
|
||||
# Segurança WP: Bloquear acesso a arquivos ocultos e uploads de scripts
|
||||
location ~ /\. { deny all; }
|
||||
location ~* /(?:uploads|files)/.*\.php$ { deny all; }
|
||||
|
||||
location / {
|
||||
try_files $uri $uri/ /index.php?$args;
|
||||
}
|
||||
|
||||
# Processamento PHP
|
||||
location ~ \.php$ {
|
||||
include fastcgi_params;
|
||||
fastcgi_pass unix:/run/php/php8.2-fpm.sock; # Ajustar versão do PHP
|
||||
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
|
||||
fastcgi_intercept_errors on;
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 3.3 Microsoft Exchange Server (Reverse Proxy)
|
||||
Foco: Headers específicos da MS, timeout alto, suporte a grandes uploads.
|
||||
|
||||
```nginx
|
||||
server {
|
||||
listen 443 ssl http2;
|
||||
server_name mail.empresa.com;
|
||||
|
||||
# Logs Exclusivos
|
||||
access_log /var/log/nginx/exchange_access.log;
|
||||
error_log /var/log/nginx/exchange_error.log;
|
||||
|
||||
# [INSERIR AQUI O BLOCO SSL E HEADERS DA SEÇÃO 2]
|
||||
|
||||
# Ajustes Exchange
|
||||
client_max_body_size 2G;
|
||||
proxy_read_timeout 3600;
|
||||
proxy_http_version 1.1;
|
||||
proxy_request_buffering off; # Importante para RPC over HTTP
|
||||
|
||||
location / {
|
||||
proxy_pass https://ip_do_servidor_exchange;
|
||||
proxy_set_header Host $host;
|
||||
proxy_set_header X-Real-IP $remote_addr;
|
||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||
proxy_set_header X-Forwarded-Proto $scheme;
|
||||
|
||||
# Headers Específicos Exchange
|
||||
proxy_set_header Front-End-Https On;
|
||||
}
|
||||
|
||||
# Redirecionamento raiz para OWA
|
||||
location = / {
|
||||
return 301 https://mail.empresa.com/owa;
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 3.4 Plex Media Server
|
||||
Foco: Websockets, streaming contínuo, evitar buffering do proxy.
|
||||
|
||||
```nginx
|
||||
server {
|
||||
listen 443 ssl http2;
|
||||
server_name plex.meudominio.com;
|
||||
|
||||
# Logs Exclusivos
|
||||
access_log /var/log/nginx/plex_access.log;
|
||||
error_log /var/log/nginx/plex_error.log;
|
||||
|
||||
# [INSERIR AQUI O BLOCO SSL E HEADERS DA SEÇÃO 2]
|
||||
|
||||
# Otimização para Streaming
|
||||
client_max_body_size 100M;
|
||||
proxy_http_version 1.1;
|
||||
proxy_set_header Upgrade $http_upgrade;
|
||||
proxy_set_header Connection "upgrade";
|
||||
|
||||
# Desabilitar buffering para streaming em tempo real
|
||||
proxy_buffering off;
|
||||
|
||||
location / {
|
||||
proxy_pass http://127.0.0.1:32400; # Porta padrão Plex
|
||||
proxy_set_header Host $host;
|
||||
proxy_set_header X-Real-IP $remote_addr;
|
||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||
proxy_set_header X-Forwarded-Proto $scheme;
|
||||
|
||||
# Headers Plex
|
||||
proxy_set_header X-Plex-Client-Identifier $http_x_plex_client_identifier;
|
||||
proxy_set_header X-Plex-Device $http_x_plex_device;
|
||||
proxy_set_header X-Plex-Device-Name $http_x_plex_device_name;
|
||||
proxy_set_header X-Plex-Platform $http_x_plex_platform;
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 3.5 Zammad (Helpdesk)
|
||||
Foco: Websockets (obrigatório para atualizações em tempo real) e Upstream.
|
||||
|
||||
```nginx
|
||||
upstream zammad-railsserver {
|
||||
server 127.0.0.1:3000;
|
||||
}
|
||||
|
||||
upstream zammad-websocket {
|
||||
server 127.0.0.1:6042;
|
||||
}
|
||||
|
||||
server {
|
||||
listen 443 ssl http2;
|
||||
server_name suporte.empresa.com;
|
||||
|
||||
# Logs Exclusivos
|
||||
access_log /var/log/nginx/zammad_access.log;
|
||||
error_log /var/log/nginx/zammad_error.log;
|
||||
|
||||
# [INSERIR AQUI O BLOCO SSL E HEADERS DA SEÇÃO 2]
|
||||
|
||||
root /opt/zammad/public;
|
||||
client_max_body_size 50M;
|
||||
|
||||
location /ws {
|
||||
proxy_pass http://zammad-websocket;
|
||||
proxy_http_version 1.1;
|
||||
proxy_set_header Upgrade $http_upgrade;
|
||||
proxy_set_header Connection "Upgrade";
|
||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||
proxy_set_header X-Forwarded-Proto $scheme;
|
||||
}
|
||||
|
||||
location / {
|
||||
proxy_pass http://zammad-railsserver;
|
||||
proxy_set_header Host $http_host;
|
||||
proxy_set_header X-Forwarded-Proto $scheme;
|
||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 3.6 Zabbix
|
||||
Foco: PHP Frontend, geralmente roda em subdiretório ou raiz.
|
||||
|
||||
```nginx
|
||||
server {
|
||||
listen 443 ssl http2;
|
||||
server_name monitoramento.empresa.com;
|
||||
root /usr/share/zabbix; # Caminho padrão comum no Linux
|
||||
index index.php;
|
||||
|
||||
# Logs Exclusivos
|
||||
access_log /var/log/nginx/zabbix_access.log;
|
||||
error_log /var/log/nginx/zabbix_error.log;
|
||||
|
||||
# [INSERIR AQUI O BLOCO SSL E HEADERS DA SEÇÃO 2]
|
||||
|
||||
location / {
|
||||
try_files $uri $uri/ /index.php?$args;
|
||||
}
|
||||
|
||||
location ~ \.php$ {
|
||||
include fastcgi_params;
|
||||
fastcgi_pass unix:/run/php/php8.2-fpm.sock; # Verificar versão PHP
|
||||
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
|
||||
fastcgi_buffer_size 128k;
|
||||
fastcgi_buffers 4 256k;
|
||||
fastcgi_busy_buffers_size 256k;
|
||||
}
|
||||
|
||||
# Previne acesso a arquivos sensíveis do Zabbix
|
||||
location ~ ^/(conf|app|include|local)/ {
|
||||
deny all;
|
||||
return 404;
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## 4. Validação e Testes Finais
|
||||
Não considere o trabalho concluído apenas ao salvar o arquivo. Siga este ritual:
|
||||
|
||||
1. **Validação de Sintaxe:**
|
||||
```bash
|
||||
nginx -t
|
||||
```
|
||||
2. **Recarregar Serviço (Sem Downtime):**
|
||||
```bash
|
||||
systemctl reload nginx
|
||||
```
|
||||
3. **Checklist de Testes Externos:** Utilize as ferramentas abaixo para validar sua configuração:
|
||||
* **SSL Labs:** Avaliar TLS/SSL e compatibilidade (Busque nota A+).
|
||||
* **CryptCheck:** Segunda opinião focada em ciphers modernos.
|
||||
* **Hardenize:** Diagnóstico de infraestrutura (DNSSEC, HSTS).
|
||||
* **HSTS Preload:** Verifica se o domínio pode ser pré-carregado nos navegadores.
|
||||
* **ImmuniWeb SSL:** Avaliação de compliance (PCI DSS, HIPAA).
|
||||
* **SecurityHeaders:** Verifica CSP, X-Frame-Options, etc.
|
||||
* **Mozilla Observatory:** Nota global de boas práticas web.
|
||||
* **GTmetrix:** Performance e Waterfall.
|
||||
File diff suppressed because it is too large
Load Diff
|
|
@ -1,466 +0,0 @@
|
|||
zabbix_export:
|
||||
version: '7.0'
|
||||
template_groups:
|
||||
- uuid: 7df96b18c230490a9a0a9e2307226338
|
||||
name: Templates/Applications
|
||||
templates:
|
||||
- uuid: sat00000-0000-0000-0000-000000000001
|
||||
template: Template Nginx Custom Site Analysis
|
||||
name: Template Nginx Custom Site Analysis
|
||||
description: Analyzes JSON logs for a specific Nginx site host.
|
||||
groups:
|
||||
- name: Templates/Applications
|
||||
items:
|
||||
- uuid: ab0f217e-2203-44b3-90ea-47b3eeebb80a
|
||||
name: Access Log Stream
|
||||
type: ZABBIX_ACTIVE
|
||||
key: log[{$NGINX.SITE.LOG}]
|
||||
delay: 1s
|
||||
value_type: LOG
|
||||
history: 7d
|
||||
tags:
|
||||
- tag: component
|
||||
value: log_stream
|
||||
- uuid: 6cecf19b-845b-4158-a90f-3c67af72f2fa
|
||||
name: 'Nginx Site: Time ISO8601'
|
||||
type: DEPENDENT
|
||||
key: nginx.site.timestamp
|
||||
delay: '0'
|
||||
value_type: TEXT
|
||||
description: Time ISO8601
|
||||
history: 30d
|
||||
preprocessing:
|
||||
- type: JSONPATH
|
||||
parameters:
|
||||
- $.@timestamp
|
||||
error_handler: DISCARD_VALUE
|
||||
master_item:
|
||||
key: log[{$NGINX.SITE.LOG}]
|
||||
tags:
|
||||
- tag: component
|
||||
value: timestamps
|
||||
- uuid: d55e36ba-c7c7-4e80-98aa-725b3935ae71
|
||||
name: 'Nginx Site: Unique Request ID'
|
||||
type: DEPENDENT
|
||||
key: nginx.site.request_id
|
||||
delay: '0'
|
||||
value_type: TEXT
|
||||
description: Unique Request ID
|
||||
history: 30d
|
||||
preprocessing:
|
||||
- type: JSONPATH
|
||||
parameters:
|
||||
- $.request_id
|
||||
error_handler: DISCARD_VALUE
|
||||
master_item:
|
||||
key: log[{$NGINX.SITE.LOG}]
|
||||
tags:
|
||||
- tag: component
|
||||
value: timestamps
|
||||
- uuid: bc5b35db-700b-4e2c-9925-e1c03aad24e3
|
||||
name: 'Nginx Site: Client IP'
|
||||
type: DEPENDENT
|
||||
key: nginx.site.remote_addr
|
||||
delay: '0'
|
||||
value_type: TEXT
|
||||
description: Client IP
|
||||
history: 30d
|
||||
preprocessing:
|
||||
- type: JSONPATH
|
||||
parameters:
|
||||
- $.remote_addr
|
||||
error_handler: DISCARD_VALUE
|
||||
master_item:
|
||||
key: log[{$NGINX.SITE.LOG}]
|
||||
tags:
|
||||
- tag: component
|
||||
value: network
|
||||
- uuid: c81de241-e241-452c-8287-c00c74fcc95b
|
||||
name: 'Nginx Site: Real IP (X-Forwarded-For)'
|
||||
type: DEPENDENT
|
||||
key: nginx.site.real_ip
|
||||
delay: '0'
|
||||
value_type: TEXT
|
||||
description: Real IP (X-Forwarded-For)
|
||||
history: 30d
|
||||
preprocessing:
|
||||
- type: JSONPATH
|
||||
parameters:
|
||||
- $.real_ip
|
||||
error_handler: DISCARD_VALUE
|
||||
master_item:
|
||||
key: log[{$NGINX.SITE.LOG}]
|
||||
tags:
|
||||
- tag: component
|
||||
value: network
|
||||
- uuid: f5fd7a97-6578-44c9-8731-ef3c6cfd9a30
|
||||
name: 'Nginx Site: Authenticated User'
|
||||
type: DEPENDENT
|
||||
key: nginx.site.remote_user
|
||||
delay: '0'
|
||||
value_type: TEXT
|
||||
description: Authenticated User
|
||||
history: 30d
|
||||
preprocessing:
|
||||
- type: JSONPATH
|
||||
parameters:
|
||||
- $.remote_user
|
||||
error_handler: DISCARD_VALUE
|
||||
master_item:
|
||||
key: log[{$NGINX.SITE.LOG}]
|
||||
tags:
|
||||
- tag: component
|
||||
value: network
|
||||
- uuid: 2792452d-6c55-4bfa-8e37-fd134d0bf76b
|
||||
name: 'Nginx Site: HTTP Method'
|
||||
type: DEPENDENT
|
||||
key: nginx.site.request_method
|
||||
delay: '0'
|
||||
value_type: TEXT
|
||||
description: HTTP Method
|
||||
history: 30d
|
||||
preprocessing:
|
||||
- type: JSONPATH
|
||||
parameters:
|
||||
- $.request_method
|
||||
error_handler: DISCARD_VALUE
|
||||
master_item:
|
||||
key: log[{$NGINX.SITE.LOG}]
|
||||
tags:
|
||||
- tag: component
|
||||
value: request
|
||||
- uuid: c32f7902-1683-4a99-8832-4d190f02ca81
|
||||
name: 'Nginx Site: Host Header'
|
||||
type: DEPENDENT
|
||||
key: nginx.site.host_header
|
||||
delay: '0'
|
||||
value_type: TEXT
|
||||
description: Host Header
|
||||
history: 30d
|
||||
preprocessing:
|
||||
- type: JSONPATH
|
||||
parameters:
|
||||
- $.host_header
|
||||
error_handler: DISCARD_VALUE
|
||||
master_item:
|
||||
key: log[{$NGINX.SITE.LOG}]
|
||||
tags:
|
||||
- tag: component
|
||||
value: request
|
||||
- uuid: 8e156772-27be-45df-afff-4cc7214aa838
|
||||
name: 'Nginx Site: URI'
|
||||
type: DEPENDENT
|
||||
key: nginx.site.uri
|
||||
delay: '0'
|
||||
value_type: TEXT
|
||||
description: URI
|
||||
history: 30d
|
||||
preprocessing:
|
||||
- type: JSONPATH
|
||||
parameters:
|
||||
- $.uri
|
||||
error_handler: DISCARD_VALUE
|
||||
master_item:
|
||||
key: log[{$NGINX.SITE.LOG}]
|
||||
tags:
|
||||
- tag: component
|
||||
value: request
|
||||
- uuid: 4febe104-a59a-4204-bf42-f21cb550d625
|
||||
name: 'Nginx Site: Request Length (bytes)'
|
||||
type: DEPENDENT
|
||||
key: nginx.site.request_length
|
||||
delay: '0'
|
||||
value_type: FLOAT
|
||||
description: Request Length (bytes)
|
||||
history: 30d
|
||||
preprocessing:
|
||||
- type: JSONPATH
|
||||
parameters:
|
||||
- $.request_length
|
||||
error_handler: DISCARD_VALUE
|
||||
master_item:
|
||||
key: log[{$NGINX.SITE.LOG}]
|
||||
tags:
|
||||
- tag: component
|
||||
value: request
|
||||
- uuid: 6ab853fb-2b27-4185-be8c-65c06bd02d4a
|
||||
name: 'Nginx Site: HTTP Status Code'
|
||||
type: DEPENDENT
|
||||
key: nginx.site.status
|
||||
delay: '0'
|
||||
value_type: FLOAT
|
||||
description: HTTP Status Code
|
||||
history: 30d
|
||||
preprocessing:
|
||||
- type: JSONPATH
|
||||
parameters:
|
||||
- $.status
|
||||
error_handler: DISCARD_VALUE
|
||||
master_item:
|
||||
key: log[{$NGINX.SITE.LOG}]
|
||||
tags:
|
||||
- tag: component
|
||||
value: response
|
||||
- uuid: 91c8ed8e-1631-435d-9114-9a2f21eaa152
|
||||
name: 'Nginx Site: Body Bytes Sent'
|
||||
type: DEPENDENT
|
||||
key: nginx.site.body_bytes_sent
|
||||
delay: '0'
|
||||
value_type: FLOAT
|
||||
description: Body Bytes Sent
|
||||
history: 30d
|
||||
preprocessing:
|
||||
- type: JSONPATH
|
||||
parameters:
|
||||
- $.body_bytes_sent
|
||||
error_handler: DISCARD_VALUE
|
||||
master_item:
|
||||
key: log[{$NGINX.SITE.LOG}]
|
||||
tags:
|
||||
- tag: component
|
||||
value: response
|
||||
- uuid: 803bf915-8366-4c0b-ba79-eba29496f69f
|
||||
name: 'Nginx Site: Total Bytes Sent'
|
||||
type: DEPENDENT
|
||||
key: nginx.site.bytes_sent
|
||||
delay: '0'
|
||||
value_type: FLOAT
|
||||
description: Total Bytes Sent
|
||||
history: 30d
|
||||
preprocessing:
|
||||
- type: JSONPATH
|
||||
parameters:
|
||||
- $.bytes_sent
|
||||
error_handler: DISCARD_VALUE
|
||||
master_item:
|
||||
key: log[{$NGINX.SITE.LOG}]
|
||||
tags:
|
||||
- tag: component
|
||||
value: response
|
||||
- uuid: 82a7d2fd-1e09-4976-9b29-12551791029f
|
||||
name: 'Nginx Site: Request Time (Total)'
|
||||
type: DEPENDENT
|
||||
key: nginx.site.request_time
|
||||
delay: '0'
|
||||
value_type: FLOAT
|
||||
description: Request Time (Total)
|
||||
history: 30d
|
||||
preprocessing:
|
||||
- type: JSONPATH
|
||||
parameters:
|
||||
- $.request_time
|
||||
error_handler: DISCARD_VALUE
|
||||
master_item:
|
||||
key: log[{$NGINX.SITE.LOG}]
|
||||
tags:
|
||||
- tag: component
|
||||
value: performance
|
||||
- uuid: f65cdff7-b3d9-428a-98a6-d0ccbe557589
|
||||
name: 'Nginx Site: Upstream Connect Time'
|
||||
type: DEPENDENT
|
||||
key: nginx.site.upstream_connect_time
|
||||
delay: '0'
|
||||
value_type: FLOAT
|
||||
description: Upstream Connect Time
|
||||
history: 30d
|
||||
preprocessing:
|
||||
- type: JSONPATH
|
||||
parameters:
|
||||
- $.upstream_connect_time
|
||||
error_handler: DISCARD_VALUE
|
||||
master_item:
|
||||
key: log[{$NGINX.SITE.LOG}]
|
||||
tags:
|
||||
- tag: component
|
||||
value: performance
|
||||
- uuid: 8c7e5f38-9865-41b3-b22c-f5e7b51bfcfe
|
||||
name: 'Nginx Site: Upstream Header Time'
|
||||
type: DEPENDENT
|
||||
key: nginx.site.upstream_header_time
|
||||
delay: '0'
|
||||
value_type: FLOAT
|
||||
description: Upstream Header Time
|
||||
history: 30d
|
||||
preprocessing:
|
||||
- type: JSONPATH
|
||||
parameters:
|
||||
- $.upstream_header_time
|
||||
error_handler: DISCARD_VALUE
|
||||
master_item:
|
||||
key: log[{$NGINX.SITE.LOG}]
|
||||
tags:
|
||||
- tag: component
|
||||
value: performance
|
||||
- uuid: 20f65169-9c54-4fe1-9468-3df9de93f8e4
|
||||
name: 'Nginx Site: Upstream Response Time'
|
||||
type: DEPENDENT
|
||||
key: nginx.site.upstream_response_time
|
||||
delay: '0'
|
||||
value_type: FLOAT
|
||||
description: Upstream Response Time
|
||||
history: 30d
|
||||
preprocessing:
|
||||
- type: JSONPATH
|
||||
parameters:
|
||||
- $.upstream_response_time
|
||||
error_handler: DISCARD_VALUE
|
||||
master_item:
|
||||
key: log[{$NGINX.SITE.LOG}]
|
||||
tags:
|
||||
- tag: component
|
||||
value: performance
|
||||
- uuid: 943cce09-54a4-42c2-8c17-81eff8d4069f
|
||||
name: 'Nginx Site: Cache Status'
|
||||
type: DEPENDENT
|
||||
key: nginx.site.upstream_cache_status
|
||||
delay: '0'
|
||||
value_type: TEXT
|
||||
description: Cache Status
|
||||
history: 30d
|
||||
preprocessing:
|
||||
- type: JSONPATH
|
||||
parameters:
|
||||
- $.upstream_cache_status
|
||||
error_handler: DISCARD_VALUE
|
||||
master_item:
|
||||
key: log[{$NGINX.SITE.LOG}]
|
||||
tags:
|
||||
- tag: component
|
||||
value: performance
|
||||
- uuid: 9ccc7f5e-e8d0-47ba-8e4a-92b6cad62879
|
||||
name: 'Nginx Site: GeoIP Country Code'
|
||||
type: DEPENDENT
|
||||
key: nginx.site.geoip_country_code
|
||||
delay: '0'
|
||||
value_type: TEXT
|
||||
description: GeoIP Country Code
|
||||
history: 30d
|
||||
preprocessing:
|
||||
- type: JSONPATH
|
||||
parameters:
|
||||
- $.geoip_country_code
|
||||
error_handler: DISCARD_VALUE
|
||||
master_item:
|
||||
key: log[{$NGINX.SITE.LOG}]
|
||||
tags:
|
||||
- tag: component
|
||||
value: geoip
|
||||
- uuid: c6cfd5f9-dd0e-495d-bca9-300b9d9c5c96
|
||||
name: 'Nginx Site: GeoIP City Name'
|
||||
type: DEPENDENT
|
||||
key: nginx.site.geoip_city_name
|
||||
delay: '0'
|
||||
value_type: TEXT
|
||||
description: GeoIP City Name
|
||||
history: 30d
|
||||
preprocessing:
|
||||
- type: JSONPATH
|
||||
parameters:
|
||||
- $.geoip_city_name
|
||||
error_handler: DISCARD_VALUE
|
||||
master_item:
|
||||
key: log[{$NGINX.SITE.LOG}]
|
||||
tags:
|
||||
- tag: component
|
||||
value: geoip
|
||||
- uuid: 24b4d01c-ce56-4bf8-84b3-a2b54ba0bc08
|
||||
name: 'Nginx Site: GeoIP ISP'
|
||||
type: DEPENDENT
|
||||
key: nginx.site.geoip_isp
|
||||
delay: '0'
|
||||
value_type: TEXT
|
||||
description: GeoIP ISP
|
||||
history: 30d
|
||||
preprocessing:
|
||||
- type: JSONPATH
|
||||
parameters:
|
||||
- $.geoip_isp
|
||||
error_handler: DISCARD_VALUE
|
||||
master_item:
|
||||
key: log[{$NGINX.SITE.LOG}]
|
||||
tags:
|
||||
- tag: component
|
||||
value: geoip
|
||||
- uuid: 52fde988-999a-4b54-8f6f-042c5e83e46f
|
||||
name: 'Nginx Site: Bad Bot Flag'
|
||||
type: DEPENDENT
|
||||
key: nginx.site.is_bad_bot
|
||||
delay: '0'
|
||||
value_type: TEXT
|
||||
description: Bad Bot Flag
|
||||
history: 30d
|
||||
preprocessing:
|
||||
- type: JSONPATH
|
||||
parameters:
|
||||
- $.is_bad_bot
|
||||
error_handler: DISCARD_VALUE
|
||||
master_item:
|
||||
key: log[{$NGINX.SITE.LOG}]
|
||||
tags:
|
||||
- tag: component
|
||||
value: security
|
||||
- uuid: abd94490-38f1-4672-a5ec-4a62ab04870b
|
||||
name: 'Nginx Site: WAF Block Flag'
|
||||
type: DEPENDENT
|
||||
key: nginx.site.block_request
|
||||
delay: '0'
|
||||
value_type: TEXT
|
||||
description: WAF Block Flag
|
||||
history: 30d
|
||||
preprocessing:
|
||||
- type: JSONPATH
|
||||
parameters:
|
||||
- $.block_request
|
||||
error_handler: DISCARD_VALUE
|
||||
master_item:
|
||||
key: log[{$NGINX.SITE.LOG}]
|
||||
tags:
|
||||
- tag: component
|
||||
value: security
|
||||
- uuid: 2d75c9e6-ef88-4205-aa6c-440037fcacb4
|
||||
name: 'Nginx Site: SSL Protocol'
|
||||
type: DEPENDENT
|
||||
key: nginx.site.ssl_protocol
|
||||
delay: '0'
|
||||
value_type: TEXT
|
||||
description: SSL Protocol
|
||||
history: 30d
|
||||
preprocessing:
|
||||
- type: JSONPATH
|
||||
parameters:
|
||||
- $.ssl_protocol
|
||||
error_handler: DISCARD_VALUE
|
||||
master_item:
|
||||
key: log[{$NGINX.SITE.LOG}]
|
||||
tags:
|
||||
- tag: component
|
||||
value: security
|
||||
- uuid: 827b7c96-1994-49f1-a476-7f2036ae9075
|
||||
name: 'Nginx Site: SSL Cipher'
|
||||
type: DEPENDENT
|
||||
key: nginx.site.ssl_cipher
|
||||
delay: '0'
|
||||
value_type: TEXT
|
||||
description: SSL Cipher
|
||||
history: 30d
|
||||
preprocessing:
|
||||
- type: JSONPATH
|
||||
parameters:
|
||||
- $.ssl_cipher
|
||||
error_handler: DISCARD_VALUE
|
||||
master_item:
|
||||
key: log[{$NGINX.SITE.LOG}]
|
||||
tags:
|
||||
- tag: component
|
||||
value: security
|
||||
- uuid: 42766b9a-5bb3-4b0e-816f-c250c00a6f00
|
||||
name: 'Nginx Site: HTTP 5xx Rate'
|
||||
type: CALCULATED
|
||||
key: nginx.site.status.5xx.rate
|
||||
params: count(//nginx.site.status, 1m, "ge", 500)
|
||||
value_type: FLOAT
|
||||
units: rps
|
||||
delay: 1m
|
||||
tags:
|
||||
- tag: component
|
||||
value: availability
|
||||
|
|
@ -0,0 +1,199 @@
|
|||
# AI Agent Execution Plan: OpenVPN Hybrid Integration
|
||||
|
||||
**Objective**: transform the `pfsense_hybrid_snmp_agent` folder into a production-ready Hybrid solution.
|
||||
**Context**: The files `C:\Users\joao.goncalves\Desktop\zabbix-itguys\templates_gold\pfsense_hybrid_snmp_agent\files\openvpn-discovery.sh` and `C:\Users\joao.goncalves\Desktop\zabbix-itguys\templates_gold\pfsense_hybrid_snmp_agent\files\userparameter_openvpn.conf` are currently raw copies. The YAML template is the original SNMP version located at `C:\Users\joao.goncalves\Desktop\zabbix-itguys\templates_gold\pfsense_hybrid_snmp_agent\template_app_pfsense_snmp.yaml`.
|
||||
|
||||
|
||||
## Execution Strategy & Safety Context
|
||||
**Goal**: We are building a "Hybrid" Zabbix Template for pfSense that combines standard SNMP monitoring with advanced OpenVPN metrics collected via Zabbix Agent Custom UserParameters.
|
||||
**Key Features**:
|
||||
1. **Dynamic Grouping**: Group VPN users by "Company" (Server Name) derived from log filenames.
|
||||
2. **Security Triggers**: Detect Exfiltration (>10GB/h), Zombie Sessions (>24h), and Session Hijacking (IP Change).
|
||||
3. **S2S vs User**: Distinguish Site-to-Site tunnels from human users to apply different alert rules via Macros and Discovery Overrides.
|
||||
|
||||
**CRITICAL INSTRUCTION**: If any step in this runbook is ambiguous, fails validation, or if you encounter unexpected file structures, **STOP IMMEDIATELY**. Do not guess. Ask the user for clarification before proceeding to the next step.
|
||||
|
||||
---
|
||||
|
||||
## Phase 1: Script & Agent Configuration
|
||||
|
||||
### 1.1. Rewrite `files/openvpn-discovery.sh`
|
||||
**Path**: `C:\Users\joao.goncalves\Desktop\zabbix-itguys\templates_gold\pfsense_hybrid_snmp_agent\files\openvpn-discovery.sh`
|
||||
**Logic**:
|
||||
- Scan `/var/log/openvpn/status*.log`.
|
||||
- Extract `{#VPN.SERVER}` from filename (Regex: `status_(.*).log` -> Group 1).
|
||||
- Extract Users, Real IP, Byte Counts from content.
|
||||
- **Critical**: Output JSON standard for Zabbix LLD.
|
||||
|
||||
```bash
|
||||
#!/bin/sh
|
||||
# OpenVPN Discovery Script (Arthur's Gold Standard)
|
||||
# Outputs: {#VPN.USER}, {#VPN.SERVER}, {#VPN.REAL_IP}
|
||||
|
||||
JSON_OUTPUT="{\"data\":["
|
||||
FIRST_ITEM=1
|
||||
|
||||
# Loop through all status logs
|
||||
for logfile in /var/log/openvpn/status*.log; do
|
||||
[ -e "$logfile" ] || continue
|
||||
|
||||
# Extract Server Name from Filename "status_SERVERNAME.log"
|
||||
# Note: Busybox filename parsing
|
||||
filename=$(basename "$logfile")
|
||||
# Remove prefix "status_" and suffix ".log"
|
||||
server_name=$(echo "$filename" | sed -e 's/^status_//' -e 's/\.log$//')
|
||||
|
||||
# Read the file and parse "CLIENT_LIST" lines
|
||||
# Format: CLIENT_LIST,CommonName,RealAddress,VirtualAddress,BytesReceived,BytesSent,Since,Since(time_t),Username,ClientID,PeerID
|
||||
while IFS=, read -r type common_name real_address virtual_address bytes_rx bytes_tx since since_unix username client_id peer_id; do
|
||||
if [ "$type" = "CLIENT_LIST" ] && [ "$common_name" != "Common Name" ]; then
|
||||
# Extract IP only from RealAddress (IP:PORT)
|
||||
real_ip=$(echo "$real_address" | cut -d: -f1)
|
||||
|
||||
# Append to JSON
|
||||
if [ $FIRST_ITEM -eq 0 ]; then JSON_OUTPUT="$JSON_OUTPUT,"; fi
|
||||
JSON_OUTPUT="$JSON_OUTPUT{\"{#VPN.USER}\":\"$common_name\",\"{#VPN.SERVER}\":\"$server_name\",\"{#VPN.REAL_IP}\":\"$real_ip\"}"
|
||||
FIRST_ITEM=0
|
||||
fi
|
||||
done < "$logfile"
|
||||
done
|
||||
|
||||
JSON_OUTPUT="$JSON_OUTPUT]}"
|
||||
echo "$JSON_OUTPUT"
|
||||
```
|
||||
|
||||
### 1.2. Update `files/userparameter_openvpn.conf`
|
||||
**Path**: `C:\Users\joao.goncalves\Desktop\zabbix-itguys\templates_gold\pfsense_hybrid_snmp_agent\files\userparameter_openvpn.conf`
|
||||
**Logic**:
|
||||
- Simplify. The discovery script now does the heavy lifting of finding users.
|
||||
- The Items need to fetch data. Since we have multiple files, `grep` needs to search ALL of them.
|
||||
- **Optimization**: `grep -h` (no filename) to search all generic status logs.
|
||||
|
||||
```conf
|
||||
UserParameter=openvpn.discovery,/opt/zabbix/openvpn-discovery.sh
|
||||
# Fetch raw metrics for a specific user (Usernames must be unique across servers or we grab the first match)
|
||||
UserParameter=openvpn.user.bytes_received.total[*],grep -h "^CLIENT_LIST,$1," /var/log/openvpn/status*.log 2>/dev/null | head -1 | cut -d, -f6
|
||||
UserParameter=openvpn.user.bytes_sent.total[*],grep -h "^CLIENT_LIST,$1," /var/log/openvpn/status*.log 2>/dev/null | head -1 | cut -d, -f7
|
||||
UserParameter=openvpn.user.connected_since[*],grep -h "^CLIENT_LIST,$1," /var/log/openvpn/status*.log 2>/dev/null | head -1 | cut -d, -f9
|
||||
UserParameter=openvpn.user.real_address.new[*],grep -h "^CLIENT_LIST,$1," /var/log/openvpn/status*.log 2>/dev/null | head -1 | cut -d, -f3 | cut -d: -f1
|
||||
UserParameter=openvpn.user.status[*],if grep -q "^CLIENT_LIST,$1," /var/log/openvpn/status*.log 2>/dev/null; then echo 1; else echo 0; fi
|
||||
UserParameter=openvpn.version,openvpn --version 2>&1 | head -1 | awk '{print $2}'
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Phase 2: Template Configuration (YAML)
|
||||
|
||||
**Target**: `templates_gold/pfsense_hybrid_snmp_agent/template_pfsense_hybrid_gold.yaml`
|
||||
|
||||
### 2.1. Add Macros
|
||||
Append to `macros` section:
|
||||
```yaml
|
||||
- macro: '{$VPN.S2S.PATTERN}'
|
||||
value: '^S2S_'
|
||||
description: 'Regex para identificar túneis Site-to-Site.'
|
||||
- macro: '{$VPN.DATA.LIMIT}'
|
||||
value: '10737418240'
|
||||
description: 'Limite de Download (10GB) para alerta de Exfiltração.'
|
||||
- macro: '{$VPN.WORK.START}'
|
||||
value: '080000'
|
||||
- macro: '{$VPN.WORK.END}'
|
||||
value: '180000'
|
||||
- macro: '{$VPN.ZOMBIE.LIMIT}'
|
||||
value: '86400'
|
||||
description: 'Tempo máximo (24h) para considerar sessão zumbi.'
|
||||
```
|
||||
|
||||
### 2.2. Add Discovery Rule
|
||||
**Name**: `Descoberta de Usuários OpenVPN`
|
||||
**Key**: `openvpn.discovery`
|
||||
**Type**: `ZABBIX_ACTIVE` (Preferred for Agents behind NAT/Firewall)
|
||||
|
||||
**Overrides**:
|
||||
```yaml
|
||||
overrides:
|
||||
- name: 'Site-to-Site (S2S)'
|
||||
step: '1'
|
||||
filter:
|
||||
conditions:
|
||||
- macro: '{#VPN.USER}'
|
||||
value: '{$VPN.S2S.PATTERN}'
|
||||
operator: REGEXP
|
||||
operations:
|
||||
- operationobject: ITEM_PROTOTYPE
|
||||
operator: REGEXP
|
||||
value: 'Stats Year|Forecast'
|
||||
status: ENABLED
|
||||
- operationobject: TRIGGER_PROTOTYPE
|
||||
operator: REGEXP
|
||||
value: 'Exfiltração|Horário|Zombie|IP Change'
|
||||
status: DISABLED
|
||||
- operationobject: ITEM_PROTOTYPE
|
||||
operator: LIKE
|
||||
value: ''
|
||||
tags:
|
||||
- tag: Type
|
||||
value: S2S
|
||||
- name: 'User (Colaborador)'
|
||||
step: '2'
|
||||
filter:
|
||||
conditions:
|
||||
- macro: '{#VPN.USER}'
|
||||
value: '{$VPN.S2S.PATTERN}'
|
||||
operator: NOT_REGEXP
|
||||
operations:
|
||||
- operationobject: ITEM_PROTOTYPE
|
||||
operator: REGEXP
|
||||
value: 'Stats Year|Forecast'
|
||||
status: DISABLED
|
||||
- operationobject: TRIGGER_PROTOTYPE
|
||||
operator: REGEXP
|
||||
value: 'Exfiltração|Horário|Zombie|IP Change'
|
||||
status: ENABLED
|
||||
- operationobject: ITEM_PROTOTYPE
|
||||
operator: LIKE
|
||||
value: ''
|
||||
tags:
|
||||
- tag: Type
|
||||
value: User
|
||||
```
|
||||
|
||||
### 2.3. Add Item Prototypes (Selected)
|
||||
|
||||
**Common Tags**: `Company: {{#VPN.SERVER}.regsub("(?:CLIENT_|S2S_)?(.*)", "\1")}`
|
||||
|
||||
1. **Download Total (Raw)**
|
||||
- Key: `openvpn.user.bytes_received.total[{#VPN.USER}]`
|
||||
- Type: ZABBIX_ACTIVE
|
||||
- Units: B
|
||||
|
||||
2. **Download Rate (Calculated/Dependent?)**
|
||||
- Actually, simpler to let Zabbix standard "Simple Change" preprocessing handle rate on a Dependent Item, or just use `Change per Second` preprocessing.
|
||||
- **Decision**: Create `openvpn.user.bytes_received.rate[{#VPN.USER}]` dependent on Total, with `Change per Second`.
|
||||
|
||||
3. **Real IP (Inventory)**
|
||||
- Key: `openvpn.user.real_address.new[{#VPN.USER}]`
|
||||
- Populates Host Inventory field? No, this is an item prototype. Just keep as value.
|
||||
|
||||
**Reporting Metrics (Calculated)**
|
||||
- **Stats Week**: `trendsum(//openvpn.user.bytes_received.total[{#VPN.USER}], 1w:now/w)`
|
||||
- **Stats Month**: `trendsum(..., 1M:now/M)`
|
||||
- **Forecast**: `(last(Month) / dayat()) * dayofmonth(end)` (Simplified)
|
||||
|
||||
### 2.4. Add Triggers
|
||||
|
||||
1. **Exfiltração**: `(last(Total) - last(Total, 1h)) > {$VPN.DATA.LIMIT}`
|
||||
2. **IP Change**: `diff(RealIP)=1 and last(Status)=1`
|
||||
3. **Zombie**: `last(ConnectedSince) < now() - {$VPN.ZOMBIE.LIMIT}`
|
||||
|
||||
### 2.5. Add Dashboard
|
||||
Insert `dashboards:` block at root (or modify existing if any).
|
||||
- Use `type: svggraph` for Trends.
|
||||
- Use `type: tophosts` for Tables (Columns: Name, Latest Value of Metric).
|
||||
|
||||
---
|
||||
|
||||
## Phase 3: Validation
|
||||
|
||||
1. **Lint**: `validate_zabbix_template.py`.
|
||||
2. **Docs**: `generate_template_docs.py`.
|
||||
|
|
@ -1,110 +0,0 @@
|
|||
# 🚀 Agent Execution Plan: Zabbix Speedtest & Strategic Intelligence (v10)
|
||||
|
||||
**Status:** APPROVED
|
||||
**Target Directory:** `c:\Users\joao.goncalves\Desktop\zabbix-itguys\templates_gold\pfsense_hybrid_snmp_agent`
|
||||
**Objective:** Implement a robust, multi-WAN speedtest solution with Business Intelligence dashboards in the Gold Template.
|
||||
|
||||
---
|
||||
|
||||
## 🏗️ 1. File Structure & Scripts (Fase 1)
|
||||
|
||||
These files must be created in the `files/` subdirectory.
|
||||
|
||||
### A. `files/speedtest_discovery.py` (Python 3.11)
|
||||
- **Goal:** Native pfSense Discovery without external dependencies.
|
||||
- **Logic:**
|
||||
1. Parse `/cf/conf/config.xml` using `xml.etree.ElementTree`.
|
||||
2. Identify interfaces with a `<gateway>` tag (WANs).
|
||||
3. Extract `descr` (Name), `if` (Interface ID like igb0), `ipaddr`.
|
||||
- **Output (LLD JSON):**
|
||||
```json
|
||||
[{"{#IFNAME}": "igb0", "{#WAN_ALIAS}": "VIVO", "{#WAN_IP}": "x.x.x.x"}]
|
||||
```
|
||||
|
||||
### B. `files/speedtest_worker.sh` (Bash)
|
||||
- **Goal:** Execute speedtest ensuring no timeouts + Telemetry.
|
||||
- **Arguments:** `--interface <IF>`
|
||||
- **Logic:**
|
||||
1. Start a background CPU monitor (`top -P 0` or `vmstat 1`) to capture `idle/interrupt` %.
|
||||
2. Execute `speedtest --interface <IP_FROM_IF> --format json`.
|
||||
3. Stop CPU monitor. Calculate average CPU Load during test.
|
||||
4. Inject `cpu_load_during_test` and `interrupts` into the Speedtest JSON.
|
||||
5. Send to Zabbix via `zabbix_sender` (Trappers).
|
||||
|
||||
### C. `files/install_speedtest.sh`
|
||||
- Helper to install `pkg install -y speedtest`.
|
||||
|
||||
---
|
||||
|
||||
## 🧠 2. Template Intelligence (Fase 2)
|
||||
|
||||
Modify `template_pfsense_hybrid_gold.yaml` (Monolithic Approach).
|
||||
|
||||
### A. Discovery Rule
|
||||
- **Key:** `speedtest.discovery`
|
||||
- **Type:** Zabbix Agent (UserParameter calling the Python script).
|
||||
|
||||
### B. Item Prototypes (Trappers)
|
||||
- **Master:** `speedtest.json[{#IFNAME}]`
|
||||
- **Dependent Items:**
|
||||
- `speedtest.download`, `speedtest.upload`, `speedtest.latency`
|
||||
- `speedtest.cpu_load` (New)
|
||||
- `speedtest.bufferbloat` (Calculated: `speedtest.latency - icmppingsec`)
|
||||
|
||||
### C. Calculated Items (Business Logic)
|
||||
1. **Forecasting (Saturação):**
|
||||
- `business.bandwidth.saturation_date`: Forecast when `net.if.in` reaches `{$WAN_CONTRACT_DOWN}`.
|
||||
2. **Financeiro (Risco):**
|
||||
- `business.downtime.cost`: `(100 - sla.uptime) * {$COMPANY.HOURLY_COST}`.
|
||||
3. **Efficiency:**
|
||||
- `business.link.efficiency`: `avg(net.if.in, 30d) / {$WAN_CONTRACT_DOWN} * 100`.
|
||||
|
||||
### D. Triggers (Cross-Correlation)
|
||||
1. **Hardware Bottleneck:**
|
||||
- `speedtest.download < Expected` AND `speedtest.cpu_load > 90%`.
|
||||
- Msg: "🔥 Hardware Limiting Speed (Not ISP)".
|
||||
2. **ISP Quality (Bufferbloat):**
|
||||
- `speedtest.bufferbloat > 100ms`.
|
||||
- Msg: "⚠️ ISP Latency Spike under Load".
|
||||
3. **Financial Opportunity:**
|
||||
- `business.downtime.cost > {$LINK.SECONDARY.COST}`.
|
||||
- Msg: "💰 Downtime costs exceed Secondary Link price."
|
||||
|
||||
---
|
||||
|
||||
## 📊 3. Dashboards (Fase 3)
|
||||
|
||||
Create a Dashboard Resource in the YAML: "Speedtest & Strategic Planning".
|
||||
|
||||
**Widgets:**
|
||||
1. **Executive Summary:** Markdown widget showing Financial Loss & Efficiency.
|
||||
2. **Forecasting:** Graph showing Traffic Growth vs Contract Limit (Projected).
|
||||
3. **Technical Correlation:** Graph with 3 Y-axes (Speed, CPU, Latency).
|
||||
|
||||
---
|
||||
|
||||
## 📝 4. Documentation (Fase 4)
|
||||
|
||||
Update `INSTRUCOES_AGENTE.txt`:
|
||||
- Add "Step 5: Setup Speedtest".
|
||||
- Instructions for `pkg install` and `cron` setup.
|
||||
|
||||
---
|
||||
|
||||
## ✅ 5. Validation & Auto-Documentation (MANDATORY)
|
||||
|
||||
Once the modifications are complete, the Agent **MUST** run the project's QA tools to ensure quality and compliance.
|
||||
|
||||
### A. Validate Template Structure
|
||||
Run the validation script to check for UUID conflicts, schema errors, or duplicate keys.
|
||||
```powershell
|
||||
python c:\Users\joao.goncalves\Desktop\zabbix-itguys\validate_zabbix_template.py c:\Users\joao.goncalves\Desktop\zabbix-itguys\templates_gold\pfsense_hybrid_snmp_agent\template_pfsense_hybrid_gold.yaml
|
||||
```
|
||||
- **Constraint:** If this script returns ANY error, the Agent must fix it immediately before finishing the task.
|
||||
|
||||
### B. Generate Documentation
|
||||
Run the documentation generator to automatically update the markdown documentation for the template.
|
||||
```powershell
|
||||
python c:\Users\joao.goncalves\Desktop\zabbix-itguys\generate_template_docs.py c:\Users\joao.goncalves\Desktop\zabbix-itguys\templates_gold\pfsense_hybrid_snmp_agent\template_pfsense_hybrid_gold.yaml
|
||||
```
|
||||
- **Output:** This will generate/update `template_pfsense_hybrid_gold_generated.md`.
|
||||
File diff suppressed because it is too large
Load Diff
|
|
@ -1,932 +0,0 @@
|
|||
zabbix_export:
|
||||
version: '7.4'
|
||||
host_groups:
|
||||
- uuid: 7fd3a689a3874d0b9212a8f11af9f356
|
||||
name: 'IT GUYS'
|
||||
- uuid: 5b5d7aa968304e2191657b4d0b0e5a4b
|
||||
name: LINUX
|
||||
- uuid: 137f19e6e2dc4219b33553b812627bc2
|
||||
name: 'VM / MAQUINA VIRTUAL'
|
||||
hosts:
|
||||
- host: srvproxy001
|
||||
name: 'iT Guys - Debian 12 - Pathfinder (Nginx Proxy)'
|
||||
templates:
|
||||
- name: Fail2ban
|
||||
- name: 'Linux via Agente Zabbix'
|
||||
- name: 'Nginx por Zabbix agent'
|
||||
groups:
|
||||
- name: 'IT GUYS'
|
||||
- name: LINUX
|
||||
- name: 'VM / MAQUINA VIRTUAL'
|
||||
interfaces:
|
||||
- ip: 172.16.254.1
|
||||
interface_ref: if1
|
||||
discovery_rules:
|
||||
- name: 'Insight: Log de Acesso'
|
||||
type: ZABBIX_ACTIVE
|
||||
key: nginx.access.logs.list
|
||||
delay: 1s
|
||||
enabled_lifetime_type: DISABLE_AFTER
|
||||
enabled_lifetime: 1h
|
||||
item_prototypes:
|
||||
- name: 'Insight: Acesso {#HOST_SITE}'
|
||||
type: ZABBIX_ACTIVE
|
||||
key: 'log[/var/log/nginx/{#HOST_SITE}.access.log]'
|
||||
delay: 1s
|
||||
history: 91d
|
||||
value_type: LOG
|
||||
timeout: 120s
|
||||
tags:
|
||||
- tag: Insight
|
||||
value: 'access log'
|
||||
- name: 'Insight: Bad-Bot {#HOST_SITE}'
|
||||
type: ZABBIX_ACTIVE
|
||||
key: 'log[/var/log/nginx/{#HOST_SITE}.bad-bot.log]'
|
||||
delay: 1s
|
||||
value_type: LOG
|
||||
timeout: 120s
|
||||
tags:
|
||||
- tag: Insight
|
||||
value: bad-bot
|
||||
- name: 'Insight: Erros {#HOST_SITE}'
|
||||
type: ZABBIX_ACTIVE
|
||||
key: 'log[/var/log/nginx/{#HOST_SITE}.error.log]'
|
||||
delay: 1s
|
||||
value_type: LOG
|
||||
timeout: 120s
|
||||
tags:
|
||||
- tag: Insight
|
||||
value: 'error log'
|
||||
- name: 'Nginx: Cache HITs Flag for {#HOST_SITE}'
|
||||
type: DEPENDENT
|
||||
key: 'nginx.cache.hit.flag.[{#HOST_SITE}]'
|
||||
preprocessing:
|
||||
- type: REGEX
|
||||
parameters:
|
||||
- 'upstream_cache_status":"HIT"'
|
||||
- '1'
|
||||
error_handler: CUSTOM_VALUE
|
||||
error_handler_params: '0'
|
||||
master_item:
|
||||
key: 'log[/var/log/nginx/{#HOST_SITE}.access.log]'
|
||||
tags:
|
||||
- tag: Insight
|
||||
value: performance
|
||||
- name: 'Insight: Cache Hit Ratio (Ultimo 1m) (%) {#HOST_SITE}'
|
||||
type: CALCULATED
|
||||
key: 'nginx.cache.hit.ratio.1m.[{#HOST_SITE}]'
|
||||
value_type: FLOAT
|
||||
units: '%'
|
||||
params: '(last(//nginx.cache.hits.1m.[{#HOST_SITE}]) * 100) / (last(//nginx.cache.hits.1m.[{#HOST_SITE}]) + last(//nginx.cache.miss.1m.[{#HOST_SITE}]) + (last(//nginx.cache.hits.1m.[{#HOST_SITE}]) + last(//nginx.cache.miss.1m.[{#HOST_SITE}]) = 0))'
|
||||
tags:
|
||||
- tag: Insight
|
||||
value: carga
|
||||
- name: 'Insight: Cache HITs no Ultimo minuto {#HOST_SITE}'
|
||||
type: CALCULATED
|
||||
key: 'nginx.cache.hits.1m.[{#HOST_SITE}]'
|
||||
units: hits
|
||||
params: 'sum(//nginx.cache.hit.flag.[{#HOST_SITE}],1m)'
|
||||
tags:
|
||||
- tag: Insight
|
||||
value: cache
|
||||
- tag: Insight
|
||||
value: performance
|
||||
- name: 'Insight: Cache HITs nos Ultimos 5 minuto {#HOST_SITE}'
|
||||
type: CALCULATED
|
||||
key: 'nginx.cache.hits.5m.[{#HOST_SITE}]'
|
||||
delay: 4m
|
||||
units: hits
|
||||
params: 'sum(//nginx.cache.hit.flag.[{#HOST_SITE}],5m)'
|
||||
tags:
|
||||
- tag: Insight
|
||||
value: cache
|
||||
- tag: Insight
|
||||
value: performance
|
||||
- name: 'Insight: Cache HITs nos Ultimos 15 minuto {#HOST_SITE}'
|
||||
type: CALCULATED
|
||||
key: 'nginx.cache.hits.15m.[{#HOST_SITE}]'
|
||||
delay: 14m
|
||||
units: hits
|
||||
params: 'sum(//nginx.cache.hit.flag.[{#HOST_SITE}],15m)'
|
||||
tags:
|
||||
- tag: Insight
|
||||
value: cache
|
||||
- tag: Insight
|
||||
value: performance
|
||||
- name: 'Insight: Cache HITs nos Ultimos 24 hrs {#HOST_SITE}'
|
||||
type: CALCULATED
|
||||
key: 'nginx.cache.hits.24h.[{#HOST_SITE}]'
|
||||
delay: 1h
|
||||
units: hits
|
||||
params: 'sum(//nginx.cache.hit.flag.[{#HOST_SITE}],24h)'
|
||||
tags:
|
||||
- tag: Insight
|
||||
value: cache
|
||||
- tag: Insight
|
||||
value: performance
|
||||
- name: 'Insight: Cache MISS no Ultimo minuto {#HOST_SITE}'
|
||||
type: CALCULATED
|
||||
key: 'nginx.cache.miss.1m.[{#HOST_SITE}]'
|
||||
units: miss
|
||||
params: 'sum(//nginx.cache.miss.flag.[{#HOST_SITE}],1m)'
|
||||
tags:
|
||||
- tag: Insight
|
||||
value: cache
|
||||
- tag: Insight
|
||||
value: performance
|
||||
- name: 'Insight: Cache MISS no Ultimos 5 minuto {#HOST_SITE}'
|
||||
type: CALCULATED
|
||||
key: 'nginx.cache.miss.5m.[{#HOST_SITE}]'
|
||||
delay: 4m
|
||||
units: miss
|
||||
params: 'sum(//nginx.cache.miss.flag.[{#HOST_SITE}],5m)'
|
||||
tags:
|
||||
- tag: Insight
|
||||
value: cache
|
||||
- tag: Insight
|
||||
value: performance
|
||||
- name: 'Insight: Cache MISS no Ultimos 15 minuto {#HOST_SITE}'
|
||||
type: CALCULATED
|
||||
key: 'nginx.cache.miss.15m.[{#HOST_SITE}]'
|
||||
delay: 14m
|
||||
units: miss
|
||||
params: 'sum(//nginx.cache.miss.flag.[{#HOST_SITE}],15m)'
|
||||
tags:
|
||||
- tag: Insight
|
||||
value: cache
|
||||
- tag: Insight
|
||||
value: performance
|
||||
- name: 'Insight: Cache MISS no Ultimos 24 horas {#HOST_SITE}'
|
||||
type: CALCULATED
|
||||
key: 'nginx.cache.miss.24h.[{#HOST_SITE}]'
|
||||
delay: 1h
|
||||
units: miss
|
||||
params: 'sum(//nginx.cache.miss.flag.[{#HOST_SITE}],24h)'
|
||||
tags:
|
||||
- tag: Insight
|
||||
value: cache
|
||||
- tag: Insight
|
||||
value: performance
|
||||
- name: 'Nginx: Cache MISS Flag for {#HOST_SITE}'
|
||||
type: DEPENDENT
|
||||
key: 'nginx.cache.miss.flag.[{#HOST_SITE}]'
|
||||
preprocessing:
|
||||
- type: REGEX
|
||||
parameters:
|
||||
- 'upstream_cache_status":"MISS"'
|
||||
- '1'
|
||||
error_handler: DISCARD_VALUE
|
||||
master_item:
|
||||
key: 'log[/var/log/nginx/{#HOST_SITE}.access.log]'
|
||||
tags:
|
||||
- tag: Insight
|
||||
value: cache
|
||||
- tag: Insight
|
||||
value: performance
|
||||
- name: 'Insight: Cache Miss Ratio (Ultimo 1m) (%) {#HOST_SITE}'
|
||||
type: CALCULATED
|
||||
key: 'nginx.cache.miss.ratio.1m.[{#HOST_SITE}]'
|
||||
value_type: FLOAT
|
||||
units: '%'
|
||||
params: '(last(//nginx.cache.miss.1m.[{#HOST_SITE}]) * 100) / (last(//nginx.cache.hits.1m.[{#HOST_SITE}]) + last(//nginx.cache.miss.1m.[{#HOST_SITE}]) + (last(//nginx.cache.hits.1m.[{#HOST_SITE}]) + last(//nginx.cache.miss.1m.[{#HOST_SITE}]) = 0))'
|
||||
tags:
|
||||
- tag: Insight
|
||||
value: carga
|
||||
- name: 'Insight: {#HOST_SITE} Marcações Usuario Online'
|
||||
type: DEPENDENT
|
||||
key: 'nginx.log.user_status.list[{#HOST_SITE}}]'
|
||||
value_type: TEXT
|
||||
preprocessing:
|
||||
- type: JAVASCRIPT
|
||||
parameters:
|
||||
- |
|
||||
// Versão compatível com JavaScript antigo (ES5) - Saída em Texto Puro
|
||||
// Usamos um objeto para garantir que cada usuário seja único.
|
||||
var uniqueUsers = {};
|
||||
|
||||
var remoteUserRegex = /"remote_user":"([a-zA-Z0-9._-]+)"/g;
|
||||
var cookieUserRegex = /nc_username=([a-zA-Z0-9._-]+);/g;
|
||||
var urlUserRegex = /\/remote\.php\/dav\/files\/([a-zA-Z0-9._-]+)\//g;
|
||||
|
||||
var lines = value.split('\n');
|
||||
|
||||
for (var i = 0; i < lines.length; i++) {
|
||||
var line = lines[i];
|
||||
var match;
|
||||
|
||||
// Função auxiliar para adicionar usuários ao nosso objeto de unicidade
|
||||
function findAndAdd(regex) {
|
||||
while ((match = regex.exec(line)) !== null) {
|
||||
if (match[1] && match[1].length > 0) {
|
||||
// Adiciona o usuário completo como uma chave do objeto.
|
||||
uniqueUsers[match[1]] = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
findAndAdd(remoteUserRegex);
|
||||
findAndAdd(cookieUserRegex);
|
||||
findAndAdd(urlUserRegex);
|
||||
}
|
||||
|
||||
// Pega todas as chaves do objeto para formar o array final de usuários únicos.
|
||||
var userArray = Object.keys(uniqueUsers);
|
||||
|
||||
// --- LINHA ALTERADA ---
|
||||
// Une todos os elementos do array em uma única string,
|
||||
// separando cada um com um caractere de quebra de linha ('\n').
|
||||
return userArray.join('\n');
|
||||
master_item:
|
||||
key: 'log[/var/log/nginx/{#HOST_SITE}.access.log]'
|
||||
tags:
|
||||
- tag: Insight
|
||||
value: performance
|
||||
- name: 'Nginx: Requests Excelentes por minuto {#HOST_SITE}'
|
||||
type: CALCULATED
|
||||
key: 'nginx.requests.excellent.count.1m.[{#HOST_SITE}]'
|
||||
units: reqs/min
|
||||
params: |
|
||||
last(//nginx.request_time.count.0-20ms.1m.[{#HOST_SITE}]) +
|
||||
last(//nginx.request_time.count.21-50ms.1m.[{#HOST_SITE}]) +
|
||||
last(//nginx.request_time.count.51-100ms.1m.[{#HOST_SITE}]) +
|
||||
last(//nginx.request_time.count.101-200ms.1m.[{#HOST_SITE}])
|
||||
tags:
|
||||
- tag: Insight
|
||||
value: cache
|
||||
- tag: Insight
|
||||
value: performance
|
||||
- name: 'Insight: Requisição nos Ultimos 5 Minuto em {#HOST_SITE}'
|
||||
type: CALCULATED
|
||||
key: 'nginx.requests.per_5minute[{#HOST_SITE}]'
|
||||
delay: 4m
|
||||
units: requests
|
||||
params: 'count(//log[/var/log/nginx/{#HOST_SITE}.access.log],5m)'
|
||||
tags:
|
||||
- tag: Insight
|
||||
value: carga
|
||||
- name: 'Insight: Requisição nos Ultimos 15 Minuto em {#HOST_SITE}'
|
||||
type: CALCULATED
|
||||
key: 'nginx.requests.per_15minute[{#HOST_SITE}]'
|
||||
delay: 14m
|
||||
units: requests
|
||||
params: 'count(//log[/var/log/nginx/{#HOST_SITE}.access.log],15m)'
|
||||
tags:
|
||||
- tag: Insight
|
||||
value: carga
|
||||
- name: 'Insight: Requisição nos Ultimos 24 horas em {#HOST_SITE}'
|
||||
type: CALCULATED
|
||||
key: 'nginx.requests.per_24h[{#HOST_SITE}]'
|
||||
delay: 1h
|
||||
units: requests
|
||||
params: 'count(//log[/var/log/nginx/{#HOST_SITE}.access.log],24h)'
|
||||
tags:
|
||||
- tag: Insight
|
||||
value: carga
|
||||
- name: 'Insight: Requisição no Ultimo 1 Minuto em {#HOST_SITE}'
|
||||
type: CALCULATED
|
||||
key: 'nginx.requests.per_minute[{#HOST_SITE}]'
|
||||
units: requests
|
||||
params: 'count(//log[/var/log/nginx/{#HOST_SITE}.access.log],1m)'
|
||||
tags:
|
||||
- tag: Insight
|
||||
value: carga
|
||||
- name: 'Insight: Média de Tempo de Resposta (1m) {#HOST_SITE}'
|
||||
type: CALCULATED
|
||||
key: 'nginx.request_time.avg.1m.[{#HOST_SITE}]'
|
||||
value_type: FLOAT
|
||||
units: ms
|
||||
params: 'avg(//nginx.request_time.[{#HOST_SITE}],1m)'
|
||||
tags:
|
||||
- tag: Insight
|
||||
value: carga
|
||||
- name: 'Insight: Média de Tempo de Resposta (5m) {#HOST_SITE}'
|
||||
type: CALCULATED
|
||||
key: 'nginx.request_time.avg.5m.[{#HOST_SITE}]'
|
||||
delay: 4m
|
||||
value_type: FLOAT
|
||||
units: ms
|
||||
params: 'avg(//nginx.request_time.[{#HOST_SITE}],5m)'
|
||||
tags:
|
||||
- tag: Insight
|
||||
value: carga
|
||||
- name: 'Insight: Média de Tempo de Resposta (15m) {#HOST_SITE}'
|
||||
type: CALCULATED
|
||||
key: 'nginx.request_time.avg.15m.[{#HOST_SITE}]'
|
||||
value_type: FLOAT
|
||||
units: ms
|
||||
params: 'avg(//nginx.request_time.[{#HOST_SITE}],15m)'
|
||||
tags:
|
||||
- tag: Insight
|
||||
value: carga
|
||||
- name: 'Nginx: RTime Flag (0-20ms) {#HOST_SITE}'
|
||||
type: DEPENDENT
|
||||
key: 'nginx.request_time.flag.0-20ms.[{#HOST_SITE}]'
|
||||
preprocessing:
|
||||
- type: JAVASCRIPT
|
||||
parameters:
|
||||
- |
|
||||
try {
|
||||
// O valor chega em segundos (ex: 0.015), convertemos para milissegundos.
|
||||
var value_ms = parseFloat(value) * 1000;
|
||||
|
||||
// Verifica se o valor está na faixa de 0 a 20ms.
|
||||
if (value_ms >= 0 && value_ms <= 20) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
// Se não estiver na faixa, retorna null para o Zabbix descartar.
|
||||
return 0;
|
||||
} catch (e) {
|
||||
// Se der qualquer erro, também descarta.
|
||||
return 0;
|
||||
}
|
||||
master_item:
|
||||
key: 'nginx.request_time.[{#HOST_SITE}]'
|
||||
tags:
|
||||
- tag: Insight
|
||||
value: cache
|
||||
- tag: Insight
|
||||
value: performance
|
||||
- name: 'Nginx: RTime Flag (21-50ms) {#HOST_SITE}'
|
||||
type: DEPENDENT
|
||||
key: 'nginx.request_time.flag.21-50ms.[{#HOST_SITE}]'
|
||||
preprocessing:
|
||||
- type: JAVASCRIPT
|
||||
parameters:
|
||||
- |
|
||||
try {
|
||||
// O valor chega em segundos (ex: 0.015), convertemos para milissegundos.
|
||||
var value_ms = parseFloat(value) * 1000;
|
||||
|
||||
// Verifica se o valor está na faixa de 0 a 20ms.
|
||||
if (value_ms >= 21 && value_ms <= 50) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
// Se não estiver na faixa, retorna null para o Zabbix descartar.
|
||||
return 0;
|
||||
} catch (e) {
|
||||
// Se der qualquer erro, também descarta.
|
||||
return 0;
|
||||
}
|
||||
master_item:
|
||||
key: 'nginx.request_time.[{#HOST_SITE}]'
|
||||
tags:
|
||||
- tag: Insight
|
||||
value: cache
|
||||
- tag: Insight
|
||||
value: performance
|
||||
- name: 'Nginx: RTime Flag (51-100ms) {#HOST_SITE}'
|
||||
type: DEPENDENT
|
||||
key: 'nginx.request_time.flag.51-100ms.[{#HOST_SITE}]'
|
||||
preprocessing:
|
||||
- type: JAVASCRIPT
|
||||
parameters:
|
||||
- |
|
||||
try {
|
||||
// O valor chega em segundos (ex: 0.015), convertemos para milissegundos.
|
||||
var value_ms = parseFloat(value) * 1000;
|
||||
|
||||
// Verifica se o valor está na faixa de 0 a 20ms.
|
||||
if (value_ms >= 51 && value_ms <= 100) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
// Se não estiver na faixa, retorna null para o Zabbix descartar.
|
||||
return 0;
|
||||
} catch (e) {
|
||||
// Se der qualquer erro, também descarta.
|
||||
return 0;
|
||||
}
|
||||
master_item:
|
||||
key: 'nginx.request_time.[{#HOST_SITE}]'
|
||||
tags:
|
||||
- tag: Insight
|
||||
value: cache
|
||||
- tag: Insight
|
||||
value: performance
|
||||
- name: 'Nginx: RTime Flag (201-300ms) {#HOST_SITE}'
|
||||
type: DEPENDENT
|
||||
key: 'nginx.request_time.flag.201-300ms.[{#HOST_SITE}]'
|
||||
preprocessing:
|
||||
- type: JAVASCRIPT
|
||||
parameters:
|
||||
- |
|
||||
try {
|
||||
// O valor chega em segundos (ex: 0.015), convertemos para milissegundos.
|
||||
var value_ms = parseFloat(value) * 1000;
|
||||
|
||||
// Verifica se o valor está na faixa de 0 a 20ms.
|
||||
if (value_ms >= 201 && value_ms <= 300) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
// Se não estiver na faixa, retorna null para o Zabbix descartar.
|
||||
return 0;
|
||||
} catch (e) {
|
||||
// Se der qualquer erro, também descarta.
|
||||
return 0;
|
||||
}
|
||||
master_item:
|
||||
key: 'nginx.request_time.[{#HOST_SITE}]'
|
||||
tags:
|
||||
- tag: Insight
|
||||
value: cache
|
||||
- tag: Insight
|
||||
value: performance
|
||||
- name: 'Nginx: RTime Flag (301-400ms) {#HOST_SITE}'
|
||||
type: DEPENDENT
|
||||
key: 'nginx.request_time.flag.301-400ms.[{#HOST_SITE}]'
|
||||
preprocessing:
|
||||
- type: JAVASCRIPT
|
||||
parameters:
|
||||
- |
|
||||
try {
|
||||
// O valor chega em segundos (ex: 0.015), convertemos para milissegundos.
|
||||
var value_ms = parseFloat(value) * 1000;
|
||||
|
||||
// Verifica se o valor está na faixa de 0 a 20ms.
|
||||
if (value_ms >= 301 && value_ms <= 400) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
// Se não estiver na faixa, retorna null para o Zabbix descartar.
|
||||
return 0;
|
||||
} catch (e) {
|
||||
// Se der qualquer erro, também descarta.
|
||||
return 0;
|
||||
}
|
||||
master_item:
|
||||
key: 'nginx.request_time.[{#HOST_SITE}]'
|
||||
tags:
|
||||
- tag: Insight
|
||||
value: cache
|
||||
- tag: Insight
|
||||
value: performance
|
||||
- name: 'Nginx: RTime Flag (401-500ms) {#HOST_SITE}'
|
||||
type: DEPENDENT
|
||||
key: 'nginx.request_time.flag.401-500ms.[{#HOST_SITE}]'
|
||||
preprocessing:
|
||||
- type: JAVASCRIPT
|
||||
parameters:
|
||||
- |
|
||||
try {
|
||||
// O valor chega em segundos (ex: 0.015), convertemos para milissegundos.
|
||||
var value_ms = parseFloat(value) * 1000;
|
||||
|
||||
// Verifica se o valor está na faixa de 0 a 20ms.
|
||||
if (value_ms >= 401 && value_ms <= 500) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
// Se não estiver na faixa, retorna null para o Zabbix descartar.
|
||||
return 0;
|
||||
} catch (e) {
|
||||
// Se der qualquer erro, também descarta.
|
||||
return 0;
|
||||
}
|
||||
master_item:
|
||||
key: 'nginx.request_time.[{#HOST_SITE}]'
|
||||
tags:
|
||||
- tag: Insight
|
||||
value: cache
|
||||
- tag: Insight
|
||||
value: performance
|
||||
- name: 'Nginx: RTime Flag (501-600ms) {#HOST_SITE}'
|
||||
type: DEPENDENT
|
||||
key: 'nginx.request_time.flag.501-600ms.[{#HOST_SITE}]'
|
||||
preprocessing:
|
||||
- type: JAVASCRIPT
|
||||
parameters:
|
||||
- |
|
||||
try {
|
||||
// O valor chega em segundos (ex: 0.015), convertemos para milissegundos.
|
||||
var value_ms = parseFloat(value) * 1000;
|
||||
|
||||
// Verifica se o valor está na faixa de 0 a 20ms.
|
||||
if (value_ms >= 501 && value_ms <= 600) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
// Se não estiver na faixa, retorna null para o Zabbix descartar.
|
||||
return 0;
|
||||
} catch (e) {
|
||||
// Se der qualquer erro, também descarta.
|
||||
return 0;
|
||||
}
|
||||
master_item:
|
||||
key: 'nginx.request_time.[{#HOST_SITE}]'
|
||||
tags:
|
||||
- tag: Insight
|
||||
value: cache
|
||||
- tag: Insight
|
||||
value: performance
|
||||
- name: 'Nginx: RTime Flag (601-700ms) {#HOST_SITE}'
|
||||
type: DEPENDENT
|
||||
key: 'nginx.request_time.flag.601-700ms.[{#HOST_SITE}]'
|
||||
preprocessing:
|
||||
- type: JAVASCRIPT
|
||||
parameters:
|
||||
- |
|
||||
try {
|
||||
// O valor chega em segundos (ex: 0.015), convertemos para milissegundos.
|
||||
var value_ms = parseFloat(value) * 1000;
|
||||
|
||||
// Verifica se o valor está na faixa de 0 a 20ms.
|
||||
if (value_ms >= 601 && value_ms <= 700) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
// Se não estiver na faixa, retorna null para o Zabbix descartar.
|
||||
return 0;
|
||||
} catch (e) {
|
||||
// Se der qualquer erro, também descarta.
|
||||
return 0;
|
||||
}
|
||||
master_item:
|
||||
key: 'nginx.request_time.[{#HOST_SITE}]'
|
||||
tags:
|
||||
- tag: Insight
|
||||
value: cache
|
||||
- tag: Insight
|
||||
value: performance
|
||||
- name: 'Nginx: RTime Flag (701-800ms) {#HOST_SITE}'
|
||||
type: DEPENDENT
|
||||
key: 'nginx.request_time.flag.701-800ms.[{#HOST_SITE}]'
|
||||
preprocessing:
|
||||
- type: JAVASCRIPT
|
||||
parameters:
|
||||
- |
|
||||
try {
|
||||
// O valor chega em segundos (ex: 0.015), convertemos para milissegundos.
|
||||
var value_ms = parseFloat(value) * 1000;
|
||||
|
||||
// Verifica se o valor está na faixa de 0 a 20ms.
|
||||
if (value_ms >= 701 && value_ms <= 800) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
// Se não estiver na faixa, retorna null para o Zabbix descartar.
|
||||
return 0;
|
||||
} catch (e) {
|
||||
// Se der qualquer erro, também descarta.
|
||||
return 0;
|
||||
}
|
||||
master_item:
|
||||
key: 'nginx.request_time.[{#HOST_SITE}]'
|
||||
tags:
|
||||
- tag: Insight
|
||||
value: cache
|
||||
- tag: Insight
|
||||
value: performance
|
||||
- name: 'Nginx: RTime Flag (801-900ms) {#HOST_SITE}'
|
||||
type: DEPENDENT
|
||||
key: 'nginx.request_time.flag.801-900ms.[{#HOST_SITE}]'
|
||||
preprocessing:
|
||||
- type: JAVASCRIPT
|
||||
parameters:
|
||||
- |
|
||||
try {
|
||||
// O valor chega em segundos (ex: 0.015), convertemos para milissegundos.
|
||||
var value_ms = parseFloat(value) * 1000;
|
||||
|
||||
// Verifica se o valor está na faixa de 0 a 20ms.
|
||||
if (value_ms >= 801 && value_ms <= 900) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
// Se não estiver na faixa, retorna null para o Zabbix descartar.
|
||||
return 0;
|
||||
} catch (e) {
|
||||
// Se der qualquer erro, também descarta.
|
||||
return 0;
|
||||
}
|
||||
master_item:
|
||||
key: 'nginx.request_time.[{#HOST_SITE}]'
|
||||
tags:
|
||||
- tag: Insight
|
||||
value: cache
|
||||
- tag: Insight
|
||||
value: performance
|
||||
- name: 'Nginx: RTime Flag (1001-2000ms) {#HOST_SITE}'
|
||||
type: DEPENDENT
|
||||
key: 'nginx.request_time.flag.1001-2000ms.[{#HOST_SITE}]'
|
||||
preprocessing:
|
||||
- type: JAVASCRIPT
|
||||
parameters:
|
||||
- |
|
||||
try {
|
||||
// O valor chega em segundos (ex: 0.015), convertemos para milissegundos.
|
||||
var value_ms = parseFloat(value) * 1000;
|
||||
|
||||
// Verifica se o valor está na faixa de 0 a 20ms.
|
||||
if (value_ms >= 1001 && value_ms <= 2000) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
// Se não estiver na faixa, retorna null para o Zabbix descartar.
|
||||
return 0;
|
||||
} catch (e) {
|
||||
// Se der qualquer erro, também descarta.
|
||||
return 0;
|
||||
}
|
||||
master_item:
|
||||
key: 'nginx.request_time.[{#HOST_SITE}]'
|
||||
tags:
|
||||
- tag: Insight
|
||||
value: cache
|
||||
- tag: Insight
|
||||
value: performance
|
||||
- name: 'Nginx: RTime Flag (>3001ms) {#HOST_SITE}'
|
||||
type: DEPENDENT
|
||||
key: 'nginx.request_time.flag.3001ms.[{#HOST_SITE}]'
|
||||
preprocessing:
|
||||
- type: JAVASCRIPT
|
||||
parameters:
|
||||
- |
|
||||
try {
|
||||
// O valor chega em segundos (ex: 0.015), convertemos para milissegundos.
|
||||
var value_ms = parseFloat(value) * 1000;
|
||||
|
||||
// Verifica se o valor está na faixa de 0 a 20ms.
|
||||
if (value_ms >= 3001) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
// Se não estiver na faixa, retorna null para o Zabbix descartar.
|
||||
return 0;
|
||||
} catch (e) {
|
||||
// Se der qualquer erro, também descarta.
|
||||
return 0;
|
||||
}
|
||||
master_item:
|
||||
key: 'nginx.request_time.[{#HOST_SITE}]'
|
||||
tags:
|
||||
- tag: Insight
|
||||
value: cache
|
||||
- tag: Insight
|
||||
value: performance
|
||||
- name: 'Insight: Tempo de Resposta Total {#HOST_SITE}'
|
||||
type: DEPENDENT
|
||||
key: 'nginx.request_time.[{#HOST_SITE}]'
|
||||
value_type: FLOAT
|
||||
units: s
|
||||
preprocessing:
|
||||
- type: JAVASCRIPT
|
||||
parameters:
|
||||
- |
|
||||
try {
|
||||
// A variável 'value' contém a linha de log completa.
|
||||
// A regex procura por "request_time": e captura o número que vem depois.
|
||||
var regex = /"request_time":(\d+\.?\d*)/;
|
||||
var match = value.match(regex);
|
||||
|
||||
// Se encontrar, match[1] conterá apenas o número (ex: "0.282").
|
||||
if (match && match[1]) {
|
||||
return match[1];
|
||||
}
|
||||
|
||||
// Se não encontrar, descarta o valor.
|
||||
return null;
|
||||
} catch (e) {
|
||||
// Se houver qualquer erro, também descarta.
|
||||
return null;
|
||||
}
|
||||
master_item:
|
||||
key: 'log[/var/log/nginx/{#HOST_SITE}.access.log]'
|
||||
tags:
|
||||
- tag: Insight
|
||||
value: 'access log'
|
||||
- name: 'Nginx: URI da Requisição {#HOST_SITE}'
|
||||
type: DEPENDENT
|
||||
key: 'nginx.request_uri.[{#HOST_SITE}]'
|
||||
value_type: TEXT
|
||||
preprocessing:
|
||||
- type: JAVASCRIPT
|
||||
parameters:
|
||||
- |
|
||||
try {
|
||||
var regex = /"request_uri":"([^"]+)"/;
|
||||
var match = value.match(regex);
|
||||
if (match && match[1]) {
|
||||
return match[1];
|
||||
}
|
||||
return null;
|
||||
} catch (e) {
|
||||
return null;
|
||||
}
|
||||
master_item:
|
||||
key: 'log[/var/log/nginx/{#HOST_SITE}.access.log]'
|
||||
tags:
|
||||
- tag: Insight
|
||||
value: cache
|
||||
- tag: Insight
|
||||
value: performance
|
||||
graph_prototypes:
|
||||
- name: 'Insight: Cache HITS {#HOST_SITE}'
|
||||
yaxismax: '0'
|
||||
percent_right: '20'
|
||||
ymin_type_1: FIXED
|
||||
graph_items:
|
||||
- color: 199C0D
|
||||
calc_fnc: ALL
|
||||
item:
|
||||
host: srvproxy001
|
||||
key: 'nginx.cache.hits.5m.[{#HOST_SITE}]'
|
||||
- sortorder: '1'
|
||||
color: F63100
|
||||
calc_fnc: ALL
|
||||
item:
|
||||
host: srvproxy001
|
||||
key: 'nginx.cache.hits.15m.[{#HOST_SITE}]'
|
||||
- sortorder: '2'
|
||||
color: 2774A4
|
||||
calc_fnc: ALL
|
||||
item:
|
||||
host: srvproxy001
|
||||
key: 'nginx.cache.hits.24h.[{#HOST_SITE}]'
|
||||
- sortorder: '3'
|
||||
color: F7941D
|
||||
calc_fnc: ALL
|
||||
item:
|
||||
host: srvproxy001
|
||||
key: 'nginx.cache.hits.1m.[{#HOST_SITE}]'
|
||||
- name: 'Insight: Cache HIT vs MISS {#HOST_SITE}'
|
||||
show_work_period: 'NO'
|
||||
show_triggers: 'NO'
|
||||
type: PIE
|
||||
graph_items:
|
||||
- color: F63100
|
||||
item:
|
||||
host: srvproxy001
|
||||
key: 'nginx.cache.miss.ratio.1m.[{#HOST_SITE}]'
|
||||
- sortorder: '1'
|
||||
color: 199C0D
|
||||
item:
|
||||
host: srvproxy001
|
||||
key: 'nginx.cache.hit.ratio.1m.[{#HOST_SITE}]'
|
||||
- name: 'Insight: Cache MISS {#HOST_SITE}'
|
||||
yaxismax: '0'
|
||||
percent_right: '20'
|
||||
ymin_type_1: FIXED
|
||||
graph_items:
|
||||
- color: 199C0D
|
||||
calc_fnc: ALL
|
||||
item:
|
||||
host: srvproxy001
|
||||
key: 'nginx.cache.miss.1m.[{#HOST_SITE}]'
|
||||
- sortorder: '1'
|
||||
color: F63100
|
||||
calc_fnc: ALL
|
||||
item:
|
||||
host: srvproxy001
|
||||
key: 'nginx.cache.miss.5m.[{#HOST_SITE}]'
|
||||
- sortorder: '2'
|
||||
color: 2774A4
|
||||
calc_fnc: ALL
|
||||
item:
|
||||
host: srvproxy001
|
||||
key: 'nginx.cache.miss.15m.[{#HOST_SITE}]'
|
||||
- sortorder: '3'
|
||||
color: F7941D
|
||||
calc_fnc: ALL
|
||||
item:
|
||||
host: srvproxy001
|
||||
key: 'nginx.cache.miss.24h.[{#HOST_SITE}]'
|
||||
- name: 'Insight: Requisições {#HOST_SITE}'
|
||||
yaxismax: '0'
|
||||
ymin_type_1: FIXED
|
||||
graph_items:
|
||||
- color: F63100
|
||||
yaxisside: RIGHT
|
||||
calc_fnc: ALL
|
||||
item:
|
||||
host: srvproxy001
|
||||
key: 'nginx.requests.per_minute[{#HOST_SITE}]'
|
||||
- sortorder: '1'
|
||||
color: 199C0D
|
||||
calc_fnc: ALL
|
||||
item:
|
||||
host: srvproxy001
|
||||
key: 'nginx.requests.per_5minute[{#HOST_SITE}]'
|
||||
- sortorder: '2'
|
||||
color: 2774A4
|
||||
calc_fnc: ALL
|
||||
item:
|
||||
host: srvproxy001
|
||||
key: 'nginx.requests.per_15minute[{#HOST_SITE}]'
|
||||
- sortorder: '3'
|
||||
color: F7941D
|
||||
calc_fnc: ALL
|
||||
item:
|
||||
host: srvproxy001
|
||||
key: 'nginx.requests.per_24h[{#HOST_SITE}]'
|
||||
- name: 'Insight: Saúde do Site {#HOST_SITE}'
|
||||
show_work_period: 'NO'
|
||||
graph_items:
|
||||
- color: 199C0D
|
||||
calc_fnc: ALL
|
||||
item:
|
||||
host: srvproxy001
|
||||
key: 'net.tcp.service[http,"{$NGINX.STUB_STATUS.HOST}","{$NGINX.STUB_STATUS.PORT}"]'
|
||||
- sortorder: '1'
|
||||
color: F63100
|
||||
calc_fnc: ALL
|
||||
item:
|
||||
host: srvproxy001
|
||||
key: 'nginx.cache.hit.ratio.1m.[{#HOST_SITE}]'
|
||||
- sortorder: '2'
|
||||
color: F7941D
|
||||
calc_fnc: ALL
|
||||
item:
|
||||
host: srvproxy001
|
||||
key: 'nginx.request_time.avg.1m.[{#HOST_SITE}]'
|
||||
- name: 'Insight: Tempo de Resposta vs Requisições {#HOST_SITE}'
|
||||
ymin_type_1: FIXED
|
||||
graph_items:
|
||||
- sortorder: '1'
|
||||
color: F63100
|
||||
yaxisside: RIGHT
|
||||
calc_fnc: ALL
|
||||
item:
|
||||
host: srvproxy001
|
||||
key: 'nginx.requests.per_minute[{#HOST_SITE}]'
|
||||
- sortorder: '2'
|
||||
drawtype: FILLED_REGION
|
||||
color: 199C0D
|
||||
calc_fnc: ALL
|
||||
item:
|
||||
host: srvproxy001
|
||||
key: 'nginx.request_time.[{#HOST_SITE}]'
|
||||
- name: 'Insight: Tempos de Resposta {#HOST_SITE}'
|
||||
percent_right: '20'
|
||||
ymin_type_1: FIXED
|
||||
graph_items:
|
||||
- color: 199C0D
|
||||
calc_fnc: ALL
|
||||
item:
|
||||
host: srvproxy001
|
||||
key: 'nginx.request_time.avg.1m.[{#HOST_SITE}]'
|
||||
- sortorder: '1'
|
||||
color: F63100
|
||||
calc_fnc: ALL
|
||||
item:
|
||||
host: srvproxy001
|
||||
key: 'nginx.request_time.avg.5m.[{#HOST_SITE}]'
|
||||
- sortorder: '2'
|
||||
color: 2774A4
|
||||
calc_fnc: ALL
|
||||
item:
|
||||
host: srvproxy001
|
||||
key: 'nginx.request_time.avg.15m.[{#HOST_SITE}]'
|
||||
preprocessing:
|
||||
- type: JAVASCRIPT
|
||||
parameters:
|
||||
- |
|
||||
// A variável 'value' é a string completa do UserParameter, contendo caminhos
|
||||
// separados por vírgula, espaço e/ou quebra de linha.
|
||||
// A Regex /[\s,]+/ divide a string em:
|
||||
// - Vírgulas (,)
|
||||
// - Espaços (incluindo múltiplos)
|
||||
// - Quebras de linha (\n, \r)
|
||||
// O filter(Boolean) remove quaisquer entradas vazias que o split possa gerar.
|
||||
var full_paths = value.trim().split(/[\s,]+/).filter(Boolean);
|
||||
|
||||
var lld_data = [];
|
||||
|
||||
// Regex para extrair o nome do site:
|
||||
// ^ -> Início do item (após o split)
|
||||
// (.+) -> Captura o nome do site (o que for que esteja lá)
|
||||
var regex = /^\/var\/log\/nginx\/(.+)\.access\.log$/;
|
||||
|
||||
// Itera sobre todos os caminhos.
|
||||
for (var i = 0; i < full_paths.length; i++) {
|
||||
var path = full_paths[i];
|
||||
|
||||
// Aplica a regex em cada item.
|
||||
var match = path.match(regex);
|
||||
|
||||
// match[1] contém o nome do site capturado em (.+).
|
||||
if (match && match[1]) {
|
||||
lld_data.push({
|
||||
"{#HOST_SITE}": match[1]
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// Retorna o JSON LLD final.
|
||||
return JSON.stringify({ "data": lld_data });
|
||||
macros:
|
||||
- macro: '{$NGINX.STUB_STATUS.HOST}'
|
||||
value: 172.16.254.1
|
||||
description: 'O hostname ou endereço IP do host Nginx ou do contêiner Nginx com `stub_status`.'
|
||||
- macro: '{$NGINX.STUB_STATUS.PATH}'
|
||||
value: nginx_status
|
||||
description: 'The path of the `Nginx stub_status` page.'
|
||||
- macro: '{$NGINX.STUB_STATUS.PORT}'
|
||||
value: '8080'
|
||||
description: 'The port of the `Nginx stub_status` host or container.'
|
||||
inventory_mode: AUTOMATIC
|
||||
inventory:
|
||||
name: srvproxy001
|
||||
os: 'Linux version 6.1.0-39-amd64 (debian-kernel@lists.debian.org) (gcc-12 (Debian 12.2.0-14+deb12u1) 12.2.0, GNU ld (GNU Binutils fo'
|
||||
Loading…
Reference in New Issue