Skip to content

Commit

Permalink
[FEATURES] Added redis metrics
Browse files Browse the repository at this point in the history
  • Loading branch information
Adrien Delle Cave committed Jul 6, 2018
1 parent 5b59d0a commit 40d0b4e
Show file tree
Hide file tree
Showing 14 changed files with 721 additions and 92 deletions.
2 changes: 1 addition & 1 deletion bin/covenant
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ __license__ = """
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
"""
__version__ = '0.0.6.32'
__version__ = '0.0.6.33'

# TODO: load Python logging configuration (using standard logging.config)

Expand Down
137 changes: 96 additions & 41 deletions covenant/classes/collect.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@
import copy
import logging

from covenant.classes.exceptions import CovenantTargetFailed
from covenant.classes.exceptions import CovenantTaskError, CovenantTargetFailed
from covenant.classes.filters import CovenantNoResult

LOG = logging.getLogger('covenant.collect')
Expand All @@ -48,6 +48,9 @@ def __init__(self,
self.labels = labels
self.value_tasks = value_tasks

self._orig = {'on_fail': on_fail,
'on_noresult': on_noresult}

self.on_fail = self._on(on_fail)
self.on_noresult = self._on(on_noresult)

Expand All @@ -70,6 +73,48 @@ def remove(self, val = True):
def removed(self):
return getattr(self.metric, '_removed', False)

def set_labels_metric(self, labels, metricvalue):
method = getattr(self.metric.labels(**labels), self.method)
try:
method(metricvalue)
except Exception, e:
LOG.exception("metric: %r, labels: %r, metricvalue: %r, error: %r",
self.name,
labels,
metricvalue,
e)
raise

def _get_value_from_tasks(self, data):
if isinstance(data, CovenantTargetFailed):
if self.on_fail['remove']:
self.remove(True)
return
return copy.copy(self.on_fail['value'])

for task in self.value_tasks:
if isinstance(data, CovenantNoResult):
if self.on_noresult['remove']:
self.remove(True)
return
data = self.on_noresult['value']
break
data = task(value = data)

return data

def _sanitize_value(self, data):
if isinstance(data, CovenantTargetFailed):
if self.on_fail['remove']:
self.remove(True)
return
data = self.on_fail['value']

if self.default is not None and data is None:
data = self.default

return data

def __call__(self, data):
self.remove(False)
if not isinstance(data, CovenantTargetFailed) \
Expand All @@ -80,32 +125,26 @@ def __call__(self, data):

if self.labels:
for label in self.labels:
if self._orig['on_fail']:
label.set_on_fail(self._orig['on_fail'])
if self._orig['on_noresult']:
label.set_on_noresult(self._orig['on_noresult'])

label.task_label(data)
label.task_value(data, self.value_tasks)
try:
label.task_value(data, self.value_tasks, self.value, self.default)
except CovenantTaskError, e:
LOG.warning("%s. (metric: %r, labelname: %r)", e, self.name, label.labelname)
elif self.value_tasks:
if isinstance(data, CovenantTargetFailed):
if self.on_fail['remove']:
self.remove(True)
return
data = copy.copy(self.on_fail['value'])
else:
for task in self.value_tasks:
if isinstance(data, CovenantNoResult):
if self.on_noresult['remove']:
self.remove(True)
return
data = self.on_noresult['value']
break
data = task(value = data)
data = self._get_value_from_tasks(data)

if isinstance(data, CovenantTargetFailed):
if self.on_fail['remove']:
self.remove(True)
return
data = self.on_fail['value']
if self.removed():
return

if self.default is not None and data is None:
data = self.default
data = self._sanitize_value(data)

if self.removed():
return

if not self.labels:
try:
Expand All @@ -116,31 +155,47 @@ def __call__(self, data):
del data
return

has_label = False
has_label = False
nb_labels = len(self.labels)
nb_values = 0
labels = {}

for label in self.labels:
if label.removed() or not label.labelvalues:
if label.removed() \
or not label.labelvalues:
continue

has_label = True

xlen = len(label.labelvalues)
if xlen > nb_values:
nb_values = xlen
r = []
for labelvalue in label.labelvalues:
method = getattr(self.metric.labels(
**{labelvalue.labelname: labelvalue.labelvalue}),
self.method)

try:
method(labelvalue.get())
except Exception, e:
LOG.exception("metric: %r, labelname: %r, labelvalue: %r, data: %r, error: %r",
self.name,
labelvalue.labelname,
labelvalue.labelvalue,
labelvalue.get(),
e)
raise
if nb_labels == 1:
self.set_labels_metric({labelvalue.labelname: labelvalue.labelvalue},
labelvalue.get())
else:
r.append((labelvalue.labelvalue, labelvalue.get()))

if nb_labels > 1:
labels[label.labelname] = r

if nb_labels > 1:
for n in range(0, nb_values):
r = {}
v = None
for labelname in self.metric._labelnames:
if len(labels[labelname]) <= n:
ref = labels[labelname][-1]
else:
ref = labels[labelname][n]

r[labelname] = ref[0]
if ref[1] is not None:
v = ref[1]
self.set_labels_metric(r, v)

if not has_label:
self.remove(True)

del data
del labels, data
11 changes: 8 additions & 3 deletions covenant/classes/controls.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@
import logging
import re

from covenant.classes.label import CovenantLabelValue
from covenant.classes.label import CovenantLabelValuesCollection, CovenantLabelValue

LOG = logging.getLogger('covenant.controls')

Expand All @@ -51,7 +51,7 @@ def _to_remove(key, kargs):
@classmethod
def dict(cls, *largs, **lkargs):
def g(*args, **kwargs):
r = []
r = CovenantLabelValuesCollection()
kargs = copy.copy(kwargs)

if not isinstance(kwargs['value'], dict):
Expand All @@ -69,8 +69,13 @@ def g(*args, **kwargs):
xlen = len(kwargs['value'])

for k, v in kwargs['value'].iteritems():
metricvalue = v
if 'value' in lkargs:
metricvalue = v.get(lkargs['value'])
if metricvalue is None:
metricvalue = lkargs.get('default')
kargs['value'] = CovenantLabelValue(labelvalue = k,
metricvalue = v,
metricvalue = metricvalue,
remove = cls._to_remove(k, lkargs))

if xlen == 1:
Expand Down
3 changes: 3 additions & 0 deletions covenant/classes/exceptions.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,3 +35,6 @@ def __init__(self, message = None, args = None):
return Exception.__init__(self, message.message, message.args)
else:
return Exception.__init__(self, message, args)

class CovenantTaskError(Exception):
pass
1 change: 1 addition & 0 deletions covenant/classes/filters.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
import copy
import logging

from covenant.classes.exceptions import CovenantConfigurationError
from sonicprobe.helpers import linesubst

LOG = logging.getLogger('covenant.plugins')
Expand Down
46 changes: 38 additions & 8 deletions covenant/classes/label.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,9 @@
import copy
import logging

from covenant.classes.exceptions import CovenantTargetFailed
from covenant.classes.exceptions import CovenantTaskError, CovenantTargetFailed
from covenant.classes.filters import CovenantNoResult
from sonicprobe import helpers

LOG = logging.getLogger('covenant.labels')

Expand Down Expand Up @@ -70,6 +71,10 @@ def vars(self):
'__labeldefault': self.labeldefault}


