gRPC 监控

最近更新时间:2025-06-19 21:11:53

我的收藏
该功能通过自动插桩或手动拦截器,实现对 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() {

@Override
public void onStart(QAPMGrpcRequestMeta meta) {
meta.customFieldUd1 = "onStart";
Log.e(TAG, "onStart: " + meta.bareMethod + " " + meta.serviceName + " " + meta.methodType);
}

@Override
public void sendMessage(QAPMGrpcRequestMeta meta) {
meta.customFieldUd2 = "sendMessage";
Log.e(TAG, "sendMessage: " + meta.reqBody.get(meta.reqBody.size() - 1));
}

@Override
public void onRequest(QAPMGrpcRequestMeta meta) {
meta.customFieldUd3 = "onRequest";
}

@Override
public void onMessage(QAPMGrpcRequestMeta meta) {
meta.customFieldUd4 = "onMessage";
meta.customFieldUv1 = 10009;
Log.e(TAG, "onMessage: " + meta.respBody.get(meta.respBody.size() - 1));
}

@Override
public 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;
}
开发可以根据 bareMethodserviceName 等信息,动态的修改开放字段,开放字段会在当条请求结束后,跟随打包一起上报到后台。

校验功能是否正常

检索 TAG:QAPM_manager_QAPMPluginManager,打印如下日志则表示功能正常开启。

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