自定义代码的监控编辑

在事务中创建额外的跨度编辑

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+ 中可用。

有关 capture_span 的更多信息,请参阅 API 文档

创建新事务编辑

需要注意的是,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")