python - 数据狗跨度在 python 线程池中丢失
问题描述
我有一个在线程池中运行的函数,但是当我在线程池之外运行它时,它只显示在 Datadog 跟踪 UI 中。在下面的屏幕截图中,您可以看到它显示在sync_work
但不显示在async_work
.
这是我的代码,包含在一个名为的脚本中ddtrace_threadpool_example.py
:
from concurrent.futures import ThreadPoolExecutor
from ddtrace import tracer
from random import random
import time
def perform_work(input_value):
with tracer.trace('do_something') as _:
seconds = random()
time.sleep(seconds)
return input_value**2
def sync_work(input_values):
with tracer.trace('sync_work') as _:
results = []
for input_value in input_values:
result = perform_work(input_value=input_value)
results.append(result)
return results
def async_work(input_values):
with tracer.trace('async_work') as _:
thread_pool = ThreadPoolExecutor(max_workers=10)
futures = thread_pool.map(
lambda input_value:
perform_work(input_value=input_value),
input_values
)
results = list(futures)
return results
@tracer.wrap(service='ddtrace-example')
def start_work():
input_values = list(range(15))
sync_results = sync_work(input_values=input_values)
print(sync_results)
async_results = async_work(input_values=input_values)
print(async_results)
if __name__ == '__main__':
start_work()
我像这样运行脚本:python ddtrace_threadpool_example.py
. 我正在使用 Python 3.7,并pip freeze
显示ddtrace==0.29.0
.
解决方案
在与 Datadog 支持人员交谈后,这似乎是一个已知问题。
感谢您在我们调查此问题时的耐心等待。我们目前正在与 PoolExecutors 一起对此进行调查,并将提供更新。现在看起来异步调用中的那些子跨度丢失了上下文,因此它们似乎断开连接。
目前的解决方法是传入父级的上下文。在调用线程池执行程序之前添加这一行。
current_context = tracer.get_call_context()
然后将该上下文传递给在线程池中运行的函数:
perform_work(
input_value=input_value,
parent_context=current_context
)
并使用它在函数内部创建一个跨度,如下所示:
span = tracer.start_span('do_something', child_of=parent_context)
seconds = random()
time.sleep(seconds)
span.finish()
完整的示例如下所示:
from concurrent.futures import ThreadPoolExecutor
from ddtrace import tracer
from random import random
import time
def perform_work(input_value, parent_context=None):
span = tracer.start_span('do_something', child_of=parent_context)
seconds = random()
time.sleep(seconds)
span.finish()
return input_value ** 2
def sync_work(input_values):
with tracer.trace('sync_work') as _:
results = []
for input_value in input_values:
result = perform_work(input_value=input_value)
results.append(result)
return results
def async_work(input_values):
with tracer.trace('async_work') as _:
current_context = tracer.get_call_context()
thread_pool = ThreadPoolExecutor(max_workers=10)
futures = thread_pool.map(
lambda input_value:
perform_work(
input_value=input_value,
parent_context=current_context
),
input_values
)
results = list(futures)
return results
@tracer.wrap(service='ddtrace-example')
def start_work():
input_values = list(range(15))
sync_results = sync_work(input_values=input_values)
print(sync_results)
async_results = async_work(input_values=input_values)
print(async_results)
if __name__ == '__main__':
start_work()
这将产生如下所示的结果:
推荐阅读
- c# - ASP.NET C# 从数据库中检索多个值并添加到会话中
- google-chrome - 浏览器从缓存中加载 JS 文件,而不是 CSS 文件
- jquery - 在 Jquery 中选择多个复选框
- html - 如何使幻灯片图像在不同的视口尺寸下按比例缩放?
- ios - 将单元格添加到可见的空 UITableView 以白色背景显示
- java - 如何在java中使用正则表达式在特定位置的文本中查找数字
- python - 为什么 matplotlib.pyplot.imsave() 和 matplotlib.pyplot.imshow() 图像质量不同?如何保证同样的质量?
- user-interface - 如何使用构建器功能?- 颤动
- c# - 在 WinForms 应用程序中运行批处理文件问题
- node.js - 节点使用 child_process 启动 VLC Player