本文奖以采集JVM类加载数量为例,详细说明Skywalking JVM自定义指标流程
探针端开发逻辑
-
在JVMMetric.proto(文件位置apm-protocolapm-networksrcmainprotolanguage-agent)下定义对应采集指标
// 在message JVMMetric中加入对应对象,如下所示
message JVMMetric {
int64 time = 1;
CPU cpu = 2;
repeated Memory memory = 3;
repeated MemoryPool memoryPool = 4;
repeated GC gc = 5;
Thread thread = 6;
Others others = 7; //Others 为新增指标集合
}// 定义Others message , 定义采集指标名称
message Others{
int64 loadingClassCount = 1;
} -
通过protoc生成对应Java Bean代码
找到skywalking自带protoc位置
如D:project
ewskywalkingapm-protocolapm-network argetprotoc-plugins
在当前目录下执行生成指标类命令
protoc-3.3.0-windows-x86_64.exe -I=D:/project/new/skywalking/apm-protocol/apm-network/src/main/proto --java_out=D:/project/new/skywalking/apm-protocol/apm-network/target/generated-sources/protobuf/java D:/project/new/skywalking/apm-protocol/apm-network/src/main/proto/language-agent/JVMMetric.proto
-
定义Other对象对应JVMMetricProvider类(包路径为org.apache.skywalking.apm.agent.core.jvm.others)
public enum CommonJVMMetricProvider {
INSTANCE;
private final ClassLoadingMXBean classLoadingMXBean; // 类加载MbbeanCommonJVMMetricProvider() { classLoadingMXBean = ManagementFactory.getClassLoadingMXBean(); } public Others getOtherJVMMetric() { int loadingClassCount = classLoadingMXBean.getLoadedClassCount(); return Others.newBuilder().setLoadingClassCount(loadingClassCount).build(); }
}
-
修改JVMService.java,调用CommonJVMMetricProvider采集逻辑完成数据采集与推送
@Override
public void run() {
…
jvmBuilder.setOthers(CommonJVMMetricProvider.INSTANCE.getOtherJVMMetric()); // 触发采集逻辑
…}
OapServer端开发流程
-
在DefaultScopeDefine.java添加新的业务scope SERVICE_INSTANCE_JVM_OTHERS
…
public static final int SERVICE_INSTANCE_JVM_OTHERS = 44;
… -
定义对应Source类,用于数据存储及查询
SERVICE_INSTANCE_JVM_OTHERS为上一步定义的作用域
@ScopeDeclaration(id = SERVICE_INSTANCE_JVM_OTHERS, name = “ServiceInstanceJVMOthers”, catalog = SERVICE_INSTANCE_CATALOG_NAME)
@ScopeDefaultColumn.VirtualColumnDefinition(fieldName = “entityId”, columnName = “entity_id”, isID = true, type = String.class)
public class ServiceInstanceJVMOthers extends Source {
@Override
public int scope() {
return SERVICE_INSTANCE_JVM_OTHERS;
}@Override public String getEntityId() { return String.valueOf(id); } @Getter @Setter private String id; @Getter @Setter @ScopeDefaultColumn.DefinedByField(columnName = "name", requireDynamicActive = true) private String name; @Getter @Setter @ScopeDefaultColumn.DefinedByField(columnName = "service_name", requireDynamicActive = true) private String serviceName; @Getter @Setter @ScopeDefaultColumn.DefinedByField(columnName = "service_id") private String serviceId; @Getter @Setter private long loadingClassCount; //类加载数量
}
-
在OALLexer.g4文件注册新的scope别名到OAL引擎
…
SRC_SERVICE_INSTANCE_JVM_OTHERS: ‘ServiceInstanceJVMOthers’;
… -
在OALParser.g4文件申明新的scope
-
source
-
SRC_ALL | SRC_SERVICE | SRC_DATABASE_ACCESS | SRC_SERVICE_INSTANCE | SRC_ENDPOINT |
SRC_SERVICE_RELATION | SRC_SERVICE_INSTANCE_RELATION | SRC_ENDPOINT_RELATION |
SRC_SERVICE_INSTANCE_JVM_CPU | SRC_SERVICE_INSTANCE_JVM_MEMORY | SRC_SERVICE_INSTANCE_JVM_MEMORY_POOL | SRC_SERVICE_INSTANCE_JVM_GC | SRC_SERVICE_INSTANCE_JVM_THREAD |
SRC_SERVICE_INSTANCE_CLR_CPU | SRC_SERVICE_INSTANCE_CLR_GC | SRC_SERVICE_INSTANCE_CLR_THREAD |
SRC_ENVOY_INSTANCE_METRIC | SRC_SERVICE_INSTANCE_JVM_OTHERS// SRC_SERVICE_INSTANCE_JVM_OTHERS
;
-
SRC_ALL | SRC_SERVICE | SRC_DATABASE_ACCESS | SRC_SERVICE_INSTANCE | SRC_ENDPOINT |
-
在java-agent.oal中定义对应流水线
…
instance_jvm__class_loading_count = from(ServiceInstanceJVMOthers.loadingClassCount).longAvg();
… -
修改JVMSourceDispatcher.java封装scope数据,分配给流水线
private void sendToOthersMetricProcess(String service,
String serviceId,
String serviceInstance,
String serviceInstanceId,
long timeBucket,
Others others) {
ServiceInstanceJVMOthers serviceInstanceJVMOthers = new ServiceInstanceJVMOthers();
serviceInstanceJVMOthers.setId(serviceInstanceId);
serviceInstanceJVMOthers.setServiceId(serviceId);
serviceInstanceJVMOthers.setName(service);
serviceInstanceJVMOthers.setServiceName(serviceInstance);
serviceInstanceJVMOthers.setLoadingClassCount(others.getLoadingClassCount());
serviceInstanceJVMOthers.setTimeBucket(timeBucket);
sourceReceiver.receive(serviceInstanceJVMOthers);
}