139 lines
6.2 KiB
Python
139 lines
6.2 KiB
Python
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")
|