公共 API编辑

Elastic APM Java 代理的公共 API 允许您自定义和手动创建跨度和事务,以及跟踪错误。

开始使用 API 的第一步是声明对 API 的依赖关系

pom.xml。

<dependency>
    <groupId>co.elastic.apm</groupId>
    <artifactId>apm-agent-api</artifactId>
    <version>${elastic-apm.version}</version>
</dependency>

build.gradle。

compile "co.elastic.apm:apm-agent-api:$elasticApmVersion"

将版本占位符替换为 来自 Maven 中央仓库的最新版本: Maven 中央仓库

Tracer API编辑

Tracer 使您可以访问当前活动的交易和跨度。它还可以用于跟踪异常。

要使用 API,您只需调用类 co.elastic.apm.api.ElasticApm 上的静态方法。

Transaction currentTransaction()编辑

返回当前活动的交易。有关如何自定义当前交易的信息,请参阅 Transaction API

如果没有当前交易,此方法将返回一个空操作交易,这意味着您永远不必检查 null 值。

import co.elastic.apm.api.ElasticApm;
import co.elastic.apm.api.Transaction;

Transaction transaction = ElasticApm.currentTransaction();

通过 ElasticApm.startTransaction() 创建的交易无法通过调用此方法检索。有关如何实现此目的的信息,请参阅 span.activate()

Span currentSpan()编辑

返回当前活动的跨度或交易。有关如何自定义当前跨度的信息,请参阅 Span API

如果没有当前跨度,此方法将返回一个空操作跨度,这意味着您永远不必检查 null 值。

请注意,即使此方法返回一个空操作跨度,您仍然可以在其上 捕获异常。这些异常将没有与跨度或交易的链接。

import co.elastic.apm.api.ElasticApm;
import co.elastic.apm.api.Span;

Span span = ElasticApm.currentSpan();

通过 startSpan()startSpan(String, String, String) 创建的跨度无法通过调用此方法检索。有关如何实现此目的的信息,请参阅 span.activate()

Transaction startTransaction()编辑

使用此方法创建自定义交易。

请注意,只要您的应用程序收到传入的 HTTP 请求,代理就会自动为您执行此操作。您只需要使用此方法来创建自定义交易。

在交易结束时调用 void end() 很重要。最佳实践是在 try-catch-finally 块中使用交易。示例

Transaction transaction = ElasticApm.startTransaction();
try {
    transaction.setName("MyController#myAction");
    transaction.setType(Transaction.TYPE_REQUEST);
    // do your thing...
} catch (Exception e) {
    transaction.captureException(e);
    throw e;
} finally {
    transaction.end();
}

通过此方法创建的交易无法通过调用 ElasticApm.currentSpan()ElasticApm.currentTransaction() 检索。有关如何实现此目的的信息,请参阅 transaction.activate()

Transaction startTransactionWithRemoteParent(HeaderExtractor) [1.3.0] 在 1.3.0 中添加。 编辑

类似于 Transaction startTransaction(),但将此交易创建为远程父级的子级。

  • headerExtractor: 一个函数式接口,它接收一个头名称并返回具有该名称的第一个头

示例

// Hook into a callback provided by the framework that is called on incoming requests
public Response onIncomingRequest(Request request) throws Exception {
    // creates a transaction representing the server-side handling of the request
    Transaction transaction = ElasticApm.startTransactionWithRemoteParent(key -> request.getHeader(key));
    try (final Scope scope = transaction.activate()) {
        String name = "a useful name like ClassName#methodName where the request is handled";
        transaction.setName(name);
        transaction.setType(Transaction.TYPE_REQUEST);
        return request.handle();
    } catch (Exception e) {
        transaction.captureException(e);
        throw e;
    } finally {
        transaction.end();
    }
}

Transaction startTransactionWithRemoteParent(HeaderExtractor, HeadersExtractor) [1.3.0] 在 1.3.0 中添加。 编辑

类似于 Transaction startTransaction(),但将此交易创建为远程父级的子级。

  • headerExtractor: 一个函数式接口,它接收一个头名称并返回具有该名称的第一个头
  • headersExtractor: 一个函数式接口,它接收一个头名称并返回具有该名称的所有头

示例

