示例#1
0
 def test_add_log_event_should_not_create_event_if_not_allowed_and_not_forced(
         self):
     add_log_event(logger.LogLevel.WARNING, 'A test WARNING log event')
     event_list = self._collect_events()
     self.assertEqual(
         len(event_list), 0,
         "No events should be created if not forced and not allowed")
    def _event_file_size_allowed(self, event_file_path):

        event_file_size = os.stat(event_file_path).st_size
        if event_file_size > self._EXTENSION_EVENT_FILE_MAX_SIZE:
            convert_to_mb = lambda x: (1.0 * x) / (1000 * 1000)
            msg = "Skipping file: {0} as its size is {1:.2f} Mb > Max size allowed {2:.1f} Mb".format(
                event_file_path, convert_to_mb(event_file_size),
                convert_to_mb(self._EXTENSION_EVENT_FILE_MAX_SIZE))
            logger.warn(msg)
            add_log_event(level=logger.LogLevel.WARNING,
                          message=msg,
                          forced=True)
            return False
        return True
示例#3
0
 def test_add_log_event_should_create_events_that_have_all_the_parameters_in_the_telemetry_schema(
         self):
     self._test_create_event_function_should_create_events_that_have_all_the_parameters_in_the_telemetry_schema(
         create_event_function=lambda: add_log_event(
             logger.LogLevel.INFO, 'A test INFO log event'),
         expected_parameters={
             GuestAgentGenericLogsSchema.EventName: 'Log',
             GuestAgentGenericLogsSchema.CapabilityUsed: 'INFO',
             GuestAgentGenericLogsSchema.Context1: 'log event',
             GuestAgentGenericLogsSchema.Context3: ''
         })
示例#4
0
 def test_add_log_event_should_always_create_events_when_forced(self):
     self._test_create_event_function_should_create_events_that_have_all_the_parameters_in_the_telemetry_schema(
         create_event_function=lambda: add_log_event(
             logger.LogLevel.WARNING,
             'A test WARNING log event',
             forced=True),
         expected_parameters={
             GuestAgentGenericLogsSchema.EventName: 'Log',
             GuestAgentGenericLogsSchema.CapabilityUsed: 'WARNING',
             GuestAgentGenericLogsSchema.Context1: 'log event',
             GuestAgentGenericLogsSchema.Context3: ''
         })
示例#5
0
 def test_add_log_event_should_create_events_that_have_all_the_parameters_in_the_telemetry_schema(
         self):
     self._test_create_event_function_should_create_events_that_have_all_the_parameters_in_the_telemetry_schema(
         create_event_function=lambda: add_log_event(
             logger.LogLevel.INFO, 'A test INFO log event'),
         expected_parameters={
             'EventName': 'Log',
             'CapabilityUsed': 'INFO',
             'Context1': 'A test INFO log event',
             'Context2': '',
             'Context3': '',
             'ExtensionType': ''
         })
    def _capture_extension_events(self, handler_name, handler_event_dir_path):
        """
        Capture Extension events and add them to the events_list
        :param handler_name: Complete Handler Name. Eg: Microsoft.CPlat.Core.RunCommandLinux
        :param handler_event_dir_path: Full path. Eg: '/var/log/azure/Microsoft.CPlat.Core.RunCommandLinux/events'
        """

        # Filter out the files that do not follow the pre-defined EXTENSION_EVENT_FILE_NAME_REGEX
        event_files = [
            event_file
            for event_file in os.listdir(handler_event_dir_path) if re.match(
                self._EXTENSION_EVENT_FILE_NAME_REGEX, event_file) is not None
        ]
        # Pick the latest files first, we'll discard older events if len(events) > MAX_EVENT_COUNT
        event_files.sort(reverse=True)

        captured_extension_events_count = 0
        dropped_events_with_error_count = defaultdict(int)

        try:
            for event_file in event_files:

                event_file_path = os.path.join(handler_event_dir_path,
                                               event_file)
                try:
                    logger.verbose("Processing event file: {0}",
                                   event_file_path)

                    if not self._event_file_size_allowed(event_file_path):
                        continue

                    # We support multiple events in a file, read the file and parse events.
                    captured_extension_events_count = self._enqueue_events_and_get_count(
                        handler_name, event_file_path,
                        captured_extension_events_count,
                        dropped_events_with_error_count)

                    # We only allow MAX_NUMBER_OF_EVENTS_PER_EXTENSION_PER_PERIOD=300 maximum events per period per handler
                    if captured_extension_events_count >= self._MAX_NUMBER_OF_EVENTS_PER_EXTENSION_PER_PERIOD:
                        msg = "Reached max count for the extension: {0}; Max Limit: {1}. Skipping the rest.".format(
                            handler_name, self.
                            _MAX_NUMBER_OF_EVENTS_PER_EXTENSION_PER_PERIOD)
                        logger.warn(msg)
                        add_log_event(level=logger.LogLevel.WARNING,
                                      message=msg,
                                      forced=True)
                        break
                except ServiceStoppedError:
                    # Not logging here as already logged once, re-raising
                    # Since we already started processing this file, deleting it as we could've already sent some events out
                    # This is a trade-off between data replication vs data loss.
                    raise
                except Exception as error:
                    msg = "Failed to process event file {0}:{1}".format(
                        event_file, textutil.format_exception(error))
                    logger.warn(msg)
                    add_log_event(level=logger.LogLevel.WARNING,
                                  message=msg,
                                  forced=True)
                finally:
                    # Todo: We should delete files after ensuring that we sent the data to Wireserver successfully
                    # from our end rather than deleting first and sending later. This is to ensure the data reliability
                    # of the agent telemetry pipeline.
                    os.remove(event_file_path)

        finally:
            if dropped_events_with_error_count:
                msg = "Dropped events for Extension: {0}; Details:\n\t{1}".format(
                    handler_name, '\n\t'.join([
                        "Reason: {0}; Dropped Count: {1}".format(k, v)
                        for k, v in dropped_events_with_error_count.items()
                    ]))
                logger.warn(msg)
                add_log_event(level=logger.LogLevel.WARNING,
                              message=msg,
                              forced=True)

            if captured_extension_events_count > 0:
                logger.info("Collected {0} events for extension: {1}".format(
                    captured_extension_events_count, handler_name))