Python 2.7 ошибочно агрегирует сообщения системного журнала с TCP, отлично работает с UDP - PullRequest
1 голос
/ 12 июня 2019

Используя Python 2.7.15rc1, который поставляется с Linux Mint 19.1, я собираю некоторые данные в rsyslog 8.32.0-1ubuntu4. Выполнение этого по TCP ошибочно объединяет несколько сообщений журнала в одну строку в / var / log / syslog, в то время как UDP правильно не выполняет эту агрегацию.

Я хочу использовать TCP вместо UDP для надежности, но мне нужен некатентированный вывод.

Если я изменю одну строку в моей программе с:

socktype = socket.SOCK_DGRAM

... чтобы:

socktype = socket.SOCK_STREAM

... тогда вещи начинают странно кататься. Одна строка - это единственное изменение кода, необходимое для воспроизведения проблемы из заведомо исправного кода.

Вот как я получаю обработчик регистрации:

handler = logging.handlers.SysLogHandler(address=address, socktype=socktype)

Сообщения журнала в хорошем случае (с UDP) выглядят так (для EG):

Jun 11 15:59:25 2019-06-11 15: 59:25,870|_|INFO|_|dstromberg-inspiron-5570|_|domain.classifier.factories.classifier_academy|_|classifier_academy.py|_|load|_|132|_|loading xgb_factory
Jun 11 15:59:25 2019-06-11 15: 59:25,871|_|INFO|_|dstromberg-inspiron-5570|_|domain.classifier.factories.classifier_academy|_|classifier_academy.py|_|load|_|132|_|loading lgb_factory
Jun 11 15:59:25 2019-06-11 15: 59:25,871|_|INFO|_|dstromberg-inspiron-5570|_|domain.classifier.factories.classifier_academy|_|classifier_academy.py|_|load|_|132|_|loading rf_factory
Jun 11 15:59:39 2019-06-11 15: 59:39,161|_|INFO|_|dstromberg-inspiron-5570|_|domain.classifier.factories.classifier_academy|_|classifier_academy.py|_|load|_|132|_|loading xgb_factory
Jun 11 15:59:39 2019-06-11 15: 59:39,161|_|INFO|_|dstromberg-inspiron-5570|_|domain.classifier.factories.classifier_academy|_|classifier_academy.py|_|load|_|132|_|loading lgb_factory
Jun 11 15:59:39 2019-06-11 15: 59:39,162|_|INFO|_|dstromberg-inspiron-5570|_|domain.classifier.factories.classifier_academy|_|classifier_academy.py|_|load|_|132|_|loading rf_factory

Сообщения журнала в плохом случае (с TCP) выглядят так (для EG):

Jun 11 11:55:04 2019-06-11 11: 53:43,139|_|INFO|_|dstromberg-inspiron-5570|_|domain.classifier.factories.classifier_academy|_|classifier_academy.py|_|load|_|132|_|loading xgb_factory#000<14>2019-06-11 11:53:43,140|_|INFO|_|dstromberg-inspiron-5570|_|domain.classifier.factories.classifier_academy|_|classifier_academy.py|_|load|_|132|_|loading lgb_factory#000<14>2019-06-11 11:53:43,141|_|INFO|_|dstromberg-inspiron-5570|_|domain.classifier.factories.classifier_academy|_|classifier_academy.py|_|load|_|132|_|loading rf_factory#000<14>2019-06-11 11:53:57,842|_|INFO|_|dstromberg-inspiron-5570|_|domain.classifier.factories.classifier_academy|_|classifier_academy.py|_|load|_|132|_|loading xgb_factory#000<14>2019-06-11 11:53:57,843|_|INFO|_|dstromberg-inspiron-5570|_|domain.classifier.factories.classifier_academy|_|classifier_academy.py|_|load|_|132|_|loading lgb_factory#000<14>2019-06-11 11:53:57,843|_|INFO|_|dstromberg-inspiron-5570|_|domain.classifier.factories.classifier_academy|_|classifier_academy.py|_|load|_|132|_|loading rf_factory

Отметка времени всегда содержит это паразитное пространство (ASCII 32 после часа в «2019-06-11 11: 53: 43,139») в случае TCP, и несколько сообщений были объединены в одно сообщение. Сообщения, кажется, объединены чем-то вроде: "# 000 <14>". Часть # 000 непротиворечива, но числовая часть 14 в данном случае изменяется от частоты к частоте. Это всегда небольшое число.

Это ошибка в SyslogHandler? Это известная проблема? Кто-нибудь знает исправление, кроме перехода на UDP?

Единственная даже немного необычная вещь, которую я делаю (кроме syslog через TCP), - это добавление фильтра для добавления имени хоста (docker). Это выглядит так:

class ContainerFilter(logging.Filter):
    """This is a filter that just adds the container name (hostname)."""

    def __init__(self, name='', container_id=None):
        """Initialize."""
        super(ContainerFilter, self).__init__(name)
        self.container_id = container_id

    def filter(self, record):
        """Set record's metric and container_id attributes, if available."""
        record.container = self.container_id
        return True

filter_ = ContainerFilter(container_id=_DOCKER_CONTAINER_ID)
handler.addFilter(filter_)

Я думаю, что это слишком много, чтобы быть Nagle.

Что касается TCP по сравнению с UDP - мне нравится надежность TCP, и мне нравится, что когда он не работает, вместо просто отбрасывания сообщений есть исключение.

Также: я знаю, что Python 2.x скоро не будет поддерживаться, но этот конкретный код будет еще на 2.x еще дольше.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...