// Hook into a callback provided by the framework that is called on incoming requests
public Response onIncomingRequest(Request request) throws Exception {
    // creates a transaction representing the server-side handling of the request
    Transaction transaction = ElasticApm.startTransactionWithRemoteParent(request::getHeader, request::getHeaders);
    try (final Scope scope = transaction.activate()) {
        String name = "a useful name like ClassName#methodName where the request is handled";
        transaction.setName(name);
        transaction.setType(Transaction.TYPE_REQUEST);
        return request.handle();
    } catch (Exception e) {
        transaction.captureException(e);
        throw e;
    } finally {
        transaction.end();
    }
}

void setServiceInfoForClassLoader(ClassLoader, String, String) [1.30.0] 在 1.30.0 中添加。 编辑

将类加载器与服务名称和版本关联。

该关联用于在启动交易时覆盖自动检测到的服务名称和版本。

如果类加载器已经与服务名称和版本关联,则不会覆盖现有信息。

  • classLoader: 应与给定服务名称和版本关联的类加载器
  • serviceName: 服务名称
  • serviceVersion: 服务版本

Annotation API编辑

API 附带两个注释,使创建自定义跨度和事务变得更容易。只需将注释放在方法顶部,代理将负责创建和报告相应的交易和跨度。它还将确保捕获任何未捕获的异常。

需要配置 application_packages,否则这些注释将被忽略。

@CaptureTransaction编辑

@CaptureTransaction 注释方法会为该方法创建一个交易。

请注意,这仅在同一线程上没有活动交易时有效。

  • value: 交易的名称。默认为 ClassName#methodName
  • type: 交易的类型。默认为 request

使用此注释会隐式创建一个交易并在进入注释的方法时激活它。它还会在退出注释的方法之前隐式结束它并停用它。请参阅 ElasticApm.startTransaction()transaction.activate()transaction.end()

@CaptureSpan编辑

@CaptureSpan 注释方法会创建一个跨度,作为当前活动跨度或交易 (Span currentSpan()) 的子级。

当没有当前跨度或交易时,不会创建跨度。

  • value: 跨度的名称。默认为 ClassName#methodName
  • type: 跨度的类型,例如 db 用于 DB 跨度。默认为 app
  • subtype: 跨度的子类型,例如 mysql 用于 DB 跨度。默认为空字符串
  • action: 与跨度相关的操作,例如 query 用于 DB 跨度。默认为空字符串
  • discardable: 默认情况下,跨度可能在某些情况下被丢弃。将此属性设置为 false 以使此跨度不可丢弃。
  • exit: 默认情况下,跨度是内部跨度,将其设为退出跨度会阻止创建嵌套跨度,并且旨在表示对外部系统的调用,例如数据库或第三方服务。

使用此注释会隐式创建一个跨度并在进入注释的方法时激活它。它还会在退出注释的方法之前隐式结束它并停用它。请参阅 startSpan()startSpan(String, String, String)span.activate()span.end()

@Traced [1.11.0] 在 1.11.0 中添加。 编辑

@Traced 注释方法会创建一个跨度,作为当前活动跨度或交易的子级。

如果没有当前跨度,则会创建一个事务。

如果一个方法既可以是入口点(事务),也可以是事务内的工作单元(跨度),则在 @CaptureSpan@CaptureTransaction 上使用此注释。

  • value: 跨度或事务的名称。默认为 ClassName#methodName
  • type: 跨度或事务的类型。事务默认为 request,跨度默认为 app
  • subtype: 跨度的子类型,例如 mysql 用于 DB 跨度。默认为空字符串。创建事务时无效。
  • action: 与跨度相关的操作,例如 query 用于 DB 跨度。默认为空字符串。创建事务时无效。
  • discardable: 默认情况下,跨度可能会在某些情况下被丢弃。将此属性设置为 false 以使此跨度不可丢弃。如果创建的事件是事务,则此属性无效。

使用此注释会隐式创建跨度或事务,并在进入带注释的方法时激活它。它还会在退出带注释的方法之前隐式结束它并停用它。见 startSpan()startSpan(String, String, String)span.activate()span.end()

事务 APIedit

事务是代理捕获的数据,表示在受监控服务中发生的事件,并将多个跨度分组到一个逻辑组中。事务是服务中的第一个 Span,也称为入口跨度。

