В один солнечный день вы интегрируете одну программу в другую. Вы просто следуете руководству. Он строится, запускается и развертывается в вашем кластере. А потом взрывается. Знакомо, не правда ли?

Сегодня я собираюсь рассказать вам историю о Opentracing Tracer и о том, как он может взорваться. Вот главные герои:

  • Python tracer предоставлен Instana (ОТКАЗ ОТ ОТВЕТСТВЕННОСТИ: очень хороший инструмент, кстати!)
  • Многопоточный воркер Python. Приложение на Python, которое запускает несколько процессов и контролирует их. Каждый процесс отвечает за обработку сообщений, поступающих из очереди. Сообщения включают SpanContext для кросс-процессной трассировки (да, мы хотим, чтобы все было видно).

Уже заметили виновника? Спойлер: «запускает несколько процессов». Разберем его пошагово:

1. Инициализация трассировщика. Он довольно стандартный и соответствует документации:

instana.tracer.init(instana_opts.Options(service=’myservice’))

Трассировщик создается в основном сценарии вместе с другими службами и конфигурациями. Предполагается, что это будет синглтон, общая служба, которая отправляет данные трассировки сборщику из всех потоков (и, надеюсь, из всех процессов).

2. Рабочие процессы запускаются с Popen.

3. Промежутки сообщаются обычным способом:

span = extract_tracing_span(carrier)
with span:
  # do useful stuff here
  # at the end ‘span.__exit__()’ is called automatically
  # which executes sending span data to the collector

Все выглядит нормально, но пролетам коллектора Instana не сообщают. Почему? Ответ прост: трассировщик успешно инициализирован для родительского процесса. Но этот контекст не копируется в дочерние процессы. Таким образом, childred инициализировал свои собственные трассировщики с настройками по умолчанию и в основном начал отправлять промежутки в черную дыру.

Как решить эту проблему? Легко: перенесите инициализацию трассировщика из родительского процесса в каждый подпроцесс.

Мораль истории

Когда дело доходит до многопроцессного приложения, будьте предельно осторожны с синглтонами, которые создаются в родительском процессе. А если вы не можете передать их от родительского процесса к дочерним - создайте эти синглтоны в дочерних процессах, сделайте их локальными.