Пример #1
0
    def setUp(self):
        thread_patch = mock.patch("threading.Thread", autospec=True)
        thread_patch.start()
        self.addCleanup(thread_patch.stop)
        configurator = Configurator()
        configurator.add_route("example", "/example", request_method="GET")
        configurator.add_view(example_application,
                              route_name="example",
                              renderer="json")

        configurator.add_route("local_test",
                               "/local_test",
                               request_method="GET")
        configurator.add_view(local_parent_trace_within_context,
                              route_name="local_test",
                              renderer="json")

        self.client = make_client("test-service")
        self.observer = TraceBaseplateObserver(self.client)

        self.baseplate = Baseplate()
        self.baseplate.register(self.observer)

        self.baseplate_configurator = BaseplateConfigurator(
            self.baseplate,
            trust_trace_headers=True,
        )
        configurator.include(self.baseplate_configurator.includeme)
        app = configurator.make_wsgi_app()
        self.local_span_ids = []
        self.local_span_observers = []
        self.test_app = webtest.TestApp(app)
Пример #2
0
    def test_simple_config(self):
        baseplate = Baseplate({"db.url": "sqlite://"})
        baseplate.configure_context({"db": SQLAlchemySession()})

        context = baseplate.make_context_object()
        with baseplate.make_server_span(context, "test"):
            context.db.execute("SELECT 1;")
Пример #3
0
def test_connection_error(client_cls):
    baseplate = Baseplate({
        "myclient.filter.ip_allowlist": "127.0.0.0/8",
        "myclient.filter.port_denylist": "0"
    })
    baseplate.configure_context({"myclient": client_cls()})

    observer = TestBaseplateObserver()
    baseplate.register(observer)

    bogus_url = "http://localhost:1/"
    with pytest.raises(requests.exceptions.ConnectionError):
        with baseplate.server_context("test") as context:
            context.myclient.get(bogus_url)

    server_span_observer = observer.children[0]
    assert len(server_span_observer.children) == 1

    client_span_observer = server_span_observer.children[0]
    assert client_span_observer.span.name == "myclient.request"
    assert client_span_observer.on_start_called
    assert client_span_observer.on_finish_called
    assert client_span_observer.on_finish_exc_info is not None
    assert client_span_observer.tags["http.url"] == bogus_url
    assert client_span_observer.tags["http.method"] == "GET"
    assert "http.status_code" not in client_span_observer.tags
Пример #4
0
    def test_configure_context_supports_complex_specs(self):
        from baseplate.clients.thrift import ThriftClient
        from baseplate.thrift import BaseplateService

        app_config = {
            "enable_some_fancy_feature": "true",
            "thrift.foo.endpoint": "localhost:9090",
            "thrift.bar.endpoint": "localhost:9091",
        }

        baseplate = Baseplate()
        baseplate.configure_context(
            app_config,
            {
                "enable_some_fancy_feature": config.Boolean,
                "thrift": {
                    "foo": ThriftClient(BaseplateService.Client),
                    "bar": ThriftClient(BaseplateService.Client),
                },
            },
        )

        context = baseplate.make_context_object()
        with baseplate.make_server_span(context, "test"):
            self.assertTrue(context.enable_some_fancy_feature)
            self.assertIsNotNone(context.thrift.foo)
            self.assertIsNotNone(context.thrift.bar)
Пример #5
0
def http_server(gevent_socket):
    class HttpServer:
        def __init__(self, address):
            self.url = f"http://{address[0]}:{address[1]}/"
            self.requests = []

        def handle_request(self, request):
            self.requests.append(request)
            return HTTPNoContent()

    server_bind_endpoint = config.Endpoint("127.0.0.1:0")
    listener = make_listener(server_bind_endpoint)
    server_address = listener.getsockname()
    http_server = HttpServer(server_address)

    baseplate = Baseplate()
    trust_handler = StaticTrustHandler(trust_headers=True)
    baseplate_configurator = BaseplateConfigurator(
        baseplate, header_trust_handler=trust_handler)
    configurator = Configurator()
    configurator.include(baseplate_configurator.includeme)
    configurator.add_route("test_view", "/")
    configurator.add_view(http_server.handle_request,
                          route_name="test_view",
                          renderer="json")
    wsgi_app = configurator.make_wsgi_app()

    server = make_server({"stop_timeout": "1 millisecond"}, listener, wsgi_app)
    server_greenlet = gevent.spawn(server.serve_forever)
    try:
        yield http_server
    finally:
        server_greenlet.kill()
