自定义代码的检测
编辑自定义代码的检测
编辑在事务中创建额外的跨度
编辑Elastic APM 开箱即用地检测各种库,但有时您需要知道特定函数执行了多长时间或调用频率。
假设您正在使用我们 支持的框架 之一,您可以应用 @elasticapm.capture_span()
装饰器来实现这一点。如果您没有使用支持的框架,请参阅 创建新事务。
elasticapm.capture_span
可以用作装饰器或上下文管理器。以下示例同时使用这两种方式
import elasticapm @elasticapm.capture_span() def coffee_maker(strength): fetch_water() with elasticapm.capture_span('near-to-machine'): insert_filter() for i in range(strength): pour_coffee() start_drip() fresh_pots()
类似地,您可以使用 elasticapm.async_capture_span
来检测 async
工作负载
import elasticapm @elasticapm.async_capture_span() async def coffee_maker(strength): await fetch_water() async with elasticapm.async_capture_span('near-to-machine'): await insert_filter() async for i in range(strength): await pour_coffee() start_drip() fresh_pots()
asyncio
支持仅在 Python 3.7 及更高版本中可用。
请参阅 API 文档,以获取有关 capture_span
的更多信息。
创建新事务
编辑需要注意的是,elasticapm.capture_span
仅在存在现有事务时才有效。如果您没有使用我们 支持的框架 之一,则需要创建一个 Client
对象并自行开始和结束事务。您甚至可以利用代理的 自动检测!
要收集支持的库生成的跨度,您需要调用 elasticapm.instrument()
(仅在应用程序的初始化阶段调用一次)并至少创建一个事务。由您来确定在您的应用程序中您认为什么是事务——它可以是脚本的整个执行或其中的一部分。
下面的示例将把整个执行视为一个包含两个 HTTP 请求跨度的事务。可以以编程方式传递 elasticapm.Client
的配置,它也会自动利用任何可用的配置环境变量。
import requests import time import elasticapm def main(): sess = requests.Session() for url in [ 'https://elastic.ac.cn', 'https://benchmarks.elastic.co' ]: resp = sess.get(url) time.sleep(1) if __name__ == '__main__': client = elasticapm.Client(service_name="foo", server_url="https://example.com:8200") elasticapm.instrument() # Only call this once, as early as possible. client.begin_transaction(transaction_type="script") main() client.end_transaction(name=__name__, result="success")
请注意,您无需执行任何操作来发送数据——Client
对象将在脚本退出之前处理该操作。此外,Client
对象应被视为单例——您应该只创建一个实例,并存储/传递该实例以进行所有事务处理。
分布式追踪
编辑在跨多个服务检测自定义代码时,您应在可能的情况下传播 TraceParent。这允许 Elastic APM 将各种事务捆绑到单个分布式跟踪中。Python Agent 会自动将 TraceParent 信息添加到传出 HTTP 请求的标头中,然后可以在接收端使用这些信息将该 TraceParent 信息添加到新手动创建的事务中。
此外,Python Agent 提供了用于以字符串格式传播 TraceParent 的实用程序。
import elasticapm client = elasticapm.Client(service_name="foo", server_url="https://example.com:8200") # Retrieve the current TraceParent as a string, requires active transaction traceparent_string = elasticapm.get_trace_parent_header() # Create a TraceParent object from a string and use it for a new transaction parent = elasticapm.trace_parent_from_string(traceparent_string) client.begin_transaction(transaction_type="script", trace_parent=parent) # Do some work client.end_transaction(name=__name__, result="success") # Create a TraceParent object from a dictionary of headers, provided # automatically by the sending service if it is using an Elastic APM Agent. parent = elasticapm.trace_parent_from_headers(headers_dict) client.begin_transaction(transaction_type="script", trace_parent=parent) # Do some work client.end_transaction(name=__name__, result="success")