配置 X-Ray SDK for Java
X-Ray SDK for Java 包括提供全局记录器的、名为 AWSXRay
的类。这是可用于检测代码的 TracingHandler
。您可以配置全局记录器以自定义为传入 HTTP 调用创建分段的 AWSXRayServletFilter
。
服务插件
plugins
用于记录有关托管应用程序的服务的信息。
插件
Amazon EC2 -
EC2Plugin
会添加实例 ID、可用区和 CloudWatch Logs 组。Elastic Beanstalk -
ElasticBeanstalkPlugin
添加环境名称、版本标签和部署 ID。Amazon ECS —
ECSPlugin
添加容器 ID。Amazon EKS -
EKSPlugin
会添加容器 ID、群集名称、Pod ID 和 CloudWatch Logs 组。
要使用插件,请在 AWSXRayRecorderBuilder
上调用 withPlugin
。
例 src/main/java/scorekeep/WebConfig.java - Recorder
import com.amazonaws.xray.AWSXRay;
import com.amazonaws.xray.AWSXRayRecorderBuilder;
import com.amazonaws.xray.plugins.EC2Plugin;
import com.amazonaws.xray.plugins.ElasticBeanstalkPlugin;
import com.amazonaws.xray.strategy.sampling.LocalizedSamplingStrategy;
@Configuration
public class WebConfig {
...
static {
AWSXRayRecorderBuilder builder = AWSXRayRecorderBuilder.standard().withPlugin(new EC2Plugin()).withPlugin(new ElasticBeanstalkPlugin());
URL ruleFile = WebConfig.class.getResource("/sampling-rules.json");
builder.withSamplingStrategy(new LocalizedSamplingStrategy(ruleFile));
AWSXRay.setGlobalRecorder(builder.build());
}
}
该 SDK 还使用插件设置为设置分段上的 origin
字段。这指示运行应用程序的 AWS 资源的类型。当使用多个插件时,SDK 会使用以下解析顺序来确定来源:ElasticBeanstalk > EKS > ECS > EC2。
采样规则
该 SDK 使用您在 X-Ray 控制台中定义的采样规则来确定要记录的请求。默认规则跟踪每秒的第一个请求,以及所有将跟踪发送到 X-Ray 的服务的任何其他请求的百分之五。在 X-Ray 控制台中创建其他规则以自定义为每个应用程序记录的数据量。
该 SDK 按照定义的顺序应用自定义规则。如果请求与多个自定义规则匹配,则 SDK 仅应用第一条规则。
注意
如果 SDK 无法访问 X-Ray 来获取采样规则,它将恢复为默认的本地规则,即每秒第一个请求以及每个主机所有其他请求的百分之五。如果主机无权调用采样 API 或者无法连接到 X-Ray 进程守护程序,后者充当 SDK 发出的 API 调用的 TCP 代理,则可能会发生这种情况。
您还可以将 SDK 配置为从 JSON 文档加载采样规则。在 X-Ray 采样不可用的情况下,SDK 可以使用本地规则作为备份,也可以只使用本地规则。
例 sampling-rules.json
{
"version": 2,
"rules": [
{
"description": "Player moves.",
"host": "*",
"http_method": "*",
"url_path": "/api/move/*",
"fixed_target": 0,
"rate": 0.05
}
],
"default": {
"fixed_target": 1,
"rate": 0.1
}
}
此示例定义了一个自定义规则和一个默认规则。自定义规则采用百分之五的采样率,对于 /api/move/
之下的路径要跟踪的请求数量不设下限。默认规则中每秒的第一个请求以及其他请求的百分之十。
在本地定义规则的缺点是,固定目标由记录器的每个实例独立应用而不是由 X-Ray 服务管理。随着您部署更多主机,固定速率会成倍增加,这使得控制记录的数据量变得更加困难。
您无法在 AWS Lambda 上修改采样率。如果您的函数由检测服务调用,Lambda 将记录生成由该服务采样的请求的调用。如果启用了活动跟踪且不存在任何跟踪标头,则 Lambda 会做出采样决定。
要在 Spring 中提供备份规则,请使用配置类中的 CentralizedSamplingStrategy
配置全局记录器。
例 src/main/java/myapp/WebConfig.java - 记录器配置
import com.amazonaws.xray.AWSXRay;
import com.amazonaws.xray.AWSXRayRecorderBuilder;
import com.amazonaws.xray.javax.servlet.AWSXRayServletFilter;
import com.amazonaws.xray.plugins.EC2Plugin;
import com.amazonaws.xray.strategy.sampling.LocalizedSamplingStrategy;
@Configuration
public class WebConfig {
static {
AWSXRayRecorderBuilder builder = AWSXRayRecorderBuilder.standard().withPlugin(new EC2Plugin());
URL ruleFile = WebConfig.class.getResource("/sampling-rules.json");
builder.withSamplingStrategy(new CentralizedSamplingStrategy(ruleFile));
AWSXRay.setGlobalRecorder(builder.build());
}
对于 Tomcat,添加一个扩展 ServletContextListener
的侦听器,并在部署描述符中注册该侦听器。
例 src/com/myapp/web/Startup.java
import com.amazonaws.xray.AWSXRay;
import com.amazonaws.xray.AWSXRayRecorderBuilder;
import com.amazonaws.xray.plugins.EC2Plugin;
import com.amazonaws.xray.strategy.sampling.LocalizedSamplingStrategy;
import java.net.URL;
import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
public class Startup implements ServletContextListener {
@Override
public void contextInitialized(ServletContextEvent event) {
AWSXRayRecorderBuilder builder = AWSXRayRecorderBuilder.standard().withPlugin(new EC2Plugin());
URL ruleFile = Startup.class.getResource("/sampling-rules.json");
builder.withSamplingStrategy(new CentralizedSamplingStrategy(ruleFile));
AWSXRay.setGlobalRecorder(builder.build());
}
@Override
public void contextDestroyed(ServletContextEvent event) { }
}
例 WEB-INF/web.xml
...
<listener>
<listener-class>com.myapp.web.Startup</listener-class>
</listener>
若要仅使用本地规则,请将 CentralizedSamplingStrategy
替换为 LocalizedSamplingStrategy
。
builder.withSamplingStrategy(new
LocalizedSamplingStrategy
(ruleFile));
日志记录
默认情况下,SDK 会将 ERROR
级消息输出到应用程序日志。可以在 SDK 上启用调试级别日志记录,将更详细的日志输出到应用程序日志文件。有效的日志级别为 DEBUG
、INFO
、WARN
、ERROR
和 FATAL
。FATAL
日志级别会静默所有日志消息,因为 SDK 不会在严重级别记录日志。
例 application.properties
使用 logging.level.com.amazonaws.xray
属性设置日志记录级别。
logging.level.com.amazonaws.xray = DEBUG
当您手动生成子分段时,使用调试日志来识别诸如未结束子分段之类的问题。
跟踪 ID 注入到日志
要将当前完全限定的跟踪 ID 公开到日志语句,您可以将此 ID 注入到映射的诊断上下文 (MDC)。在分段生命周期事件过程中使用 SegmentListener
接口从 X-Ray 记录器调用方法。当分段或子分段开始时,使用密钥 AWS-XRAY-TRACE-ID
将限定的跟踪 ID 注入到 MDC 中。当该分段结束后,从 MDC 中删除密钥。这会向正在使用的日志库公开跟踪 ID。当子分段结束时,其父级 ID 将注入到 MDC 中。
例 完全限定的跟踪 ID
完全限定的 ID 表示为 TraceID@EntityID
1-5df42873-011e96598b447dfca814c156@541b3365be3dafc3
此特征可以与使用 AWS X-Ray SDK for Java 进行检测的 Java 应用程序一起使用,并且支持以下日志记录配置:
-
带有 Logback 后端的 SLF4J 前端 API
-
带有 Log4J2 后端的 SLF4J 前端 API
-
带有 Log4J2 后端的 Log4J2 前端 API
请查看以下选项卡,了解每个前端和每个后端的需求。
跟踪 ID 注入示例
以下显示了一个经过修改包含跟踪 ID 的 PatternLayout
字符串。跟踪 ID 在线程名称 (%t
) 之后和日志级别 (%-5p
) 之前输出。
例 PatternLayout
(带 ID 注入)
%d{HH:mm:ss.SSS} [%t]
%X{AWS-XRAY-TRACE-ID}
%-5p %m%n
AWS X-Ray 自动在日志语句中输出密钥和跟踪 ID 以便于解析。下面显示了使用已修改的 PatternLayout
的日志语句。
例 带 ID 注入的日志语句
2019-09-10 18:58:30.844 [nio-5000-exec-4]
AWS-XRAY-TRACE-ID
: 1-5d77f256-19f12e4eaa02e3f76c78f46a@1ce7df03252d99e1 WARN 1 -Your logging message here
日志记录消息本身保存在模式 %m
中,并在调用记录器时设置。
分段侦听器
分段侦听器是一个用于拦截生命周期事件(例如,由 AWSXRayRecorder
生成的分段的开始和结束)的接口。分段侦听器事件函数的实现可能是在使用 onBeginSubsegment
创建所有子分段时向所有子分段添加相同的注释,使用 afterEndSegment
将每个分段发送到进程守护程序后记录一条消息,或者使用 beforeEndSubsegment
记录由 SQL 拦截程序发送的查询,以验证子分段是否代表 SQL 查询,如果是,则添加其他元数据。
要查看 SegmentListener
函数的完整列表,请访问 AWS X-Ray Recorder SDK for Java API 相关文档。
以下示例说明如何在使用 onBeginSubsegment
创建所有子分段时向所有子分段添加一致的注释,以及如何使用 afterEndSegment
在每个分段末尾打印日志消息。
例 MySegmentListener.java
import com.amazonaws.xray.entities.Segment;
import com.amazonaws.xray.entities.Subsegment;
import com.amazonaws.xray.listeners.SegmentListener;
public class MySegmentListener implements SegmentListener {
.....
@Override
public void onBeginSubsegment(Subsegment subsegment) {
subsegment.putAnnotation("annotationKey
", "annotationValue
");
}
@Override
public void afterEndSegment(Segment segment) {
// Be mindful not to mutate the segment
logger.info("Segment with ID " + segment.getId()
);
}
}
然后,在构建 AWSXRayRecorder
时引用此自定义分段侦听器。
例 AWSXRayRecorderBuilder 语句
AWSXRayRecorderBuilder builder = AWSXRayRecorderBuilder
.standard().withSegmentListener(new MySegmentListener()
);
环境变量
您可以使用环境变量来配置 X-Ray SDK for Java。SDK 支持以下变量。
AWS_XRAY_CONTEXT_MISSING
- 设置为RUNTIME_ERROR
在您的已检测代码尝试在分段未打开的情况下记录数据时引发异常。有效值
-
RUNTIME_ERROR
— 引发运行时异常。 -
LOG_ERROR
— 记录错误并继续(默认)。 -
IGNORE_ERROR
— 忽略错误并继续。
对于在未打开任何请求时运行的启动代码或者会生成新线程的代码,如果您尝试在其中使用检测过的客户端,则可能发生与缺失分段或子分段相关的错误。
-
AWS_XRAY_DAEMON_ADDRESS
- 设置 X-Ray 进程守护程序侦听器的主机和端口。默认情况下,SDK 使用用于跟踪数据(UDP)和采样(TCP)的127.0.0.1:2000
。如果您已将进程守护程序配置为侦听不同端口或者进程守护程序在另一台主机上运行,则使用此变量。格式
-
同一个端口 —
address
:port
-
不同的端口 —
tcp:
address
:port
udp:address
:port
-
-
AWS_LOG_GROUP
- 将日志组的名称设置为与您的应用程序关联的日志组。如果您的日志组使用与您的应用程序相同的 AWS 账户和区域,X-Ray 将使用此指定的日志组自动搜索应用程序的分段数据。有关日志组的更多信息,请参阅使用日志组和日志流。 -
AWS_XRAY_TRACING_NAME
- 设置 SDK 用于进行分段的服务名称。覆盖您根据 servlet 筛选器的分段命名策略设置的服务名称。
环境变量覆盖在代码中设置的等效系统属性和值。
系统属性
您可以将系统属性用作环境变量的 JVM 特定替代项。SDK 支持以下属性:
-
com.amazonaws.xray.strategy.tracingName
- 等效于AWS_XRAY_TRACING_NAME
。 -
com.amazonaws.xray.emitters.daemonAddress
- 等效于AWS_XRAY_DAEMON_ADDRESS
。 -
com.amazonaws.xray.strategy.contextMissingStrategy
- 等效于AWS_XRAY_CONTEXT_MISSING
。
如果同时设置系统属性和等效的环境变量,则使用环境变量值。每种方法都会覆盖在代码中设置的值。