Пример #6
0
    def setUp(self):
        self.baseplate_observer = TestBaseplateObserver()

        profiles = {
            "foo": ExecutionProfile(consistency_level=ConsistencyLevel.QUORUM)
        }

        baseplate = Baseplate()
        baseplate.register(self.baseplate_observer)
        baseplate.configure_context(
            {
                "cassandra.contact_points":
                cassandra_endpoint.address.host,
                "cassandra_no_prof.contact_points":
                cassandra_endpoint.address.host,
            },
            {
                "cassandra_no_prof":
                CassandraClient(keyspace="system"),
                "cassandra":
                CassandraClient(keyspace="system",
                                execution_profiles=profiles),
            },
        )

        self.context = baseplate.make_context_object()
        self.server_span = baseplate.make_server_span(self.context, "test")
def make_wsgi_app(app_config):
    cfg = config.parse_config(app_config)
    signer = MessageSigner(cfg.ads_tracking.click_secret)

    metrics_client = make_metrics_client(app_config)

    baseplate = Baseplate()
    baseplate.configure_logging()
    baseplate.configure_metrics(metrics_client)
    baseplate.add_to_context("events", events.EventQueue("production"))
    baseplate.add_to_context("events_test", events.EventQueue("test"))

    configurator = Configurator(settings=app_config)

    baseplate_configurator = BaseplateConfigurator(baseplate)
    configurator.include(baseplate_configurator.includeme)

    controller = TrackingService(signer=signer, )
    configurator.add_route("health", "/health", request_method="GET")
    configurator.add_view(controller.is_healthy,
                          route_name="health",
                          renderer="json")

    configurator.add_route("click", "/click", request_method="GET")
    configurator.add_view(controller.track_click,
                          route_name="click",
                          renderer="json")

    return configurator.make_wsgi_app()
Пример #8
0
    def setUp(self):
        configurator = Configurator()
        configurator.add_route("example", "/example", request_method="GET")
        configurator.add_route("trace_context",
                               "/trace_context",
                               request_method="GET")

        configurator.add_view(example_application,
                              route_name="example",
                              renderer="json")

        configurator.add_view(local_tracing_within_context,
                              route_name="trace_context",
                              renderer="json")

        self.observer = mock.Mock(spec=BaseplateObserver)
        self.server_observer = mock.Mock(spec=ServerSpanObserver)

        def _register_mock(context, server_span):
            server_span.register(self.server_observer)

        self.observer.on_server_span_created.side_effect = _register_mock

        self.baseplate = Baseplate()
        self.baseplate.register(self.observer)
        self.baseplate_configurator = BaseplateConfigurator(
            self.baseplate,
            trust_trace_headers=True,
        )
        configurator.include(self.baseplate_configurator.includeme)
        app = configurator.make_wsgi_app()
        self.test_app = webtest.TestApp(app)
Пример #9
0
def make_processor(app_config):  # pragma: nocover
    cfg = config.parse_config(app_config, {
        "activity": {
            "window": config.Timespan,
            "fuzz_threshold": config.Integer,
        },

        "redis": {
            "url": config.String,
            "max_connections": config.Optional(config.Integer, default=100),
        },
    })

    metrics_client = make_metrics_client(app_config)
    redis_pool = redis.BlockingConnectionPool.from_url(
        cfg.redis.url,
        max_connections=cfg.redis.max_connections,
        timeout=0.1,
    )

    baseplate = Baseplate()
    baseplate.configure_logging()
    baseplate.configure_metrics(metrics_client)
    baseplate.add_to_context("redis", RedisContextFactory(redis_pool))

    counter = ActivityCounter(cfg.activity.window.total_seconds())
    handler = Handler(
        fuzz_threshold=cfg.activity.fuzz_threshold,
        counter=counter,
    )
    processor = ActivityService.ContextProcessor(handler)
    event_handler = BaseplateProcessorEventHandler(logger, baseplate)
    processor.setEventHandler(event_handler)

    return processor
Пример #10
0
def baseplate_thrift_client(endpoint, client_spec, client_span_observer=None):
    baseplate = Baseplate(
        app_config={
            "baseplate.service_name": "fancy test client",
            "example_service.endpoint": str(endpoint),
        }
    )

    if client_span_observer:

        class TestServerSpanObserver(ServerSpanObserver):
            def on_child_span_created(self, span):
                span.register(client_span_observer)

        observer = TestServerSpanObserver()

        class TestBaseplateObserver(BaseplateObserver):
            def on_server_span_created(self, context, span):
                span.register(observer)

        baseplate.register(TestBaseplateObserver())

    context = baseplate.make_context_object()
    trace_info = TraceInfo.from_upstream(
        trace_id="1234", parent_id="2345", span_id="3456", flags=4567, sampled=True
    )

    baseplate.configure_context({"example_service": ThriftClient(client_spec.Client)})

    baseplate.make_server_span(context, "example_service.example", trace_info)

    context.raw_edge_context = FakeEdgeContextFactory.RAW_BYTES

    yield context
