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
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
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!
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)
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;")
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 consume( baseplate: Baseplate, exchange: Exchange, connection: Connection, queue_name: str, routing_keys: Sequence[str], handler: Handler, ) -> NoReturn: """Create a long-running process to consume messages from a queue. A queue with name ``queue_name`` is created and bound to the ``routing_keys`` so messages published to the ``routing_keys`` are routed to the queue. Next, the process registers a consumer that receives messages from the queue and feeds them to the ``handler``. The ``handler`` function must take 3 arguments: * ``context``: a baseplate context * ``message_body``: the text body of the message * ``message``: :py:class:`kombu.message.Message` The consumer will automatically ``ack`` each message after the handler method exits. If there is an error in processing and the message must be retried the handler should raise an exception to crash the process. This will prevent the ``ack`` and the message will be re-queued at the head of the queue. :param baseplate: A baseplate instance for the service. :param exchange: :param connection: :param queue_name: The name of the queue. :param routing_keys: List of routing keys. :param handler: The handler method. """ warn_deprecated( "baseplate.frameworks.queue_consumer is deprecated and will be removed " "in the next major release. You should migrate your consumers to use " "baseplate.server.queue_consumer.\n" "https://baseplate.readthedocs.io/en/stable/api/baseplate/frameworks/queue_consumer/deprecated.html" ) queues = [] for routing_key in routing_keys: queues.append( Queue(name=queue_name, exchange=exchange, routing_key=routing_key)) logger.info("registering %s as a handler for %r", handler.__name__, queues) kombu_consumer = KombuConsumer.new(connection, queues) logger.info("waiting for messages") while True: context = baseplate.make_context_object() with baseplate.make_server_span(context, queue_name) as span: message = kombu_consumer.get_message(span) handler(context, message.body, message) message.ack()
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")
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")
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, [])
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")
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))
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) edge_context_factory = make_edge_context_factory() edge_context = edge_context_factory.from_upstream( SERIALIZED_EDGECONTEXT_WITH_VALID_AUTH) edge_context.attach_context(context) yield context
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")
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")
def setUp(self): self.allowance = 10 self.interval = 1 ratelimiter_factory = RateLimiterContextFactory( self.backend_factory, self.allowance, self.interval ) self.baseplate_observer = TestBaseplateObserver() baseplate = Baseplate() baseplate.register(self.baseplate_observer) baseplate.add_to_context("ratelimiter", ratelimiter_factory) self.context = baseplate.make_context_object() self.server_span = baseplate.make_server_span(self.context, "test")