diff --git a/extract_nginx_config.py b/extract_nginx_config.py new file mode 100644 index 0000000..3149e72 --- /dev/null +++ b/extract_nginx_config.py @@ -0,0 +1,81 @@ +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 ") + else: + extract_nginx_config(sys.argv[1], sys.argv[2]) diff --git a/merge_nginx_templates.py b/merge_nginx_templates.py new file mode 100644 index 0000000..22b907b --- /dev/null +++ b/merge_nginx_templates.py @@ -0,0 +1,69 @@ +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 ") + else: + merge_templates(sys.argv[1], sys.argv[2], sys.argv[3]) diff --git a/template_nginx_custom_extracted.yaml b/template_nginx_custom_extracted.yaml new file mode 100644 index 0000000..f248be6 --- /dev/null +++ b/template_nginx_custom_extracted.yaml @@ -0,0 +1,749 @@ +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" diff --git a/templates_gold/nginx_agent/agent_execution_plan.md b/templates_gold/nginx_agent/agent_execution_plan.md new file mode 100644 index 0000000..9a925a3 --- /dev/null +++ b/templates_gold/nginx_agent/agent_execution_plan.md @@ -0,0 +1,75 @@ +# 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. diff --git a/templates_gold/nginx_agent/generate_nginx_satellite.py b/templates_gold/nginx_agent/generate_nginx_satellite.py new file mode 100644 index 0000000..7a07060 --- /dev/null +++ b/templates_gold/nginx_agent/generate_nginx_satellite.py @@ -0,0 +1,138 @@ +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") diff --git a/templates_gold/nginx_agent/nginx_best_practices.md b/templates_gold/nginx_agent/nginx_best_practices.md new file mode 100644 index 0000000..d4e767c --- /dev/null +++ b/templates_gold/nginx_agent/nginx_best_practices.md @@ -0,0 +1,316 @@ +# 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. diff --git a/templates_gold/nginx_agent/template_app_nginx_agent_gold.yaml b/templates_gold/nginx_agent/template_app_nginx_agent_gold.yaml new file mode 100644 index 0000000..43f6a03 --- /dev/null +++ b/templates_gold/nginx_agent/template_app_nginx_agent_gold.yaml @@ -0,0 +1,1365 @@ +zabbix_export: + version: '7.0' + template_groups: + - uuid: a571c0d144b14fd4a87a9d9b2aa9fcd6 + name: Templates/Applications + templates: + - uuid: 27f6424905884dbb96ab9210d987a56c + template: Nginx by Zabbix agent + name: Nginx by Zabbix agent (Gold) + description: 'Get metrics from stub status module using Zabbix agent running on + Linux + + https://nginx.ru/en/docs/http/ngx_http_stub_status_module.html + + + You can discuss this template or leave feedback on our forum https://www.zabbix.com/forum/zabbix-suggestions-and-feedback/384765-discussion-thread-for-official-zabbix-template-nginx + + + Generated by official Zabbix template tool "Templator" + + ' + vendor: + name: Zabbix + version: 7.0-1 + groups: + - name: Templates/Applications + items: + - uuid: 75a7795df3034835bcfd143f7c3e9b94 + name: Service response time + key: net.tcp.service.perf[http,"{$NGINX.STUB_STATUS.HOST}","{$NGINX.STUB_STATUS.PORT}"] + value_type: FLOAT + units: s + tags: + - tag: component + value: application + - tag: component + value: health + - uuid: f06e76888f464e13b7cc4c3db33e8131 + name: Service status + key: net.tcp.service[http,"{$NGINX.STUB_STATUS.HOST}","{$NGINX.STUB_STATUS.PORT}"] + valuemap: + name: Service state + preprocessing: + - type: DISCARD_UNCHANGED_HEARTBEAT + parameters: + - 10m + tags: + - tag: component + value: application + - tag: component + value: health + - uuid: 9e2be446ac79491c8be1bcd789392066 + name: Connections accepted per second + type: DEPENDENT + key: nginx.connections.accepted.rate + delay: '0' + value_type: FLOAT + description: The total number of accepted client connections. + preprocessing: + - type: REGEX + parameters: + - server accepts handled requests\s+([0-9]+) ([0-9]+) ([0-9]+) + - \1 + - type: CHANGE_PER_SECOND + parameters: + - '' + master_item: + key: web.page.get["{$NGINX.STUB_STATUS.HOST}","{$NGINX.STUB_STATUS.PATH}","{$NGINX.STUB_STATUS.PORT}"] + tags: + - tag: component + value: connections + - uuid: 436f2dc87cda418eb8f19ed6910c7bd0 + name: Connections active + type: DEPENDENT + key: nginx.connections.active + delay: '0' + description: The current number of active client connections including waiting + connections. + preprocessing: + - type: REGEX + parameters: + - 'Active connections: ([0-9]+)' + - \1 + master_item: + key: web.page.get["{$NGINX.STUB_STATUS.HOST}","{$NGINX.STUB_STATUS.PATH}","{$NGINX.STUB_STATUS.PORT}"] + tags: + - tag: component + value: connections + - uuid: 4027e6db5e024aff98056faa2d4b43cd + name: Connections dropped per second + type: DEPENDENT + key: nginx.connections.dropped.rate + delay: '0' + value_type: FLOAT + description: The total number of dropped client connections. + preprocessing: + - type: JAVASCRIPT + parameters: + - "var a = value.match(/server accepts handled requests\\s+([0-9]+) ([0-9]+)\ + \ ([0-9]+)/)\nif (a) {\n\treturn a[1]-a[2]\n}\n" + - type: CHANGE_PER_SECOND + parameters: + - '' + master_item: + key: web.page.get["{$NGINX.STUB_STATUS.HOST}","{$NGINX.STUB_STATUS.PATH}","{$NGINX.STUB_STATUS.PORT}"] + tags: + - tag: component + value: connections + - uuid: 06191636a7104e1bb40d197493b80958 + name: Connections handled per second + type: DEPENDENT + key: nginx.connections.handled.rate + delay: '0' + value_type: FLOAT + description: The total number of handled connections. Generally, the parameter + value is the same as for the accepted connections, unless some resource limits + have been reached (for example, the `worker_connections limit`). + preprocessing: + - type: REGEX + parameters: + - server accepts handled requests\s+([0-9]+) ([0-9]+) ([0-9]+) + - \2 + - type: CHANGE_PER_SECOND + parameters: + - '' + master_item: + key: web.page.get["{$NGINX.STUB_STATUS.HOST}","{$NGINX.STUB_STATUS.PATH}","{$NGINX.STUB_STATUS.PORT}"] + tags: + - tag: component + value: connections + - uuid: f5925c78389143c7924432483a5c716c + name: Connections reading + type: DEPENDENT + key: nginx.connections.reading + delay: '0' + description: The current number of connections where Nginx is reading the request + header. + preprocessing: + - type: REGEX + parameters: + - 'Reading: ([0-9]+) Writing: ([0-9]+) Waiting: ([0-9]+)' + - \1 + master_item: + key: web.page.get["{$NGINX.STUB_STATUS.HOST}","{$NGINX.STUB_STATUS.PATH}","{$NGINX.STUB_STATUS.PORT}"] + tags: + - tag: component + value: connections + - uuid: d6cfa828ba344ffe948d8d985b849316 + name: Connections waiting + type: DEPENDENT + key: nginx.connections.waiting + delay: '0' + description: The current number of idle client connections waiting for a request. + preprocessing: + - type: REGEX + parameters: + - 'Reading: ([0-9]+) Writing: ([0-9]+) Waiting: ([0-9]+)' + - \3 + master_item: + key: web.page.get["{$NGINX.STUB_STATUS.HOST}","{$NGINX.STUB_STATUS.PATH}","{$NGINX.STUB_STATUS.PORT}"] + tags: + - tag: component + value: connections + - uuid: c038a572f73f4a418ddcc5aeb8b0a547 + name: Connections writing + type: DEPENDENT + key: nginx.connections.writing + delay: '0' + description: The current number of connections where Nginx is writing a response + back to the client. + preprocessing: + - type: REGEX + parameters: + - 'Reading: ([0-9]+) Writing: ([0-9]+) Waiting: ([0-9]+)' + - \2 + master_item: + key: web.page.get["{$NGINX.STUB_STATUS.HOST}","{$NGINX.STUB_STATUS.PATH}","{$NGINX.STUB_STATUS.PORT}"] + tags: + - tag: component + value: connections + - uuid: b28444fb9b834d03a72036882c80b921 + name: Requests total + type: DEPENDENT + key: nginx.requests.total + delay: '0' + description: The total number of client requests. + preprocessing: + - type: REGEX + parameters: + - server accepts handled requests\s+([0-9]+) ([0-9]+) ([0-9]+) + - \3 + master_item: + key: web.page.get["{$NGINX.STUB_STATUS.HOST}","{$NGINX.STUB_STATUS.PATH}","{$NGINX.STUB_STATUS.PORT}"] + tags: + - tag: component + value: requests + - uuid: 2600a696278f490f86cadd8c8836f269 + name: Requests per second + type: DEPENDENT + key: nginx.requests.total.rate + delay: '0' + value_type: FLOAT + description: The total number of client requests. + preprocessing: + - type: REGEX + parameters: + - server accepts handled requests\s+([0-9]+) ([0-9]+) ([0-9]+) + - \3 + - type: CHANGE_PER_SECOND + parameters: + - '' + master_item: + key: web.page.get["{$NGINX.STUB_STATUS.HOST}","{$NGINX.STUB_STATUS.PATH}","{$NGINX.STUB_STATUS.PORT}"] + tags: + - tag: component + value: requests + - uuid: 3dcc81006977478f92be6dd040d66eb5 + name: Version + type: DEPENDENT + key: nginx.version + delay: '0' + value_type: CHAR + trends: '0' + preprocessing: + - type: REGEX + parameters: + - '(?i)Server: nginx\/(.+(?last(/Nginx by + Zabbix agent/nginx.version,#2) and length(last(/Nginx by Zabbix agent/nginx.version))>0 + name: 'Nginx: Version has changed' + event_name: 'Nginx: Version has changed (new version: {ITEM.VALUE})' + priority: INFO + description: The Nginx version has changed. Acknowledge to close the problem + manually. + manual_close: 'YES' + tags: + - tag: scope + value: notice + - uuid: d43b4b99b6084076a4feb1fde51ecc40 + name: Get processes summary + key: proc.get[{$NGINX.PROCESS.NAME.PARAMETER},,,summary] + history: '0' + value_type: TEXT + trends: '0' + description: The aggregated data of summary metrics for all processes. + tags: + - tag: component + value: raw + - uuid: 52a23a9f6d60490c8f5565b938154f61 + name: Get stub status page + key: web.page.get["{$NGINX.STUB_STATUS.HOST}","{$NGINX.STUB_STATUS.PATH}","{$NGINX.STUB_STATUS.PORT}"] + history: 1h + value_type: TEXT + trends: '0' + description: 'The following status information is provided: + + `Active connections` - the current number of active client connections including + waiting connections. + + `Accepted` - the total number of accepted client connections. + + `Handled` - the total number of handled connections. Generally, the parameter + value is the same as for the accepted connections, unless some resource limits + have been reached (for example, the `worker_connections` limit). + + `Requests` - the total number of client requests. + + `Reading` - the current number of connections where Nginx is reading the request + header. + + `Writing` - the current number of connections where Nginx is writing a response + back to the client. + + `Waiting` - the current number of idle client connections waiting for a request. + + + See also [Module ngx_http_stub_status_module](https://nginx.org/en/docs/http/ngx_http_stub_status_module.html). + + ' + tags: + - tag: component + value: application + - tag: component + value: health + discovery_rules: + - uuid: f4a898f929c54b3493506e68703fa2cc + name: Nginx process discovery + type: DEPENDENT + key: nginx.proc.discovery + delay: '0' + filter: + evaltype: AND + conditions: + - macro: '{#NGINX.NAME}' + value: '{$NGINX.PROCESS_NAME}' + formulaid: A + description: The discovery of Nginx process summary. + item_prototypes: + - uuid: 632e441011674f04886096475180dcbb + name: Get process data + type: DEPENDENT + key: nginx.proc.get[{#NGINX.NAME}] + delay: '0' + history: '0' + value_type: TEXT + trends: '0' + description: The summary metrics aggregated by a process {#NGINX.NAME}. + preprocessing: + - type: JSONPATH + parameters: + - $.[?(@["name"]=="{#NGINX.NAME}")].first() + error_handler: CUSTOM_VALUE + error_handler_params: Failed to retrieve process {#NGINX.NAME} data + master_item: + key: proc.get[{$NGINX.PROCESS.NAME.PARAMETER},,,summary] + tags: + - tag: component + value: raw + - uuid: ba3da6baccee4b31947bf20d3cae0e5f + name: Number of running processes + type: DEPENDENT + key: nginx.proc.num[{#NGINX.NAME}] + delay: '0' + description: The number of running processes {#NGINX.NAME}. + preprocessing: + - type: JSONPATH + parameters: + - $.processes + error_handler: CUSTOM_VALUE + error_handler_params: '0' + - type: DISCARD_UNCHANGED_HEARTBEAT + parameters: + - 1h + master_item: + key: nginx.proc.get[{#NGINX.NAME}] + tags: + - tag: component + value: system + trigger_prototypes: + - uuid: 903e6a1f30154ee49df3f8d87e0164cc + expression: last(/Nginx by Zabbix agent/nginx.proc.num[{#NGINX.NAME}])=0 + name: 'Nginx: Process is not running' + priority: HIGH + tags: + - tag: scope + value: availability + - uuid: 5887d0062bed4233a03d4f408fac7163 + name: Memory usage, % + type: DEPENDENT + key: nginx.proc.pmem[{#NGINX.NAME}] + delay: '0' + value_type: FLOAT + units: '%' + description: The percentage of real memory used by a process {#NGINX.NAME}. + preprocessing: + - type: JSONPATH + parameters: + - $.pmem + error_handler: DISCARD_VALUE + master_item: + key: nginx.proc.get[{#NGINX.NAME}] + tags: + - tag: component + value: memory + - uuid: 64d208475c034bae953a64cde1833ebb + name: Memory usage (rss) + type: DEPENDENT + key: nginx.proc.rss[{#NGINX.NAME}] + delay: '0' + units: B + description: The summary of resident set size memory used by a process {#NGINX.NAME} + expressed in bytes. + preprocessing: + - type: JSONPATH + parameters: + - $.rss + error_handler: DISCARD_VALUE + master_item: + key: nginx.proc.get[{#NGINX.NAME}] + tags: + - tag: component + value: memory + - uuid: 21fccb0286fb407c85f1972e994c698e + name: Memory usage (vsize) + type: DEPENDENT + key: nginx.proc.vmem[{#NGINX.NAME}] + delay: '0' + units: B + description: The summary of virtual memory used by a process {#NGINX.NAME} + expressed in bytes. + preprocessing: + - type: JSONPATH + parameters: + - $.vsize + error_handler: DISCARD_VALUE + master_item: + key: nginx.proc.get[{#NGINX.NAME}] + tags: + - tag: component + value: memory + - uuid: 84c95c1955bf4ccaa12a060a9acdb478 + name: CPU utilization + key: proc.cpu.util[{#NGINX.NAME}] + value_type: FLOAT + units: '%' + description: The percentage of the CPU utilization by a process {#NGINX.NAME}. + tags: + - tag: component + value: cpu + trigger_prototypes: + - uuid: a497b80eb03f469c9552881b498003b2 + expression: '(find(/Nginx by Zabbix agent/web.page.get["{$NGINX.STUB_STATUS.HOST}","{$NGINX.STUB_STATUS.PATH}","{$NGINX.STUB_STATUS.PORT}"],,"iregexp","HTTP\\/[\\d.]+\\s+200")=0 + or + + nodata(/Nginx by Zabbix agent/web.page.get["{$NGINX.STUB_STATUS.HOST}","{$NGINX.STUB_STATUS.PATH}","{$NGINX.STUB_STATUS.PORT}"],30m)) + and last(/Nginx by Zabbix agent/nginx.proc.num[{#NGINX.NAME}])>0 + + ' + name: 'Nginx: Failed to fetch stub status page' + event_name: 'Nginx: Failed to fetch stub status page (or no data for 30m)' + priority: WARNING + description: Zabbix has not received any data for items for the last 30 minutes. + manual_close: 'YES' + dependencies: + - name: 'Nginx: Service is down' + expression: last(/Nginx by Zabbix agent/net.tcp.service[http,"{$NGINX.STUB_STATUS.HOST}","{$NGINX.STUB_STATUS.PORT}"])=0 + and last(/Nginx by Zabbix agent/nginx.proc.num[{#NGINX.NAME}])>0 + tags: + - tag: scope + value: availability + - uuid: f2d431fa9bc446608caa3f80ef27c41b + expression: min(/Nginx by Zabbix agent/nginx.connections.dropped.rate,5m) + > {$NGINX.DROP_RATE.MAX.WARN} and last(/Nginx by Zabbix agent/nginx.proc.num[{#NGINX.NAME}])>0 + name: 'Nginx: High connections drop rate' + event_name: 'Nginx: High connections drop rate (more than {$NGINX.DROP_RATE.MAX.WARN} + for 5m)' + opdata: 'Current rate: {ITEM.LASTVALUE1}' + priority: WARNING + description: The rate of dropping connections has been greater than {$NGINX.DROP_RATE.MAX.WARN} + for the last 5 minutes. + dependencies: + - name: 'Nginx: Service is down' + expression: last(/Nginx by Zabbix agent/net.tcp.service[http,"{$NGINX.STUB_STATUS.HOST}","{$NGINX.STUB_STATUS.PORT}"])=0 + and last(/Nginx by Zabbix agent/nginx.proc.num[{#NGINX.NAME}])>0 + tags: + - tag: scope + value: performance + - uuid: c043191c22f34522ba4f83430d9f88b1 + expression: last(/Nginx by Zabbix agent/net.tcp.service[http,"{$NGINX.STUB_STATUS.HOST}","{$NGINX.STUB_STATUS.PORT}"])=0 + and last(/Nginx by Zabbix agent/nginx.proc.num[{#NGINX.NAME}])>0 + name: 'Nginx: Service is down' + priority: AVERAGE + manual_close: 'YES' + tags: + - tag: scope + value: availability + - uuid: f5db329410a14609a5f3e883ca493cc8 + expression: min(/Nginx by Zabbix agent/net.tcp.service.perf[http,"{$NGINX.STUB_STATUS.HOST}","{$NGINX.STUB_STATUS.PORT}"],5m)>{$NGINX.RESPONSE_TIME.MAX.WARN} + and last(/Nginx by Zabbix agent/nginx.proc.num[{#NGINX.NAME}])>0 + name: 'Nginx: Service response time is too high' + event_name: 'Nginx: Service response time is too high (over {$NGINX.RESPONSE_TIME.MAX.WARN}s + for 5m)' + priority: WARNING + manual_close: 'YES' + dependencies: + - name: 'Nginx: Service is down' + expression: last(/Nginx by Zabbix agent/net.tcp.service[http,"{$NGINX.STUB_STATUS.HOST}","{$NGINX.STUB_STATUS.PORT}"])=0 + and last(/Nginx by Zabbix agent/nginx.proc.num[{#NGINX.NAME}])>0 + tags: + - tag: scope + value: performance + graph_prototypes: + - uuid: 69ca908afa1d468d983a263d06910925 + name: 'Nginx: Memory usage[{#NGINX.NAME}]' + graph_items: + - drawtype: BOLD_LINE + color: 199C0D + item: + host: Nginx by Zabbix agent + key: nginx.proc.vmem[{#NGINX.NAME}] + - sortorder: '1' + drawtype: BOLD_LINE + color: F63100 + item: + host: Nginx by Zabbix agent + key: nginx.proc.rss[{#NGINX.NAME}] + master_item: + key: proc.get[{$NGINX.PROCESS.NAME.PARAMETER},,,summary] + lld_macro_paths: + - lld_macro: '{#NGINX.NAME}' + path: $.name + - 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" + tags: + - tag: class + value: software + - tag: target + value: nginx + macros: + - macro: '{$NGINX.DROP_RATE.MAX.WARN}' + value: '1' + description: The critical rate of the dropped connections for a trigger expression. + - macro: '{$NGINX.PROCESS.NAME.PARAMETER}' + description: The process name of the Nginx server used in the item key `proc.get`. + It could be specified if the correct process name is known. + - macro: '{$NGINX.PROCESS_NAME}' + value: nginx + description: The process name filter for the Nginx process discovery. + - macro: '{$NGINX.RESPONSE_TIME.MAX.WARN}' + value: '10' + description: The maximum response time of Nginx expressed in seconds for a trigger + expression. + - macro: '{$NGINX.STUB_STATUS.HOST}' + value: localhost + description: The hostname or IP address of the Nginx host or Nginx container + of `astub_status`. + - macro: '{$NGINX.STUB_STATUS.PATH}' + value: basic_status + description: The path of the `Nginx stub_status` page. + - macro: '{$NGINX.STUB_STATUS.PORT}' + value: '80' + description: The port of the `Nginx stub_status` host or container. + dashboards: + - uuid: 9d071e3a148c405e85c53ef25d54efaf + name: Nginx performance + pages: + - widgets: + - type: graph + width: '36' + height: '5' + fields: + - type: GRAPH + name: graphid.0 + value: + host: Nginx by Zabbix agent + name: 'Nginx: Connections by state' + - type: STRING + name: reference + value: AAAAA + - type: graph + y: '5' + width: '36' + height: '5' + fields: + - type: GRAPH + name: graphid.0 + value: + host: Nginx by Zabbix agent + name: 'Nginx: Connections per second' + - type: STRING + name: reference + value: AAAAC + - type: graph + x: '36' + width: '36' + height: '5' + fields: + - type: GRAPH + name: graphid.0 + value: + host: Nginx by Zabbix agent + name: 'Nginx: Requests per second' + - type: STRING + name: reference + value: AAAAB + valuemaps: + - uuid: 53c8528c18814f30a45d1540ab9e5c00 + name: Service state + mappings: + - value: '0' + newvalue: Down + - value: '1' + newvalue: Up + graphs: + - uuid: ba234158aeca468a8592d944f9aae691 + name: 'Nginx: Connections by state' + graph_items: + - drawtype: BOLD_LINE + color: 199C0D + item: + host: Nginx by Zabbix agent + key: nginx.connections.active + - sortorder: '1' + color: F63100 + item: + host: Nginx by Zabbix agent + key: nginx.connections.waiting + - sortorder: '2' + color: 00611C + item: + host: Nginx by Zabbix agent + key: nginx.connections.writing + - sortorder: '3' + color: F7941D + item: + host: Nginx by Zabbix agent + key: nginx.connections.reading + - uuid: b82a5b89864a47638421458f3e74563d + name: 'Nginx: Connections per second' + graph_items: + - color: 199C0D + item: + host: Nginx by Zabbix agent + key: nginx.connections.accepted.rate + - sortorder: '1' + color: F63100 + item: + host: Nginx by Zabbix agent + key: nginx.connections.handled.rate + - sortorder: '2' + color: 00611C + item: + host: Nginx by Zabbix agent + key: nginx.connections.dropped.rate + - uuid: a2d2fec823514df09731381304c245e9 + name: 'Nginx: Requests per second' + graph_items: + - drawtype: GRADIENT_LINE + color: 199C0D + item: + host: Nginx by Zabbix agent + key: nginx.requests.total.rate diff --git a/templates_gold/nginx_agent/template_nginx_site_analysis.yaml b/templates_gold/nginx_agent/template_nginx_site_analysis.yaml new file mode 100644 index 0000000..d117afe --- /dev/null +++ b/templates_gold/nginx_agent/template_nginx_site_analysis.yaml @@ -0,0 +1,466 @@ +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 diff --git a/zbx_export_hosts.yaml b/zbx_export_hosts.yaml new file mode 100644 index 0000000..7bb8d19 --- /dev/null +++ b/zbx_export_hosts.yaml @@ -0,0 +1,932 @@ +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'