def test_patch_unpatch(self): tracer = DummyTracer() # Test patch idempotence patch() patch() r = redis.Redis(port=REDIS_CONFIG["port"]) Pin.get_from(r).clone(tracer=tracer).onto(r) r.get("key") spans = tracer.pop() assert spans, spans assert len(spans) == 1 # Test unpatch unpatch() r = redis.Redis(port=REDIS_CONFIG["port"]) r.get("key") spans = tracer.pop() assert not spans, spans # Test patch again patch() r = redis.Redis(port=REDIS_CONFIG["port"]) Pin.get_from(r).clone(tracer=tracer).onto(r) r.get("key") spans = tracer.pop() assert spans, spans assert len(spans) == 1
def setUp(self): self.tracer = DummyTracer() self.traced_app = TraceMiddleware( cherrypy, self.tracer, service="test.cherrypy.service", distributed_tracing=True, )
def tracer(): tracer = DummyTracer() if sys.version_info < (3, 7): # enable legacy asyncio support from ddtrace.contrib.asyncio.provider import AsyncioContextProvider tracer.configure(context_provider=AsyncioContextProvider()) yield tracer
def test_redis_legacy(): # ensure the old interface isn't broken, but doesn't trace tracer = DummyTracer() TracedRedisCache = get_traced_redis(tracer, "foo") r = TracedRedisCache(port=REDIS_CONFIG["port"]) r.set("a", "b") got = r.get("a") assert compat.to_unicode(got) == "b" assert not tracer.pop()
def make_ot_tracer(service_name="my_svc", config=None, scope_manager=None, context_provider=None): config = config or {} tracer = Tracer(service_name=service_name, config=config, scope_manager=scope_manager) # similar to how we test the ddtracer, use a dummy tracer dd_tracer = DummyTracer() if context_provider: dd_tracer.configure(context_provider=context_provider) # attach the dummy tracer to the opentracer tracer._dd_tracer = dd_tracer return tracer
def tracer(): original_tracer = ddtrace.tracer tracer = DummyTracer() if sys.version_info < (3, 7): # enable legacy asyncio support from ddtrace.contrib.asyncio.provider import AsyncioContextProvider tracer.configure(context_provider=AsyncioContextProvider()) setattr(ddtrace, "tracer", tracer) patch() yield tracer setattr(ddtrace, "tracer", original_tracer) unpatch()
def nop_tracer(): from ddtrace.opentracer import Tracer tracer = Tracer(service_name="mysvc", config={}) # use the same test tracer used by the primary tests tracer._tracer = DummyTracer() return tracer
def test_log_unfinished_spans_disabled(self, log): # the trace finished status logging is disabled tracer = DummyTracer() ctx = Context() # manually create a root-child trace root = Span(tracer=tracer, name="root") child_1 = Span(tracer=tracer, name="child_1", trace_id=root.trace_id, parent_id=root.span_id) child_2 = Span(tracer=tracer, name="child_2", trace_id=root.trace_id, parent_id=root.span_id) child_1._parent = root child_2._parent = root ctx.add_span(root) ctx.add_span(child_1) ctx.add_span(child_2) # close only the parent root.finish() # the logger has never been invoked to print unfinished spans for call, _ in log.call_args_list: msg = call[0] assert "the trace has %d unfinished spans" not in msg
def test_inject(self): tracer = DummyTracer() ctx = Context(trace_id=1234, sampling_priority=2, dd_origin="synthetics") tracer.context_provider.activate(ctx) with tracer.trace("global_root_span") as span: headers = {} HTTPPropagator.inject(span.context, headers) assert int(headers[HTTP_HEADER_TRACE_ID]) == span.trace_id assert int(headers[HTTP_HEADER_PARENT_ID]) == span.span_id assert int(headers[HTTP_HEADER_SAMPLING_PRIORITY] ) == span.context.sampling_priority assert headers[HTTP_HEADER_ORIGIN] == span.context.dd_origin
def test_pre_v4(): tracer = DummyTracer() MySQL = get_traced_pymysql_connection(tracer, service="my-mysql-server") conn = MySQL(**config.MYSQL_CONFIG) cursor = conn.cursor() cursor.execute("SELECT 1") assert cursor.fetchone()[0] == 1
def test_extract(self): tracer = DummyTracer() headers = { "x-datadog-trace-id": "1234", "x-datadog-parent-id": "5678", "x-datadog-sampling-priority": "1", "x-datadog-origin": "synthetics", } context = HTTPPropagator.extract(headers) tracer.context_provider.activate(context) with tracer.trace("local_root_span") as span: assert span.trace_id == 1234 assert span.parent_id == 5678 assert span.context.sampling_priority == 1 assert span.context.dd_origin == "synthetics"
def tracer_with_debug_logging(): # All the tracers, dummy or not, shares the same logging object. tracer = DummyTracer() level = tracer.log.level tracer.log.setLevel(logging.DEBUG) try: yield tracer finally: tracer.log.setLevel(level)
def test_WSGI_extract(self): """Ensure we support the WSGI formatted headers as well.""" tracer = DummyTracer() headers = { "HTTP_X_DATADOG_TRACE_ID": "1234", "HTTP_X_DATADOG_PARENT_ID": "5678", "HTTP_X_DATADOG_SAMPLING_PRIORITY": "1", "HTTP_X_DATADOG_ORIGIN": "synthetics", } context = HTTPPropagator.extract(headers) tracer.context_provider.activate(context) with tracer.trace("local_root_span") as span: assert span.trace_id == 1234 assert span.parent_id == 5678 assert span.context.sampling_priority == 1 assert span.context.dd_origin == "synthetics"
def test_log_unfinished_spans_when_ok(self, log): # if the unfinished spans logging is enabled but the trace is finished, don't log anything tracer = DummyTracer() ctx = Context() # manually create a root-child trace root = Span(tracer=tracer, name="root") child = Span(tracer=tracer, name="child_1", trace_id=root.trace_id, parent_id=root.span_id) child._parent = root ctx.add_span(root) ctx.add_span(child) # close the trace child.finish() root.finish() # the logger has never been invoked to print unfinished spans for call, _ in log.call_args_list: msg = call[0] assert "the trace has %d unfinished spans" not in msg
def get_dummy_tracer(): return DummyTracer()
def tracer(): return DummyTracer()
def tracer(): tracer = DummyTracer() return tracer
class TestCherrypy(helper.CPWebCase): """ FIXME: the tests using getPage() are not synchronous and so require a delay afterwards. """ @staticmethod def setup_server(): cherrypy.tree.mount( TestApp(), "/", { "/": { "tools.tracer.on": True }, }, ) def setUp(self): self.tracer = DummyTracer() self.traced_app = TraceMiddleware( cherrypy, self.tracer, service="test.cherrypy.service", distributed_tracing=True, ) def test_double_instrumentation(self): # ensure CherryPy is never instrumented twice when `ddtrace-run` # and `TraceMiddleware` are used together. `traced_app` MUST # be assigned otherwise it's not possible to reproduce the # problem (the test scope must keep a strong reference) traced_app = TraceMiddleware(cherrypy, self.tracer) # noqa: F841 self.getPage("/") time.sleep(0.1) self.assertHeader("Content-Type", "text/html;charset=utf-8") self.assertStatus("200 OK") spans = self.tracer.writer.pop() assert len(spans) == 1 def test_double_instrumentation_config(self): # ensure CherryPy uses the last set configuration to be sure # there are no breaking changes for who uses `ddtrace-run` # with the `TraceMiddleware` assert cherrypy.tools.tracer.service == "test.cherrypy.service" TraceMiddleware( cherrypy, self.tracer, service="new-intake", ) self.getPage("/") time.sleep(0.1) self.assertHeader("Content-Type", "text/html;charset=utf-8") self.assertStatus("200 OK") spans = self.tracer.writer.pop() assert len(spans) == 1 assert cherrypy.tools.tracer.service == "new-intake" def test_child(self): self.getPage("/child") time.sleep(0.1) self.assertStatus("200 OK") self.assertHeader("Content-Type", "text/html;charset=utf-8") self.assertBody("child") # ensure trace worked spans = self.tracer.writer.pop() assert len(spans) == 2 spans_by_name = {s.name: s for s in spans} s = spans_by_name["cherrypy.request"] assert s.span_id assert s.trace_id assert not s.parent_id assert s.service == "test.cherrypy.service" assert s.resource == "GET /child" assert s.error == 0 c = spans_by_name["child"] assert c.span_id assert c.trace_id == s.trace_id assert c.parent_id == s.span_id assert c.service == "test.cherrypy.service" assert c.resource == "child" assert c.error == 0 def test_success(self): self.getPage("/") time.sleep(0.1) self.assertStatus("200 OK") self.assertHeader("Content-Type", "text/html;charset=utf-8") self.assertBody("Hello world!") assert not self.tracer.current_span(), self.tracer.current_span( ).pprint() spans = self.tracer.writer.pop() assert len(spans) == 1 s = spans[0] assert s.service == "test.cherrypy.service" assert s.resource == "GET /" assert s.error == 0 assert_span_http_status_code(s, 200) assert s.meta.get(http.METHOD) == "GET" def test_alias(self): self.getPage("/aliases") time.sleep(0.1) self.assertStatus("200 OK") self.assertHeader("Content-Type", "text/html;charset=utf-8") self.assertBody("alias") assert not self.tracer.current_span(), self.tracer.current_span( ).pprint() spans = self.tracer.writer.pop() assert len(spans) == 1 s = spans[0] assert s.service == "test.cherrypy.service" assert s.resource == "GET /aliases" assert s.error == 0 assert_span_http_status_code(s, 200) assert s.meta.get(http.METHOD) == "GET" def test_handleme(self): self.getPage("/handleme") time.sleep(0.1) self.assertErrorPage(418, message="handled") # ensure trace worked assert not self.tracer.current_span(), self.tracer.current_span( ).pprint() spans = self.tracer.writer.pop() assert len(spans) == 1 s = spans[0] assert s.service == "test.cherrypy.service" assert s.resource == "GET /handleme" assert s.error == 0 assert_span_http_status_code(s, 418) assert s.meta.get(http.METHOD) == "GET" def test_error(self): self.getPage("/error") time.sleep(0.1) self.assertErrorPage(500) # ensure the request was traced. assert not self.tracer.current_span() spans = self.tracer.writer.pop() assert len(spans) == 1 s = spans[0] assert s.service == "test.cherrypy.service" assert s.resource == "GET /error" assert_span_http_status_code(s, 500) assert s.error == 1 assert s.meta.get(http.METHOD) == "GET" def test_fatal(self): self.getPage("/fatal") time.sleep(0.1) self.assertErrorPage(500) assert not self.tracer.current_span() spans = self.tracer.writer.pop() assert len(spans) == 1 s = spans[0] assert s.service == "test.cherrypy.service" assert s.resource == "GET /fatal" assert_span_http_status_code(s, 500) assert s.error == 1 assert s.meta.get(http.METHOD) == "GET" assert "ZeroDivisionError" in s.meta.get(errors.ERROR_TYPE), s.meta assert "by zero" in s.meta.get(errors.ERROR_MSG) assert re.search( 'File ".*/contrib/cherrypy/web.py", line [0-9]+, in fatal', s.meta.get(errors.ERROR_STACK)) def test_unicode(self): # Encoded utf8 query strings MUST be parsed correctly. # Here, the URL is encoded in utf8 and then %HEX # See https://docs.cherrypy.org/en/latest/_modules/cherrypy/test/test_encoding.html for more self.getPage(url_quote(u"/üŋïĉóđē".encode("utf-8"))) time.sleep(0.1) self.assertStatus("200 OK") self.assertHeader("Content-Type", "text/html;charset=utf-8") self.assertBody( b"\xc3\xbc\xc5\x8b\xc3\xaf\xc4\x89\xc3\xb3\xc4\x91\xc4\x93") # ensure trace worked assert not self.tracer.current_span(), self.tracer.current_span( ).pprint() spans = self.tracer.writer.pop() assert len(spans) == 1 s = spans[0] assert s.service == "test.cherrypy.service" assert s.resource == u"GET /üŋïĉóđē" assert s.error == 0 assert_span_http_status_code(s, 200) assert s.meta.get(http.METHOD) == "GET" assert s.meta.get(http.URL) == u"http://127.0.0.1:54583/üŋïĉóđē" def test_404(self): self.getPage(u"/404/test") time.sleep(0.1) self.assertStatus("404 Not Found") # ensure trace worked assert not self.tracer.current_span(), self.tracer.current_span( ).pprint() spans = self.tracer.writer.pop() assert len(spans) == 1 s = spans[0] assert s.service == "test.cherrypy.service" assert s.resource == u"GET /404/test" assert s.error == 0 assert_span_http_status_code(s, 404) assert s.meta.get(http.METHOD) == "GET" assert s.meta.get(http.URL) == u"http://127.0.0.1:54583/404/test" def test_propagation(self): self.getPage( "/", headers=[ ("x-datadog-trace-id", "1234"), ("x-datadog-parent-id", "4567"), ("x-datadog-sampling-priority", "2"), ], ) time.sleep(0.1) self.assertStatus("200 OK") self.assertHeader("Content-Type", "text/html;charset=utf-8") self.assertBody("Hello world!") assert not self.tracer.current_span(), self.tracer.current_span( ).pprint() spans = self.tracer.writer.pop() assert len(spans) == 1 s = spans[0] # ensure the propagation worked well assert s.trace_id == 1234 assert s.parent_id == 4567 assert s.get_metric(SAMPLING_PRIORITY_KEY) == 2 def test_disabled_distributed_tracing_config(self): previous_distributed_tracing = config.cherrypy["distributed_tracing"] config.cherrypy["distributed_tracing"] = False self.getPage( "/", headers=[ ("x-datadog-trace-id", "1234"), ("x-datadog-parent-id", "4567"), ("x-datadog-sampling-priority", "2"), ], ) time.sleep(0.1) self.assertStatus("200 OK") self.assertHeader("Content-Type", "text/html;charset=utf-8") self.assertBody("Hello world!") # ensure trace worked assert not self.tracer.current_span(), self.tracer.current_span( ).pprint() spans = self.tracer.writer.pop() assert len(spans) == 1 s = spans[0] # ensure the propagation worked well assert s.trace_id != 1234 assert s.parent_id != 4567 assert s.get_metric(SAMPLING_PRIORITY_KEY) != 2 config.cherrypy["distributed_tracing"] = previous_distributed_tracing def test_disabled_distributed_tracing_middleware(self): previous_distributed_tracing = cherrypy.tools.tracer.use_distributed_tracing cherrypy.tools.tracer.use_distributed_tracing = False self.getPage( "/", headers=[ ("x-datadog-trace-id", "1234"), ("x-datadog-parent-id", "4567"), ("x-datadog-sampling-priority", "2"), ], ) time.sleep(0.1) self.assertStatus("200 OK") self.assertHeader("Content-Type", "text/html;charset=utf-8") self.assertBody("Hello world!") # ensure trace worked assert not self.tracer.current_span(), self.tracer.current_span( ).pprint() spans = self.tracer.writer.pop() assert len(spans) == 1 s = spans[0] # ensure the propagation worked well assert s.trace_id != 1234 assert s.parent_id != 4567 assert s.get_metric(SAMPLING_PRIORITY_KEY) != 2 cherrypy.tools.tracer.use_distributed_tracing = previous_distributed_tracing def test_custom_span(self): self.getPage(u"/custom_span") time.sleep(0.1) self.assertStatus("200 OK") self.assertBody("hiya") # ensure trace worked assert not self.tracer.current_span(), self.tracer.current_span( ).pprint() spans = self.tracer.writer.pop() assert len(spans) == 1 s = spans[0] assert s.service == "test.cherrypy.service" assert s.resource == "overridden" assert s.error == 0 assert_span_http_status_code(s, 200) assert s.meta.get(http.METHOD) == "GET" def test_http_request_header_tracing(self): config.cherrypy.http.trace_headers(["Host", "my-header"]) self.getPage( "/", headers=[ ("my-header", "my_value"), ("x-datadog-parent-id", "4567"), ("x-datadog-sampling-priority", "2"), ], ) time.sleep(0.1) traces = self.tracer.writer.pop_traces() assert len(traces) == 1 assert len(traces[0]) == 1 span = traces[0][0] assert span.get_tag("http.request.headers.my-header") == "my_value" assert span.get_tag("http.request.headers.host") == "127.0.0.1:54583" def test_http_response_header_tracing(self): config.cherrypy.http.trace_headers(["my-response-header"]) self.getPage("/response_headers") time.sleep(0.1) traces = self.tracer.writer.pop_traces() assert len(traces) == 1 assert len(traces[0]) == 1 span = traces[0][0] assert span.get_tag( "http.response.headers.my-response-header") == "my_response_value" def test_variable_resource(self): self.getPage("/dispatch/abc123/") time.sleep(0.1) self.assertStatus("200 OK") self.assertHeader("Content-Type", "text/html;charset=utf-8") self.assertBody("dispatch with abc123") # ensure trace worked assert not self.tracer.current_span(), self.tracer.current_span( ).pprint() spans = self.tracer.writer.pop() assert len(spans) == 1 s = spans[0] assert s.service == "test.cherrypy.service" # Once CherryPy returns sensible results for virtual path components, this # can be: "GET /dispatch/{{test_value}}/" assert s.resource == "GET /dispatch/abc123/" assert s.error == 0 assert_span_http_status_code(s, 200) assert s.meta.get(http.METHOD) == "GET" def test_post(self): self.getPage("/", method="POST") time.sleep(0.1) self.assertStatus("200 OK") self.assertHeader("Content-Type", "text/html;charset=utf-8") self.assertBody("Hello world!") # ensure trace worked assert not self.tracer.current_span(), self.tracer.current_span( ).pprint() spans = self.tracer.writer.pop() assert len(spans) == 1 s = spans[0] assert s.service == "test.cherrypy.service" assert s.resource == "POST /" assert s.error == 0 assert_span_http_status_code(s, 200) assert s.meta.get(http.METHOD) == "POST" def test_service_configuration_config(self): previous_service = config.cherrypy.get("service", "test.cherrypy.service") config.cherrypy["service"] = "my_cherrypy_service" self.getPage("/") time.sleep(0.1) self.assertStatus("200 OK") self.assertHeader("Content-Type", "text/html;charset=utf-8") self.assertBody("Hello world!") # ensure trace worked assert not self.tracer.current_span(), self.tracer.current_span( ).pprint() spans = self.tracer.writer.pop() assert len(spans) == 1 s = spans[0] assert s.service == "my_cherrypy_service" assert s.resource == "GET /" assert s.error == 0 assert_span_http_status_code(s, 200) assert s.meta.get(http.METHOD) == "GET" config.cherrypy["service"] = previous_service def test_service_configuration_middleware(self): previous_service = cherrypy.tools.tracer.service cherrypy.tools.tracer.service = "my_cherrypy_service2" self.getPage("/") time.sleep(0.1) self.assertStatus("200 OK") self.assertHeader("Content-Type", "text/html;charset=utf-8") self.assertBody("Hello world!") # ensure trace worked assert not self.tracer.current_span(), self.tracer.current_span( ).pprint() spans = self.tracer.writer.pop() assert len(spans) == 1 s = spans[0] assert s.service == "my_cherrypy_service2" assert s.resource == "GET /" assert s.error == 0 assert_span_http_status_code(s, 200) assert s.meta.get(http.METHOD) == "GET" cherrypy.tools.tracer.service = previous_service