公共 API
编辑公共 API
编辑Elastic APM Java 代理的公共 API 允许您自定义和手动创建 Span 和事务,以及跟踪错误。
开始使用 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 central 的最新版本:
- Tracer API - 访问当前活动的事务和 Span
- 注解 API - 使创建自定义 Span 和事务更容易的注解
- 事务 API - 事务方法
- Span API - Span 方法
Tracer API
编辑Tracer 使您可以访问当前活动的事务和 Span。它还可用于跟踪异常。
要使用 API,您只需调用 co.elastic.apm.api.ElasticApm
类上的静态方法即可。
Transaction currentTransaction()
编辑返回当前活动的事务。有关如何自定义当前事务,请参阅 事务 API。
如果没有当前事务,此方法将返回一个 noop 事务,这意味着您永远不必检查 null
值。
import co.elastic.apm.api.ElasticApm; import co.elastic.apm.api.Transaction; Transaction transaction = ElasticApm.currentTransaction();
通过 ElasticApm.startTransaction()
创建的事务无法通过调用此方法检索。有关如何实现这一点,请参阅 span.activate()
。
Span currentSpan()
编辑返回当前活动的 Span 或事务。有关如何自定义当前 Span,请参阅 Span API。
如果没有当前 Span,此方法将返回一个 noop Span,这意味着您永远不必检查 null
值。
请注意,即使此方法返回一个 noop Span,您仍然可以在其上捕获异常。这些异常将不会链接到 Span 或事务。
import co.elastic.apm.api.ElasticApm; import co.elastic.apm.api.Span; Span span = ElasticApm.currentSpan();
通过 startSpan()
或 startSpan(String, String, String)
创建的 Span 无法通过调用此方法检索。有关如何实现这一点,请参阅 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
:服务版本
注解 API
编辑该 API 带有两个注解,可以更轻松地创建自定义 Span 和事务。只需将注解放在您的方法之上,代理将负责创建和报告相应的事务和 Span。它还将确保捕获任何未捕获的异常。
需要配置 application_packages
,否则将忽略这些注解。
@CaptureTransaction
编辑使用 @CaptureTransaction
注解方法会为该方法创建一个事务。
请注意,这仅在同一线程上没有活动事务时才有效。
-
value
:事务的名称。默认为ClassName#methodName
-
type
:事务的类型。默认为request
使用此注解会隐式创建一个事务,并在进入注解方法时将其激活。它还会在退出注解方法之前隐式结束并停用它。请参阅 ElasticApm.startTransaction()
、transaction.activate()
和 transaction.end()
@CaptureSpan
编辑使用 @CaptureSpan
注解方法会创建一个 Span 作为当前活动的 Span 或事务的子项(Span currentSpan()
)。
如果没有当前 Span 或事务,则不会创建 Span。
-
value
:Span 的名称。默认为ClassName#methodName
-
type
:Span 的类型,例如 DB Span 的db
。默认为app
-
subtype
:Span 的子类型,例如 DB Span 的mysql
。默认为空字符串 -
action
:与 Span 相关的操作,例如 DB Span 的query
。默认为空字符串 -
discardable
:默认情况下,Span 可能会在某些情况下被丢弃。将此属性设置为false
以使此 Span 不可丢弃。 -
exit
:默认情况下,Span 是内部 Span,使它成为出口 Span 可以防止创建嵌套的 Span,并且旨在表示对外部系统(如数据库或第三方服务)的调用。
使用此注解会隐式创建一个 Span,并在进入注解方法时将其激活。它还会在退出注解方法之前隐式结束并停用它。请参阅 startSpan()
、startSpan(String, String, String)
、span.activate()
和 span.end()
@Traced
[1.11.0] 在 1.11.0 中添加。
编辑使用 @Traced
注解方法会创建一个 Span 作为当前活动的 Span 或事务的子项。
如果没有当前 Span,则会创建一个事务。
如果方法既可以是入口点(事务),也可以是事务中的工作单元(Span),则应使用此注解而不是 @CaptureSpan
或 @CaptureTransaction
。
-
value
:Span 或事务的名称。默认为ClassName#methodName
-
type
:Span 或事务的类型。事务默认为request
,Span 默认为app
-
subtype
:Span 的子类型,例如 DB Span 的mysql
。默认为空字符串。当创建事务时无效。 -
action
:与 Span 相关的操作,例如 DB Span 的query
。默认为空字符串。当创建事务时无效。 -
discardable
:默认情况下,在某些情况下可能会丢弃 span。将此属性设置为false
可以使此 span 不可丢弃。如果创建的事件是事务,则此属性无效。
使用此注解会在进入注解方法时隐式创建 span 或事务并激活它。它还会在退出注解方法之前隐式结束并停用它。请参阅 startSpan()
,startSpan(String, String, String)
,span.activate()
和 span.end()
事务 API
编辑事务是由代理捕获的数据,表示在受监控服务中发生的事件,并将多个 span 分组到一个逻辑组中。事务是服务的第一个 Span
,也称为入口 span。
请参阅 Transaction currentTransaction()
,了解如何获取当前事务的引用。
Transaction
是 Span
的子类型。因此它具有 Span
提供的所有方法,以及其他一些方法。
在调用 void end()
之后调用事务的任何方法都是非法的。您只能在控制其生命周期时与事务进行交互。例如,如果一个 span 在另一个线程中结束,则如果在 void end()
和 Transaction setLabel(String key, value)
[1.5.0 作为 addLabel
] 在 1.5.0 中作为 addLabel
添加。数字和布尔标签需要 APM Server 6.7 方法之间存在竞争,则不得添加标签。
Transaction setName(String name)
编辑覆盖当前事务的名称。对于受支持的框架,事务名称是自动确定的,可以使用此方法覆盖。
例如
transaction.setName("My Transaction");
-
name
:(必需)描述事务名称的字符串
Transaction setType(String type)
编辑设置事务的类型。有一种特殊的类型叫做 request
,当检测到传入的 HTTP 请求时,代理会自动为创建的事务使用该类型。
例如
transaction.setType(Transaction.TYPE_REQUEST);
-
type
:事务的类型
Transaction setFrameworkName(String frameworkName)
[1.25.0] 在 1.25.0 中添加。
编辑提供了一种手动设置 service.framework.name
字段的方法。对于受支持的框架,框架名称是自动确定的,可以使用此函数覆盖。null
或空字符串将使代理省略此字段。
例如
transaction.setFrameworkName("My Framework");
-
frameworkName
:框架的名称
Transaction setServiceInfo(String serviceName, String serviceVersion)
[1.30.0] 在 1.30.0 中添加。
编辑为此事务及其子 span 设置服务名称和版本。
如果在已创建子 span 后调用此方法,它们可能具有错误的服务名称和版本。
-
serviceName
:服务名称 -
serviceVersion
:服务版本
Transaction useServiceInfoForClassLoader(ClassLoader classLoader)
[1.30.0] 在 1.30.0 中添加。
编辑为此事务及其子 span 设置与给定类加载器关联的服务名称和版本(请参阅:ElasticApm#setServiceInfoForClassLoader(ClassLoader, String, String)
)。
如果在已创建子 span 后调用此方法,它们可能具有错误的服务名称和版本。
-
classLoader
:应该用于设置服务名称和版本的类加载器
Transaction setLabel(String key, value)
[1.5.0 作为 addLabel
] 在 1.5.0 中作为 addLabel
添加。数字和布尔标签需要 APM Server 6.7
编辑标签用于向事务、span 和错误添加 索引 信息。索引意味着数据可以在 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] 在 1.7.0 中添加。
编辑自定义上下文用于向事务添加非索引的自定义上下文信息。非索引意味着数据在 Elasticsearch 中不可搜索或不可聚合,并且您无法在数据之上构建仪表板。但是,非索引信息对于其他原因很有用,例如提供上下文信息来帮助您快速调试性能问题或错误。
该值可以是 String
、Number
或 boolean
。
transaction.addCustomContext("foo", "bar");
-
String key
:标签键 -
String|Number|boolean value
:标签值
Transaction setUser(String id, String email, String username)
编辑调用此方法以使用有关用户/客户端的信息来丰富收集的性能数据和错误。可以在请求/响应生命周期的任何时间点(即,在事务处于活动状态时)调用此方法。给定的上下文将添加到活动事务中。
如果捕获到错误,则会使用活动事务中的上下文作为捕获的错误的上下文。
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] 在 1.23.0 中添加。
编辑调用此方法以使用有关用户/客户端的信息来丰富收集的性能数据和错误。可以在请求/响应生命周期的任何时间点(即,在事务处于活动状态时)调用此方法。给定的上下文将添加到活动事务中。
如果捕获到错误,则会使用活动事务中的上下文作为捕获的错误的上下文。
transaction.setUser(user.getId(), user.getEmail(), user.getUsername(), user.getDomain());
-
id
:用户的 ID,如果不可用,则为null
。 -
email
:用户的电子邮件地址,如果不可用,则为null
。 -
username
:用户的姓名,如果不可用,则为null
。 -
domain
:用户的域,如果不可用,则为null
。
String captureException(Exception e)
编辑捕获异常并将其报告给 APM 服务器。自版本 1.14.0 起 - 返回报告的错误的 ID。
String getId()
编辑返回此事务的 ID(永不为 null
)
如果此事务表示 noop,则此方法返回一个空字符串。
String getTraceId()
编辑返回此事务的跟踪 ID。
跟踪 ID 在属于同一逻辑跟踪的所有事务和 span 中保持一致,即使对于发生在另一个服务中的事务和 span(前提是此服务也由 Elastic APM 监视)。
如果此 span 表示 noop,则此方法返回一个空字符串。
String ensureParentId()
编辑如果事务还没有父 ID,则调用此方法会生成一个新的 ID,将其设置为此事务的父 ID,并将其作为 String
返回。
这使得 JavaScript 真实用户监控 (RUM) 代理为初始页面加载创建的 span 与后端服务的事务相关联。如果您的后端服务动态生成 HTML 页面,则使用此方法的值初始化 JavaScript RUM 代理可以分析在浏览器中花费的时间与在后端服务中花费的时间。
要在使用 Freemarker 等 HTML 模板语言时启用 JavaScript RUM 代理,请将 ElasticApm.currentTransaction()
与键 "transaction"
添加到模型中。
此外,将类似于此的代码片段添加到 HTML 页面的 body 中,最好在其他 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)
编辑启动并返回一个新的 span,其中包含类型、子类型和操作,作为此事务的子级。
类型、子类型和操作字符串用于将相似的跨度分组在一起,具有不同的解析度。例如,所有数据库跨度都具有类型 db
;所有 MySQL 查询的跨度都具有子类型 mysql
,所有描述查询的跨度都具有操作 query
。在本示例中,db
被视为通用类型。虽然对于通用类型没有命名限制,但以下类型在所有 Elastic APM 代理中都是标准化的:app
、db
、cache
、template
和 ext
。
.(点)字符不允许在类型、子类型和操作中使用。任何此类字符都将被替换为 _(下划线)字符。
当跨度结束时,调用 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.type
和 service.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()
了解如何实现此目的。
Transaction setResult(String result)
编辑一个描述事务结果的字符串。这通常是 HTTP 状态代码,或者例如后台任务的“成功”。
-
result
:一个描述事务结果的字符串。
通过 API 设置的结果值将优先于自动检测设置的值。
Span setOutcome(Outcome outcome)
[1.21.0] 在 1.21.0 中添加。
编辑设置事务或跨度的结果。使用 FAILURE
或 SUCCESS
来指示成功或失败,当结果无法正确得知时,使用 UNKNOWN
。
-
outcome
:事务或跨度的结果
结果用于计算服务之间的错误率,使用 UNKNOWN
不会改变这些比率。通过 API 设置的值将优先于自动检测设置的值。
Transaction setStartTimestamp(long epochMicros)
[1.5.0] 在 1.5.0 中添加。
编辑设置此事件的开始时间戳。
-
epochMicros
:此事件开始时的时间戳,以自 epoch 以来的微秒 (µs) 为单位。
void end()
编辑结束事务并安排将其报告给 APM Server。对已结束的事务实例调用任何方法都是非法的。这也包括此方法和 Span startSpan()
。示例
transaction.end();
void end(long epochMicros)
[1.5.0] 在 1.5.0 中添加。
编辑结束事务并安排将其报告给 APM Server。对已结束的事务实例调用任何方法都是非法的。这也包括此方法和 Span startSpan()
。
-
epochMicros
:此事件结束时的时间戳,以自 epoch 以来的微秒 (µs) 为单位。
例如
transaction.end(System.currentTimeMillis() * 1000);
Scope activate()
编辑使此跨度成为当前线程上的活动跨度,直到调用 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()
编辑如果此事务被记录并发送到 APM Server,则返回 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(); } }
Span API
编辑跨度包含有关作为事务一部分执行的特定代码路径的信息。
例如,如果数据库查询在记录的事务中发生,则可能会创建一个表示此数据库查询的跨度。在这种情况下,跨度的名称将包含有关查询本身的信息,并且类型将包含有关数据库类型的信息。
有关如何获取当前跨度的引用,请参阅 Span currentSpan()
。
Span setName(String name)
编辑覆盖当前跨度的名称。
例如
span.setName("SELECT FROM customer");
-
name
:跨度的名称
Span setLabel(String key, value)
[1.5.0 as addLabel
] 在 1.5.0 中作为 addLabel
添加。
编辑用户定义的标签的扁平映射,带有字符串、数字或布尔值。
在 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)
编辑捕获异常并将其报告给 APM 服务器。自版本 1.14.0 起 - 返回报告的错误的 ID。
String getId()
编辑返回此跨度的 ID(永远不是 null
)
如果此 span 表示 noop,则此方法返回一个空字符串。
String getTraceId()
编辑返回此跨度的跟踪 ID。
跟踪 ID 在属于同一逻辑跟踪的所有事务和跨度中都是一致的,即使是在另一个服务中发生的事务和跨度(假设此服务也受到 Elastic APM 的监控)。
如果此 span 表示 noop,则此方法返回一个空字符串。
Span setStartTimestamp(long epochMicros)
[1.5.0] 在 1.5.0 中添加。
编辑设置此事件的开始时间戳。
-
epochMicros
:此事件开始时的时间戳,以自 epoch 以来的微秒 (µs) 为单位。
Span setDestinationService(String resource)
[1.25.0] 在 1.25.0 中添加。
编辑提供了一种手动设置跨度的 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.address
和 destination.port
字段的方法。通过此方法设置的值将优先于自动发现的值。使用 null
或空地址或非正端口将导致从跨度上下文中省略相应的字段。
Span setServiceTarget(String type, String name)
[1.32.0] 在 1.32.0 中添加。
编辑提供了一种手动设置 span 的 service.target.type
和 service.target.name
字段的方法。通过此方法设置的值将优先于自动发现的值。使用 null
或空字符串值将导致从 span 上下文中省略这些字段。
void end()
编辑结束 span 并将其计划报告给 APM Server。在已结束的 span 实例上调用任何方法都是非法的。这包括此方法和 Span startSpan()
。
void end(long epochMicros)
[1.5.0] 在 1.5.0 中添加。
编辑结束 span 并将其计划报告给 APM Server。在已结束的 span 实例上调用任何方法都是非法的。这包括此方法和 Span startSpan()
。
-
epochMicros
:此事件结束时的时间戳,以自 epoch 以来的微秒 (µs) 为单位。
例如
span.end(System.currentTimeMillis() * 1000);
Span startSpan(String type, String subtype, String action)
编辑启动并返回一个新的 span,其中包含类型、子类型和操作,作为此 span 的子级。
类型、子类型和操作字符串用于将相似的 span 分组在一起,具有不同的分辨率。例如,所有 DB span 都被赋予类型 db
;所有 MySQL 查询的 span 都被赋予子类型 mysql
,所有描述查询的 span 都被赋予操作 query
。在此示例中,db
被认为是通用类型。虽然对通用类型没有命名限制,但以下类型在所有 Elastic APM 代理中都是标准化的:app
、db
、cache
、template
和 ext
。
.(点)字符不允许在类型、子类型和操作中使用。任何此类字符都将被替换为 _(下划线)字符。
当跨度结束时,调用 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)
编辑启动并返回一个新的出口 span,其中包含类型、子类型和操作,作为此 span 的子级。
类似于 startSpan(String, String, String)
,但创建的跨度将用于在服务地图中创建一个节点以及在依赖关系表中创建一个下游服务。除非通过 setServiceTarget(String type, String name)
显式设置 service.target.type
和 service.target.name
字段,否则提供的子类型将用作下游服务名称。
如果在已是出口 span 的 span 上调用此方法,将返回一个 noop span。
Span startSpan()
编辑启动并返回一个新的自定义 span,没有类型,作为此 span 的子级。
当跨度结束时,调用 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()
之后调用 span 的任何方法都是非法的。只有在您可以控制其生命周期时才可以与 span 交互。例如,如果一个 span 在另一个线程中结束,那么如果 void end()
和 Span setLabel(String key, value)
[1.5.0 作为 addLabel
] 在 1.5.0 中作为 addLabel
添加。 方法之间存在竞争的可能性,则不能添加标签。
boolean isSampled()
编辑如果此 span 被记录并发送到 APM Server,则返回 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(); } }