ARMS提供了从调用链路中提取特定属性的能力,无侵入地提取请求和响应中的指定参数,进一步帮助您定位问题根因和追踪请求信息。您可以配置业务参数提取规则,并根据提取出的参数配置自定义错误。
该功能目前仅支持Java应用。
由于业务参数提取规则中存在反射和序列化/反序列化过程,可能会对您的业务带来一定的额外开销,关于开销的详细说明请参见性能开销。
前提条件
已为应用安装4.1.0或以上版本探针,具体操作,请参见应用监控接入概述。如果您的探针版本低于4.1.0,本功能配置后将不会有任何作用和影响。
4.2.0及更高版本探针支持为一条业务参数提取规则添加多条接口匹配及参数提取规则。如果您的探针版本在4.1.0~4.2.0之间,仅第一条匹配规则会生效。
功能入口
登录ARMS控制台,在左侧导航栏选择 。
在应用列表页面顶部选择目标地域,然后单击目标应用名称。
说明语言列的图标含义如下:
:接入应用监控的Java应用。
:接入应用监控的Golang应用。
:接入应用监控的Python应用。
-:接入可观测链路 OpenTelemetry 版的应用。
在上方导航栏选择
。在业务参数提取规则区域,您可以创建、查看和修改当前应用的业务参数提取规则。
ARMS应用监控探针会动态识别规则变化,并依照所有已启动的规则将业务参数提取出来。
在自定义错误设置区域,您可以配置自定义错误规则,对提取出来的业务参数值进行过滤。
业务参数提取规则
支持范围说明
业务参数提取规则对框架和实际用法有一定要求,支持的类型和来源如下:
参数提取类型 | 参数提取来源 | 支持的框架 | 备注 |
HTTP服务端请求 |
|
| - |
Body | SpringMVC 4.2.0+ | 类名需使用@Controller注解标注,且方法入参被@RequestBody注解标注。 | |
HTTP服务端响应 |
|
| - |
Body | SpringMVC 4.2.0+ | 类名需使用@Controller注解标注,且方法被@ResponseBody注解标注。 | |
异常信息 | Message | - | 对应类需要继承 java.lang.Exception。 |
新增规则
规则创建完成并启用后将实时下发至客户端探针侧,无需重启应用,预计1~2分钟后开始生效。
业务参数被提取后将记录至对应调用链Span的属性Attributes中,可在调用链分析页面按需筛选查询。
Attribute名称会默认具有
biz.
前缀,不允许重复。Span数据是否上报会受到采样策略影响,您可以通过调整采样策略来保证重要信息被正确上报,更多信息请参见调用链采样模式选择(3.2.8以下探针版本)。
如果调用链中无对应的业务参数信息,请检查提取规则的参数是否配置正确。
在业务参数提取规则区域单击新增规则,填写规则信息并保存。
规则名称:该条规则的可读名称。
Attribute名称:该条规则提取出的值在Span中对应的Attribute名称,默认以biz.开头,后续由多个单词组成,每个单词仅允许由大小写字母、数字、短划线(-)、下划线(_)组成,单词与单词之间必须有一个半角句号(.)分隔。最多允许存在10个单词。
参数提取类型:需要提取的参数类型。
生效接口(HTTP类型):该条规则作用的HTTP接口范围,探针仅对匹配成功的接口提取相应参数。
异常类名(异常类型):该条规则作用的异常类名范围,探针仅对匹配成功的异常提取相应参数。
文本编码类型:待提取参数文本的编码类型。
参数提取规则:定义待提取参数所在的实际载体来源和提取后的处理方式,支持配置多个参数来源和提取步骤。若多个来源均可提取到参数,排序在前的参数提取步骤优先级高于后者。更多信息,请参见参数提取规则示例。
参数来源:待提取参数所在的实际载体来源,对于Header、Cookie、Parameter,需要您填写相应的Key来初步提取,对于Body、Message,则代表载体为整个对象。
参数处理步骤:流式的参数处理步骤,用于从参数载体中逐步解析出最终的参数值。您可以添加多条参数处理步骤,前者的解析结果会成为后者的输入。如果不添加处理步骤,则提取到的参数值为载体对象的Json文本。更多信息,请参见参数处理步骤最佳实践。
支持的参数处理方式:
Ognl:入参要求为Object,支持点表示法的Ognl语句,示例:
#this.data.getCode()
。JsonPath:入参要求为JsonString,支持点表示法的JsonPath语句,示例:
$.data.code
。Regex:入参要求为String,支持基于命名分组的正则表达式语句,待提取的子串对应名为res的分组,示例:
.*from:(?<res>[a-z]+).*
。
是否启用:该条规则是否启用。
生效验证
参数提取规则配置完成后,无需重启应用即可生效。跳转到调用链分析页面查看相关调用链,如果对应接口的Span Attribute有自定义的Attribute被写入,说明提取规则生效。
找到新增的规则对应的Attribute名称。
在调用链分析页面添加
attributes.$attributesName
作为查询条件,过滤相关Span。单击任意一条Trace,在对应的Span下可以看到自定义的Attributes。
管理规则
启用/禁用规则:在目标规则右侧设置是否启用开关。
编辑和删除:在目标规则右侧单击编辑和删除,可以修改或删除对应规则。
批量删除:选中需要删除的提取规则,并单击批量删除。
批量复制:选中需要复制的提取规则,并单击批量复制至其他应用,在弹窗中选择复制到其他所有应用或者选择指定应用。
说明批量复制至其他应用需要1~2分钟时间生效。
该功能仅复制参数提取规则,其配套的自定义错误不会被复制到目标应用。
参数提取规则要求Attribute名称唯一,如果目标应用已经存在同样的Attribute名称,则该条规则不会被复制到目标应用。
参数提取规则示例
Ognl
Ognl语句是一种对象访问语言,允许使用者通过表达式获取Java对象中的属性,或者执行Java对象的方法。Ognl作为参数处理方法,允许您对使用了@ResponseBody或者@RequestBody注解标注的Java对象进行提取。提取结果会被转为一个String(如果是对象会被转为Json字符串),便于您做进一步提取。示例:
@RestController
@RequestMapping("/components/api/v1/mall")
public class MallController {
@RequestMapping("/product")
@ResponseBody
public ResponseBody product(@RequestBody RequestBody req) {
// 您的业务代码
}
static class RequestBody {
String requestId;
Map<String, String> queryParam;
public String getQueryJsonStr() {
return JSON.toJsonString(queryParam);
}
}
static class ResponseBody {
int code;
boolean success;
String message;
}
}
如果您希望提取RequestBody中的requestId字段,可以将提取规则设置如下。
如果您希望提取ResponseBody中的code字段,可以将提取规则设置如下。
Ognl支持您调用对象中的get方法来获取字段,如果您希望提取RequestBody中getQueryJsonStr()方法的执行结果,可以将提取规则设置如下。
在使用前请保证该类存在该方法。
JsonPath
JsonPath语句是一种Json字符串提取语言,允许使用者通过表达式获取Json String中的属性。JsonPath作为参数处理方法,允许您对Json字符串进行提取。示例:
{
"code": 200,
"message": "Query success.",
"success": true,
"data": {
"name": "John",
"age": 21
}
}
如果您希望提取上述JSON中data.age字段,可以将提取规则设置如下。
Regex
Regex语句即正则表达式,用于描述、匹配一系列符合某个句法规则的字符串。Regex作为参数处理方法,允许您对待提取字符串进行正则匹配,并将匹配到的名称为res的分组作为提取结果。示例:
正则表达式默认为从头匹配,如果为任意匹配,请在语句前后添加.*
。
https://test.aliyun.com/v2/workitem#requestId=0c978f115b6f7&cityCode=34&env=online
如果您希望提取上述URL中的cityCode部分,可以将提取规则设置如下。
实际样例
如下示例为HTTP应用的响应Body对象。
class DemoResponse {
int code = 200;
boolean success = true;
String message = "text content";
String extraInfo = "{\"id\": 15, \"cityInfo\": \"from:hangzhou,to:beijing\"}";
public String getExtraInfo() {
return this.extraInfo;
}
}
如果希望从extraInfo字段中提取cityInfo的from城市名,可以将提取规则设置如下。
探针实际的提取与处理过程如下:
从响应中获取到DemoResponse对象。
执行
#this.getExtraInfo()
语句,获取到extraInfo字段。执行
$.cityInfo
语句,将extraInfo字段的值当作JsonString解析,并获取到其中的cityInfo字段。执行
^from:(?<res>[a-z]+).*
语句,将cityInfo字段的值当做String解析,匹配到res命名的分组,即hangzhou
子串。把
hangzhou
作为提取结果写入Span的Attribute。
参数处理步骤最佳实践
参数处理原理
参数处理步骤支持您从参数载体中进一步检索和过滤需要的信息,可以理解为一种流式映射规则,上一步的输出会作为下一步的输入。
不同的参数处理方法对输入有一定的要求,如果输入不满足要求,则会直接中止后续流程,把当前结果作为最终值记录下来。
参数处理方法 | 输入 | 输出 |
Ognl | 任意的Java对象 | String(如果处理结果为一个对象,会序列化为Json字符串) |
JsonPath | JSON字符串 | String |
Regex | String | String |
性能开销
参数处理步骤涉及序列化/反序列化、Java反射、正则匹配等逻辑,是整个业务参数提取环节中性能损耗占比最高的部分,不建议对RT要求高和性能要求高的接口配置过多参数处理步骤。如果您需要对这样的接口进行提取,可以考虑适当地对业务进行改造。
如果安全合规允许,可以考虑在业务中把对应参数直接写入Header等位置。
采用OTelSDK手动为把相关参数写入Span的Attribute,具体操作请参见通过OpenTelemetry Java SDK为调用链增加自定义埋点。
参数处理语句合法性
为了保证提取逻辑的安全性,参数处理语句相比开源实现有更严格的限制,详情如下:
参数处理方法 | 语法参考 | 额外语法限制 | 正确示例 |
Ognl | 仅支持点表示法的字段/方法访问,且调用方法必须为get开头。最大支持的访问深度为10。 | #this.extraInfo.getPid() | |
JsonPath | 仅支持点表示法的字段访问。最大支持的访问深度为10。 | $.cityInfo | |
Regex | 必须有且仅有一个名为res的分组表示被提取的结果。 | ^from:(?<res>[a-z]+).* |
自定义错误规则
如果提取到的参数命中了自定义错误规则,该参数所在Span会被标记为错误Span。如果错误发生在某次服务访问中,该次错误会被统计到arms_$callType_requests_error_count
指标中,您可以对该规则配置告警。
自定义错误指标统计不受采样策略影响,未被采样的错Span也会被正常统计。
服务访问类型及可用维度请参见应用监控指标说明。
设置自定义错误规则
在自定义错误设置区域打开自定义错误码开关,开启自定义错误码功能。
单击添加匹配规则,新增一条匹配规则。
指定对应的业务参数提取规则,并设置错误过滤规则。
单击保存,无需重启应用,规则会在1~2分钟后生效。
生效验证
自定义错误配置完成后,无需重启应用即可生效。跳转到调用链分析页面查看错误Span中是否有符合自定义错误条件的Span。
确认错误匹配规则对应的Attribute名称与条件。
在调用链分析页面选择所有错误Span作为查询条件,查看所有错误Span。
单击任意一条Trace,查看Attribute是否与配置的规则相匹配。
下图示例中biz.resp.body的值为670,满足大于499的错误匹配规则。
进入应用概览页面,可以看到错误数被正确纳入总错误数大盘。
性能开销
业务参数提取功能会给您的应用带来一定的额外开销,开销的主要来源为提取过程的序列化/反序列化及反射操作。本文构建了一个测试Demo来验证业务参数提取功能的基本开销,Demo运行的基本情况如下:
Pod规格:1c2g × 1
服务端存在5个HTTP接口,施压机按照2000 QPS分别调用5个服务端接口产生Span,每个接口对应一种参数提取来源。
测试配置:每100次调用会提取出240个自定义参数,执行20次正则处理,40次JsonPath处理,40次Ognl处理。
开启提取规则后的开销对比:
消耗对象 | 基线(不开启该功能) | 开启该功能 | 开销增幅 |
CPU | 0.230 c | 0.257 c | +0.027 c |
内存(启动后20分钟) | 575 MB | 693 MB | +118 MB |
RT | 101 ms | 101 ms | +0 ms |
常见问题
什么情况下会导致参数提取失败?
如果您的提取来源为Body,请确认您的应用是否使用了SpringMVC,方法所在类添加了@Controller注解,以及对对应方法和参数添加了@RequestBody和@ResponseBody注解。
如果您的提取来源为Response中的Cookie,目前仅支持Tomcat 7.0.4-9.x版本、Undertow 1.4.0.Final+版本获取,建议您将提取来源替换为Request中的Cookie。
异常的提取生效范围?
Java探针仅会对抛到Span外部的自定义异常进行拦截,对于内部的关键方法,如果需要提取其中的异常信息并标识为错误,可以通过监控方法自定义功能为该方法创建埋点,具体操作请参见监控方法自定义。
SpringMVC应用中常见注解的参数提取应该如何配置?
当前已支持的SpringMVC注解与相关配置的对应关系如下所示:
注解 | 参数提取类型 | 参数 |
@RequestParam | HTTP服务端请求 | Parameter |
@RequestHeader | HTTP服务端请求 | Header |
@CookieValue | HTTP服务端请求 | Cookie |
@RequestBody | HTTP服务端请求 | Body |
@ResponseBody | HTTP服务端响应 | Body |
目前不支持的业务参数来源应该如何提取?
您可以通过引入OpenTelemetry SDK为应用添加自定义埋点,并将希望提取的业务参数作为Attributes写入Span。详情请参见通过OpenTelemetry Java SDK为调用链增加自定义埋点。
自定义参数提取规则是否支持从RequestBodyAdvice和ResponseBodyAdvice修饰过的Body对象中提取?
支持。ARMS探针对Body的提取时机发生在用户定义的BodyAdvice之后,Spring内置的BodyAdvice之前。