def test_baggage_as_unicode_strings_with_httplib(httpserver): if six.PY2: import urllib2 urllib_under_test = urllib2 else: import urllib.request urllib_under_test = urllib.request # httpserver is provided by pytest-localserver httpserver.serve_content(content='Hello', code=200, headers=None) tracer = Tracer( service_name='test', reporter=InMemoryReporter(), # don't sample to avoid logging baggage to the span sampler=ConstSampler(False), ) tracer.codecs[Format.TEXT_MAP] = TextCodec(url_encoding=True) baggage = [(b'key1', b'value'), (u'key2', b'value'), ('key3', u'value'), (b'key4', bytes(chr(255)) if six.PY2 else bytes([255])), (u'key5', u'\U0001F47E')] for b in baggage: span = tracer.start_span('test') span.set_baggage_item(b[0], b[1]) headers = {} tracer.inject(span_context=span.context, format=Format.TEXT_MAP, carrier=headers) # make sure httplib doesn't blow up request = urllib_under_test.Request(httpserver.url, None, headers) response = urllib_under_test.urlopen(request) assert response.read() == b'Hello' response.close()
def test_non_ascii_baggage_with_httplib(httpserver): # httpserver is provided by pytest-localserver httpserver.serve_content(content='Hello', code=200, headers=None) tracer = Tracer( service_name='test', reporter=InMemoryReporter(), # don't sample to avoid logging baggage to the span sampler=ConstSampler(False), ) tracer.codecs[Format.TEXT_MAP] = TextCodec(url_encoding=True) baggage = [ (b'key', b'value'), (u'key', b'value'), (b'key', bytes(chr(255))), (u'caf\xe9', 'caf\xc3\xa9'), ('caf\xc3\xa9', 'value'), ] for b in baggage: span = tracer.start_span('test') span.set_baggage_item(b[0], b[1]) headers = {} tracer.inject(span_context=span.context, format=Format.TEXT_MAP, carrier=headers) # make sure httplib doesn't blow up request = urllib2.Request(httpserver.url, None, headers) response = urllib2.urlopen(request) assert response.read() == 'Hello' response.close()
def test_non_ascii_baggage_with_httplib(httpserver): # TODO this test requires `futurize`. Unfortunately, that also changes # how the test works under Py2. # Some observation: # - In Py2, the httplib does not like unicode strings, maybe we need to convert everything to bytes. # - Not sure yet what's the story with httplib in Py3, it seems not to like raw bytes. if six.PY3: raise ValueError('this test does not work with Py3') # httpserver is provided by pytest-localserver httpserver.serve_content(content='Hello', code=200, headers=None) tracer = Tracer( service_name='test', reporter=InMemoryReporter(), # don't sample to avoid logging baggage to the span sampler=ConstSampler(False), ) tracer.codecs[Format.TEXT_MAP] = TextCodec(url_encoding=True) baggage = [ (b'key', b'value'), (u'key', b'value'), (b'key', byte255), (u'caf\xe9', 'caf\xc3\xa9'), ('caf\xc3\xa9', 'value'), ] for b in baggage: span = tracer.start_span('test') span.set_baggage_item(b[0], b[1]) headers = {} tracer.inject(span_context=span.context, format=Format.TEXT_MAP, carrier=headers) # make sure httplib doesn't blow up import urllib2 request = urllib2.Request(httpserver.url, None, headers) response = urllib2.urlopen(request) assert response.read() == b'Hello' response.close()
def test_baggage_as_unicode_strings_with_httplib(httpserver): if six.PY2: import urllib2 urllib_under_test = urllib2 else: import urllib.request urllib_under_test = urllib.request # httpserver is provided by pytest-localserver httpserver.serve_content(content='Hello', code=200, headers=None) tracer = Tracer( service_name='test', reporter=InMemoryReporter(), # don't sample to avoid logging baggage to the span sampler=ConstSampler(False), ) tracer.codecs[Format.TEXT_MAP] = TextCodec(url_encoding=True) baggage = [ (b'key1', b'value'), (u'key2', b'value'), ('key3', u'value'), (b'key4', bytes(chr(255)) if six.PY2 else bytes([255])), (u'key5', u'\U0001F47E') ] for b in baggage: span = tracer.start_span('test') span.set_baggage_item(b[0], b[1]) headers = {} tracer.inject(span_context=span.context, format=Format.TEXT_MAP, carrier=headers) # make sure httplib doesn't blow up request = urllib_under_test.Request(httpserver.url, None, headers) response = urllib_under_test.urlopen(request) assert response.read() == b'Hello' response.close()
class SimpleTracer: '''A very basic OpenTracing tracer, with null reporter''' def __init__(self, sname): self.tracer = Tracer(one_span_per_rpc=True, service_name=sname, reporter=NullReporter(), sampler=ConstSampler(decision=True), extra_codecs={Format.HTTP_HEADERS: B3Codec()}) def trace(self): ''' Decorator that creates opentracing span from incoming b3 headers ''' def decorator(f): def wrapper(*args, **kwargs): global stack request = stack.top.request try: # Create a new span context, reading in values (traceid, # spanid, etc) from the incoming x-b3-*** headers. span_ctx = self.tracer.extract(Format.HTTP_HEADERS, dict(request.headers)) # Note: this tag means that the span will *not* be # a child span. It will use the incoming traceid and # spanid. We do this to propagate the headers verbatim. rpc_tag = {tags.SPAN_KIND: tags.SPAN_KIND_RPC_SERVER} span = self.tracer.start_span(operation_name='op', child_of=span_ctx, tags=rpc_tag) except Exception as e: # We failed to create a context, possibly due to no # incoming x-b3-*** headers. Start a fresh span. # Note: This is a fallback only, and will create fresh # headers, not propagate headers. span = self.tracer.start_span('op') with span_in_context(span): r = f(*args, **kwargs) return r wrapper.__name__ = f.__name__ return wrapper return decorator def getForwardHeaders(self, request): ''' Return the headers that should be forwarded to subservices. This function currently forwards instances of tracing headers for a much wider range of tracing tools than are used in this course. If those headers are not present, nothing happens other than a bit of wasted computation here. At some point, we should pare down the list to only those headers needed by the tools used in class. The final block, "Application-specific", includes headers not needed for tracing but that our application requires to be forwarded. ''' headers = {} # x-b3-*** headers can be populated using the opentracing span span = get_current_span() carrier = {} self.tracer.inject(span_context=span.context, format=Format.HTTP_HEADERS, carrier=carrier) headers.update(carrier) # CMPT 756 --- COMMENTED OUT FROM bookinfo # We handle other (non x-b3-***) headers manually #if 'user' in session: # headers['end-user'] = session['user'] # Keep this in sync with the headers in details and reviews. incoming_headers = [ # All applications should propagate x-request-id. This header is # included in access log statements and is used for consistent trace # sampling and log sampling decisions in Istio. 'x-request-id', # Lightstep tracing header. Propagate this if you use lightstep tracing # in Istio (see # https://istio.io/latest/docs/tasks/observability/distributed-tracing/lightstep/) # Note: this should probably be changed to use B3 or W3C TRACE_CONTEXT. # Lightstep recommends using B3 or TRACE_CONTEXT and most application # libraries from lightstep do not support x-ot-span-context. 'x-ot-span-context', # Datadog tracing header. Propagate these headers if you use Datadog # tracing. 'x-datadog-trace-id', 'x-datadog-parent-id', 'x-datadog-sampling-priority', # W3C Trace Context. Compatible with OpenCensusAgent and Stackdriver Istio # configurations. 'traceparent', 'tracestate', # Cloud trace context. Compatible with OpenCensusAgent and Stackdriver Istio # configurations. 'x-cloud-trace-context', # Grpc binary trace context. Compatible with OpenCensusAgent nad # Stackdriver Istio configurations. 'grpc-trace-bin', # b3 trace headers. Compatible with Zipkin, OpenCensusAgent, and # Stackdriver Istio configurations. Commented out since they are # propagated by the OpenTracing tracer above. # 'x-b3-traceid', # 'x-b3-spanid', # 'x-b3-parentspanid', # 'x-b3-sampled', # 'x-b3-flags', # Application-specific headers to forward. 'user-agent', 'Authorization', # CMPT 756 ] # For Zipkin, always propagate b3 headers. # For Lightstep, always propagate the x-ot-span-context header. # For Datadog, propagate the corresponding datadog headers. # For OpenCensusAgent and Stackdriver configurations, you can choose any # set of compatible headers to propagate within your application. For # example, you can propagate b3 headers or W3C trace context headers with # the same result. This can also allow you to translate between context # propagation mechanisms between different applications. for ihdr in incoming_headers: val = request.headers.get(ihdr) if val is not None: headers[ihdr] = val return headers