def test_tags_from_returns_empty_list_on_no_match(self): # arrange kwargs my_kwargs = { "message": { "payload": {} }, "another_message": { "payload": {} } } # act tags = Resolver.resolve_tags_from(tags_from=None, **my_kwargs) # assert self.assertEqual(tags, []) # act tags = Resolver.resolve_tags_from(tags_from={ "message": None, "another_message": None }, **my_kwargs) # assert self.assertEqual(tags, []) # act tags = Resolver.resolve_tags_from(tags_from={ "message": [], "another_message": [] }, **my_kwargs) # assert self.assertEqual(tags, []) # act tags = Resolver.resolve_tags_from(tags_from={ "message": [None, "adsad", [], {}], "another_message": [None, "adsad", [], {}] }, **my_kwargs) # assert self.assertEqual(tags, []) # act tags = Resolver.resolve_tags_from(tags_from={ "message": ["type", "schema"], "another_message": ["type", "schema"] }, **my_kwargs) # assert self.assertEqual(tags, [])
def test_tags_from_returns_tags_from_message_and_another_message(self): # arrange kwargs my_kwargs = { "message": { "type": "this_is_the_event_type_from_message", "schema": "this_is_the_event_schema_from_message", "payload": {} }, "another_message": { "type": "this_is_the_event_type_from_another_message", "schema": "this_is_the_event_schema_from_another_message", "payload": {} } } # act tags = Resolver.resolve_tags_from(tags_from={ "message": ["type", "schema"], "another_message": ["type", "schema"] }, **my_kwargs) # assert self.assertEqual(tags, [ "type:this_is_the_event_type_from_message", "schema:this_is_the_event_schema_from_message", "type:this_is_the_event_type_from_another_message", "schema:this_is_the_event_schema_from_another_message" ])
def test_trace_id_returns_value(self): kwargs = {"message": {"eventId": "aaaa-1111-bbbb-2222-cccc"}} trace_id = Resolver.resolve_trace_id( trace_id_from={"message": "eventId"}, **kwargs) self.assertEqual(trace_id, "aaaa-1111-bbbb-2222-cccc")
def test_tags_from_returns_tags_from_message_no_payload_of_message(self): """This tests that even if the user requests tags from the payload, it still just resolves the first level tags. Note: This can be implemented later if desired. """ # arrange kwargs my_kwargs = { "message": { "type": "this_is_the_event_type_from_message", "schema": "this_is_the_event_schema_from_message", "payload": { "name": "observe" } } } # act tags = Resolver.resolve_tags_from( tags_from={"message": ["type", "schema", { "payload": ["name"] }]}, **my_kwargs) # assert self.assertEqual(tags, [ "type:this_is_the_event_type_from_message", "schema:this_is_the_event_schema_from_message" ])
def test_tags_from_returns_empty_list_on_tag_value_not_string(self): # arrange kwargs my_kwargs = {"message": {"type": 1234}} # act tags = Resolver.resolve_tags_from(tags_from={"message": ["type"]}, **my_kwargs) # assert self.assertEqual(tags, [])
def test_tags_from_returns_empty_list_on_message_not_dict(self): # arrange kwargs my_kwargs = {"message": "type"} # act tags = Resolver.resolve_tags_from( tags_from={"message": ["type", "schema"]}, **my_kwargs) # assert self.assertEqual(tags, [])
def test_threshold_1800001ms(self): """This tests that the last value of the threshold map is returns correctly. """ # arrange process_time = 1800001 # act tag = Resolver.resolve_observed_sli_tag(process_time=process_time) # assert self.assertEqual(tag, "observed_sli:OVER_30min")
def test_threshold_100ms(self): """This tests that the first value of the threshold map is returned correctly, at the edge to the second value. """ # arrange process_time = 100 # act tag = Resolver.resolve_observed_sli_tag(process_time=process_time) # assert self.assertEqual(tag, "observed_sli:100ms")
def test_identity_from_function(self): # arrange args def process_function(): pass # act identity = Resolver.resolve_identity(func=process_function) # assert self.assertEqual(identity, "process_function()")
def test_identity_from_class(self): # arrange class MainProcess: def start(self): pass # act identity = Resolver.resolve_identity(MainProcess(), func=None) # assert self.assertEqual(identity, "MainProcess()")
def test_tags_from_returns_tags_from_message_type_only(self): # arrange kwargs my_kwargs = { "message": { "type": "this_is_the_event_type_from_message" } } # act tags = Resolver.resolve_tags_from( tags_from={"message": ["type", "schema"]}, **my_kwargs) # assert self.assertEqual(tags, ["type:this_is_the_event_type_from_message"])
def test_tags_from_returns_empty_list_on_no_kwargs(self): # act tags = Resolver.resolve_tags_from(tags_from=None) # assert self.assertEqual(tags, []) # act tags = Resolver.resolve_tags_from(tags_from={ "message": None, "another_message": None }) # assert self.assertEqual(tags, []) # act tags = Resolver.resolve_tags_from(tags_from={ "message": [], "another_message": [] }) # assert self.assertEqual(tags, []) # act tags = Resolver.resolve_tags_from( tags_from={ "message": [None, "adsad", [], {}], "another_message": [None, "adsad", [], {}] }) # assert self.assertEqual(tags, []) # act tags = Resolver.resolve_tags_from(tags_from={ "message": ["type", "schema"], "another_message": ["type", "schema"] }) # assert self.assertEqual(tags, [])
def test_threshold_map(self): """This tests the whole algorithm to obtain tags, excluding last value. """ timings = list(observe_threshold_map.keys()) expected_tags = list(observe_threshold_map.values()) for i, process_time in enumerate(timings): tag = Resolver.resolve_observed_sli_tag(process_time=process_time) if i == 0: self.assertEqual(tag, "observed_sli:%s" % (expected_tags[i])) else: # return always the last value of the current match self.assertEqual(tag, "observed_sli:%s" % (expected_tags[i - 1]))
def test_trace_id_returns_empty_string(self): trace_id = Resolver.resolve_trace_id(trace_id_from=None) self.assertEqual(trace_id, "") trace_id = Resolver.resolve_trace_id(trace_id_from=1337) self.assertEqual(trace_id, "") trace_id = Resolver.resolve_trace_id(trace_id_from="") self.assertEqual(trace_id, "") trace_id = Resolver.resolve_trace_id(trace_id_from={}) self.assertEqual(trace_id, "") trace_id = Resolver.resolve_trace_id(trace_id_from=[]) self.assertEqual(trace_id, "") trace_id = Resolver.resolve_trace_id( trace_id_from={"message": "eventId"}) self.assertEqual(trace_id, "")
def test_identity_default(self): # act identity = Resolver.resolve_identity(func=None, trace_id="abcd") # assert self.assertEqual(identity, "observe(abcd)")
def inner(*args: Any, **kwargs: Any) -> Any: # setup tracing and tags trace_id = Resolver.resolve_trace_id(trace_id_from=trace_id_from, **kwargs) identity = Resolver.resolve_identity(*args, func=func, trace_id=trace_id) additional_tags = Resolver.resolve_tags_from(tags_from=tags_from, **kwargs) all_tags = additional_tags + static_tags imetric = Provider.get_metric(*args) # start timing time_start: float = time.monotonic() try: # actual function execution response: Any = func(*args, **kwargs) # calculate process time process_time = int(time.monotonic() - time_start) * 1000 # append extra tags all_tags.append( Resolver.resolve_observed_sli_tag( process_time=process_time)) # send metrics, finished successfully imetric.timing("%s.time.finished" % metric, process_time, all_tags) imetric.gauge("%s.time_gauge.finished" % metric, process_time, all_tags) imetric.increment("%s.finished" % metric, 1, all_tags) except Exception as ex: # calculate process time process_time = int(time.monotonic() - time_start) * 1000 # append extra tags all_tags.append('exception:%s' % type(ex).__name__) all_tags.append( Resolver.resolve_observed_sli_tag( process_time=process_time)) # accept on, returns True if type(ex) in accept_on: # log warning Provider.get_logger(*args).warning( "%s: %s(%s) during '%s' accepted.\n%s" % (identity, type(ex).__name__, ex, func.__name__, traceback.format_exc())) # send metrics, raised but accepted imetric.timing("%s.time.accepted" % metric, process_time, all_tags) imetric.gauge("%s.time_gauge.accepted" % metric, process_time, all_tags) imetric.increment('%s.exception.accepted' % metric, 1, all_tags) # return truthy, to be acknowledged return True # decline on, returns False if type(ex) in decline_on: # log error Provider.get_logger(*args).error( "%s: %s(%s) during '%s' declined.\n%s" % (identity, type(ex).__name__, ex, func.__name__, traceback.format_exc())) # send metrics, raised but declined imetric.timing("%s.time.declined" % metric, process_time, all_tags) imetric.gauge("%s.time_gauge.declined" % metric, process_time, all_tags) imetric.increment('%s.exception.declined' % metric, 1, all_tags) # return falsy, not to be acknowledged return False # unhandled exception, log error Provider.get_logger(*args).error( "%s: %s(%s) during '%s' raised.\n%s" % (identity, type(ex).__name__, ex, func.__name__, traceback.format_exc())) # send metrics, raised and unhandled imetric.timing("%s.time.raised" % metric, process_time, all_tags) imetric.gauge("%s.time_gauge.raised" % metric, process_time, all_tags) imetric.increment('%s.exception.raised' % metric, 1, all_tags) # check if notification client available slack = Provider.get_slack(*args) if slack: # notify slack.error(header=identity, title=type(ex).__name__, text=f"{ex}\n{traceback.format_exc()}") # re-raise raise ex finally: # send metric, start imetric.increment("%s.start" % metric, 1, all_tags) # return actual response of the function return response