def test_runner_duration(_wrapped_post): runner = RunnerEventMock() runner.terminated = False trace = trace_factory.get_or_create_trace() trace.token = 'a' trace.set_runner(runner) time.sleep(0.2) trace.send_traces() assert 0.2 < runner.duration < 0.3
def test_send_on_error_only_off_no_error(wrapped_post): trace = trace_factory.get_or_create_trace() trace.token = 'a' trace.runner = mock.MagicMock() trace.runner.error_code = ErrorCode.OK event = EventMock() event.resource['metadata'] = datetime.fromtimestamp(1000) trace.add_event(event) trace.send_traces() wrapped_post.assert_called_once()
def test_send_traces_sanity(wrapped_post): trace = trace_factory.get_or_create_trace() trace.token = 'a' trace.send_traces() wrapped_post.assert_called_with( '', data=json.dumps(trace.to_dict()), timeout=epsagon.constants.SEND_TIMEOUT, headers={'Authorization': 'Bearer {}'.format(trace.token)} )
def test_send_with_split_off(wrapped_post): # Should be low enough to force trace split. os.environ['EPSAGON_MAX_TRACE_SIZE'] = '500' trace = trace_factory.get_or_create_trace() trace.runner = mock.MagicMock() trace.add_event(trace.runner) trace.token = 'a' trace.split_on_send = False for _ in range(10): event = EventMock() trace.add_event(event) trace.send_traces() wrapped_post.assert_called_once()
def test_event_with_datetime(wrapped_post): trace = trace_factory.get_or_create_trace() trace.token = 'a' event = EventMock() event.resource['metadata'] = datetime.fromtimestamp(1000) trace.add_event(event) trace.send_traces() wrapped_post.assert_called_with( '', data=json.dumps(trace.to_dict(), cls=TraceEncoder), timeout=epsagon.constants.SEND_TIMEOUT, headers={'Authorization': 'Bearer {}'.format(trace.token)} )
def test_timeout_happyflow_handler_call(wrapped_post): """ Test in case we already sent the traces on happy flow, that timeout handler call won't send them again. """ context = ContextMock(300) runner = RunnerEventMock() trace = trace_factory.get_or_create_trace() trace.set_runner(runner) trace.token = 'a' trace.send_traces() trace.set_timeout_handler(context) time.sleep(0.5) trace.reset_timeout_handler() assert trace.trace_sent assert wrapped_post.call_count == 1
def _gcp_wrapper(*args, **kwargs): """ Generic google function wrapper """ trace = epsagon.trace.trace_factory.get_or_create_trace() trace.prepare() try: runner = GoogleFunctionRunner(time.time(), ) # pylint: disable=W0703 except Exception as exception: # Regress to python runner. warnings.warn( 'GCP environment is invalid, using simple python wrapper', EpsagonWarning) trace.add_exception(exception, traceback.format_exc()) return epsagon.wrappers.python_function.wrap_python_function( func, args, kwargs) constants.COLD_START = False result = None try: result = func(*args, **kwargs) return result # pylint: disable=W0703 except Exception as exception: runner.set_exception(exception, traceback.format_exc()) raise finally: try: if not trace.metadata_only: add_return_value(runner, result) # pylint: disable=W0703 except Exception as exception: trace.add_exception(exception, traceback.format_exc()) try: trace.add_event(runner) trace.send_traces() # pylint: disable=W0703 except Exception: pass
def _teardown_request(self, exception): """ Runs at the end of the request. Exception will be passed if happens. :param exception: Exception (or None). :return: None. """ if self.ignored_request: return if exception: self.exception_handler[sys.version_info.major](exception) # Ignoring endpoint, only if no error happened. if not exception and request.url_rule.rule in self.ignored_endpoints: return trace = epsagon.trace.trace_factory.get_or_create_trace() trace.send_traces() trace.prepare()
def test_send_big_trace(wrapped_post): trace = trace_factory.get_or_create_trace() runner = RunnerEventMock() trace.set_runner(runner) trace.token = 'a' for _ in range(2): trace.add_event(BigEventMock()) trace.send_traces() assert len(trace.to_dict()['events']) == 3 for event in trace.to_dict()['events']: if event['origin'] == 'runner': assert event['resource']['metadata']['is_trimmed'] wrapped_post.assert_called_with( '', data=json.dumps(trace.to_dict()), timeout=epsagon.constants.SEND_TIMEOUT, headers={'Authorization': 'Bearer {}'.format(trace.token)} )
def test_send_traces_no_token(wrapped_post): trace = trace_factory.get_or_create_trace() trace.send_traces() wrapped_post.assert_not_called()
def _lambda_wrapper(*args, **kwargs): """ Generic Lambda function wrapper """ trace = epsagon.trace.trace_factory.get_or_create_trace() trace.prepare() try: event, context = args except ValueError: # This can happen when someone manually calls handler without # parameters / sends kwargs. In such case we ignore this trace. return func(*args, **kwargs) try: runner = epsagon.runners.aws_lambda.LambdaRunner( time.time(), context) trace.set_runner(runner) # pylint: disable=W0703 except Exception as exception: # Regress to python runner. warnings.warn( 'Lambda context is invalid, using simple python wrapper', EpsagonWarning) trace.add_exception(exception, traceback.format_exc()) return epsagon.wrappers.python_function.wrap_python_function( func, args, kwargs) constants.COLD_START = False try: trace.add_event( epsagon.triggers.aws_lambda.LambdaTriggerFactory.factory( time.time(), event, context)) # pylint: disable=W0703 except Exception as exception: trace.add_exception(exception, traceback.format_exc(), additional_data={'event': event}) if not trace.disable_timeout_send: trace.set_timeout_handler(context) result = None try: result = func(*args, **kwargs) return result # pylint: disable=W0703 except Exception as exception: runner.set_exception(exception, traceback.format_exc()) raise finally: try: if not trace.metadata_only: add_return_value(runner, result) # pylint: disable=W0703 except Exception as exception: trace.add_exception( exception, traceback.format_exc(), ) try: if not trace.disable_timeout_send: epsagon.trace.Trace.reset_timeout_handler() # pylint: disable=W0703 except Exception: pass try: trace.send_traces() # pylint: disable=W0703 except Exception: pass
def _lambda_wrapper(*args, **kwargs): """ Generic Step Function wrapper """ trace = epsagon.trace.trace_factory.get_or_create_trace() trace.prepare() try: event, context = args except ValueError: # This can happen when someone manually calls handler without # parameters / sends kwargs. In such case we ignore this trace. return func(*args, **kwargs) try: runner = epsagon.runners.aws_lambda.StepLambdaRunner( time.time(), context) trace.set_runner(runner) # pylint: disable=W0703 except Exception as exception: # Regress to python runner. warnings.warn( 'Lambda context is invalid, using simple python wrapper', EpsagonWarning) trace.add_exception(exception, traceback.format_exc()) return epsagon.wrappers.python_function.wrap_python_function( func, args, kwargs) constants.COLD_START = False try: trace.add_event( epsagon.triggers.aws_lambda.LambdaTriggerFactory.factory( time.time(), event, context)) # pylint: disable=W0703 except Exception as exception: trace.add_exception(exception, traceback.format_exc(), additional_data={'event': event}) trace.set_timeout_handler(context) result = None try: result = func(*args, **kwargs) steps_dict = epsagon.utils.find_in_object(event, STEP_DICT_NAME) if isinstance(result, dict): # If the step functions data is not present, then this is the # First step. if steps_dict is None: steps_dict = {'id': str(uuid4()), 'step_num': 0} # Otherwise, just advance the steps number by one. else: # don't change trigger data steps_dict = copy.deepcopy(steps_dict) steps_dict['step_num'] += 1 result[STEP_DICT_NAME] = steps_dict runner.add_step_data(steps_dict) return result # pylint: disable=W0703 except Exception as exception: runner.set_exception(exception, traceback.format_exc()) raise finally: try: if not trace.metadata_only: add_return_value(runner, result) # pylint: disable=W0703 except Exception as exception: trace.add_exception( exception, traceback.format_exc(), ) try: epsagon.trace.Trace.reset_timeout_handler() # pylint: disable=W0703 except Exception: pass try: trace.send_traces() # pylint: disable=W0703 except Exception: pass