Пример #11
0
def test_client_makes_client_span(client_cls, method, http_server):
    baseplate = Baseplate({
        "myclient.filter.ip_allowlist": "127.0.0.0/8",
        "myclient.filter.port_denylist": "0"
    })
    baseplate.configure_context({"myclient": client_cls()})

    observer = TestBaseplateObserver()
    baseplate.register(observer)

    with baseplate.server_context("test") as context:
        fn = getattr(context.myclient, method.lower())
        response = fn(http_server.url)

    assert response.status_code == 204

    server_span_observer = observer.children[0]
    assert len(server_span_observer.children) == 1

    client_span_observer = server_span_observer.children[0]
    assert client_span_observer.span.name == "myclient.request"
    assert client_span_observer.on_start_called
    assert client_span_observer.on_finish_called
    assert client_span_observer.on_finish_exc_info is None
    assert client_span_observer.tags["http.url"] == http_server.url
    assert client_span_observer.tags["http.method"] == method
    assert client_span_observer.tags["http.status_code"] == 204
Пример #12
0
def serve_thrift(handler, server_span_observer=None):
    # create baseplate root
    baseplate = Baseplate()
    if server_span_observer:

        class TestBaseplateObserver(BaseplateObserver):
            def on_server_span_created(self, context, server_span):
                server_span.register(server_span_observer)

        baseplate.register(TestBaseplateObserver())

    # set up the server's processor
    logger = mock.Mock(spec=logging.Logger)
    edge_context_factory = make_edge_context_factory()
    processor = TestService.Processor(handler)
    processor = baseplateify_processor(processor, logger, baseplate, edge_context_factory)

    # bind a server socket on an available port
    server_bind_endpoint = config.Endpoint("127.0.0.1:0")
    listener = make_listener(server_bind_endpoint)
    server = make_server(
        {"max_concurrency": "100", "stop_timeout": "1 millisecond"}, listener, processor
    )

    # figure out what port the server ended up on
    server_address = listener.getsockname()
    server.endpoint = config.Endpoint(f"{server_address[0]}:{server_address[1]}")

    # run the server until our caller is done with it
    server_greenlet = gevent.spawn(server.serve_forever)
    try:
        yield server
    finally:
        server_greenlet.kill()
Пример #13
0
 def test_configure_tracing_with_defaults_legacy_style(self):
     baseplate = Baseplate()
     self.assertEqual(0, len(baseplate.observers))
     baseplate.configure_tracing('test')
     self.assertEqual(1, len(baseplate.observers))
     tracing_observer = baseplate.observers[0]
     self.assertEqual('test', tracing_observer.service_name)
Пример #14
0
    def setUp(self):
        configurator = Configurator()
        configurator.add_route("example", "/example", request_method="GET")
        configurator.add_route("trace_context",
                               "/trace_context",
                               request_method="GET")

        configurator.add_view(example_application,
                              route_name="example",
                              renderer="json")

        configurator.add_view(local_tracing_within_context,
                              route_name="trace_context",
                              renderer="json")

        configurator.add_view(render_exception_view,
                              context=ControlFlowException,
                              renderer="json")

        configurator.add_view(render_bad_exception_view,
                              context=ControlFlowException2,
                              renderer="json")

        mock_filewatcher = mock.Mock(spec=FileWatcher)
        mock_filewatcher.get_data.return_value = {
            "secrets": {
                "secret/authentication/public-key": {
                    "type": "versioned",
                    "current": AUTH_TOKEN_PUBLIC_KEY,
                }
            },
            "vault": {
                "token": "test",
                "url": "http://vault.example.com:8200/"
            },
        }
        secrets = SecretsStore("/secrets")
        secrets._filewatcher = mock_filewatcher

        self.observer = mock.Mock(spec=BaseplateObserver)
        self.server_observer = mock.Mock(spec=ServerSpanObserver)

        def _register_mock(context, server_span):
            server_span.register(self.server_observer)

        self.observer.on_server_span_created.side_effect = _register_mock

        self.baseplate = Baseplate()
        self.baseplate.register(self.observer)
        self.baseplate_configurator = BaseplateConfigurator(
            self.baseplate,
            trust_trace_headers=True,
            edge_context_factory=EdgeRequestContextFactory(secrets),
        )
        configurator.include(self.baseplate_configurator.includeme)
        self.context_init_event_subscriber = mock.Mock()
        configurator.add_subscriber(self.context_init_event_subscriber,
                                    ServerSpanInitialized)
        app = configurator.make_wsgi_app()
        self.test_app = webtest.TestApp(app)
