def tracer(): tracer = Tracer( service_name='test-tracer', sampler=ConstSampler(True), reporter=InMemoryReporter(), ) try: yield tracer finally: tracer.close()
def test_tracer_tags(): reporter = mock.MagicMock() sampler = ConstSampler(True) with mock.patch('socket.gethostname', return_value='dream-host.com'): t = Tracer(service_name='x', reporter=reporter, sampler=sampler) assert t.tags.get('hostname') == 'dream-host.com' assert 'ip' in t.tags assert 'jaeger.version' in t.tags
def test_default_tracer(): class Sender(object): def __init__(self): self._channel = mock.MagicMock() self.io_loop = mock.MagicMock() channel = Sender() sampler = ConstSampler(False) tracer = Tracer.default_tracer(channel=channel, service_name='service') assert tracer.reporter._channel == channel reporter = 'reporter' tracer = Tracer.default_tracer(channel=channel, service_name='service', reporter=reporter) assert tracer.reporter == reporter tracer = Tracer.default_tracer(channel=channel, service_name='service', sampler=sampler) assert tracer.sampler == sampler
def tracer(): reporter = InMemoryReporter() report_func = reporter.report_span def log_and_report(span): print 'Reporting span %s' % span report_func(span) reporter.report_span = log_and_report tracer = Tracer( service_name='test-tracer', sampler=ConstSampler(True), reporter=reporter, ) try: yield tracer finally: tracer.close()
def build_started_scope(tracer: Tracer, parent_span: SpanContext, verb: str, message: any, span_setup: 'Callable[[Span, any], None]') -> None: message_type = type(message).__name__ scope = tracer.start_active_span(f'{verb} {message_type}', child_of=parent_span) scope.span.set_tag('proto.messagetype', message_type) if span_setup is not None: span_setup(scope.span, message) return scope
def test_tracer_tags_no_hostname(): reporter = mock.MagicMock() sampler = ConstSampler(True) from jaeger_client.tracer import logger with mock.patch.object(logger, 'exception') as mock_log: with mock.patch('socket.gethostname', side_effect=['host', ValueError()]): Tracer(service_name='x', reporter=reporter, sampler=sampler) assert mock_log.call_count == 1
def test_tracer_ip_tag(): reporter = mock.MagicMock() sampler = ConstSampler(True) tracer = Tracer( service_name='x', tags={c.JAEGER_IP_TAG_KEY: '192.0.2.3'}, reporter=reporter, sampler=sampler, ) assert tracer.tags[c.JAEGER_IP_TAG_KEY] == '192.0.2.3'
def test_tracer_tags_passed_to_reporter(): reporter = mock.MagicMock() reporter.set_process = mock.MagicMock() sampler = ConstSampler(True) tracer = Tracer( service_name='x', reporter=reporter, sampler=sampler, max_tag_value_length=123, ) reporter.set_process.assert_called_once_with( service_name='x', tags=tracer.tags, max_length=123, )
def test_tracer_hostname_tag(): reporter = mock.MagicMock() sampler = ConstSampler(True) tracer = Tracer( service_name='x', tags={c.JAEGER_HOSTNAME_TAG_KEY: 'jaeger-client-app.local'}, reporter=reporter, sampler=sampler, ) assert tracer.tags[c.JAEGER_HOSTNAME_TAG_KEY] == 'jaeger-client-app.local'
def test_round_trip(tracer, fmt, carrier): tracer_128bit = Tracer(service_name='test', reporter=InMemoryReporter(), sampler=ConstSampler(True), generate_128bit_trace_id=True) for tracer1, tracer2 in product([tracer, tracer_128bit], repeat=2): span = tracer1.start_span('test-%s' % fmt) tracer1.inject(span, fmt, carrier) context = tracer2.extract(fmt, carrier) span2 = tracer2.start_span('test-%s' % fmt, child_of=context) assert span.trace_id == span2.trace_id
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_debug_id(): debug_header = 'correlation-id' tracer = Tracer( service_name='test', reporter=InMemoryReporter(), sampler=ConstSampler(True), debug_id_header=debug_header, ) tracer.codecs[Format.TEXT_MAP] = TextCodec( url_encoding=False, debug_id_header=debug_header, ) carrier = {debug_header: 'Coraline'} context = tracer.extract(Format.TEXT_MAP, carrier) assert context.is_debug_id_container_only assert context.debug_id == 'Coraline' span = tracer.start_span('test', child_of=context) assert span.is_debug() assert span.is_sampled() tags = [t for t in span.tags if t.key == debug_header] assert len(tags) == 1 assert tags[0].vStr == 'Coraline'
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 APITest(unittest.TestCase, APICompatibilityCheckMixin): reporter = NullReporter() sampler = ConstSampler(True) _tracer = Tracer(service_name='test_service_1', reporter=reporter, sampler=sampler) def tracer(self): return APITest._tracer def test_binary_propagation(self): # TODO binary codecs are not implemented at the moment pass
def tracer(): reporter = InMemoryReporter() report_func = reporter.report_span def log_and_report(span): print(('Reporting span %s' % span)) print(('Span type %s' % type(span))) print(('SpanContext type %s' % type(span.context))) report_func(span) reporter.report_span = log_and_report tracer = Tracer( service_name='test-tracer', sampler=ConstSampler(True), reporter=reporter, scope_manager=TornadoScopeManager() ) opentracing.set_global_tracer(tracer) try: yield tracer finally: opentracing._reset_global_tracer() tracer.close()
def test_tracer_tags_on_root_span(span_type, expected_tags): reporter = mock.MagicMock() sampler = ConstSampler(True) with mock.patch('socket.gethostname', return_value='dream-host.com'): tracer = Tracer(service_name='x', reporter=reporter, sampler=sampler, tags={'global-tag': 'global-tag'}) span = tracer.start_span(operation_name='root') if span_type == 'child': span = tracer.start_span('child', child_of=span) if span_type == 'rpc-server': span = tracer.start_span( 'child', child_of=span.context, tags={ext_tags.SPAN_KIND: ext_tags.SPAN_KIND_RPC_SERVER}) for key, value in six.iteritems(expected_tags): found_tag = find_tag(span, key, type(value).__name__) if value is None: assert found_tag is None, 'test (%s)' % span_type continue assert found_tag == value, \ 'test (%s): expecting tag %s=%s' % (span_type, key, value)
def test_tracer_override_codecs(): reporter = mock.MagicMock() sampler = ConstSampler(True) codecs = { 'extra_codec': "codec_placeholder", Format.BINARY: "overridden_binary_codec" } with mock.patch('socket.gethostname', return_value='dream-host.com'): tracer = Tracer(service_name='x', reporter=reporter, sampler=sampler, extra_codecs=codecs) assert tracer.codecs['extra_codec'] == "codec_placeholder",\ "Extra codec not found" assert tracer.codecs[Format.BINARY] == "overridden_binary_codec",\ "Binary format codec not overridden"
def _init_tracer(self): service_name = '' try: value = getattr(settings, 'SERVICE_CONF', '') if value: service_name = value.get('NAME', '') except Exception as e: logger.error('SERVICE_CONF:NAME is not set in settings. {}'.format(str(e))) # create a global tracer first tracer = Tracer( one_span_per_rpc=True, service_name=service_name, reporter=NullReporter(), sampler=ConstSampler(decision=True), extra_codecs={Format.HTTP_HEADERS: B3Codec()} ) opentracing.set_global_tracer(tracer)
def serve(): """main entry point""" logging.getLogger().setLevel(logging.DEBUG) logging.info('Python Tornado Crossdock Server Starting ...') tracer = Tracer(service_name='python', reporter=NullReporter(), sampler=ConstSampler(decision=True)) opentracing.tracer = tracer tchannel = TChannel(name='python', hostport=':%d' % DEFAULT_SERVER_PORT, trace=True) register_tchannel_handlers(tchannel=tchannel) tchannel.listen() app = tornado.web.Application(debug=True) register_http_handlers(app) app.listen(DEFAULT_CLIENT_PORT) tornado.ioloop.IOLoop.current().start()
def test_inject_with_128bit_trace_id(tracer, fmt, carrier, get_trace_id): tracer_128bit = Tracer(service_name='test', reporter=InMemoryReporter(), sampler=ConstSampler(True), generate_128bit_trace_id=True) for tracer in [tracer, tracer_128bit]: length = tracer.max_trace_id_bits / 4 trace_id = (1 << 64) - 1 if length == 16 else (1 << 128) - 1 ctx = SpanContext(trace_id=trace_id, span_id=127, parent_id=None, flags=1) span = Span(ctx, operation_name='test-%s' % fmt, tracer=None, start_time=1) tracer.inject(span, fmt, carrier) assert len(get_trace_id(carrier)) == length # test if the trace_id arrived on wire remains same even if # the tracer is configured for 64bit ids or 128bit ids ctx = SpanContext(trace_id=(1 << 128) - 1, span_id=127, parent_id=None, flags=0) span = tracer.start_span('test-%s' % fmt, child_of=ctx) carrier = dict() tracer.inject(span, fmt, carrier) assert len(get_trace_id(carrier)) == 32 ctx = SpanContext(trace_id=(1 << 64) - 1, span_id=127, parent_id=None, flags=0) span = tracer.start_span('test-%s' % fmt, child_of=ctx) carrier = dict() tracer.inject(span, fmt, carrier) assert len(get_trace_id(carrier)) == 16
def tracer(): reporter = mock.MagicMock() sampler = ConstSampler(True) return Tracer(service_name='test_service_1', reporter=reporter, sampler=sampler)
# x-b3-flags # # This example code uses OpenTracing (http://opentracing.io/) to propagate # the 'b3' (zipkin) headers. Using OpenTracing for this is not a requirement. # Using OpenTracing allows you to add application-specific tracing later on, # but you can just manually forward the headers if you prefer. # # The OpenTracing example here is very basic. It only forwards headers. It is # intended as a reference to help people get started, eg how to create spans, # extract/inject context, etc. # A very basic OpenTracing tracer (with null reporter) tracer = Tracer( one_span_per_rpc=True, service_name='productpage', reporter=NullReporter(), sampler=ConstSampler(decision=True), extra_codecs={Format.HTTP_HEADERS: B3Codec()} ) def trace(): ''' Function decorator that creates opentracing span from incoming b3 headers ''' def decorator(f): def wrapper(*args, **kwargs): request = stack.top.request try: # Create a new span context, reading in values (traceid, # spanid, etc) from the incoming x-b3-*** headers.
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()})
from opentracing_instrumentation import http_client, http_server, get_current_span, request_context from opentracing_instrumentation.client_hooks import tornado_http import opentracing.ext.tags as ext_tags from crossdock.thrift_gen.tracetest.ttypes import ObservedSpan, TraceResponse, Transport, \ JoinTraceRequest from tchannel import TChannel, thrift from crossdock.server.thriftrw_serializer import trace_response_to_thriftrw, \ join_trace_request_to_thriftrw DefaultClientPortHTTP = 8080 DefaultServerPortHTTP = 8081 DefaultServerPortTChannel = 8082 tracer = Tracer(service_name='python', reporter=NullReporter(), sampler=ConstSampler(decision=True), scope_manager=TornadoScopeManager()) opentracing.set_global_tracer(tracer) idl_path = 'idl/thrift/crossdock/tracetest.thrift' thrift_services = {} def get_thrift_service(service_name): if service_name in thrift_services: return thrift_services[service_name] thrift_service = thrift.load(path=idl_path, service=service_name) thrift_services[service_name] = thrift_service return thrift_service
__name__ = "fastapi_opentracing" from jaeger_client import Tracer, ConstSampler from jaeger_client.reporter import NullReporter from jaeger_client.codecs import B3Codec from opentracing.scope_managers.contextvars import ContextVarsScopeManager from opentracing.propagation import Format tracer = Tracer( one_span_per_rpc=True, service_name='wk_api_gateway', reporter=NullReporter(), sampler=ConstSampler(decision=True), extra_codecs={Format.HTTP_HEADERS: B3Codec()}, scope_manager=ContextVarsScopeManager(), ) async def get_opentracing_span_headers(): scope = tracer.scope_manager.active carrier = {} if scope is not None: span = scope.span tracer.inject(span_context=span, format=Format.HTTP_HEADERS, carrier=carrier) for k, v in getattr(span, 'extra_headers', {}).items(): carrier[k] = v return carrier
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
def tracer(): reporter = mock.MagicMock() sampler = ConstSampler(True) return Tracer.default_tracer(None, 'test_service_1', reporter, sampler)
from opentracing_instrumentation.client_hooks import tornado_http import opentracing.ext.tags as ext_tags from crossdock.thrift_gen.tracetest.ttypes import ObservedSpan, TraceResponse, Transport, \ JoinTraceRequest from tchannel import TChannel, thrift from crossdock.server.thriftrw_serializer import trace_response_to_thriftrw, \ join_trace_request_to_thriftrw DefaultClientPortHTTP = 8080 DefaultServerPortHTTP = 8081 DefaultServerPortTChannel = 8082 tracer = Tracer( service_name='python', reporter=NullReporter(), sampler=ConstSampler(decision=True)) opentracing.tracer = tracer idl_path = 'idl/thrift/crossdock/tracetest.thrift' thrift_services = {} def get_thrift_service(service_name): if service_name in thrift_services: return thrift_services[service_name] thrift_service = thrift.load(path=idl_path, service=service_name) thrift_services[service_name] = thrift_service return thrift_service