docs: def match_rules(self, log_data):
          """
          Process a log line data message with app's pattern rules.
          Return a tuple with this data:
  
              Element #0 (app_matched): True if a rule match, False otherwise;
              Element #1 (has_full_match): True if a rule match and is a filter or the
                  app has not filters; False if a rule match but is not a filter;
                  None otherwise;
              Element #2 (app_thread): Thread value if a rule match and it has a "thread"
                  group, None otherwise;
              Element #3 (output_data): Mapping dictionary if a rule match and a map
                  of output is requested (--anonymize/--ip/--uid options).
          """
          for rule in self.rules:
              match = rule.regexp.search(log_data.message)
              if match is not None:
                  gids = rule.regexp.groupindex
                  self._last_rule = rule
                  if self.name_cache is not None:
                      values = self.name_cache.match_to_dict(match, rule.key_gids)
                      values['host'] = self.name_cache.map_value(log_data.host, 'host')
                      output_data = {
                          'host': values['host'],
                          'message': self.name_cache.match_to_string(match, gids, values),
                      }
                  else:
                      values = {'host': log_data.host}
                      for gid in gids:
                          values[gid] = match.group(gid)
                      output_data = None
  
                  if self._thread and 'thread' in rule.regexp.groupindex:
                      thread = match.group('thread')
                      if rule.filter_keys is not None and \
                              any([values[key] is None for key in rule.filter_keys]):
                          return False, None, None, None
                      if self._report:
                          rule.add_result(values)
                      return True, rule.full_match, thread, output_data
                  else:
                      if rule.filter_keys is not None and \
                              any([values[key] is None for key in rule.filter_keys]):
                          return False, None, None, None
                      elif self._report or (rule.filter_keys is not None or not self.has_filters):
                          rule.add_result(values)
                      return True, rule.full_match, None, output_data
  
          # No rule match: the application log message is not parsable with enabled rules.
          self._last_rule = None
          return False, None, None, None