该功能通过自动插桩或手动拦截器,实现对 gRPC 微服务的性能监控,覆盖请求生命周期各阶段(启动、消息收发、关闭),支持自定义指标注入与协议级性能分析,助力精准定位网络延迟、流式异常及业务逻辑问题。
注意:
该功能随原生网络监控功能一并开启,否则无法生效。
自动集成
前提条件
qapmplugin 升级至3.6版本,默认会对 gRPC 的 OkHttpChannelBuilder 的 build 方法插桩。
配置步骤
// 原代码ManagedChannel channel = OkHttpChannelBuilder.forAddress(host, port).usePlaintext().build();// 替换成以下代码OkHttpChannelBuilder builder = OkHttpChannelBuilder.forAddress(host, port).usePlaintext();ManagedChannel channel = QAPMGrpcInstrumentation.builderInit(builder);
手动集成
如果您的 gRPC 不是使用上述 API 来创建的,或者是插桩失败,则需要手动添加拦截器。
配置步骤
import com.tencent.qapmsdk.impl.instrumentation.grpc.QAPMGrpcInterceptor;xxxx.intercept(new QAPMGrpcInterceptor())
添加混淆
SDK 会有反射 gRPC 接口的相关动作,为了避免混淆 GRPC SDK,在 App 的 proguard-rules.pro 文件中增加以下配置。
-keep class io.grpc.** { *; }
相关接口
为了开发更方便的分析 gRPC 的性能问题,我们提供了如下的相关回调接口。
QAPM.setProperty(QAPM.PropertyGrpcListener, new IGrpcListener() {@Overridepublic void onStart(QAPMGrpcRequestMeta meta) {meta.customFieldUd1 = "onStart";Log.e(TAG, "onStart: " + meta.bareMethod + " " + meta.serviceName + " " + meta.methodType);}@Overridepublic void sendMessage(QAPMGrpcRequestMeta meta) {meta.customFieldUd2 = "sendMessage";Log.e(TAG, "sendMessage: " + meta.reqBody.get(meta.reqBody.size() - 1));}@Overridepublic void onRequest(QAPMGrpcRequestMeta meta) {meta.customFieldUd3 = "onRequest";}@Overridepublic void onMessage(QAPMGrpcRequestMeta meta) {meta.customFieldUd4 = "onMessage";meta.customFieldUv1 = 10009;Log.e(TAG, "onMessage: " + meta.respBody.get(meta.respBody.size() - 1));}@Overridepublic void onClose(QAPMGrpcRequestMeta meta) {meta.customFieldUd5 = "onClose";meta.customFieldUv2 = 10008;Log.e(TAG, "onClose: " + meta.status);}});
实现上述接口,我们会在5个不同的时机分别回调。
回调方法 | 回调时机 |
onStart | 接口开始执行 |
sendMessage | 每次发送消息的时候 |
onRequest | 每次请求后台的时候 |
onMessage | 每次接收消息的时候 |
onClose | 请求结束的时候 |
其中 QAPMGrpcRequestMeta 的结构如下:
public class QAPMGrpcRequestMeta<ReqT, RespT> {public String bareMethod;public String serviceName;public MethodDescriptor.MethodType methodType;// 请求的响应体,每一次信息都会追加到这个list中,最后一个为最新接收的消息public List<RespT> respBody = new ArrayList<>();// 请求的body, 每一次信息都会追加到这个list中,最后一个为最新发送的消息public List<ReqT> reqBody = new ArrayList<>();// 请求的头部信息public Map<String, String> requestHeaders;// 响应的头部信息public Map<String, String> responseHeaders;// 最终结果public Status status;public void addRespBody(RespT respBody) {this.respBody.add(respBody);}public void addReqBody(ReqT reqBody) {this.reqBody.add(reqBody);}/*** 开放字段uv1-uv10,用于指标聚合*/public long customFieldUv1;public long customFieldUv2;public long customFieldUv3;public long customFieldUv4;public long customFieldUv5;public long customFieldUv6;public long customFieldUv7;public long customFieldUv8;public long customFieldUv9;public long customFieldUv10;/*** 开放字段ud1-ud5,用于日志上下文展示*/public String customFieldUd1;public String customFieldUd2;public String customFieldUd3;public String customFieldUd4;public String customFieldUd5;}
开发可以根据
bareMethod
、serviceName
等信息,动态的修改开放字段,开放字段会在当条请求结束后,跟随打包一起上报到后台。校验功能是否正常
检索 TAG:QAPM_manager_QAPMPluginManager,打印如下日志则表示功能正常开启。

检索 TAG: [plugin::142]。每次网络请求后1分钟,如打印以下日志,则代表网络数据上报成功:
