コード例 #1
0
    def test_beta_endpoint_call_report_and_refresh_and_do_not_override_one_setting_of_default_agent_configuration(
            self):
        self.environment["agent_config_merger"] = AgentConfigurationMerger(
            default=self.agent_config,
            user_overrides=AgentConfiguration(sampling_interval=timedelta(
                seconds=2)))

        sdk_reporter = SdkReporter(self.environment)
        sdk_reporter.setup()

        assert AgentConfiguration.get().should_profile is True
        assert AgentConfiguration.get().sampling_interval == timedelta(
            seconds=2)
        assert AgentConfiguration.get().reporting_interval == timedelta(
            minutes=13)
        assert AgentConfiguration.get().minimum_time_reporting == timedelta(
            minutes=6)
        assert AgentConfiguration.get().max_stack_depth == 2345
        assert AgentConfiguration.get().cpu_limit_percentage == 29

        assert sdk_reporter.report(self.profile) is True

        sdk_reporter.refresh_configuration()
        assert AgentConfiguration.get().should_profile is True
        assert AgentConfiguration.get().sampling_interval == timedelta(
            seconds=2)
        assert AgentConfiguration.get().reporting_interval == timedelta(
            minutes=5)
        assert AgentConfiguration.get().minimum_time_reporting == timedelta(
            seconds=60)
        assert AgentConfiguration.get().max_stack_depth == 1000
        assert AgentConfiguration.get().cpu_limit_percentage == 10
    def before(self):
        self.mock_collector = MagicMock(name="collector", spec=LocalAggregator)
        self.mock_disabler = MagicMock(name="profile", spec=ProfilerDisabler)
        self.mock_disabler.should_stop_profiling.return_value = False
        self.mock_disabler.should_stop_sampling.return_value = False
        self.mock_sampler = MagicMock(name="sampler", spec=Sampler)

        self.environment = {
            "collector": self.mock_collector,
            "profiler_disabler": self.mock_disabler,
            "sampler": self.mock_sampler,
            "initial_sampling_interval": timedelta(),
            "profiler_thread_name":
            "codeguru-profiler-agent-TestProfilerRunner"
        }

        self.agent_configuration = AgentConfiguration(
            should_profile=True,
            sampling_interval=timedelta(seconds=2),
            reporting_interval=timedelta(seconds=100))

        # mock the collector's refresh_configuration function to actual set agent configuration singleton
        def set_new_configuration():
            AgentConfiguration.set(self.agent_configuration)

        self.mock_collector.refresh_configuration.side_effect = set_new_configuration

        # mock the collector's flush function to return True or False according to self.is_time_to_report
        self.is_time_to_report = False
        self.mock_collector.flush.side_effect = lambda *args, **kwargs: self.is_time_to_report
        self.mock_collector.profile = None  # we need this as we pass the profile object to the disabler, None is fine
        self.profiler_runner = ProfilerRunner(self.environment)

        yield
        self.profiler_runner.stop()
コード例 #3
0
    def before(self):
        codeguru_client_builder = CodeGuruClientBuilder(
            environment={"aws_session": boto3.session.Session()})

        self.client_stubber = Stubber(codeguru_client_builder.codeguru_client)

        self.clear_lambda_specific_environment_variables_for_test_run()

        profile_encoder = MagicMock(name="profile_encoder",
                                    spec=ProfileEncoder)
        profile_encoder.encode.side_effect = lambda **args: args[
            "output_stream"].write(b"test-profile-encoder-output")
        self.environment = {
            "profiling_group_name": profiling_group_name,
            "profile_encoder": profile_encoder,
            "codeguru_profiler_builder": codeguru_client_builder,
            "agent_metadata": AgentMetadata(fleet_info=DefaultFleetInfo()),
            "reporting_interval": timedelta(minutes=13),
            "sampling_interval": timedelta(seconds=13),
            "minimum_time_reporting": timedelta(minutes=13),
            "max_stack_depth": 1300
        }
        default_config = AgentConfiguration(
            should_profile=True,
            sampling_interval=self.environment["sampling_interval"],
            reporting_interval=self.environment["reporting_interval"],
            minimum_time_reporting=self.environment["minimum_time_reporting"])
        self.environment["agent_config_merger"] = AgentConfigurationMerger(
            default_config)
        self.subject = SdkReporter(environment=self.environment)
        self.subject.setup()
コード例 #4
0
    def before(self):
        now_millis = int(time.time()) * 1000
        five_minutes_ago_millis = now_millis - (5 * 60 * 1000)
        sample = Sample(
            stacks=[[Frame(MY_PROFILING_GROUP_NAME_FOR_INTEG_TESTS)]],
            attempted_sample_threads_count=1,
            seen_threads_count=1)

        self.profile = Profile(MY_PROFILING_GROUP_NAME_FOR_INTEG_TESTS, 1.0,
                               1.0, five_minutes_ago_millis)
        # FIXME: Remove adding the end time manually below after feature fully support
        self.profile.end = now_millis
        self.profile.add(sample)

        self.environment = {
            "should_profile": True,
            "profiling_group_name": MY_PROFILING_GROUP_NAME_FOR_INTEG_TESTS,
            "aws_session": boto3.session.Session(),
            "reporting_interval": timedelta(minutes=13),
            "sampling_interval": timedelta(seconds=1),
            "minimum_time_reporting": timedelta(minutes=6),
            "max_stack_depth": 2345,
            "cpu_limit_percentage": 29,
            "agent_metadata": AgentMetadata(fleet_info=DefaultFleetInfo())
        }
        self.environment["codeguru_profiler_builder"] = CodeGuruClientBuilder(
            self.environment)
        self.agent_config = AgentConfiguration(
            should_profile=True,
            sampling_interval=self.environment["sampling_interval"],
            reporting_interval=self.environment["reporting_interval"],
            minimum_time_reporting=self.environment["minimum_time_reporting"],
            max_stack_depth=self.environment["max_stack_depth"],
            cpu_limit_percentage=self.environment["cpu_limit_percentage"])
コード例 #5
0
    def test_user_overrides_are_not_overridden_at_merge_with(self):
        agent_config_merger = AgentConfigurationMerger(
            default=AgentConfiguration(), user_overrides=self.config)
        self.assert_init_values()

        agent_config_merger.merge_with(
            configure_agent_response=self.configure_agent_response)
        self.assert_init_values()
 def before(self):
     self.agent_config = AgentConfiguration(
         should_profile=True,
         sampling_interval=timedelta(milliseconds=9100),
         minimum_time_reporting=timedelta(seconds=7),
         reporting_interval=timedelta(minutes=7),
         max_stack_depth=999,
         cpu_limit_percentage=9)
     AgentConfiguration.set(self.agent_config)
コード例 #7
0
 def before(self):
     self.config = AgentConfiguration(
         should_profile=True,
         sampling_interval=timedelta(milliseconds=1),
         minimum_time_reporting=timedelta(seconds=1),
         reporting_interval=timedelta(minutes=1),
         max_stack_depth=998)
     self.overide_config = AgentConfiguration(sampling_interval=timedelta(
         seconds=9))
     self.configure_agent_response = {
         "agentParameters": {
             "SamplingIntervalInMilliseconds": "2000",
             "MinimumTimeForReportingInMilliseconds": "21000",
             "MaxStackDepth": "1001"
         },
         "periodInSeconds": 123,
         "shouldProfile": False
     }
コード例 #8
0
 def before(self):
     self.config = AgentConfiguration(
         should_profile=True,
         sampling_interval=timedelta(milliseconds=1),
         minimum_time_reporting=timedelta(seconds=1),
         reporting_interval=timedelta(minutes=1),
         max_stack_depth=998)
     self.agent_config_merger = AgentConfigurationMerger(
         default=self.config)
