【问题标题】:Fluentd tcp contact succeeds via netcat tool. But fails via basic Python 3.7. Why?Fluentd tcp 联系通过 netcat 工具成功。但是通过基本的 Python 3.7 失败了。为什么?
【发布时间】:2020-08-27 15:51:23
【问题描述】:

所以我开发了一个基于 docker 的 fluentd TCP 日志收集器

按照此处的示例 https://docs.fluentd.org/input/tcp ,通过说成功从我的主机 Win 10 WSL (Debian) 发送了一行

echo "my_service: 08:03:10 INFO [my_py_file:343]: My valuable log info." | netcat 127.0.0.1 5170

正如所希望的那样,这以一个不错的 JSON 形式出现在 fluentd 中。但我想从 python 3.7 开始!所以:

import socket


def netcat(hn: str, p: int, content: bytes):
    """https://www.instructables.com/id/Netcat-in-Python/"""
    sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    sock.connect((hn, p))
    sock.sendall(content)
    sock.close()


msg_raw = "my_service: 08:03:10 INFO [my_py_file:343]: My valuable log info."

netcat('127.0.0.1', 5170, bytes(msg_raw, 'utf-8'))

WSL 或否:此 python 脚本运行,没有例外。 fluentd也没有任何反应,我无法解释。 你们中的任何人都可以吗?

如果有任何后果:这是我的fluentd.conf 中的相关部分。

<source>
  @type tcp
  @label mainstream
  @id pawc_tcp
  tag paws.tcp
  port 5170
  bind 0.0.0.0
  # https://docs.fluentd.org/parser/regexp
  <parse>
    @type regexp
    expression /^(?<service_uuid>[a-zA-Z0-9_-]+): (?<logtime>[^\s]+) (?<loglvl>[^\s]+) \[(?<file>[^\]:]+):(?<line>\d+)\]: (?<msg>.*)$/
    time_key logtime
    time_format %H:%M:%S
    types line:integer
  </parse>
</source>

<label mainstream>
  <match paws.tcp>
    @type file
    @id output_tcp
    path /fluentd/log/tcp.*.log
    symlink_path /fluentd/log/tcp.log
  </match>
</label>

【问题讨论】:

  • 您是否尝试在邮件末尾发送\r\n\0?它是字节,所以它可能被保存在缓冲区中,他们需要一种方法来知道消息已经结束并且正则表达式匹配行终止符
  • 亚历克斯,谢谢您的回复!对行结尾的 TCP 太缺乏经验了。无论如何:尾随的“\n”确实是消息!你为什么不制定一个适当的答案帖子,以便我可以适当地赞扬你的努力?
  • 太棒了!很高兴我能帮忙,是的,我会添加一个答案
  • 只是为了好奇,如果你sock.shutdown(socket.SHUT_WR)在关闭它之前,基本上是向对端发送一个FIN / EOF,它会达到与@AlexW解决方案相同的结果吗?
  • Neo,不,它没有。起初尝试.shutdown(..WR),正如我在python源代码中引用的页面上所建议的那样。阅读该 shutdown 方法的文档后,我得出结论认为这是不必要的:Plain .close() 就足够了。但是,\n 很重要! netcat 在我的示例中也没有关闭(命令阻止控制台)。然而线路到了。

标签: python-3.x docker fluentd


【解决方案1】:

尝试在邮件末尾发送\r\n\0。消息通过网络作为字节发送,因此它可能存储在缓冲区中,读取缓冲区的代码需要一种方法来知道消息已经结束。正则表达式也匹配行终止符,所以我认为那里也是必要的。

【讨论】:

    【解决方案2】:

    正如上面的 Alex W 所述,我使用的流利的正则表达式接受的 TCP 线路需要 \n。我想添加第二个答案来改进原始问题的python代码。

    实际上有一个易于实现的logging.handler.SocketHandler 类!但是,它会挑选它的输出,查看 python 日志服务器。使用 fluentd 这意味着必须重写 emit 函数才能使用它。之后一切正常。

    import logging, logging.handlers
    
    
    class SocketHandlerBytes(logging.handlers.SocketHandler):
        def emit(self, record):
            try:
                msg = bytes(self.format(record) + "\n", 'utf-8')
                self.send(msg)
            except Exception:
                self.handleError(record)
    
    
    sh = SocketHandlerBytes(host, port)
    sh.setFormatter(logger_format_appropriate_for_your_fluentd_tcp_regex)
    logging.root.addHandler(sh)
    

    【讨论】:

      猜你喜欢
      • 2012-02-10
      • 1970-01-01
      • 1970-01-01
      • 2018-07-07
      • 1970-01-01
      • 2011-04-18
      • 2013-04-13
      • 1970-01-01
      • 2019-06-03
      相关资源
      最近更新 更多