Пример #15
0
def make_wsgi_app(app_config):
    cfg = config.parse_config(app_config, {
        "activity": {
            "endpoint": config.Endpoint,
        },
    })

    metrics_client = make_metrics_client(app_config)

    pool = ThriftConnectionPool(cfg.activity.endpoint)

    baseplate = Baseplate()
    baseplate.configure_logging()
    baseplate.configure_metrics(metrics_client)
    baseplate.add_to_context(
        "activity", ThriftContextFactory(pool, ActivityService.Client))

    configurator = Configurator(settings=app_config)

    baseplate_configurator = BaseplateConfigurator(baseplate)
    configurator.include(baseplate_configurator.includeme)

    controller = ActivityGateway()
    configurator.add_route("health", "/health", request_method="GET")
    configurator.add_view(controller.is_healthy,
                          route_name="health",
                          renderer="json")

    configurator.add_route("pixel",
                           "/{context_id:[A-Za-z0-9_]{,40}}.png",
                           request_method="GET")
    configurator.add_view(controller.pixel, route_name="pixel")

    return configurator.make_wsgi_app()
Пример #16
0
 def test_configure_tracing_with_defaults_new_style(self):
     baseplate = Baseplate()
     self.assertEqual(0, len(baseplate.observers))
     client = make_client("test")
     baseplate.configure_tracing(client)
     self.assertEqual(1, len(baseplate.observers))
     tracing_observer = baseplate.observers[0]
     self.assertEqual('test', tracing_observer.service_name)
Пример #17
0
    def test_null_server_observer(self):
        baseplate = Baseplate()
        mock_context = baseplate.make_context_object()
        mock_observer = mock.Mock(spec=BaseplateObserver)
        mock_observer.on_server_span_created.return_value = None
        baseplate.register(mock_observer)
        server_span = baseplate.make_server_span(mock_context, "name", TraceInfo(1, 2, 3, None, 0))

        self.assertEqual(server_span.observers, [])
Пример #18
0
    def test_with_server_context(self):
        baseplate = Baseplate()
        observer = mock.Mock(spec=BaseplateObserver)
        baseplate.register(observer)

        observer.on_server_span_created.assert_not_called()
        with baseplate.server_context("example") as context:
            observer.on_server_span_created.assert_called_once()
            self.assertIsInstance(context, RequestContext)
Пример #19
0
    def setUp(self):
        self.baseplate_observer = TestBaseplateObserver()

        baseplate = Baseplate({"redis.url": f"redis://{redis_endpoint}/0"})
        baseplate.register(self.baseplate_observer)
        baseplate.configure_context({"redis": RedisClient()})

        self.context = baseplate.make_context_object()
        self.server_span = baseplate.make_server_span(self.context, "test")
Пример #20
0
    def setUp(self):
        self.baseplate_observer = TestBaseplateObserver()

        baseplate = Baseplate({"memcache.endpoint": str(memcached_endpoint)})
        baseplate.register(self.baseplate_observer)
        baseplate.configure_context({"memcache": MemcacheClient()})

        self.context = baseplate.make_context_object()
        self.server_span = baseplate.make_server_span(self.context, "test")
Пример #21
0
    def setUp(self):
        self.baseplate_observer = TestBaseplateObserver()

        baseplate = Baseplate({"cassandra.contact_points": cassandra_endpoint.address.host})
        baseplate.register(self.baseplate_observer)
        baseplate.configure_context({"cassandra": CassandraClient(keyspace="system")})

        self.context = baseplate.make_context_object()
        self.server_span = baseplate.make_server_span(self.context, "test")
Пример #22
0
def make_wsgi_app(app_config):
    baseplate = Baseplate()
    baseplate.configure_observers(app_config)

    configurator = Configurator(settings=app_config)
    configurator.include(BaseplateConfigurator(baseplate).includeme)
    configurator.add_route("hello_world", "/", request_method="GET")
    configurator.scan()
    return configurator.make_wsgi_app()
Пример #23
0
    def test_context_object_reused(self):
        baseplate = Baseplate()
        context = baseplate.make_context_object()

        with baseplate.make_server_span(context, "foo"):
            pass

        with self.assertRaises(ReusedContextObjectError):
            with baseplate.make_server_span(context, "bar"):
                pass
