def test_outbound_payload_outside_transaction(mock_grpc_server, method_type, method_name, stub): request_type, response_type = method_type.split('_', 1) streaming_request = request_type == 'stream' streaming_response = response_type == 'stream' stub_method = 'DtNoTxn' + method_type.title().replace('_', '') request = create_request(streaming_request) method_callable = getattr(stub, stub_method) method = getattr(method_callable, method_name) reply = method(request) if isinstance(reply, tuple): reply = reply[0] try: # If the reply was canceled or the server code raises an exception, # this will raise an exception which will be recorded by the agent if streaming_response: reply = list(reply) else: reply = [reply.result()] except (AttributeError, TypeError): reply = [reply] # Verify there were no DT headers sent metadata = json.loads(reply[0].text) assert 'newrelic' not in metadata assert 'traceparent' not in metadata assert 'tracestate' not in metadata
def test_simple(method_name, streaming_request, mock_grpc_server, stub): port = mock_grpc_server request = create_request(streaming_request) _transaction_name = \ "sample_application:SampleApplicationServicer.{}".format(method_name) method = getattr(stub, method_name) @validate_transaction_metrics(_transaction_name) @override_application_settings({'attributes.include': ['request.*']}) @validate_transaction_event_attributes(required_params={ 'agent': [ 'request.uri', 'request.headers.userAgent', 'response.status', 'response.headers.contentType' ], 'user': [], 'intrinsic': ['port'], }, exact_attrs={ 'agent': {}, 'user': {}, 'intrinsic': { 'port': port } }) @wait_for_transaction_completion def _doit(): response = method(request) try: list(response) except Exception: pass _doit()
def test_newrelic_disabled_no_transaction(mock_grpc_server, stub): port = mock_grpc_server request = create_request(False) method = getattr(stub, 'DoUnaryUnary') @override_generic_settings(global_settings(), {'enabled': False}) @function_not_called('newrelic.core.stats_engine', 'StatsEngine.record_transaction') @wait_for_transaction_completion def _doit(): method(request) _doit()
def test_raises_response_status(method_name, streaming_request, mock_grpc_server, stub): port = mock_grpc_server request = create_request(streaming_request) method_name = method_name + 'Raises' _transaction_name = \ "sample_application:SampleApplicationServicer.{}".format(method_name) method = getattr(stub, method_name) status_code = str(grpc.StatusCode.UNKNOWN.value[0]) @validate_code_level_metrics( "sample_application.SampleApplicationServicer", method_name) @validate_transaction_errors(errors=[ select_python_version(py2='exceptions:AssertionError', py3='builtins:AssertionError') ]) @validate_transaction_metrics(_transaction_name) @override_application_settings({'attributes.include': ['request.*']}) @validate_transaction_event_attributes(required_params={ 'agent': ['request.uri', 'request.headers.userAgent', 'response.status'], 'user': [], 'intrinsic': ['port'], }, exact_attrs={ 'agent': { 'response.status': status_code }, 'user': {}, 'intrinsic': { 'port': port } }) @wait_for_transaction_completion def _doit(): try: response = method(request) list(response) except Exception: pass _doit()
def test_abort(method_name, streaming_request, mock_grpc_server, stub): port = mock_grpc_server request = create_request(streaming_request) method = getattr(stub, method_name + 'Abort') @validate_transaction_errors(errors=[ select_python_version(py2='exceptions:Exception', py3='builtins:Exception') ]) @wait_for_transaction_completion def _doit(): with pytest.raises(grpc.RpcError) as error: response = method(request) list(response) assert error.value.details() == 'aborting' assert error.value.code() == grpc.StatusCode.ABORTED _doit()
def test_inbound_distributed_trace(mock_grpc_server, method_name, streaming_request, stub): request = create_request(streaming_request) transaction = Transaction(application_instance()) dt_headers = ExternalTrace.generate_request_headers(transaction) @validate_transaction_metrics( 'sample_application:SampleApplicationServicer.' + method_name, rollup_metrics=(('Supportability/TraceContext/Accept/Success', 1), ), ) @wait_for_transaction_completion def _test(): method = getattr(stub, method_name) response = method(request, metadata=dt_headers) try: list(response) except Exception: pass _test()
def test_no_exception_client_close(mock_grpc_server): port = mock_grpc_server # We can't use the stub_and_channel fixture here as closing # that channel will cause any subsequent tests to fail. # Instead we create a brand new channel to close. stub, channel = create_stub_and_channel(port) with channel: request = create_request(False, timesout=True) method = getattr(stub, 'DoUnaryUnary') @validate_transaction_errors(errors=[]) @wait_for_transaction_completion def _doit(): future_response = method.future(request) channel.close() with pytest.raises(grpc.RpcError) as error: future_response.result() assert error.value.code() == grpc.StatusCode.CANCELLED _doit()
def test_abort_with_status(method_name, streaming_request, mock_grpc_server, stub): method_name += 'AbortWithStatus' port = mock_grpc_server request = create_request(streaming_request) method = getattr(stub, method_name) @validate_code_level_metrics( "sample_application.SampleApplicationServicer", method_name) @validate_transaction_errors(errors=[ select_python_version(py2='exceptions:Exception', py3='builtins:Exception') ]) @wait_for_transaction_completion def _doit(): with pytest.raises(grpc.RpcError) as error: response = method(request) list(response) assert error.value.details() == 'abort_with_status' assert error.value.code() == grpc.StatusCode.ABORTED _doit()
def test_outbound_distributed_trace(mock_grpc_server, method_type, method_name, dt_enabled, dt_error, stub): request_type, response_type = method_type.split('_', 1) streaming_request = request_type == 'stream' streaming_response = response_type == 'stream' stub_method = 'DtNoTxn' + method_type.title().replace('_', '') request = create_request(streaming_request) method_callable = getattr(stub, stub_method) method = getattr(method_callable, method_name) exact_intrinsics = { 'category': 'http', 'span.kind': 'client', } txn_name = 'test_outbound_DT[{0}-{1}-{2}-{3}]'.format( method_type, method_name, dt_enabled, dt_error) settings = {'distributed_tracing.enabled': dt_enabled} span_count = 1 if dt_enabled else 0 if dt_error: settings['trusted_account_key'] = None @override_application_settings(settings) @validate_span_events(count=span_count, exact_intrinsics=exact_intrinsics) @wait_for_transaction_completion @background_task(name=txn_name) def _test(): # Always mark sampled as True. current_transaction() is guaranteed to # be non-None here as test fixtures ensure activation prior to testing. current_transaction()._sampled = True reply = method(request) if isinstance(reply, tuple): reply = reply[0] try: # If the reply was canceled or the server code raises an exception, # this will raise an exception which will be recorded by the agent if streaming_response: reply = list(reply) else: reply = [reply.result()] except (AttributeError, TypeError): reply = [reply] metadata = json.loads(reply[0].text) if not dt_enabled or dt_error: assert 'newrelic' not in metadata assert 'traceparent' not in metadata assert 'tracestate' not in metadata else: decoded = DistributedTracePayload.decode(metadata['newrelic']) # The external span should be the parent exact_intrinsics['guid'] = decoded['d']['id'] # Check that tracestate / traceparent payload matches newrelic # payload w3c_data = W3CTraceParent.decode(metadata['traceparent']) nr_tracestate = list( W3CTraceState.decode(metadata['tracestate']).values())[0] nr_tracestate = NrTraceState.decode(nr_tracestate, None) w3c_data.update(nr_tracestate) # Remove all trust keys decoded['d'].pop('tk', None) w3c_data.pop('tk') assert decoded['d'] == w3c_data _test()