自定义代码的检测

编辑

在事务中创建额外的跨度

编辑

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")