Skip to content

Instantly share code, notes, and snippets.

@codeinthehole
Last active May 15, 2019 22:00
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save codeinthehole/7f60b011f969787a7fff to your computer and use it in GitHub Desktop.
Save codeinthehole/7f60b011f969787a7fff to your computer and use it in GitHub Desktop.
Zabbix plugin script for extracting uWSGI metrics from a log file
#!/usr/bin/env python
"""
Extract metrics from a uWSGI log file
This should be saved as /etc/zabbix/pluginx/uwsgi_stats and called from
/etc/zabbix/zabbix_agentd.conf.d/uwsgi.conf, which should have contents:
UserParameter=uwsgi.stats[*],/etc/zabbix/plugins/uwsgi_stats $1 $2
To gather these metrics in Zabbix, create a new item which calls this plugin and
passes the filepath and metric key. Eg:
uwsgi.stats[/var/log/client/project/logs/prod/uwsgi.log,req_count]
The available metric keys are:
- req_count -> requests per minute
- get_req_count -> GET requests per minute
- post_req_count -> POST requests per minute
- avg_req_time -> average request time in ms
- avg_req_size -> average request size in bytes
Author: David Winterbottom
"""
import datetime
import subprocess
import re
import sys
import os
def extract_metric(filepath, metric):
# Determine time pattern to grep for
now = datetime.datetime.now()
# Fiddle with date format as uWSGI does not zero pad the day
last_minute = now - datetime.timedelta(minutes=1)
day = last_minute.strftime("%d").lstrip("0")
month = last_minute.strftime("%b")
time = last_minute.strftime("%H:%M")
pattern = "%s %s %s" % (month, day, time)
# Extract data from access log
try:
output = subprocess.Popen(
["grep", pattern, filepath], stdout=subprocess.PIPE).communicate()[0]
except subprocess.CalledProcessError:
# Happens when no matches
lines = []
else:
lines = output.split("\n")
data = []
regex = re.compile(r'.* (?P<method>[A-Z]+) (?P<path>\S+) => generated (?P<bytes>\d+) bytes in (?P<msecs>\d+) msecs \(HTTP/1.\d (?P<status>\d+).*')
for line in lines:
match = regex.match(line)
if match:
data.append(match.groupdict())
if not data:
return
# Calculate and print appropriate metric
if metric == 'avg_req_time':
times = [int(x['msecs']) for x in data]
return float(sum(times)) / len(times)
elif metric == 'avg_req_size':
sizes = [int(x['bytes']) for x in data]
return float(sum(sizes)) / len(sizes)
elif metric == 'req_count':
return len(data)
elif metric == 'get_req_count':
return len([1 for x in data if x['method'] == 'GET'])
elif metric == 'post_req_count':
return len([1 for x in data if x['method'] == 'POST'])
elif metric == '2xx_req_count':
return len([1 for x in data if x['status'].startswith('2')])
elif metric == '3xx_req_count':
return len([1 for x in data if x['status'].startswith('3')])
elif metric == '4xx_req_count':
return len([1 for x in data if x['status'].startswith('4')])
elif metric == '5xx_req_count':
return len([1 for x in data if x['status'].startswith('5')])
if __name__ == '__main__':
filepath = sys.argv[1]
metric_key = sys.argv[2]
metric = extract_metric(filepath, metric_key)
if metric is not None:
print metric
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment