【问题标题】:Python jaeger-client tracer not reporting on reusePython jaeger-client 跟踪器未报告重用
【发布时间】:2019-07-04 23:35:45
【问题描述】:

使用示例代码在 celery 4.1.1 中跟踪任务。每个工人运行:

import logging
from jaeger_client import Config
import opentracing 

def get_tracer(service="Vienna"):
    config = Config(
        config={

            'sampler': {
                'type': 'const',
                'param': 1,
            },
            'logging': True,
        },
        service_name=service,
    )
    return config.initialize_tracer() or opentracing.global_tracer()

当我第一次启动 celery 并运行任务时,每个工作人员都会得到一个工作跟踪器,并且每个工作人员都有一个日志输出:

[2019-07-04 19:17:00,527: INFO/ForkPoolWorker-2] Initializing Jaeger Tracer with UDP reporter
[2019-07-04 19:17:00,546: INFO/ForkPoolWorker-2] opentracing.tracer initialized to <jaeger_client.tracer.Tracer object at 0x7f804d079c10>[app_name=SocketIOTask]

在初始之后运行的任何任务都会获得全局跟踪器 来自Config.initialze_tracer(返回None)和日志警告Jaeger tracer already initialized, skipping

在控制台上观察 tcpdump 表明没有发送 UDP 数据包,我想我得到了一个未初始化的默认跟踪器,它正在使用 noop 报告器。

我仔细研究了 opentracing 和 jaeger_client 中的代码,但找不到解决此问题的规范方法。

【问题讨论】:

  • 嘿,马克,你是如何向 jaeger 代理/收集器报告跨度的?
  • 有什么运气吗?我的情况更糟 - 调试器显示全局跟踪器完全存在,只是没有任何东西到达收集器。

标签: python opentracing jaeger


【解决方案1】:
from jaeger_client import Config
def get_tracer(service="Vienna"):

    config = Config(
        config={
            'sampler': {
                'type': 'const',
                'param': 1,
            },
            'logging': True,
        },
        service_name=service,
     )

    tracer = config.initialize_tracer()
    if tracer is None:
        Config._initialized = False
        tracer = config.initialize_tracer()
    return tracer

【讨论】:

  • 您好,欢迎来到 stackoverflow,感谢您的回答。您能否简单地解释一下您解决了什么问题以及您是如何解决的,而不是仅仅发布一段代码?这将有助于以后发现此问题的人更好地了解该问题以及如何处理它。
【解决方案2】:

Celery 默认分叉多个进程 (--pool=prefork)。问题是 jaeger_client 在单独的线程中执行实际消息发送。该线程是在分叉之前创建的,在子进程中不可用。结果,子进程的日志记录不起作用。

最明显的解决方案是使用--pool=solo-pool=threads等。但是在CPU密集型任务的情况下,我们仍然需要使用--pool=prefork。在这种情况下,我们会遇到另一个问题。

一方面,jaeger_client 被设计为用作单例。它打开文件描述符但从不关闭它们(即使close() 比关闭更刷新)。另一方面,我们需要为每个 celery 进程创建一个单独的跟踪器。

为了解决这个问题,我使用了以下解决方法:

tracer = None
tracer_owner_pid = 0

def get_jaeger_tracer():
    global tracer_owner_pid
    global tracer

    pid = os.getpid()
    if tracer_owner_pid == pid:
        return tracer

    logging.getLogger('').handlers = []
    logging.basicConfig(format='%(message)s', level=logging.DEBUG)
    config = Config(
        config={
            'sampler': {
                'type': 'const',
                'param': 1,
            },
            'logging': True,
        },
        service_name='foo',
    )

    tracer = config.new_tracer()
    tracer_owner_pid = pid
    return tracer

【讨论】:

    猜你喜欢
    • 2022-08-05
    • 1970-01-01
    • 2021-12-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-11-13
    • 2023-03-31
    相关资源
    最近更新 更多