Advertisement
Guest User

Untitled

a guest
Mar 1st, 2019
72
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 6.82 KB | None | 0 0
  1. #
  2. # Licensed to the Apache Software Foundation (ASF) under one or more
  3. # contributor license agreements.  See the NOTICE file distributed with
  4. # this work for additional information regarding copyright ownership.
  5. # The ASF licenses this file to You under the Apache License, Version 2.0
  6. # (the "License"); you may not use this file except in compliance with
  7. # the License.  You may obtain a copy of the License at
  8. #
  9. #    http://www.apache.org/licenses/LICENSE-2.0
  10. #
  11. # Unless required by applicable law or agreed to in writing, software
  12. # distributed under the License is distributed on an "AS IS" BASIS,
  13. # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  14. # See the License for the specific language governing permissions and
  15. # limitations under the License.
  16. #
  17. """MetricResult matchers for validating metrics in PipelineResults.
  18.  
  19. example usage:
  20.    result = my_pipeline.run()
  21.    all_metrics = result.metrics().all_metrics()
  22.  
  23.    matchers = [
  24.      MetricResultMatcher(
  25.          namespace='myNamespace',
  26.          name='myName',
  27.          step='myStep',
  28.          labels={
  29.              'pcollection': 'myCollection',
  30.              'myCustomKey': 'myCustomValue'
  31.          },
  32.          attempted=42,
  33.          committed=42
  34.      )
  35.    ]
  36.    errors = metric_result_matchers.verify_all(all_metrics, matchers)
  37.    self.assertFalse(errors, errors)
  38. """
  39.  
  40. from __future__ import absolute_import
  41.  
  42. from hamcrest import equal_to
  43. from hamcrest.core import string_description
  44. from hamcrest.core.base_matcher import BaseMatcher
  45. from hamcrest.core.matcher import Matcher
  46.  
  47. from apache_beam.metrics.cells import DistributionResult
  48.  
  49.  
  50. def _matcher_or_equal_to(value_or_matcher):
  51.   """Pass-thru for matchers, and wraps value inputs in an equal_to matcher."""
  52.   if value_or_matcher is None:
  53.     return None
  54.   if isinstance(value_or_matcher, Matcher):
  55.     return value_or_matcher
  56.   return equal_to(value_or_matcher)
  57.  
  58.  
  59. class MetricResultMatcher(BaseMatcher):
  60.   """A PyHamcrest matcher that validates counter MetricResults."""
  61.  
  62.   def __init__(self, namespace=None, name=None, step=None, labels=None,
  63.                attempted=None, committed=None, sum_value=None, count_value=None,
  64.                min_value=None, max_value=None,):
  65.     self.namespace = _matcher_or_equal_to(namespace)
  66.     self.name = _matcher_or_equal_to(name)
  67.     self.step = _matcher_or_equal_to(step)
  68.     self.attempted = _matcher_or_equal_to(attempted)
  69.     self.committed = _matcher_or_equal_to(committed)
  70.     labels = labels or dict()
  71.     self.label_matchers = dict()
  72.     for (k, v) in labels.items():
  73.       self.label_matchers[_matcher_or_equal_to(k)] = _matcher_or_equal_to(v)
  74.  
  75.   def _matches(self, metric_result):
  76.     if self.namespace is not None and not self.namespace.matches(
  77.         metric_result.key.metric.namespace):
  78.       return False
  79.     if self.name and not self.name.matches(metric_result.key.metric.name):
  80.       return False
  81.     if self.step and not self.step.matches(metric_result.key.step):
  82.       return False
  83.     if (self.attempted is not None and
  84.         not self.attempted.matches(metric_result.attempted)):
  85.       return False
  86.     if (self.committed is not None and
  87.         not self.committed.matches(metric_result.committed)):
  88.       return False
  89.     for (k_matcher, v_matcher) in self.label_matchers.items():
  90.       matched_keys = [key for key in metric_result.key.labels.keys() if
  91.                       k_matcher.matches(key)]
  92.       matched_key = matched_keys[0] if matched_keys else None
  93.       if not matched_key:
  94.         return False
  95.       label_value = metric_result.key.labels[matched_key]
  96.       if not v_matcher.matches(label_value):
  97.         return False
  98.     return True
  99.  
  100.   def describe_to(self, description):
  101.     if self.namespace:
  102.       description.append_text(' namespace: ')
  103.       self.namespace.describe_to(description)
  104.     if self.name:
  105.       description.append_text(' name: ')
  106.       self.name.describe_to(description)
  107.     if self.step:
  108.       description.append_text(' step: ')
  109.       self.step.describe_to(description)
  110.     for (k_matcher, v_matcher) in self.label_matchers.items():
  111.       description.append_text(' (label_key: ')
  112.       k_matcher.describe_to(description)
  113.       description.append_text(' label_value: ')
  114.       v_matcher.describe_to(description)
  115.       description.append_text('). ')
  116.     if self.attempted is not None:
  117.       description.append_text(' attempted: ')
  118.       self.attempted.describe_to(description)
  119.     if self.committed is not None:
  120.       description.append_text(' committed: ')
  121.       self.committed.describe_to(description)
  122.  
  123.   def describe_mismatch(self, metric_result, mismatch_description):
  124.     mismatch_description.append_text("was").append_value(metric_result)
  125.  
  126.  
  127. class DistributionMatcher(BaseMatcher):
  128.   """A PyHamcrest matcher that validates counter distributions."""
  129.  
  130.   def __init__(self, sum_value=None, count_value=None, min_value=None,
  131.                max_value=None):
  132.     self.sum_value = _matcher_or_equal_to(sum_value)
  133.     self.count_value = _matcher_or_equal_to(count_value)
  134.     self.min_value = _matcher_or_equal_to(min_value)
  135.     self.max_value = _matcher_or_equal_to(max_value)
  136.  
  137.   def _matches(self, distribution_result):
  138.     if not isinstance(distribution_result, DistributionResult):
  139.       return False
  140.     if self.sum_value and not self.sum_value.matches(distribution_result.sum):
  141.       return False
  142.     if self.count_value and not self.count_value.matches(
  143.         distribution_result.count):
  144.       return False
  145.     if self.min_value and not self.min_value.matches(distribution_result.min):
  146.       return False
  147.     if self.max_value and not self.max_value.matches(distribution_result.max):
  148.       return False
  149.     return True
  150.  
  151.   def describe_to(self, description):
  152.     if self.sum_value:
  153.       description.append_text(' sum_value: ')
  154.       self.sum_value.describe_to(description)
  155.     if self.count_value:
  156.       description.append_text(' count_value: ')
  157.       self.count_value.describe_to(description)
  158.     if self.min_value:
  159.       description.append_text(' min_value: ')
  160.       self.min_value.describe_to(description)
  161.     if self.max_value:
  162.       description.append_text(' max_value: ')
  163.       self.max_value.describe_to(description)
  164.  
  165.   def describe_mismatch(self, distribution_result, mismatch_description):
  166.     mismatch_description.append_text('was').append_value(distribution_result)
  167.  
  168.  
  169. def verify_all(all_metrics, matchers):
  170.   errors = []
  171.   matched_metrics = []
  172.   for matcher in matchers:
  173.     matched_metrics = [mr for mr in all_metrics if matcher.matches(mr)]
  174.     if not matched_metrics:
  175.       errors.append('Unable to match metrics for matcher %s' % (
  176.           string_description.tostring(matcher)))
  177.   if errors:
  178.     errors.append('\nActual MetricResults:\n' +
  179.                   '\n'.join([str(mr) for mr in all_metrics]))
  180.   return ''.join(errors)
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement