Python jaeger-client tracer не сообщает о повторном использовании

Задачи трассировки в сельдерее 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()

Когда я впервые запускаю сельдерей и выполняю задачи, каждый рабочий получает рабочий трассировщик, и для каждого из них есть вывод журнала:

[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, и я не могу найти канонический способ обойти это.


person Mark Dineen    schedule 04.07.2019    source источник
comment
Привет, Марк, как ты сообщаешь об объемах работ агенту / коллекционеру егеря?   -  person Mohit Chawla    schedule 12.09.2019
comment
Повезло с этим? Мой случай еще хуже - отладчик показывает, что глобальный трассировщик полностью присутствует, просто до сборщика ничего не доходит.   -  person Lauri Elias    schedule 23.03.2020


Ответы (2)


По умолчанию Celery разделяет несколько процессов (--pool=prefork). Проблема в том, что jaeger_client выполняет эту фактическую отправку сообщения в отдельном потоке. Этот поток создается перед разветвлением и недоступен в подпроцессах. В результате регистрация из подпроцессов не работает.

Наиболее очевидное решение - использовать --pool=solo, -pool=threads и т. Д. Но в случае задач, связанных с процессором, нам все равно нужно использовать --pool=prefork. В этом случае возникает другая проблема.

С одной стороны, jaeger_client предназначен для использования как синглтон. Он открывает файловые дескрипторы, но никогда не закрывает их (даже close() скорее заподлицо, чем близко). С другой стороны, нам нужно создать отдельный индикатор для каждого процесса сельдерея.

Чтобы решить эту проблему, я использовал следующий обходной путь:

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
person Vadym Hulakov    schedule 30.04.2021

person    schedule
comment
Привет и добро пожаловать в stackoverflow, и спасибо за ваш ответ. Вместо того, чтобы просто опубликовать блок кода, можете ли вы дать краткое объяснение того, какую проблему вы решили и как вы ее решили? Это поможет людям, которые столкнутся с этим вопросом в будущем, лучше понять проблему и способы ее решения. - person Plutian; 17.12.2019