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")