python - Python 2.7 错误地使用 TCP 聚合系统日志消息,与 UDP 一起工作正常
问题描述
使用 Linux Mint 19.1 附带的 Python 2.7.15rc1,我将一些数据系统记录到 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
在 TCP 情况下,时间戳总是有那个虚假的空间(ASCII 32,在“2019-06-11 11:53:43,139”中的小时后),并且多条消息被连接成一条消息。这些消息似乎与以下内容相结合:“#000<14>”。#000 部分是一致的,但数字部分(在这种情况下为 14)会随着发生率的变化而变化。不过,它总是一个很小的整数。
这是 SyslogHandler 中的错误吗?这是一个已知问题吗?除了切换到UDP之外,有谁知道修复?
我正在做的唯一甚至有点不寻常的事情(除了基于 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.xa 上出现一段时间。
解决方案
推荐阅读
- postgresql - 使用环境变量将两个容器与 Kubernetes 连接
- python - 如何用 Pandas 计算逗号分隔列的平均值?
- haskell - 在haskell中使用graphviz包读取点文件
- python - 使用 log_loss/roc_auc_score 或使用 score='neg_log_loss'/'roc_auc' 执行 cross_val_score 的不同结果(Scikit learn)
- jestjs - 如何让 Jest 忽略 package.json 文件?
- c++ - 新手 C++ 错误(函数调用中的参数太多)
- reactjs - 如何在 React 中使用 Emotion.js 使用 :not(.className) 和伪选择器
- javascript - 如何在 ReactJS 中集成普通(香草)JavaScript?
- javascript - 从函数中检索 javascript 变量
- r - 如何在R中的数据框中为列值添加括号?