Python 跟踪 SDK
使用 Instana 进行跟踪是自动的,但如果您想进一步了解自定义代码、特定应用程序区域或内部组件,则可以使用 Instana Python Tracing SDK。
Instana Python Tracing SDK 3.0.0 及更高版本支持 OpenTelemetry API。 如果要使用支持已废弃的 OpenTracing API 的 Instana Python Tracing SDK,请参阅 Python OpenTracing (已废弃)。
Instana Python 追踪 SDK
Instana Python 模块提供基于 OpenTelemetry API 的应用程序接口,用于跟踪应用程序的任意部分。
您可以按以下方式使用 API 设置一段代码以进行跟踪:
from instana.singletons import tracer
try:
span = tracer.start_span("span_name")
# The code to be instrumented
id = user.find_by_name("john.smith")
span.set_attribute("user_id", id)
except Exception as e:
span.record_exception(e)
finally:
if span and span.is_recording():
span.end()
另外,也可以使用 with-as 语句来使用上下文管理器,它可以自动捕获并记录任何异常,如下所示:
from instana.singletons import tracer
with tracer.start_as_current_span("span_name") as span:
# The code to be instrumented.
id = user.find_by_name("john.smith")
span.set_attribute("user_id", id)
异步跟踪
您要跟踪的某些操作可能是异步的,这意味着它们会立即返回,但会继续与主指令序列分开运行。 要跟踪这些操作,例如使用 asyncio 库,可以使用以下跟踪方法:
import asyncio
from instana.singletons import tracer
async def do_work(parent_span):
parent_context = parent_span.get_span_context() if parent_span else None
with tracer.start_as_current_span(
"launch_async_work",
span_context=parent_context
):
print("Work stared")
await asyncio.sleep(1)
print("Work finished!")
with tracer.start_as_current_span("launch_uvloop") as sync_span:
asyncio.run(do_work(sync_span))
跟踪分叉进程中的跨度
如果要跟踪分叉进程中的跨度,则在 span.end() 后添加 time.sleep() 。 请参阅以下示例:
from instana.singletons import tracer
def forked_process(num):
print(f"in forked process {num}")
try:
span = tracer.start_span(f"forked process {num}")
print(f"sleep 10 for forked process {num}")
time.sleep(10)
except Exception as e:
span.record_exception(e)
finally:
if span and span.is_recording():
span.end()
logger.warning(f"sleep 2 for forked process {num}")
time.sleep(2) ## < -- with a sleep after span.finish(), the span can be collected
将上下文带入新线程
跟踪是线程的本地功能。 如果您创建了一个新线程,则上下文必须被传输到该新线程,然后再被拾取。 您可以按如下方式使用代码,将上下文带入新线程:
from instana.singletons import tracer
from threading import Thread
def child_thread_function(parent_span):
parent_context = parent_span.get_span_context() if parent_span else None
with tracer.start_as_current_span(
"child_thread_span",
span_context=parent_context
) as child_span:
print("Thread offloaded work goes here")
with tracer.start_as_current_span("parent_thread_span") as parent_span:
thread = Thread(
target = child_thread_function,
args = (parent_span,)
)
thread.start()
thread.join()
跟踪计划稍后运行的作业
您可以按以下方式对排队等待稍后运行的作业进行设置:
# Python 3.8
import asyncio
import datetime
import uvloop
import aiohttp
from instana.singletons import tracer
from opentelemetry.trace import SpanKind
uvloop.install()
async def launch_async_calls(parent_span):
parent_context = parent_span.get_span_context() if parent_span else None
with tracer.start_as_current_span(
"launch_async_calls",
span_context=parent_context
):
async with aiohttp.ClientSession() as session:
async with session.get("https://wikipedia.org") as resp:
print(resp.status)
print(await resp.text())
async def run_at(dt, coro):
await asyncio.sleep((dt - datetime.datetime.now()).total_seconds())
return await coro
with tracer.start_as_current_span("launch_uvloop") as sync_span:
sync_span.set_attribute("span.kind", SpanKind.SERVER)
asyncio.run(
run_at(
datetime.datetime.now() + datetime.timedelta(seconds=5),
launch_async_calls(sync_scope.span)
)
)