Transaction currentTransaction() 如何获取当前事务的引用。

TransactionSpan 的子类型。因此,它具有 Span 提供的所有方法以及其他方法。

在调用 void end() 之后调用任何事务方法都是非法的。只有在您控制其生命周期时才能与事务交互。例如,如果跨度在另一个线程中结束,则您不得添加标签,因为 void end()Transaction setLabel(String key, value) [1.5.0 as addLabel] Added in 1.5.0 as addLabel. Number and boolean labels require APM Server 6.7 方法之间存在竞争的可能性。

Transaction setName(String name)edit

覆盖当前事务的名称。对于支持的框架,事务名称是自动确定的,可以使用此方法覆盖。

示例

transaction.setName("My Transaction");
  • name: (必需) 描述事务名称的字符串

Transaction setType(String type)edit

设置事务的类型。有一种特殊的类型称为 request,代理在检测到传入的 HTTP 请求时会自动为事务使用它。

示例

transaction.setType(Transaction.TYPE_REQUEST);
  • type: 事务的类型

Transaction setFrameworkName(String frameworkName) [1.25.0] Added in 1.25.0. edit

提供一种手动设置 service.framework.name 字段的方法。对于支持的框架,框架名称是自动确定的,可以使用此函数覆盖。 null 或空字符串将使代理省略此字段。

示例

transaction.setFrameworkName("My Framework");
  • frameworkName: 框架的名称

Transaction setServiceInfo(String serviceName, String serviceVersion) [1.30.0] Added in 1.30.0. edit

为该事务及其子跨度设置服务名称和版本。

如果在创建子跨度后调用此方法,它们可能具有错误的服务名称和版本。

  • serviceName: 服务名称
  • serviceVersion: 服务版本

Transaction useServiceInfoForClassLoader(ClassLoader classLoader) [1.30.0] Added in 1.30.0. edit

