From 5c6dddfc6ea62e8e7989583d36c92fbb7838f783 Mon Sep 17 00:00:00 2001 From: Joseph Davis Date: Thu, 20 Dec 2018 14:52:20 -0800 Subject: [PATCH] Add the metric name to the Exception message when validation fails In the general validate_metric case, when possible add the metric name to the exception message. This makes it much easier to track down what metric failed. Also, fixing code where an exception could be thrown but then immediately ignored and another exception fo the same type with a different message would be thrown. Change-Id: I8b8f04bb98a65b6904894dc00af88ea367a350f8 Story: 2004185 Task: 27675 --- .../validation/test_metric_validation.py | 20 +++++++++++-- monasca_common/validation/metrics.py | 28 +++++++++++-------- 2 files changed, 35 insertions(+), 13 deletions(-) diff --git a/monasca_common/tests/validation/test_metric_validation.py b/monasca_common/tests/validation/test_metric_validation.py index 81e0976e..e5bfbd61 100644 --- a/monasca_common/tests/validation/test_metric_validation.py +++ b/monasca_common/tests/validation/test_metric_validation.py @@ -281,6 +281,21 @@ class TestMetricValidation(base.BaseTestCase): value, metric_validator.validate, metric) + def test_invalid_value_includes_metric(self): + """When it fails, does it include the metric name in the ex?""" + metric = {"name": "test_metric_name", + "dimensions": {"key1": "value1", + "key2": "value2"}, + "timestamp": 1405630174123, + "value": None} + + for value in ('nan', 'inf', '-inf'): + metric['value'] = float(value) + self.assertRaisesRegex( + metric_validator.InvalidValue, + "for metric test_metric_name", + metric_validator.validate, metric) + def test_valid_name_chars(self): for c in valid_name_chars: metric = {"name": 'test{}counter'.format(c), @@ -335,7 +350,7 @@ class TestMetricValidation(base.BaseTestCase): def test_invalid_too_many_value_meta(self): value_meta = {} - for i in six.moves.range(0, 17): + for i in six.moves.range(0, metric_validator.VALUE_META_MAX_NUMBER + 3): value_meta['key{}'.format(i)] = 'value{}'.format(i) metric = {"name": "test_metric_name", "dimensions": {"key1": "value1", @@ -393,8 +408,9 @@ class TestMetricValidation(base.BaseTestCase): "value": 5} self.assertRaisesRegex( metric_validator.InvalidValueMeta, - "Unable to serialize valueMeta into JSON", + "value combinations must be", metric_validator.validate, metric) + # TODO: what would make ujson.dumps fail? def test_invalid_timestamp(self): metric = {'name': 'test_metric_name', diff --git a/monasca_common/validation/metrics.py b/monasca_common/validation/metrics.py index 816f9121..e75bc9b4 100644 --- a/monasca_common/validation/metrics.py +++ b/monasca_common/validation/metrics.py @@ -17,6 +17,7 @@ import math import re import six +import sys import ujson # This is used to ensure that metrics with a timestamp older than @@ -77,12 +78,17 @@ def validate(metrics): def validate_metric(metric): validate_name(metric['name']) - validate_value(metric['value']) - validate_timestamp(metric['timestamp']) - if "dimensions" in metric: - validate_dimensions(metric['dimensions']) - if "value_meta" in metric: - validate_value_meta(metric['value_meta']) + try: + validate_value(metric['value']) + validate_timestamp(metric['timestamp']) + if "dimensions" in metric: + validate_dimensions(metric['dimensions']) + if "value_meta" in metric: + validate_value_meta(metric['value_meta']) + except Exception as ex: + six.reraise(type(ex), + type(ex)(str(ex) + ": for metric %s" % metric['name']), + sys.exc_info()[2]) def validate_value_meta(value_meta): @@ -103,13 +109,13 @@ def validate_value_meta(value_meta): try: value_meta_json = ujson.dumps(value_meta) - if len(value_meta_json) > VALUE_META_VALUE_MAX_LENGTH: - msg = "valueMeta name value combinations must be {0} characters " \ - "or less: valueMeta {1}".format(VALUE_META_VALUE_MAX_LENGTH, - value_meta) - raise InvalidValueMeta(msg) except Exception: raise InvalidValueMeta("Unable to serialize valueMeta into JSON") + if len(value_meta_json) > VALUE_META_VALUE_MAX_LENGTH: + msg = "valueMeta name value combinations must be {0} characters " \ + "or less: valueMeta {1}".format(VALUE_META_VALUE_MAX_LENGTH, + value_meta) + raise InvalidValueMeta(msg) def validate_dimension_key(k):