def _nr_aiohttp_add_cat_headers_(wrapped, instance, args, kwargs): transaction = current_transaction() if transaction is None: return wrapped(*args, **kwargs) try: cat_headers = ExternalTrace.generate_request_headers(transaction) except: return wrapped(*args, **kwargs) tmp = instance.headers instance.headers = HeaderProxy(tmp, cat_headers) if is_coroutine_function(wrapped): @asyncio.coroutine def new_coro(): try: result = yield from wrapped(*args, **kwargs) return result finally: instance.headers = tmp return new_coro() else: try: return wrapped(*args, **kwargs) finally: instance.headers = tmp
def httplib_endheaders_wrapper(wrapped, instance, args, kwargs): transaction = current_transaction() if transaction is None: return wrapped(*args, **kwargs) connection = instance # Check if the NR headers have already been added. This is just in # case a higher level library which uses httplib underneath so # happened to have been instrumented to also add the headers. try: skip_headers = getattr(connection, '_nr_skip_headers', False) if skip_headers: return wrapped(*args, **kwargs) outgoing_headers = ExternalTrace.generate_request_headers(transaction) for header_name, header_value in outgoing_headers: connection.putheader(header_name, header_value) return wrapped(*args, **kwargs) finally: try: del connection._nr_skip_headers except AttributeError: pass
def target_wsgi_application(environ, start_response): start_response('200 OK', [('Content-Type', 'application/json')]) txn = current_transaction() if txn._sampled is None: txn._sampled = True txn._priority = 1.2 headers = ExternalTrace.generate_request_headers(txn) return [json.dumps(headers).encode('utf-8')]
def target_wsgi_application(environ, start_response): status = '200 OK' txn_name = environ.get('txn') if six.PY2: txn_name = txn_name.decode('UTF-8') txn_name = txn_name.split('/', 3) guid = environ.get('guid') old_cat = environ.get('old_cat') == 'True' txn = current_transaction() txn.guid = guid for req in OUTBOUD_REQUESTS: # Change the transaction name before making an outbound call. outgoing_name = req['outboundTxnName'].split('/', 3) if outgoing_name[0] != 'WebTransaction': set_background_task(True) set_transaction_name(outgoing_name[2], group=outgoing_name[1]) expected_outbound_header = obfuscate( json_encode(req['expectedOutboundPayload']), ENCODING_KEY) generated_outbound_header = dict( ExternalTrace.generate_request_headers(txn)) # A 500 error is returned because 'assert' statements in the wsgi app # are ignored. if old_cat: if (expected_outbound_header != generated_outbound_header['X-NewRelic-Transaction']): status = '500 Outbound Headers Check Failed.' else: if 'X-NewRelic-Transaction' in generated_outbound_header: status = '500 Outbound Headers Check Failed.' r = urlopen(environ['server_url']) r.read(10) # Set the final transaction name. if txn_name[0] != 'WebTransaction': set_background_task(True) set_transaction_name(txn_name[2], group=txn_name[1]) text = '<html><head>%s</head><body><p>RESPONSE</p>%s</body></html>' output = (text % (get_browser_timing_header(), get_browser_timing_footer())).encode('UTF-8') response_headers = [('Content-type', 'text/html; charset=utf-8'), ('Content-Length', str(len(output)))] start_response(status, response_headers) return [output]
def _test_cat_headers(): transaction = current_transaction() payload = ExternalTrace.generate_request_headers(transaction) assert not payload trace = ExternalTrace('testlib', 'http://example.com') response_headers = [('X-NewRelic-App-Data', 'Cookies')] with trace: trace.process_response_headers(response_headers) assert transaction.settings.cross_application_tracer.enabled is False
def _nr_aiohttp_add_cat_headers_simple_(wrapped, instance, args, kwargs): transaction = current_transaction() if transaction is None: return wrapped(*args, **kwargs) try: cat_headers = ExternalTrace.generate_request_headers(transaction) except: return wrapped(*args, **kwargs) for k, _ in cat_headers: if k in instance.headers: return wrapped(*args, **kwargs) instance.headers.update(cat_headers) return wrapped(*args, **kwargs)
def _nr_wrap_PayloadWriter_write_headers(wrapped, instance, args, kwargs): transaction = current_transaction() if transaction is None: return wrapped(*args, **kwargs) status_line, headers, _args, _kwargs = _bind_write_headers( *args, **kwargs) try: cat_headers = ExternalTrace.generate_request_headers(transaction) updated_headers = dict(cat_headers + [(k, v) for k, v in headers.items()]) except: return wrapped(*args, **kwargs) return wrapped(status_line, updated_headers, *_args, **_kwargs)
def _nr_wrapper_httpclient_AsyncHTTPClient_fetch_(wrapped, instance, args, kwargs): transaction = current_transaction() if transaction is None: return wrapped(*args, **kwargs) try: req, _cb, _raise_error = _prepare_request(*args, **kwargs) except: return wrapped(*args, **kwargs) # Prepare outgoing CAT headers outgoing_headers = ExternalTrace.generate_request_headers(transaction) for header_name, header_value in outgoing_headers: # User headers should override our CAT headers if header_name in req.headers: continue req.headers[header_name] = header_value trace = ExternalTrace(transaction, 'tornado.httpclient', req.url, req.method.upper()) def external_trace_done(future): exc_info = future.exc_info() if exc_info: trace.__exit__(*exc_info) else: response = future.result() # Process CAT response headers trace.process_response_headers(response.headers.get_all()) trace.__exit__(None, None, None) trace.__enter__() if trace.transaction and trace.transaction.current_node is trace: # externals should not have children trace.transaction._pop_current(trace) try: future = wrapped(req, _cb, _raise_error) future.add_done_callback(external_trace_done) except Exception: trace.__exit__(*sys.exc_info()) raise return future
def _nr_wrapper_httpclient_AsyncHTTPClient_fetch_(wrapped, instance, args, kwargs): transaction = retrieve_current_transaction() if transaction is None: return wrapped(*args, **kwargs) req, _cb, _raise_error = _prepare_request(*args, **kwargs) # Prepare outgoing CAT headers outgoing_headers = ExternalTrace.generate_request_headers(transaction) for header_name, header_value in outgoing_headers: req.headers[header_name] = header_value trace = ExternalTrace(transaction, 'tornado.httpclient', req.url) def external_trace_done(future): exc_info = future.exc_info() if exc_info: trace.__exit__(*exc_info) else: response = future.result() # Process CAT response headers trace.process_response_headers(response.headers.get_all()) trace.__exit__(None, None, None) transaction._ref_count -= 1 transaction._ref_count += 1 trace.__enter__() # Because traces are terminal but can be generated concurrently in # tornado, pop the trace immediately after entering. if trace.transaction and trace.transaction.current_node is trace: trace.transaction._pop_current(trace) try: future = wrapped(req, _cb, _raise_error) future.add_done_callback(external_trace_done) except Exception: transaction._ref_count -= 1 trace.__exit__(*sys.exc_info()) raise return future
def _validate_synthetics_external_trace_header(wrapped, instance, args, kwargs): def _bind_params(transaction, *args, **kwargs): return transaction transaction = _bind_params(*args, **kwargs) try: result = wrapped(*args, **kwargs) except: raise else: if should_exist: # XXX This validation routine is technically # broken as the argument to record_transaction() # is not actually an instance of the Transaction # object. Instead it is a TransactionNode object. # The static method generate_request_headers() is # expecting a Transaction object and not # TransactionNode. The latter provides attributes # which are not updatable by the static method # generate_request_headers(), which it wants to # update, so would fail. For now what we do is use # a little proxy wrapper so that updates do not # fail. The use of this wrapper needs to be # reviewed and a better way of achieving what is # required found. class _Transaction(object): def __init__(self, wrapped): self.__wrapped__ = wrapped def __getattr__(self, name): return getattr(self.__wrapped__, name) external_headers = ExternalTrace.generate_request_headers( _Transaction(transaction)) assert required_header in external_headers, ( 'required_header=%r, ''external_headers=%r' % ( required_header, external_headers)) return result
def _nr_wrapper_httpclient_AsyncHTTPClient_fetch_(wrapped, instance, args, kwargs): transaction = current_transaction() if transaction is None: return wrapped(*args, **kwargs) try: req, _cb, _raise_error = _prepare_request(*args, **kwargs) except: return wrapped(*args, **kwargs) # Prepare outgoing CAT headers outgoing_headers = ExternalTrace.generate_request_headers(transaction) for header_name, header_value in outgoing_headers: # User headers should override our CAT headers if header_name in req.headers: continue req.headers[header_name] = header_value # wrap the fetch_impl on the unbound method instance_type = type(instance) if not hasattr(instance_type, '_nr_wrapped'): instance_type.fetch_impl = wrap_fetch_impl(instance_type.fetch_impl) instance_type._nr_wrapped = True trace = ExternalTrace(transaction, 'tornado.httpclient', req.url, req.method.upper()) instance._nr_args = (_raise_error, trace) trace.__enter__() if trace.transaction and trace.transaction.current_node is trace: # externals should not have children trace.transaction._pop_current(trace) try: future = wrapped(req, _cb, _raise_error) except Exception: trace.__exit__(*sys.exc_info()) raise return future
def wrap_httpclient_fetch(wrapped, instance, args, kwargs): try: req, raise_error = _prepare_request(*args, **kwargs) except: return wrapped(*args, **kwargs) trace = ExternalTrace('tornado', req.url, req.method.upper()) outgoing_headers = trace.generate_request_headers(current_transaction()) for header_name, header_value in outgoing_headers: # User headers should override our CAT headers if header_name in req.headers: continue req.headers[header_name] = header_value try: fetch = create_client_wrapper(wrapped, trace) except: return wrapped(*args, **kwargs) return convert_yielded(fetch(req, raise_error))
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_inbound_distributed_trace(app): transaction = Transaction(application_instance()) dt_headers = ExternalTrace.generate_request_headers(transaction) response = app.fetch('get', '/', headers=dict(dt_headers)) assert response.status == 200
def _test_dt_outbound(): transaction = current_transaction() payload = ExternalTrace.generate_request_headers(transaction) assert payload