class CovenantLabelValuesCollection(list):
pass


class CovenantLabels(object):
def __init__(self,
labelname,
Expand All @@ -87,6 +92,8 @@ def __init__(self,
self.label_tasks = label_tasks
self.value_tasks = value_tasks
self._removed = False
self._orig = {'on_fail': on_fail,
'on_noresult': on_noresult}

self.on_fail = self._on(on_fail)
self.on_noresult = self._on(on_noresult)
Expand All @@ -113,6 +120,20 @@ def _on(self, cfg):

return default.copy()

def set_on_fail(self, cfg):
if not self._orig['on_fail']:
self.on_fail = self._on(cfg)

def set_on_noresult(self, cfg):
if not self._orig['on_noresult']:
self.on_noresult = self._on(cfg)

def labels(self):
r = {}
for labelvalue in self.labelvalues:
r[labelvalue.labelname] = labelvalue.labelvalue
return r

def remove(self, val = True):
self._removed = bool(val)
return self
Expand Down Expand Up @@ -166,7 +187,10 @@ def task_label(self, data):

value = task(value = value)

nvalues.append(value)
if not isinstance(value, CovenantLabelValuesCollection):
nvalues.append(value)
else:
nvalues.extend(value)

if nolabelvalue:
nvalues = [self.on_noresult['labelvalue']]
Expand All @@ -185,11 +209,8 @@ def task_label(self, data):

return self

def task_value(self, data, value_tasks = None):
def task_value(self, data, value_tasks = None, collect_value = None, collect_default = None):
tasks = value_tasks or self.value_tasks
if not tasks:
return self

(failed, noresult) = (False, False)

if isinstance(data, CovenantTargetFailed):
Expand All @@ -203,9 +224,11 @@ def task_value(self, data, value_tasks = None):
noresult = True
data = copy.copy(self.on_noresult['value'])

value = None

for labelvalue in self.labelvalues:
value = copy.copy(data)
if not failed and not noresult:
if not failed and not noresult and tasks:
for task in tasks:
if isinstance(value, CovenantNoResult):
if self.on_noresult['remove']:
Expand All @@ -217,7 +240,14 @@ def task_value(self, data, value_tasks = None):
if self.on_noresult['remove']:
return self.remove(True)
value = self.on_noresult['value']
labelvalue.set(value)
if helpers.is_scalar(value):
labelvalue.set(value)
elif collect_value is not None:
labelvalue.set(collect_value)
elif collect_default is not None:
labelvalue.set(collect_default)
elif tasks:
raise CovenantTaskError("unable to fetch metricvalue for labelvalue: %r" % labelvalue.labelvalue)

del value

Expand Down

0 comments on commit 40d0b4e

Please sign in to comment.