def set_agent_config(sampling_interval_seconds=1,
                     cpu_limit_percentage=DEFAULT_CPU_LIMIT_PERCENTAGE):
    """
    Reporting interval needs to have a minimum value and cpu_limit_percentage is used later in tests;
    the other values can be None as we are not using them here.
    """
    return AgentConfiguration.set(
        AgentConfiguration(
            sampling_interval=timedelta(seconds=sampling_interval_seconds),
            reporting_interval=timedelta(seconds=300),
            minimum_time_reporting=timedelta(seconds=60),
            cpu_limit_percentage=cpu_limit_percentage))
    def before(self):
        self.mock_reporter = MagicMock(name="reporter", spec=SdkReporter)
        self.mock_profile = MagicMock(name="profile", spec=Profile)
        self.mock_profile_factory = MagicMock(name="profile_factory",
                                              spec=Profile,
                                              return_value=self.mock_profile)
        self.timer = mock_timer()
        self.time_now = CURRENT_TIME_FOR_TESTING_SECOND
        self.clock = lambda: self.time_now
        self.reporting_interval = DEFAULT_REPORTING_INTERVAL

        self.environment = {
            "profiling_group_name": TEST_PROFILING_GROUP_NAME,
            "sampling_interval": timedelta(seconds=TEST_SAMPLING_INTERVAL),
            "host_weight": TEST_HOST_WEIGHT,
            "profile_factory": self.mock_profile_factory,
            "errors_metadata": ERRORS_METADATA,
            "memory_limit_bytes": DEFAULT_MEMORY_LIMIT_BYTES,
            "clock": self.clock,
            "timer": self.timer,
        }

        self.configuration = {
            "reporter": self.mock_reporter,
            "environment": self.environment,
        }

        AgentConfiguration.set(
            AgentConfiguration(
                should_profile=True,
                sampling_interval=timedelta(seconds=TEST_SAMPLING_INTERVAL),
                minimum_time_reporting=INITIAL_MINIMUM_REPORTING_INTERVAL,
                reporting_interval=self.reporting_interval,
                max_stack_depth=999,
                cpu_limit_percentage=10))

        assert len(self.environment.keys()) == 8
        self.profiler = Profiler(
            profiling_group_name=TEST_PROFILING_GROUP_NAME,
            environment_override=self.environment)
        assert len(self.environment.keys()) == 7

        self.subject = LocalAggregator(**self.configuration)
        self.mock_profile_factory.reset_mock()
        self.timer.reset_mock()

        def move_clock_to(duration_timedelta):
            self.time_now = \
                CURRENT_TIME_FOR_TESTING_SECOND + duration_timedelta.total_seconds()

        self.move_clock_to = move_clock_to
    def test_when_orchestrator_says_no_to_profiler(self):
        self.agent_configuration = AgentConfiguration(
            should_profile=False,
            sampling_interval=timedelta(seconds=2),
            reporting_interval=timedelta(seconds=151))
        # calling start in this test, it will start the scheduler and because initial delay is 0 it will execute now
        self.profiler_runner.start()
        # still it is safer to wait until the new config has been applied
        wait_for(lambda: AgentConfiguration.get().reporting_interval.
                 total_seconds() == 151)
        wait_for(lambda: self.profiler_runner.scheduler.
                 _get_next_delay_seconds() == 151)

        assert self.profiler_runner.scheduler._get_next_delay_seconds() == 151
        self.mock_collector.add.assert_not_called()
