mirror of
https://github.com/munin-monitoring/contrib.git
synced 2025-07-21 18:41:03 +00:00
varnish4_multigraph: multigraph version of varnish4_, rewritten in python
This commit is contained in:
parent
7e48a2c8b5
commit
b2a11780b3
1 changed files with 453 additions and 0 deletions
453
plugins/varnish/varnish4_multigraph
Executable file
453
plugins/varnish/varnish4_multigraph
Executable file
|
@ -0,0 +1,453 @@
|
|||
#!/usr/bin/python3 -tt
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
""" Munin plugin to monitor Varnish 4 status.
|
||||
|
||||
Copyright 2016, Kim B. Heino, b@bbbs.net, Foobar Oy
|
||||
License GPLv2+
|
||||
|
||||
This is based heavily on varnish4_ plugin from Munin contrib
|
||||
by Kristian Lyngstol <kristian@bohemians.org> / Redpill Linpro AS.
|
||||
|
||||
#%# capabilities=autoconf
|
||||
#%# family=auto
|
||||
"""
|
||||
# pylint: disable=invalid-name
|
||||
# pylint: enable=invalid-name
|
||||
|
||||
import json
|
||||
import subprocess
|
||||
import sys
|
||||
|
||||
|
||||
def run_binary(arg):
|
||||
"""Run binary and return output."""
|
||||
try:
|
||||
cmd = subprocess.Popen(
|
||||
arg, shell=False, close_fds=True, bufsize=-1,
|
||||
stdout=subprocess.PIPE, stderr=subprocess.PIPE)
|
||||
outdata, dummy_errdata = cmd.communicate()
|
||||
except OSError:
|
||||
return ''
|
||||
return outdata.decode('utf-8', 'ignore')
|
||||
|
||||
|
||||
def get_values():
|
||||
"""Run varnishstat and parse it's output."""
|
||||
output = run_binary(['/usr/bin/varnishstat', '-j'])
|
||||
try:
|
||||
return json.loads(output)
|
||||
except (TypeError, ValueError):
|
||||
return {}
|
||||
|
||||
|
||||
def autoconf():
|
||||
"""Print "yes" or "no"."""
|
||||
status = 'yes' if get_values() else 'no'
|
||||
print(status)
|
||||
|
||||
|
||||
def config():
|
||||
"""Print plugin config."""
|
||||
# pylint: disable=too-many-statements
|
||||
|
||||
# backend_traffic
|
||||
print('multigraph varnish_backend_traffic')
|
||||
print('graph_category webserver')
|
||||
print('graph_title Backend traffic')
|
||||
print('backend_busy.label Backend conn. too many')
|
||||
print('backend_busy.min 0')
|
||||
print('backend_busy.type DERIVE')
|
||||
print('backend_conn.label Backend conn. success')
|
||||
print('backend_conn.min 0')
|
||||
print('backend_conn.type DERIVE')
|
||||
print('backend_retry.label Backend conn. retry')
|
||||
print('backend_retry.min 0')
|
||||
print('backend_retry.type DERIVE')
|
||||
print('backend_unhealthy.label Backend conn. not attempted')
|
||||
print('backend_unhealthy.min 0')
|
||||
print('backend_unhealthy.warning :1')
|
||||
print('backend_unhealthy.type DERIVE')
|
||||
print('backend_recycle.label Backend conn. recycles')
|
||||
print('backend_recycle.min 0')
|
||||
print('backend_recycle.type DERIVE')
|
||||
print('backend_fail.label Backend conn. failures')
|
||||
print('backend_fail.min 0')
|
||||
print('backend_fail.type DERIVE')
|
||||
print('backend_toolate.label Backend conn. was closed')
|
||||
print('backend_toolate.min 0')
|
||||
print('backend_toolate.type DERIVE')
|
||||
print('backend_reuse.label Backend conn. reuses')
|
||||
print('backend_reuse.min 0')
|
||||
print('backend_reuse.type DERIVE')
|
||||
print('backend_req.label Backend requests made')
|
||||
print('backend_req.min 0')
|
||||
print('backend_req.type DERIVE')
|
||||
|
||||
# bad
|
||||
print('multigraph varnish_bad')
|
||||
print('graph_category webserver')
|
||||
print('graph_title Misbehavior')
|
||||
print('sess_drop.label Sessions dropped')
|
||||
print('sess_drop.type DERIVE')
|
||||
print('threads_failed.label Thread creation failed')
|
||||
print('threads_failed.type DERIVE')
|
||||
print('threads_destroyed.label Threads destroyed')
|
||||
print('threads_destroyed.type DERIVE')
|
||||
print('thread_queue_len.label Length of session queue')
|
||||
print('thread_queue_len.type GAUGE')
|
||||
print('sess_pipe_overflow.label Session pipe overflow')
|
||||
print('sess_pipe_overflow.type DERIVE')
|
||||
print('esi_warnings.label ESI parse warnings (unlock)')
|
||||
print('esi_warnings.type DERIVE')
|
||||
print('sess_fail.label Session accept failures')
|
||||
print('sess_fail.type DERIVE')
|
||||
print('backend_busy.label Backend conn. too many')
|
||||
print('backend_busy.type DERIVE')
|
||||
print('esi_errors.label ESI parse errors (unlock)')
|
||||
print('esi_errors.type DERIVE')
|
||||
print('SMF_s0_c_fail.label Allocator failures SMF s0')
|
||||
print('SMF_s0_c_fail.type DERIVE')
|
||||
print('SMA_Transient_c_fail.label Allocator failures SMA Transient')
|
||||
print('SMA_Transient_c_fail.type DERIVE')
|
||||
print('losthdr.label HTTP header overflows')
|
||||
print('losthdr.type DERIVE')
|
||||
print('backend_unhealthy.label Backend conn. not attempted')
|
||||
print('backend_unhealthy.type DERIVE')
|
||||
print('threads_limited.label Threads hit max')
|
||||
print('threads_limited.type DERIVE')
|
||||
print('fetch_failed.label Fetch failed (all causes)')
|
||||
print('fetch_failed.type DERIVE')
|
||||
|
||||
# expunge
|
||||
print('multigraph varnish_expunge')
|
||||
print('graph_category webserver')
|
||||
print('graph_title Object expunging')
|
||||
print('graph_order n_expired n_lru_nuked')
|
||||
print('n_lru_nuked.label Number of LRU nuked objects')
|
||||
print('n_lru_nuked.min 0')
|
||||
print('n_lru_nuked.type DERIVE')
|
||||
print('n_expired.label Number of expired objects')
|
||||
print('n_expired.min 0')
|
||||
print('n_expired.type DERIVE')
|
||||
|
||||
# hit_rate
|
||||
print('multigraph varnish_hit_rate')
|
||||
print('graph_category webserver')
|
||||
print('graph_title Hit rates')
|
||||
print('graph_order client_req cache_hit cache_miss cache_hitpass')
|
||||
print('graph_scale no')
|
||||
print('graph_vlabel %')
|
||||
print('graph_args -l 0 -u 100 --rigid')
|
||||
print('client_req.label Good client requests received')
|
||||
print('client_req.graph off')
|
||||
print('client_req.min 0')
|
||||
print('client_req.type DERIVE')
|
||||
print('cache_miss.label Cache misses')
|
||||
print('cache_miss.min 0')
|
||||
print('cache_miss.draw STACK')
|
||||
print('cache_miss.cdef cache_miss,client_req,/,100,*')
|
||||
print('cache_miss.type DERIVE')
|
||||
print('cache_hit.label Cache hits')
|
||||
print('cache_hit.min 0')
|
||||
print('cache_hit.draw AREA')
|
||||
print('cache_hit.cdef cache_hit,client_req,/,100,*')
|
||||
print('cache_hit.type DERIVE')
|
||||
print('cache_hitpass.label Cache hits for pass')
|
||||
print('cache_hitpass.min 0')
|
||||
print('cache_hitpass.draw STACK')
|
||||
print('cache_hitpass.cdef cache_hitpass,client_req,/,100,*')
|
||||
print('cache_hitpass.type DERIVE')
|
||||
|
||||
# memory_usage
|
||||
print('multigraph varnish_memory_usage')
|
||||
print('graph_category webserver')
|
||||
print('graph_title Memory usage')
|
||||
print('graph_vlabel bytes')
|
||||
print('graph_args --base 1024')
|
||||
print('SMA_Transient_g_bytes.label Bytes outstanding SMA Transient')
|
||||
print('SMA_Transient_g_bytes.type GAUGE')
|
||||
print('SMA_Transient_g_space.label Bytes available SMA Transient')
|
||||
print('SMA_Transient_g_space.type GAUGE')
|
||||
print('SMF_s0_g_bytes.label Bytes outstanding SMF s0')
|
||||
print('SMF_s0_g_bytes.type GAUGE')
|
||||
print('sms_nbytes.label SMS outstanding bytes')
|
||||
print('sms_nbytes.type GAUGE')
|
||||
print('sms_balloc.label SMS bytes allocated')
|
||||
print('sms_balloc.type GAUGE')
|
||||
print('SMF_s0_g_space.label Bytes available SMF s0')
|
||||
print('SMF_s0_g_space.type GAUGE')
|
||||
print('SMA_Transient_c_bytes.label Bytes allocated SMA Transient')
|
||||
print('SMA_Transient_c_bytes.type DERIVE')
|
||||
|
||||
# objects
|
||||
print('multigraph varnish_objects')
|
||||
print('graph_category webserver')
|
||||
print('graph_title Number of objects')
|
||||
print('graph_order n_object n_objectcore n_vampireobject n_objecthead')
|
||||
print('n_object.label Number of objects')
|
||||
print('n_object.type GAUGE')
|
||||
print('n_vampireobject.label Number of unresurrected objects')
|
||||
print('n_vampireobject.type GAUGE')
|
||||
print('n_objectcore.label Number of object cores')
|
||||
print('n_objectcore.type GAUGE')
|
||||
print('n_objecthead.label Number of object heads')
|
||||
print(
|
||||
'n_objecthead.info Each object head can have one or more object '
|
||||
'attached, typically based on the Vary: header')
|
||||
print('n_objecthead.type GAUGE')
|
||||
|
||||
# request_rate
|
||||
print('multigraph varnish_request_rate')
|
||||
print('graph_category webserver')
|
||||
print('graph_title Request rates')
|
||||
print(
|
||||
'graph_order cache_hit cache_hitpass cache_miss backend_conn '
|
||||
'backend_unhealthy client_req client_conn')
|
||||
print('client_req.label Good client requests received')
|
||||
print('client_req.min 0')
|
||||
print('client_req.colour 111111')
|
||||
print('client_req.type DERIVE')
|
||||
print('s_pipe.label Total pipe sessions seen')
|
||||
print('s_pipe.min 0')
|
||||
print('s_pipe.colour 1d2bdf')
|
||||
print('s_pipe.type DERIVE')
|
||||
print('sess_conn.label Sessions accepted')
|
||||
print('sess_conn.graph ON')
|
||||
print('sess_conn.min 0')
|
||||
print('sess_conn.colour 444444')
|
||||
print('sess_conn.type DERIVE')
|
||||
print('cache_miss.label Cache misses')
|
||||
print('cache_miss.min 0')
|
||||
print('cache_miss.draw STACK')
|
||||
print('cache_miss.colour FF0000')
|
||||
print('cache_miss.type DERIVE')
|
||||
print('backend_conn.label Backend conn. success')
|
||||
print('backend_conn.min 0')
|
||||
print('backend_conn.colour 995599')
|
||||
print('backend_conn.type DERIVE')
|
||||
print('s_pass.label Total pass-ed requests seen')
|
||||
print('s_pass.min 0')
|
||||
print('s_pass.colour 785d0d')
|
||||
print('s_pass.type DERIVE')
|
||||
print('backend_unhealthy.label Backend conn. not attempted')
|
||||
print('backend_unhealthy.min 0')
|
||||
print('backend_unhealthy.colour FF55FF')
|
||||
print('backend_unhealthy.type DERIVE')
|
||||
print('cache_hitpass.label Cache hits for pass')
|
||||
print('cache_hitpass.min 0')
|
||||
print('cache_hitpass.draw STACK')
|
||||
print('cache_hitpass.colour FFFF00')
|
||||
print(
|
||||
'cache_hitpass.info Hitpass are cached passes: An entry in the '
|
||||
'cache instructing Varnish to pass. Typically achieved after a '
|
||||
'pass in vcl_fetch.')
|
||||
print('cache_hitpass.type DERIVE')
|
||||
print('cache_hit.label Cache hits')
|
||||
print('cache_hit.min 0')
|
||||
print('cache_hit.draw AREA')
|
||||
print('cache_hit.colour 00FF00')
|
||||
print('cache_hit.type DERIVE')
|
||||
|
||||
# threads
|
||||
print('multigraph varnish_threads')
|
||||
print('graph_category webserver')
|
||||
print('graph_title Thread status')
|
||||
print('threads_created.label Threads created')
|
||||
print('threads_created.min 0')
|
||||
print('threads_created.type DERIVE')
|
||||
print('threads_failed.label Thread creation failed')
|
||||
print('threads_failed.min 0')
|
||||
print('threads_failed.warning :1')
|
||||
print('threads_failed.type DERIVE')
|
||||
print('threads_destroyed.label Threads destroyed')
|
||||
print('threads_destroyed.min 0')
|
||||
print('threads_destroyed.warning :1')
|
||||
print('threads_destroyed.type DERIVE')
|
||||
print('threads_limited.label Threads hit max')
|
||||
print('threads_limited.min 0')
|
||||
print('threads_limited.type DERIVE')
|
||||
print('threads.label Total number of threads')
|
||||
print('threads.min 0')
|
||||
print('threads.warning 1:')
|
||||
print('threads.type GAUGE')
|
||||
|
||||
# transfer_rates
|
||||
print('multigraph varnish_transfer_rates')
|
||||
print('graph_category webserver')
|
||||
print('graph_title Transfer rates')
|
||||
print('graph_order s_resp_bodybytes s_resp_hdrbytes')
|
||||
print('graph_vlabel bit/s')
|
||||
print('graph_args -l 0')
|
||||
print('s_resp_bodybytes.label Body traffic')
|
||||
print('s_resp_bodybytes.min 0')
|
||||
print('s_resp_bodybytes.draw AREA')
|
||||
print('s_resp_bodybytes.cdef s_resp_bodybytes,8,*')
|
||||
print('s_resp_bodybytes.type DERIVE')
|
||||
print('s_resp_hdrbytes.label Header traffic')
|
||||
print('s_resp_hdrbytes.min 0')
|
||||
print('s_resp_hdrbytes.draw STACK')
|
||||
print('s_resp_hdrbytes.cdef s_resp_hdrbytes,8,*')
|
||||
print(
|
||||
's_resp_hdrbytes.info HTTP Header traffic. TCP/IP overhead is not '
|
||||
'included.')
|
||||
print('s_resp_hdrbytes.type DERIVE')
|
||||
|
||||
# uptime
|
||||
print('multigraph varnish_uptime')
|
||||
print('graph_category webserver')
|
||||
print('graph_title Varnish uptime')
|
||||
print('graph_scale no')
|
||||
print('graph_vlabel days')
|
||||
print('uptime.label Management process uptime')
|
||||
print('uptime.cdef uptime,86400,/')
|
||||
print('uptime.type GAUGE')
|
||||
|
||||
|
||||
def fetch():
|
||||
"""Print values."""
|
||||
# pylint: disable=too-many-statements
|
||||
data = get_values()
|
||||
if not data:
|
||||
return
|
||||
|
||||
# backend_traffic
|
||||
print('multigraph varnish_backend_traffic')
|
||||
for key in (
|
||||
'backend_busy',
|
||||
'backend_conn',
|
||||
'backend_retry',
|
||||
'backend_unhealthy',
|
||||
'backend_recycle',
|
||||
'backend_fail',
|
||||
'backend_toolate',
|
||||
'backend_reuse',
|
||||
'backend_req',
|
||||
):
|
||||
print('{0}.value {1}'.format(
|
||||
key, data['MAIN.' + key]['value']))
|
||||
|
||||
# bad
|
||||
print('multigraph varnish_bad')
|
||||
for key in (
|
||||
'sess_drop',
|
||||
'threads_failed',
|
||||
'threads_destroyed',
|
||||
'thread_queue_len',
|
||||
'sess_pipe_overflow',
|
||||
'esi_warnings',
|
||||
'sess_fail',
|
||||
'backend_busy',
|
||||
'esi_errors',
|
||||
'losthdr',
|
||||
'backend_unhealthy',
|
||||
'threads_limited',
|
||||
'fetch_failed',
|
||||
):
|
||||
print('{0}.value {1}'.format(
|
||||
key, data['MAIN.' + key]['value']))
|
||||
print('SMA_Transient_c_fail.value {0}'.format(
|
||||
data['SMA.Transient.c_fail']['value']))
|
||||
print('SMF_s0_c_fail.value {0}'.format(
|
||||
data['SMF.s0.c_fail']['value']))
|
||||
|
||||
# expunge
|
||||
print('multigraph varnish_expunge')
|
||||
for key in (
|
||||
'n_lru_nuked',
|
||||
'n_expired',
|
||||
):
|
||||
print('{0}.value {1}'.format(
|
||||
key, data['MAIN.' + key]['value']))
|
||||
|
||||
# hit_rate
|
||||
print('multigraph varnish_hit_rate')
|
||||
print('client_req.value {0}'.format(
|
||||
data['MAIN.cache_hit']['value'] +
|
||||
data['MAIN.cache_miss']['value'] +
|
||||
data['MAIN.cache_hitpass']['value']))
|
||||
for key in (
|
||||
'cache_miss',
|
||||
'cache_hit',
|
||||
'cache_hitpass',
|
||||
):
|
||||
print('{0}.value {1}'.format(
|
||||
key, data['MAIN.' + key]['value']))
|
||||
|
||||
# memory_usage
|
||||
print('multigraph varnish_memory_usage')
|
||||
print('SMA_Transient_g_bytes.value {0}'.format(
|
||||
data['SMA.Transient.g_bytes']['value']))
|
||||
print('SMA_Transient_g_space.value {0}'.format(
|
||||
data['SMA.Transient.g_space']['value']))
|
||||
print('SMF_s0_g_bytes.value {0}'.format(
|
||||
data['SMF.s0.g_bytes']['value']))
|
||||
print('sms_nbytes.value {0}'.format(
|
||||
data['MAIN.sms_nbytes']['value']))
|
||||
print('sms_balloc.value {0}'.format(
|
||||
data['MAIN.sms_balloc']['value']))
|
||||
print('SMF_s0_g_space.value {0}'.format(
|
||||
data['SMF.s0.g_space']['value']))
|
||||
print('SMA_Transient_c_bytes.value {0}'.format(
|
||||
data['SMA.Transient.c_bytes']['value']))
|
||||
|
||||
# objects
|
||||
print('multigraph varnish_objects')
|
||||
for key in (
|
||||
'n_object',
|
||||
'n_vampireobject',
|
||||
'n_objectcore',
|
||||
'n_objecthead',
|
||||
):
|
||||
print('{0}.value {1}'.format(
|
||||
key, data['MAIN.' + key]['value']))
|
||||
|
||||
# request_rate
|
||||
print('multigraph varnish_request_rate')
|
||||
for key in (
|
||||
'client_req',
|
||||
's_pipe',
|
||||
'sess_conn',
|
||||
'cache_miss',
|
||||
'backend_conn',
|
||||
's_pass',
|
||||
'backend_unhealthy',
|
||||
'cache_hitpass',
|
||||
'cache_hit',
|
||||
):
|
||||
print('{0}.value {1}'.format(
|
||||
key, data['MAIN.' + key]['value']))
|
||||
|
||||
# threads
|
||||
print('multigraph varnish_threads')
|
||||
for key in (
|
||||
'threads_created',
|
||||
'threads_failed',
|
||||
'threads_destroyed',
|
||||
'threads_limited',
|
||||
'threads',
|
||||
):
|
||||
print('{0}.value {1}'.format(
|
||||
key, data['MAIN.' + key]['value']))
|
||||
|
||||
# transfer_rates
|
||||
print('multigraph varnish_transfer_rates')
|
||||
for key in (
|
||||
's_resp_bodybytes',
|
||||
's_resp_hdrbytes',
|
||||
):
|
||||
print('{0}.value {1}'.format(
|
||||
key, data['MAIN.' + key]['value']))
|
||||
|
||||
# uptime
|
||||
print('multigraph varnish_uptime')
|
||||
print('uptime.value {0}'.format(data['MAIN.uptime']['value']))
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
if len(sys.argv) > 1 and sys.argv[1] == 'autoconf':
|
||||
autoconf()
|
||||
elif len(sys.argv) > 1 and sys.argv[1] == 'config':
|
||||
config()
|
||||
else:
|
||||
fetch()
|
Loading…
Add table
Add a link
Reference in a new issue