Esempio n. 1
0
 def setUp(self):
     self._client_sys = FakeSys()
     self._server_sys = FakeSys()
     self._fake_clock = scalyr_util.FakeClock()
     self._client_channel = FakeClientChannel(self._fake_clock)
     self._server_channel = FakeServerChannel(self._client_channel)
     self._client = RedirectorClient(self._client_channel, sys_impl=self._client_sys, fake_clock=self._fake_clock)
     self._server = RedirectorServer(self._server_channel, sys_impl=self._server_sys)
     self._client.start()
     self._server.start()
Esempio n. 2
0
 def setUp(self):
     self._fake_sys = FakeSys()
     # Since the client is an actual other thread that blocks waiting for input from the server, we have to
     # simulate the time using a fake clock.  That will allow us to wait up the client thread from time to time.
     self._fake_clock = scalyr_util.FakeClock()
     # The fake channel allows us to insert bytes being sent by the server.
     self._client_channel = FakeClientChannel(self._fake_clock)
     self._client = RedirectorClient(self._client_channel, sys_impl=self._fake_sys, fake_clock=self._fake_clock)
     self._client.start()
     # Wait until the client thread begins to block for the initial accept from the server.
     self._fake_clock.block_until_n_waiting_threads(1)
    def test_user_agent_polling(self):
        """Test polling of user-agent fragments and invocation of the callback (only on change)

        A MonitorsManager + 2 monitors are started (each has their own threads).
        1 monitor returns non-empty frags. 1 returns None.
        We then verify that the callback is invoked correctly, only if the fragments change.

        Notes:
        - FakeClocks are used to avoid having to wait for thread loops.
        - A FakeAgentLogger is defined so we can modify local test state
        - Even though this test could have been broken up into 2 smaller ones, it is kept as one to minimize overhead
            time taken by stop_manager()
        """
        counter = {"callback_invocations": 0}
        test_frag = "some_frag"
        poll_interval = 30

        # Create MonitorsManager + 2 monitors. Set each to daemon otherwise unit test doesn't terminate
        # Fake the clock to fast-forward MonitorsManager sleep loop
        fake_clock = scalyr_util.FakeClock()
        test_manager, _ = ScalyrTestUtils.create_test_monitors_manager(
            config_monitors=[
                {
                    "module": "scalyr_agent.builtin_monitors.test_monitor",
                    "gauss_mean": 0,
                },
                {
                    "module": "scalyr_agent.builtin_monitors.test_monitor",
                    "gauss_mean": 0,
                },
                {
                    "module": "scalyr_agent.builtin_monitors.test_monitor",
                    "gauss_mean": 0,
                },
            ],
            platform_monitors=[],
            extra_toplevel_config={"user_agent_refresh_interval": poll_interval},
            null_logger=True,
            fake_clock=fake_clock,
        )
        self.assertEquals(
            test_manager._user_agent_refresh_interval, 30
        )  # ensure config setting works
        self.assertEquals(len(test_manager.monitors), 3)
        patched_monitor_0 = test_manager.monitors[0]
        patched_monitor_1 = test_manager.monitors[1]
        unpatched_monitor = test_manager.monitors[2]

        # The MonitorsManager + 3 monitor threads will wait on the fake clock
        fragment_polls = FakeClockCounter(fake_clock, num_waiters=4)

        # Mock the function that returns user_agent_fragment (normally invoked on a Monitor)
        def mock_get_user_agent_fragment():
            # Will be called on 2 patched monitors concurrently
            fragment_polls.increment()
            return test_frag

        for mon in [patched_monitor_0, patched_monitor_1]:
            mon.get_user_agent_fragment = mock_get_user_agent_fragment
            self.assertEquals(
                mon.get_user_agent_fragment(), test_frag
            )  # monkey patched
        self.assertEquals(
            unpatched_monitor.get_user_agent_fragment(), None
        )  # not patched

        # Mock the callback (that would normally be invoked on ScalyrClientSession)
        # Check that the exact fragment returned by the 2 patched monitors are deduplicated.
        def augment_user_agent(fragments):
            counter["callback_invocations"] += 1
            self.assertEquals(fragments, [test_frag])

        test_manager.set_user_agent_augment_callback(augment_user_agent)

        # We're finally ready start all threads and assert correct behavior.
        # Wait for MonitorsManager to poll for user-agent fragments 10x
        # Since 2 monitors are being polled for fragments, num polls should reach 2 x 10 = 20.
        # However, the monitors always return a non-changing frag, so the callback should be invoked only once.
        # (Note: FakeClock ensures all the above happen within a split second)
        test_manager.start_manager()
        self.assertTrue(
            fragment_polls.sleep_until_count_or_maxwait(20, poll_interval, 1)
        )
        self.assertEquals(counter["callback_invocations"], 1)

        # Rerun the above test but this time have monitors return changing fragments.
        # This will cause the user agent callback to be invoked during each round of polling.
        # (The manager polls monitors 10x, and each poll results in a callback invocation).
        fragment_polls = FakeClockCounter(fake_clock, num_waiters=4)
        counter["callback_invocations"] = 0

        def mock_get_user_agent_fragment_2():
            fragment_polls.increment()
            return test_frag + str(fragment_polls.count())

        for mon in [patched_monitor_0, patched_monitor_1]:
            mon.get_user_agent_fragment = mock_get_user_agent_fragment_2

        variable_frag_pattern = re.compile(test_frag + r"\d+")

        def augment_user_agent_2(fragments):
            counter["callback_invocations"] += 1
            self.assertIsNotNone(variable_frag_pattern.match(fragments[0]))

        test_manager.set_user_agent_augment_callback(augment_user_agent_2)

        self.assertTrue(
            fragment_polls.sleep_until_count_or_maxwait(20, poll_interval, 1)
        )
        self.assertEquals(counter["callback_invocations"], 10)

        # set_daemon=True obviates the following (saves a few seconds in cleanup):
        test_manager.stop_manager(wait_on_join=False)
        fake_clock.advance_time(increment_by=poll_interval)