コード例 #12
0
    def __init__(self,
                 profiling_group_name,
                 region_name=None,
                 aws_session=None,
                 environment_override=dict()):
        """
        NOTE: The profiler MUST be instantiated using keyword arguments. We provide no compatibility for the order
        (or number) of arguments.

        - Configuration

            :param profiling_group_name: name of the profiling group where the profiles will be stored.
            :param region_name: AWS Region to report to, given profiling group name must exist in that region. Note
                that this value overwrites what is used in aws_session. If not provided, boto3 will search
                configuration for the region. (e.g. "us-west-2")
            :param aws_session: The boto3.Session that this profiler should be using for communicating with the backend
                Check https://boto3.amazonaws.com/v1/documentation/api/latest/guide/session.html for more details.

        - Advanced Configuration Options - We recommend not to touch these
            :param environment_override: custom dependency container dictionary. allows custom behavior to be injected
                but please note that we do not guarantee compatibility between any different profiler agent versions for
                this api (default: dict()). Possible keys:
                    - reporting_interval: delay between profile reports in datetime.timedelta (default: None)
                    - sampling_interval: delay between each sample in datetime.timedelta (default: 1 seconds)
                    - reporting_mode: Reporting mode to be used, two modes are supported: "codeguru_service" and "file".
                                      "file" mode is only used for testing at the moment. (default: "codeguru_service")
                    - file_prefix: path + file prefix to use for profile reports when in "file" reporting mode
                                   (default: './profile-{profiling_group_name}' only used when reporting mode is "file")
                    - cpu_limit_percentage: cpu limit (%) for profiler (default: 30)
                    - max_threads: the max number of threads getting sampled (default: 100)
                    - killswitch_filepath: file path pointing to the killswitch file (default: "/var/tmp/killProfiler")
                    - host_weight: A scale factor used to rescale the profile collected in this host to make the profile
                                   representative of the whole fleet (default: 1)
                    - endpoint_url: url used for submitting profile (default: None, will target codeguru prod APIs)
                    - excluded_threads: set of thread names to be excluded from sampling (default: set())
        """
        self._profiler_runner_instance = None
        self.environment = {}
        try:
            if not profiling_group_name:
                logger.info(
                    "Profiler must be passed a non empty profiling group name, CodeGuru Profiler will not start. "
                    "Please specify a ``profiling_group_name`` when configuring the ``Profiler`` class."
                )
                return

            # This is the profiler instance-wide dependency container aka environment
            # It is used to contain shared dependencies and configuration, and can also be used to override the behavior
            # on the profiler classes without needing to monkey-patch.
            self.environment = self._set_default_environment(
                profiling_group_name)
            self.environment["profiling_group_name"] = profiling_group_name
            self.environment["region_name"] = region_name
            self.environment["aws_session"] = aws_session

            default_config = AgentConfiguration(
                should_profile=self.environment["should_profile"],
                sampling_interval=self.environment["sampling_interval"],
                reporting_interval=self.environment["reporting_interval"],
                minimum_time_reporting=self.
                environment["minimum_time_reporting"],
                max_stack_depth=self.environment["max_stack_depth"],
                cpu_limit_percentage=self.environment["cpu_limit_percentage"])
            user_overrides = AgentConfiguration(
                should_profile=environment_override.get('should_profile'),
                sampling_interval=environment_override.get(
                    'sampling_interval'),
                reporting_interval=environment_override.get(
                    'reporting_interval'),
                minimum_time_reporting=environment_override.get(
                    'minimum_time_reporting'),
                max_stack_depth=environment_override.get('max_stack_depth'),
                cpu_limit_percentage=environment_override.get(
                    'cpu_limit_percentage'))
            agent_config_merger = AgentConfigurationMerger(
                default=default_config, user_overrides=user_overrides)
            self.environment["agent_config_merger"] = agent_config_merger

            # Removing all keys from the environment that were used for the AgentConfigurationMerger
            # to make sure the rest of the code would read it from the AgentConfiguration.
            for key in default_config.as_dict().keys():
                del self.environment[key]
            for key in user_overrides.as_dict().keys():
                del environment_override[key]

            self.environment = self._setup_final_environment(
                self.environment, environment_override)
            profiler_runner_factory = self.environment.get(
                "profiler_runner_factory") or ProfilerRunner
            self._profiler_runner_instance = profiler_runner_factory(
                environment=self.environment)
        except:
            logger.info(
                "Caught exception while creating the CodeGuru Profiler Agent instance",
                exc_info=True)
            if environment_override.get("allow_top_level_exceptions") is True:
                raise
 def test_when_customer_reporting_interval_is_less_than_30_seconds_it_raises_a_value_error(
         self):
     with pytest.raises(ValueError):
         AgentConfiguration(reporting_interval=timedelta(seconds=28),
                            minimum_time_reporting=timedelta(seconds=29))