设置与给定类加载器关联的服务名称和版本(见:ElasticApm#setServiceInfoForClassLoader(ClassLoader, String, String)),用于该事务及其子跨度。

如果在创建子跨度后调用此方法,它们可能具有错误的服务名称和版本。

  • classLoader: 应该用于设置服务名称和版本的类加载器

Transaction setLabel(String key, value) [1.5.0 as addLabel] Added in 1.5.0 as addLabel. Number and boolean labels require APM Server 6.7 edit

标签用于向事务、跨度和错误添加 索引 信息。索引意味着数据在 Elasticsearch 中是可搜索和可聚合的。可以使用不同的键值对定义多个标签。

  • 索引:是
  • Elasticsearch 类型:object
  • Elasticsearch 字段:labels(以前在 <v.7.0 中为 context.tags

标签值可以是字符串、布尔值或数字。因为给定键的标签存储在 Elasticsearch 中的同一个位置,所以给定键的所有标签值必须具有相同的数据类型。每个键的多个数据类型将抛出异常,例如 {foo: bar}{foo: 42}

数字和布尔标签仅在 APM Server 6.7+ 中引入。将此 API 与旧的 APM Server 版本结合使用会导致验证错误。

避免定义太多用户指定的标签。在索引中定义太多唯一字段是一种会导致 映射爆炸 的情况。

transaction.setLabel("foo", "bar");
  • String key: 标签键
  • String|Number|boolean value: 标签值

Transaction addCustomContext(String key, value) [1.7.0] Added in 1.7.0. edit

自定义上下文用于向事务添加非索引的自定义上下文信息。非索引意味着数据在 Elasticsearch 中不可搜索或不可聚合,您无法在数据之上构建仪表板。但是,非索引信息对于其他原因很有用,例如提供上下文信息以帮助您快速调试性能问题或错误。

值可以是 StringNumberboolean

transaction.addCustomContext("foo", "bar");
  • String key: 标签键
  • String|Number|boolean value: 标签值

Transaction setUser(String id, String email, String username)edit

调用此方法以使用有关用户/客户端的信息来丰富收集的性能数据和错误。此方法可以在请求/响应生命周期中的任何时间点调用(即在事务处于活动状态时)。给定的上下文将被添加到活动事务中。

如果捕获到错误,则来自活动事务的上下文将用作捕获错误的上下文。

transaction.setUser(user.getId(), user.getEmail(), user.getUsername());
  • id: 用户的 ID 或 null(如果适用)。
  • email: 用户的电子邮件地址或 null(如果适用)。
  • username: 用户的姓名或 null(如果适用)。

Transaction setUser(String id, String email, String username, String domain) [1.23.0] Added in 1.23.0. edit

调用此方法以使用有关用户/客户端的信息来丰富收集的性能数据和错误。此方法可以在请求/响应生命周期中的任何时间点调用(即在事务处于活动状态时)。给定的上下文将被添加到活动事务中。

如果捕获到错误,则来自活动事务的上下文将用作捕获错误的上下文。

transaction.setUser(user.getId(), user.getEmail(), user.getUsername(), user.getDomain());
  • id: 用户的 ID 或 null(如果适用)。
  • email: 用户的电子邮件地址或 null(如果适用)。
  • username: 用户的姓名或 null(如果适用)。
  • domain: 用户的域或 null(如果适用)。

String captureException(Exception e)edit

捕获异常并将其报告给 APM 服务器。从 1.14.0 版开始 - 返回已报告错误的 ID。

String getId()edit

返回此事务的 ID(从不为 null

如果此事务表示一个空操作,则此方法返回一个空字符串。

String getTraceId()edit

返回此事务的跟踪 ID。

跟踪 ID 在属于同一逻辑跟踪的所有事务和跨度中保持一致,即使对于发生在另一个服务中的事务和跨度也是如此(假设该服务也由 Elastic APM 监控)。

如果此跨度表示一个空操作,则此方法返回一个空字符串。

String ensureParentId()edit

如果事务还没有父 ID,则调用此方法会生成一个新的 ID,将其设置为此事务的父 ID,并将其作为 String 返回。

这使得能够将 JavaScript 实时用户监控 (RUM) 代理为初始页面加载创建的跨度与后端服务的交易相关联。如果您的后端服务动态生成 HTML 页面,则使用此方法的值初始化 JavaScript RUM 代理允许分析在浏览器中花费的时间与在后端服务中花费的时间。

当使用像 Freemarker 这样的 HTML 模板语言时,要启用 JavaScript RUM 代理,请将 ElasticApm.currentTransaction() 与键 "transaction" 添加到模型中。

此外,将类似于此的代码片段添加到 HTML 页面主体中,最好放在其他 JS 库之前。

<script src="elastic-apm-js-base/dist/bundles/elastic-apm-js-base.umd.min.js"></script>
<script>
  elasticApm.init({
    serviceName: "service-name",
    serverUrl: "http://127.0.0.1:8200",
    pageLoadTraceId: "${transaction.traceId}",
    pageLoadSpanId: "${transaction.ensureParentId()}",
    pageLoadSampled: ${transaction.sampled}
  })
</script>

有关更多信息,请参阅 JavaScript RUM 代理文档

Span startSpan(String type, String subtype, String action)edit

启动并返回一个新的跨度,该跨度具有类型、子类型和操作,作为此事务的子级。

类型、子类型和操作字符串用于将具有不同分辨率的类似跨度分组在一起。例如,所有 DB 跨度都指定类型 db;所有 MySQL 查询的跨度都指定子类型 mysql,所有描述查询的跨度都指定操作 query。在此示例中,db 被视为通用类型。虽然通用类型没有命名限制,但以下类型在所有 Elastic APM 代理中都是标准化的:appdbcachetemplateext

.(点)字符在类型、子类型和操作中不允许使用。任何此类字符都将被替换为 _(下划线)字符。

当跨度结束时,调用 void end() 很重要。最佳实践是在 try-catch-finally 块中使用跨度。示例

Span span = parent.startSpan("db", "mysql", "query");
try {
    span.setName("SELECT FROM customer");
    // do your thing...
} catch (Exception e) {
    span.captureException(e);
    throw e;
} finally {
    span.end();
}

通过此方法创建的跨度无法通过调用 ElasticApm.currentSpan() 来检索。有关如何实现此目的,请参阅 span.activate()

Span startExitSpan(String type, String subtype, String action)edit

启动并返回一个新的退出跨度,该跨度具有类型、子类型和操作,作为此事务的子级。

类似于 startSpan(String, String, String),但创建的跨度将用于在服务地图中创建节点,并在依赖关系表中创建下游服务。提供的子类型将用作下游服务名称,除非通过 setServiceTarget(String type, String name) 显式设置 service.target.typeservice.target.name 字段。

Span startSpan()edit

启动并返回一个新的自定义跨度,该跨度没有类型,作为此事务的子级。

当跨度结束时,调用 void end() 很重要。最佳实践是在 try-catch-finally 块中使用跨度。示例

Span span = parent.startSpan();
try {
    span.setName("SELECT FROM customer");
    // do your thing...
} catch (Exception e) {
    span.captureException(e);
    throw e;
} finally {
    span.end();
}

通过此方法创建的跨度无法通过调用 ElasticApm.currentSpan() 来检索。有关如何实现此目的,请参阅 span.activate()

Transaction setResult(String result)edit

描述事务结果的字符串。这通常是 HTTP 状态代码,或者例如对于后台任务,是“success”。

  • result:描述事务结果的字符串

通过 API 设置的结果值将优先于自动检测可能设置的值。

Span setOutcome(Outcome outcome) [1.21.0] Added in 1.21.0. edit

设置事务或跨度结果。使用 FAILURESUCCESS 来指示成功或失败,当结果无法正确识别时,使用 UNKNOWN

  • outcome:事务或跨度结果

结果用于计算服务之间的错误率,使用 UNKNOWN 不会改变这些比率。通过 API 设置的值将优先于自动检测可能设置的值。

Transaction setStartTimestamp(long epochMicros) [1.5.0] Added in 1.5.0. edit

设置此事件的开始时间戳。

  • epochMicros:此事件开始时的时间戳,以自纪元以来的微秒 (µs) 为单位

void end()edit

结束事务并安排将其报告给 APM 服务器。在已结束的事务实例上调用任何方法都是非法的。这也包括此方法和 Span startSpan()。示例

transaction.end();

void end(long epochMicros) [1.5.0] Added in 1.5.0. edit

结束事务并安排将其报告给 APM 服务器。在已结束的事务实例上调用任何方法都是非法的。这也包括此方法和 Span startSpan()

  • epochMicros:此事件结束时的时间戳,以自纪元以来的微秒 (µs) 为单位

示例

transaction.end(System.currentTimeMillis() * 1000);

Scope activate()edit

使此跨度成为当前线程上的活动跨度,直到调用 Scope#close()。范围应仅在 try-with-resource 语句中使用,以确保在所有情况下都调用 Scope#close() 方法。未能关闭范围会导致内存泄漏并破坏父子关系。

此方法应始终在 try-with-resources 语句中使用

Transaction transaction = ElasticApm.startTransaction();
// Within the try block the transaction is available
// on the current thread via ElasticApm.currentTransaction().
// This is also true for methods called within the try block.
try (final Scope scope = transaction.activate()) {
    transaction.setName("MyController#myAction");
    transaction.setType(Transaction.TYPE_REQUEST);
    // do your thing...
} catch (Exception e) {
    transaction.captureException(e);
    throw e;
} finally {
    transaction.end();
}

Scope activate()Scope#close() 必须在同一线程上调用。

boolean isSampled()edit

如果此事务被记录并发送到 APM 服务器,则返回 true

void injectTraceHeaders(HeaderInjector headerInjector) [1.3.0] Added in 1.3.0. edit

  • headerInjector:告诉代理如何将标头注入请求对象

允许手动传播跟踪标头。

如果你想手动检测尚未由代理的自动检测功能支持的 RPC 框架,可以使用此方法将所需的跟踪标头注入该框架的请求对象的标头部分。

示例

// Hook into a callback provided by the RPC framework that is called on outgoing requests
public Response onOutgoingRequest(Request request) throws Exception {
    // creates a span representing the external call
    Span span = ElasticApm.currentSpan()
            .startSpan("external", "http", null)
            .setName(request.getMethod() + " " + request.getHost());
    try (final Scope scope = transaction.activate()) {
        span.injectTraceHeaders((name, value) -> request.addHeader(name, value));
        return request.execute();
    } catch (Exception e) {
        span.captureException(e);
        throw e;
    } finally {
        span.end();
    }
}

Span APIedit

跨度包含有关作为事务的一部分执行的特定代码路径的信息。

例如,如果在记录的事务中发生数据库查询,则可能会创建一个表示此数据库查询的跨度。在这种情况下,跨度的名称将包含有关查询本身的信息,而类型将包含有关数据库类型的信息。

有关如何获取当前跨度的引用,请参阅 Span currentSpan()

Span setName(String name)edit

覆盖当前跨度的名称。

示例

span.setName("SELECT FROM customer");
  • name:跨度的名称

Span setLabel(String key, value) [1.5.0 as addLabel] Added in 1.5.0 as addLabel. edit

用户定义标签的扁平映射,具有字符串、数字或布尔值。

在 6.x 版本中,标签存储在 Elasticsearch 中的 context.tags 下。从 7.x 版本开始,它们存储为 labels,以符合 Elastic Common Schema (ECS)

标签在 Elasticsearch 中被索引,以便它们可搜索和聚合。无论如何,你应该避免使用用户指定的数据(如 URL 参数)作为标签键,因为这会导致映射爆炸。

span.setLabel("foo", "bar");
  • String key: 标签键
  • String|Number|boolean value: 标签值

String captureException(Exception e)edit

捕获异常并将其报告给 APM 服务器。从 1.14.0 版开始 - 返回已报告错误的 ID。

String getId()edit

返回此跨度的 ID(从不为 null

如果此跨度表示一个空操作,则此方法返回一个空字符串。

String getTraceId()edit

返回此跨度的跟踪 ID。

跟踪 ID 在属于同一逻辑跟踪的所有事务和跨度中保持一致,即使对于发生在另一个服务中的事务和跨度也是如此(假设此服务也由 Elastic APM 监控)。

如果此跨度表示一个空操作,则此方法返回一个空字符串。

Span setStartTimestamp(long epochMicros) [1.5.0] Added in 1.5.0. edit

设置此事件的开始时间戳。

  • epochMicros:此事件开始时的时间戳,以自纪元以来的微秒 (µs) 为单位

Span setDestinationService(String resource) [1.25.0] Added in 1.25.0. edit

提供了一种手动设置跨度 destination.service.resource 字段的方法,该字段用于构建服务地图和识别下游服务。通过此方法设置的任何值都将优先于自动推断的值。使用 null 或空资源字符串会导致此字段从跨度上下文中省略。

Span setNonDiscardable() [1.32.0] 在 1.32.0 中添加。 编辑

使此跨度不可丢弃。在某些情况下,跨度可能会被丢弃,例如,如果 span_min_duration ( [1.16.0] 在 1.16.0 中添加。 ) 设置,并且跨度未超过配置的阈值。使用此方法确保当前跨度不会被丢弃。

使跨度不可丢弃会隐式地使整个活动跨度堆栈也不可丢弃。子跨度仍然可以被丢弃。

Span setDestinationAddress(String address, int port) [1.25.0] 在 1.25.0 中添加。 编辑

提供了一种手动设置跨度 destination.addressdestination.port 字段的方法。通过此方法设置的值将优先于自动发现的值。使用 null 或空地址或非正端口会导致相应的字段从跨度上下文中省略。

Span setServiceTarget(String type, String name) [1.32.0] 在 1.32.0 中添加。 编辑

提供了一种手动设置跨度 service.target.typeservice.target.name 字段的方法。通过此方法设置的值将优先于自动发现的值。使用 null 或空字符串值会导致这些字段从跨度上下文中省略。

void end()编辑

结束跨度并将其安排到 APM 服务器进行报告。在已结束的跨度实例上调用任何方法都是非法的。这也包括此方法和 Span startSpan()

void end(long epochMicros) [1.5.0] 在 1.5.0 中添加。 编辑

结束跨度并将其安排到 APM 服务器进行报告。在已结束的跨度实例上调用任何方法都是非法的。这也包括此方法和 Span startSpan()

  • epochMicros:此事件结束时的时间戳,以自纪元以来的微秒 (µs) 为单位

示例

span.end(System.currentTimeMillis() * 1000);

Span startSpan(String type, String subtype, String action)编辑

启动并返回一个新的跨度,该跨度具有类型、子类型和操作,作为此跨度的子级。

类型、子类型和操作字符串用于将具有不同分辨率的类似跨度分组在一起。例如,所有 DB 跨度都具有类型 db;所有 MySQL 查询的跨度都具有子类型 mysql,所有描述查询的跨度都具有操作 query。在此示例中,db 被认为是通用类型。虽然通用类型没有命名限制,但以下类型在所有 Elastic APM 代理中都是标准化的:appdbcachetemplateext

.(点)字符在类型、子类型和操作中不允许使用。任何此类字符都将被替换为 _(下划线)字符。

当跨度结束时,调用 void end() 很重要。最佳实践是在 try-catch-finally 块中使用跨度。示例

Span span = parent.startSpan("db", "mysql", "query");
try {
    span.setName("SELECT FROM customer");
    // do your thing...
} catch (Exception e) {
    span.captureException(e);
    throw e;
} finally {
    span.end();
}

通过此方法创建的跨度无法通过调用 ElasticApm.currentSpan() 来检索。有关如何实现此目的,请参阅 span.activate()

Span startExitSpan(String type, String subtype, String action)编辑

启动并返回一个新的退出跨度,该跨度具有类型、子类型和操作,作为此跨度的子级。

类似于 startSpan(String, String, String),但创建的跨度将用于在服务地图中创建节点,并在依赖关系表中创建下游服务。提供的子类型将用作下游服务名称,除非通过 setServiceTarget(String type, String name) 显式设置 service.target.typeservice.target.name 字段。

如果在已经是退出跨度的跨度上调用,此方法将返回一个无操作跨度。

Span startSpan()编辑

启动并返回一个新的自定义跨度,该跨度没有类型,作为此跨度的子级。

当跨度结束时,调用 void end() 很重要。最佳实践是在 try-catch-finally 块中使用跨度。示例

Span span = parent.startSpan();
try {
    span.setName("SELECT FROM customer");
    // do your thing...
} catch (Exception e) {
    span.captureException(e);
    throw e;
} finally {
    span.end();
}

通过此方法创建的跨度无法通过调用 ElasticApm.currentSpan() 来检索。有关如何实现此目的,请参阅 span.activate()

Scope activate()编辑

使此跨度成为当前线程上的活动跨度,直到调用 Scope#close()。范围应仅在 try-with-resource 语句中使用,以确保在所有情况下都调用 Scope#close() 方法。未能关闭范围会导致内存泄漏并破坏父子关系。

此方法应始终在 try-with-resources 语句中使用

Span span = parent.startSpan("db", "mysql", "query");
// Within the try block the span is available
// on the current thread via ElasticApm.currentSpan().
// This is also true for methods called within the try block.
try (final Scope scope = span.activate()) {
    span.setName("SELECT FROM customer");
    // do your thing...
} catch (Exception e) {
    span.captureException(e);
    throw e;
} finally {
    span.end();
}

在调用 void end() 之后,调用跨度的任何方法都是非法的。您只能在控制跨度生命周期时与跨度进行交互。例如,如果跨度在另一个线程中结束,则如果 void end()Span setLabel(String key, value) [1.5.0 作为 addLabel] 在 1.5.0 中添加为 addLabel 方法之间存在竞争,则您不得添加标签。

boolean isSampled()编辑

如果此跨度被记录并发送到 APM 服务器,则返回 true

void injectTraceHeaders(HeaderInjector headerInjector) [1.3.0] 在 1.3.0 中添加。 编辑

  • headerInjector:告诉代理如何将标头注入请求对象

允许手动传播跟踪标头。

如果你想手动检测尚未由代理的自动检测功能支持的 RPC 框架,可以使用此方法将所需的跟踪标头注入该框架的请求对象的标头部分。

示例

// Hook into a callback provided by the RPC framework that is called on outgoing requests
public Response onOutgoingRequest(Request request) throws Exception {
    // creates a span representing the external call
    Span span = ElasticApm.currentSpan()
            .startSpan("external", "http", null)
            .setName(request.getMethod() + " " + request.getHost());
    try (final Scope scope = transaction.activate()) {
        span.injectTraceHeaders((name, value) -> request.addHeader(name, value));
        return request.execute();
    } catch (Exception e) {
        span.captureException(e);
        throw e;
    } finally {
        span.end();
    }
}