Пример #24
0
    def test_add_to_context(self):
        baseplate = Baseplate()
        forty_two_factory = mock.Mock(spec=ContextFactory)
        forty_two_factory.make_object_for_context = mock.Mock(return_value=42)
        baseplate.add_to_context("forty_two", forty_two_factory)
        baseplate.add_to_context("true", True)

        context = baseplate.make_context_object()

        self.assertEqual(42, context.forty_two)
        self.assertTrue(context.true)
Пример #25
0
    def test_server_observer_made(self):
        baseplate = Baseplate()
        mock_context = baseplate.make_context_object()
        mock_observer = mock.Mock(spec=BaseplateObserver)
        baseplate.register(mock_observer)
        server_span = baseplate.make_server_span(mock_context, "name",
                                                 TraceInfo(1, 2, 3, None, 0))

        self.assertEqual(baseplate.observers, [mock_observer])
        self.assertEqual(mock_observer.on_server_span_created.call_count, 1)
        self.assertEqual(mock_observer.on_server_span_created.call_args,
                         mock.call(mock_context, server_span))
Пример #26
0
    def setUp(self):
        self.baseplate_observer = TestBaseplateObserver()

        baseplate = Baseplate({
            "rediscluster.url": f"redis://{redis_endpoint}/0",
            "rediscluster.timeout": "1 second",
            "rediscluster.max_connections": "4",
        })
        baseplate.register(self.baseplate_observer)
        baseplate.configure_context({"rediscluster": ClusterRedisClient()})

        self.context = baseplate.make_context_object()
        self.server_span = baseplate.make_server_span(self.context, "test")
Пример #27
0
 def test_configure_tracing_with_args(self):
     baseplate = Baseplate()
     self.assertEqual(0, len(baseplate.observers))
     baseplate.configure_tracing('test',
                                 None,
                                 max_span_queue_size=500,
                                 num_span_workers=5,
                                 span_batch_interval=0.5,
                                 num_conns=100,
                                 sample_rate=0.1)
     self.assertEqual(1, len(baseplate.observers))
     tracing_observer = baseplate.observers[0]
     self.assertEqual('test', tracing_observer.service_name)
Пример #28
0
    def setUp(self):
        engine = engine_from_config({"database.url":
                                     "sqlite://"})  # in-memory db
        Base.metadata.create_all(bind=engine)
        factory = SQLAlchemySessionContextFactory(engine)

        self.baseplate_observer = TestBaseplateObserver()

        baseplate = Baseplate()
        baseplate.register(self.baseplate_observer)
        baseplate.add_to_context("db", factory)

        self.context = baseplate.make_context_object()
        self.server_span = baseplate.make_server_span(self.context, "test")
Пример #29
0
def test_default_timeout():
    baseplate = Baseplate()

    observer = TimeoutBaseplateObserver.from_config({"server_timeout.default": "50 milliseconds"})
    baseplate.register(observer)

    context = baseplate.make_context_object()
    with baseplate.make_server_span(context, "test"):
        with pytest.raises(ServerTimeout):
            gevent.sleep(1)

    context = baseplate.make_context_object()
    with baseplate.make_server_span(context, "test"):
        gevent.sleep(0)  # shouldn't time out since it's so fast!
Пример #30
0
    def setUp(self):
        configurator = Configurator()
        configurator.add_route("example", "/example", request_method="GET")
        configurator.add_route("trace_context",
                               "/trace_context",
                               request_method="GET")

        configurator.add_view(example_application,
                              route_name="example",
                              renderer="json")

        configurator.add_view(local_tracing_within_context,
                              route_name="trace_context",
                              renderer="json")

        mock_filewatcher = mock.Mock(spec=FileWatcher)
        mock_filewatcher.get_data.return_value = {
            "secrets": {
                "jwt/authentication/secret": {
                    "type": "simple",
                    "value": self.TOKEN_SECRET,
                },
            },
            "vault": {
                "token": "test",
                "url": "http://vault.example.com:8200/",
            }
        }
        secrets = store.SecretsStore("/secrets")
        secrets._filewatcher = mock_filewatcher

        self.observer = mock.Mock(spec=BaseplateObserver)
        self.server_observer = mock.Mock(spec=ServerSpanObserver)

        def _register_mock(context, server_span):
            server_span.register(self.server_observer)

        self.observer.on_server_span_created.side_effect = _register_mock

        self.baseplate = Baseplate()
        self.baseplate.register(self.observer)
        self.baseplate_configurator = BaseplateConfigurator(
            self.baseplate,
            trust_trace_headers=True,
            auth_factory=AuthenticationContextFactory(secrets),
        )
        configurator.include(self.baseplate_configurator.includeme)
        app = configurator.make_wsgi_app()
        self.test_app = webtest.TestApp(app)