diff --git a/README.md b/README.md index 604ea4e0979ff5fc851017997f7e9011221da29b..546d9e633a0d6e7d96141b14a522c031742ef58d 100644 --- a/README.md +++ b/README.md @@ -24,7 +24,7 @@ Sky Walking | [中文](README_ZH.md) # Architecture * Architecture graph for 3.2+ - + # Document * [WIKI](https://github.com/OpenSkywalking/skywalking/wiki) @@ -65,8 +65,8 @@ This project adheres to the Contributor Covenant [code of conduct](CODE_OF_CONDU # Open Skywalking Organization [Open Skywalking Organization Teams and Contributors](https://github.com/OpenSkywalking/Organization/blob/master/README.md) -# Commercial Support Partners -[![Shurenyun Logo](https://skywalkingtest.github.io/page-resources/partners/shurenyun-logo.png)](https://www.shurenyun.com/) +# Partners + # License [Apache 2.0 License.](/LICENSE) diff --git a/README_ZH.md b/README_ZH.md index 27414f1cdfe52976a7b3fea7e0ba330b8bb3c90e..9fdd902c422b6c17313b810a7149c74cee3a6348 100644 --- a/README_ZH.md +++ b/README_ZH.md @@ -25,7 +25,7 @@ Sky Walking | [English](README.md) # Architecture * 3.2+版本架构图 - + # Document * [WIKI](https://github.com/OpenSkywalking/skywalking/wiki) @@ -67,9 +67,8 @@ This project adheres to the Contributor Covenant [code of conduct](CODE_OF_CONDU # Open Skywalking Organization [Open Skywalking Organization Teams and Contributors](https://github.com/OpenSkywalking/Organization/blob/master/README.md) -# Commercial Support Partners -[![Shurenyun Logo](https://skywalkingtest.github.io/page-resources/partners/shurenyun-logo.png)](https://www.shurenyun.com/) - +# Partners + # License [Apache 2.0 License.](/LICENSE) diff --git a/apm-collector/apm-collector-agentjvm/src/main/java/org/skywalking/apm/collector/agentjvm/worker/cpu/dao/CpuMetricH2DAO.java b/apm-collector/apm-collector-agentjvm/src/main/java/org/skywalking/apm/collector/agentjvm/worker/cpu/dao/CpuMetricH2DAO.java index 3349bb9fcaeaa5f94eaf5dcd3b29764adacfb9d5..349c15b5f50302594273416a93a787ec23ecee8f 100644 --- a/apm-collector/apm-collector-agentjvm/src/main/java/org/skywalking/apm/collector/agentjvm/worker/cpu/dao/CpuMetricH2DAO.java +++ b/apm-collector/apm-collector-agentjvm/src/main/java/org/skywalking/apm/collector/agentjvm/worker/cpu/dao/CpuMetricH2DAO.java @@ -18,10 +18,44 @@ package org.skywalking.apm.collector.agentjvm.worker.cpu.dao; +import org.skywalking.apm.collector.core.stream.Data; +import org.skywalking.apm.collector.storage.define.DataDefine; +import org.skywalking.apm.collector.storage.define.jvm.CpuMetricTable; +import org.skywalking.apm.collector.storage.h2.SqlBuilder; import org.skywalking.apm.collector.storage.h2.dao.H2DAO; +import org.skywalking.apm.collector.storage.h2.define.H2SqlEntity; +import org.skywalking.apm.collector.stream.worker.impl.dao.IPersistenceDAO; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.HashMap; +import java.util.Map; /** - * @author pengys5 + * @author pengys5, clevertension */ -public class CpuMetricH2DAO extends H2DAO implements ICpuMetricDAO { +public class CpuMetricH2DAO extends H2DAO implements ICpuMetricDAO, IPersistenceDAO { + private final Logger logger = LoggerFactory.getLogger(CpuMetricH2DAO.class); + @Override public Data get(String id, DataDefine dataDefine) { + return null; + } + + @Override public H2SqlEntity prepareBatchInsert(Data data) { + H2SqlEntity entity = new H2SqlEntity(); + Map source = new HashMap<>(); + source.put("id", data.getDataString(0)); + source.put(CpuMetricTable.COLUMN_INSTANCE_ID, data.getDataInteger(0)); + source.put(CpuMetricTable.COLUMN_USAGE_PERCENT, data.getDataDouble(0)); + source.put(CpuMetricTable.COLUMN_TIME_BUCKET, data.getDataLong(0)); + + logger.debug("prepare cpu metric batch insert, id: {}", data.getDataString(0)); + String sql = SqlBuilder.buildBatchInsertSql(CpuMetricTable.TABLE, source.keySet()); + entity.setSql(sql); + entity.setParams(source.values().toArray(new Object[0])); + return entity; + } + + @Override public H2SqlEntity prepareBatchUpdate(Data data) { + return null; + } } diff --git a/apm-collector/apm-collector-agentjvm/src/main/java/org/skywalking/apm/collector/agentjvm/worker/gc/dao/GCMetricH2DAO.java b/apm-collector/apm-collector-agentjvm/src/main/java/org/skywalking/apm/collector/agentjvm/worker/gc/dao/GCMetricH2DAO.java index e4aa523b9c1809e768ed4810b4e70177b2eb45a1..bbe619015ef71bf6b765c22a2721129c1c581fbc 100644 --- a/apm-collector/apm-collector-agentjvm/src/main/java/org/skywalking/apm/collector/agentjvm/worker/gc/dao/GCMetricH2DAO.java +++ b/apm-collector/apm-collector-agentjvm/src/main/java/org/skywalking/apm/collector/agentjvm/worker/gc/dao/GCMetricH2DAO.java @@ -18,10 +18,42 @@ package org.skywalking.apm.collector.agentjvm.worker.gc.dao; +import java.util.HashMap; +import java.util.Map; + +import org.skywalking.apm.collector.core.stream.Data; +import org.skywalking.apm.collector.storage.define.DataDefine; +import org.skywalking.apm.collector.storage.define.jvm.GCMetricTable; +import org.skywalking.apm.collector.storage.h2.SqlBuilder; import org.skywalking.apm.collector.storage.h2.dao.H2DAO; +import org.skywalking.apm.collector.storage.h2.define.H2SqlEntity; +import org.skywalking.apm.collector.stream.worker.impl.dao.IPersistenceDAO; /** - * @author pengys5 + * @author pengys5, clevertension */ -public class GCMetricH2DAO extends H2DAO implements IGCMetricDAO { +public class GCMetricH2DAO extends H2DAO implements IGCMetricDAO, IPersistenceDAO { + @Override public Data get(String id, DataDefine dataDefine) { + return null; + } + + @Override public H2SqlEntity prepareBatchInsert(Data data) { + H2SqlEntity entity = new H2SqlEntity(); + Map source = new HashMap<>(); + source.put("id", data.getDataString(0)); + source.put(GCMetricTable.COLUMN_INSTANCE_ID, data.getDataInteger(0)); + source.put(GCMetricTable.COLUMN_PHRASE, data.getDataInteger(1)); + source.put(GCMetricTable.COLUMN_COUNT, data.getDataLong(0)); + source.put(GCMetricTable.COLUMN_TIME, data.getDataLong(1)); + source.put(GCMetricTable.COLUMN_TIME_BUCKET, data.getDataLong(2)); + + String sql = SqlBuilder.buildBatchInsertSql(GCMetricTable.TABLE, source.keySet()); + entity.setSql(sql); + entity.setParams(source.values().toArray(new Object[0])); + return entity; + } + + @Override public H2SqlEntity prepareBatchUpdate(Data data) { + return null; + } } diff --git a/apm-collector/apm-collector-agentjvm/src/main/java/org/skywalking/apm/collector/agentjvm/worker/heartbeat/dao/InstanceHeartBeatH2DAO.java b/apm-collector/apm-collector-agentjvm/src/main/java/org/skywalking/apm/collector/agentjvm/worker/heartbeat/dao/InstanceHeartBeatH2DAO.java index 299797bad709996a372eda53188324fe913bb888..ecc7f5418063b2edbdf494ee00b8ad19b0a6d14a 100644 --- a/apm-collector/apm-collector-agentjvm/src/main/java/org/skywalking/apm/collector/agentjvm/worker/heartbeat/dao/InstanceHeartBeatH2DAO.java +++ b/apm-collector/apm-collector-agentjvm/src/main/java/org/skywalking/apm/collector/agentjvm/worker/heartbeat/dao/InstanceHeartBeatH2DAO.java @@ -18,10 +18,62 @@ package org.skywalking.apm.collector.agentjvm.worker.heartbeat.dao; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import org.skywalking.apm.collector.client.h2.H2Client; +import org.skywalking.apm.collector.client.h2.H2ClientException; +import org.skywalking.apm.collector.core.framework.UnexpectedException; +import org.skywalking.apm.collector.core.stream.Data; +import org.skywalking.apm.collector.storage.define.DataDefine; +import org.skywalking.apm.collector.storage.define.register.InstanceTable; +import org.skywalking.apm.collector.storage.h2.SqlBuilder; import org.skywalking.apm.collector.storage.h2.dao.H2DAO; +import org.skywalking.apm.collector.storage.h2.define.H2SqlEntity; +import org.skywalking.apm.collector.stream.worker.impl.dao.IPersistenceDAO; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; /** - * @author pengys5 + * @author pengys5, clevertension */ -public class InstanceHeartBeatH2DAO extends H2DAO implements IInstanceHeartBeatDAO { +public class InstanceHeartBeatH2DAO extends H2DAO implements IInstanceHeartBeatDAO, IPersistenceDAO { + private final Logger logger = LoggerFactory.getLogger(InstanceHeartBeatEsDAO.class); + private static final String GET_INSTANCE_HEARTBEAT_SQL = "select * from {0} where {1} = ?"; + @Override public Data get(String id, DataDefine dataDefine) { + H2Client client = getClient(); + String sql = SqlBuilder.buildSql(GET_INSTANCE_HEARTBEAT_SQL, InstanceTable.TABLE, InstanceTable.COLUMN_INSTANCE_ID); + Object[] params = new Object[]{id}; + try (ResultSet rs = client.executeQuery(sql, params)) { + if (rs.next()) { + Data data = dataDefine.build(id); + data.setDataInteger(0, rs.getInt(InstanceTable.COLUMN_INSTANCE_ID)); + data.setDataLong(0, rs.getLong(InstanceTable.COLUMN_HEARTBEAT_TIME)); + return data; + } + } catch (SQLException | H2ClientException e) { + logger.error(e.getMessage(), e); + } + return null; + } + + @Override public H2SqlEntity prepareBatchInsert(Data data) { + throw new UnexpectedException("There is no need to merge stream data with database data."); + } + + @Override public H2SqlEntity prepareBatchUpdate(Data data) { + H2SqlEntity entity = new H2SqlEntity(); + Map source = new HashMap<>(); + source.put(InstanceTable.COLUMN_HEARTBEAT_TIME, data.getDataLong(0)); + String sql = SqlBuilder.buildBatchUpdateSql(InstanceTable.TABLE, source.keySet(), InstanceTable.COLUMN_APPLICATION_ID); + entity.setSql(sql); + List params = new ArrayList<>(source.values()); + params.add(data.getDataString(0)); + entity.setParams(params.toArray(new Object[0])); + return entity; + } } diff --git a/apm-collector/apm-collector-agentjvm/src/main/java/org/skywalking/apm/collector/agentjvm/worker/memory/dao/MemoryMetricH2DAO.java b/apm-collector/apm-collector-agentjvm/src/main/java/org/skywalking/apm/collector/agentjvm/worker/memory/dao/MemoryMetricH2DAO.java index daf545e2b68ff012825bb5c6c73b0c338f4ff747..3d6fb0d4dd2bdc9d7043eb4ffc9c7893525a8d31 100644 --- a/apm-collector/apm-collector-agentjvm/src/main/java/org/skywalking/apm/collector/agentjvm/worker/memory/dao/MemoryMetricH2DAO.java +++ b/apm-collector/apm-collector-agentjvm/src/main/java/org/skywalking/apm/collector/agentjvm/worker/memory/dao/MemoryMetricH2DAO.java @@ -18,10 +18,44 @@ package org.skywalking.apm.collector.agentjvm.worker.memory.dao; +import java.util.HashMap; +import java.util.Map; + +import org.skywalking.apm.collector.core.stream.Data; +import org.skywalking.apm.collector.storage.define.DataDefine; +import org.skywalking.apm.collector.storage.define.jvm.MemoryMetricTable; +import org.skywalking.apm.collector.storage.h2.SqlBuilder; import org.skywalking.apm.collector.storage.h2.dao.H2DAO; +import org.skywalking.apm.collector.storage.h2.define.H2SqlEntity; +import org.skywalking.apm.collector.stream.worker.impl.dao.IPersistenceDAO; /** - * @author pengys5 + * @author pengys5, clevertension */ -public class MemoryMetricH2DAO extends H2DAO implements IMemoryMetricDAO { +public class MemoryMetricH2DAO extends H2DAO implements IMemoryMetricDAO, IPersistenceDAO { + @Override public Data get(String id, DataDefine dataDefine) { + return null; + } + + @Override public H2SqlEntity prepareBatchInsert(Data data) { + H2SqlEntity entity = new H2SqlEntity(); + Map source = new HashMap<>(); + source.put("id", data.getDataString(0)); + source.put(MemoryMetricTable.COLUMN_APPLICATION_INSTANCE_ID, data.getDataInteger(0)); + source.put(MemoryMetricTable.COLUMN_IS_HEAP, data.getDataBoolean(0)); + source.put(MemoryMetricTable.COLUMN_INIT, data.getDataLong(0)); + source.put(MemoryMetricTable.COLUMN_MAX, data.getDataLong(1)); + source.put(MemoryMetricTable.COLUMN_USED, data.getDataLong(2)); + source.put(MemoryMetricTable.COLUMN_COMMITTED, data.getDataLong(3)); + source.put(MemoryMetricTable.COLUMN_TIME_BUCKET, data.getDataLong(4)); + + String sql = SqlBuilder.buildBatchInsertSql(MemoryMetricTable.TABLE, source.keySet()); + entity.setSql(sql); + entity.setParams(source.values().toArray(new Object[0])); + return entity; + } + + @Override public H2SqlEntity prepareBatchUpdate(Data data) { + return null; + } } diff --git a/apm-collector/apm-collector-agentjvm/src/main/java/org/skywalking/apm/collector/agentjvm/worker/memorypool/dao/MemoryPoolMetricH2DAO.java b/apm-collector/apm-collector-agentjvm/src/main/java/org/skywalking/apm/collector/agentjvm/worker/memorypool/dao/MemoryPoolMetricH2DAO.java index 478455d24727d7eda68245a1142c442d923efffb..8ecfe5ab5c56eafca090173e2d66bf9d81d03929 100644 --- a/apm-collector/apm-collector-agentjvm/src/main/java/org/skywalking/apm/collector/agentjvm/worker/memorypool/dao/MemoryPoolMetricH2DAO.java +++ b/apm-collector/apm-collector-agentjvm/src/main/java/org/skywalking/apm/collector/agentjvm/worker/memorypool/dao/MemoryPoolMetricH2DAO.java @@ -18,10 +18,44 @@ package org.skywalking.apm.collector.agentjvm.worker.memorypool.dao; +import java.util.HashMap; +import java.util.Map; + +import org.skywalking.apm.collector.core.stream.Data; +import org.skywalking.apm.collector.storage.define.DataDefine; +import org.skywalking.apm.collector.storage.define.jvm.MemoryPoolMetricTable; +import org.skywalking.apm.collector.storage.h2.SqlBuilder; import org.skywalking.apm.collector.storage.h2.dao.H2DAO; +import org.skywalking.apm.collector.storage.h2.define.H2SqlEntity; +import org.skywalking.apm.collector.stream.worker.impl.dao.IPersistenceDAO; /** - * @author pengys5 + * @author pengys5, clevertension */ -public class MemoryPoolMetricH2DAO extends H2DAO implements IMemoryPoolMetricDAO { +public class MemoryPoolMetricH2DAO extends H2DAO implements IMemoryPoolMetricDAO, IPersistenceDAO { + @Override public Data get(String id, DataDefine dataDefine) { + return null; + } + + @Override public H2SqlEntity prepareBatchInsert(Data data) { + H2SqlEntity entity = new H2SqlEntity(); + Map source = new HashMap<>(); + source.put("id", data.getDataString(0)); + source.put(MemoryPoolMetricTable.COLUMN_INSTANCE_ID, data.getDataInteger(0)); + source.put(MemoryPoolMetricTable.COLUMN_POOL_TYPE, data.getDataInteger(1)); + source.put(MemoryPoolMetricTable.COLUMN_INIT, data.getDataLong(0)); + source.put(MemoryPoolMetricTable.COLUMN_MAX, data.getDataLong(1)); + source.put(MemoryPoolMetricTable.COLUMN_USED, data.getDataLong(2)); + source.put(MemoryPoolMetricTable.COLUMN_COMMITTED, data.getDataLong(3)); + source.put(MemoryPoolMetricTable.COLUMN_TIME_BUCKET, data.getDataLong(4)); + + String sql = SqlBuilder.buildBatchInsertSql(MemoryPoolMetricTable.TABLE, source.keySet()); + entity.setSql(sql); + entity.setParams(source.values().toArray(new Object[0])); + return entity; + } + + @Override public H2SqlEntity prepareBatchUpdate(Data data) { + return null; + } } diff --git a/apm-collector/apm-collector-agentregister/src/main/java/org/skywalking/apm/collector/agentregister/worker/application/dao/ApplicationH2DAO.java b/apm-collector/apm-collector-agentregister/src/main/java/org/skywalking/apm/collector/agentregister/worker/application/dao/ApplicationH2DAO.java index 2336cb46f20d7ce1a3598fbc9f76fe9ecd06f759..e63ceb38b4172a642786fa6ba906e4ad8f2a9187 100644 --- a/apm-collector/apm-collector-agentregister/src/main/java/org/skywalking/apm/collector/agentregister/worker/application/dao/ApplicationH2DAO.java +++ b/apm-collector/apm-collector-agentregister/src/main/java/org/skywalking/apm/collector/agentregister/worker/application/dao/ApplicationH2DAO.java @@ -18,23 +18,42 @@ package org.skywalking.apm.collector.agentregister.worker.application.dao; +import org.skywalking.apm.collector.client.h2.H2Client; +import org.skywalking.apm.collector.client.h2.H2ClientException; import org.skywalking.apm.collector.storage.define.register.ApplicationDataDefine; +import org.skywalking.apm.collector.storage.define.register.ApplicationTable; +import org.skywalking.apm.collector.storage.h2.SqlBuilder; import org.skywalking.apm.collector.storage.h2.dao.H2DAO; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; /** - * @author pengys5 + * @author pengys5, clevertension */ public class ApplicationH2DAO extends H2DAO implements IApplicationDAO { + private final Logger logger = LoggerFactory.getLogger(ApplicationH2DAO.class); + private static final String INSERT_APPLICATION_SQL = "insert into {0}({1}, {2}) values(?, ?)"; - @Override public int getMaxApplicationId() { - return 0; + @Override + public int getMaxApplicationId() { + return getMaxId(ApplicationTable.TABLE, ApplicationTable.COLUMN_APPLICATION_ID); } - @Override public int getMinApplicationId() { - return 0; + @Override + public int getMinApplicationId() { + return getMinId(ApplicationTable.TABLE, ApplicationTable.COLUMN_APPLICATION_ID); } - @Override public void save(ApplicationDataDefine.Application application) { - + @Override + public void save(ApplicationDataDefine.Application application) { + H2Client client = getClient(); + String sql = SqlBuilder.buildSql(INSERT_APPLICATION_SQL, ApplicationTable.TABLE, ApplicationTable.COLUMN_APPLICATION_ID, + ApplicationTable.COLUMN_APPLICATION_CODE); + Object[] params = new Object[] {application.getApplicationId(), application.getApplicationCode()}; + try { + client.execute(sql, params); + } catch (H2ClientException e) { + logger.error(e.getMessage(), e); + } } } diff --git a/apm-collector/apm-collector-agentregister/src/main/java/org/skywalking/apm/collector/agentregister/worker/instance/dao/InstanceH2DAO.java b/apm-collector/apm-collector-agentregister/src/main/java/org/skywalking/apm/collector/agentregister/worker/instance/dao/InstanceH2DAO.java index 6acaaa964768341c81fa3d2279ee346b4215de61..11cc4f35c09e75131c7b383f2e40674ad0986300 100644 --- a/apm-collector/apm-collector-agentregister/src/main/java/org/skywalking/apm/collector/agentregister/worker/instance/dao/InstanceH2DAO.java +++ b/apm-collector/apm-collector-agentregister/src/main/java/org/skywalking/apm/collector/agentregister/worker/instance/dao/InstanceH2DAO.java @@ -18,31 +18,79 @@ package org.skywalking.apm.collector.agentregister.worker.instance.dao; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.util.HashMap; +import java.util.Map; +import org.skywalking.apm.collector.client.h2.H2Client; +import org.skywalking.apm.collector.client.h2.H2ClientException; import org.skywalking.apm.collector.storage.define.register.InstanceDataDefine; +import org.skywalking.apm.collector.storage.define.register.InstanceTable; +import org.skywalking.apm.collector.storage.h2.SqlBuilder; import org.skywalking.apm.collector.storage.h2.dao.H2DAO; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; /** - * @author pengys5 + * @author pengys5, clevertension */ public class InstanceH2DAO extends H2DAO implements IInstanceDAO { + private final Logger logger = LoggerFactory.getLogger(InstanceH2DAO.class); + + private static final String GET_INSTANCE_ID_SQL = "select {0} from {1} where {2} = ? and {3} = ?"; + private static final String UPDATE_HEARTBEAT_TIME_SQL = "updatte {0} set {1} = ? where {2} = ?"; @Override public int getInstanceId(int applicationId, String agentUUID) { + logger.info("get the application id with application id = {}, agentUUID = {}", applicationId, agentUUID); + H2Client client = getClient(); + String sql = SqlBuilder.buildSql(GET_INSTANCE_ID_SQL, InstanceTable.COLUMN_INSTANCE_ID, InstanceTable.TABLE, InstanceTable.COLUMN_APPLICATION_ID, + InstanceTable.COLUMN_AGENT_UUID); + Object[] params = new Object[] {applicationId, agentUUID}; + try (ResultSet rs = client.executeQuery(sql, params)) { + if (rs.next()) { + return rs.getInt(InstanceTable.COLUMN_INSTANCE_ID); + } + } catch (SQLException | H2ClientException e) { + logger.error(e.getMessage(), e); + } return 0; } @Override public int getMaxInstanceId() { - return 0; + return getMaxId(InstanceTable.TABLE, InstanceTable.COLUMN_INSTANCE_ID); } @Override public int getMinInstanceId() { - return 0; + return getMinId(InstanceTable.TABLE, InstanceTable.COLUMN_INSTANCE_ID); } @Override public void save(InstanceDataDefine.Instance instance) { - + H2Client client = getClient(); + Map source = new HashMap<>(); + source.put(InstanceTable.COLUMN_INSTANCE_ID, instance.getInstanceId()); + source.put(InstanceTable.COLUMN_APPLICATION_ID, instance.getApplicationId()); + source.put(InstanceTable.COLUMN_AGENT_UUID, instance.getAgentUUID()); + source.put(InstanceTable.COLUMN_REGISTER_TIME, instance.getRegisterTime()); + source.put(InstanceTable.COLUMN_HEARTBEAT_TIME, instance.getHeartBeatTime()); + source.put(InstanceTable.COLUMN_OS_INFO, instance.getOsInfo()); + String sql = SqlBuilder.buildBatchInsertSql(InstanceTable.TABLE, source.keySet()); + Object[] params = source.values().toArray(new Object[0]); + try { + client.execute(sql, params); + } catch (H2ClientException e) { + logger.error(e.getMessage(), e); + } } @Override public void updateHeartbeatTime(int instanceId, long heartbeatTime) { - + H2Client client = getClient(); + String sql = SqlBuilder.buildSql(UPDATE_HEARTBEAT_TIME_SQL, InstanceTable.TABLE, InstanceTable.COLUMN_HEARTBEAT_TIME, + InstanceTable.COLUMN_INSTANCE_ID); + Object[] params = new Object[] {heartbeatTime, instanceId}; + try { + client.execute(sql, params); + } catch (H2ClientException e) { + logger.error(e.getMessage(), e); + } } } diff --git a/apm-collector/apm-collector-agentregister/src/main/java/org/skywalking/apm/collector/agentregister/worker/servicename/dao/ServiceNameH2DAO.java b/apm-collector/apm-collector-agentregister/src/main/java/org/skywalking/apm/collector/agentregister/worker/servicename/dao/ServiceNameH2DAO.java index b0c87a3d24ba7da372197c900e68ab887f95a998..b224a578ef2dcd73f2ea1e9517ffdc4cb1cd841b 100644 --- a/apm-collector/apm-collector-agentregister/src/main/java/org/skywalking/apm/collector/agentregister/worker/servicename/dao/ServiceNameH2DAO.java +++ b/apm-collector/apm-collector-agentregister/src/main/java/org/skywalking/apm/collector/agentregister/worker/servicename/dao/ServiceNameH2DAO.java @@ -18,23 +18,48 @@ package org.skywalking.apm.collector.agentregister.worker.servicename.dao; +import java.util.HashMap; +import java.util.Map; +import org.skywalking.apm.collector.client.h2.H2Client; +import org.skywalking.apm.collector.client.h2.H2ClientException; import org.skywalking.apm.collector.storage.define.register.ServiceNameDataDefine; +import org.skywalking.apm.collector.storage.define.register.ServiceNameTable; +import org.skywalking.apm.collector.storage.h2.SqlBuilder; import org.skywalking.apm.collector.storage.h2.dao.H2DAO; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; /** - * @author pengys5 + * @author pengys5, clevertension */ public class ServiceNameH2DAO extends H2DAO implements IServiceNameDAO { + private final Logger logger = LoggerFactory.getLogger(ServiceNameH2DAO.class); - @Override public int getMaxServiceId() { - return 0; + @Override + public int getMaxServiceId() { + return getMaxId(ServiceNameTable.TABLE, ServiceNameTable.COLUMN_SERVICE_ID); } - @Override public int getMinServiceId() { - return 0; + @Override + public int getMinServiceId() { + return getMinId(ServiceNameTable.TABLE, ServiceNameTable.COLUMN_SERVICE_ID); } - @Override public void save(ServiceNameDataDefine.ServiceName serviceName) { + @Override + public void save(ServiceNameDataDefine.ServiceName serviceName) { + logger.debug("save service name register info, application id: {}, service name: {}", serviceName.getApplicationId(), serviceName.getServiceName()); + H2Client client = getClient(); + Map source = new HashMap<>(); + source.put(ServiceNameTable.COLUMN_SERVICE_ID, serviceName.getServiceId()); + source.put(ServiceNameTable.COLUMN_APPLICATION_ID, serviceName.getApplicationId()); + source.put(ServiceNameTable.COLUMN_SERVICE_NAME, serviceName.getServiceName()); + String sql = SqlBuilder.buildBatchInsertSql(ServiceNameTable.TABLE, source.keySet()); + Object[] params = source.values().toArray(new Object[0]); + try { + client.execute(sql, params); + } catch (H2ClientException e) { + logger.error(e.getMessage(), e); + } } } diff --git a/apm-collector/apm-collector-agentstream/src/main/java/org/skywalking/apm/collector/agentstream/worker/global/dao/GlobalTraceH2DAO.java b/apm-collector/apm-collector-agentstream/src/main/java/org/skywalking/apm/collector/agentstream/worker/global/dao/GlobalTraceH2DAO.java index 8a40e6505d045087b3fd997d1c227ea4adecdf10..24cc79424ca5064884dd260dbbe0557a01308691 100644 --- a/apm-collector/apm-collector-agentstream/src/main/java/org/skywalking/apm/collector/agentstream/worker/global/dao/GlobalTraceH2DAO.java +++ b/apm-collector/apm-collector-agentstream/src/main/java/org/skywalking/apm/collector/agentstream/worker/global/dao/GlobalTraceH2DAO.java @@ -18,10 +18,45 @@ package org.skywalking.apm.collector.agentstream.worker.global.dao; +import org.skywalking.apm.collector.core.framework.UnexpectedException; +import org.skywalking.apm.collector.core.stream.Data; +import org.skywalking.apm.collector.storage.define.DataDefine; +import org.skywalking.apm.collector.storage.define.global.GlobalTraceTable; +import org.skywalking.apm.collector.storage.h2.SqlBuilder; import org.skywalking.apm.collector.storage.h2.dao.H2DAO; +import org.skywalking.apm.collector.storage.h2.define.H2SqlEntity; +import org.skywalking.apm.collector.stream.worker.impl.dao.IPersistenceDAO; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.HashMap; +import java.util.Map; /** - * @author pengys5 + * @author pengys5, clevertension */ -public class GlobalTraceH2DAO extends H2DAO implements IGlobalTraceDAO { +public class GlobalTraceH2DAO extends H2DAO implements IGlobalTraceDAO, IPersistenceDAO { + private final Logger logger = LoggerFactory.getLogger(GlobalTraceH2DAO.class); + @Override public Data get(String id, DataDefine dataDefine) { + throw new UnexpectedException("There is no need to merge stream data with database data."); + } + + @Override public H2SqlEntity prepareBatchUpdate(Data data) { + throw new UnexpectedException("There is no need to merge stream data with database data."); + } + + @Override public H2SqlEntity prepareBatchInsert(Data data) { + Map source = new HashMap<>(); + H2SqlEntity entity = new H2SqlEntity(); + source.put("id", data.getDataString(0)); + source.put(GlobalTraceTable.COLUMN_SEGMENT_ID, data.getDataString(1)); + source.put(GlobalTraceTable.COLUMN_GLOBAL_TRACE_ID, data.getDataString(2)); + source.put(GlobalTraceTable.COLUMN_TIME_BUCKET, data.getDataLong(0)); + logger.debug("global trace source: {}", source.toString()); + + String sql = SqlBuilder.buildBatchInsertSql(GlobalTraceTable.TABLE, source.keySet()); + entity.setSql(sql); + entity.setParams(source.values().toArray(new Object[0])); + return entity; + } } diff --git a/apm-collector/apm-collector-agentstream/src/main/java/org/skywalking/apm/collector/agentstream/worker/instance/performance/dao/InstPerformanceH2DAO.java b/apm-collector/apm-collector-agentstream/src/main/java/org/skywalking/apm/collector/agentstream/worker/instance/performance/dao/InstPerformanceH2DAO.java index f3b197d089eb107d0f99df94728210fc461c622d..578da83d203aa49938efaebe27eda7fba4028277 100644 --- a/apm-collector/apm-collector-agentstream/src/main/java/org/skywalking/apm/collector/agentstream/worker/instance/performance/dao/InstPerformanceH2DAO.java +++ b/apm-collector/apm-collector-agentstream/src/main/java/org/skywalking/apm/collector/agentstream/worker/instance/performance/dao/InstPerformanceH2DAO.java @@ -18,11 +18,78 @@ package org.skywalking.apm.collector.agentstream.worker.instance.performance.dao; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import org.skywalking.apm.collector.client.h2.H2Client; +import org.skywalking.apm.collector.client.h2.H2ClientException; +import org.skywalking.apm.collector.core.stream.Data; +import org.skywalking.apm.collector.storage.define.DataDefine; +import org.skywalking.apm.collector.storage.define.instance.InstPerformanceTable; +import org.skywalking.apm.collector.storage.h2.SqlBuilder; import org.skywalking.apm.collector.storage.h2.dao.H2DAO; +import org.skywalking.apm.collector.storage.h2.define.H2SqlEntity; +import org.skywalking.apm.collector.stream.worker.impl.dao.IPersistenceDAO; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; /** - * @author pengys5 + * @author pengys5, clevertension */ -public class InstPerformanceH2DAO extends H2DAO implements IInstPerformanceDAO { - +public class InstPerformanceH2DAO extends H2DAO implements IInstPerformanceDAO, IPersistenceDAO { + private final Logger logger = LoggerFactory.getLogger(InstPerformanceH2DAO.class); + private static final String GET_SQL = "select * from {0} where {1} = ?"; + @Override public Data get(String id, DataDefine dataDefine) { + H2Client client = getClient(); + String sql = SqlBuilder.buildSql(GET_SQL, InstPerformanceTable.TABLE, "id"); + Object[] params = new Object[]{id}; + try (ResultSet rs = client.executeQuery(sql, params)) { + if (rs.next()) { + Data data = dataDefine.build(id); + data.setDataInteger(0, rs.getInt(InstPerformanceTable.COLUMN_APPLICATION_ID)); + data.setDataInteger(1, rs.getInt(InstPerformanceTable.COLUMN_INSTANCE_ID)); + data.setDataInteger(2, rs.getInt(InstPerformanceTable.COLUMN_CALLS)); + data.setDataLong(0, rs.getLong(InstPerformanceTable.COLUMN_COST_TOTAL)); + data.setDataLong(1, rs.getLong(InstPerformanceTable.COLUMN_TIME_BUCKET)); + return data; + } + } catch (SQLException | H2ClientException e) { + logger.error(e.getMessage(), e); + } + return null; + } + @Override public H2SqlEntity prepareBatchInsert(Data data) { + Map source = new HashMap<>(); + H2SqlEntity entity = new H2SqlEntity(); + source.put("id", data.getDataString(0)); + source.put(InstPerformanceTable.COLUMN_APPLICATION_ID, data.getDataInteger(0)); + source.put(InstPerformanceTable.COLUMN_INSTANCE_ID, data.getDataInteger(1)); + source.put(InstPerformanceTable.COLUMN_CALLS, data.getDataInteger(2)); + source.put(InstPerformanceTable.COLUMN_COST_TOTAL, data.getDataLong(0)); + source.put(InstPerformanceTable.COLUMN_TIME_BUCKET, data.getDataLong(1)); + String sql = SqlBuilder.buildBatchInsertSql(InstPerformanceTable.TABLE, source.keySet()); + entity.setSql(sql); + entity.setParams(source.values().toArray(new Object[0])); + return entity; + } + @Override public H2SqlEntity prepareBatchUpdate(Data data) { + Map source = new HashMap<>(); + H2SqlEntity entity = new H2SqlEntity(); + source.put(InstPerformanceTable.COLUMN_APPLICATION_ID, data.getDataInteger(0)); + source.put(InstPerformanceTable.COLUMN_INSTANCE_ID, data.getDataInteger(1)); + source.put(InstPerformanceTable.COLUMN_CALLS, data.getDataInteger(2)); + source.put(InstPerformanceTable.COLUMN_COST_TOTAL, data.getDataLong(0)); + source.put(InstPerformanceTable.COLUMN_TIME_BUCKET, data.getDataLong(1)); + String id = data.getDataString(0); + String sql = SqlBuilder.buildBatchUpdateSql(InstPerformanceTable.TABLE, source.keySet(), "id"); + entity.setSql(sql); + List values = new ArrayList<>(source.values()); + values.add(id); + entity.setParams(values.toArray(new Object[0])); + return entity; + } } diff --git a/apm-collector/apm-collector-agentstream/src/main/java/org/skywalking/apm/collector/agentstream/worker/node/component/dao/NodeComponentH2DAO.java b/apm-collector/apm-collector-agentstream/src/main/java/org/skywalking/apm/collector/agentstream/worker/node/component/dao/NodeComponentH2DAO.java index d727a31ae13ef284b6ed10db4aede49341377c9a..e44b263df5507a4c71853c1e146e865900d45b1d 100644 --- a/apm-collector/apm-collector-agentstream/src/main/java/org/skywalking/apm/collector/agentstream/worker/node/component/dao/NodeComponentH2DAO.java +++ b/apm-collector/apm-collector-agentstream/src/main/java/org/skywalking/apm/collector/agentstream/worker/node/component/dao/NodeComponentH2DAO.java @@ -18,11 +18,86 @@ package org.skywalking.apm.collector.agentstream.worker.node.component.dao; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import org.skywalking.apm.collector.client.h2.H2Client; +import org.skywalking.apm.collector.client.h2.H2ClientException; +import org.skywalking.apm.collector.core.stream.Data; +import org.skywalking.apm.collector.storage.define.DataDefine; +import org.skywalking.apm.collector.storage.define.node.NodeComponentTable; +import org.skywalking.apm.collector.storage.define.serviceref.ServiceReferenceTable; +import org.skywalking.apm.collector.storage.h2.SqlBuilder; import org.skywalking.apm.collector.storage.h2.dao.H2DAO; +import org.skywalking.apm.collector.storage.h2.define.H2SqlEntity; +import org.skywalking.apm.collector.stream.worker.impl.dao.IPersistenceDAO; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; /** - * @author pengys5 + * @author pengys5, clevertension */ -public class NodeComponentH2DAO extends H2DAO implements INodeComponentDAO { +public class NodeComponentH2DAO extends H2DAO implements INodeComponentDAO, IPersistenceDAO { + private final Logger logger = LoggerFactory.getLogger(NodeComponentH2DAO.class); + private static final String GET_SQL = "select * from {0} where {1} = ?"; + + @Override + public Data get(String id, DataDefine dataDefine) { + H2Client client = getClient(); + String sql = SqlBuilder.buildSql(GET_SQL, ServiceReferenceTable.TABLE, "id"); + Object[] params = new Object[]{id}; + try (ResultSet rs = client.executeQuery(sql, params)) { + if (rs.next()) { + Data data = dataDefine.build(id); + data.setDataInteger(0, rs.getInt(NodeComponentTable.COLUMN_COMPONENT_ID)); + data.setDataString(1, rs.getString(NodeComponentTable.COLUMN_COMPONENT_NAME)); + data.setDataInteger(1, rs.getInt(NodeComponentTable.COLUMN_PEER_ID)); + data.setDataString(2, rs.getString(NodeComponentTable.COLUMN_PEER)); + data.setDataLong(0, rs.getLong(NodeComponentTable.COLUMN_TIME_BUCKET)); + return data; + } + } catch (SQLException | H2ClientException e) { + logger.error(e.getMessage(), e); + } + return null; + } + + @Override + public H2SqlEntity prepareBatchInsert(Data data) { + Map source = new HashMap<>(); + H2SqlEntity entity = new H2SqlEntity(); + source.put("id", data.getDataString(0)); + source.put(NodeComponentTable.COLUMN_COMPONENT_ID, data.getDataInteger(0)); + source.put(NodeComponentTable.COLUMN_COMPONENT_NAME, data.getDataString(1)); + source.put(NodeComponentTable.COLUMN_PEER_ID, data.getDataInteger(1)); + source.put(NodeComponentTable.COLUMN_PEER, data.getDataString(2)); + source.put(NodeComponentTable.COLUMN_TIME_BUCKET, data.getDataLong(0)); + + String sql = SqlBuilder.buildBatchInsertSql(NodeComponentTable.TABLE, source.keySet()); + entity.setSql(sql); + entity.setParams(source.values().toArray(new Object[0])); + return entity; + } + @Override + public H2SqlEntity prepareBatchUpdate(Data data) { + Map source = new HashMap<>(); + H2SqlEntity entity = new H2SqlEntity(); + source.put(NodeComponentTable.COLUMN_COMPONENT_ID, data.getDataInteger(0)); + source.put(NodeComponentTable.COLUMN_COMPONENT_NAME, data.getDataString(1)); + source.put(NodeComponentTable.COLUMN_PEER_ID, data.getDataInteger(1)); + source.put(NodeComponentTable.COLUMN_PEER, data.getDataString(2)); + source.put(NodeComponentTable.COLUMN_TIME_BUCKET, data.getDataLong(0)); + String id = data.getDataString(0); + String sql = SqlBuilder.buildBatchUpdateSql(NodeComponentTable.TABLE, source.keySet(), "id"); + entity.setSql(sql); + List values = new ArrayList<>(source.values()); + values.add(id); + entity.setParams(values.toArray(new Object[0])); + return entity; + } } diff --git a/apm-collector/apm-collector-agentstream/src/main/java/org/skywalking/apm/collector/agentstream/worker/node/mapping/dao/NodeMappingH2DAO.java b/apm-collector/apm-collector-agentstream/src/main/java/org/skywalking/apm/collector/agentstream/worker/node/mapping/dao/NodeMappingH2DAO.java index 064c901c780c3bb68d35c85453b33a4f3a521656..3805ad9af03a1c676265d36df1068a2ce43133ce 100644 --- a/apm-collector/apm-collector-agentstream/src/main/java/org/skywalking/apm/collector/agentstream/worker/node/mapping/dao/NodeMappingH2DAO.java +++ b/apm-collector/apm-collector-agentstream/src/main/java/org/skywalking/apm/collector/agentstream/worker/node/mapping/dao/NodeMappingH2DAO.java @@ -18,10 +18,77 @@ package org.skywalking.apm.collector.agentstream.worker.node.mapping.dao; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import org.skywalking.apm.collector.agentstream.worker.node.component.dao.NodeComponentH2DAO; +import org.skywalking.apm.collector.client.h2.H2Client; +import org.skywalking.apm.collector.client.h2.H2ClientException; +import org.skywalking.apm.collector.core.stream.Data; +import org.skywalking.apm.collector.storage.define.DataDefine; +import org.skywalking.apm.collector.storage.define.node.NodeMappingTable; +import org.skywalking.apm.collector.storage.h2.SqlBuilder; import org.skywalking.apm.collector.storage.h2.dao.H2DAO; +import org.skywalking.apm.collector.storage.h2.define.H2SqlEntity; +import org.skywalking.apm.collector.stream.worker.impl.dao.IPersistenceDAO; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; /** - * @author pengys5 + * @author pengys5, clevertension */ -public class NodeMappingH2DAO extends H2DAO implements INodeMappingDAO { +public class NodeMappingH2DAO extends H2DAO implements INodeMappingDAO, IPersistenceDAO { + private final Logger logger = LoggerFactory.getLogger(NodeComponentH2DAO.class); + private static final String GET_SQL = "select * from {0} where {1} = ?"; + @Override public Data get(String id, DataDefine dataDefine) { + H2Client client = getClient(); + String sql = SqlBuilder.buildSql(GET_SQL, NodeMappingTable.TABLE, "id"); + Object[] params = new Object[]{id}; + try (ResultSet rs = client.executeQuery(sql, params)) { + if (rs.next()) { + Data data = dataDefine.build(id); + data.setDataInteger(0, rs.getInt(NodeMappingTable.COLUMN_APPLICATION_ID)); + data.setDataInteger(1, rs.getInt(NodeMappingTable.COLUMN_ADDRESS_ID)); + data.setDataString(1, rs.getString(NodeMappingTable.COLUMN_ADDRESS)); + data.setDataLong(0, rs.getLong(NodeMappingTable.COLUMN_TIME_BUCKET)); + return data; + } + } catch (SQLException | H2ClientException e) { + logger.error(e.getMessage(), e); + } + return null; + } + @Override public H2SqlEntity prepareBatchInsert(Data data) { + Map source = new HashMap<>(); + H2SqlEntity entity = new H2SqlEntity(); + source.put("id", data.getDataString(0)); + source.put(NodeMappingTable.COLUMN_APPLICATION_ID, data.getDataInteger(0)); + source.put(NodeMappingTable.COLUMN_ADDRESS_ID, data.getDataInteger(1)); + source.put(NodeMappingTable.COLUMN_ADDRESS, data.getDataString(1)); + source.put(NodeMappingTable.COLUMN_TIME_BUCKET, data.getDataLong(0)); + String sql = SqlBuilder.buildBatchInsertSql(NodeMappingTable.TABLE, source.keySet()); + entity.setSql(sql); + + entity.setParams(source.values().toArray(new Object[0])); + return entity; + } + @Override public H2SqlEntity prepareBatchUpdate(Data data) { + Map source = new HashMap<>(); + H2SqlEntity entity = new H2SqlEntity(); + source.put(NodeMappingTable.COLUMN_APPLICATION_ID, data.getDataInteger(0)); + source.put(NodeMappingTable.COLUMN_ADDRESS_ID, data.getDataInteger(1)); + source.put(NodeMappingTable.COLUMN_ADDRESS, data.getDataString(1)); + source.put(NodeMappingTable.COLUMN_TIME_BUCKET, data.getDataLong(0)); + String id = data.getDataString(0); + String sql = SqlBuilder.buildBatchUpdateSql(NodeMappingTable.TABLE, source.keySet(), "id"); + entity.setSql(sql); + List values = new ArrayList<>(source.values()); + values.add(id); + entity.setParams(values.toArray(new Object[0])); + return entity; + } } diff --git a/apm-collector/apm-collector-agentstream/src/main/java/org/skywalking/apm/collector/agentstream/worker/noderef/dao/NodeReferenceH2DAO.java b/apm-collector/apm-collector-agentstream/src/main/java/org/skywalking/apm/collector/agentstream/worker/noderef/dao/NodeReferenceH2DAO.java index 00bdbd8b82a370ac16d4b6950d05d12e59a6c954..da6957b9f0b6e9fe02d556b74c8cbb4a615c43d8 100644 --- a/apm-collector/apm-collector-agentstream/src/main/java/org/skywalking/apm/collector/agentstream/worker/noderef/dao/NodeReferenceH2DAO.java +++ b/apm-collector/apm-collector-agentstream/src/main/java/org/skywalking/apm/collector/agentstream/worker/noderef/dao/NodeReferenceH2DAO.java @@ -18,10 +18,94 @@ package org.skywalking.apm.collector.agentstream.worker.noderef.dao; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import org.skywalking.apm.collector.client.h2.H2Client; +import org.skywalking.apm.collector.client.h2.H2ClientException; +import org.skywalking.apm.collector.core.stream.Data; +import org.skywalking.apm.collector.storage.define.DataDefine; +import org.skywalking.apm.collector.storage.define.noderef.NodeReferenceTable; +import org.skywalking.apm.collector.storage.h2.SqlBuilder; import org.skywalking.apm.collector.storage.h2.dao.H2DAO; +import org.skywalking.apm.collector.storage.h2.define.H2SqlEntity; +import org.skywalking.apm.collector.stream.worker.impl.dao.IPersistenceDAO; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; /** - * @author pengys5 + * @author pengys5, clevertension */ -public class NodeReferenceH2DAO extends H2DAO implements INodeReferenceDAO { +public class NodeReferenceH2DAO extends H2DAO implements INodeReferenceDAO, IPersistenceDAO { + private final Logger logger = LoggerFactory.getLogger(NodeReferenceH2DAO.class); + private static final String GET_SQL = "select * from {0} where {1} = ?"; + @Override public Data get(String id, DataDefine dataDefine) { + H2Client client = getClient(); + String sql = SqlBuilder.buildSql(GET_SQL, NodeReferenceTable.TABLE, "id"); + Object[] params = new Object[]{id}; + try (ResultSet rs = client.executeQuery(sql, params)) { + if (rs.next()) { + Data data = dataDefine.build(id); + data.setDataInteger(0, rs.getInt(NodeReferenceTable.COLUMN_FRONT_APPLICATION_ID)); + data.setDataInteger(1, rs.getInt(NodeReferenceTable.COLUMN_BEHIND_APPLICATION_ID)); + data.setDataString(1, rs.getString(NodeReferenceTable.COLUMN_BEHIND_PEER)); + data.setDataInteger(2, rs.getInt(NodeReferenceTable.COLUMN_S1_LTE)); + data.setDataInteger(3, rs.getInt(NodeReferenceTable.COLUMN_S3_LTE)); + data.setDataInteger(4, rs.getInt(NodeReferenceTable.COLUMN_S5_LTE)); + data.setDataInteger(5, rs.getInt(NodeReferenceTable.COLUMN_S5_GT)); + data.setDataInteger(6, rs.getInt(NodeReferenceTable.COLUMN_SUMMARY)); + data.setDataInteger(7, rs.getInt(NodeReferenceTable.COLUMN_ERROR)); + data.setDataLong(0, rs.getLong(NodeReferenceTable.COLUMN_TIME_BUCKET)); + return data; + } + } catch (SQLException | H2ClientException e) { + logger.error(e.getMessage(), e); + } + return null; + } + @Override public H2SqlEntity prepareBatchInsert(Data data) { + Map source = new HashMap<>(); + H2SqlEntity entity = new H2SqlEntity(); + source.put("id", data.getDataString(0)); + source.put(NodeReferenceTable.COLUMN_FRONT_APPLICATION_ID, data.getDataInteger(0)); + source.put(NodeReferenceTable.COLUMN_BEHIND_APPLICATION_ID, data.getDataInteger(1)); + source.put(NodeReferenceTable.COLUMN_BEHIND_PEER, data.getDataString(1)); + source.put(NodeReferenceTable.COLUMN_S1_LTE, data.getDataInteger(2)); + source.put(NodeReferenceTable.COLUMN_S3_LTE, data.getDataInteger(3)); + source.put(NodeReferenceTable.COLUMN_S5_LTE, data.getDataInteger(4)); + source.put(NodeReferenceTable.COLUMN_S5_GT, data.getDataInteger(5)); + source.put(NodeReferenceTable.COLUMN_SUMMARY, data.getDataInteger(6)); + source.put(NodeReferenceTable.COLUMN_ERROR, data.getDataInteger(7)); + source.put(NodeReferenceTable.COLUMN_TIME_BUCKET, data.getDataLong(0)); + String sql = SqlBuilder.buildBatchInsertSql(NodeReferenceTable.TABLE, source.keySet()); + entity.setSql(sql); + + entity.setParams(source.values().toArray(new Object[0])); + return entity; + } + @Override public H2SqlEntity prepareBatchUpdate(Data data) { + Map source = new HashMap<>(); + H2SqlEntity entity = new H2SqlEntity(); + source.put(NodeReferenceTable.COLUMN_FRONT_APPLICATION_ID, data.getDataInteger(0)); + source.put(NodeReferenceTable.COLUMN_BEHIND_APPLICATION_ID, data.getDataInteger(1)); + source.put(NodeReferenceTable.COLUMN_BEHIND_PEER, data.getDataString(1)); + source.put(NodeReferenceTable.COLUMN_S1_LTE, data.getDataInteger(2)); + source.put(NodeReferenceTable.COLUMN_S3_LTE, data.getDataInteger(3)); + source.put(NodeReferenceTable.COLUMN_S5_LTE, data.getDataInteger(4)); + source.put(NodeReferenceTable.COLUMN_S5_GT, data.getDataInteger(5)); + source.put(NodeReferenceTable.COLUMN_SUMMARY, data.getDataInteger(6)); + source.put(NodeReferenceTable.COLUMN_ERROR, data.getDataInteger(7)); + source.put(NodeReferenceTable.COLUMN_TIME_BUCKET, data.getDataLong(0)); + String id = data.getDataString(0); + String sql = SqlBuilder.buildBatchUpdateSql(NodeReferenceTable.TABLE, source.keySet(), "id"); + entity.setSql(sql); + List values = new ArrayList<>(source.values()); + values.add(id); + entity.setParams(values.toArray(new Object[0])); + return entity; + } } diff --git a/apm-collector/apm-collector-agentstream/src/main/java/org/skywalking/apm/collector/agentstream/worker/noderef/define/NodeReferenceH2TableDefine.java b/apm-collector/apm-collector-agentstream/src/main/java/org/skywalking/apm/collector/agentstream/worker/noderef/define/NodeReferenceH2TableDefine.java index 90e931d406029f181d06f4c92fda282efc8e29f8..a5389eae8d235f6f4f27a943c00fab13b943bbe3 100644 --- a/apm-collector/apm-collector-agentstream/src/main/java/org/skywalking/apm/collector/agentstream/worker/noderef/define/NodeReferenceH2TableDefine.java +++ b/apm-collector/apm-collector-agentstream/src/main/java/org/skywalking/apm/collector/agentstream/worker/noderef/define/NodeReferenceH2TableDefine.java @@ -32,6 +32,7 @@ public class NodeReferenceH2TableDefine extends H2TableDefine { } @Override public void initialize() { + addColumn(new H2ColumnDefine(NodeReferenceTable.COLUMN_ID, H2ColumnDefine.Type.Varchar.name())); addColumn(new H2ColumnDefine(NodeReferenceTable.COLUMN_FRONT_APPLICATION_ID, H2ColumnDefine.Type.Int.name())); addColumn(new H2ColumnDefine(NodeReferenceTable.COLUMN_BEHIND_APPLICATION_ID, H2ColumnDefine.Type.Int.name())); addColumn(new H2ColumnDefine(NodeReferenceTable.COLUMN_BEHIND_PEER, H2ColumnDefine.Type.Varchar.name())); diff --git a/apm-collector/apm-collector-agentstream/src/main/java/org/skywalking/apm/collector/agentstream/worker/segment/cost/dao/SegmentCostH2DAO.java b/apm-collector/apm-collector-agentstream/src/main/java/org/skywalking/apm/collector/agentstream/worker/segment/cost/dao/SegmentCostH2DAO.java index 212d01a3d239956fd192340effbe197a0efee180..a8b30c3c4bbe15aae2633c97f3c16a6b9e6d0655 100644 --- a/apm-collector/apm-collector-agentstream/src/main/java/org/skywalking/apm/collector/agentstream/worker/segment/cost/dao/SegmentCostH2DAO.java +++ b/apm-collector/apm-collector-agentstream/src/main/java/org/skywalking/apm/collector/agentstream/worker/segment/cost/dao/SegmentCostH2DAO.java @@ -18,11 +18,48 @@ package org.skywalking.apm.collector.agentstream.worker.segment.cost.dao; +import org.skywalking.apm.collector.core.stream.Data; +import org.skywalking.apm.collector.storage.define.DataDefine; +import org.skywalking.apm.collector.storage.define.segment.SegmentCostTable; +import org.skywalking.apm.collector.storage.h2.SqlBuilder; import org.skywalking.apm.collector.storage.h2.dao.H2DAO; +import org.skywalking.apm.collector.storage.h2.define.H2SqlEntity; +import org.skywalking.apm.collector.stream.worker.impl.dao.IPersistenceDAO; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.HashMap; +import java.util.Map; /** - * @author pengys5 + * @author pengys5, clevertension */ -public class SegmentCostH2DAO extends H2DAO implements ISegmentCostDAO { +public class SegmentCostH2DAO extends H2DAO implements ISegmentCostDAO, IPersistenceDAO { + private final Logger logger = LoggerFactory.getLogger(SegmentCostH2DAO.class); + @Override public Data get(String id, DataDefine dataDefine) { + return null; + } + @Override public H2SqlEntity prepareBatchInsert(Data data) { + logger.debug("segment cost prepareBatchInsert, id: {}", data.getDataString(0)); + H2SqlEntity entity = new H2SqlEntity(); + Map source = new HashMap<>(); + source.put("id", data.getDataString(0)); + source.put(SegmentCostTable.COLUMN_SEGMENT_ID, data.getDataString(1)); + source.put(SegmentCostTable.COLUMN_APPLICATION_ID, data.getDataInteger(0)); + source.put(SegmentCostTable.COLUMN_SERVICE_NAME, data.getDataString(2)); + source.put(SegmentCostTable.COLUMN_COST, data.getDataLong(0)); + source.put(SegmentCostTable.COLUMN_START_TIME, data.getDataLong(1)); + source.put(SegmentCostTable.COLUMN_END_TIME, data.getDataLong(2)); + source.put(SegmentCostTable.COLUMN_IS_ERROR, data.getDataBoolean(0)); + source.put(SegmentCostTable.COLUMN_TIME_BUCKET, data.getDataLong(3)); + logger.debug("segment cost source: {}", source.toString()); + String sql = SqlBuilder.buildBatchInsertSql(SegmentCostTable.TABLE, source.keySet()); + entity.setSql(sql); + entity.setParams(source.values().toArray(new Object[0])); + return entity; + } + @Override public H2SqlEntity prepareBatchUpdate(Data data) { + return null; + } } diff --git a/apm-collector/apm-collector-agentstream/src/main/java/org/skywalking/apm/collector/agentstream/worker/segment/origin/dao/SegmentH2DAO.java b/apm-collector/apm-collector-agentstream/src/main/java/org/skywalking/apm/collector/agentstream/worker/segment/origin/dao/SegmentH2DAO.java index 5beb0bdcf6b1f15fe75a43cc0fe231f95028622f..8a1ead97bce660df1f23f1160ef6ab935c71ddbf 100644 --- a/apm-collector/apm-collector-agentstream/src/main/java/org/skywalking/apm/collector/agentstream/worker/segment/origin/dao/SegmentH2DAO.java +++ b/apm-collector/apm-collector-agentstream/src/main/java/org/skywalking/apm/collector/agentstream/worker/segment/origin/dao/SegmentH2DAO.java @@ -18,10 +18,42 @@ package org.skywalking.apm.collector.agentstream.worker.segment.origin.dao; +import java.util.Base64; +import java.util.HashMap; +import java.util.Map; + +import org.skywalking.apm.collector.agentstream.worker.segment.cost.dao.SegmentCostH2DAO; +import org.skywalking.apm.collector.core.stream.Data; +import org.skywalking.apm.collector.storage.define.DataDefine; +import org.skywalking.apm.collector.storage.define.segment.SegmentTable; +import org.skywalking.apm.collector.storage.h2.SqlBuilder; import org.skywalking.apm.collector.storage.h2.dao.H2DAO; +import org.skywalking.apm.collector.storage.h2.define.H2SqlEntity; +import org.skywalking.apm.collector.stream.worker.impl.dao.IPersistenceDAO; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; /** - * @author pengys5 + * @author pengys5, clevertension */ -public class SegmentH2DAO extends H2DAO implements ISegmentDAO { +public class SegmentH2DAO extends H2DAO implements ISegmentDAO, IPersistenceDAO { + private final Logger logger = LoggerFactory.getLogger(SegmentCostH2DAO.class); + @Override public Data get(String id, DataDefine dataDefine) { + return null; + } + @Override public H2SqlEntity prepareBatchInsert(Data data) { + Map source = new HashMap<>(); + H2SqlEntity entity = new H2SqlEntity(); + source.put("id", data.getDataString(0)); + source.put(SegmentTable.COLUMN_DATA_BINARY, Base64.getEncoder().encode(data.getDataBytes(0))); + logger.debug("segment source: {}", source.toString()); + + String sql = SqlBuilder.buildBatchInsertSql(SegmentTable.TABLE, source.keySet()); + entity.setSql(sql); + entity.setParams(source.values().toArray(new Object[0])); + return entity; + } + @Override public H2SqlEntity prepareBatchUpdate(Data data) { + return null; + } } diff --git a/apm-collector/apm-collector-agentstream/src/main/java/org/skywalking/apm/collector/agentstream/worker/service/entry/dao/ServiceEntryH2DAO.java b/apm-collector/apm-collector-agentstream/src/main/java/org/skywalking/apm/collector/agentstream/worker/service/entry/dao/ServiceEntryH2DAO.java index a82e5497cc56be1f8ab8033a0d58997bc9bc2f55..6f91ba64ce7690e234b0cd2cf3784943bb240036 100644 --- a/apm-collector/apm-collector-agentstream/src/main/java/org/skywalking/apm/collector/agentstream/worker/service/entry/dao/ServiceEntryH2DAO.java +++ b/apm-collector/apm-collector-agentstream/src/main/java/org/skywalking/apm/collector/agentstream/worker/service/entry/dao/ServiceEntryH2DAO.java @@ -18,10 +18,78 @@ package org.skywalking.apm.collector.agentstream.worker.service.entry.dao; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import org.skywalking.apm.collector.client.h2.H2Client; +import org.skywalking.apm.collector.client.h2.H2ClientException; +import org.skywalking.apm.collector.core.stream.Data; +import org.skywalking.apm.collector.storage.define.DataDefine; +import org.skywalking.apm.collector.storage.define.service.ServiceEntryTable; +import org.skywalking.apm.collector.storage.h2.SqlBuilder; import org.skywalking.apm.collector.storage.h2.dao.H2DAO; +import org.skywalking.apm.collector.storage.h2.define.H2SqlEntity; +import org.skywalking.apm.collector.stream.worker.impl.dao.IPersistenceDAO; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; /** - * @author pengys5 + * @author pengys5, clevertension */ -public class ServiceEntryH2DAO extends H2DAO implements IServiceEntryDAO { +public class ServiceEntryH2DAO extends H2DAO implements IServiceEntryDAO, IPersistenceDAO { + private final Logger logger = LoggerFactory.getLogger(ServiceEntryH2DAO.class); + private static final String GET_SERIVCE_ENTRY_SQL = "select * from {0} where {1} = ?"; + @Override public Data get(String id, DataDefine dataDefine) { + H2Client client = getClient(); + String sql = SqlBuilder.buildSql(ServiceEntryTable.TABLE, "id"); + Object[] params = new Object[] {id}; + try (ResultSet rs = client.executeQuery(sql, params)) { + if (rs.next()) { + Data data = dataDefine.build(id); + data.setDataInteger(0, rs.getInt(ServiceEntryTable.COLUMN_APPLICATION_ID)); + data.setDataInteger(1, rs.getInt(ServiceEntryTable.COLUMN_ENTRY_SERVICE_ID)); + data.setDataString(1, rs.getString(ServiceEntryTable.COLUMN_ENTRY_SERVICE_NAME)); + data.setDataLong(0, rs.getLong(ServiceEntryTable.COLUMN_REGISTER_TIME)); + data.setDataLong(1, rs.getLong(ServiceEntryTable.COLUMN_NEWEST_TIME)); + return data; + } + } catch (SQLException | H2ClientException e) { + logger.error(e.getMessage(), e); + } + return null; + } + @Override public H2SqlEntity prepareBatchInsert(Data data) { + H2SqlEntity entity = new H2SqlEntity(); + Map source = new HashMap<>(); + source.put("id", data.getDataString(0)); + source.put(ServiceEntryTable.COLUMN_APPLICATION_ID, data.getDataInteger(0)); + source.put(ServiceEntryTable.COLUMN_ENTRY_SERVICE_ID, data.getDataInteger(1)); + source.put(ServiceEntryTable.COLUMN_ENTRY_SERVICE_NAME, data.getDataString(1)); + source.put(ServiceEntryTable.COLUMN_REGISTER_TIME, data.getDataLong(0)); + source.put(ServiceEntryTable.COLUMN_NEWEST_TIME, data.getDataLong(1)); + String sql = SqlBuilder.buildBatchInsertSql(ServiceEntryTable.TABLE, source.keySet()); + entity.setSql(sql); + entity.setParams(source.values().toArray(new Object[0])); + return entity; + } + @Override public H2SqlEntity prepareBatchUpdate(Data data) { + H2SqlEntity entity = new H2SqlEntity(); + Map source = new HashMap<>(); + source.put(ServiceEntryTable.COLUMN_APPLICATION_ID, data.getDataInteger(0)); + source.put(ServiceEntryTable.COLUMN_ENTRY_SERVICE_ID, data.getDataInteger(1)); + source.put(ServiceEntryTable.COLUMN_ENTRY_SERVICE_NAME, data.getDataString(1)); + source.put(ServiceEntryTable.COLUMN_REGISTER_TIME, data.getDataLong(0)); + source.put(ServiceEntryTable.COLUMN_NEWEST_TIME, data.getDataLong(1)); + String id = data.getDataString(0); + String sql = SqlBuilder.buildBatchUpdateSql(ServiceEntryTable.TABLE, source.keySet(), "id"); + entity.setSql(sql); + List values = new ArrayList<>(source.values()); + values.add(id); + entity.setParams(values.toArray(new Object[0])); + return entity; + } } diff --git a/apm-collector/apm-collector-agentstream/src/main/java/org/skywalking/apm/collector/agentstream/worker/serviceref/dao/ServiceReferenceH2DAO.java b/apm-collector/apm-collector-agentstream/src/main/java/org/skywalking/apm/collector/agentstream/worker/serviceref/dao/ServiceReferenceH2DAO.java index 91f4f8cb4c143c649f681c304915f79118f581dc..f649c7cae2e28263003ba6a149b30d6521520f29 100644 --- a/apm-collector/apm-collector-agentstream/src/main/java/org/skywalking/apm/collector/agentstream/worker/serviceref/dao/ServiceReferenceH2DAO.java +++ b/apm-collector/apm-collector-agentstream/src/main/java/org/skywalking/apm/collector/agentstream/worker/serviceref/dao/ServiceReferenceH2DAO.java @@ -18,25 +18,112 @@ package org.skywalking.apm.collector.agentstream.worker.serviceref.dao; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import org.skywalking.apm.collector.client.h2.H2Client; +import org.skywalking.apm.collector.client.h2.H2ClientException; import org.skywalking.apm.collector.core.stream.Data; import org.skywalking.apm.collector.storage.define.DataDefine; +import org.skywalking.apm.collector.storage.define.serviceref.ServiceReferenceTable; +import org.skywalking.apm.collector.storage.h2.SqlBuilder; import org.skywalking.apm.collector.storage.h2.dao.H2DAO; +import org.skywalking.apm.collector.storage.h2.define.H2SqlEntity; import org.skywalking.apm.collector.stream.worker.impl.dao.IPersistenceDAO; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; /** - * @author pengys5 + * @author pengys5, clevertension */ -public class ServiceReferenceH2DAO extends H2DAO implements IServiceReferenceDAO, IPersistenceDAO { - - @Override public Data get(String id, DataDefine dataDefine) { +public class ServiceReferenceH2DAO extends H2DAO implements IServiceReferenceDAO, IPersistenceDAO { + private final Logger logger = LoggerFactory.getLogger(ServiceReferenceH2DAO.class); + private static final String GET_SQL = "select * from {0} where {1} = ?"; + @Override + public Data get(String id, DataDefine dataDefine) { + H2Client client = getClient(); + String sql = SqlBuilder.buildSql(GET_SQL, ServiceReferenceTable.TABLE, "id"); + Object[] params = new Object[]{id}; + try (ResultSet rs = client.executeQuery(sql, params)) { + if (rs.next()) { + Data data = dataDefine.build(id); + data.setDataInteger(0, rs.getInt(ServiceReferenceTable.COLUMN_ENTRY_SERVICE_ID)); + data.setDataString(1, rs.getString(ServiceReferenceTable.COLUMN_ENTRY_SERVICE_NAME)); + data.setDataInteger(1, rs.getInt(ServiceReferenceTable.COLUMN_FRONT_SERVICE_ID)); + data.setDataString(2, rs.getString(ServiceReferenceTable.COLUMN_FRONT_SERVICE_NAME)); + data.setDataInteger(2, rs.getInt(ServiceReferenceTable.COLUMN_BEHIND_SERVICE_ID)); + data.setDataString(3, rs.getString(ServiceReferenceTable.COLUMN_BEHIND_SERVICE_NAME)); + data.setDataLong(0, rs.getLong(ServiceReferenceTable.COLUMN_S1_LTE)); + data.setDataLong(1, rs.getLong(ServiceReferenceTable.COLUMN_S3_LTE)); + data.setDataLong(2, rs.getLong(ServiceReferenceTable.COLUMN_S5_LTE)); + data.setDataLong(3, rs.getLong(ServiceReferenceTable.COLUMN_S5_GT)); + data.setDataLong(4, rs.getLong(ServiceReferenceTable.COLUMN_SUMMARY)); + data.setDataLong(5, rs.getLong(ServiceReferenceTable.COLUMN_ERROR)); + data.setDataLong(6, rs.getLong(ServiceReferenceTable.COLUMN_COST_SUMMARY)); + data.setDataLong(7, rs.getLong(ServiceReferenceTable.COLUMN_TIME_BUCKET)); + return data; + } + } catch (SQLException | H2ClientException e) { + logger.error(e.getMessage(), e); + } return null; } - @Override public String prepareBatchInsert(Data data) { - return null; + @Override + public H2SqlEntity prepareBatchInsert(Data data) { + H2SqlEntity entity = new H2SqlEntity(); + Map source = new HashMap<>(); + source.put("id", data.getDataString(0)); + source.put(ServiceReferenceTable.COLUMN_ENTRY_SERVICE_ID, data.getDataInteger(0)); + source.put(ServiceReferenceTable.COLUMN_ENTRY_SERVICE_NAME, data.getDataString(1)); + source.put(ServiceReferenceTable.COLUMN_FRONT_SERVICE_ID, data.getDataInteger(1)); + source.put(ServiceReferenceTable.COLUMN_FRONT_SERVICE_NAME, data.getDataString(2)); + source.put(ServiceReferenceTable.COLUMN_BEHIND_SERVICE_ID, data.getDataInteger(2)); + source.put(ServiceReferenceTable.COLUMN_BEHIND_SERVICE_NAME, data.getDataString(3)); + source.put(ServiceReferenceTable.COLUMN_S1_LTE, data.getDataLong(0)); + source.put(ServiceReferenceTable.COLUMN_S3_LTE, data.getDataLong(1)); + source.put(ServiceReferenceTable.COLUMN_S5_LTE, data.getDataLong(2)); + source.put(ServiceReferenceTable.COLUMN_S5_GT, data.getDataLong(3)); + source.put(ServiceReferenceTable.COLUMN_SUMMARY, data.getDataLong(4)); + source.put(ServiceReferenceTable.COLUMN_ERROR, data.getDataLong(5)); + source.put(ServiceReferenceTable.COLUMN_COST_SUMMARY, data.getDataLong(6)); + source.put(ServiceReferenceTable.COLUMN_TIME_BUCKET, data.getDataLong(7)); + + String sql = SqlBuilder.buildBatchInsertSql(ServiceReferenceTable.TABLE, source.keySet()); + entity.setSql(sql); + entity.setParams(source.values().toArray(new Object[0])); + return entity; } - @Override public String prepareBatchUpdate(Data data) { - return null; + @Override + public H2SqlEntity prepareBatchUpdate(Data data) { + H2SqlEntity entity = new H2SqlEntity(); + Map source = new HashMap<>(); + source.put(ServiceReferenceTable.COLUMN_ENTRY_SERVICE_ID, data.getDataInteger(0)); + source.put(ServiceReferenceTable.COLUMN_ENTRY_SERVICE_NAME, data.getDataString(1)); + source.put(ServiceReferenceTable.COLUMN_FRONT_SERVICE_ID, data.getDataInteger(1)); + source.put(ServiceReferenceTable.COLUMN_FRONT_SERVICE_NAME, data.getDataString(2)); + source.put(ServiceReferenceTable.COLUMN_BEHIND_SERVICE_ID, data.getDataInteger(2)); + source.put(ServiceReferenceTable.COLUMN_BEHIND_SERVICE_NAME, data.getDataString(3)); + source.put(ServiceReferenceTable.COLUMN_S1_LTE, data.getDataLong(0)); + source.put(ServiceReferenceTable.COLUMN_S3_LTE, data.getDataLong(1)); + source.put(ServiceReferenceTable.COLUMN_S5_LTE, data.getDataLong(2)); + source.put(ServiceReferenceTable.COLUMN_S5_GT, data.getDataLong(3)); + source.put(ServiceReferenceTable.COLUMN_SUMMARY, data.getDataLong(4)); + source.put(ServiceReferenceTable.COLUMN_ERROR, data.getDataLong(5)); + source.put(ServiceReferenceTable.COLUMN_COST_SUMMARY, data.getDataLong(6)); + source.put(ServiceReferenceTable.COLUMN_TIME_BUCKET, data.getDataLong(7)); + + String id = data.getDataString(0); + String sql = SqlBuilder.buildBatchUpdateSql(ServiceReferenceTable.TABLE, source.keySet(), "id"); + entity.setSql(sql); + List values = new ArrayList<>(source.values()); + values.add(id); + entity.setParams(values.toArray(new Object[0])); + return entity; } } diff --git a/apm-collector/apm-collector-boot/src/main/resources/application.yml b/apm-collector/apm-collector-boot/src/main/resources/application.yml index 18014b05d07f3c50d65ec47a2d16ad1cc880a784..02d49d0944e1ae149c44c786f2755bde0b83d8a4 100644 --- a/apm-collector/apm-collector-boot/src/main/resources/application.yml +++ b/apm-collector/apm-collector-boot/src/main/resources/application.yml @@ -1,7 +1,7 @@ -cluster: - zookeeper: - hostPort: localhost:2181 - sessionTimeout: 100000 +#cluster: +# zookeeper: +# hostPort: localhost:2181 +# sessionTimeout: 100000 agent_server: jetty: host: localhost @@ -34,3 +34,9 @@ storage: cluster_nodes: localhost:9300 index_shards_number: 2 index_replicas_number: 0 +# uncomment to enable h2 storage +#storage: +# h2: +# url: jdbc:h2:~/collector +# user_name: sa +# password: sa \ No newline at end of file diff --git a/apm-collector/apm-collector-cache/src/main/java/org/skywalking/apm/collector/cache/dao/ApplicationH2DAO.java b/apm-collector/apm-collector-cache/src/main/java/org/skywalking/apm/collector/cache/dao/ApplicationH2DAO.java index d9a139be403259e0aa79459bd7e4734537357274..ab9c13406bc0ffa4f299932e05516eaa1fc144e7 100644 --- a/apm-collector/apm-collector-cache/src/main/java/org/skywalking/apm/collector/cache/dao/ApplicationH2DAO.java +++ b/apm-collector/apm-collector-cache/src/main/java/org/skywalking/apm/collector/cache/dao/ApplicationH2DAO.java @@ -18,20 +18,45 @@ package org.skywalking.apm.collector.cache.dao; +import java.sql.ResultSet; +import java.sql.SQLException; import org.skywalking.apm.collector.client.h2.H2Client; +import org.skywalking.apm.collector.client.h2.H2ClientException; +import org.skywalking.apm.collector.core.util.Const; +import org.skywalking.apm.collector.storage.define.register.ApplicationTable; +import org.skywalking.apm.collector.storage.h2.SqlBuilder; import org.skywalking.apm.collector.storage.h2.dao.H2DAO; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; /** - * @author pengys5 + * @author pengys5, clevertension */ public class ApplicationH2DAO extends H2DAO implements IApplicationDAO { - @Override public int getApplicationId(String applicationCode) { - H2Client client = getClient(); - return 100; + private final Logger logger = LoggerFactory.getLogger(ApplicationH2DAO.class); + private static final String GET_APPLICATION_CODE_SQL = "select {0} from {1} where {2} = ?"; + + @Override + public int getApplicationId(String applicationCode) { + logger.info("get the application id with application code = {}", applicationCode); + String sql = "select " + ApplicationTable.COLUMN_APPLICATION_ID + " from " + + ApplicationTable.TABLE + " where " + ApplicationTable.COLUMN_APPLICATION_CODE + "='" + applicationCode + "'"; + return getIntValueBySQL(sql); } @Override public String getApplicationCode(int applicationId) { - return null; + logger.debug("get application code, applicationId: {}", applicationId); + H2Client client = getClient(); + String sql = SqlBuilder.buildSql(GET_APPLICATION_CODE_SQL, ApplicationTable.COLUMN_APPLICATION_CODE, ApplicationTable.TABLE, ApplicationTable.COLUMN_APPLICATION_ID); + Object[] params = new Object[] {applicationId}; + try (ResultSet rs = client.executeQuery(sql, params)) { + if (rs.next()) { + return rs.getString(1); + } + } catch (SQLException | H2ClientException e) { + logger.error(e.getMessage(), e); + } + return Const.UNKNOWN; } } diff --git a/apm-collector/apm-collector-cache/src/main/java/org/skywalking/apm/collector/cache/dao/InstanceH2DAO.java b/apm-collector/apm-collector-cache/src/main/java/org/skywalking/apm/collector/cache/dao/InstanceH2DAO.java index 126279cdee5a8e6636fdf303d1eda1d08088afde..2b4ce8256b704455dbedf5a13633593b6ffb1f75 100644 --- a/apm-collector/apm-collector-cache/src/main/java/org/skywalking/apm/collector/cache/dao/InstanceH2DAO.java +++ b/apm-collector/apm-collector-cache/src/main/java/org/skywalking/apm/collector/cache/dao/InstanceH2DAO.java @@ -18,13 +18,37 @@ package org.skywalking.apm.collector.cache.dao; +import java.sql.ResultSet; +import java.sql.SQLException; +import org.skywalking.apm.collector.client.h2.H2Client; +import org.skywalking.apm.collector.client.h2.H2ClientException; +import org.skywalking.apm.collector.storage.define.register.InstanceTable; +import org.skywalking.apm.collector.storage.h2.SqlBuilder; import org.skywalking.apm.collector.storage.h2.dao.H2DAO; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; /** * @author pengys5 */ public class InstanceH2DAO extends H2DAO implements IInstanceDAO { + + private final Logger logger = LoggerFactory.getLogger(InstanceH2DAO.class); + + private static final String GET_APPLICATION_ID_SQL = "select {0} from {1} where {2} = ?"; + @Override public int getApplicationId(int applicationInstanceId) { + logger.info("get the application id with application id = {}", applicationInstanceId); + H2Client client = getClient(); + String sql = SqlBuilder.buildSql(GET_APPLICATION_ID_SQL, InstanceTable.COLUMN_APPLICATION_ID, InstanceTable.TABLE, InstanceTable.COLUMN_APPLICATION_ID); + Object[] params = new Object[] {applicationInstanceId}; + try (ResultSet rs = client.executeQuery(sql, params)) { + if (rs.next()) { + return rs.getInt(InstanceTable.COLUMN_APPLICATION_ID); + } + } catch (SQLException | H2ClientException e) { + logger.error(e.getMessage(), e); + } return 0; } } diff --git a/apm-collector/apm-collector-cache/src/main/java/org/skywalking/apm/collector/cache/dao/ServiceNameH2DAO.java b/apm-collector/apm-collector-cache/src/main/java/org/skywalking/apm/collector/cache/dao/ServiceNameH2DAO.java index a56b2aafe5ab9ebafc42af3fc635ade9aff53025..8de1635c23706eaf93fdb0649bb5764e6a2bdd7f 100644 --- a/apm-collector/apm-collector-cache/src/main/java/org/skywalking/apm/collector/cache/dao/ServiceNameH2DAO.java +++ b/apm-collector/apm-collector-cache/src/main/java/org/skywalking/apm/collector/cache/dao/ServiceNameH2DAO.java @@ -18,18 +18,53 @@ package org.skywalking.apm.collector.cache.dao; +import java.sql.ResultSet; +import java.sql.SQLException; +import org.skywalking.apm.collector.client.h2.H2Client; +import org.skywalking.apm.collector.client.h2.H2ClientException; +import org.skywalking.apm.collector.core.util.Const; +import org.skywalking.apm.collector.storage.define.register.ServiceNameTable; +import org.skywalking.apm.collector.storage.h2.SqlBuilder; import org.skywalking.apm.collector.storage.h2.dao.H2DAO; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; /** - * @author pengys5 + * @author pengys5, clevertension */ public class ServiceNameH2DAO extends H2DAO implements IServiceNameDAO { + private final Logger logger = LoggerFactory.getLogger(ServiceNameH2DAO.class); + private static final String GET_SERVICE_NAME_SQL = "select {0} from {1} where {2} = ?"; + private static final String GET_SERVICE_ID_SQL = "select {0} from {1} where {2} = ? and {3} = ? limit 1"; @Override public String getServiceName(int serviceId) { - return null; + H2Client client = getClient(); + String sql = SqlBuilder.buildSql(GET_SERVICE_NAME_SQL, ServiceNameTable.COLUMN_SERVICE_NAME, + ServiceNameTable.TABLE, ServiceNameTable.COLUMN_SERVICE_ID); + Object[] params = new Object[] {serviceId}; + try (ResultSet rs = client.executeQuery(sql, params)) { + if (rs.next()) { + return rs.getString(ServiceNameTable.COLUMN_SERVICE_NAME); + } + } catch (SQLException | H2ClientException e) { + logger.error(e.getMessage(), e); + } + return Const.UNKNOWN; } @Override public int getServiceId(int applicationId, String serviceName) { + H2Client client = getClient(); + String sql = SqlBuilder.buildSql(GET_SERVICE_ID_SQL, ServiceNameTable.COLUMN_SERVICE_ID, + ServiceNameTable.TABLE, ServiceNameTable.COLUMN_APPLICATION_ID, ServiceNameTable.COLUMN_SERVICE_NAME); + Object[] params = new Object[] {applicationId, serviceName}; + try (ResultSet rs = client.executeQuery(sql, params)) { + if (rs.next()) { + int serviceId = rs.getInt(ServiceNameTable.COLUMN_SERVICE_ID); + return serviceId; + } + } catch (SQLException | H2ClientException e) { + logger.error(e.getMessage(), e); + } return 0; } } diff --git a/apm-collector/apm-collector-client/src/main/java/org/skywalking/apm/collector/client/h2/H2Client.java b/apm-collector/apm-collector-client/src/main/java/org/skywalking/apm/collector/client/h2/H2Client.java index 8fb004941b84a64905004d8e6dc1328c14a3f3ff..8ab7c47d86e11e7a14c757b2bb7212fc1cc5e95c 100644 --- a/apm-collector/apm-collector-client/src/main/java/org/skywalking/apm/collector/client/h2/H2Client.java +++ b/apm-collector/apm-collector-client/src/main/java/org/skywalking/apm/collector/client/h2/H2Client.java @@ -18,11 +18,10 @@ package org.skywalking.apm.collector.client.h2; -import java.sql.Connection; -import java.sql.DriverManager; -import java.sql.ResultSet; -import java.sql.SQLException; -import java.sql.Statement; +import java.sql.*; + +import org.h2.jdbcx.JdbcConnectionPool; +import org.h2.util.IOUtils; import org.skywalking.apm.collector.core.client.Client; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -34,25 +33,47 @@ public class H2Client implements Client { private final Logger logger = LoggerFactory.getLogger(H2Client.class); + private JdbcConnectionPool cp; private Connection conn; + private String url; + private String userName; + private String password; + + public H2Client() { + this.url = "jdbc:h2:mem:collector"; + this.userName = ""; + this.password = ""; + } + + public H2Client(String url, String userName, String password) { + this.url = url; + this.userName = userName; + this.password = password; + } @Override public void initialize() throws H2ClientException { try { - Class.forName("org.h2.Driver"); - conn = DriverManager.getConnection("jdbc:h2:mem:collector"); - } catch (ClassNotFoundException | SQLException e) { + cp = JdbcConnectionPool. + create(this.url, this.userName, this.password); + conn = cp.getConnection(); + } catch (Exception e) { throw new H2ClientException(e.getMessage(), e); } } @Override public void shutdown() { + if (cp != null) { + cp.dispose(); + } + IOUtils.closeSilently(conn); + } + public Connection getConnection() throws H2ClientException { + return conn; } public void execute(String sql) throws H2ClientException { - Statement statement = null; - try { - statement = conn.createStatement(); + try (Statement statement = getConnection().createStatement()) { statement.execute(sql); statement.closeOnCompletion(); } catch (SQLException e) { @@ -60,17 +81,40 @@ public class H2Client implements Client { } } - public void executeQuery(String sql) throws H2ClientException { - Statement statement = null; + public ResultSet executeQuery(String sql, Object[] params) throws H2ClientException { + logger.debug("execute query with result: {}", sql); + ResultSet rs; + PreparedStatement statement; try { - statement = conn.createStatement(); - ResultSet rs = statement.executeQuery(sql); - while (rs.next()) { - logger.debug(rs.getString("ADDRESS") + "," + rs.getString("DATA")); + statement = getConnection().prepareStatement(sql); + if (params != null) { + for (int i = 0; i < params.length; i++) { + statement.setObject(i + 1, params[i]); + } } + rs = statement.executeQuery(); statement.closeOnCompletion(); } catch (SQLException e) { throw new H2ClientException(e.getMessage(), e); } + return rs; + } + + public boolean execute(String sql, Object[] params) throws H2ClientException { + logger.debug("execute insert/update/delete: {}", sql); + boolean flag; + Connection conn = getConnection(); + try (PreparedStatement statement = conn.prepareStatement(sql)) { + conn.setAutoCommit(true); + if (params != null) { + for (int i = 0; i < params.length; i++) { + statement.setObject(i + 1, params[i]); + } + } + flag = statement.execute(); + } catch (SQLException e) { + throw new H2ClientException(e.getMessage(), e); + } + return flag; } } diff --git a/apm-collector/apm-collector-client/src/main/java/org/skywalking/apm/collector/client/zookeeper/ZookeeperClient.java b/apm-collector/apm-collector-client/src/main/java/org/skywalking/apm/collector/client/zookeeper/ZookeeperClient.java index 9c68ad8633893c04f087220e549940e6a4e83ed4..2af662c5be44ddb836c3f182ceb0041da68a8063 100644 --- a/apm-collector/apm-collector-client/src/main/java/org/skywalking/apm/collector/client/zookeeper/ZookeeperClient.java +++ b/apm-collector/apm-collector-client/src/main/java/org/skywalking/apm/collector/client/zookeeper/ZookeeperClient.java @@ -78,6 +78,14 @@ public class ZookeeperClient implements Client { } } + public void delete(final String path, int version) throws ZookeeperClientException { + try { + zk.delete(path, version); + } catch (KeeperException | InterruptedException e) { + throw new ZookeeperClientException(e.getMessage(), e); + } + } + public byte[] getData(String path, boolean watch, Stat stat) throws ZookeeperClientException { try { return zk.getData(path, watch, stat); diff --git a/apm-collector/apm-collector-cluster/src/main/java/org/skywalking/apm/collector/cluster/zookeeper/ClusterZKDataMonitor.java b/apm-collector/apm-collector-cluster/src/main/java/org/skywalking/apm/collector/cluster/zookeeper/ClusterZKDataMonitor.java index a2f9e3ef7c841f4cf159dca293068e825534789e..356e804f6483957130120a4e267dfaf3609cd8bc 100644 --- a/apm-collector/apm-collector-cluster/src/main/java/org/skywalking/apm/collector/cluster/zookeeper/ClusterZKDataMonitor.java +++ b/apm-collector/apm-collector-cluster/src/main/java/org/skywalking/apm/collector/cluster/zookeeper/ClusterZKDataMonitor.java @@ -115,9 +115,15 @@ public class ClusterZKDataMonitor implements DataMonitor, Watcher { client.getChildren(next.getKey(), true); String serverPath = next.getKey() + "/" + value.getHostPort(); - if (client.exists(serverPath, false) == null) { + Stat stat = client.exists(serverPath, false); + if (stat != null) { + client.delete(serverPath, stat.getVersion()); + } + stat = client.exists(serverPath, false); + if (stat == null) { setData(serverPath, contextPath); } else { + client.delete(serverPath, stat.getVersion()); throw new ClusterNodeExistException("current address: " + value.getHostPort() + " has been registered, check the host and port configuration or wait a moment."); } } diff --git a/apm-collector/apm-collector-core/src/main/java/org/skywalking/apm/collector/core/module/ModuleConfigLoader.java b/apm-collector/apm-collector-core/src/main/java/org/skywalking/apm/collector/core/module/ModuleConfigLoader.java index afda1299f3c0a440cc7ee1f274b29e8d4edf8e9e..42238dc8466f4d55e8a8f68a2c2d7041c6fb16a6 100644 --- a/apm-collector/apm-collector-core/src/main/java/org/skywalking/apm/collector/core/module/ModuleConfigLoader.java +++ b/apm-collector/apm-collector-core/src/main/java/org/skywalking/apm/collector/core/module/ModuleConfigLoader.java @@ -19,7 +19,7 @@ package org.skywalking.apm.collector.core.module; import java.io.FileNotFoundException; -import java.io.FileReader; +import java.io.Reader; import java.util.Map; import org.skywalking.apm.collector.core.config.ConfigLoader; import org.skywalking.apm.collector.core.framework.DefineException; @@ -39,8 +39,8 @@ public class ModuleConfigLoader implements ConfigLoader> { Yaml yaml = new Yaml(); try { try { - FileReader applicationFileReader = ResourceUtils.read("application.yml"); - return (Map)yaml.load(applicationFileReader); + Reader applicationReader = ResourceUtils.read("application.yml"); + return (Map)yaml.load(applicationReader); } catch (FileNotFoundException e) { logger.info("Could not found application.yml file, use default"); return (Map)yaml.load(ResourceUtils.read("application-default.yml")); diff --git a/apm-collector/apm-collector-core/src/main/java/org/skywalking/apm/collector/core/util/ResourceUtils.java b/apm-collector/apm-collector-core/src/main/java/org/skywalking/apm/collector/core/util/ResourceUtils.java index 3c86ac494670027042aa542258127e64fbe46112..0ec0f83a4baf14df54e730f32f8449c665e0085a 100644 --- a/apm-collector/apm-collector-core/src/main/java/org/skywalking/apm/collector/core/util/ResourceUtils.java +++ b/apm-collector/apm-collector-core/src/main/java/org/skywalking/apm/collector/core/util/ResourceUtils.java @@ -18,9 +18,10 @@ package org.skywalking.apm.collector.core.util; -import java.io.File; import java.io.FileNotFoundException; -import java.io.FileReader; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.io.Reader; import java.net.URL; /** @@ -28,12 +29,12 @@ import java.net.URL; */ public class ResourceUtils { - public static FileReader read(String fileName) throws FileNotFoundException { + public static Reader read(String fileName) throws FileNotFoundException { URL url = ResourceUtils.class.getClassLoader().getResource(fileName); if (url == null) { throw new FileNotFoundException("file not found: " + fileName); } - File file = new File(ResourceUtils.class.getClassLoader().getResource(fileName).getFile()); - return new FileReader(file); + InputStream inputStream = ResourceUtils.class.getClassLoader().getResourceAsStream(fileName); + return new InputStreamReader(inputStream); } } diff --git a/apm-collector/apm-collector-core/src/test/java/org/skywalking/apm/collector/core/module/ModuleConfigLoaderTestCase.java b/apm-collector/apm-collector-core/src/test/java/org/skywalking/apm/collector/core/module/ModuleConfigLoaderTestCase.java new file mode 100644 index 0000000000000000000000000000000000000000..546e39dcd359d324e68c7293fbab66ee401ec093 --- /dev/null +++ b/apm-collector/apm-collector-core/src/test/java/org/skywalking/apm/collector/core/module/ModuleConfigLoaderTestCase.java @@ -0,0 +1,40 @@ +/* + * Copyright 2017, OpenSkywalking Organization All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * Project repository: https://github.com/OpenSkywalking/skywalking + */ + +package org.skywalking.apm.collector.core.module; + +import java.util.Map; + +import org.junit.Assert; +import org.junit.Test; +import org.skywalking.apm.collector.core.framework.DefineException; + +/** + * @author neeuq + */ +public class ModuleConfigLoaderTestCase { + + @SuppressWarnings({ "rawtypes" }) + @Test + public void testLoad() throws DefineException { + ModuleConfigLoader configLoader = new ModuleConfigLoader(); + Map configuration = configLoader.load(); + Assert.assertNotNull(configuration.get("cluster")); + Assert.assertNotNull(configuration.get("cluster").get("zookeeper")); + } +} diff --git a/apm-collector/apm-collector-core/src/test/java/org/skywalking/apm/collector/core/utils/ResourceUtilsTestCase.java b/apm-collector/apm-collector-core/src/test/java/org/skywalking/apm/collector/core/utils/ResourceUtilsTestCase.java new file mode 100644 index 0000000000000000000000000000000000000000..851050c1175fbe9d146adc3ead54f3c29060bb37 --- /dev/null +++ b/apm-collector/apm-collector-core/src/test/java/org/skywalking/apm/collector/core/utils/ResourceUtilsTestCase.java @@ -0,0 +1,40 @@ +/* + * Copyright 2017, OpenSkywalking Organization All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * Project repository: https://github.com/OpenSkywalking/skywalking + */ + +package org.skywalking.apm.collector.core.utils; + +import java.io.IOException; +import java.io.Reader; + +import org.junit.Assert; +import org.junit.Test; +import org.skywalking.apm.collector.core.util.ResourceUtils; + +/** + * @author neeuq + */ +public class ResourceUtilsTestCase { + + @Test + public void testRead() throws IOException { + Reader reader = ResourceUtils.read("application.yml"); + Assert.assertNotNull(reader); + reader.close(); + } + +} diff --git a/apm-collector/apm-collector-storage/src/main/java/org/skywalking/apm/collector/storage/define/segment/SegmentCostDataDefine.java b/apm-collector/apm-collector-storage/src/main/java/org/skywalking/apm/collector/storage/define/segment/SegmentCostDataDefine.java index 89ad822ecb70ee58e2cc59e400adab918b246b4d..1e3b4f0f0ed9b8918cfa90bf6ee9af1309311c5c 100644 --- a/apm-collector/apm-collector-storage/src/main/java/org/skywalking/apm/collector/storage/define/segment/SegmentCostDataDefine.java +++ b/apm-collector/apm-collector-storage/src/main/java/org/skywalking/apm/collector/storage/define/segment/SegmentCostDataDefine.java @@ -28,7 +28,7 @@ import org.skywalking.apm.collector.storage.define.AttributeType; import org.skywalking.apm.collector.storage.define.DataDefine; /** - * @author pengys5 + * @author pengys5H */ public class SegmentCostDataDefine extends DataDefine { diff --git a/apm-collector/apm-collector-storage/src/main/java/org/skywalking/apm/collector/storage/h2/SqlBuilder.java b/apm-collector/apm-collector-storage/src/main/java/org/skywalking/apm/collector/storage/h2/SqlBuilder.java new file mode 100644 index 0000000000000000000000000000000000000000..f3944030c4c1f90419e3309fd7d0e2a2adc35fca --- /dev/null +++ b/apm-collector/apm-collector-storage/src/main/java/org/skywalking/apm/collector/storage/h2/SqlBuilder.java @@ -0,0 +1,61 @@ +/* + * Copyright 2017, OpenSkywalking Organization All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * Project repository: https://github.com/OpenSkywalking/skywalking + */ + +package org.skywalking.apm.collector.storage.h2; + +import java.text.MessageFormat; +import java.util.List; +import java.util.Set; + +public class SqlBuilder { + public static final String buildSql(String sql, Object ... args) { + return MessageFormat.format(sql, args); + } + + public static final String buildSql(String sql, List args) { + MessageFormat messageFormat = new MessageFormat(sql); + return messageFormat.format(args.toArray(new Object[0])); + } + + public static final String buildBatchInsertSql(String tableName, Set columnNames) { + StringBuilder sb = new StringBuilder("insert into "); + sb.append(tableName).append("("); + columnNames.forEach((columnName) -> { + sb.append(columnName).append(","); + }); + sb.delete(sb.length() - 1, sb.length()); + sb.append(") values("); + for (int i = 0; i < columnNames.size(); i++) { + sb.append("?,"); + } + sb.delete(sb.length() - 1, sb.length()); + sb.append(")"); + return sb.toString(); + } + + public static final String buildBatchUpdateSql(String tableName, Set columnNames, String whereClauseName) { + StringBuilder sb = new StringBuilder("update "); + sb.append(tableName).append(" set "); + columnNames.forEach((columnName) -> { + sb.append(columnName).append("=?,"); + }); + sb.delete(sb.length() - 1, sb.length()); + sb.append(" where ").append(whereClauseName).append("=?"); + return sb.toString(); + } +} diff --git a/apm-collector/apm-collector-storage/src/main/java/org/skywalking/apm/collector/storage/h2/StorageH2Config.java b/apm-collector/apm-collector-storage/src/main/java/org/skywalking/apm/collector/storage/h2/StorageH2Config.java new file mode 100644 index 0000000000000000000000000000000000000000..a467b9cf4115ce4489ceb4691af1dc0f854d2063 --- /dev/null +++ b/apm-collector/apm-collector-storage/src/main/java/org/skywalking/apm/collector/storage/h2/StorageH2Config.java @@ -0,0 +1,28 @@ +/* + * Copyright 2017, OpenSkywalking Organization All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * Project repository: https://github.com/OpenSkywalking/skywalking + */ + +package org.skywalking.apm.collector.storage.h2; + +/** + * @author clevertension + */ +public class StorageH2Config { + public static String URL; + public static String USER_NAME; + public static String PASSWORD; +} diff --git a/apm-collector/apm-collector-storage/src/main/java/org/skywalking/apm/collector/storage/h2/StorageH2ConfigParser.java b/apm-collector/apm-collector-storage/src/main/java/org/skywalking/apm/collector/storage/h2/StorageH2ConfigParser.java index c945c18dd32bf4a11b9f5dec4ca4e587b7bb4dd3..85a08c426d0d16657ed90f9d3a91fc19114ca6bb 100644 --- a/apm-collector/apm-collector-storage/src/main/java/org/skywalking/apm/collector/storage/h2/StorageH2ConfigParser.java +++ b/apm-collector/apm-collector-storage/src/main/java/org/skywalking/apm/collector/storage/h2/StorageH2ConfigParser.java @@ -21,12 +21,25 @@ package org.skywalking.apm.collector.storage.h2; import java.util.Map; import org.skywalking.apm.collector.core.config.ConfigParseException; import org.skywalking.apm.collector.core.module.ModuleConfigParser; +import org.skywalking.apm.collector.core.util.ObjectUtils; +import org.skywalking.apm.collector.core.util.StringUtils; /** * @author pengys5 */ public class StorageH2ConfigParser implements ModuleConfigParser { - + private static final String URL = "url"; + public static final String USER_NAME = "user_name"; + public static final String PASSWORD = "password"; @Override public void parse(Map config) throws ConfigParseException { + if (ObjectUtils.isNotEmpty(config) && StringUtils.isNotEmpty(config.get(URL))) { + StorageH2Config.URL = (String)config.get(URL); + } + if (ObjectUtils.isNotEmpty(config) && StringUtils.isNotEmpty(config.get(USER_NAME))) { + StorageH2Config.USER_NAME = (String)config.get(USER_NAME); + } + if (ObjectUtils.isNotEmpty(config) && StringUtils.isNotEmpty(config.get(PASSWORD))) { + StorageH2Config.PASSWORD = (String)config.get(PASSWORD); + } } } diff --git a/apm-collector/apm-collector-storage/src/main/java/org/skywalking/apm/collector/storage/h2/StorageH2ModuleDefine.java b/apm-collector/apm-collector-storage/src/main/java/org/skywalking/apm/collector/storage/h2/StorageH2ModuleDefine.java index 9705f888ab5708ab809f16e5bfeeefdd7ff598d6..9faae085feb315438b676c260a86fd634b6b0cb8 100644 --- a/apm-collector/apm-collector-storage/src/main/java/org/skywalking/apm/collector/storage/h2/StorageH2ModuleDefine.java +++ b/apm-collector/apm-collector-storage/src/main/java/org/skywalking/apm/collector/storage/h2/StorageH2ModuleDefine.java @@ -51,7 +51,7 @@ public class StorageH2ModuleDefine extends StorageModuleDefine { } @Override protected Client createClient() { - return new H2Client(); + return new H2Client(StorageH2Config.URL, StorageH2Config.USER_NAME, StorageH2Config.PASSWORD); } @Override public StorageInstaller storageInstaller() { diff --git a/apm-collector/apm-collector-storage/src/main/java/org/skywalking/apm/collector/storage/h2/dao/BatchH2DAO.java b/apm-collector/apm-collector-storage/src/main/java/org/skywalking/apm/collector/storage/h2/dao/BatchH2DAO.java index b41935ef340c24adcf27eea2128e9a32781a0b96..ac0989f42d8c627346a5dcb51ac905e71bd2dccb 100644 --- a/apm-collector/apm-collector-storage/src/main/java/org/skywalking/apm/collector/storage/h2/dao/BatchH2DAO.java +++ b/apm-collector/apm-collector-storage/src/main/java/org/skywalking/apm/collector/storage/h2/dao/BatchH2DAO.java @@ -18,15 +18,69 @@ package org.skywalking.apm.collector.storage.h2.dao; -import java.util.List; +import org.skywalking.apm.collector.client.h2.H2ClientException; import org.skywalking.apm.collector.storage.dao.IBatchDAO; +import org.skywalking.apm.collector.storage.h2.define.H2SqlEntity; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.sql.Connection; +import java.sql.PreparedStatement; +import java.sql.SQLException; +import java.util.HashMap; +import java.util.List; +import java.util.Map; /** * @author pengys5 */ public class BatchH2DAO extends H2DAO implements IBatchDAO { + private final Logger logger = LoggerFactory.getLogger(BatchH2DAO.class); - @Override public void batchPersistence(List batchCollection) { + @Override + public void batchPersistence(List batchCollection) { + if (batchCollection != null && batchCollection.size() > 0) { + logger.debug("the batch collection size is {}", batchCollection.size()); + Connection conn = null; + final Map batchSqls = new HashMap<>(); + try { + conn = getClient().getConnection(); + conn.setAutoCommit(true); + PreparedStatement ps; + for (Object entity : batchCollection) { + H2SqlEntity e = getH2SqlEntity(entity); + String sql = e.getSql(); + if (batchSqls.containsKey(sql)) { + ps = batchSqls.get(sql); + } else { + ps = conn.prepareStatement(sql); + batchSqls.put(sql, ps); + } + + Object[] params = e.getParams(); + if (params != null) { + logger.debug("the sql is {}, params size is {}", e.getSql(), params.length); + for (int i = 0; i < params.length; i++) { + ps.setObject(i + 1, params[i]); + } + } + ps.addBatch(); + } + + for (String k : batchSqls.keySet()) { + batchSqls.get(k).executeBatch(); + } + } catch (SQLException | H2ClientException e) { + logger.error(e.getMessage(), e); + } + batchSqls.clear(); + } + } + private H2SqlEntity getH2SqlEntity(Object entity) { + if (entity instanceof H2SqlEntity) { + return (H2SqlEntity) entity; + } + return null; } } diff --git a/apm-collector/apm-collector-storage/src/main/java/org/skywalking/apm/collector/storage/h2/dao/H2DAO.java b/apm-collector/apm-collector-storage/src/main/java/org/skywalking/apm/collector/storage/h2/dao/H2DAO.java index a3dac86a6b1f13563251fb1b27ac067e3a9cf280..39dbc78e000c8c2a264a1d83343199fcbec5df8c 100644 --- a/apm-collector/apm-collector-storage/src/main/java/org/skywalking/apm/collector/storage/h2/dao/H2DAO.java +++ b/apm-collector/apm-collector-storage/src/main/java/org/skywalking/apm/collector/storage/h2/dao/H2DAO.java @@ -18,11 +18,45 @@ package org.skywalking.apm.collector.storage.h2.dao; +import java.sql.ResultSet; +import java.sql.SQLException; + import org.skywalking.apm.collector.client.h2.H2Client; +import org.skywalking.apm.collector.client.h2.H2ClientException; import org.skywalking.apm.collector.storage.dao.DAO; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; /** * @author pengys5 */ public abstract class H2DAO extends DAO { + private final Logger logger = LoggerFactory.getLogger(H2DAO.class); + public final int getMaxId(String tableName, String columnName) { + String sql = "select max(" + columnName + ") from " + tableName; + return getIntValueBySQL(sql); + } + + public final int getMinId(String tableName, String columnName) { + String sql = "select min(" + columnName + ") from " + tableName; + return getIntValueBySQL(sql); + } + + public final int getIntValueBySQL(String sql) { + H2Client client = getClient(); + try (ResultSet rs = client.executeQuery(sql, null)) { + if (rs.next()) { + int id = rs.getInt(1); + if (id == Integer.MAX_VALUE || id == Integer.MIN_VALUE) { + return 0; + } else { + return id; + } + } + } catch (SQLException | H2ClientException e) { + logger.error(e.getMessage(), e); + } + return 0; + } + } diff --git a/apm-collector/apm-collector-storage/src/main/java/org/skywalking/apm/collector/storage/h2/define/H2SqlEntity.java b/apm-collector/apm-collector-storage/src/main/java/org/skywalking/apm/collector/storage/h2/define/H2SqlEntity.java new file mode 100644 index 0000000000000000000000000000000000000000..39cba0ad9405d030b3a35cf31fc3c7d841912504 --- /dev/null +++ b/apm-collector/apm-collector-storage/src/main/java/org/skywalking/apm/collector/storage/h2/define/H2SqlEntity.java @@ -0,0 +1,43 @@ +/* + * Copyright 2017, OpenSkywalking Organization All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * Project repository: https://github.com/OpenSkywalking/skywalking + */ + +package org.skywalking.apm.collector.storage.h2.define; + +/** + * @author clevertension + */ +public class H2SqlEntity { + private String sql; + private Object[] params; + + public String getSql() { + return sql; + } + + public void setSql(String sql) { + this.sql = sql; + } + + public Object[] getParams() { + return params; + } + + public void setParams(Object[] params) { + this.params = params; + } +} diff --git a/apm-collector/apm-collector-storage/src/main/java/org/skywalking/apm/collector/storage/h2/define/H2StorageInstaller.java b/apm-collector/apm-collector-storage/src/main/java/org/skywalking/apm/collector/storage/h2/define/H2StorageInstaller.java index 7fdecfca1eb5419690038900fd3d13cf3f695877..1c68dac620904616d3091c9ba0ee1febf430d8ef 100644 --- a/apm-collector/apm-collector-storage/src/main/java/org/skywalking/apm/collector/storage/h2/define/H2StorageInstaller.java +++ b/apm-collector/apm-collector-storage/src/main/java/org/skywalking/apm/collector/storage/h2/define/H2StorageInstaller.java @@ -18,7 +18,6 @@ package org.skywalking.apm.collector.storage.h2.define; -import java.util.List; import org.skywalking.apm.collector.client.h2.H2Client; import org.skywalking.apm.collector.client.h2.H2ClientException; import org.skywalking.apm.collector.core.client.Client; @@ -26,12 +25,20 @@ import org.skywalking.apm.collector.core.storage.StorageException; import org.skywalking.apm.collector.core.storage.StorageInstallException; import org.skywalking.apm.collector.core.storage.StorageInstaller; import org.skywalking.apm.collector.core.storage.TableDefine; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.sql.ResultSet; +import java.sql.SQLException; +import java.util.List; /** * @author pengys5 */ public class H2StorageInstaller extends StorageInstaller { + private final Logger logger = LoggerFactory.getLogger(H2StorageInstaller.class); + @Override protected void defineFilter(List tableDefines) { int size = tableDefines.size(); for (int i = size - 1; i >= 0; i--) { @@ -42,11 +49,36 @@ public class H2StorageInstaller extends StorageInstaller { } @Override protected boolean isExists(Client client, TableDefine tableDefine) throws StorageException { + H2Client h2Client = (H2Client)client; + ResultSet rs = null; + try { + logger.info("check if table {} exist ", tableDefine.getName()); + rs = h2Client.getConnection().getMetaData().getTables(null, null, tableDefine.getName().toUpperCase(), null); + if (rs.next()) { + return true; + } + } catch (SQLException | H2ClientException e) { + throw new StorageInstallException(e.getMessage(), e); + } finally { + try { + if (rs != null) { + rs.close(); + } + } catch (SQLException e) { + throw new StorageInstallException(e.getMessage(), e); + } + } return false; } @Override protected boolean deleteTable(Client client, TableDefine tableDefine) throws StorageException { - return false; + H2Client h2Client = (H2Client)client; + try { + h2Client.execute("drop table if exists " + tableDefine.getName()); + return true; + } catch (H2ClientException e) { + throw new StorageInstallException(e.getMessage(), e); + } } @Override protected boolean createTable(Client client, TableDefine tableDefine) throws StorageException { @@ -59,14 +91,16 @@ public class H2StorageInstaller extends StorageInstaller { h2TableDefine.getColumnDefines().forEach(columnDefine -> { H2ColumnDefine h2ColumnDefine = (H2ColumnDefine)columnDefine; if (h2ColumnDefine.getType().equals(H2ColumnDefine.Type.Varchar.name())) { - sqlBuilder.append(h2ColumnDefine.getName()).append(" ").append(h2ColumnDefine.getType()).append("(255)"); + sqlBuilder.append(h2ColumnDefine.getName()).append(" ").append(h2ColumnDefine.getType()).append("(255),"); } else { - sqlBuilder.append(h2ColumnDefine.getName()).append(" ").append(h2ColumnDefine.getType()); + sqlBuilder.append(h2ColumnDefine.getName()).append(" ").append(h2ColumnDefine.getType()).append(","); } }); - + //remove last comma + sqlBuilder.delete(sqlBuilder.length() - 1, sqlBuilder.length()); sqlBuilder.append(")"); try { + logger.info("create h2 table with sql {}", sqlBuilder); h2Client.execute(sqlBuilder.toString()); } catch (H2ClientException e) { throw new StorageInstallException(e.getMessage(), e); diff --git a/apm-collector/apm-collector-ui/src/main/java/org/skywalking/apm/collector/ui/dao/CpuMetricH2DAO.java b/apm-collector/apm-collector-ui/src/main/java/org/skywalking/apm/collector/ui/dao/CpuMetricH2DAO.java new file mode 100644 index 0000000000000000000000000000000000000000..8d6d302ba0e471ae4ff253ba5b352e5643e0b392 --- /dev/null +++ b/apm-collector/apm-collector-ui/src/main/java/org/skywalking/apm/collector/ui/dao/CpuMetricH2DAO.java @@ -0,0 +1,93 @@ +/* + * Copyright 2017, OpenSkywalking Organization All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * Project repository: https://github.com/OpenSkywalking/skywalking + */ + +package org.skywalking.apm.collector.ui.dao; + +import java.sql.ResultSet; +import java.sql.SQLException; +import java.util.ArrayList; +import java.util.List; + +import org.skywalking.apm.collector.client.h2.H2Client; +import org.skywalking.apm.collector.client.h2.H2ClientException; +import org.skywalking.apm.collector.core.util.Const; +import org.skywalking.apm.collector.core.util.TimeBucketUtils; +import org.skywalking.apm.collector.storage.define.jvm.CpuMetricTable; +import org.skywalking.apm.collector.storage.h2.SqlBuilder; +import org.skywalking.apm.collector.storage.h2.dao.H2DAO; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.google.gson.JsonArray; + +/** + * @author pengys5, clevertension + */ +public class CpuMetricH2DAO extends H2DAO implements ICpuMetricDAO { + private final Logger logger = LoggerFactory.getLogger(InstanceH2DAO.class); + private static final String GET_CPU_METRIC_SQL = "select * from {0} where {1} = ?"; + private static final String GET_CPU_METRICS_SQL = "select * from {0} where {1} in ("; + @Override public int getMetric(int instanceId, long timeBucket) { + String id = timeBucket + Const.ID_SPLIT + instanceId; + H2Client client = getClient(); + String sql = SqlBuilder.buildSql(GET_CPU_METRIC_SQL, CpuMetricTable.TABLE, "id"); + Object[] params = new Object[]{id}; + try (ResultSet rs = client.executeQuery(sql, params)) { + if (rs.next()) { + return rs.getInt(CpuMetricTable.COLUMN_USAGE_PERCENT); + } + } catch (SQLException | H2ClientException e) { + logger.error(e.getMessage(), e); + } + return 0; + } + + @Override public JsonArray getMetric(int instanceId, long startTimeBucket, long endTimeBucket) { + H2Client client = getClient(); + String sql = SqlBuilder.buildSql(GET_CPU_METRICS_SQL, CpuMetricTable.TABLE, "id"); + + long timeBucket = startTimeBucket; + List idList = new ArrayList<>(); + do { + timeBucket = TimeBucketUtils.INSTANCE.addSecondForSecondTimeBucket(TimeBucketUtils.TimeBucketType.SECOND.name(), timeBucket, 1); + String id = timeBucket + Const.ID_SPLIT + instanceId; + idList.add(id); + } + while (timeBucket <= endTimeBucket); + + StringBuilder builder = new StringBuilder(); + for (int i = 0; i < idList.size(); i++) { + builder.append("?,"); + } + builder.delete(builder.length() - 1, builder.length()); + builder.append(")"); + sql = sql + builder; + Object[] params = idList.toArray(new String[0]); + + JsonArray metrics = new JsonArray(); + try (ResultSet rs = client.executeQuery(sql, params)) { + while (rs.next()) { + double cpuUsed = rs.getDouble(CpuMetricTable.COLUMN_USAGE_PERCENT); + metrics.add((int)(cpuUsed * 100)); + } + } catch (SQLException | H2ClientException e) { + logger.error(e.getMessage(), e); + } + return metrics; + } +} diff --git a/apm-collector/apm-collector-ui/src/main/java/org/skywalking/apm/collector/ui/dao/GCMetricH2DAO.java b/apm-collector/apm-collector-ui/src/main/java/org/skywalking/apm/collector/ui/dao/GCMetricH2DAO.java index 6b9b75bee84b0b972500461e6349a5380349ff62..be97ac1e08500f918fca40bd5c0b34184b61a254 100644 --- a/apm-collector/apm-collector-ui/src/main/java/org/skywalking/apm/collector/ui/dao/GCMetricH2DAO.java +++ b/apm-collector/apm-collector-ui/src/main/java/org/skywalking/apm/collector/ui/dao/GCMetricH2DAO.java @@ -18,23 +18,158 @@ package org.skywalking.apm.collector.ui.dao; -import com.google.gson.JsonObject; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.util.ArrayList; +import java.util.List; + +import org.skywalking.apm.collector.client.h2.H2Client; +import org.skywalking.apm.collector.client.h2.H2ClientException; +import org.skywalking.apm.collector.core.util.Const; +import org.skywalking.apm.collector.core.util.TimeBucketUtils; +import org.skywalking.apm.collector.storage.define.jvm.GCMetricTable; +import org.skywalking.apm.collector.storage.h2.SqlBuilder; import org.skywalking.apm.collector.storage.h2.dao.H2DAO; +import org.skywalking.apm.network.proto.GCPhrase; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.google.gson.JsonArray; +import com.google.gson.JsonObject; /** - * @author pengys5 + * @author pengys5, clevertension */ public class GCMetricH2DAO extends H2DAO implements IGCMetricDAO { - + private final Logger logger = LoggerFactory.getLogger(GCMetricH2DAO.class); + private static final String GET_GC_COUNT_SQL = "select {1}, sum({0}) as cnt, {1} from {2} where {3} = ? and {4} in ("; + private static final String GET_GC_METRIC_SQL = "select * from {0} where {1} = ?"; + private static final String GET_GC_METRICS_SQL = "select * from {0} where {1} in ("; @Override public GCCount getGCCount(long[] timeBuckets, int instanceId) { - return null; + GCCount gcCount = new GCCount(); + H2Client client = getClient(); + String sql = GET_GC_COUNT_SQL; + StringBuilder builder = new StringBuilder(); + for (int i = 0; i < timeBuckets.length; i++) { + builder.append("?,"); + } + builder.delete(builder.length() - 1, builder.length()); + builder.append(")"); + sql = sql + builder + " group by {1}"; + sql = SqlBuilder.buildSql(sql, GCMetricTable.COLUMN_COUNT, GCMetricTable.COLUMN_PHRASE, + GCMetricTable.TABLE, GCMetricTable.COLUMN_INSTANCE_ID, "id"); + Object[] params = new Object[timeBuckets.length + 1]; + for (int i = 0; i < timeBuckets.length; i++) { + params[i + 1] = timeBuckets[i]; + } + params[0] = instanceId; + try (ResultSet rs = client.executeQuery(sql, params)) { + if (rs.next()) { + int phrase = rs.getInt(GCMetricTable.COLUMN_PHRASE); + int count = rs.getInt("cnt"); + + if (phrase == GCPhrase.NEW_VALUE) { + gcCount.setYoung(count); + } else if (phrase == GCPhrase.OLD_VALUE) { + gcCount.setOld(count); + } + } + } catch (SQLException | H2ClientException e) { + logger.error(e.getMessage(), e); + } + return gcCount; } @Override public JsonObject getMetric(int instanceId, long timeBucket) { - return null; + JsonObject response = new JsonObject(); + H2Client client = getClient(); + String sql = SqlBuilder.buildSql(GET_GC_METRIC_SQL, GCMetricTable.TABLE, "id"); + String youngId = timeBucket + Const.ID_SPLIT + GCPhrase.NEW_VALUE + instanceId; + Object[] params = new Object[]{youngId}; + try (ResultSet rs = client.executeQuery(sql, params)) { + if (rs.next()) { + response.addProperty("ygc", rs.getInt(GCMetricTable.COLUMN_COUNT)); + } + } catch (SQLException | H2ClientException e) { + logger.error(e.getMessage(), e); + } + String oldId = timeBucket + Const.ID_SPLIT + GCPhrase.OLD_VALUE + instanceId; + Object[] params1 = new Object[]{oldId}; + try (ResultSet rs = client.executeQuery(sql, params1)) { + if (rs.next()) { + response.addProperty("ogc", rs.getInt(GCMetricTable.COLUMN_COUNT)); + } + } catch (SQLException | H2ClientException e) { + logger.error(e.getMessage(), e); + } + + return response; } @Override public JsonObject getMetric(int instanceId, long startTimeBucket, long endTimeBucket) { - return null; + JsonObject response = new JsonObject(); + H2Client client = getClient(); + String sql = SqlBuilder.buildSql(GET_GC_METRICS_SQL, GCMetricTable.TABLE, "id"); + long timeBucket = startTimeBucket; + List idList = new ArrayList<>(); + do { + timeBucket = TimeBucketUtils.INSTANCE.addSecondForSecondTimeBucket(TimeBucketUtils.TimeBucketType.SECOND.name(), timeBucket, 1); + String youngId = timeBucket + Const.ID_SPLIT + instanceId + Const.ID_SPLIT + GCPhrase.NEW_VALUE; + idList.add(youngId); + } + while (timeBucket <= endTimeBucket); + StringBuilder builder = new StringBuilder(); + for (int i = 0; i < idList.size(); i++) { + builder.append("?,"); + } + builder.delete(builder.length() - 1, builder.length()); + builder.append(")"); + sql = sql + builder; + Object[] params = idList.toArray(new String[0]); + + JsonArray youngArray = new JsonArray(); + try (ResultSet rs = client.executeQuery(sql, params)) { + while (rs.next()) { + youngArray.add(rs.getInt(GCMetricTable.COLUMN_COUNT)); + } + if (youngArray.size() == 0) { + youngArray.add(0); + } + } catch (SQLException | H2ClientException e) { + logger.error(e.getMessage(), e); + } + response.add("ygc", youngArray); + List idList1 = new ArrayList<>(); + timeBucket = startTimeBucket; + do { + timeBucket = TimeBucketUtils.INSTANCE.addSecondForSecondTimeBucket(TimeBucketUtils.TimeBucketType.SECOND.name(), timeBucket, 1); + String oldId = timeBucket + Const.ID_SPLIT + instanceId + Const.ID_SPLIT + GCPhrase.OLD_VALUE; + idList1.add(oldId); + } + while (timeBucket <= endTimeBucket); + String sql1 = SqlBuilder.buildSql(GET_GC_METRICS_SQL, GCMetricTable.TABLE, "id"); + StringBuilder builder1 = new StringBuilder(); + for (int i = 0; i < idList1.size(); i++) { + builder1.append("?,"); + } + builder1.delete(builder1.length() - 1, builder1.length()); + builder1.append(")"); + sql1 = sql1 + builder1; + Object[] params1 = idList.toArray(new String[0]); + JsonArray oldArray = new JsonArray(); + + try (ResultSet rs = client.executeQuery(sql1, params1)) { + while (rs.next()) { + oldArray.add(rs.getInt(GCMetricTable.COLUMN_COUNT)); + } + if (oldArray.size() == 0) { + oldArray.add(0); + } + } catch (SQLException | H2ClientException e) { + logger.error(e.getMessage(), e); + } + response.add("ogc", oldArray); + + return response; } } diff --git a/apm-collector/apm-collector-ui/src/main/java/org/skywalking/apm/collector/ui/dao/GlobalTraceH2DAO.java b/apm-collector/apm-collector-ui/src/main/java/org/skywalking/apm/collector/ui/dao/GlobalTraceH2DAO.java index 2ecb922e86f72f7a1c6a18e2cc553a6693dca30e..6920d915aa1e0d1bd6a6eb22ee6d8ab689b58ad2 100644 --- a/apm-collector/apm-collector-ui/src/main/java/org/skywalking/apm/collector/ui/dao/GlobalTraceH2DAO.java +++ b/apm-collector/apm-collector-ui/src/main/java/org/skywalking/apm/collector/ui/dao/GlobalTraceH2DAO.java @@ -18,18 +18,59 @@ package org.skywalking.apm.collector.ui.dao; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.util.ArrayList; import java.util.List; + +import org.skywalking.apm.collector.client.h2.H2Client; +import org.skywalking.apm.collector.client.h2.H2ClientException; +import org.skywalking.apm.collector.storage.define.global.GlobalTraceTable; +import org.skywalking.apm.collector.storage.h2.SqlBuilder; import org.skywalking.apm.collector.storage.h2.dao.H2DAO; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; /** - * @author pengys5 + * @author pengys5, clevertension */ public class GlobalTraceH2DAO extends H2DAO implements IGlobalTraceDAO { + private final Logger logger = LoggerFactory.getLogger(GlobalTraceH2DAO.class); + private static final String GET_GLOBAL_TRACE_ID_SQL = "select {0} from {1} where {2} = ? limit 10"; + private static final String GET_SEGMENT_IDS_SQL = "select {0} from {1} where {2} = ? limit 10"; @Override public List getGlobalTraceId(String segmentId) { - return null; + List globalTraceIds = new ArrayList<>(); + H2Client client = getClient(); + String sql = SqlBuilder.buildSql(GET_GLOBAL_TRACE_ID_SQL, GlobalTraceTable.COLUMN_GLOBAL_TRACE_ID, + GlobalTraceTable.TABLE, GlobalTraceTable.COLUMN_SEGMENT_ID); + Object[] params = new Object[]{segmentId}; + try (ResultSet rs = client.executeQuery(sql, params)) { + while (rs.next()) { + String globalTraceId = rs.getString(GlobalTraceTable.COLUMN_GLOBAL_TRACE_ID); + logger.debug("segmentId: {}, global trace id: {}", segmentId, globalTraceId); + globalTraceIds.add(globalTraceId); + } + } catch (SQLException | H2ClientException e) { + logger.error(e.getMessage(), e); + } + return globalTraceIds; } @Override public List getSegmentIds(String globalTraceId) { - return null; + List segmentIds = new ArrayList<>(); + H2Client client = getClient(); + String sql = SqlBuilder.buildSql(GET_SEGMENT_IDS_SQL, GlobalTraceTable.COLUMN_SEGMENT_ID, + GlobalTraceTable.TABLE, GlobalTraceTable.COLUMN_GLOBAL_TRACE_ID); + Object[] params = new Object[]{globalTraceId}; + try (ResultSet rs = client.executeQuery(sql, params)) { + while (rs.next()) { + String segmentId = rs.getString(GlobalTraceTable.COLUMN_SEGMENT_ID); + logger.debug("segmentId: {}, global trace id: {}", segmentId, globalTraceId); + segmentIds.add(globalTraceId); + } + } catch (SQLException | H2ClientException e) { + logger.error(e.getMessage(), e); + } + return segmentIds; } } diff --git a/apm-collector/apm-collector-ui/src/main/java/org/skywalking/apm/collector/ui/dao/InstPerformanceH2DAO.java b/apm-collector/apm-collector-ui/src/main/java/org/skywalking/apm/collector/ui/dao/InstPerformanceH2DAO.java index 14bfb232b95c1dc07c60f5780e4b435929838a06..9cd63b8280510522c063860b64e7ae177dc3411b 100644 --- a/apm-collector/apm-collector-ui/src/main/java/org/skywalking/apm/collector/ui/dao/InstPerformanceH2DAO.java +++ b/apm-collector/apm-collector-ui/src/main/java/org/skywalking/apm/collector/ui/dao/InstPerformanceH2DAO.java @@ -18,31 +18,157 @@ package org.skywalking.apm.collector.ui.dao; -import com.google.gson.JsonArray; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.util.ArrayList; +import java.util.List; + +import org.skywalking.apm.collector.client.h2.H2Client; +import org.skywalking.apm.collector.client.h2.H2ClientException; +import org.skywalking.apm.collector.core.util.Const; +import org.skywalking.apm.collector.core.util.TimeBucketUtils; +import org.skywalking.apm.collector.storage.define.instance.InstPerformanceTable; +import org.skywalking.apm.collector.storage.h2.SqlBuilder; import org.skywalking.apm.collector.storage.h2.dao.H2DAO; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.google.gson.JsonArray; /** - * @author pengys5 + * @author pengys5, clevertension */ public class InstPerformanceH2DAO extends H2DAO implements IInstPerformanceDAO { - + private final Logger logger = LoggerFactory.getLogger(InstPerformanceH2DAO.class); + private static final String GET_INST_PERF_SQL = "select * from {0} where {1} = ? and {2} in ("; + private static final String GET_TPS_METRIC_SQL = "select * from {0} where {1} = ?"; + private static final String GET_TPS_METRICS_SQL = "select * from {0} where {1} in ("; @Override public InstPerformance get(long[] timeBuckets, int instanceId) { + H2Client client = getClient(); + logger.info("the inst performance inst id = {}", instanceId); + String sql = SqlBuilder.buildSql(GET_INST_PERF_SQL, InstPerformanceTable.TABLE, InstPerformanceTable.COLUMN_INSTANCE_ID, InstPerformanceTable.COLUMN_TIME_BUCKET); + StringBuilder builder = new StringBuilder(); + for (int i = 0; i < timeBuckets.length; i++) { + builder.append("?,"); + } + builder.delete(builder.length() - 1, builder.length()); + builder.append(")"); + sql = sql + builder; + Object[] params = new Object[timeBuckets.length + 1]; + for (int i = 0; i < timeBuckets.length; i++) { + params[i + 1] = timeBuckets[i]; + } + params[0] = instanceId; + try (ResultSet rs = client.executeQuery(sql, params)) { + if (rs.next()) { + int callTimes = rs.getInt(InstPerformanceTable.COLUMN_CALLS); + int costTotal = rs.getInt(InstPerformanceTable.COLUMN_COST_TOTAL); + return new InstPerformance(instanceId, callTimes, costTotal); + } + } catch (SQLException | H2ClientException e) { + logger.error(e.getMessage(), e); + } return null; } @Override public int getTpsMetric(int instanceId, long timeBucket) { + logger.info("getTpMetric instanceId = {}, startTimeBucket = {}", instanceId, timeBucket); + H2Client client = getClient(); + String sql = SqlBuilder.buildSql(GET_TPS_METRIC_SQL, InstPerformanceTable.TABLE, "id"); + Object[] params = new Object[]{instanceId}; + try (ResultSet rs = client.executeQuery(sql, params)) { + if (rs.next()) { + return rs.getInt(InstPerformanceTable.COLUMN_CALLS); + } + } catch (SQLException | H2ClientException e) { + logger.error(e.getMessage(), e); + } return 0; } @Override public JsonArray getTpsMetric(int instanceId, long startTimeBucket, long endTimeBucket) { - return null; + logger.info("getTpsMetric instanceId = {}, startTimeBucket = {}, endTimeBucket = {}", instanceId, startTimeBucket, endTimeBucket); + H2Client client = getClient(); + String sql = SqlBuilder.buildSql(GET_TPS_METRICS_SQL, InstPerformanceTable.TABLE, "id"); + + long timeBucket = startTimeBucket; + List idList = new ArrayList<>(); + do { + String id = timeBucket + Const.ID_SPLIT + instanceId; + timeBucket = TimeBucketUtils.INSTANCE.addSecondForSecondTimeBucket(TimeBucketUtils.TimeBucketType.SECOND.name(), timeBucket, 1); + idList.add(id); + } + while (timeBucket <= endTimeBucket); + + StringBuilder builder = new StringBuilder(); + for (int i = 0; i < idList.size(); i++) { + builder.append("?,"); + } + builder.delete(builder.length() - 1, builder.length()); + builder.append(")"); + sql = sql + builder; + Object[] params = idList.toArray(new String[0]); + + JsonArray metrics = new JsonArray(); + try (ResultSet rs = client.executeQuery(sql, params)) { + while (rs.next()) { + int calls = rs.getInt(InstPerformanceTable.COLUMN_CALLS); + metrics.add(calls); + } + } catch (SQLException | H2ClientException e) { + logger.error(e.getMessage(), e); + } + return metrics; } @Override public int getRespTimeMetric(int instanceId, long timeBucket) { + H2Client client = getClient(); + String sql = SqlBuilder.buildSql(GET_TPS_METRIC_SQL, InstPerformanceTable.TABLE, "id"); + Object[] params = new Object[]{instanceId}; + try (ResultSet rs = client.executeQuery(sql, params)) { + if (rs.next()) { + int callTimes = rs.getInt(InstPerformanceTable.COLUMN_CALLS); + int costTotal = rs.getInt(InstPerformanceTable.COLUMN_COST_TOTAL); + return costTotal / callTimes; + } + } catch (SQLException | H2ClientException e) { + logger.error(e.getMessage(), e); + } return 0; } @Override public JsonArray getRespTimeMetric(int instanceId, long startTimeBucket, long endTimeBucket) { - return null; + H2Client client = getClient(); + String sql = SqlBuilder.buildSql(GET_TPS_METRICS_SQL, InstPerformanceTable.TABLE, "id"); + + long timeBucket = startTimeBucket; + List idList = new ArrayList<>(); + do { + String id = timeBucket + Const.ID_SPLIT + instanceId; + timeBucket = TimeBucketUtils.INSTANCE.addSecondForSecondTimeBucket(TimeBucketUtils.TimeBucketType.SECOND.name(), timeBucket, 1); + idList.add(id); + } + while (timeBucket <= endTimeBucket); + + StringBuilder builder = new StringBuilder(); + for (int i = 0; i < idList.size(); i++) { + builder.append("?,"); + } + builder.delete(builder.length() - 1, builder.length()); + builder.append(")"); + sql = sql + builder; + Object[] params = idList.toArray(new String[0]); + + JsonArray metrics = new JsonArray(); + try (ResultSet rs = client.executeQuery(sql, params)) { + while (rs.next()) { + int callTimes = rs.getInt(InstPerformanceTable.COLUMN_CALLS); + int costTotal = rs.getInt(InstPerformanceTable.COLUMN_COST_TOTAL); + metrics.add(costTotal / callTimes); + } + } catch (SQLException | H2ClientException e) { + logger.error(e.getMessage(), e); + } + return metrics; } } diff --git a/apm-collector/apm-collector-ui/src/main/java/org/skywalking/apm/collector/ui/dao/InstanceH2DAO.java b/apm-collector/apm-collector-ui/src/main/java/org/skywalking/apm/collector/ui/dao/InstanceH2DAO.java index 298de1b9cf4011e20ad92215d230236c3a47ec16..6b3c72fc0cbf43c243ef90476caaf4eddf8f23a7 100644 --- a/apm-collector/apm-collector-ui/src/main/java/org/skywalking/apm/collector/ui/dao/InstanceH2DAO.java +++ b/apm-collector/apm-collector-ui/src/main/java/org/skywalking/apm/collector/ui/dao/InstanceH2DAO.java @@ -18,32 +18,134 @@ package org.skywalking.apm.collector.ui.dao; -import com.google.gson.JsonArray; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.util.LinkedList; import java.util.List; + +import org.skywalking.apm.collector.client.h2.H2Client; +import org.skywalking.apm.collector.client.h2.H2ClientException; +import org.skywalking.apm.collector.core.util.TimeBucketUtils; import org.skywalking.apm.collector.storage.define.register.InstanceDataDefine; +import org.skywalking.apm.collector.storage.define.register.InstanceTable; +import org.skywalking.apm.collector.storage.h2.SqlBuilder; import org.skywalking.apm.collector.storage.h2.dao.H2DAO; +import org.skywalking.apm.collector.ui.cache.ApplicationCache; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.google.gson.JsonArray; +import com.google.gson.JsonObject; /** - * @author pengys5 + * @author pengys5, clevertension */ public class InstanceH2DAO extends H2DAO implements IInstanceDAO { - @Override public Long lastHeartBeatTime() { - return null; + private final Logger logger = LoggerFactory.getLogger(InstanceH2DAO.class); + private static final String GET_LAST_HEARTBEAT_TIME_SQL = "select {0} from {1} where {2} > ? limit 1"; + private static final String GET_INST_LAST_HEARTBEAT_TIME_SQL = "select {0} from {1} where {2} > ? and {3} = ? limit 1"; + private static final String GET_INSTANCE_SQL = "select * from {0} where {1} = ?"; + private static final String GET_INSTANCES_SQL = "select * from {0} where {1} = ? and {2} >= ?"; + private static final String GET_APPLICATIONS_SQL = "select {3}, count({0}) as cnt from {1} where {2} >= ? and {2} <= ? group by {3} limit 100"; + + @Override + public Long lastHeartBeatTime() { + H2Client client = getClient(); + long fiveMinuteBefore = System.currentTimeMillis() - 5 * 60 * 1000; + fiveMinuteBefore = TimeBucketUtils.INSTANCE.getSecondTimeBucket(fiveMinuteBefore); + String sql = SqlBuilder.buildSql(GET_LAST_HEARTBEAT_TIME_SQL, InstanceTable.COLUMN_HEARTBEAT_TIME, InstanceTable.TABLE, InstanceTable.COLUMN_HEARTBEAT_TIME); + Object[] params = new Object[]{fiveMinuteBefore}; + try (ResultSet rs = client.executeQuery(sql, params)) { + if (rs.next()) { + return rs.getLong(1); + } + } catch (SQLException | H2ClientException e) { + logger.error(e.getMessage(), e); + } + return 0L; } - @Override public Long instanceLastHeartBeatTime(long applicationInstanceId) { - return null; + @Override + public Long instanceLastHeartBeatTime(long applicationInstanceId) { + H2Client client = getClient(); + long fiveMinuteBefore = System.currentTimeMillis() - 5 * 60 * 1000; + fiveMinuteBefore = TimeBucketUtils.INSTANCE.getSecondTimeBucket(fiveMinuteBefore); + String sql = SqlBuilder.buildSql(GET_INST_LAST_HEARTBEAT_TIME_SQL, InstanceTable.COLUMN_HEARTBEAT_TIME, InstanceTable.TABLE, + InstanceTable.COLUMN_HEARTBEAT_TIME, InstanceTable.COLUMN_INSTANCE_ID); + Object[] params = new Object[]{fiveMinuteBefore, applicationInstanceId}; + try (ResultSet rs = client.executeQuery(sql, params)) { + if (rs.next()) { + return rs.getLong(1); + } + } catch (SQLException | H2ClientException e) { + logger.error(e.getMessage(), e); + } + return 0L; } - @Override public JsonArray getApplications(long startTime, long endTime) { - return null; + @Override + public JsonArray getApplications(long startTime, long endTime) { + H2Client client = getClient(); + JsonArray applications = new JsonArray(); + String sql = SqlBuilder.buildSql(GET_APPLICATIONS_SQL, InstanceTable.COLUMN_INSTANCE_ID, + InstanceTable.TABLE, InstanceTable.COLUMN_HEARTBEAT_TIME, InstanceTable.COLUMN_APPLICATION_ID); + Object[] params = new Object[]{startTime, endTime}; + try (ResultSet rs = client.executeQuery(sql, params)) { + while (rs.next()) { + Integer applicationId = rs.getInt(InstanceTable.COLUMN_APPLICATION_ID); + logger.debug("applicationId: {}", applicationId); + JsonObject application = new JsonObject(); + application.addProperty("applicationId", applicationId); + application.addProperty("applicationCode", ApplicationCache.getForUI(applicationId)); + application.addProperty("instanceCount", rs.getInt("cnt")); + applications.add(application); + } + } catch (SQLException | H2ClientException e) { + logger.error(e.getMessage(), e); + } + return applications; } - @Override public InstanceDataDefine.Instance getInstance(int instanceId) { + @Override + public InstanceDataDefine.Instance getInstance(int instanceId) { + H2Client client = getClient(); + String sql = SqlBuilder.buildSql(GET_INSTANCE_SQL, InstanceTable.TABLE, InstanceTable.COLUMN_INSTANCE_ID); + Object[] params = new Object[]{instanceId}; + try (ResultSet rs = client.executeQuery(sql, params)) { + if (rs.next()) { + InstanceDataDefine.Instance instance = new InstanceDataDefine.Instance(); + instance.setId(String.valueOf(instanceId)); + instance.setApplicationId(rs.getInt(InstanceTable.COLUMN_APPLICATION_ID)); + instance.setAgentUUID(rs.getString(InstanceTable.COLUMN_AGENT_UUID)); + instance.setRegisterTime(rs.getLong(InstanceTable.COLUMN_REGISTER_TIME)); + instance.setHeartBeatTime(rs.getLong(InstanceTable.COLUMN_HEARTBEAT_TIME)); + instance.setOsInfo(rs.getString(InstanceTable.COLUMN_OS_INFO)); + return instance; + } + } catch (SQLException | H2ClientException e) { + logger.error(e.getMessage(), e); + } return null; } - @Override public List getInstances(int applicationId, long timeBucket) { - return null; + @Override + public List getInstances(int applicationId, long timeBucket) { + logger.debug("get instances info, application id: {}, timeBucket: {}", applicationId, timeBucket); + List instanceList = new LinkedList<>(); + H2Client client = getClient(); + String sql = SqlBuilder.buildSql(GET_INSTANCES_SQL, InstanceTable.TABLE, InstanceTable.COLUMN_APPLICATION_ID, InstanceTable.COLUMN_HEARTBEAT_TIME); + Object[] params = new Object[]{applicationId, timeBucket}; + try (ResultSet rs = client.executeQuery(sql, params)) { + while (rs.next()) { + InstanceDataDefine.Instance instance = new InstanceDataDefine.Instance(); + instance.setApplicationId(rs.getInt(InstanceTable.COLUMN_APPLICATION_ID)); + instance.setHeartBeatTime(rs.getLong(InstanceTable.COLUMN_HEARTBEAT_TIME)); + instance.setInstanceId(rs.getInt(InstanceTable.COLUMN_INSTANCE_ID)); + instanceList.add(instance); + } + } catch (SQLException | H2ClientException e) { + logger.error(e.getMessage(), e); + } + return instanceList; } } diff --git a/apm-collector/apm-collector-ui/src/main/java/org/skywalking/apm/collector/ui/dao/MemoryMetricH2DAO.java b/apm-collector/apm-collector-ui/src/main/java/org/skywalking/apm/collector/ui/dao/MemoryMetricH2DAO.java new file mode 100644 index 0000000000000000000000000000000000000000..70b5dc971db334ada24d91b3d409b6088b0fdb51 --- /dev/null +++ b/apm-collector/apm-collector-ui/src/main/java/org/skywalking/apm/collector/ui/dao/MemoryMetricH2DAO.java @@ -0,0 +1,108 @@ +/* + * Copyright 2017, OpenSkywalking Organization All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * Project repository: https://github.com/OpenSkywalking/skywalking + */ + +package org.skywalking.apm.collector.ui.dao; + +import java.sql.ResultSet; +import java.sql.SQLException; +import java.util.ArrayList; +import java.util.List; + +import org.skywalking.apm.collector.client.h2.H2Client; +import org.skywalking.apm.collector.client.h2.H2ClientException; +import org.skywalking.apm.collector.core.util.Const; +import org.skywalking.apm.collector.core.util.TimeBucketUtils; +import org.skywalking.apm.collector.storage.define.jvm.MemoryMetricTable; +import org.skywalking.apm.collector.storage.h2.SqlBuilder; +import org.skywalking.apm.collector.storage.h2.dao.H2DAO; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.google.gson.JsonArray; +import com.google.gson.JsonObject; + +/** + * @author clevertension + */ +public class MemoryMetricH2DAO extends H2DAO implements IMemoryMetricDAO { + private final Logger logger = LoggerFactory.getLogger(InstanceH2DAO.class); + private static final String GET_MEMORY_METRIC_SQL = "select * from {0} where {1} =?"; + private static final String GET_MEMORY_METRICS_SQL = "select * from {0} where {1} in ("; + @Override public JsonObject getMetric(int instanceId, long timeBucket, boolean isHeap) { + H2Client client = getClient(); + String id = timeBucket + Const.ID_SPLIT + instanceId + Const.ID_SPLIT + isHeap; + String sql = SqlBuilder.buildSql(GET_MEMORY_METRIC_SQL, MemoryMetricTable.TABLE, "id"); + Object[] params = new Object[]{id}; + JsonObject metric = new JsonObject(); + try (ResultSet rs = client.executeQuery(sql, params)) { + if (rs.next()) { + metric.addProperty("max", rs.getInt(MemoryMetricTable.COLUMN_MAX)); + metric.addProperty("init", rs.getInt(MemoryMetricTable.COLUMN_INIT)); + metric.addProperty("used", rs.getInt(MemoryMetricTable.COLUMN_USED)); + } else { + metric.addProperty("max", 0); + metric.addProperty("init", 0); + metric.addProperty("used", 0); + } + } catch (SQLException | H2ClientException e) { + logger.error(e.getMessage(), e); + } + return metric; + } + + @Override public JsonObject getMetric(int instanceId, long startTimeBucket, long endTimeBucket, boolean isHeap) { + H2Client client = getClient(); + String sql = SqlBuilder.buildSql(GET_MEMORY_METRICS_SQL, MemoryMetricTable.TABLE, "id"); + List idList = new ArrayList<>(); + long timeBucket = startTimeBucket; + do { + timeBucket = TimeBucketUtils.INSTANCE.addSecondForSecondTimeBucket(TimeBucketUtils.TimeBucketType.SECOND.name(), timeBucket, 1); + String id = timeBucket + Const.ID_SPLIT + instanceId + Const.ID_SPLIT + isHeap; + idList.add(id); + } + while (timeBucket <= endTimeBucket); + + StringBuilder builder = new StringBuilder(); + for (int i = 0; i < idList.size(); i++) { + builder.append("?,"); + } + builder.delete(builder.length() - 1, builder.length()); + builder.append(")"); + sql = sql + builder; + Object[] params = idList.toArray(new String[0]); + JsonObject metric = new JsonObject(); + JsonArray usedMetric = new JsonArray(); + try (ResultSet rs = client.executeQuery(sql, params)) { + while (rs.next()) { + metric.addProperty("max", rs.getLong(MemoryMetricTable.COLUMN_MAX)); + metric.addProperty("init", rs.getLong(MemoryMetricTable.COLUMN_INIT)); + usedMetric.add(rs.getLong(MemoryMetricTable.COLUMN_USED)); + } + if (usedMetric.size() == 0) { + metric.addProperty("max", 0); + metric.addProperty("init",0); + usedMetric.add(0); + } + } catch (SQLException | H2ClientException e) { + logger.error(e.getMessage(), e); + } + + metric.add("used", usedMetric); + return metric; + } +} diff --git a/apm-collector/apm-collector-ui/src/main/java/org/skywalking/apm/collector/ui/dao/MemoryPoolMetricH2DAO.java b/apm-collector/apm-collector-ui/src/main/java/org/skywalking/apm/collector/ui/dao/MemoryPoolMetricH2DAO.java new file mode 100644 index 0000000000000000000000000000000000000000..2d567f91e9f9df9b0648cf250ab624d341d01964 --- /dev/null +++ b/apm-collector/apm-collector-ui/src/main/java/org/skywalking/apm/collector/ui/dao/MemoryPoolMetricH2DAO.java @@ -0,0 +1,108 @@ +/* + * Copyright 2017, OpenSkywalking Organization All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * Project repository: https://github.com/OpenSkywalking/skywalking + */ + +package org.skywalking.apm.collector.ui.dao; + +import java.sql.ResultSet; +import java.sql.SQLException; +import java.util.ArrayList; +import java.util.List; + +import org.skywalking.apm.collector.client.h2.H2Client; +import org.skywalking.apm.collector.client.h2.H2ClientException; +import org.skywalking.apm.collector.core.util.Const; +import org.skywalking.apm.collector.core.util.TimeBucketUtils; +import org.skywalking.apm.collector.storage.define.jvm.MemoryPoolMetricTable; +import org.skywalking.apm.collector.storage.h2.SqlBuilder; +import org.skywalking.apm.collector.storage.h2.dao.H2DAO; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.google.gson.JsonArray; +import com.google.gson.JsonObject; + +/** + * @author clevertension + */ +public class MemoryPoolMetricH2DAO extends H2DAO implements IMemoryPoolMetricDAO { + private final Logger logger = LoggerFactory.getLogger(InstanceH2DAO.class); + private static final String GET_MEMORY_POOL_METRIC_SQL = "select * from {0} where {1} =?"; + private static final String GET_MEMORY_POOL_METRICS_SQL = "select * from {0} where {1} in ("; + @Override public JsonObject getMetric(int instanceId, long timeBucket, int poolType) { + H2Client client = getClient(); + String id = timeBucket + Const.ID_SPLIT + instanceId + Const.ID_SPLIT + poolType; + String sql = SqlBuilder.buildSql(GET_MEMORY_POOL_METRIC_SQL, MemoryPoolMetricTable.TABLE, "id"); + Object[] params = new Object[]{id}; + JsonObject metric = new JsonObject(); + try (ResultSet rs = client.executeQuery(sql, params)) { + if (rs.next()) { + metric.addProperty("max", rs.getInt(MemoryPoolMetricTable.COLUMN_MAX)); + metric.addProperty("init", rs.getInt(MemoryPoolMetricTable.COLUMN_INIT)); + metric.addProperty("used", rs.getInt(MemoryPoolMetricTable.COLUMN_USED)); + } else { + metric.addProperty("max", 0); + metric.addProperty("init", 0); + metric.addProperty("used", 0); + } + } catch (SQLException | H2ClientException e) { + logger.error(e.getMessage(), e); + } + return metric; + } + + @Override public JsonObject getMetric(int instanceId, long startTimeBucket, long endTimeBucket, int poolType) { + H2Client client = getClient(); + String sql = SqlBuilder.buildSql(GET_MEMORY_POOL_METRICS_SQL, MemoryPoolMetricTable.TABLE, "id"); + List idList = new ArrayList<>(); + long timeBucket = startTimeBucket; + do { + timeBucket = TimeBucketUtils.INSTANCE.addSecondForSecondTimeBucket(TimeBucketUtils.TimeBucketType.SECOND.name(), timeBucket, 1); + String id = timeBucket + Const.ID_SPLIT + instanceId + Const.ID_SPLIT + poolType; + idList.add(id); + } + while (timeBucket <= endTimeBucket); + + StringBuilder builder = new StringBuilder(); + for (int i = 0; i < idList.size(); i++) { + builder.append("?,"); + } + builder.delete(builder.length() - 1, builder.length()); + builder.append(")"); + sql = sql + builder; + Object[] params = idList.toArray(new String[0]); + JsonObject metric = new JsonObject(); + JsonArray usedMetric = new JsonArray(); + try (ResultSet rs = client.executeQuery(sql, params)) { + while (rs.next()) { + metric.addProperty("max", rs.getLong(MemoryPoolMetricTable.COLUMN_MAX)); + metric.addProperty("init", rs.getLong(MemoryPoolMetricTable.COLUMN_INIT)); + usedMetric.add(rs.getLong(MemoryPoolMetricTable.COLUMN_USED)); + } + if (usedMetric.size() == 0) { + metric.addProperty("max", 0); + metric.addProperty("init",0); + usedMetric.add(0); + } + } catch (SQLException | H2ClientException e) { + logger.error(e.getMessage(), e); + } + + metric.add("used", usedMetric); + return metric; + } +} diff --git a/apm-collector/apm-collector-ui/src/main/java/org/skywalking/apm/collector/ui/dao/NodeComponentH2DAO.java b/apm-collector/apm-collector-ui/src/main/java/org/skywalking/apm/collector/ui/dao/NodeComponentH2DAO.java index 60bb86d071bedda77a3844ae21b9f76f06a1db27..5fd855025d4f59bdcf73e9f4ce62b7892ebba833 100644 --- a/apm-collector/apm-collector-ui/src/main/java/org/skywalking/apm/collector/ui/dao/NodeComponentH2DAO.java +++ b/apm-collector/apm-collector-ui/src/main/java/org/skywalking/apm/collector/ui/dao/NodeComponentH2DAO.java @@ -18,15 +18,66 @@ package org.skywalking.apm.collector.ui.dao; -import com.google.gson.JsonArray; +import java.sql.ResultSet; +import java.sql.SQLException; + +import org.skywalking.apm.collector.client.h2.H2Client; +import org.skywalking.apm.collector.client.h2.H2ClientException; +import org.skywalking.apm.collector.core.util.StringUtils; +import org.skywalking.apm.collector.storage.define.node.NodeComponentTable; +import org.skywalking.apm.collector.storage.h2.SqlBuilder; import org.skywalking.apm.collector.storage.h2.dao.H2DAO; +import org.skywalking.apm.collector.ui.cache.ApplicationCache; +import org.skywalking.apm.network.trace.component.ComponentsDefine; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.google.gson.JsonArray; +import com.google.gson.JsonObject; /** - * @author pengys5 + * @author pengys5, clevertension */ public class NodeComponentH2DAO extends H2DAO implements INodeComponentDAO { - + private final Logger logger = LoggerFactory.getLogger(NodeComponentH2DAO.class); + private static final String AGGREGATE_COMPONENT_SQL = "select {0}, {1}, {2} from {3} where {4} >= ? and {4} <= ? group by {0}, {1}, {2} limit 100"; @Override public JsonArray load(long startTime, long endTime) { - return null; + JsonArray nodeComponentArray = new JsonArray(); + nodeComponentArray.addAll(aggregationComponent(startTime, endTime)); + return nodeComponentArray; + } + private JsonArray aggregationComponent(long startTime, long endTime) { + H2Client client = getClient(); + + JsonArray nodeComponentArray = new JsonArray(); + String sql = SqlBuilder.buildSql(AGGREGATE_COMPONENT_SQL, NodeComponentTable.COLUMN_COMPONENT_ID, + NodeComponentTable.COLUMN_PEER, NodeComponentTable.COLUMN_PEER_ID, + NodeComponentTable.TABLE, NodeComponentTable.COLUMN_TIME_BUCKET); + Object[] params = new Object[]{startTime, endTime}; + try (ResultSet rs = client.executeQuery(sql, params)) { + while (rs.next()) { + int peerId = rs.getInt(NodeComponentTable.COLUMN_PEER_ID); + int componentId = rs.getInt(NodeComponentTable.COLUMN_COMPONENT_ID); + String componentName = ComponentsDefine.getInstance().getComponentName(componentId); + if (peerId != 0) { + String peer = ApplicationCache.getForUI(peerId); + nodeComponentArray.add(buildNodeComponent(peer, componentName)); + } + String peer = rs.getString(NodeComponentTable.COLUMN_PEER); + if (StringUtils.isNotEmpty(peer)) { + nodeComponentArray.add(buildNodeComponent(peer, componentName)); + } + } + } catch (SQLException | H2ClientException e) { + logger.error(e.getMessage(), e); + } + return nodeComponentArray; + } + + private JsonObject buildNodeComponent(String peer, String componentName) { + JsonObject nodeComponentObj = new JsonObject(); + nodeComponentObj.addProperty("componentName", componentName); + nodeComponentObj.addProperty("peer", peer); + return nodeComponentObj; } } diff --git a/apm-collector/apm-collector-ui/src/main/java/org/skywalking/apm/collector/ui/dao/NodeMappingH2DAO.java b/apm-collector/apm-collector-ui/src/main/java/org/skywalking/apm/collector/ui/dao/NodeMappingH2DAO.java index 56df1a49ffad06e8502bedb383bbd5d9ede2792f..7febe8065a0db42768360514c6eac387675744ee 100644 --- a/apm-collector/apm-collector-ui/src/main/java/org/skywalking/apm/collector/ui/dao/NodeMappingH2DAO.java +++ b/apm-collector/apm-collector-ui/src/main/java/org/skywalking/apm/collector/ui/dao/NodeMappingH2DAO.java @@ -18,15 +18,60 @@ package org.skywalking.apm.collector.ui.dao; -import com.google.gson.JsonArray; +import java.sql.ResultSet; +import java.sql.SQLException; + +import org.skywalking.apm.collector.client.h2.H2Client; +import org.skywalking.apm.collector.client.h2.H2ClientException; +import org.skywalking.apm.collector.core.util.StringUtils; +import org.skywalking.apm.collector.storage.define.node.NodeMappingTable; +import org.skywalking.apm.collector.storage.h2.SqlBuilder; import org.skywalking.apm.collector.storage.h2.dao.H2DAO; +import org.skywalking.apm.collector.ui.cache.ApplicationCache; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.google.gson.JsonArray; +import com.google.gson.JsonObject; /** - * @author pengys5 + * @author pengys5, clevertension */ public class NodeMappingH2DAO extends H2DAO implements INodeMappingDAO { - + private final Logger logger = LoggerFactory.getLogger(NodeMappingH2DAO.class); + private static final String NODE_MAPPING_SQL = "select {0}, {1}, {2} from {3} where {4} >= ? and {4} <= ? group by {0}, {1}, {2} limit 100"; @Override public JsonArray load(long startTime, long endTime) { - return null; + H2Client client = getClient(); + JsonArray nodeMappingArray = new JsonArray(); + String sql = SqlBuilder.buildSql(NODE_MAPPING_SQL, NodeMappingTable.COLUMN_APPLICATION_ID, + NodeMappingTable.COLUMN_ADDRESS_ID, NodeMappingTable.COLUMN_ADDRESS, + NodeMappingTable.TABLE, NodeMappingTable.COLUMN_TIME_BUCKET); + + Object[] params = new Object[]{startTime, endTime}; + try (ResultSet rs = client.executeQuery(sql, params)) { + while (rs.next()) { + int applicationId = rs.getInt(NodeMappingTable.COLUMN_APPLICATION_ID); + String applicationCode = ApplicationCache.getForUI(applicationId); + int addressId = rs.getInt(NodeMappingTable.COLUMN_ADDRESS_ID); + if (addressId != 0) { + String address = ApplicationCache.getForUI(addressId); + JsonObject nodeMappingObj = new JsonObject(); + nodeMappingObj.addProperty("applicationCode", applicationCode); + nodeMappingObj.addProperty("address", address); + nodeMappingArray.add(nodeMappingObj); + } + String address = rs.getString(NodeMappingTable.COLUMN_ADDRESS); + if (StringUtils.isNotEmpty(address)) { + JsonObject nodeMappingObj = new JsonObject(); + nodeMappingObj.addProperty("applicationCode", applicationCode); + nodeMappingObj.addProperty("address", address); + nodeMappingArray.add(nodeMappingObj); + } + } + } catch (SQLException | H2ClientException e) { + logger.error(e.getMessage(), e); + } + logger.debug("node mapping data: {}", nodeMappingArray.toString()); + return nodeMappingArray; } } diff --git a/apm-collector/apm-collector-ui/src/main/java/org/skywalking/apm/collector/ui/dao/NodeReferenceH2DAO.java b/apm-collector/apm-collector-ui/src/main/java/org/skywalking/apm/collector/ui/dao/NodeReferenceH2DAO.java index bd5e0db79358a46b50181efb8308da8bd6791e6f..52cdf9a410fb805243c17c302c1075d9867ad556 100644 --- a/apm-collector/apm-collector-ui/src/main/java/org/skywalking/apm/collector/ui/dao/NodeReferenceH2DAO.java +++ b/apm-collector/apm-collector-ui/src/main/java/org/skywalking/apm/collector/ui/dao/NodeReferenceH2DAO.java @@ -18,14 +18,75 @@ package org.skywalking.apm.collector.ui.dao; -import com.google.gson.JsonArray; +import java.sql.ResultSet; +import java.sql.SQLException; + +import org.skywalking.apm.collector.client.h2.H2Client; +import org.skywalking.apm.collector.client.h2.H2ClientException; +import org.skywalking.apm.collector.core.util.StringUtils; +import org.skywalking.apm.collector.storage.define.noderef.NodeReferenceTable; +import org.skywalking.apm.collector.storage.h2.SqlBuilder; import org.skywalking.apm.collector.storage.h2.dao.H2DAO; +import org.skywalking.apm.collector.ui.cache.ApplicationCache; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.google.gson.JsonArray; +import com.google.gson.JsonObject; /** - * @author pengys5 + * @author pengys5, clevertension */ public class NodeReferenceH2DAO extends H2DAO implements INodeReferenceDAO { + private final Logger logger = LoggerFactory.getLogger(NodeReferenceH2DAO.class); + private static final String NODE_REFERENCE_SQL = "select {8}, {9}, {10}, sum({0}) as {0}, sum({1}) as {1}, sum({2}) as {2}, " + + "sum({3}) as {3}, sum({4}) as {4}, sum({5}) as {5} from {6} where {7} >= ? and {7} <= ? group by {8}, {9}, {10} limit 100"; @Override public JsonArray load(long startTime, long endTime) { - return null; + H2Client client = getClient(); + JsonArray nodeRefResSumArray = new JsonArray(); + String sql = SqlBuilder.buildSql(NODE_REFERENCE_SQL, NodeReferenceTable.COLUMN_S1_LTE, + NodeReferenceTable.COLUMN_S3_LTE, NodeReferenceTable.COLUMN_S5_LTE, + NodeReferenceTable.COLUMN_S5_GT, NodeReferenceTable.COLUMN_SUMMARY, + NodeReferenceTable.COLUMN_ERROR, NodeReferenceTable.TABLE, NodeReferenceTable.COLUMN_TIME_BUCKET, + NodeReferenceTable.COLUMN_FRONT_APPLICATION_ID, NodeReferenceTable.COLUMN_BEHIND_APPLICATION_ID, NodeReferenceTable.COLUMN_BEHIND_PEER); + + Object[] params = new Object[]{startTime, endTime}; + try (ResultSet rs = client.executeQuery(sql, params)) { + while (rs.next()) { + int applicationId = rs.getInt(NodeReferenceTable.COLUMN_FRONT_APPLICATION_ID); + String applicationCode = ApplicationCache.getForUI(applicationId); + int behindApplicationId = rs.getInt(NodeReferenceTable.COLUMN_BEHIND_APPLICATION_ID); + if (behindApplicationId != 0) { + String behindApplicationCode = ApplicationCache.getForUI(behindApplicationId); + + JsonObject nodeRefResSumObj = new JsonObject(); + nodeRefResSumObj.addProperty("front", applicationCode); + nodeRefResSumObj.addProperty("behind", behindApplicationCode); + nodeRefResSumObj.addProperty(NodeReferenceTable.COLUMN_S1_LTE, rs.getDouble(NodeReferenceTable.COLUMN_S1_LTE)); + nodeRefResSumObj.addProperty(NodeReferenceTable.COLUMN_S3_LTE, rs.getDouble(NodeReferenceTable.COLUMN_S3_LTE)); + nodeRefResSumObj.addProperty(NodeReferenceTable.COLUMN_S5_LTE, rs.getDouble(NodeReferenceTable.COLUMN_S5_LTE)); + nodeRefResSumObj.addProperty(NodeReferenceTable.COLUMN_S5_GT, rs.getDouble(NodeReferenceTable.COLUMN_S5_GT)); + nodeRefResSumObj.addProperty(NodeReferenceTable.COLUMN_ERROR, rs.getDouble(NodeReferenceTable.COLUMN_ERROR)); + nodeRefResSumObj.addProperty(NodeReferenceTable.COLUMN_SUMMARY, rs.getDouble(NodeReferenceTable.COLUMN_SUMMARY)); + nodeRefResSumArray.add(nodeRefResSumObj); + } + String behindPeer = rs.getString(NodeReferenceTable.COLUMN_BEHIND_PEER); + if (StringUtils.isNotEmpty(behindPeer)) { + JsonObject nodeRefResSumObj = new JsonObject(); + nodeRefResSumObj.addProperty("front", applicationCode); + nodeRefResSumObj.addProperty("behind", behindPeer); + nodeRefResSumObj.addProperty(NodeReferenceTable.COLUMN_S1_LTE, rs.getDouble(NodeReferenceTable.COLUMN_S1_LTE)); + nodeRefResSumObj.addProperty(NodeReferenceTable.COLUMN_S3_LTE, rs.getDouble(NodeReferenceTable.COLUMN_S3_LTE)); + nodeRefResSumObj.addProperty(NodeReferenceTable.COLUMN_S5_LTE, rs.getDouble(NodeReferenceTable.COLUMN_S5_LTE)); + nodeRefResSumObj.addProperty(NodeReferenceTable.COLUMN_S5_GT, rs.getDouble(NodeReferenceTable.COLUMN_S5_GT)); + nodeRefResSumObj.addProperty(NodeReferenceTable.COLUMN_ERROR, rs.getDouble(NodeReferenceTable.COLUMN_ERROR)); + nodeRefResSumObj.addProperty(NodeReferenceTable.COLUMN_SUMMARY, rs.getDouble(NodeReferenceTable.COLUMN_SUMMARY)); + nodeRefResSumArray.add(nodeRefResSumObj); + } + } + } catch (SQLException | H2ClientException e) { + logger.error(e.getMessage(), e); + } + return nodeRefResSumArray; } } diff --git a/apm-collector/apm-collector-ui/src/main/java/org/skywalking/apm/collector/ui/dao/SegmentCostH2DAO.java b/apm-collector/apm-collector-ui/src/main/java/org/skywalking/apm/collector/ui/dao/SegmentCostH2DAO.java index 98734f3943bfe7962d3a7741e5e51306e1a2098e..b992c69478d5c8fa5ded1f80b7d68922de29c1d3 100644 --- a/apm-collector/apm-collector-ui/src/main/java/org/skywalking/apm/collector/ui/dao/SegmentCostH2DAO.java +++ b/apm-collector/apm-collector-ui/src/main/java/org/skywalking/apm/collector/ui/dao/SegmentCostH2DAO.java @@ -18,16 +18,142 @@ package org.skywalking.apm.collector.ui.dao; -import com.google.gson.JsonObject; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.util.ArrayList; import java.util.List; + +import org.elasticsearch.search.sort.SortOrder; +import org.skywalking.apm.collector.client.h2.H2Client; +import org.skywalking.apm.collector.client.h2.H2ClientException; +import org.skywalking.apm.collector.core.util.CollectionUtils; +import org.skywalking.apm.collector.core.util.StringUtils; +import org.skywalking.apm.collector.storage.dao.DAOContainer; +import org.skywalking.apm.collector.storage.define.global.GlobalTraceTable; +import org.skywalking.apm.collector.storage.define.segment.SegmentCostTable; +import org.skywalking.apm.collector.storage.h2.SqlBuilder; import org.skywalking.apm.collector.storage.h2.dao.H2DAO; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.google.gson.JsonArray; +import com.google.gson.JsonObject; /** - * @author pengys5 + * @author pengys5, clevertension */ public class SegmentCostH2DAO extends H2DAO implements ISegmentCostDAO { + private final Logger logger = LoggerFactory.getLogger(SegmentCostH2DAO.class); + private static final String GET_SEGMENT_COST_SQL = "select * from {0} where {1} >= ? and {1} <= ?"; @Override public JsonObject loadTop(long startTime, long endTime, long minCost, long maxCost, String operationName, Error error, int applicationId, List segmentIds, int limit, int from, Sort sort) { - return null; + H2Client client = getClient(); + String sql = GET_SEGMENT_COST_SQL; + List params = new ArrayList<>(); + List columns = new ArrayList<>(); + columns.add(SegmentCostTable.TABLE); + columns.add(SegmentCostTable.COLUMN_TIME_BUCKET); + params.add(startTime); + params.add(endTime); + int paramIndex = 1; + if (minCost != -1 || maxCost != -1) { + if (minCost != -1) { + paramIndex++; + sql = sql + " and {" + paramIndex + "} >= ?"; + params.add(minCost); + columns.add(SegmentCostTable.COLUMN_COST); + } + if (maxCost != -1) { + paramIndex++; + sql = sql + " and {" + paramIndex + "} <= ?"; + params.add(maxCost); + columns.add(SegmentCostTable.COLUMN_COST); + } + } + if (StringUtils.isNotEmpty(operationName)) { + paramIndex++; + sql = sql + " and {" + paramIndex + "} = ?"; + params.add(operationName); + columns.add(SegmentCostTable.COLUMN_SERVICE_NAME); + } + if (CollectionUtils.isNotEmpty(segmentIds)) { + paramIndex++; + sql = sql + " and {" + paramIndex + "} in ("; + columns.add(SegmentCostTable.COLUMN_SEGMENT_ID); + StringBuilder builder = new StringBuilder(); + for (int i = 0; i < segmentIds.size(); i++) { + builder.append("?,"); + } + builder.delete(builder.length() - 1, builder.length()); + builder.append(")"); + sql = sql + builder; + for (String segmentId : segmentIds) { + params.add(segmentId); + } + } + if (Error.True.equals(error)) { + paramIndex++; + sql = sql + " and {" + paramIndex + "} = ?"; + params.add(true); + columns.add(SegmentCostTable.COLUMN_IS_ERROR); + } else if (Error.False.equals(error)) { + paramIndex++; + sql = sql + " and {" + paramIndex + "} = ?"; + params.add(false); + columns.add(SegmentCostTable.COLUMN_IS_ERROR); + } + if (applicationId != 0) { + paramIndex++; + sql = sql + " and {" + paramIndex + "} = ?"; + params.add(applicationId); + columns.add(SegmentCostTable.COLUMN_APPLICATION_ID); + } + + if (Sort.Cost.equals(sort)) { + sql = sql + " order by " + SegmentCostTable.COLUMN_COST + " " + SortOrder.DESC; + } else if (Sort.Time.equals(sort)) { + sql = sql + " order by " + SegmentCostTable.COLUMN_START_TIME + " " + SortOrder.DESC; + } + + sql = sql + " limit " + from + "," + limit; + sql = SqlBuilder.buildSql(sql, columns); + Object[] p = params.toArray(new Object[0]); + + JsonObject topSegPaging = new JsonObject(); + + + JsonArray topSegArray = new JsonArray(); + topSegPaging.add("data", topSegArray); + int cnt = 0; + int num = from; + try (ResultSet rs = client.executeQuery(sql, p)) { + while (rs.next()) { + JsonObject topSegmentJson = new JsonObject(); + topSegmentJson.addProperty("num", num); + String segmentId = rs.getString(SegmentCostTable.COLUMN_SEGMENT_ID); + topSegmentJson.addProperty(SegmentCostTable.COLUMN_SEGMENT_ID, segmentId); + topSegmentJson.addProperty(SegmentCostTable.COLUMN_START_TIME, rs.getLong(SegmentCostTable.COLUMN_START_TIME)); + topSegmentJson.addProperty(SegmentCostTable.COLUMN_END_TIME, rs.getLong(SegmentCostTable.COLUMN_END_TIME)); + + IGlobalTraceDAO globalTraceDAO = (IGlobalTraceDAO) DAOContainer.INSTANCE.get(IGlobalTraceDAO.class.getName()); + List globalTraces = globalTraceDAO.getGlobalTraceId(segmentId); + if (CollectionUtils.isNotEmpty(globalTraces)) { + topSegmentJson.addProperty(GlobalTraceTable.COLUMN_GLOBAL_TRACE_ID, globalTraces.get(0)); + } + + topSegmentJson.addProperty(SegmentCostTable.COLUMN_APPLICATION_ID, rs.getInt(SegmentCostTable.COLUMN_APPLICATION_ID)); + topSegmentJson.addProperty(SegmentCostTable.COLUMN_SERVICE_NAME, rs.getString(SegmentCostTable.COLUMN_SERVICE_NAME)); + topSegmentJson.addProperty(SegmentCostTable.COLUMN_COST, rs.getLong(SegmentCostTable.COLUMN_COST)); + topSegmentJson.addProperty(SegmentCostTable.COLUMN_IS_ERROR, rs.getBoolean(SegmentCostTable.COLUMN_IS_ERROR)); + + num++; + topSegArray.add(topSegmentJson); + cnt++; + } + } catch (SQLException | H2ClientException e) { + logger.error(e.getMessage(), e); + } + topSegPaging.addProperty("recordsTotal", cnt); + return topSegPaging; } } diff --git a/apm-collector/apm-collector-ui/src/main/java/org/skywalking/apm/collector/ui/dao/SegmentH2DAO.java b/apm-collector/apm-collector-ui/src/main/java/org/skywalking/apm/collector/ui/dao/SegmentH2DAO.java index 4d20f480c2d4a4f7dcb84dd34546ab68251e36f2..079e2dc12e481d92356e4fe7a8ae0d531b5cfbda 100644 --- a/apm-collector/apm-collector-ui/src/main/java/org/skywalking/apm/collector/ui/dao/SegmentH2DAO.java +++ b/apm-collector/apm-collector-ui/src/main/java/org/skywalking/apm/collector/ui/dao/SegmentH2DAO.java @@ -18,14 +18,48 @@ package org.skywalking.apm.collector.ui.dao; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.util.Base64; + +import org.skywalking.apm.collector.client.h2.H2Client; +import org.skywalking.apm.collector.client.h2.H2ClientException; +import org.skywalking.apm.collector.core.util.StringUtils; +import org.skywalking.apm.collector.storage.define.segment.SegmentTable; +import org.skywalking.apm.collector.storage.h2.SqlBuilder; import org.skywalking.apm.collector.storage.h2.dao.H2DAO; import org.skywalking.apm.network.proto.TraceSegmentObject; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.google.protobuf.InvalidProtocolBufferException; /** - * @author pengys5 + * @author pengys5, clevertension */ public class SegmentH2DAO extends H2DAO implements ISegmentDAO { + private final Logger logger = LoggerFactory.getLogger(SegmentH2DAO.class); + private static final String GET_SEGMENT_SQL = "select {0} from {1} where {2} = ?"; @Override public TraceSegmentObject load(String segmentId) { + H2Client client = getClient(); + String sql = SqlBuilder.buildSql(GET_SEGMENT_SQL, SegmentTable.COLUMN_DATA_BINARY, + SegmentTable.TABLE, "id"); + Object[] params = new Object[]{segmentId}; + try (ResultSet rs = client.executeQuery(sql, params)) { + if (rs.next()) { + String dataBinaryBase64 = rs.getString(SegmentTable.COLUMN_DATA_BINARY); + if (StringUtils.isNotEmpty(dataBinaryBase64)) { + byte[] dataBinary = Base64.getDecoder().decode(dataBinaryBase64); + try { + return TraceSegmentObject.parseFrom(dataBinary); + } catch (InvalidProtocolBufferException e) { + logger.error(e.getMessage(), e); + } + } + } + } catch (SQLException | H2ClientException e) { + logger.error(e.getMessage(), e); + } return null; } } diff --git a/apm-collector/apm-collector-ui/src/main/java/org/skywalking/apm/collector/ui/dao/ServiceEntryH2DAO.java b/apm-collector/apm-collector-ui/src/main/java/org/skywalking/apm/collector/ui/dao/ServiceEntryH2DAO.java index 02a166e5a443f9be13f659611bbf180b55889b61..dcf71a00a8898159d5fbd617732355ddefee12b4 100644 --- a/apm-collector/apm-collector-ui/src/main/java/org/skywalking/apm/collector/ui/dao/ServiceEntryH2DAO.java +++ b/apm-collector/apm-collector-ui/src/main/java/org/skywalking/apm/collector/ui/dao/ServiceEntryH2DAO.java @@ -18,15 +18,82 @@ package org.skywalking.apm.collector.ui.dao; -import com.google.gson.JsonObject; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.util.ArrayList; +import java.util.List; + +import org.skywalking.apm.collector.client.h2.H2Client; +import org.skywalking.apm.collector.client.h2.H2ClientException; +import org.skywalking.apm.collector.core.util.ColumnNameUtils; +import org.skywalking.apm.collector.core.util.StringUtils; +import org.skywalking.apm.collector.storage.define.service.ServiceEntryTable; +import org.skywalking.apm.collector.storage.h2.SqlBuilder; import org.skywalking.apm.collector.storage.h2.dao.H2DAO; +import org.skywalking.apm.collector.ui.cache.ApplicationCache; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.google.gson.JsonArray; +import com.google.gson.JsonObject; /** * @author pengys5 */ public class ServiceEntryH2DAO extends H2DAO implements IServiceEntryDAO { + private final Logger logger = LoggerFactory.getLogger(SegmentH2DAO.class); + private static final String GET_SERVICE_ENTRY_SQL = "select * from {0} where {1} >= ? and {2} <= ?"; @Override public JsonObject load(int applicationId, String entryServiceName, long startTime, long endTime, int from, int size) { - return null; + H2Client client = getClient(); + String sql = GET_SERVICE_ENTRY_SQL; + List params = new ArrayList<>(); + List columns = new ArrayList<>(); + columns.add(ServiceEntryTable.TABLE); + columns.add(ServiceEntryTable.COLUMN_NEWEST_TIME); + columns.add(ServiceEntryTable.COLUMN_REGISTER_TIME); + params.add(startTime); + params.add(endTime); + int paramIndex = 2; + if (applicationId != 0) { + paramIndex++; + sql = sql + " and {" + paramIndex + "} = ?"; + params.add(applicationId); + columns.add(ServiceEntryTable.COLUMN_APPLICATION_ID); + } + if (StringUtils.isNotEmpty(entryServiceName)) { + paramIndex++; + sql = sql + " and {" + paramIndex + "} = ?"; + params.add(entryServiceName); + columns.add(ServiceEntryTable.COLUMN_ENTRY_SERVICE_NAME); + } + sql = sql + " limit " + from + "," + size; + sql = SqlBuilder.buildSql(sql, columns); + Object[] p = params.toArray(new Object[0]); + JsonArray serviceArray = new JsonArray(); + JsonObject response = new JsonObject(); + int index = 0; + try (ResultSet rs = client.executeQuery(sql, p)) { + while (rs.next()) { + int appId = rs.getInt(ServiceEntryTable.COLUMN_APPLICATION_ID); + int entryServiceId = rs.getInt(ServiceEntryTable.COLUMN_ENTRY_SERVICE_ID); + String applicationCode = ApplicationCache.getForUI(applicationId); + String entryServiceName1 = rs.getString(ServiceEntryTable.COLUMN_ENTRY_SERVICE_NAME); + + JsonObject row = new JsonObject(); + row.addProperty(ColumnNameUtils.INSTANCE.rename(ServiceEntryTable.COLUMN_ENTRY_SERVICE_ID), entryServiceId); + row.addProperty(ColumnNameUtils.INSTANCE.rename(ServiceEntryTable.COLUMN_ENTRY_SERVICE_NAME), entryServiceName1); + row.addProperty(ColumnNameUtils.INSTANCE.rename(ServiceEntryTable.COLUMN_APPLICATION_ID), appId); + row.addProperty("applicationCode", applicationCode); + serviceArray.add(row); + index++; + } + } catch (SQLException | H2ClientException e) { + logger.error(e.getMessage(), e); + } + response.addProperty("total", index); + response.add("array", serviceArray); + + return response; } } diff --git a/apm-collector/apm-collector-ui/src/main/java/org/skywalking/apm/collector/ui/dao/ServiceReferenceH2DAO.java b/apm-collector/apm-collector-ui/src/main/java/org/skywalking/apm/collector/ui/dao/ServiceReferenceH2DAO.java index d0d745ace235b9c767fec9724247308aaaf3801a..37a818e0a12401898283efb2f7f75dc4a0ececa0 100644 --- a/apm-collector/apm-collector-ui/src/main/java/org/skywalking/apm/collector/ui/dao/ServiceReferenceH2DAO.java +++ b/apm-collector/apm-collector-ui/src/main/java/org/skywalking/apm/collector/ui/dao/ServiceReferenceH2DAO.java @@ -18,19 +18,263 @@ package org.skywalking.apm.collector.ui.dao; -import com.google.gson.JsonArray; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.util.Iterator; +import java.util.LinkedHashMap; +import java.util.Map; + +import org.skywalking.apm.collector.client.h2.H2Client; +import org.skywalking.apm.collector.client.h2.H2ClientException; +import org.skywalking.apm.collector.core.util.ColumnNameUtils; +import org.skywalking.apm.collector.core.util.Const; +import org.skywalking.apm.collector.core.util.ObjectUtils; +import org.skywalking.apm.collector.core.util.StringUtils; +import org.skywalking.apm.collector.storage.define.serviceref.ServiceReferenceTable; +import org.skywalking.apm.collector.storage.h2.SqlBuilder; import org.skywalking.apm.collector.storage.h2.dao.H2DAO; +import org.skywalking.apm.collector.ui.cache.ServiceIdCache; +import org.skywalking.apm.collector.ui.cache.ServiceNameCache; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.google.gson.JsonArray; +import com.google.gson.JsonObject; /** - * @author pengys5 + * @author pengys5, clevertension */ public class ServiceReferenceH2DAO extends H2DAO implements IServiceReferenceDAO { + private final Logger logger = LoggerFactory.getLogger(ServiceReferenceH2DAO.class); + + private static final String GET_SRV_REF_LOAD1 = "select {4}, {5}, {6}, {7}, sum({8}) as cnt1, sum({9}) as cnt2, sum({10}) as cnt3" + + ",sum({11}) as cnt4, sum({12}) cnt5, sum({13}) as cnt6, sum({14}) as cnt7 from {0} where {1} >= ? and {1} <= ? and {2} = ? and {3} = ? group by {4}, {5}, {6}, {7}"; + private static final String GET_SRV_REF_LOAD2 = "select {3}, {4}, {5}, {6}, sum({7}) as cnt1, sum({8}) as cnt2, sum({9}) as cnt3" + + ",sum({10}) as cnt4, sum({11}) cnt5, sum({12}) as cnt6, sum({13}) as cnt7 from {0} where {1} >= ? and {1} <= ? and {2} = ? group by {3}, {4}, {5}, {6}"; @Override public JsonArray load(int entryServiceId, long startTime, long endTime) { + H2Client client = getClient(); + String sql = SqlBuilder.buildSql(GET_SRV_REF_LOAD1, ServiceReferenceTable.TABLE, + ServiceReferenceTable.COLUMN_TIME_BUCKET, ServiceReferenceTable.COLUMN_ENTRY_SERVICE_ID, ServiceReferenceTable.COLUMN_ENTRY_SERVICE_NAME, + ServiceReferenceTable.COLUMN_FRONT_SERVICE_ID, ServiceReferenceTable.COLUMN_BEHIND_SERVICE_ID, + ServiceReferenceTable.COLUMN_FRONT_SERVICE_NAME, ServiceReferenceTable.COLUMN_BEHIND_SERVICE_NAME, + ServiceReferenceTable.COLUMN_S1_LTE, ServiceReferenceTable.COLUMN_S3_LTE, ServiceReferenceTable.COLUMN_S5_LTE, + ServiceReferenceTable.COLUMN_S5_GT, ServiceReferenceTable.COLUMN_ERROR, ServiceReferenceTable.COLUMN_SUMMARY, + ServiceReferenceTable.COLUMN_COST_SUMMARY); + String entryServiceName = ServiceNameCache.get(entryServiceId); + Object[] params = new Object[]{startTime, endTime, entryServiceId, entryServiceName}; + try (ResultSet rs = client.executeQuery(sql, params)) { + if (rs.next()) { + Map serviceReferenceMap = new LinkedHashMap<>(); + + int frontServiceId = rs.getInt(ServiceReferenceTable.COLUMN_FRONT_SERVICE_ID); + if (frontServiceId != 0) { + parseSubAggregate(serviceReferenceMap, rs, frontServiceId); + } + + String frontServiceName = rs.getString(ServiceReferenceTable.COLUMN_FRONT_SERVICE_NAME); + if (StringUtils.isNotEmpty(frontServiceName)) { + String[] serviceNames = frontServiceName.split(Const.ID_SPLIT); + int frontServiceId1 = ServiceIdCache.getForUI(Integer.parseInt(serviceNames[0]), serviceNames[1]); + parseSubAggregate(serviceReferenceMap, rs, frontServiceId1); + } + + JsonArray serviceReferenceArray = new JsonArray(); + JsonObject rootServiceReference = findRoot(serviceReferenceMap); + if (ObjectUtils.isNotEmpty(rootServiceReference)) { + serviceReferenceArray.add(rootServiceReference); + String id = rootServiceReference.get(ColumnNameUtils.INSTANCE.rename(ServiceReferenceTable.COLUMN_FRONT_SERVICE_ID)) + Const.ID_SPLIT + rootServiceReference.get(ColumnNameUtils.INSTANCE.rename(ServiceReferenceTable.COLUMN_BEHIND_SERVICE_ID)); + serviceReferenceMap.remove(id); + + int rootServiceId = rootServiceReference.get(ColumnNameUtils.INSTANCE.rename(ServiceReferenceTable.COLUMN_BEHIND_SERVICE_ID)).getAsInt(); + sortAsTree(rootServiceId, serviceReferenceArray, serviceReferenceMap); + } + return serviceReferenceArray; + } + } catch (SQLException | H2ClientException e) { + logger.error(e.getMessage(), e); + } return null; } @Override public JsonArray load(String entryServiceName, int entryApplicationId, long startTime, long endTime) { + H2Client client = getClient(); + String sql = SqlBuilder.buildSql(GET_SRV_REF_LOAD2, ServiceReferenceTable.TABLE, + ServiceReferenceTable.COLUMN_TIME_BUCKET, ServiceReferenceTable.COLUMN_ENTRY_SERVICE_NAME, + ServiceReferenceTable.COLUMN_FRONT_SERVICE_ID, ServiceReferenceTable.COLUMN_BEHIND_SERVICE_ID, + ServiceReferenceTable.COLUMN_FRONT_SERVICE_NAME, ServiceReferenceTable.COLUMN_BEHIND_SERVICE_NAME, + ServiceReferenceTable.COLUMN_S1_LTE, ServiceReferenceTable.COLUMN_S3_LTE, ServiceReferenceTable.COLUMN_S5_LTE, + ServiceReferenceTable.COLUMN_S5_GT, ServiceReferenceTable.COLUMN_ERROR, ServiceReferenceTable.COLUMN_SUMMARY, + ServiceReferenceTable.COLUMN_COST_SUMMARY); + entryServiceName = entryApplicationId + Const.ID_SPLIT + entryServiceName; + Object[] params = new Object[]{startTime, endTime, entryServiceName}; + int entryServiceId = ServiceIdCache.get(entryApplicationId, entryServiceName); + if (entryServiceId != 0) { + sql = SqlBuilder.buildSql(GET_SRV_REF_LOAD1, ServiceReferenceTable.TABLE, + ServiceReferenceTable.COLUMN_TIME_BUCKET, ServiceReferenceTable.COLUMN_ENTRY_SERVICE_ID, ServiceReferenceTable.COLUMN_ENTRY_SERVICE_NAME, + ServiceReferenceTable.COLUMN_FRONT_SERVICE_ID, ServiceReferenceTable.COLUMN_BEHIND_SERVICE_ID, + ServiceReferenceTable.COLUMN_FRONT_SERVICE_NAME, ServiceReferenceTable.COLUMN_BEHIND_SERVICE_NAME, + ServiceReferenceTable.COLUMN_S1_LTE, ServiceReferenceTable.COLUMN_S3_LTE, ServiceReferenceTable.COLUMN_S5_LTE, + ServiceReferenceTable.COLUMN_S5_GT, ServiceReferenceTable.COLUMN_ERROR, ServiceReferenceTable.COLUMN_SUMMARY, + ServiceReferenceTable.COLUMN_COST_SUMMARY); + params = new Object[]{startTime, endTime, entryServiceId, entryServiceName}; + } + + try (ResultSet rs = client.executeQuery(sql, params)) { + if (rs.next()) { + Map serviceReferenceMap = new LinkedHashMap<>(); + + int frontServiceId = rs.getInt(ServiceReferenceTable.COLUMN_FRONT_SERVICE_ID); + if (frontServiceId != 0) { + parseSubAggregate(serviceReferenceMap, rs, frontServiceId); + } + + String frontServiceName = rs.getString(ServiceReferenceTable.COLUMN_FRONT_SERVICE_NAME); + if (StringUtils.isNotEmpty(frontServiceName)) { + String[] serviceNames = frontServiceName.split(Const.ID_SPLIT); + int frontServiceId1 = ServiceIdCache.getForUI(Integer.parseInt(serviceNames[0]), serviceNames[1]); + parseSubAggregate(serviceReferenceMap, rs, frontServiceId1); + } + + JsonArray serviceReferenceArray = new JsonArray(); + JsonObject rootServiceReference = findRoot(serviceReferenceMap); + if (ObjectUtils.isNotEmpty(rootServiceReference)) { + serviceReferenceArray.add(rootServiceReference); + String id = rootServiceReference.get(ColumnNameUtils.INSTANCE.rename(ServiceReferenceTable.COLUMN_FRONT_SERVICE_ID)) + Const.ID_SPLIT + rootServiceReference.get(ColumnNameUtils.INSTANCE.rename(ServiceReferenceTable.COLUMN_BEHIND_SERVICE_ID)); + serviceReferenceMap.remove(id); + + int rootServiceId = rootServiceReference.get(ColumnNameUtils.INSTANCE.rename(ServiceReferenceTable.COLUMN_BEHIND_SERVICE_ID)).getAsInt(); + sortAsTree(rootServiceId, serviceReferenceArray, serviceReferenceMap); + } + return serviceReferenceArray; + } + } catch (SQLException | H2ClientException e) { + logger.error(e.getMessage(), e); + } + return null; + } + + private void parseSubAggregate(Map serviceReferenceMap, + ResultSet rs, + int frontServiceId) { + try { + int behindServiceId = rs.getInt(ServiceReferenceTable.COLUMN_BEHIND_SERVICE_ID); + if (behindServiceId != 0) { + long s1LteSum = rs.getLong("cnt1"); + long s3LteSum = rs.getLong("cnt2"); + long s5LteSum = rs.getLong("cnt3"); + long s5GtSum = rs.getLong("cnt3"); + long error = rs.getLong("cnt3"); + long summary = rs.getLong("cnt3"); + long costSum = rs.getLong("cnt3"); + + String frontServiceName = ServiceNameCache.getForUI(frontServiceId); + if (StringUtils.isNotEmpty(frontServiceName)) { + frontServiceName = frontServiceName.split(Const.ID_SPLIT)[1]; + } + String behindServiceName = ServiceNameCache.getForUI(behindServiceId); + if (StringUtils.isNotEmpty(frontServiceName)) { + behindServiceName = behindServiceName.split(Const.ID_SPLIT)[1]; + } + + JsonObject serviceReference = new JsonObject(); + serviceReference.addProperty(ColumnNameUtils.INSTANCE.rename(ServiceReferenceTable.COLUMN_FRONT_SERVICE_ID), frontServiceId); + serviceReference.addProperty(ColumnNameUtils.INSTANCE.rename(ServiceReferenceTable.COLUMN_FRONT_SERVICE_NAME), frontServiceName); + serviceReference.addProperty(ColumnNameUtils.INSTANCE.rename(ServiceReferenceTable.COLUMN_BEHIND_SERVICE_ID), behindServiceId); + serviceReference.addProperty(ColumnNameUtils.INSTANCE.rename(ServiceReferenceTable.COLUMN_BEHIND_SERVICE_NAME), behindServiceName); + serviceReference.addProperty(ColumnNameUtils.INSTANCE.rename(ServiceReferenceTable.COLUMN_S1_LTE), s1LteSum); + serviceReference.addProperty(ColumnNameUtils.INSTANCE.rename(ServiceReferenceTable.COLUMN_S3_LTE), s3LteSum); + serviceReference.addProperty(ColumnNameUtils.INSTANCE.rename(ServiceReferenceTable.COLUMN_S5_LTE), s5LteSum); + serviceReference.addProperty(ColumnNameUtils.INSTANCE.rename(ServiceReferenceTable.COLUMN_S5_GT), s5GtSum); + serviceReference.addProperty(ColumnNameUtils.INSTANCE.rename(ServiceReferenceTable.COLUMN_ERROR), error); + serviceReference.addProperty(ColumnNameUtils.INSTANCE.rename(ServiceReferenceTable.COLUMN_SUMMARY), summary); + serviceReference.addProperty(ColumnNameUtils.INSTANCE.rename(ServiceReferenceTable.COLUMN_COST_SUMMARY), costSum); + merge(serviceReferenceMap, serviceReference); + } + } catch (SQLException e) { + logger.error(e.getMessage(), e); + } + + try { + String behindServiceName = rs.getString(ServiceReferenceTable.COLUMN_BEHIND_SERVICE_NAME); + if (StringUtils.isNotEmpty(behindServiceName)) { + long s1LteSum = rs.getLong("cnt1"); + long s3LteSum = rs.getLong("cnt2"); + long s5LteSum = rs.getLong("cnt3"); + long s5GtSum = rs.getLong("cnt3"); + long error = rs.getLong("cnt3"); + long summary = rs.getLong("cnt3"); + long costSum = rs.getLong("cnt3"); + + String frontServiceName = ServiceNameCache.getForUI(frontServiceId); + String[] serviceNames = behindServiceName.split(Const.ID_SPLIT); + int behindServiceId = ServiceIdCache.getForUI(Integer.parseInt(serviceNames[0]), serviceNames[1]); + behindServiceName = serviceNames[1]; + + JsonObject serviceReference = new JsonObject(); + serviceReference.addProperty(ColumnNameUtils.INSTANCE.rename(ServiceReferenceTable.COLUMN_FRONT_SERVICE_ID), frontServiceId); + serviceReference.addProperty(ColumnNameUtils.INSTANCE.rename(ServiceReferenceTable.COLUMN_FRONT_SERVICE_NAME), frontServiceName); + serviceReference.addProperty(ColumnNameUtils.INSTANCE.rename(ServiceReferenceTable.COLUMN_BEHIND_SERVICE_ID), behindServiceId); + serviceReference.addProperty(ColumnNameUtils.INSTANCE.rename(ServiceReferenceTable.COLUMN_BEHIND_SERVICE_NAME), behindServiceName); + serviceReference.addProperty(ColumnNameUtils.INSTANCE.rename(ServiceReferenceTable.COLUMN_S1_LTE), s1LteSum); + serviceReference.addProperty(ColumnNameUtils.INSTANCE.rename(ServiceReferenceTable.COLUMN_S3_LTE), s3LteSum); + serviceReference.addProperty(ColumnNameUtils.INSTANCE.rename(ServiceReferenceTable.COLUMN_S5_LTE), s5LteSum); + serviceReference.addProperty(ColumnNameUtils.INSTANCE.rename(ServiceReferenceTable.COLUMN_S5_GT), s5GtSum); + serviceReference.addProperty(ColumnNameUtils.INSTANCE.rename(ServiceReferenceTable.COLUMN_ERROR), error); + serviceReference.addProperty(ColumnNameUtils.INSTANCE.rename(ServiceReferenceTable.COLUMN_SUMMARY), summary); + serviceReference.addProperty(ColumnNameUtils.INSTANCE.rename(ServiceReferenceTable.COLUMN_COST_SUMMARY), costSum); + merge(serviceReferenceMap, serviceReference); + } + } catch (SQLException e) { + logger.error(e.getMessage(), e); + } + } + + private void merge(Map serviceReferenceMap, JsonObject serviceReference) { + String id = serviceReference.get(ColumnNameUtils.INSTANCE.rename(ServiceReferenceTable.COLUMN_FRONT_SERVICE_ID)) + Const.ID_SPLIT + serviceReference.get(ColumnNameUtils.INSTANCE.rename(ServiceReferenceTable.COLUMN_BEHIND_SERVICE_ID)); + + if (serviceReferenceMap.containsKey(id)) { + JsonObject reference = serviceReferenceMap.get(id); + add(reference, serviceReference, ColumnNameUtils.INSTANCE.rename(ServiceReferenceTable.COLUMN_S1_LTE)); + add(reference, serviceReference, ColumnNameUtils.INSTANCE.rename(ServiceReferenceTable.COLUMN_S3_LTE)); + add(reference, serviceReference, ColumnNameUtils.INSTANCE.rename(ServiceReferenceTable.COLUMN_S5_LTE)); + add(reference, serviceReference, ColumnNameUtils.INSTANCE.rename(ServiceReferenceTable.COLUMN_S5_GT)); + add(reference, serviceReference, ColumnNameUtils.INSTANCE.rename(ServiceReferenceTable.COLUMN_ERROR)); + add(reference, serviceReference, ColumnNameUtils.INSTANCE.rename(ServiceReferenceTable.COLUMN_SUMMARY)); + add(reference, serviceReference, ColumnNameUtils.INSTANCE.rename(ServiceReferenceTable.COLUMN_COST_SUMMARY)); + } else { + serviceReferenceMap.put(id, serviceReference); + } + } + + private void add(JsonObject oldReference, JsonObject newReference, String key) { + long oldValue = oldReference.get(key).getAsLong(); + long newValue = newReference.get(key).getAsLong(); + oldReference.addProperty(key, oldValue + newValue); + } + + private JsonObject findRoot(Map serviceReferenceMap) { + for (JsonObject serviceReference : serviceReferenceMap.values()) { + int frontServiceId = serviceReference.get(ColumnNameUtils.INSTANCE.rename(ServiceReferenceTable.COLUMN_FRONT_SERVICE_ID)).getAsInt(); + if (frontServiceId == 1) { + return serviceReference; + } + } return null; } + + private void sortAsTree(int serviceId, JsonArray serviceReferenceArray, + Map serviceReferenceMap) { + Iterator iterator = serviceReferenceMap.values().iterator(); + while (iterator.hasNext()) { + JsonObject serviceReference = iterator.next(); + int frontServiceId = serviceReference.get(ColumnNameUtils.INSTANCE.rename(ServiceReferenceTable.COLUMN_FRONT_SERVICE_ID)).getAsInt(); + if (serviceId == frontServiceId) { + serviceReferenceArray.add(serviceReference); + + int behindServiceId = serviceReference.get(ColumnNameUtils.INSTANCE.rename(ServiceReferenceTable.COLUMN_BEHIND_SERVICE_ID)).getAsInt(); + sortAsTree(behindServiceId, serviceReferenceArray, serviceReferenceMap); + } + } + } } diff --git a/apm-collector/apm-collector-ui/src/main/java/org/skywalking/apm/collector/ui/service/InstanceHealthService.java b/apm-collector/apm-collector-ui/src/main/java/org/skywalking/apm/collector/ui/service/InstanceHealthService.java index ef7d82c9543d63137b1454124aaf3cb5163fe7b4..3a739522f3910911cd83fe8e6f250e2f332648ba 100644 --- a/apm-collector/apm-collector-ui/src/main/java/org/skywalking/apm/collector/ui/service/InstanceHealthService.java +++ b/apm-collector/apm-collector-ui/src/main/java/org/skywalking/apm/collector/ui/service/InstanceHealthService.java @@ -59,10 +59,14 @@ public class InstanceHealthService { IGCMetricDAO gcMetricDAO = (IGCMetricDAO)DAOContainer.INSTANCE.get(IGCMetricDAO.class.getName()); JsonObject instanceJson = new JsonObject(); instanceJson.addProperty("id", instance.getInstanceId()); - instanceJson.addProperty("tps", performance.getCalls()); + if (performance != null) { + instanceJson.addProperty("tps", performance.getCalls()); + } else { + instanceJson.addProperty("tps", 0); + } int avg = 0; - if (performance.getCalls() != 0) { + if (performance != null && performance.getCalls() != 0) { avg = (int)(performance.getCostTotal() / performance.getCalls()); } instanceJson.addProperty("avg", avg); diff --git a/apm-collector/apm-collector-ui/src/main/resources/META-INF/defines/h2_dao.define b/apm-collector/apm-collector-ui/src/main/resources/META-INF/defines/h2_dao.define index f69604fec6684968d9e1fe6d742ee80701b8c8fe..bc4d41f8b9c743dd4299292ef606d596ad3dce29 100644 --- a/apm-collector/apm-collector-ui/src/main/resources/META-INF/defines/h2_dao.define +++ b/apm-collector/apm-collector-ui/src/main/resources/META-INF/defines/h2_dao.define @@ -6,6 +6,9 @@ org.skywalking.apm.collector.ui.dao.GlobalTraceH2DAO org.skywalking.apm.collector.ui.dao.SegmentH2DAO org.skywalking.apm.collector.ui.dao.InstanceH2DAO org.skywalking.apm.collector.ui.dao.InstPerformanceH2DAO +org.skywalking.apm.collector.ui.dao.CpuMetricH2DAO org.skywalking.apm.collector.ui.dao.GCMetricH2DAO +org.skywalking.apm.collector.ui.dao.MemoryMetricH2DAO +org.skywalking.apm.collector.ui.dao.MemoryPoolMetricH2DAO org.skywalking.apm.collector.ui.dao.ServiceEntryH2DAO org.skywalking.apm.collector.ui.dao.ServiceReferenceH2DAO \ No newline at end of file diff --git a/apm-network/src/main/java/org/skywalking/apm/network/trace/component/ComponentsDefine.java b/apm-network/src/main/java/org/skywalking/apm/network/trace/component/ComponentsDefine.java index 672d6d14f14002dc90f021a28eb3cbd0ae6678ae..0151346e8cb2f436673b5c6a7e08333320fee21d 100644 --- a/apm-network/src/main/java/org/skywalking/apm/network/trace/component/ComponentsDefine.java +++ b/apm-network/src/main/java/org/skywalking/apm/network/trace/component/ComponentsDefine.java @@ -63,10 +63,14 @@ public class ComponentsDefine { public static final OfficialComponent JETTY_SERVER = new OfficialComponent(19, "JettyServer"); - public static final OfficialComponent MEMCACHE = new OfficialComponent(20, "Memcache"); + public static final OfficialComponent MEMCACHED = new OfficialComponent(20, "Memcached"); public static final OfficialComponent SHARDING_JDBC = new OfficialComponent(21, "ShardingJDBC"); + public static final OfficialComponent POSTGRESQL = new OfficialComponent(22, "PostgreSQL"); + + public static final OfficialComponent GRPC = new OfficialComponent(23, "GRPC"); + private static ComponentsDefine instance = new ComponentsDefine(); private String[] components; @@ -76,7 +80,7 @@ public class ComponentsDefine { } public ComponentsDefine() { - components = new String[22]; + components = new String[24]; addComponent(TOMCAT); addComponent(HTTPCLIENT); addComponent(DUBBO); @@ -96,8 +100,10 @@ public class ComponentsDefine { addComponent(NUTZ_HTTP); addComponent(JETTY_CLIENT); addComponent(JETTY_SERVER); - addComponent(MEMCACHE); + addComponent(MEMCACHED); addComponent(SHARDING_JDBC); + addComponent(POSTGRESQL); + addComponent(GRPC); } private void addComponent(OfficialComponent component) { @@ -111,4 +117,4 @@ public class ComponentsDefine { return components[componentId]; } } -} \ No newline at end of file +} diff --git a/apm-sniffer/apm-agent/pom.xml b/apm-sniffer/apm-agent/pom.xml index 8047e216183e0a2a018a2f1b5d83b50b57767982..4adc5103993e65e3c761556e7066c370aad86a92 100644 --- a/apm-sniffer/apm-agent/pom.xml +++ b/apm-sniffer/apm-agent/pom.xml @@ -153,6 +153,16 @@ apm-sharding-jdbc-1.5.x-plugin ${project.version} + + org.skywalking + apm-xmemcached-2.x-plugin + ${project.version} + + + org.skywalking + apm-grpc-1.x-plugin + ${project.version} + diff --git a/apm-sniffer/apm-sdk-plugin/grpc-1.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/grpc-1.x-plugin/pom.xml new file mode 100644 index 0000000000000000000000000000000000000000..7b72913a804d718dd0f4a7db427319f5f9809ba6 --- /dev/null +++ b/apm-sniffer/apm-sdk-plugin/grpc-1.x-plugin/pom.xml @@ -0,0 +1,59 @@ + + + + + 4.0.0 + + org.skywalking + apm-sdk-plugin + 3.2.3-2017 + + + apm-grpc-1.x-plugin + grpc-1.x-plugin + jar + + + UTF-8 + + + + + io.grpc + grpc-all + 1.6.0 + provided + + + + + + + org.apache.maven.plugins + maven-resources-plugin + 2.4.3 + + ${project.build.sourceEncoding} + + + + + diff --git a/apm-sniffer/apm-sdk-plugin/grpc-1.x-plugin/src/main/java/org/skywalking/apm/plugin/grpc/v1/ClientCallIConstructorInterceptor.java b/apm-sniffer/apm-sdk-plugin/grpc-1.x-plugin/src/main/java/org/skywalking/apm/plugin/grpc/v1/ClientCallIConstructorInterceptor.java new file mode 100644 index 0000000000000000000000000000000000000000..b6c85d1ce1267621455919a487a1e5db7a458de8 --- /dev/null +++ b/apm-sniffer/apm-sdk-plugin/grpc-1.x-plugin/src/main/java/org/skywalking/apm/plugin/grpc/v1/ClientCallIConstructorInterceptor.java @@ -0,0 +1,40 @@ +/* + * Copyright 2017, OpenSkywalking Organization All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * Project repository: https://github.com/OpenSkywalking/skywalking + */ + +package org.skywalking.apm.plugin.grpc.v1; + +import io.grpc.MethodDescriptor; +import org.skywalking.apm.agent.core.plugin.interceptor.enhance.EnhancedInstance; +import org.skywalking.apm.agent.core.plugin.interceptor.enhance.InstanceConstructorInterceptor; +import org.skywalking.apm.plugin.grpc.v1.vo.GRPCDynamicFields; + +/** + * {@link ClientCallIConstructorInterceptor} pass the {@link GRPCDynamicFields} into the + * io.grpc.internal.ClientCallImpl instance for propagate the information of build span. + * + * @author zhangxin + */ +public class ClientCallIConstructorInterceptor implements InstanceConstructorInterceptor { + + @Override + public void onConstruct(EnhancedInstance objInst, Object[] allArguments) { + GRPCDynamicFields dynamicFields = new GRPCDynamicFields(); + dynamicFields.setDescriptor((MethodDescriptor)allArguments[0]); + objInst.setSkyWalkingDynamicField(dynamicFields); + } +} diff --git a/apm-sniffer/apm-sdk-plugin/grpc-1.x-plugin/src/main/java/org/skywalking/apm/plugin/grpc/v1/ClientCallOnNextInterceptor.java b/apm-sniffer/apm-sdk-plugin/grpc-1.x-plugin/src/main/java/org/skywalking/apm/plugin/grpc/v1/ClientCallOnNextInterceptor.java new file mode 100644 index 0000000000000000000000000000000000000000..a46de3c77ba0e1641cd2da279500f13b757a772d --- /dev/null +++ b/apm-sniffer/apm-sdk-plugin/grpc-1.x-plugin/src/main/java/org/skywalking/apm/plugin/grpc/v1/ClientCallOnNextInterceptor.java @@ -0,0 +1,61 @@ +/* + * Copyright 2017, OpenSkywalking Organization All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * Project repository: https://github.com/OpenSkywalking/skywalking + */ + +package org.skywalking.apm.plugin.grpc.v1; + +import java.lang.reflect.Method; +import org.skywalking.apm.agent.core.context.ContextManager; +import org.skywalking.apm.agent.core.plugin.interceptor.enhance.EnhancedInstance; +import org.skywalking.apm.agent.core.plugin.interceptor.enhance.InstanceMethodsAroundInterceptor; +import org.skywalking.apm.agent.core.plugin.interceptor.enhance.MethodInterceptResult; +import org.skywalking.apm.plugin.grpc.v1.vo.GRPCDynamicFields; + +import static org.skywalking.apm.plugin.grpc.v1.define.Constants.STREAM_OPERATION_NAME_SUFFIX; + +/** + * {@link ClientCallOnNextInterceptor} create a local span when the client stream receive an message that send from + * server stream and record the value of OnNext.count tag. + * + * @author zhangxin + */ +public class ClientCallOnNextInterceptor implements InstanceMethodsAroundInterceptor { + + @Override + public void beforeMethod(EnhancedInstance objInst, Method method, Object[] allArguments, Class[] argumentsTypes, + MethodInterceptResult result) throws Throwable { + GRPCDynamicFields cachedObjects = (GRPCDynamicFields)objInst.getSkyWalkingDynamicField(); + ContextManager.createLocalSpan(cachedObjects.getRequestMethodName() + STREAM_OPERATION_NAME_SUFFIX); + } + + @Override + public Object afterMethod(EnhancedInstance objInst, Method method, Object[] allArguments, Class[] argumentsTypes, + Object ret) throws Throwable { + ContextManager.stopSpan(); + + // record the call count of onNext method + GRPCDynamicFields cachedObjects = (GRPCDynamicFields)objInst.getSkyWalkingDynamicField(); + cachedObjects.incrementOnNextCount(); + + return ret; + } + + @Override public void handleMethodException(EnhancedInstance objInst, Method method, Object[] allArguments, + Class[] argumentsTypes, Throwable t) { + ContextManager.activeSpan().errorOccurred().log(t); + } +} diff --git a/apm-sniffer/apm-sdk-plugin/grpc-1.x-plugin/src/main/java/org/skywalking/apm/plugin/grpc/v1/ClientCallStartInterceptor.java b/apm-sniffer/apm-sdk-plugin/grpc-1.x-plugin/src/main/java/org/skywalking/apm/plugin/grpc/v1/ClientCallStartInterceptor.java new file mode 100644 index 0000000000000000000000000000000000000000..9515364b3061129e7c7d5226248ef216033d4ed9 --- /dev/null +++ b/apm-sniffer/apm-sdk-plugin/grpc-1.x-plugin/src/main/java/org/skywalking/apm/plugin/grpc/v1/ClientCallStartInterceptor.java @@ -0,0 +1,82 @@ +/* + * Copyright 2017, OpenSkywalking Organization All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * Project repository: https://github.com/OpenSkywalking/skywalking + */ + +package org.skywalking.apm.plugin.grpc.v1; + +import io.grpc.Metadata; +import io.grpc.MethodDescriptor; +import java.lang.reflect.Method; +import org.skywalking.apm.agent.core.context.CarrierItem; +import org.skywalking.apm.agent.core.context.ContextCarrier; +import org.skywalking.apm.agent.core.context.ContextManager; +import org.skywalking.apm.agent.core.context.trace.AbstractSpan; +import org.skywalking.apm.agent.core.context.trace.SpanLayer; +import org.skywalking.apm.agent.core.plugin.interceptor.enhance.EnhancedInstance; +import org.skywalking.apm.agent.core.plugin.interceptor.enhance.InstanceMethodsAroundInterceptor; +import org.skywalking.apm.agent.core.plugin.interceptor.enhance.MethodInterceptResult; +import org.skywalking.apm.network.trace.component.ComponentsDefine; +import org.skywalking.apm.plugin.grpc.v1.vo.GRPCDynamicFields; + +/** + * {@link ClientCallOnNextInterceptor} create a exist span when the grpc start call. it will stop span when the method + * type is non-unary. + * + * @author zhangxin + */ +public class ClientCallStartInterceptor + implements InstanceMethodsAroundInterceptor { + + @Override + public void beforeMethod(EnhancedInstance objInst, Method method, Object[] allArguments, Class[] argumentsTypes, + MethodInterceptResult result) throws Throwable { + GRPCDynamicFields cachedObjects = (GRPCDynamicFields)objInst.getSkyWalkingDynamicField(); + final Metadata headers = (Metadata)allArguments[1]; + final AbstractSpan span = ContextManager.createExitSpan(cachedObjects.getRequestMethodName(), cachedObjects.getAuthority()); + span.setComponent(ComponentsDefine.GRPC); + SpanLayer.asRPCFramework(span); + final ContextCarrier contextCarrier = new ContextCarrier(); + ContextManager.inject(contextCarrier); + + CarrierItem contextItem = contextCarrier.items(); + while (contextItem.hasNext()) { + contextItem = contextItem.next(); + Metadata.Key headerKey = Metadata.Key.of(contextItem.getHeadKey(), Metadata.ASCII_STRING_MARSHALLER); + headers.put(headerKey, contextItem.getHeadValue()); + } + + GRPCDynamicFields listenerCachedObject = new GRPCDynamicFields(); + listenerCachedObject.setSnapshot(ContextManager.capture()); + listenerCachedObject.setDescriptor(cachedObjects.getDescriptor()); + ((EnhancedInstance)allArguments[0]).setSkyWalkingDynamicField(listenerCachedObject); + } + + @Override + public Object afterMethod(EnhancedInstance objInst, Method method, Object[] allArguments, Class[] argumentsTypes, + Object ret) throws Throwable { + + if (((GRPCDynamicFields)objInst.getSkyWalkingDynamicField()).getMethodType() != MethodDescriptor.MethodType.UNARY) { + ContextManager.stopSpan(); + } + return ret; + } + + @Override public void handleMethodException(EnhancedInstance objInst, Method method, Object[] allArguments, + Class[] argumentsTypes, Throwable t) { + ContextManager.activeSpan().errorOccurred().log(t); + } +} diff --git a/apm-sniffer/apm-sdk-plugin/grpc-1.x-plugin/src/main/java/org/skywalking/apm/plugin/grpc/v1/ManagedChannelInterceptor.java b/apm-sniffer/apm-sdk-plugin/grpc-1.x-plugin/src/main/java/org/skywalking/apm/plugin/grpc/v1/ManagedChannelInterceptor.java new file mode 100644 index 0000000000000000000000000000000000000000..d075179c8d2864a840541c457db41096fe78e936 --- /dev/null +++ b/apm-sniffer/apm-sdk-plugin/grpc-1.x-plugin/src/main/java/org/skywalking/apm/plugin/grpc/v1/ManagedChannelInterceptor.java @@ -0,0 +1,51 @@ +/* + * Copyright 2017, OpenSkywalking Organization All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * Project repository: https://github.com/OpenSkywalking/skywalking + */ + +package org.skywalking.apm.plugin.grpc.v1; + +import io.grpc.internal.ManagedChannelImpl; +import java.lang.reflect.Method; +import org.skywalking.apm.agent.core.plugin.interceptor.enhance.EnhancedInstance; +import org.skywalking.apm.agent.core.plugin.interceptor.enhance.InstanceMethodsAroundInterceptor; +import org.skywalking.apm.agent.core.plugin.interceptor.enhance.MethodInterceptResult; +import org.skywalking.apm.plugin.grpc.v1.vo.GRPCDynamicFields; + +/** + * {@link ManagedChannelInterceptor} record the IP address of the GRPC server into {@link GRPCDynamicFields} for build + * span. + * + * @author zhangxin + */ +public class ManagedChannelInterceptor implements InstanceMethodsAroundInterceptor { + @Override + public void beforeMethod(EnhancedInstance objInst, Method method, Object[] allArguments, Class[] argumentsTypes, + MethodInterceptResult result) throws Throwable { + } + + @Override + public Object afterMethod(EnhancedInstance objInst, Method method, Object[] allArguments, Class[] argumentsTypes, + Object ret) throws Throwable { + GRPCDynamicFields cachedObjects = (GRPCDynamicFields)((EnhancedInstance)ret).getSkyWalkingDynamicField(); + cachedObjects.setAuthority(((ManagedChannelImpl)((Object)objInst)).authority()); + return ret; + } + + @Override public void handleMethodException(EnhancedInstance objInst, Method method, Object[] allArguments, + Class[] argumentsTypes, Throwable t) { + } +} diff --git a/apm-sniffer/apm-sdk-plugin/grpc-1.x-plugin/src/main/java/org/skywalking/apm/plugin/grpc/v1/ServerCallHandlerInterceptor.java b/apm-sniffer/apm-sdk-plugin/grpc-1.x-plugin/src/main/java/org/skywalking/apm/plugin/grpc/v1/ServerCallHandlerInterceptor.java new file mode 100644 index 0000000000000000000000000000000000000000..cf13514f1d37b61186e2591d4ae365b8009f277c --- /dev/null +++ b/apm-sniffer/apm-sdk-plugin/grpc-1.x-plugin/src/main/java/org/skywalking/apm/plugin/grpc/v1/ServerCallHandlerInterceptor.java @@ -0,0 +1,57 @@ +/* + * Copyright 2017, OpenSkywalking Organization All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * Project repository: https://github.com/OpenSkywalking/skywalking + */ + +package org.skywalking.apm.plugin.grpc.v1; + +import io.grpc.Metadata; +import io.grpc.ServerCall; +import java.lang.reflect.Method; +import org.skywalking.apm.agent.core.plugin.interceptor.enhance.EnhancedInstance; +import org.skywalking.apm.agent.core.plugin.interceptor.enhance.InstanceMethodsAroundInterceptor; +import org.skywalking.apm.agent.core.plugin.interceptor.enhance.MethodInterceptResult; +import org.skywalking.apm.plugin.grpc.v1.vo.GRPCDynamicFields; + +/** + * {@link ServerCallHandlerInterceptor} record the {@link Metadata} argument into {@link GRPCDynamicFields} for + * propagate {@link org.skywalking.apm.agent.core.context.ContextCarrier} and also record the {@link + * io.grpc.MethodDescriptor} into {@link GRPCDynamicFields} for building span. + * + * @author zhangxin + */ +public class ServerCallHandlerInterceptor implements InstanceMethodsAroundInterceptor { + @Override + public void beforeMethod(EnhancedInstance objInst, Method method, Object[] allArguments, Class[] argumentsTypes, + MethodInterceptResult result) throws Throwable { + + } + + @Override + public Object afterMethod(EnhancedInstance objInst, Method method, Object[] allArguments, Class[] argumentsTypes, + Object ret) throws Throwable { + GRPCDynamicFields cachedObjects = new GRPCDynamicFields(); + cachedObjects.setMetadata((Metadata)allArguments[1]); + cachedObjects.setDescriptor(((ServerCall)allArguments[0]).getMethodDescriptor()); + ((EnhancedInstance)ret).setSkyWalkingDynamicField(cachedObjects); + return ret; + } + + @Override public void handleMethodException(EnhancedInstance objInst, Method method, Object[] allArguments, + Class[] argumentsTypes, Throwable t) { + + } +} diff --git a/apm-sniffer/apm-sdk-plugin/grpc-1.x-plugin/src/main/java/org/skywalking/apm/plugin/grpc/v1/ServerCallOnCancelInterceptor.java b/apm-sniffer/apm-sdk-plugin/grpc-1.x-plugin/src/main/java/org/skywalking/apm/plugin/grpc/v1/ServerCallOnCancelInterceptor.java new file mode 100644 index 0000000000000000000000000000000000000000..ab64ceed6170f7a56351e38a732ca1f2935c60e9 --- /dev/null +++ b/apm-sniffer/apm-sdk-plugin/grpc-1.x-plugin/src/main/java/org/skywalking/apm/plugin/grpc/v1/ServerCallOnCancelInterceptor.java @@ -0,0 +1,57 @@ +/* + * Copyright 2017, OpenSkywalking Organization All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * Project repository: https://github.com/OpenSkywalking/skywalking + */ + +package org.skywalking.apm.plugin.grpc.v1; + +import java.lang.reflect.Method; +import org.skywalking.apm.agent.core.context.ContextManager; +import org.skywalking.apm.agent.core.context.trace.AbstractSpan; +import org.skywalking.apm.agent.core.plugin.interceptor.enhance.EnhancedInstance; +import org.skywalking.apm.agent.core.plugin.interceptor.enhance.InstanceMethodsAroundInterceptor; +import org.skywalking.apm.agent.core.plugin.interceptor.enhance.MethodInterceptResult; +import org.skywalking.apm.plugin.grpc.v1.vo.GRPCDynamicFields; + +import static org.skywalking.apm.plugin.grpc.v1.define.Constants.ON_NEXT_COUNT_TAG_KEY; + +/** + * {@link ServerCallOnCancelInterceptor} stop the active span when the call cancelled. + * + * @author zhangxin + */ +public class ServerCallOnCancelInterceptor implements InstanceMethodsAroundInterceptor { + + @Override + public void beforeMethod(EnhancedInstance objInst, Method method, Object[] allArguments, Class[] argumentsTypes, + MethodInterceptResult result) throws Throwable { + } + + @Override + public Object afterMethod(EnhancedInstance objInst, Method method, Object[] allArguments, Class[] argumentsTypes, + Object ret) throws Throwable { + AbstractSpan abstractSpan = ContextManager.activeSpan(); + abstractSpan.tag(ON_NEXT_COUNT_TAG_KEY, String.valueOf(((GRPCDynamicFields)objInst.getSkyWalkingDynamicField()).getOnNextCount())); + + ContextManager.stopSpan(); + return ret; + } + + @Override public void handleMethodException(EnhancedInstance objInst, Method method, Object[] allArguments, + Class[] argumentsTypes, Throwable t) { + ContextManager.activeSpan().errorOccurred().log(t); + } +} diff --git a/apm-sniffer/apm-sdk-plugin/grpc-1.x-plugin/src/main/java/org/skywalking/apm/plugin/grpc/v1/ServerCallOnCloseInterceptor.java b/apm-sniffer/apm-sdk-plugin/grpc-1.x-plugin/src/main/java/org/skywalking/apm/plugin/grpc/v1/ServerCallOnCloseInterceptor.java new file mode 100644 index 0000000000000000000000000000000000000000..fd451c852d64f9f7025e1e734f17f057a3aa7d74 --- /dev/null +++ b/apm-sniffer/apm-sdk-plugin/grpc-1.x-plugin/src/main/java/org/skywalking/apm/plugin/grpc/v1/ServerCallOnCloseInterceptor.java @@ -0,0 +1,57 @@ +/* + * Copyright 2017, OpenSkywalking Organization All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * Project repository: https://github.com/OpenSkywalking/skywalking + */ + +package org.skywalking.apm.plugin.grpc.v1; + +import java.lang.reflect.Method; +import org.skywalking.apm.agent.core.context.ContextManager; +import org.skywalking.apm.agent.core.context.trace.AbstractSpan; +import org.skywalking.apm.agent.core.plugin.interceptor.enhance.EnhancedInstance; +import org.skywalking.apm.agent.core.plugin.interceptor.enhance.InstanceMethodsAroundInterceptor; +import org.skywalking.apm.agent.core.plugin.interceptor.enhance.MethodInterceptResult; +import org.skywalking.apm.plugin.grpc.v1.vo.GRPCDynamicFields; + +import static org.skywalking.apm.plugin.grpc.v1.define.Constants.ON_NEXT_COUNT_TAG_KEY; + +/** + * {@link ServerCallOnCloseInterceptor} stop the active span when the call end. + * + * @author zhangxin + */ +public class ServerCallOnCloseInterceptor implements InstanceMethodsAroundInterceptor { + + @Override + public void beforeMethod(EnhancedInstance objInst, Method method, Object[] allArguments, Class[] argumentsTypes, + MethodInterceptResult result) throws Throwable { + + } + + @Override + public Object afterMethod(EnhancedInstance objInst, Method method, Object[] allArguments, Class[] argumentsTypes, + Object ret) throws Throwable { + AbstractSpan abstractSpan = ContextManager.activeSpan(); + abstractSpan.tag(ON_NEXT_COUNT_TAG_KEY, String.valueOf(((GRPCDynamicFields)objInst.getSkyWalkingDynamicField()).getOnNextCount())); + ContextManager.stopSpan(); + return ret; + } + + @Override public void handleMethodException(EnhancedInstance objInst, Method method, Object[] allArguments, + Class[] argumentsTypes, Throwable t) { + ContextManager.activeSpan().errorOccurred().log(t); + } +} diff --git a/apm-sniffer/apm-sdk-plugin/grpc-1.x-plugin/src/main/java/org/skywalking/apm/plugin/grpc/v1/ServerCallOnMessageInterceptor.java b/apm-sniffer/apm-sdk-plugin/grpc-1.x-plugin/src/main/java/org/skywalking/apm/plugin/grpc/v1/ServerCallOnMessageInterceptor.java new file mode 100644 index 0000000000000000000000000000000000000000..1e51aa76f7a93d7778b7cb55b2c6a9231d8accaa --- /dev/null +++ b/apm-sniffer/apm-sdk-plugin/grpc-1.x-plugin/src/main/java/org/skywalking/apm/plugin/grpc/v1/ServerCallOnMessageInterceptor.java @@ -0,0 +1,61 @@ +/* + * Copyright 2017, OpenSkywalking Organization All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * Project repository: https://github.com/OpenSkywalking/skywalking + */ + +package org.skywalking.apm.plugin.grpc.v1; + +import java.lang.reflect.Method; +import org.skywalking.apm.agent.core.context.ContextManager; +import org.skywalking.apm.agent.core.plugin.interceptor.enhance.EnhancedInstance; +import org.skywalking.apm.agent.core.plugin.interceptor.enhance.InstanceMethodsAroundInterceptor; +import org.skywalking.apm.agent.core.plugin.interceptor.enhance.MethodInterceptResult; +import org.skywalking.apm.plugin.grpc.v1.vo.GRPCDynamicFields; + +import static org.skywalking.apm.plugin.grpc.v1.define.Constants.STREAM_OPERATION_NAME_SUFFIX; + +/** + * {@link ServerCallOnMessageInterceptor} create a local span when the server stream receive a message that send by the + * client. + * + * @author zhangxin + */ +public class ServerCallOnMessageInterceptor implements InstanceMethodsAroundInterceptor { + + @Override + public void beforeMethod(EnhancedInstance objInst, Method method, Object[] allArguments, Class[] argumentsTypes, + MethodInterceptResult result) throws Throwable { + GRPCDynamicFields cachedObjects = (GRPCDynamicFields)objInst.getSkyWalkingDynamicField(); + ContextManager.createLocalSpan(cachedObjects.getRequestMethodName() + STREAM_OPERATION_NAME_SUFFIX); + } + + @Override + public Object afterMethod(EnhancedInstance objInst, Method method, Object[] allArguments, Class[] argumentsTypes, + Object ret) throws Throwable { + ContextManager.stopSpan(); + + // record the call count of onNext method + GRPCDynamicFields cachedObjects = (GRPCDynamicFields)objInst.getSkyWalkingDynamicField(); + cachedObjects.incrementOnNextCount(); + + return ret; + } + + @Override public void handleMethodException(EnhancedInstance objInst, Method method, Object[] allArguments, + Class[] argumentsTypes, Throwable t) { + ContextManager.activeSpan().errorOccurred().log(t); + } +} diff --git a/apm-sniffer/apm-sdk-plugin/grpc-1.x-plugin/src/main/java/org/skywalking/apm/plugin/grpc/v1/ServerCallOnReadyInterceptor.java b/apm-sniffer/apm-sdk-plugin/grpc-1.x-plugin/src/main/java/org/skywalking/apm/plugin/grpc/v1/ServerCallOnReadyInterceptor.java new file mode 100644 index 0000000000000000000000000000000000000000..90d571579a5d0e9362c70865f4761e8a4b9802da --- /dev/null +++ b/apm-sniffer/apm-sdk-plugin/grpc-1.x-plugin/src/main/java/org/skywalking/apm/plugin/grpc/v1/ServerCallOnReadyInterceptor.java @@ -0,0 +1,85 @@ +/* + * Copyright 2017, OpenSkywalking Organization All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * Project repository: https://github.com/OpenSkywalking/skywalking + */ + +package org.skywalking.apm.plugin.grpc.v1; + +import io.grpc.Metadata; +import io.grpc.MethodDescriptor; +import java.lang.reflect.Method; +import java.util.HashMap; +import java.util.Map; +import org.skywalking.apm.agent.core.context.CarrierItem; +import org.skywalking.apm.agent.core.context.ContextCarrier; +import org.skywalking.apm.agent.core.context.ContextManager; +import org.skywalking.apm.agent.core.context.trace.AbstractSpan; +import org.skywalking.apm.agent.core.plugin.interceptor.enhance.EnhancedInstance; +import org.skywalking.apm.agent.core.plugin.interceptor.enhance.InstanceMethodsAroundInterceptor; +import org.skywalking.apm.agent.core.plugin.interceptor.enhance.MethodInterceptResult; +import org.skywalking.apm.network.trace.component.ComponentsDefine; +import org.skywalking.apm.plugin.grpc.v1.vo.GRPCDynamicFields; +import org.skywalking.apm.util.StringUtil; + +import static org.skywalking.apm.plugin.grpc.v1.define.Constants.STREAM_CALL_OPERATION_NAME_SUFFIX; +import static org.skywalking.apm.plugin.grpc.v1.define.Constants.BLOCK_CALL_OPERATION_NAME_SUFFIX; + +/** + * {@link ServerCallOnReadyInterceptor} create a entry span when the server side is ready for receive the message from + * the client side. + * + * @author zhangxin + */ +public class ServerCallOnReadyInterceptor implements InstanceMethodsAroundInterceptor { + + @Override + public void beforeMethod(EnhancedInstance objInst, Method method, Object[] allArguments, Class[] argumentsTypes, + MethodInterceptResult result) throws Throwable { + GRPCDynamicFields cachedObjects = (GRPCDynamicFields)objInst.getSkyWalkingDynamicField(); + Metadata headers = cachedObjects.getMetadata(); + Map headerMap = new HashMap(); + for (String key : headers.keys()) { + if (!key.endsWith(Metadata.BINARY_HEADER_SUFFIX)) { + String value = headers.get(Metadata.Key.of(key, Metadata.ASCII_STRING_MARSHALLER)); + headerMap.put(key, value); + } + } + + ContextCarrier contextCarrier = new ContextCarrier(); + CarrierItem next = contextCarrier.items(); + while (next.hasNext()) { + next = next.next(); + String contextValue = headerMap.get(next.getHeadKey()); + if (!StringUtil.isEmpty(contextValue)) { + next.setHeadValue(contextValue); + } + } + + final AbstractSpan span = ContextManager.createEntrySpan(cachedObjects.getRequestMethodName() + (cachedObjects.getMethodType() != MethodDescriptor.MethodType.UNARY ? STREAM_CALL_OPERATION_NAME_SUFFIX : BLOCK_CALL_OPERATION_NAME_SUFFIX), contextCarrier); + span.setComponent(ComponentsDefine.GRPC); + } + + @Override + public Object afterMethod(EnhancedInstance objInst, Method method, Object[] allArguments, Class[] argumentsTypes, + Object ret) throws Throwable { + return ret; + } + + @Override public void handleMethodException(EnhancedInstance objInst, Method method, Object[] allArguments, + Class[] argumentsTypes, Throwable t) { + ContextManager.activeSpan().errorOccurred().log(t); + } +} diff --git a/apm-sniffer/apm-sdk-plugin/grpc-1.x-plugin/src/main/java/org/skywalking/apm/plugin/grpc/v1/StreamClientOnCloseInterceptor.java b/apm-sniffer/apm-sdk-plugin/grpc-1.x-plugin/src/main/java/org/skywalking/apm/plugin/grpc/v1/StreamClientOnCloseInterceptor.java new file mode 100644 index 0000000000000000000000000000000000000000..26be1d525adb37a9327f4204aa3fbd8d1bdd5c1f --- /dev/null +++ b/apm-sniffer/apm-sdk-plugin/grpc-1.x-plugin/src/main/java/org/skywalking/apm/plugin/grpc/v1/StreamClientOnCloseInterceptor.java @@ -0,0 +1,78 @@ +/* + * Copyright 2017, OpenSkywalking Organization All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * Project repository: https://github.com/OpenSkywalking/skywalking + */ + +package org.skywalking.apm.plugin.grpc.v1; + +import io.grpc.Metadata; +import io.grpc.Status; +import java.lang.reflect.Method; +import org.skywalking.apm.agent.core.context.ContextManager; +import org.skywalking.apm.agent.core.context.tag.Tags; +import org.skywalking.apm.agent.core.context.trace.AbstractSpan; +import org.skywalking.apm.agent.core.context.trace.SpanLayer; +import org.skywalking.apm.agent.core.plugin.interceptor.enhance.EnhancedInstance; +import org.skywalking.apm.agent.core.plugin.interceptor.enhance.InstanceMethodsAroundInterceptor; +import org.skywalking.apm.agent.core.plugin.interceptor.enhance.MethodInterceptResult; +import org.skywalking.apm.network.trace.component.ComponentsDefine; +import org.skywalking.apm.plugin.grpc.v1.vo.GRPCDynamicFields; + +import static org.skywalking.apm.plugin.grpc.v1.define.Constants.ON_NEXT_COUNT_TAG_KEY; +import static org.skywalking.apm.plugin.grpc.v1.define.Constants.STREAM_CALL_OPERATION_NAME_SUFFIX; + +/** + * {@link StreamClientOnCloseInterceptor} stop the active span when the call end. + * + * @author zhangxin + */ +public class StreamClientOnCloseInterceptor implements InstanceMethodsAroundInterceptor { + + @Override + public void beforeMethod(EnhancedInstance objInst, Method method, Object[] allArguments, Class[] argumentsTypes, + MethodInterceptResult result) throws Throwable { + Status status = (Status)allArguments[0]; + if (status.getCode() == Status.Code.UNAVAILABLE) { + GRPCDynamicFields cachedObjects = (GRPCDynamicFields)objInst.getSkyWalkingDynamicField(); + AbstractSpan span = ContextManager.createLocalSpan(cachedObjects.getRequestMethodName() + STREAM_CALL_OPERATION_NAME_SUFFIX); + span.setComponent(ComponentsDefine.GRPC); + span.setLayer(SpanLayer.RPC_FRAMEWORK); + ContextManager.continued(cachedObjects.getSnapshot()); + } + + } + + @Override + public Object afterMethod(EnhancedInstance objInst, Method method, Object[] allArguments, Class[] argumentsTypes, + Object ret) throws Throwable { + AbstractSpan activeSpan = ContextManager.activeSpan(); + activeSpan.tag(ON_NEXT_COUNT_TAG_KEY, String.valueOf(((GRPCDynamicFields)objInst.getSkyWalkingDynamicField()).getOnNextCount())); + + Status status = (Status)allArguments[0]; + if (status != Status.OK) { + activeSpan.errorOccurred().log(status.asRuntimeException((Metadata)allArguments[1])); + Tags.STATUS_CODE.set(activeSpan, status.getCode().toString()); + } + + ContextManager.stopSpan(); + return ret; + } + + @Override public void handleMethodException(EnhancedInstance objInst, Method method, Object[] allArguments, + Class[] argumentsTypes, Throwable t) { + ContextManager.activeSpan().errorOccurred().log(t); + } +} diff --git a/apm-sniffer/apm-sdk-plugin/grpc-1.x-plugin/src/main/java/org/skywalking/apm/plugin/grpc/v1/StreamClientOnReadyInterceptor.java b/apm-sniffer/apm-sdk-plugin/grpc-1.x-plugin/src/main/java/org/skywalking/apm/plugin/grpc/v1/StreamClientOnReadyInterceptor.java new file mode 100644 index 0000000000000000000000000000000000000000..f856eaa7438b3d71b92f15579a5b712e8c1335da --- /dev/null +++ b/apm-sniffer/apm-sdk-plugin/grpc-1.x-plugin/src/main/java/org/skywalking/apm/plugin/grpc/v1/StreamClientOnReadyInterceptor.java @@ -0,0 +1,62 @@ +/* + * Copyright 2017, OpenSkywalking Organization All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * Project repository: https://github.com/OpenSkywalking/skywalking + */ + +package org.skywalking.apm.plugin.grpc.v1; + +import java.lang.reflect.Method; +import org.skywalking.apm.agent.core.context.ContextManager; +import org.skywalking.apm.agent.core.context.trace.AbstractSpan; +import org.skywalking.apm.agent.core.context.trace.SpanLayer; +import org.skywalking.apm.agent.core.plugin.interceptor.enhance.EnhancedInstance; +import org.skywalking.apm.agent.core.plugin.interceptor.enhance.InstanceMethodsAroundInterceptor; +import org.skywalking.apm.agent.core.plugin.interceptor.enhance.MethodInterceptResult; +import org.skywalking.apm.network.trace.component.ComponentsDefine; +import org.skywalking.apm.plugin.grpc.v1.vo.GRPCDynamicFields; + +import static org.skywalking.apm.plugin.grpc.v1.define.Constants.STREAM_CALL_OPERATION_NAME_SUFFIX; + +/** + * {@link ServerCallOnReadyInterceptor} create a local span when the client side is ready for send the message to the + * server side. + * + * @author zhangxin + */ +public class StreamClientOnReadyInterceptor implements InstanceMethodsAroundInterceptor { + + @Override + public void beforeMethod(EnhancedInstance objInst, Method method, Object[] allArguments, Class[] argumentsTypes, + MethodInterceptResult result) throws Throwable { + GRPCDynamicFields cachedObjects = (GRPCDynamicFields)objInst.getSkyWalkingDynamicField(); + AbstractSpan span = ContextManager.createLocalSpan(cachedObjects.getRequestMethodName() + STREAM_CALL_OPERATION_NAME_SUFFIX); + span.setComponent(ComponentsDefine.GRPC); + span.setLayer(SpanLayer.RPC_FRAMEWORK); + + ContextManager.continued(cachedObjects.getSnapshot()); + } + + @Override + public Object afterMethod(EnhancedInstance objInst, Method method, Object[] allArguments, Class[] argumentsTypes, + Object ret) throws Throwable { + return ret; + } + + @Override public void handleMethodException(EnhancedInstance objInst, Method method, Object[] allArguments, + Class[] argumentsTypes, Throwable t) { + ContextManager.activeSpan().errorOccurred().log(t); + } +} diff --git a/apm-sniffer/apm-sdk-plugin/grpc-1.x-plugin/src/main/java/org/skywalking/apm/plugin/grpc/v1/UnaryClientOnCloseInterceptor.java b/apm-sniffer/apm-sdk-plugin/grpc-1.x-plugin/src/main/java/org/skywalking/apm/plugin/grpc/v1/UnaryClientOnCloseInterceptor.java new file mode 100644 index 0000000000000000000000000000000000000000..efc04a11685d63e5f917aaebaf5818ceb020797d --- /dev/null +++ b/apm-sniffer/apm-sdk-plugin/grpc-1.x-plugin/src/main/java/org/skywalking/apm/plugin/grpc/v1/UnaryClientOnCloseInterceptor.java @@ -0,0 +1,62 @@ +/* + * Copyright 2017, OpenSkywalking Organization All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * Project repository: https://github.com/OpenSkywalking/skywalking + */ + +package org.skywalking.apm.plugin.grpc.v1; + +import io.grpc.Metadata; +import io.grpc.Status; +import java.lang.reflect.Method; +import org.skywalking.apm.agent.core.context.ContextManager; +import org.skywalking.apm.agent.core.context.tag.Tags; +import org.skywalking.apm.agent.core.context.trace.AbstractSpan; +import org.skywalking.apm.agent.core.plugin.interceptor.enhance.EnhancedInstance; +import org.skywalking.apm.agent.core.plugin.interceptor.enhance.InstanceMethodsAroundInterceptor; +import org.skywalking.apm.agent.core.plugin.interceptor.enhance.MethodInterceptResult; + +/** + * {@link UnaryClientOnCloseInterceptor} stop the active span when the call end. + * + * @author zhangxin + */ +public class UnaryClientOnCloseInterceptor implements InstanceMethodsAroundInterceptor { + @Override + public void beforeMethod(EnhancedInstance objInst, Method method, Object[] allArguments, Class[] argumentsTypes, + MethodInterceptResult result) throws Throwable { + + } + + @Override + public Object afterMethod(EnhancedInstance objInst, Method method, Object[] allArguments, Class[] argumentsTypes, + Object ret) throws Throwable { + AbstractSpan activeSpan = ContextManager.activeSpan(); + Status status = (Status)allArguments[0]; + + if (status != Status.OK) { + activeSpan.errorOccurred().log(status.asRuntimeException((Metadata)allArguments[1])); + Tags.STATUS_CODE.set(activeSpan, status.getCode().toString()); + } + + ContextManager.stopSpan(); + return ret; + } + + @Override public void handleMethodException(EnhancedInstance objInst, Method method, Object[] allArguments, + Class[] argumentsTypes, Throwable t) { + ContextManager.activeSpan().errorOccurred().log(t); + } +} diff --git a/apm-sniffer/apm-sdk-plugin/grpc-1.x-plugin/src/main/java/org/skywalking/apm/plugin/grpc/v1/define/ClientCallInstrumentation.java b/apm-sniffer/apm-sdk-plugin/grpc-1.x-plugin/src/main/java/org/skywalking/apm/plugin/grpc/v1/define/ClientCallInstrumentation.java new file mode 100644 index 0000000000000000000000000000000000000000..02d0a8ffa622199fe7dd9ebcd96798d2b79bc06d --- /dev/null +++ b/apm-sniffer/apm-sdk-plugin/grpc-1.x-plugin/src/main/java/org/skywalking/apm/plugin/grpc/v1/define/ClientCallInstrumentation.java @@ -0,0 +1,80 @@ +/* + * Copyright 2017, OpenSkywalking Organization All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * Project repository: https://github.com/OpenSkywalking/skywalking + */ + +package org.skywalking.apm.plugin.grpc.v1.define; + +import net.bytebuddy.description.method.MethodDescription; +import net.bytebuddy.matcher.ElementMatcher; +import org.skywalking.apm.agent.core.plugin.interceptor.ConstructorInterceptPoint; +import org.skywalking.apm.agent.core.plugin.interceptor.InstanceMethodsInterceptPoint; +import org.skywalking.apm.agent.core.plugin.interceptor.enhance.ClassInstanceMethodsEnhancePluginDefine; +import org.skywalking.apm.agent.core.plugin.match.ClassMatch; + +import static net.bytebuddy.matcher.ElementMatchers.any; +import static net.bytebuddy.matcher.ElementMatchers.named; +import static org.skywalking.apm.agent.core.plugin.match.NameMatch.byName; + +/** + * {@link ClientCallInstrumentation} presents that skywalking intercept the start method in + * io.grpc.internal.ClientCallImpl class by org.skywalking.apm.plugin.grpc.v1.ClientCallStartInterceptor + * and the constructor in io.grpc.internal.ClientCallImpl by org.skywalking.apm.plugin.grpc.v1.ClientCallIConstructorInterceptor + * + * @author zhangxin + */ +public class ClientCallInstrumentation extends ClassInstanceMethodsEnhancePluginDefine { + private static final String ENHANCE_CLASS = "io.grpc.internal.ClientCallImpl"; + private static final String ENHANCE_METHOD = "start"; + public static final String CONSTRUCTOR_CLASS = "org.skywalking.apm.plugin.grpc.v1.ClientCallIConstructorInterceptor"; + public static final String START_METHOD_INTERCEPT_CLASS = "org.skywalking.apm.plugin.grpc.v1.ClientCallStartInterceptor"; + + @Override protected ConstructorInterceptPoint[] getConstructorsInterceptPoints() { + return new ConstructorInterceptPoint[] { + new ConstructorInterceptPoint() { + @Override public ElementMatcher getConstructorMatcher() { + return any(); + } + + @Override public String getConstructorInterceptor() { + return CONSTRUCTOR_CLASS; + } + } + }; + } + + @Override protected InstanceMethodsInterceptPoint[] getInstanceMethodsInterceptPoints() { + return new InstanceMethodsInterceptPoint[] { + new InstanceMethodsInterceptPoint() { + @Override public ElementMatcher getMethodsMatcher() { + return named(ENHANCE_METHOD); + } + + @Override public String getMethodsInterceptor() { + return START_METHOD_INTERCEPT_CLASS; + } + + @Override public boolean isOverrideArgs() { + return true; + } + } + }; + } + + @Override protected ClassMatch enhanceClass() { + return byName(ENHANCE_CLASS); + } +} diff --git a/apm-sniffer/apm-sdk-plugin/grpc-1.x-plugin/src/main/java/org/skywalking/apm/plugin/grpc/v1/define/Constants.java b/apm-sniffer/apm-sdk-plugin/grpc-1.x-plugin/src/main/java/org/skywalking/apm/plugin/grpc/v1/define/Constants.java new file mode 100644 index 0000000000000000000000000000000000000000..d74c6b711024aba5e6ef121434f89e94d996d3c2 --- /dev/null +++ b/apm-sniffer/apm-sdk-plugin/grpc-1.x-plugin/src/main/java/org/skywalking/apm/plugin/grpc/v1/define/Constants.java @@ -0,0 +1,36 @@ +/* + * Copyright 2017, OpenSkywalking Organization All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * Project repository: https://github.com/OpenSkywalking/skywalking + */ + +package org.skywalking.apm.plugin.grpc.v1.define; + +/** + * GRPC Plugin constants variables. + * + * @author zhangxin + */ +public final class Constants { + + public static final String STREAM_OPERATION_NAME_SUFFIX = "/ResponseStreamObserver/OnNext"; + + public static final String ON_NEXT_COUNT_TAG_KEY = "onNext.count"; + + public static final String STREAM_CALL_OPERATION_NAME_SUFFIX = "/StreamCall"; + + public static final String BLOCK_CALL_OPERATION_NAME_SUFFIX = "/BlockCall"; + +} diff --git a/apm-sniffer/apm-sdk-plugin/grpc-1.x-plugin/src/main/java/org/skywalking/apm/plugin/grpc/v1/define/ManagedChannelInstrumentation.java b/apm-sniffer/apm-sdk-plugin/grpc-1.x-plugin/src/main/java/org/skywalking/apm/plugin/grpc/v1/define/ManagedChannelInstrumentation.java new file mode 100644 index 0000000000000000000000000000000000000000..28a6b1a8bc08c19ab86923281f5523edc7c76f1c --- /dev/null +++ b/apm-sniffer/apm-sdk-plugin/grpc-1.x-plugin/src/main/java/org/skywalking/apm/plugin/grpc/v1/define/ManagedChannelInstrumentation.java @@ -0,0 +1,67 @@ +/* + * Copyright 2017, OpenSkywalking Organization All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * Project repository: https://github.com/OpenSkywalking/skywalking + */ + +package org.skywalking.apm.plugin.grpc.v1.define; + +import net.bytebuddy.description.method.MethodDescription; +import net.bytebuddy.matcher.ElementMatcher; +import org.skywalking.apm.agent.core.plugin.interceptor.ConstructorInterceptPoint; +import org.skywalking.apm.agent.core.plugin.interceptor.InstanceMethodsInterceptPoint; +import org.skywalking.apm.agent.core.plugin.interceptor.enhance.ClassInstanceMethodsEnhancePluginDefine; +import org.skywalking.apm.agent.core.plugin.match.ClassMatch; + +import static net.bytebuddy.matcher.ElementMatchers.named; +import static org.skywalking.apm.agent.core.plugin.match.NameMatch.byName; + +/** + * {@link ManagedChannelInstrumentation} presents that skywalking intercept the newCall method in + * io.grpc.internal.ManagedChannelImpl class by org.skywalking.apm.plugin.grpc.v1.ManagedChannelInterceptor + * + * @author zhangxin + */ +public class ManagedChannelInstrumentation extends ClassInstanceMethodsEnhancePluginDefine { + private static final String ENHANCE_CLASS = "io.grpc.internal.ManagedChannelImpl"; + private static final String ENHANCE_METHOD = "newCall"; + public static final String INTERCEPT_CLASS = "org.skywalking.apm.plugin.grpc.v1.ManagedChannelInterceptor"; + + @Override protected ConstructorInterceptPoint[] getConstructorsInterceptPoints() { + return new ConstructorInterceptPoint[0]; + } + + @Override protected InstanceMethodsInterceptPoint[] getInstanceMethodsInterceptPoints() { + return new InstanceMethodsInterceptPoint[] { + new InstanceMethodsInterceptPoint() { + @Override public ElementMatcher getMethodsMatcher() { + return named(ENHANCE_METHOD); + } + + @Override public String getMethodsInterceptor() { + return INTERCEPT_CLASS; + } + + @Override public boolean isOverrideArgs() { + return false; + } + } + }; + } + + @Override protected ClassMatch enhanceClass() { + return byName(ENHANCE_CLASS); + } +} diff --git a/apm-sniffer/apm-sdk-plugin/grpc-1.x-plugin/src/main/java/org/skywalking/apm/plugin/grpc/v1/define/StreamObserverToCallListenerInstrumentation.java b/apm-sniffer/apm-sdk-plugin/grpc-1.x-plugin/src/main/java/org/skywalking/apm/plugin/grpc/v1/define/StreamObserverToCallListenerInstrumentation.java new file mode 100644 index 0000000000000000000000000000000000000000..8bfddefa4bdd28b1104e39c31e3f7633f085bd54 --- /dev/null +++ b/apm-sniffer/apm-sdk-plugin/grpc-1.x-plugin/src/main/java/org/skywalking/apm/plugin/grpc/v1/define/StreamObserverToCallListenerInstrumentation.java @@ -0,0 +1,100 @@ +/* + * Copyright 2017, OpenSkywalking Organization All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * Project repository: https://github.com/OpenSkywalking/skywalking + */ + +package org.skywalking.apm.plugin.grpc.v1.define; + +import net.bytebuddy.description.method.MethodDescription; +import net.bytebuddy.matcher.ElementMatcher; +import org.skywalking.apm.agent.core.plugin.interceptor.ConstructorInterceptPoint; +import org.skywalking.apm.agent.core.plugin.interceptor.InstanceMethodsInterceptPoint; +import org.skywalking.apm.agent.core.plugin.interceptor.enhance.ClassInstanceMethodsEnhancePluginDefine; +import org.skywalking.apm.agent.core.plugin.match.ClassMatch; + +import static net.bytebuddy.matcher.ElementMatchers.named; +import static org.skywalking.apm.agent.core.plugin.match.NameMatch.byName; + +/** + * {@link StreamingServerCallHandlerInstrumentation} presents that skywalking intercept the onReady method + * by org.skywalking.apm.plugin.grpc.v1.ServerCallOnReadyInterceptor, the onHalfClose method + * by org.skywalking.apm.plugin.grpc.v1.ServerCallOnCloseInterceptor and the onMessage method + * by org.skywalking.apm.plugin.grpc.v1.ServerCallOnMessageInterceptor in + * io.grpc.stub.ServerCalls$StreamingServerCallHandler$StreamingServerCallListener class + * + * @author zhangxin + */ +public class StreamObserverToCallListenerInstrumentation extends ClassInstanceMethodsEnhancePluginDefine { + private static final String ENHANCE_CLASS = "io.grpc.stub.ClientCalls$StreamObserverToCallListenerAdapter"; + public static final String ON_READY_METHOD = "onReady"; + public static final String ON_READY_INTERCEPT_CLASS = "org.skywalking.apm.plugin.grpc.v1.StreamClientOnReadyInterceptor"; + public static final String ON_CLASS_METHOD = "onClose"; + public static final String ON_CLOSE_INTERCEPT_CLASS = "org.skywalking.apm.plugin.grpc.v1.StreamClientOnCloseInterceptor"; + public static final String ON_MESSAGE_METHOD = "onMessage"; + public static final String ON_MESSAGE_INTERCEPT_CLASS = "org.skywalking.apm.plugin.grpc.v1.ClientCallOnNextInterceptor"; + + @Override protected ConstructorInterceptPoint[] getConstructorsInterceptPoints() { + return new ConstructorInterceptPoint[0]; + } + + @Override protected InstanceMethodsInterceptPoint[] getInstanceMethodsInterceptPoints() { + return new InstanceMethodsInterceptPoint[] { + new InstanceMethodsInterceptPoint() { + @Override public ElementMatcher getMethodsMatcher() { + return named(ON_READY_METHOD); + } + + @Override public String getMethodsInterceptor() { + return ON_READY_INTERCEPT_CLASS; + } + + @Override public boolean isOverrideArgs() { + return false; + } + }, + new InstanceMethodsInterceptPoint() { + @Override public ElementMatcher getMethodsMatcher() { + return named(ON_CLASS_METHOD); + } + + @Override public String getMethodsInterceptor() { + return ON_CLOSE_INTERCEPT_CLASS; + } + + @Override public boolean isOverrideArgs() { + return false; + } + }, + new InstanceMethodsInterceptPoint() { + @Override public ElementMatcher getMethodsMatcher() { + return named(ON_MESSAGE_METHOD); + } + + @Override public String getMethodsInterceptor() { + return ON_MESSAGE_INTERCEPT_CLASS; + } + + @Override public boolean isOverrideArgs() { + return false; + } + } + }; + } + + @Override protected ClassMatch enhanceClass() { + return byName(ENHANCE_CLASS); + } +} diff --git a/apm-sniffer/apm-sdk-plugin/grpc-1.x-plugin/src/main/java/org/skywalking/apm/plugin/grpc/v1/define/StreamingServerCallHandlerInstrumentation.java b/apm-sniffer/apm-sdk-plugin/grpc-1.x-plugin/src/main/java/org/skywalking/apm/plugin/grpc/v1/define/StreamingServerCallHandlerInstrumentation.java new file mode 100644 index 0000000000000000000000000000000000000000..5840a6b0d1c1247178c637c25e11bbf29cb0e9e8 --- /dev/null +++ b/apm-sniffer/apm-sdk-plugin/grpc-1.x-plugin/src/main/java/org/skywalking/apm/plugin/grpc/v1/define/StreamingServerCallHandlerInstrumentation.java @@ -0,0 +1,68 @@ +/* + * Copyright 2017, OpenSkywalking Organization All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * Project repository: https://github.com/OpenSkywalking/skywalking + */ + +package org.skywalking.apm.plugin.grpc.v1.define; + +import net.bytebuddy.description.method.MethodDescription; +import net.bytebuddy.matcher.ElementMatcher; +import org.skywalking.apm.agent.core.plugin.interceptor.ConstructorInterceptPoint; +import org.skywalking.apm.agent.core.plugin.interceptor.InstanceMethodsInterceptPoint; +import org.skywalking.apm.agent.core.plugin.interceptor.enhance.ClassInstanceMethodsEnhancePluginDefine; +import org.skywalking.apm.agent.core.plugin.match.ClassMatch; + +import static net.bytebuddy.matcher.ElementMatchers.named; +import static org.skywalking.apm.agent.core.plugin.match.NameMatch.byName; + +/** + * {@link StreamingServerCallHandlerInstrumentation} presents that skywalking intercept the startCall + * method in io.grpc.stub.ServerCalls$UnaryServerCallHandler class by + * org.skywalking.apm.plugin.grpc.v1.ServerCallHandlerInterceptor + * + * @author zhangxin + */ +public class StreamingServerCallHandlerInstrumentation extends ClassInstanceMethodsEnhancePluginDefine { + private static final String ENHANCE_CLASS = "io.grpc.stub.ServerCalls$UnaryServerCallHandler"; + private static final String ENHANCE_METHOD = "startCall"; + public static final String INTERCEPT_CLASS = "org.skywalking.apm.plugin.grpc.v1.ServerCallHandlerInterceptor"; + + @Override protected ConstructorInterceptPoint[] getConstructorsInterceptPoints() { + return new ConstructorInterceptPoint[0]; + } + + @Override protected InstanceMethodsInterceptPoint[] getInstanceMethodsInterceptPoints() { + return new InstanceMethodsInterceptPoint[] { + new InstanceMethodsInterceptPoint() { + @Override public ElementMatcher getMethodsMatcher() { + return named(ENHANCE_METHOD); + } + + @Override public String getMethodsInterceptor() { + return INTERCEPT_CLASS; + } + + @Override public boolean isOverrideArgs() { + return false; + } + } + }; + } + + @Override protected ClassMatch enhanceClass() { + return byName(ENHANCE_CLASS); + } +} diff --git a/apm-sniffer/apm-sdk-plugin/grpc-1.x-plugin/src/main/java/org/skywalking/apm/plugin/grpc/v1/define/StreamingServerCallListenerInstrumentation.java b/apm-sniffer/apm-sdk-plugin/grpc-1.x-plugin/src/main/java/org/skywalking/apm/plugin/grpc/v1/define/StreamingServerCallListenerInstrumentation.java new file mode 100644 index 0000000000000000000000000000000000000000..d79e15bda9dac884dd18dd579482cb3ae552b7c7 --- /dev/null +++ b/apm-sniffer/apm-sdk-plugin/grpc-1.x-plugin/src/main/java/org/skywalking/apm/plugin/grpc/v1/define/StreamingServerCallListenerInstrumentation.java @@ -0,0 +1,116 @@ +/* + * Copyright 2017, OpenSkywalking Organization All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * Project repository: https://github.com/OpenSkywalking/skywalking + */ + +package org.skywalking.apm.plugin.grpc.v1.define; + +import net.bytebuddy.description.method.MethodDescription; +import net.bytebuddy.matcher.ElementMatcher; +import org.skywalking.apm.agent.core.plugin.interceptor.ConstructorInterceptPoint; +import org.skywalking.apm.agent.core.plugin.interceptor.InstanceMethodsInterceptPoint; +import org.skywalking.apm.agent.core.plugin.interceptor.enhance.ClassInstanceMethodsEnhancePluginDefine; +import org.skywalking.apm.agent.core.plugin.match.ClassMatch; + +import static net.bytebuddy.matcher.ElementMatchers.named; +import static org.skywalking.apm.agent.core.plugin.match.NameMatch.byName; + +/** + * {@link StreamingServerCallHandlerInstrumentation} presents that skywalking intercept the onReady method + * by org.skywalking.apm.plugin.grpc.v1.ServerCallOnReadyInterceptor, the onHalfClose method + * by org.skywalking.apm.plugin.grpc.v1.ServerCallOnCloseInterceptor, the onMessage method by + * org.skywalking.apm.plugin.grpc.v1.ServerCallOnMessageInterceptor and the onCancel method by + * org.skywalking.apm.plugin.grpc.v1.ServerCallOnCancelInterceptor in + * io.grpc.stub.ServerCalls$StreamingServerCallHandler$StreamingServerCallListener class + * + * @author zhangxin + */ +public class StreamingServerCallListenerInstrumentation extends ClassInstanceMethodsEnhancePluginDefine { + private static final String ENHANCE_CLASS = "io.grpc.stub.ServerCalls$StreamingServerCallHandler$StreamingServerCallListener"; + public static final String ON_READY_METHOD = "onReady"; + public static final String ON_READ_INTERCEPT_CLASS = "org.skywalking.apm.plugin.grpc.v1.ServerCallOnReadyInterceptor"; + public static final String ON_HALF_CLOSE_METHOD = "onHalfClose"; + public static final String ON_HALF_CLOSE_INTERCEPT_CLASS = "org.skywalking.apm.plugin.grpc.v1.ServerCallOnCloseInterceptor"; + public static final String ON_MESSAGE_METHOD = "onMessage"; + public static final String ON_MESSAGE_INTERCEPT_CLASS = "org.skywalking.apm.plugin.grpc.v1.ServerCallOnMessageInterceptor"; + public static final String ON_CANCEL_METHOD = "onCancel"; + public static final String ON_CANCEL_INTERCEPT_CLASS = "org.skywalking.apm.plugin.grpc.v1.ServerCallOnCancelInterceptor"; + + @Override protected ConstructorInterceptPoint[] getConstructorsInterceptPoints() { + return new ConstructorInterceptPoint[0]; + } + + @Override protected InstanceMethodsInterceptPoint[] getInstanceMethodsInterceptPoints() { + return new InstanceMethodsInterceptPoint[] { + new InstanceMethodsInterceptPoint() { + @Override public ElementMatcher getMethodsMatcher() { + return named(ON_READY_METHOD); + } + + @Override public String getMethodsInterceptor() { + return ON_READ_INTERCEPT_CLASS; + } + + @Override public boolean isOverrideArgs() { + return false; + } + }, + new InstanceMethodsInterceptPoint() { + @Override public ElementMatcher getMethodsMatcher() { + return named(ON_HALF_CLOSE_METHOD); + } + + @Override public String getMethodsInterceptor() { + return ON_HALF_CLOSE_INTERCEPT_CLASS; + } + + @Override public boolean isOverrideArgs() { + return false; + } + }, + new InstanceMethodsInterceptPoint() { + @Override public ElementMatcher getMethodsMatcher() { + return named(ON_MESSAGE_METHOD); + } + + @Override public String getMethodsInterceptor() { + return ON_MESSAGE_INTERCEPT_CLASS; + } + + @Override public boolean isOverrideArgs() { + return false; + } + }, + new InstanceMethodsInterceptPoint() { + @Override public ElementMatcher getMethodsMatcher() { + return named(ON_CANCEL_METHOD); + } + + @Override public String getMethodsInterceptor() { + return ON_CANCEL_INTERCEPT_CLASS; + } + + @Override public boolean isOverrideArgs() { + return false; + } + } + }; + } + + @Override protected ClassMatch enhanceClass() { + return byName(ENHANCE_CLASS); + } +} diff --git a/apm-sniffer/apm-sdk-plugin/grpc-1.x-plugin/src/main/java/org/skywalking/apm/plugin/grpc/v1/define/UnaryClientCallListenerInstrumentation.java b/apm-sniffer/apm-sdk-plugin/grpc-1.x-plugin/src/main/java/org/skywalking/apm/plugin/grpc/v1/define/UnaryClientCallListenerInstrumentation.java new file mode 100644 index 0000000000000000000000000000000000000000..42b4814a54bb489bd4daf1bd85732537cbd9c5bd --- /dev/null +++ b/apm-sniffer/apm-sdk-plugin/grpc-1.x-plugin/src/main/java/org/skywalking/apm/plugin/grpc/v1/define/UnaryClientCallListenerInstrumentation.java @@ -0,0 +1,67 @@ +/* + * Copyright 2017, OpenSkywalking Organization All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * Project repository: https://github.com/OpenSkywalking/skywalking + */ + +package org.skywalking.apm.plugin.grpc.v1.define; + +import net.bytebuddy.description.method.MethodDescription; +import net.bytebuddy.matcher.ElementMatcher; +import org.skywalking.apm.agent.core.plugin.interceptor.ConstructorInterceptPoint; +import org.skywalking.apm.agent.core.plugin.interceptor.InstanceMethodsInterceptPoint; +import org.skywalking.apm.agent.core.plugin.interceptor.enhance.ClassInstanceMethodsEnhancePluginDefine; +import org.skywalking.apm.agent.core.plugin.match.ClassMatch; + +import static net.bytebuddy.matcher.ElementMatchers.named; +import static org.skywalking.apm.agent.core.plugin.match.NameMatch.byName; + +/** + * {@link UnaryClientCallListenerInstrumentation} indicates that skywalking enhance the onClose method in + * io.grpc.stub.ClientCalls$UnaryStreamToFuture class by org.skywalking.apm.plugin.grpc.v1.UnaryClientOnCloseInterceptor + * + * @author zhangxin + */ +public class UnaryClientCallListenerInstrumentation extends ClassInstanceMethodsEnhancePluginDefine { + private static final String ENHANCE_CLASS = "io.grpc.stub.ClientCalls$UnaryStreamToFuture"; + private static final String ENHANCE_METHOD = "onClose"; + public static final String INTERCEPT_CLASS = "org.skywalking.apm.plugin.grpc.v1.UnaryClientOnCloseInterceptor"; + + @Override protected ConstructorInterceptPoint[] getConstructorsInterceptPoints() { + return new ConstructorInterceptPoint[0]; + } + + @Override protected InstanceMethodsInterceptPoint[] getInstanceMethodsInterceptPoints() { + return new InstanceMethodsInterceptPoint[] { + new InstanceMethodsInterceptPoint() { + @Override public ElementMatcher getMethodsMatcher() { + return named(ENHANCE_METHOD); + } + + @Override public String getMethodsInterceptor() { + return INTERCEPT_CLASS; + } + + @Override public boolean isOverrideArgs() { + return false; + } + } + }; + } + + @Override protected ClassMatch enhanceClass() { + return byName(ENHANCE_CLASS); + } +} diff --git a/apm-sniffer/apm-sdk-plugin/grpc-1.x-plugin/src/main/java/org/skywalking/apm/plugin/grpc/v1/define/UnaryServerCallHandlerInstrumentation.java b/apm-sniffer/apm-sdk-plugin/grpc-1.x-plugin/src/main/java/org/skywalking/apm/plugin/grpc/v1/define/UnaryServerCallHandlerInstrumentation.java new file mode 100644 index 0000000000000000000000000000000000000000..76abdc6e5f6b7a925b0d89f7eb109d681c118990 --- /dev/null +++ b/apm-sniffer/apm-sdk-plugin/grpc-1.x-plugin/src/main/java/org/skywalking/apm/plugin/grpc/v1/define/UnaryServerCallHandlerInstrumentation.java @@ -0,0 +1,67 @@ +/* + * Copyright 2017, OpenSkywalking Organization All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * Project repository: https://github.com/OpenSkywalking/skywalking + */ + +package org.skywalking.apm.plugin.grpc.v1.define; + +import net.bytebuddy.description.method.MethodDescription; +import net.bytebuddy.matcher.ElementMatcher; +import org.skywalking.apm.agent.core.plugin.interceptor.ConstructorInterceptPoint; +import org.skywalking.apm.agent.core.plugin.interceptor.InstanceMethodsInterceptPoint; +import org.skywalking.apm.agent.core.plugin.interceptor.enhance.ClassInstanceMethodsEnhancePluginDefine; +import org.skywalking.apm.agent.core.plugin.match.ClassMatch; + +import static net.bytebuddy.matcher.ElementMatchers.named; +import static org.skywalking.apm.agent.core.plugin.match.NameMatch.byName; + +/** + * {@link UnaryServerCallHandlerInstrumentation} indicates that skywalking enhance the startCall in + * io.grpc.stub.ServerCalls$StreamingServerCallHandler class by org.skywalking.apm.plugin.grpc.v1.ServerCallHandlerInterceptor. + * + * @author zhangxin + */ +public class UnaryServerCallHandlerInstrumentation extends ClassInstanceMethodsEnhancePluginDefine { + private static final String ENHANCE_CLASS = "io.grpc.stub.ServerCalls$StreamingServerCallHandler"; + private static final String ENHANCE_METHOD = "startCall"; + public static final String INTERCEPT_CLASS = "org.skywalking.apm.plugin.grpc.v1.ServerCallHandlerInterceptor"; + + @Override protected ConstructorInterceptPoint[] getConstructorsInterceptPoints() { + return new ConstructorInterceptPoint[0]; + } + + @Override protected InstanceMethodsInterceptPoint[] getInstanceMethodsInterceptPoints() { + return new InstanceMethodsInterceptPoint[] { + new InstanceMethodsInterceptPoint() { + @Override public ElementMatcher getMethodsMatcher() { + return named(ENHANCE_METHOD); + } + + @Override public String getMethodsInterceptor() { + return INTERCEPT_CLASS; + } + + @Override public boolean isOverrideArgs() { + return false; + } + } + }; + } + + @Override protected ClassMatch enhanceClass() { + return byName(ENHANCE_CLASS); + } +} diff --git a/apm-sniffer/apm-sdk-plugin/grpc-1.x-plugin/src/main/java/org/skywalking/apm/plugin/grpc/v1/define/UnaryServerCallListenerInstrumentation.java b/apm-sniffer/apm-sdk-plugin/grpc-1.x-plugin/src/main/java/org/skywalking/apm/plugin/grpc/v1/define/UnaryServerCallListenerInstrumentation.java new file mode 100644 index 0000000000000000000000000000000000000000..957480da8ae912e3214f335835d26332db3f5210 --- /dev/null +++ b/apm-sniffer/apm-sdk-plugin/grpc-1.x-plugin/src/main/java/org/skywalking/apm/plugin/grpc/v1/define/UnaryServerCallListenerInstrumentation.java @@ -0,0 +1,101 @@ +/* + * Copyright 2017, OpenSkywalking Organization All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * Project repository: https://github.com/OpenSkywalking/skywalking + */ + +package org.skywalking.apm.plugin.grpc.v1.define; + +import net.bytebuddy.description.method.MethodDescription; +import net.bytebuddy.matcher.ElementMatcher; +import org.skywalking.apm.agent.core.plugin.interceptor.ConstructorInterceptPoint; +import org.skywalking.apm.agent.core.plugin.interceptor.InstanceMethodsInterceptPoint; +import org.skywalking.apm.agent.core.plugin.interceptor.enhance.ClassInstanceMethodsEnhancePluginDefine; +import org.skywalking.apm.agent.core.plugin.match.ClassMatch; + +import static net.bytebuddy.matcher.ElementMatchers.named; +import static org.skywalking.apm.agent.core.plugin.match.NameMatch.byName; + +/** + * {@link StreamingServerCallHandlerInstrumentation} presents that skywalking intercept the onReady method + * by org.skywalking.apm.plugin.grpc.v1.ServerCallOnReadyInterceptor, the onHalfClose method + * by org.skywalking.apm.plugin.grpc.v1.ServerCallOnCloseInterceptor, the onMessage method by + * org.skywalking.apm.plugin.grpc.v1.ServerCallOnMessageInterceptor and the onCancel method by + * org.skywalking.apm.plugin.grpc.v1.ServerCallOnCancelInterceptor in + * io.grpc.stub.ServerCalls$UnaryServerCallHandler$UnaryServerCallListener class + * + * @author zhangxin + */ +public class UnaryServerCallListenerInstrumentation extends ClassInstanceMethodsEnhancePluginDefine { + private static final String ENHANCE_CLASS = "io.grpc.stub.ServerCalls$UnaryServerCallHandler$UnaryServerCallListener"; + public static final String ON_CLOSE_METHOD = "onHalfClose"; + public static final String ON_CLOSE_INTERCEPT_CLASS = "org.skywalking.apm.plugin.grpc.v1.ServerCallOnCloseInterceptor"; + public static final String ON_READY_METHOD = "onReady"; + public static final String ON_READY_INTERCEPT_CLASS = "org.skywalking.apm.plugin.grpc.v1.ServerCallOnReadyInterceptor"; + public static final String ON_CANCEL_METHOD = "onCancel"; + public static final String ON_CANCEL_INTERCEPT_CLASS = "org.skywalking.apm.plugin.grpc.v1.ServerCallOnCancelInterceptor"; + + @Override protected ConstructorInterceptPoint[] getConstructorsInterceptPoints() { + return new ConstructorInterceptPoint[0]; + } + + @Override protected InstanceMethodsInterceptPoint[] getInstanceMethodsInterceptPoints() { + return new InstanceMethodsInterceptPoint[] { + new InstanceMethodsInterceptPoint() { + @Override public ElementMatcher getMethodsMatcher() { + return named(ON_CLOSE_METHOD); + } + + @Override public String getMethodsInterceptor() { + return ON_CLOSE_INTERCEPT_CLASS; + } + + @Override public boolean isOverrideArgs() { + return false; + } + }, + new InstanceMethodsInterceptPoint() { + @Override public ElementMatcher getMethodsMatcher() { + return named(ON_READY_METHOD); + } + + @Override public String getMethodsInterceptor() { + return ON_READY_INTERCEPT_CLASS; + } + + @Override public boolean isOverrideArgs() { + return false; + } + }, + new InstanceMethodsInterceptPoint() { + @Override public ElementMatcher getMethodsMatcher() { + return named(ON_CANCEL_METHOD); + } + + @Override public String getMethodsInterceptor() { + return ON_CANCEL_INTERCEPT_CLASS; + } + + @Override public boolean isOverrideArgs() { + return false; + } + } + }; + } + + @Override protected ClassMatch enhanceClass() { + return byName(ENHANCE_CLASS); + } +} diff --git a/apm-sniffer/apm-sdk-plugin/grpc-1.x-plugin/src/main/java/org/skywalking/apm/plugin/grpc/v1/vo/GRPCDynamicFields.java b/apm-sniffer/apm-sdk-plugin/grpc-1.x-plugin/src/main/java/org/skywalking/apm/plugin/grpc/v1/vo/GRPCDynamicFields.java new file mode 100644 index 0000000000000000000000000000000000000000..03ae66a1e364517ee5236679242d2d2eb91b4e10 --- /dev/null +++ b/apm-sniffer/apm-sdk-plugin/grpc-1.x-plugin/src/main/java/org/skywalking/apm/plugin/grpc/v1/vo/GRPCDynamicFields.java @@ -0,0 +1,88 @@ +/* + * Copyright 2017, OpenSkywalking Organization All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * Project repository: https://github.com/OpenSkywalking/skywalking + */ + +package org.skywalking.apm.plugin.grpc.v1.vo; + +import io.grpc.Metadata; +import io.grpc.MethodDescriptor; +import org.skywalking.apm.agent.core.context.ContextSnapshot; + +/** + * {@link GRPCDynamicFields} contain the require information of span. + * + * @author zhangxin + */ +public class GRPCDynamicFields { + private ServiceDescriptor descriptor; + private Metadata metadata; + private String authority; + private ContextSnapshot snapshot; + private int onNextCount; + + public Metadata getMetadata() { + return metadata; + } + + public void setMetadata(Metadata metadata) { + this.metadata = metadata; + } + + public String getAuthority() { + return authority; + } + + public void setAuthority(String authority) { + this.authority = authority; + } + + public String getRequestMethodName() { + return descriptor.getServiceName(); + } + + public void setDescriptor(MethodDescriptor methodDescriptor) { + this.descriptor = new ServiceDescriptor(methodDescriptor); + } + + public void setDescriptor(ServiceDescriptor methodDescriptor) { + this.descriptor = methodDescriptor; + } + + public ServiceDescriptor getDescriptor() { + return descriptor; + } + + public ContextSnapshot getSnapshot() { + return snapshot; + } + + public void setSnapshot(ContextSnapshot snapshot) { + this.snapshot = snapshot; + } + + public MethodDescriptor.MethodType getMethodType() { + return descriptor.getMethodType(); + } + + public void incrementOnNextCount() { + onNextCount++; + } + + public int getOnNextCount() { + return onNextCount; + } +} diff --git a/apm-sniffer/apm-sdk-plugin/grpc-1.x-plugin/src/main/java/org/skywalking/apm/plugin/grpc/v1/vo/ServiceDescriptor.java b/apm-sniffer/apm-sdk-plugin/grpc-1.x-plugin/src/main/java/org/skywalking/apm/plugin/grpc/v1/vo/ServiceDescriptor.java new file mode 100644 index 0000000000000000000000000000000000000000..1409a314473b15c0864f219a315ca3cea95d13fd --- /dev/null +++ b/apm-sniffer/apm-sdk-plugin/grpc-1.x-plugin/src/main/java/org/skywalking/apm/plugin/grpc/v1/vo/ServiceDescriptor.java @@ -0,0 +1,58 @@ +/* + * Copyright 2017, OpenSkywalking Organization All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * Project repository: https://github.com/OpenSkywalking/skywalking + */ + +package org.skywalking.apm.plugin.grpc.v1.vo; + +import io.grpc.MethodDescriptor; + +/** + * {@link ServiceDescriptor} indicate the descriptor of an grpc service. it contains {@link #methodType} and + * {@link #serviceName}. + * + * @author zhangxin + */ +public class ServiceDescriptor { + private MethodDescriptor.MethodType methodType; + private String serviceName; + + public ServiceDescriptor(MethodDescriptor descriptor) { + this.methodType = descriptor.getType(); + String fullMethodName = descriptor.getFullMethodName(); + this.serviceName = formatServiceName(fullMethodName) + "." + formatMethodName(fullMethodName); + } + + private String formatServiceName(String requestMethodName) { + int splitIndex = requestMethodName.lastIndexOf("/"); + return requestMethodName.substring(0, splitIndex); + } + + private String formatMethodName(String requestMethodName) { + int splitIndex = requestMethodName.lastIndexOf("/"); + String methodName = requestMethodName.substring(splitIndex + 1); + methodName = methodName.substring(0, 1).toLowerCase() + methodName.substring(1); + return methodName; + } + + public MethodDescriptor.MethodType getMethodType() { + return methodType; + } + + public String getServiceName() { + return serviceName; + } +} diff --git a/apm-sniffer/apm-sdk-plugin/grpc-1.x-plugin/src/main/resources/skywalking-plugin.def b/apm-sniffer/apm-sdk-plugin/grpc-1.x-plugin/src/main/resources/skywalking-plugin.def new file mode 100644 index 0000000000000000000000000000000000000000..6dbb61d92e165f0178599c9b7efbc277b5856d7d --- /dev/null +++ b/apm-sniffer/apm-sdk-plugin/grpc-1.x-plugin/src/main/resources/skywalking-plugin.def @@ -0,0 +1,8 @@ +grpc-1.x=org.skywalking.apm.plugin.grpc.v1.define.ClientCallInstrumentation +grpc-1.x=org.skywalking.apm.plugin.grpc.v1.define.UnaryClientCallListenerInstrumentation +grpc-1.x=org.skywalking.apm.plugin.grpc.v1.define.UnaryServerCallListenerInstrumentation +grpc-1.x=org.skywalking.apm.plugin.grpc.v1.define.UnaryServerCallHandlerInstrumentation +grpc-1.x=org.skywalking.apm.plugin.grpc.v1.define.ManagedChannelInstrumentation +grpc-1.x=org.skywalking.apm.plugin.grpc.v1.define.StreamingServerCallHandlerInstrumentation +grpc-1.x=org.skywalking.apm.plugin.grpc.v1.define.StreamingServerCallListenerInstrumentation +grpc-1.x=org.skywalking.apm.plugin.grpc.v1.define.StreamObserverToCallListenerInstrumentation diff --git a/apm-sniffer/apm-sdk-plugin/grpc-1.x-plugin/src/test/java/org/skywalking/apm/plugin/grpc/v1/ClientCallIConstructorInterceptorTest.java b/apm-sniffer/apm-sdk-plugin/grpc-1.x-plugin/src/test/java/org/skywalking/apm/plugin/grpc/v1/ClientCallIConstructorInterceptorTest.java new file mode 100644 index 0000000000000000000000000000000000000000..d71081f887cab5b95d1c261b923813e37515c134 --- /dev/null +++ b/apm-sniffer/apm-sdk-plugin/grpc-1.x-plugin/src/test/java/org/skywalking/apm/plugin/grpc/v1/ClientCallIConstructorInterceptorTest.java @@ -0,0 +1,64 @@ +/* + * Copyright 2017, OpenSkywalking Organization All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * Project repository: https://github.com/OpenSkywalking/skywalking + */ + +package org.skywalking.apm.plugin.grpc.v1; + +import io.grpc.MethodDescriptor; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Matchers; +import org.mockito.Mock; +import org.powermock.core.classloader.annotations.PrepareForTest; +import org.powermock.modules.junit4.PowerMockRunner; +import org.skywalking.apm.agent.core.plugin.interceptor.enhance.EnhancedInstance; + +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; +import static org.powermock.api.mockito.PowerMockito.mock; +import static org.powermock.api.mockito.PowerMockito.when; + +@RunWith(PowerMockRunner.class) +@PrepareForTest(MethodDescriptor.class) +public class ClientCallIConstructorInterceptorTest { + + private ClientCallIConstructorInterceptor constructorInterceptor; + + @Mock + private EnhancedInstance enhancedInstance; + + private Object[] arguments; + + @Before + public void setUp() { + constructorInterceptor = new ClientCallIConstructorInterceptor(); + + MethodDescriptor methodDescriptor = mock(MethodDescriptor.class); + when(methodDescriptor.getType()).thenReturn(MethodDescriptor.MethodType.UNARY); + when(methodDescriptor.getFullMethodName()).thenReturn("test/testMethod"); + + arguments = new Object[] {methodDescriptor}; + } + + @Test + public void testOnConstructor() { + constructorInterceptor.onConstruct(enhancedInstance, arguments); + verify(enhancedInstance, times(1)).setSkyWalkingDynamicField(Matchers.any()); + } + +} diff --git a/apm-sniffer/apm-sdk-plugin/grpc-1.x-plugin/src/test/java/org/skywalking/apm/plugin/grpc/v1/ClientCallOnNextInterceptorTest.java b/apm-sniffer/apm-sdk-plugin/grpc-1.x-plugin/src/test/java/org/skywalking/apm/plugin/grpc/v1/ClientCallOnNextInterceptorTest.java new file mode 100644 index 0000000000000000000000000000000000000000..7524016a6c1018969002c48d8aba810dadfc9fa9 --- /dev/null +++ b/apm-sniffer/apm-sdk-plugin/grpc-1.x-plugin/src/test/java/org/skywalking/apm/plugin/grpc/v1/ClientCallOnNextInterceptorTest.java @@ -0,0 +1,84 @@ +/* + * Copyright 2017, OpenSkywalking Organization All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * Project repository: https://github.com/OpenSkywalking/skywalking + */ + +package org.skywalking.apm.plugin.grpc.v1; + +import org.junit.Before; +import org.junit.Rule; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mock; +import org.powermock.modules.junit4.PowerMockRunner; +import org.powermock.modules.junit4.PowerMockRunnerDelegate; +import org.skywalking.apm.agent.core.context.trace.AbstractTracingSpan; +import org.skywalking.apm.agent.core.context.trace.TraceSegment; +import org.skywalking.apm.agent.core.plugin.interceptor.enhance.EnhancedInstance; +import org.skywalking.apm.agent.test.helper.SegmentHelper; +import org.skywalking.apm.agent.test.tools.AgentServiceRule; +import org.skywalking.apm.agent.test.tools.SegmentStorage; +import org.skywalking.apm.agent.test.tools.SegmentStoragePoint; +import org.skywalking.apm.agent.test.tools.TracingSegmentRunner; +import org.skywalking.apm.plugin.grpc.v1.vo.GRPCDynamicFields; + +import static org.hamcrest.core.Is.is; +import static org.junit.Assert.assertThat; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; +import static org.powermock.api.mockito.PowerMockito.when; + +@RunWith(PowerMockRunner.class) +@PowerMockRunnerDelegate(TracingSegmentRunner.class) +public class ClientCallOnNextInterceptorTest { + @SegmentStoragePoint + private SegmentStorage segmentStorage; + + @Rule + public AgentServiceRule agentServiceRule = new AgentServiceRule(); + + @Mock + private EnhancedInstance clientCall; + + @Mock + private GRPCDynamicFields cachedObjects; + + private ClientCallOnNextInterceptor callOnNextInterceptor; + + @Before + public void setUp() { + when(cachedObjects.getRequestMethodName()).thenReturn("org.skywalking.test.grpc.GreetService.sayHello"); + when(clientCall.getSkyWalkingDynamicField()).thenReturn(cachedObjects); + + callOnNextInterceptor = new ClientCallOnNextInterceptor(); + } + + @Test + public void testCallOnNext() throws Throwable { + callOnNextInterceptor.beforeMethod(clientCall, null, null, null, null); + callOnNextInterceptor.afterMethod(clientCall, null, null, null, null); + + verify(cachedObjects, times(1)).incrementOnNextCount(); + + assertThat(segmentStorage.getTraceSegments().size(), is(1)); + TraceSegment traceSegment = segmentStorage.getTraceSegments().get(0); + assertThat(SegmentHelper.getSpans(traceSegment).size(), is(1)); + AbstractTracingSpan span = SegmentHelper.getSpans(traceSegment).get(0); + assertThat(span.getOperationName(), is("org.skywalking.test.grpc.GreetService.sayHello/ResponseStreamObserver/OnNext")); + assertThat(span.isEntry(), is(false)); + assertThat(span.isExit(), is(false)); + } +} diff --git a/apm-sniffer/apm-sdk-plugin/grpc-1.x-plugin/src/test/java/org/skywalking/apm/plugin/grpc/v1/ClientCallStartInterceptorTest.java b/apm-sniffer/apm-sdk-plugin/grpc-1.x-plugin/src/test/java/org/skywalking/apm/plugin/grpc/v1/ClientCallStartInterceptorTest.java new file mode 100644 index 0000000000000000000000000000000000000000..a266a110e1fc7e9b583f4fb63d03bae1dd27ba08 --- /dev/null +++ b/apm-sniffer/apm-sdk-plugin/grpc-1.x-plugin/src/test/java/org/skywalking/apm/plugin/grpc/v1/ClientCallStartInterceptorTest.java @@ -0,0 +1,148 @@ +/* + * Copyright 2017, OpenSkywalking Organization All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * Project repository: https://github.com/OpenSkywalking/skywalking + */ + +package org.skywalking.apm.plugin.grpc.v1; + +import io.grpc.Metadata; +import io.grpc.MethodDescriptor; +import io.grpc.Status; +import io.grpc.StatusRuntimeException; +import org.junit.Before; +import org.junit.Rule; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mock; +import org.powermock.modules.junit4.PowerMockRunner; +import org.powermock.modules.junit4.PowerMockRunnerDelegate; +import org.skywalking.apm.agent.core.context.trace.AbstractTracingSpan; +import org.skywalking.apm.agent.core.context.trace.SpanLayer; +import org.skywalking.apm.agent.core.context.trace.TraceSegment; +import org.skywalking.apm.agent.core.plugin.interceptor.enhance.EnhancedInstance; +import org.skywalking.apm.agent.test.helper.SegmentHelper; +import org.skywalking.apm.agent.test.helper.SpanHelper; +import org.skywalking.apm.agent.test.tools.AgentServiceRule; +import org.skywalking.apm.agent.test.tools.SegmentStorage; +import org.skywalking.apm.agent.test.tools.SegmentStoragePoint; +import org.skywalking.apm.agent.test.tools.SpanAssert; +import org.skywalking.apm.agent.test.tools.TracingSegmentRunner; +import org.skywalking.apm.network.trace.component.ComponentsDefine; +import org.skywalking.apm.plugin.grpc.v1.vo.GRPCDynamicFields; + +import static org.hamcrest.CoreMatchers.is; +import static org.junit.Assert.assertThat; +import static org.powermock.api.mockito.PowerMockito.when; + +@RunWith(PowerMockRunner.class) +@PowerMockRunnerDelegate(TracingSegmentRunner.class) +public class ClientCallStartInterceptorTest { + + @SegmentStoragePoint + private SegmentStorage segmentStorage; + + @Rule + public AgentServiceRule agentServiceRule = new AgentServiceRule(); + + private ClientCallStartInterceptor clientCallStartInterceptor; + private UnaryClientOnCloseInterceptor unaryClientOnCloseInterceptor; + + @Mock + private EnhancedInstance clientCallImpl; + + @Mock + private EnhancedInstance clientCallListener; + + @Mock + private GRPCDynamicFields unaryCachedObjects; + + @Mock + private GRPCDynamicFields streamCachedObjects; + + private Status exceptionStatus = Status.NOT_FOUND.withCause(new RuntimeException()); + + private Object[] arguments; + private Class[] argumentTypes; + + @Before + public void setUp() { + when(unaryCachedObjects.getRequestMethodName()).thenReturn("org.skywalking.test.grpc.GreetService.sayHello"); + when(unaryCachedObjects.getAuthority()).thenReturn("localhost:500051"); + when(unaryCachedObjects.getMethodType()).thenReturn(MethodDescriptor.MethodType.UNARY); + + when(streamCachedObjects.getRequestMethodName()).thenReturn("org.skywalking.test.grpc.GreetService.sayHello"); + when(streamCachedObjects.getAuthority()).thenReturn("localhost:500051"); + when(streamCachedObjects.getMethodType()).thenReturn(MethodDescriptor.MethodType.SERVER_STREAMING); + + arguments = new Object[] {clientCallListener, new Metadata()}; + argumentTypes = new Class[] {clientCallListener.getClass(), Metadata.class}; + + clientCallStartInterceptor = new ClientCallStartInterceptor(); + unaryClientOnCloseInterceptor = new UnaryClientOnCloseInterceptor(); + } + + @Test + public void testNormalUnaryCallStart() throws Throwable { + when(clientCallImpl.getSkyWalkingDynamicField()).thenReturn(unaryCachedObjects); + + clientCallStartInterceptor.beforeMethod(clientCallImpl, null, arguments, argumentTypes, null); + clientCallStartInterceptor.afterMethod(clientCallImpl, null, arguments, argumentTypes, null); + unaryClientOnCloseInterceptor.afterMethod(null, null, new Object[] {Status.OK, new Metadata()}, null, null); + + assertThat(segmentStorage.getTraceSegments().size(), is(1)); + TraceSegment traceSegment = segmentStorage.getTraceSegments().get(0); + assertThat(SegmentHelper.getSpans(traceSegment).size(), is(1)); + AbstractTracingSpan abstractTracingSpan = SegmentHelper.getSpans(traceSegment).get(0); + SpanAssert.assertComponent(abstractTracingSpan, ComponentsDefine.GRPC); + SpanAssert.assertLayer(abstractTracingSpan, SpanLayer.RPC_FRAMEWORK); + SpanAssert.assertOccurException(abstractTracingSpan, false); + } + + @Test + public void testUnaryCallStartWithException() throws Throwable { + when(clientCallImpl.getSkyWalkingDynamicField()).thenReturn(unaryCachedObjects); + + clientCallStartInterceptor.beforeMethod(clientCallImpl, null, arguments, argumentTypes, null); + clientCallStartInterceptor.afterMethod(clientCallImpl, null, arguments, argumentTypes, null); + unaryClientOnCloseInterceptor.afterMethod(null, null, new Object[] {exceptionStatus, new Metadata()}, null, null); + + assertThat(segmentStorage.getTraceSegments().size(), is(1)); + TraceSegment traceSegment = segmentStorage.getTraceSegments().get(0); + assertThat(SegmentHelper.getSpans(traceSegment).size(), is(1)); + AbstractTracingSpan abstractTracingSpan = SegmentHelper.getSpans(traceSegment).get(0); + SpanAssert.assertComponent(abstractTracingSpan, ComponentsDefine.GRPC); + SpanAssert.assertLayer(abstractTracingSpan, SpanLayer.RPC_FRAMEWORK); + SpanAssert.assertOccurException(abstractTracingSpan, true); + SpanAssert.assertException(SpanHelper.getLogs(abstractTracingSpan).get(0), StatusRuntimeException.class, "NOT_FOUND"); + } + + @Test + public void testNormalStreamCallStart() throws Throwable { + when(clientCallImpl.getSkyWalkingDynamicField()).thenReturn(streamCachedObjects); + + clientCallStartInterceptor.beforeMethod(clientCallImpl, null, arguments, argumentTypes, null); + clientCallStartInterceptor.afterMethod(clientCallImpl, null, arguments, argumentTypes, null); + + assertThat(segmentStorage.getTraceSegments().size(), is(1)); + TraceSegment traceSegment = segmentStorage.getTraceSegments().get(0); + assertThat(SegmentHelper.getSpans(traceSegment).size(), is(1)); + AbstractTracingSpan abstractTracingSpan = SegmentHelper.getSpans(traceSegment).get(0); + SpanAssert.assertComponent(abstractTracingSpan, ComponentsDefine.GRPC); + SpanAssert.assertLayer(abstractTracingSpan, SpanLayer.RPC_FRAMEWORK); + SpanAssert.assertOccurException(abstractTracingSpan, false); + } + +} diff --git a/apm-sniffer/apm-sdk-plugin/grpc-1.x-plugin/src/test/java/org/skywalking/apm/plugin/grpc/v1/ServerCallHandlerInterceptorTest.java b/apm-sniffer/apm-sdk-plugin/grpc-1.x-plugin/src/test/java/org/skywalking/apm/plugin/grpc/v1/ServerCallHandlerInterceptorTest.java new file mode 100644 index 0000000000000000000000000000000000000000..e25f77cae6d2b573a0443ec8e5d2c83234d1b3c7 --- /dev/null +++ b/apm-sniffer/apm-sdk-plugin/grpc-1.x-plugin/src/test/java/org/skywalking/apm/plugin/grpc/v1/ServerCallHandlerInterceptorTest.java @@ -0,0 +1,71 @@ +/* + * Copyright 2017, OpenSkywalking Organization All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * Project repository: https://github.com/OpenSkywalking/skywalking + */ + +package org.skywalking.apm.plugin.grpc.v1; + +import io.grpc.Metadata; +import io.grpc.MethodDescriptor; +import io.grpc.ServerCall; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Matchers; +import org.mockito.Mock; +import org.powermock.core.classloader.annotations.PrepareForTest; +import org.powermock.modules.junit4.PowerMockRunner; +import org.skywalking.apm.agent.core.plugin.interceptor.enhance.EnhancedInstance; + +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; +import static org.powermock.api.mockito.PowerMockito.when; + +@RunWith(PowerMockRunner.class) +@PrepareForTest(MethodDescriptor.class) +public class ServerCallHandlerInterceptorTest { + @Mock + private EnhancedInstance enhancedInstance; + + private ServerCallHandlerInterceptor callHandlerInterceptor; + + @Mock + private ServerCall serverCall; + @Mock + private MethodDescriptor methodDescriptor; + + private Metadata metadata; + + private Object[] arguments; + private Class[] argumentTypes; + + @Before + public void setUp() { + when(methodDescriptor.getFullMethodName()).thenReturn("org.skywalking.test.GreetService/SayHello"); + when(serverCall.getMethodDescriptor()).thenReturn(methodDescriptor); + + callHandlerInterceptor = new ServerCallHandlerInterceptor(); + metadata = new Metadata(); + arguments = new Object[] {serverCall, metadata}; + argumentTypes = new Class[] {serverCall.getClass(), metadata.getClass()}; + } + + @Test + public void testSetCachedObjects() throws Throwable { + callHandlerInterceptor.afterMethod(null, null, arguments, argumentTypes, enhancedInstance); + verify(enhancedInstance, times(1)).setSkyWalkingDynamicField(Matchers.any()); + } +} diff --git a/apm-sniffer/apm-sdk-plugin/grpc-1.x-plugin/src/test/java/org/skywalking/apm/plugin/grpc/v1/ServerCallOnMessageInterceptorTest.java b/apm-sniffer/apm-sdk-plugin/grpc-1.x-plugin/src/test/java/org/skywalking/apm/plugin/grpc/v1/ServerCallOnMessageInterceptorTest.java new file mode 100644 index 0000000000000000000000000000000000000000..71d36d228f97b28359367e46043eb0ca0750fbea --- /dev/null +++ b/apm-sniffer/apm-sdk-plugin/grpc-1.x-plugin/src/test/java/org/skywalking/apm/plugin/grpc/v1/ServerCallOnMessageInterceptorTest.java @@ -0,0 +1,85 @@ +/* + * Copyright 2017, OpenSkywalking Organization All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * Project repository: https://github.com/OpenSkywalking/skywalking + */ + +package org.skywalking.apm.plugin.grpc.v1; + +import org.junit.Before; +import org.junit.Rule; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mock; +import org.powermock.modules.junit4.PowerMockRunner; +import org.powermock.modules.junit4.PowerMockRunnerDelegate; +import org.skywalking.apm.agent.core.context.trace.AbstractTracingSpan; +import org.skywalking.apm.agent.core.context.trace.TraceSegment; +import org.skywalking.apm.agent.core.plugin.interceptor.enhance.EnhancedInstance; +import org.skywalking.apm.agent.test.helper.SegmentHelper; +import org.skywalking.apm.agent.test.tools.AgentServiceRule; +import org.skywalking.apm.agent.test.tools.SegmentStorage; +import org.skywalking.apm.agent.test.tools.SegmentStoragePoint; +import org.skywalking.apm.agent.test.tools.TracingSegmentRunner; +import org.skywalking.apm.plugin.grpc.v1.vo.GRPCDynamicFields; + +import static org.hamcrest.core.Is.is; +import static org.junit.Assert.assertThat; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; +import static org.powermock.api.mockito.PowerMockito.when; + +@RunWith(PowerMockRunner.class) +@PowerMockRunnerDelegate(TracingSegmentRunner.class) +public class ServerCallOnMessageInterceptorTest { + + @SegmentStoragePoint + private SegmentStorage segmentStorage; + + @Rule + public AgentServiceRule agentServiceRule = new AgentServiceRule(); + + @Mock + private EnhancedInstance clientCall; + + @Mock + private GRPCDynamicFields cachedObjects; + + private ServerCallOnMessageInterceptor serverCallOnMessageInterceptor; + + @Before + public void setUp() { + when(cachedObjects.getRequestMethodName()).thenReturn("org.skywalking.test.grpc.GreetService.sayHello"); + when(clientCall.getSkyWalkingDynamicField()).thenReturn(cachedObjects); + + serverCallOnMessageInterceptor = new ServerCallOnMessageInterceptor(); + } + + @Test + public void testCallOnNext() throws Throwable { + serverCallOnMessageInterceptor.beforeMethod(clientCall, null, null, null, null); + serverCallOnMessageInterceptor.afterMethod(clientCall, null, null, null, null); + + verify(cachedObjects, times(1)).incrementOnNextCount(); + + assertThat(segmentStorage.getTraceSegments().size(), is(1)); + TraceSegment traceSegment = segmentStorage.getTraceSegments().get(0); + assertThat(SegmentHelper.getSpans(traceSegment).size(), is(1)); + AbstractTracingSpan span = SegmentHelper.getSpans(traceSegment).get(0); + assertThat(span.getOperationName(), is("org.skywalking.test.grpc.GreetService.sayHello/ResponseStreamObserver/OnNext")); + assertThat(span.isEntry(), is(false)); + assertThat(span.isExit(), is(false)); + } +} diff --git a/apm-sniffer/apm-sdk-plugin/grpc-1.x-plugin/src/test/java/org/skywalking/apm/plugin/grpc/v1/ServerCallOnReadyInterceptorTest.java b/apm-sniffer/apm-sdk-plugin/grpc-1.x-plugin/src/test/java/org/skywalking/apm/plugin/grpc/v1/ServerCallOnReadyInterceptorTest.java new file mode 100644 index 0000000000000000000000000000000000000000..8bf3e189da2c683bfb52df9f48fb4b2c46978442 --- /dev/null +++ b/apm-sniffer/apm-sdk-plugin/grpc-1.x-plugin/src/test/java/org/skywalking/apm/plugin/grpc/v1/ServerCallOnReadyInterceptorTest.java @@ -0,0 +1,138 @@ +/* + * Copyright 2017, OpenSkywalking Organization All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * Project repository: https://github.com/OpenSkywalking/skywalking + */ + +package org.skywalking.apm.plugin.grpc.v1; + +import io.grpc.Metadata; +import io.grpc.MethodDescriptor; +import org.junit.Before; +import org.junit.Rule; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mock; +import org.powermock.modules.junit4.PowerMockRunner; +import org.powermock.modules.junit4.PowerMockRunnerDelegate; +import org.skywalking.apm.agent.core.context.trace.AbstractTracingSpan; +import org.skywalking.apm.agent.core.context.trace.TraceSegment; +import org.skywalking.apm.agent.core.plugin.interceptor.enhance.EnhancedInstance; +import org.skywalking.apm.agent.test.helper.SegmentHelper; +import org.skywalking.apm.agent.test.helper.SpanHelper; +import org.skywalking.apm.agent.test.tools.AgentServiceRule; +import org.skywalking.apm.agent.test.tools.SegmentRefAssert; +import org.skywalking.apm.agent.test.tools.SegmentStorage; +import org.skywalking.apm.agent.test.tools.SegmentStoragePoint; +import org.skywalking.apm.agent.test.tools.TracingSegmentRunner; +import org.skywalking.apm.plugin.grpc.v1.vo.GRPCDynamicFields; + +import static org.hamcrest.core.Is.is; +import static org.junit.Assert.assertThat; +import static org.powermock.api.mockito.PowerMockito.when; + +@RunWith(PowerMockRunner.class) +@PowerMockRunnerDelegate(TracingSegmentRunner.class) +public class ServerCallOnReadyInterceptorTest { + + @SegmentStoragePoint + private SegmentStorage segmentStorage; + + @Rule + public AgentServiceRule agentServiceRule = new AgentServiceRule(); + + @Mock + private EnhancedInstance enhancedInstance; + + private GRPCDynamicFields cachedObjects; + + @Mock + private MethodDescriptor.Marshaller requestMarshaller; + @Mock + private MethodDescriptor.Marshaller responseMarshaller; + + private ServerCallOnReadyInterceptor serverCallOnReadyInterceptor; + + private ServerCallOnCloseInterceptor serverCallOnCloseInterceptor; + + private ServerCallOnMessageInterceptor serverCallOnMessageInterceptor; + + @Before + public void setUp() { + cachedObjects = new GRPCDynamicFields(); + cachedObjects.setDescriptor(MethodDescriptor.create(MethodDescriptor.MethodType.SERVER_STREAMING, "org.skywalking.test.grpc.GreetService/SayHello", requestMarshaller, responseMarshaller)); + when(enhancedInstance.getSkyWalkingDynamicField()).thenReturn(cachedObjects); + + serverCallOnReadyInterceptor = new ServerCallOnReadyInterceptor(); + serverCallOnCloseInterceptor = new ServerCallOnCloseInterceptor(); + serverCallOnMessageInterceptor = new ServerCallOnMessageInterceptor(); + } + + @Test + public void testOnReadyWithoutContextCarrier() throws Throwable { + cachedObjects.setMetadata(new Metadata()); + serverCallOnReadyInterceptor.beforeMethod(enhancedInstance, null, null, null, null); + serverCallOnMessageInterceptor.beforeMethod(enhancedInstance, null, null, null, null); + serverCallOnMessageInterceptor.afterMethod(enhancedInstance, null, null, null, null); + serverCallOnCloseInterceptor.afterMethod(enhancedInstance, null, null, null, null); + + assertThat(segmentStorage.getTraceSegments().size(), is(1)); + TraceSegment segment = segmentStorage.getTraceSegments().get(0); + + assertThat(segment.getRefs() == null, is(true)); + + assertThat(SegmentHelper.getSpans(segment).size(), is(2)); + AbstractTracingSpan abstractTracingSpan = SegmentHelper.getSpans(segment).get(0); + assertThat(abstractTracingSpan.getOperationName(), is("org.skywalking.test.grpc.GreetService.sayHello/ResponseStreamObserver/OnNext")); + + abstractTracingSpan = SegmentHelper.getSpans(segment).get(1); + assertThat(abstractTracingSpan.getOperationName(), is("org.skywalking.test.grpc.GreetService.sayHello/StreamCall")); + assertThat(abstractTracingSpan.isEntry(), is(true)); + assertThat(SpanHelper.getTags(abstractTracingSpan).size(), is(1)); + assertThat(SpanHelper.getTags(abstractTracingSpan).get(0).getKey(), is("onNext.count")); + assertThat(SpanHelper.getTags(abstractTracingSpan).get(0).getValue(), is("1")); + } + + @Test + public void testOnReadyWithContextCarrier() throws Throwable { + Metadata metadata = new Metadata(); + metadata.put(Metadata.Key.of("sw3", Metadata.ASCII_STRING_MARSHALLER), "1.234.111|3|1|1|#192.168.1.100:50051|#/portal/|#/testEntrySpan|#AQA*#AQA*Et0We0tQNQA*"); + cachedObjects.setMetadata(metadata); + serverCallOnReadyInterceptor.beforeMethod(enhancedInstance, null, null, null, null); + serverCallOnMessageInterceptor.beforeMethod(enhancedInstance, null, null, null, null); + serverCallOnMessageInterceptor.afterMethod(enhancedInstance, null, null, null, null); + serverCallOnCloseInterceptor.afterMethod(enhancedInstance, null, null, null, null); + + assertThat(segmentStorage.getTraceSegments().size(), is(1)); + TraceSegment segment = segmentStorage.getTraceSegments().get(0); + + assertThat(segment.getRefs() != null, is(true)); + SegmentRefAssert.assertPeerHost(segment.getRefs().get(0), "192.168.1.100:50051"); + SegmentRefAssert.assertEntryApplicationInstanceId(segment.getRefs().get(0), 1); + SegmentRefAssert.assertSpanId(segment.getRefs().get(0), 3); + SegmentRefAssert.assertSegmentId(segment.getRefs().get(0), "1.234.111"); + + assertThat(SegmentHelper.getSpans(segment).size(), is(2)); + AbstractTracingSpan abstractTracingSpan = SegmentHelper.getSpans(segment).get(0); + assertThat(abstractTracingSpan.getOperationName(), is("org.skywalking.test.grpc.GreetService.sayHello/ResponseStreamObserver/OnNext")); + + abstractTracingSpan = SegmentHelper.getSpans(segment).get(1); + assertThat(abstractTracingSpan.getOperationName(), is("org.skywalking.test.grpc.GreetService.sayHello/StreamCall")); + assertThat(abstractTracingSpan.isEntry(), is(true)); + assertThat(SpanHelper.getTags(abstractTracingSpan).size(), is(1)); + assertThat(SpanHelper.getTags(abstractTracingSpan).get(0).getKey(), is("onNext.count")); + assertThat(SpanHelper.getTags(abstractTracingSpan).get(0).getValue(), is("1")); + } +} diff --git a/apm-sniffer/apm-sdk-plugin/jdbc-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/jdbc-plugin/pom.xml index f3bdd0c048a42215c647e538aebc24bd1284e560..c271e7fa74fa42fbc3efd24e2e45d66ed311849a 100755 --- a/apm-sniffer/apm-sdk-plugin/jdbc-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/jdbc-plugin/pom.xml @@ -60,6 +60,12 @@ [2.0.14,6.0.6] provided + + org.postgresql + postgresql + 42.0.0 + provided + diff --git a/apm-sniffer/apm-sdk-plugin/jdbc-plugin/src/main/java/org/skywalking/apm/plugin/jdbc/connectionurl/parser/PostgreSQLURLParser.java b/apm-sniffer/apm-sdk-plugin/jdbc-plugin/src/main/java/org/skywalking/apm/plugin/jdbc/connectionurl/parser/PostgreSQLURLParser.java new file mode 100644 index 0000000000000000000000000000000000000000..3ce8604232e614209504fac3566905d5b1fadb66 --- /dev/null +++ b/apm-sniffer/apm-sdk-plugin/jdbc-plugin/src/main/java/org/skywalking/apm/plugin/jdbc/connectionurl/parser/PostgreSQLURLParser.java @@ -0,0 +1,85 @@ +/* + * Copyright 2017, OpenSkywalking Organization All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * Project repository: https://github.com/OpenSkywalking/skywalking + */ + +package org.skywalking.apm.plugin.jdbc.connectionurl.parser; + +import org.skywalking.apm.network.trace.component.ComponentsDefine; +import org.skywalking.apm.plugin.jdbc.ConnectionInfo; + +/** + * {@link PostgreSQLURLParser} parse connection url of mysql. + *

+ * The {@link ConnectionInfo#host} be set the string between charset "//" and the first + * charset "/" after the charset "//", and {@link ConnectionInfo#databaseName} be set the + * string between the last index of "/" and the first charset "?". but one more thing, the + * {@link ConnectionInfo#hosts} be set if the host container multiple host. + * + * @author zhangxin + */ +public class PostgreSQLURLParser extends AbstractURLParser { + + private static final int DEFAULT_PORT = 5432; + private static final String DB_TYPE = "PostgreSQL"; + + public PostgreSQLURLParser(String url) { + super(url); + } + + @Override + protected int[] fetchDatabaseHostsIndexRange() { + int hostLabelStartIndex = url.indexOf("//"); + int hostLabelEndIndex = url.indexOf("/", hostLabelStartIndex + 2); + return new int[] {hostLabelStartIndex + 2, hostLabelEndIndex}; + } + + @Override + protected int[] fetchDatabaseNameIndexRange() { + int databaseStartTag = url.lastIndexOf("/"); + int databaseEndTag = url.indexOf("?", databaseStartTag); + if (databaseEndTag == -1) { + databaseEndTag = url.length(); + } + return new int[] {databaseStartTag + 1, databaseEndTag}; + } + + @Override + public ConnectionInfo parse() { + int[] hostRangeIndex = fetchDatabaseHostsIndexRange(); + String hosts = url.substring(hostRangeIndex[0], hostRangeIndex[1]); + String[] hostSegment = hosts.split(","); + if (hostSegment.length > 1) { + StringBuilder sb = new StringBuilder(); + for (String host : hostSegment) { + if (host.split(":").length == 1) { + sb.append(host + ":" + DEFAULT_PORT + ","); + } else { + sb.append(host + ","); + } + } + return new ConnectionInfo(ComponentsDefine.POSTGRESQL, DB_TYPE, sb.toString(), fetchDatabaseNameFromURL()); + } else { + String[] hostAndPort = hostSegment[0].split(":"); + if (hostAndPort.length != 1) { + return new ConnectionInfo(ComponentsDefine.POSTGRESQL, DB_TYPE, hostAndPort[0], Integer.valueOf(hostAndPort[1]), fetchDatabaseNameFromURL()); + } else { + return new ConnectionInfo(ComponentsDefine.POSTGRESQL, DB_TYPE, hostAndPort[0], DEFAULT_PORT, fetchDatabaseNameFromURL()); + } + } + } + +} diff --git a/apm-sniffer/apm-sdk-plugin/jdbc-plugin/src/main/java/org/skywalking/apm/plugin/jdbc/connectionurl/parser/URLParser.java b/apm-sniffer/apm-sdk-plugin/jdbc-plugin/src/main/java/org/skywalking/apm/plugin/jdbc/connectionurl/parser/URLParser.java index ff52f80ec575d4e82150e963e44ee8bd04a8194a..ffc5ac051028368aa2f5056652c4a9348c25e5bc 100644 --- a/apm-sniffer/apm-sdk-plugin/jdbc-plugin/src/main/java/org/skywalking/apm/plugin/jdbc/connectionurl/parser/URLParser.java +++ b/apm-sniffer/apm-sdk-plugin/jdbc-plugin/src/main/java/org/skywalking/apm/plugin/jdbc/connectionurl/parser/URLParser.java @@ -21,8 +21,8 @@ package org.skywalking.apm.plugin.jdbc.connectionurl.parser; import org.skywalking.apm.plugin.jdbc.ConnectionInfo; /** - * {@link URLParser#parser(String)} support parse the connection url, such as Mysql, Oracle, H2 Database. - * But there are some url cannot be parsed, such as Oracle connection url with multiple host. + * {@link URLParser#parser(String)} support parse the connection url, such as Mysql, Oracle, H2 Database. But there are + * some url cannot be parsed, such as Oracle connection url with multiple host. * * @author zhangxin */ @@ -31,6 +31,7 @@ public class URLParser { private static final String MYSQL_JDBC_URL_PREFIX = "jdbc:mysql"; private static final String ORACLE_JDBC_URL_PREFIX = "jdbc:oracle"; private static final String H2_JDBC_URL_PREFIX = "jdbc:h2"; + private static final String POSTGRESQL_JDBC_URL_PREFIX = "jdbc:postgresql"; public static ConnectionInfo parser(String url) { ConnectionURLParser parser = null; @@ -40,6 +41,8 @@ public class URLParser { parser = new OracleURLParser(url); } else if (url.startsWith(H2_JDBC_URL_PREFIX)) { parser = new H2URLParser(url); + } else if (url.startsWith(POSTGRESQL_JDBC_URL_PREFIX)) { + parser = new PostgreSQLURLParser(url); } return parser.parse(); } diff --git a/apm-sniffer/apm-sdk-plugin/jdbc-plugin/src/main/java/org/skywalking/apm/plugin/jdbc/define/PostgreSQLInstrumentation.java b/apm-sniffer/apm-sdk-plugin/jdbc-plugin/src/main/java/org/skywalking/apm/plugin/jdbc/define/PostgreSQLInstrumentation.java new file mode 100644 index 0000000000000000000000000000000000000000..99e249a64f416c008535662638da94af57de125c --- /dev/null +++ b/apm-sniffer/apm-sdk-plugin/jdbc-plugin/src/main/java/org/skywalking/apm/plugin/jdbc/define/PostgreSQLInstrumentation.java @@ -0,0 +1,35 @@ +/* + * Copyright 2017, OpenSkywalking Organization All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * Project repository: https://github.com/OpenSkywalking/skywalking + */ + +package org.skywalking.apm.plugin.jdbc.define; + +import org.skywalking.apm.agent.core.plugin.match.ClassMatch; + +import static org.skywalking.apm.agent.core.plugin.match.NameMatch.byName; + +/** + * {@link PostgreSQLInstrumentation} presents that skywalking intercepts {@link org.postgresql.Driver}. + * + * @author zhangxin + */ +public class PostgreSQLInstrumentation extends AbstractDatabaseInstrumentation { + @Override + protected ClassMatch enhanceClass() { + return byName("org.postgresql.Driver"); + } +} diff --git a/apm-sniffer/apm-sdk-plugin/jdbc-plugin/src/main/resources/skywalking-plugin.def b/apm-sniffer/apm-sdk-plugin/jdbc-plugin/src/main/resources/skywalking-plugin.def index c946b2924ce5670b02a3d72778a9edb636d57501..a28a6c03dab0588174ea364ba15413abdd791517 100644 --- a/apm-sniffer/apm-sdk-plugin/jdbc-plugin/src/main/resources/skywalking-plugin.def +++ b/apm-sniffer/apm-sdk-plugin/jdbc-plugin/src/main/resources/skywalking-plugin.def @@ -1,3 +1,4 @@ jdbc=org.skywalking.apm.plugin.jdbc.define.H2Instrumentation jdbc=org.skywalking.apm.plugin.jdbc.define.MysqlInstrumentation -jdbc=org.skywalking.apm.plugin.jdbc.define.OracleInstrumentation \ No newline at end of file +jdbc=org.skywalking.apm.plugin.jdbc.define.OracleInstrumentation +jdbc=org.skywalking.apm.plugin.jdbc.define.PostgreSQLInstrumentation diff --git a/apm-sniffer/apm-sdk-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/pom.xml index 84ccc21931d6400f536ad2faf3b564f42d9bfb8a..77c3cae9a13f83929fee93551911052b83a4b148 100644 --- a/apm-sniffer/apm-sdk-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/pom.xml @@ -46,6 +46,8 @@ jetty-plugin spymemcached-2.x-plugin sharding-jdbc-1.5.x-plugin + xmemcached-2.x-plugin + grpc-1.x-plugin pom diff --git a/apm-sniffer/apm-sdk-plugin/spymemcached-2.x-plugin/src/main/java/org/skywalking/apm/plugin/spymemcached/v2/MemcachedMethodInterceptor.java b/apm-sniffer/apm-sdk-plugin/spymemcached-2.x-plugin/src/main/java/org/skywalking/apm/plugin/spymemcached/v2/MemcachedMethodInterceptor.java index cac14c7770383d7123c695c44bcd590ef07d0a7d..3bdfd8802694ede54999b0dbcc42aba32de3f0d8 100644 --- a/apm-sniffer/apm-sdk-plugin/spymemcached-2.x-plugin/src/main/java/org/skywalking/apm/plugin/spymemcached/v2/MemcachedMethodInterceptor.java +++ b/apm-sniffer/apm-sdk-plugin/spymemcached-2.x-plugin/src/main/java/org/skywalking/apm/plugin/spymemcached/v2/MemcachedMethodInterceptor.java @@ -37,8 +37,8 @@ public class MemcachedMethodInterceptor implements InstanceMethodsAroundIntercep Class[] argumentsTypes, MethodInterceptResult result) throws Throwable { String peer = String.valueOf(objInst.getSkyWalkingDynamicField()); AbstractSpan span = ContextManager.createExitSpan(SPY_MEMCACHE + method.getName(), peer); - span.setComponent(ComponentsDefine.MEMCACHE); - Tags.DB_TYPE.set(span, ComponentsDefine.MEMCACHE.getName()); + span.setComponent(ComponentsDefine.MEMCACHED); + Tags.DB_TYPE.set(span, ComponentsDefine.MEMCACHED.getName()); SpanLayer.asDB(span); Tags.DB_STATEMENT.set(span, method.getName() + " " + allArguments[0]); } diff --git a/apm-sniffer/apm-sdk-plugin/spymemcached-2.x-plugin/src/test/java/org/skywalking/apm/plugin/spymemcached/v2/MemcachedMethodInterceptorTest.java b/apm-sniffer/apm-sdk-plugin/spymemcached-2.x-plugin/src/test/java/org/skywalking/apm/plugin/spymemcached/v2/MemcachedMethodInterceptorTest.java index 17f1885ea8da3698155538587ff0a99f0f62df49..d7cbdd8620d1a33b27c0765ba169b06344109a6a 100644 --- a/apm-sniffer/apm-sdk-plugin/spymemcached-2.x-plugin/src/test/java/org/skywalking/apm/plugin/spymemcached/v2/MemcachedMethodInterceptorTest.java +++ b/apm-sniffer/apm-sdk-plugin/spymemcached-2.x-plugin/src/test/java/org/skywalking/apm/plugin/spymemcached/v2/MemcachedMethodInterceptorTest.java @@ -112,7 +112,7 @@ public class MemcachedMethodInterceptorTest { assertThat(span.isExit(), is(true)); assertThat(SpanHelper.getComponentId(span), is(20)); List tags = SpanHelper.getTags(span); - assertThat(tags.get(0).getValue(), is("Memcache")); + assertThat(tags.get(0).getValue(), is("Memcached")); assertThat(tags.get(1).getValue(), is("set OperationKey")); assertThat(SpanHelper.getLayer(span), is(SpanLayer.DB)); } diff --git a/apm-sniffer/apm-sdk-plugin/xmemcached-2.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/xmemcached-2.x-plugin/pom.xml new file mode 100644 index 0000000000000000000000000000000000000000..69a4eea0756c60fd802aab4d9b19baea16173b84 --- /dev/null +++ b/apm-sniffer/apm-sdk-plugin/xmemcached-2.x-plugin/pom.xml @@ -0,0 +1,52 @@ + + + + 4.0.0 + + org.skywalking + apm-sdk-plugin + 3.2.3-2017 + + + apm-xmemcached-2.x-plugin + xmemcached-2.x-plugin + jar + + + UTF-8 + 2.0.0 + + + + + com.googlecode.xmemcached + xmemcached + ${xmemcached.version} + provided + + + org.apache.logging.log4j + log4j-core + 2.4.1 + test + + + \ No newline at end of file diff --git a/apm-sniffer/apm-sdk-plugin/xmemcached-2.x-plugin/src/main/java/org/skywalking/apm/plugin/xmemcached/v2/XMemcachedConstructorWithComplexArgInterceptor.java b/apm-sniffer/apm-sdk-plugin/xmemcached-2.x-plugin/src/main/java/org/skywalking/apm/plugin/xmemcached/v2/XMemcachedConstructorWithComplexArgInterceptor.java new file mode 100644 index 0000000000000000000000000000000000000000..491f6a9b0c48896be906d922eb1351e5d95d7cac --- /dev/null +++ b/apm-sniffer/apm-sdk-plugin/xmemcached-2.x-plugin/src/main/java/org/skywalking/apm/plugin/xmemcached/v2/XMemcachedConstructorWithComplexArgInterceptor.java @@ -0,0 +1,74 @@ +/* + * Copyright 2017, OpenSkywalking Organization All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * Project repository: https://github.com/OpenSkywalking/skywalking + */ + +package org.skywalking.apm.plugin.xmemcached.v2; + +import java.net.InetSocketAddress; +import java.util.Map; +import java.util.Map.Entry; + +import org.skywalking.apm.agent.core.plugin.interceptor.enhance.EnhancedInstance; +import org.skywalking.apm.agent.core.plugin.interceptor.enhance.InstanceConstructorInterceptor; + +/** + * {@link XMemcachedConstructorWithComplexArgInterceptor} intercept constructor of + * {@link XMemcachedClient(MemcachedSessionLocator locator,BufferAllocator allocator, Configuration conf, + * Map socketOptions, CommandFactory commandFactory, Transcoder transcoder, + * Map addressMap, List stateListeners, + * Map map, int poolSize, long connectTimeout, String name, boolean failureMode)} or + * {@link XMemcachedClient(MemcachedSessionLocator locator, BufferAllocator allocator, Configuration conf, + * Map socketOptions, CommandFactory commandFactory, Transcoder transcoder, + * Map addressMap, int[] weights, List stateListeners, + * Map infoMap, int poolSize, long connectTimeout, final String name, boolean failureMode)}. + * For parameter addressMap, every k-v is a master standby mode. + * + * @author IluckySi + */ +public class XMemcachedConstructorWithComplexArgInterceptor implements InstanceConstructorInterceptor { + + @Override + public void onConstruct(EnhancedInstance objInst, Object[] allArguments) { + StringBuilder memcachConnInfo = new StringBuilder(); + @SuppressWarnings("unchecked") + Map inetSocketAddressMap = (Map)allArguments[6]; + for (Entry entry : inetSocketAddressMap.entrySet()) { + memcachConnInfo = append(memcachConnInfo, entry.getKey()); + memcachConnInfo = append(memcachConnInfo, entry.getValue()); + } + Integer length = memcachConnInfo.length(); + if (length > 1) { + memcachConnInfo = new StringBuilder(memcachConnInfo.substring(0, length - 1)); + } + objInst.setSkyWalkingDynamicField(memcachConnInfo.toString()); + } + + /** + * Parse InetSocketAddress in specified format + * @param sb + * @param inetSocketAddress + * @return + */ + private StringBuilder append(StringBuilder sb, InetSocketAddress inetSocketAddress) { + if (inetSocketAddress != null) { + String host = inetSocketAddress.getAddress().getHostAddress(); + int port = inetSocketAddress.getPort(); + sb.append(host).append(":").append(port).append(";"); + } + return sb; + } +} diff --git a/apm-sniffer/apm-sdk-plugin/xmemcached-2.x-plugin/src/main/java/org/skywalking/apm/plugin/xmemcached/v2/XMemcachedConstructorWithHostPortArgInterceptor.java b/apm-sniffer/apm-sdk-plugin/xmemcached-2.x-plugin/src/main/java/org/skywalking/apm/plugin/xmemcached/v2/XMemcachedConstructorWithHostPortArgInterceptor.java new file mode 100644 index 0000000000000000000000000000000000000000..c2f63fe79a1f8d0f1fb5d2df437c00b296d127dc --- /dev/null +++ b/apm-sniffer/apm-sdk-plugin/xmemcached-2.x-plugin/src/main/java/org/skywalking/apm/plugin/xmemcached/v2/XMemcachedConstructorWithHostPortArgInterceptor.java @@ -0,0 +1,39 @@ +/* + * Copyright 2017, OpenSkywalking Organization All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * Project repository: https://github.com/OpenSkywalking/skywalking + */ + +package org.skywalking.apm.plugin.xmemcached.v2; + +import org.skywalking.apm.agent.core.plugin.interceptor.enhance.EnhancedInstance; +import org.skywalking.apm.agent.core.plugin.interceptor.enhance.InstanceConstructorInterceptor; + +/** + * {@link XMemcachedConstructorWithHostPortArgInterceptor} intercept constructor of + * {@link XMemcachedClient(final String host, final int port)} or + * {@link XMemcachedClient(final String host, final int port, int weight)}. + * + * @author IluckySi + */ +public class XMemcachedConstructorWithHostPortArgInterceptor implements InstanceConstructorInterceptor { + + @Override + public void onConstruct(EnhancedInstance objInst, Object[] allArguments) { + Object host = allArguments[0]; + Object port = allArguments[1]; + objInst.setSkyWalkingDynamicField(host + ":" + port); + } +} \ No newline at end of file diff --git a/apm-sniffer/apm-sdk-plugin/xmemcached-2.x-plugin/src/main/java/org/skywalking/apm/plugin/xmemcached/v2/XMemcachedConstructorWithInetSocketAddressArgInterceptor.java b/apm-sniffer/apm-sdk-plugin/xmemcached-2.x-plugin/src/main/java/org/skywalking/apm/plugin/xmemcached/v2/XMemcachedConstructorWithInetSocketAddressArgInterceptor.java new file mode 100644 index 0000000000000000000000000000000000000000..023fa944539897a0571fc6915c3cdd254697fab8 --- /dev/null +++ b/apm-sniffer/apm-sdk-plugin/xmemcached-2.x-plugin/src/main/java/org/skywalking/apm/plugin/xmemcached/v2/XMemcachedConstructorWithInetSocketAddressArgInterceptor.java @@ -0,0 +1,42 @@ +/* + * Copyright 2017, OpenSkywalking Organization All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * Project repository: https://github.com/OpenSkywalking/skywalking + */ + +package org.skywalking.apm.plugin.xmemcached.v2; + +import java.net.InetSocketAddress; + +import org.skywalking.apm.agent.core.plugin.interceptor.enhance.EnhancedInstance; +import org.skywalking.apm.agent.core.plugin.interceptor.enhance.InstanceConstructorInterceptor; + +/** + * {@link XMemcachedConstructorWithInetSocketAddressArgInterceptor} intercept constructor of + * {@link XMemcachedClient(final InetSocketAddress inetSocketAddress)} or + * {@link XMemcachedClient(final InetSocketAddress inetSocketAddress, int weight)}. + * + * @author IluckySi + */ +public class XMemcachedConstructorWithInetSocketAddressArgInterceptor implements InstanceConstructorInterceptor { + + @Override + public void onConstruct(EnhancedInstance objInst, Object[] allArguments) { + InetSocketAddress inetSocketAddress = (InetSocketAddress)allArguments[0]; + String host = inetSocketAddress.getAddress().getHostAddress(); + int port = inetSocketAddress.getPort(); + objInst.setSkyWalkingDynamicField(host + ":" + port); + } +} \ No newline at end of file diff --git a/apm-sniffer/apm-sdk-plugin/xmemcached-2.x-plugin/src/main/java/org/skywalking/apm/plugin/xmemcached/v2/XMemcachedConstructorWithInetSocketAddressListArgInterceptor.java b/apm-sniffer/apm-sdk-plugin/xmemcached-2.x-plugin/src/main/java/org/skywalking/apm/plugin/xmemcached/v2/XMemcachedConstructorWithInetSocketAddressListArgInterceptor.java new file mode 100644 index 0000000000000000000000000000000000000000..a38111b980345720c3fe737d1f5e345ccd5de99c --- /dev/null +++ b/apm-sniffer/apm-sdk-plugin/xmemcached-2.x-plugin/src/main/java/org/skywalking/apm/plugin/xmemcached/v2/XMemcachedConstructorWithInetSocketAddressListArgInterceptor.java @@ -0,0 +1,51 @@ +/* + * Copyright 2017, OpenSkywalking Organization All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * Project repository: https://github.com/OpenSkywalking/skywalking + */ + +package org.skywalking.apm.plugin.xmemcached.v2; + +import java.net.InetSocketAddress; +import java.util.List; + +import org.skywalking.apm.agent.core.plugin.interceptor.enhance.EnhancedInstance; +import org.skywalking.apm.agent.core.plugin.interceptor.enhance.InstanceConstructorInterceptor; + +/** + * {@link XMemcachedConstructorWithInetSocketAddressListArgInterceptor} intercept constructor of + * {@link XMemcachedClient(List addressList). + * + * @author IluckySi + */ +public class XMemcachedConstructorWithInetSocketAddressListArgInterceptor implements InstanceConstructorInterceptor { + + @Override + public void onConstruct(EnhancedInstance objInst, Object[] allArguments) { + StringBuilder memcachConnInfo = new StringBuilder(); + @SuppressWarnings("unchecked") + List inetSocketAddressList = (List)allArguments[0]; + for (InetSocketAddress inetSocketAddress : inetSocketAddressList) { + String host = inetSocketAddress.getAddress().getHostAddress(); + int port = inetSocketAddress.getPort(); + memcachConnInfo.append(host).append(":").append(port).append(";"); + } + int length = memcachConnInfo.length(); + if (length > 1) { + memcachConnInfo = new StringBuilder(memcachConnInfo.substring(0, length - 1)); + } + objInst.setSkyWalkingDynamicField(memcachConnInfo.toString()); + } +} \ No newline at end of file diff --git a/apm-sniffer/apm-sdk-plugin/xmemcached-2.x-plugin/src/main/java/org/skywalking/apm/plugin/xmemcached/v2/XMemcachedMethodInterceptor.java b/apm-sniffer/apm-sdk-plugin/xmemcached-2.x-plugin/src/main/java/org/skywalking/apm/plugin/xmemcached/v2/XMemcachedMethodInterceptor.java new file mode 100644 index 0000000000000000000000000000000000000000..77fb444406ae9ff354d4f399dcb979d4edf2c80e --- /dev/null +++ b/apm-sniffer/apm-sdk-plugin/xmemcached-2.x-plugin/src/main/java/org/skywalking/apm/plugin/xmemcached/v2/XMemcachedMethodInterceptor.java @@ -0,0 +1,64 @@ +/* + * Copyright 2017, OpenSkywalking Organization All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * Project repository: https://github.com/OpenSkywalking/skywalking + */ + +package org.skywalking.apm.plugin.xmemcached.v2; + +import java.lang.reflect.Method; + +import org.skywalking.apm.agent.core.context.ContextManager; +import org.skywalking.apm.agent.core.context.tag.Tags; +import org.skywalking.apm.agent.core.context.trace.AbstractSpan; +import org.skywalking.apm.agent.core.context.trace.SpanLayer; +import org.skywalking.apm.agent.core.plugin.interceptor.enhance.EnhancedInstance; +import org.skywalking.apm.agent.core.plugin.interceptor.enhance.InstanceMethodsAroundInterceptor; +import org.skywalking.apm.agent.core.plugin.interceptor.enhance.MethodInterceptResult; +import org.skywalking.apm.network.trace.component.ComponentsDefine; + +/** + * {@link XMemcachedMethodInterceptor} intercept the operation method, + * record the memcached host, operation name and the key of the operation. + * + * @author IluckySi + */ +public class XMemcachedMethodInterceptor implements InstanceMethodsAroundInterceptor { + + private static final String XMEMCACHED = "XMemcached/"; + + @Override public void beforeMethod(EnhancedInstance objInst, Method method, Object[] allArguments, + Class[] argumentsTypes, MethodInterceptResult result) throws Throwable { + String peer = String.valueOf(objInst.getSkyWalkingDynamicField()); + AbstractSpan span = ContextManager.createExitSpan(XMEMCACHED + method.getName(), peer); + span.setComponent(ComponentsDefine.MEMCACHED); + Tags.DB_TYPE.set(span, ComponentsDefine.MEMCACHED.getName()); + SpanLayer.asDB(span); + Tags.DB_STATEMENT.set(span, method.getName() + " " + allArguments[0]); + } + + @Override public Object afterMethod(EnhancedInstance objInst, Method method, Object[] allArguments, + Class[] argumentsTypes, Object ret) throws Throwable { + ContextManager.stopSpan(); + return ret; + } + + @Override public void handleMethodException(EnhancedInstance objInst, Method method, Object[] allArguments, + Class[] argumentsTypes, Throwable t) { + AbstractSpan span = ContextManager.activeSpan(); + span.errorOccurred(); + span.log(t); + } +} diff --git a/apm-sniffer/apm-sdk-plugin/xmemcached-2.x-plugin/src/main/java/org/skywalking/apm/plugin/xmemcached/v2/define/XMemcachedInstrumentation.java b/apm-sniffer/apm-sdk-plugin/xmemcached-2.x-plugin/src/main/java/org/skywalking/apm/plugin/xmemcached/v2/define/XMemcachedInstrumentation.java new file mode 100644 index 0000000000000000000000000000000000000000..8a6fb3ea5d7de3b90fc6c35a09723e31dec5ad1e --- /dev/null +++ b/apm-sniffer/apm-sdk-plugin/xmemcached-2.x-plugin/src/main/java/org/skywalking/apm/plugin/xmemcached/v2/define/XMemcachedInstrumentation.java @@ -0,0 +1,135 @@ +/* + * Copyright 2017, OpenSkywalking Organization All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * Project repository: https://github.com/OpenSkywalking/skywalking + */ + +package org.skywalking.apm.plugin.xmemcached.v2.define; + +import java.net.InetSocketAddress; +import java.util.List; +import java.util.Map; + +import net.bytebuddy.description.method.MethodDescription; +import net.bytebuddy.matcher.ElementMatcher; +import org.skywalking.apm.agent.core.plugin.interceptor.ConstructorInterceptPoint; +import org.skywalking.apm.agent.core.plugin.interceptor.InstanceMethodsInterceptPoint; +import org.skywalking.apm.agent.core.plugin.interceptor.enhance.ClassInstanceMethodsEnhancePluginDefine; +import org.skywalking.apm.agent.core.plugin.match.ClassMatch; + +import static net.bytebuddy.matcher.ElementMatchers.named; +import static net.bytebuddy.matcher.ElementMatchers.takesArgument; +import static net.bytebuddy.matcher.ElementMatchers.takesArguments; +import static org.skywalking.apm.agent.core.plugin.match.NameMatch.byName; + +/** + * {@link MemcachedInstrumentation} presents that skywalking intercept all constructors and methods of + * {@link net.rubyeye.xmemcached.XMemcachedClient}. + * {@link XMemcachedConstructorWithHostPortArgInterceptor} intercepts the constructor with + * ip and port arguments. + * {@link XMemcachedConstructorWithInetSocketAddressArgInterceptor} intercepts the constructor with + * argument {@link java.net.InetSocketAddress}. + * {@link XMemcachedConstructorWithInetSocketAddressListArgInterceptor} intercepts the constructor with + * argument {@link java.net.InetSocketAddress}. + * {@link XMemcachedConstructorWithComplexArgInterceptor} intercepts the constructor with complex arguments. + * + * @author IluckySi + */ +public class XMemcachedInstrumentation extends ClassInstanceMethodsEnhancePluginDefine { + + private static final String ENHANCE_CLASS = "net.rubyeye.xmemcached.XMemcachedClient"; + private static final String CONSTRUCTOR_WITH_HOSTPORT_ARG_INTERCEPT_CLASS = "org.skywalking.apm.plugin.xmemcached.v2.XMemcachedConstructorWithHostPortArgInterceptor"; + private static final String CONSTRUCTOR_WITH_INETSOCKETADDRESS_ARG_INTERCEPT_CLASS = "org.skywalking.apm.plugin.xmemcached.v2.XMemcachedConstructorWithInetSocketAddressArgInterceptor"; + private static final String CONSTRUCTOR_WITH_INETSOCKETADDRESS_LIST_ARG_INTERCEPT_CLASS = "org.skywalking.apm.plugin.xmemcached.v2.XMemcachedConstructorWithInetSocketAddressListArgInterceptor"; + private static final String CONSTRUCTOR_WITH_COMPLEX_ARG_INTERCEPT_CLASS = "org.skywalking.apm.plugin.xmemcached.v2.XMemcachedConstructorWithComplexArgInterceptor"; + private static final String METHOD_INTERCEPT_CLASS = "org.skywalking.apm.plugin.xmemcached.v2.XMemcachedMethodInterceptor"; + + @Override + public ClassMatch enhanceClass() { + return byName(ENHANCE_CLASS); + } + @Override + protected ConstructorInterceptPoint[] getConstructorsInterceptPoints() { + return new ConstructorInterceptPoint[] { + new ConstructorInterceptPoint() { + @Override + public ElementMatcher getConstructorMatcher() { + return takesArguments(String.class, int.class); + } + + @Override + public String getConstructorInterceptor() { + return CONSTRUCTOR_WITH_HOSTPORT_ARG_INTERCEPT_CLASS; + } + }, + new ConstructorInterceptPoint() { + @Override + public ElementMatcher getConstructorMatcher() { + return takesArgument(0, InetSocketAddress.class); + } + + @Override + public String getConstructorInterceptor() { + return CONSTRUCTOR_WITH_INETSOCKETADDRESS_ARG_INTERCEPT_CLASS; + } + }, + new ConstructorInterceptPoint() { + @Override + public ElementMatcher getConstructorMatcher() { + return takesArgument(0, List.class); + } + + @Override + public String getConstructorInterceptor() { + return CONSTRUCTOR_WITH_INETSOCKETADDRESS_LIST_ARG_INTERCEPT_CLASS; + } + }, + new ConstructorInterceptPoint() { + @Override + public ElementMatcher getConstructorMatcher() { + return takesArgument(6, Map.class); + } + + @Override + public String getConstructorInterceptor() { + return CONSTRUCTOR_WITH_COMPLEX_ARG_INTERCEPT_CLASS; + } + } + }; + } + + @Override + protected InstanceMethodsInterceptPoint[] getInstanceMethodsInterceptPoints() { + return new InstanceMethodsInterceptPoint[] { + new InstanceMethodsInterceptPoint() { + @Override + public ElementMatcher getMethodsMatcher() { + return named("get").or(named("set")) .or(named("add")).or(named("replace")).or(named("gets")) + .or(named("append")) .or(named("prepend")).or(named("cas")).or(named("delete")).or(named("touch")). + or(named("getAndTouch")).or(named("incr")) .or(named("decr")); + } + + @Override + public String getMethodsInterceptor() { + return METHOD_INTERCEPT_CLASS; + } + + @Override public boolean isOverrideArgs() { + return false; + } + } + }; + } +} diff --git a/apm-sniffer/apm-sdk-plugin/xmemcached-2.x-plugin/src/main/resources/skywalking-plugin.def b/apm-sniffer/apm-sdk-plugin/xmemcached-2.x-plugin/src/main/resources/skywalking-plugin.def new file mode 100644 index 0000000000000000000000000000000000000000..c04b8817ba5a3fd072f92ba3449b81e5e51cb81e --- /dev/null +++ b/apm-sniffer/apm-sdk-plugin/xmemcached-2.x-plugin/src/main/resources/skywalking-plugin.def @@ -0,0 +1 @@ +memcache-2.x=org.skywalking.apm.plugin.xmemcached.v2.define.XMemcachedInstrumentation \ No newline at end of file diff --git a/apm-sniffer/apm-sdk-plugin/xmemcached-2.x-plugin/src/test/java/org/skywalking/apm/plugin/xmemcached/v2/XMemcachedConstructorWithComplexArgInterceptorTest.java b/apm-sniffer/apm-sdk-plugin/xmemcached-2.x-plugin/src/test/java/org/skywalking/apm/plugin/xmemcached/v2/XMemcachedConstructorWithComplexArgInterceptorTest.java new file mode 100644 index 0000000000000000000000000000000000000000..6615eee2f742aef5823c9fe7a84a92cbd7ac7cb5 --- /dev/null +++ b/apm-sniffer/apm-sdk-plugin/xmemcached-2.x-plugin/src/test/java/org/skywalking/apm/plugin/xmemcached/v2/XMemcachedConstructorWithComplexArgInterceptorTest.java @@ -0,0 +1,56 @@ +/* + * Copyright 2017, OpenSkywalking Organization All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * Project repository: https://github.com/OpenSkywalking/skywalking + */ + +package org.skywalking.apm.plugin.xmemcached.v2; + +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; + +import java.net.InetSocketAddress; +import java.util.HashMap; +import java.util.Map; + +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mock; +import org.mockito.runners.MockitoJUnitRunner; +import org.skywalking.apm.agent.core.plugin.interceptor.enhance.EnhancedInstance; + +@RunWith(MockitoJUnitRunner.class) +public class XMemcachedConstructorWithComplexArgInterceptorTest { + + private XMemcachedConstructorWithComplexArgInterceptor interceptor; + + @Mock + private EnhancedInstance enhancedInstance; + + @Before + public void setUp() throws Exception { + interceptor = new XMemcachedConstructorWithComplexArgInterceptor(); + } + + @Test + public void onConstructWithComplex() { + Map inetSocketAddressMap = new HashMap(); + inetSocketAddressMap.put(new InetSocketAddress("127.0.0.1", 11211), new InetSocketAddress("127.0.0.2", 11211)); + interceptor.onConstruct(enhancedInstance, new Object[]{null, null, null, null, null, null, inetSocketAddressMap}); + + verify(enhancedInstance, times(1)).setSkyWalkingDynamicField("127.0.0.1:11211;127.0.0.2:11211"); + } +} \ No newline at end of file diff --git a/apm-sniffer/apm-sdk-plugin/xmemcached-2.x-plugin/src/test/java/org/skywalking/apm/plugin/xmemcached/v2/XMemcachedConstructorWithHostPortArgInterceptorTest.java b/apm-sniffer/apm-sdk-plugin/xmemcached-2.x-plugin/src/test/java/org/skywalking/apm/plugin/xmemcached/v2/XMemcachedConstructorWithHostPortArgInterceptorTest.java new file mode 100644 index 0000000000000000000000000000000000000000..ae8101e19a4efb5f188e698be4bd7f7e8aff9985 --- /dev/null +++ b/apm-sniffer/apm-sdk-plugin/xmemcached-2.x-plugin/src/test/java/org/skywalking/apm/plugin/xmemcached/v2/XMemcachedConstructorWithHostPortArgInterceptorTest.java @@ -0,0 +1,50 @@ +/* + * Copyright 2017, OpenSkywalking Organization All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * Project repository: https://github.com/OpenSkywalking/skywalking + */ + +package org.skywalking.apm.plugin.xmemcached.v2; + +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; + +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mock; +import org.mockito.runners.MockitoJUnitRunner; +import org.skywalking.apm.agent.core.plugin.interceptor.enhance.EnhancedInstance; + +@RunWith(MockitoJUnitRunner.class) +public class XMemcachedConstructorWithHostPortArgInterceptorTest { + + private XMemcachedConstructorWithHostPortArgInterceptor interceptor; + + @Mock + private EnhancedInstance enhancedInstance; + + @Before + public void setUp() throws Exception { + interceptor = new XMemcachedConstructorWithHostPortArgInterceptor(); + } + + @Test + public void onConstructWithHostPort() { + interceptor.onConstruct(enhancedInstance, new Object[]{"127.0.0.1", 11211}); + + verify(enhancedInstance, times(1)).setSkyWalkingDynamicField("127.0.0.1:11211"); + } +} \ No newline at end of file diff --git a/apm-sniffer/apm-sdk-plugin/xmemcached-2.x-plugin/src/test/java/org/skywalking/apm/plugin/xmemcached/v2/XMemcachedConstructorWithInetSocketAddressArgInterceptorTest.java b/apm-sniffer/apm-sdk-plugin/xmemcached-2.x-plugin/src/test/java/org/skywalking/apm/plugin/xmemcached/v2/XMemcachedConstructorWithInetSocketAddressArgInterceptorTest.java new file mode 100644 index 0000000000000000000000000000000000000000..f83178ba9261f5acb58b5c52125743d3df941969 --- /dev/null +++ b/apm-sniffer/apm-sdk-plugin/xmemcached-2.x-plugin/src/test/java/org/skywalking/apm/plugin/xmemcached/v2/XMemcachedConstructorWithInetSocketAddressArgInterceptorTest.java @@ -0,0 +1,52 @@ +/* + * Copyright 2017, OpenSkywalking Organization All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * Project repository: https://github.com/OpenSkywalking/skywalking + */ + +package org.skywalking.apm.plugin.xmemcached.v2; + +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; + +import java.net.InetSocketAddress; + +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mock; +import org.mockito.runners.MockitoJUnitRunner; +import org.skywalking.apm.agent.core.plugin.interceptor.enhance.EnhancedInstance; + +@RunWith(MockitoJUnitRunner.class) +public class XMemcachedConstructorWithInetSocketAddressArgInterceptorTest { + + private XMemcachedConstructorWithInetSocketAddressArgInterceptor interceptor; + + @Mock + private EnhancedInstance enhancedInstance; + + @Before + public void setUp() throws Exception { + interceptor = new XMemcachedConstructorWithInetSocketAddressArgInterceptor(); + } + + @Test + public void onConstructWithInetSocketAddress() { + interceptor.onConstruct(enhancedInstance, new Object[]{new InetSocketAddress("127.0.0.1", 11211)}); + + verify(enhancedInstance, times(1)).setSkyWalkingDynamicField("127.0.0.1:11211"); + } +} \ No newline at end of file diff --git a/apm-sniffer/apm-sdk-plugin/xmemcached-2.x-plugin/src/test/java/org/skywalking/apm/plugin/xmemcached/v2/XMemcachedConstructorWithInetSocketAddressListArgInterceptorTest.java b/apm-sniffer/apm-sdk-plugin/xmemcached-2.x-plugin/src/test/java/org/skywalking/apm/plugin/xmemcached/v2/XMemcachedConstructorWithInetSocketAddressListArgInterceptorTest.java new file mode 100644 index 0000000000000000000000000000000000000000..0e4a96ca67428982093b4c302269a71b932df36c --- /dev/null +++ b/apm-sniffer/apm-sdk-plugin/xmemcached-2.x-plugin/src/test/java/org/skywalking/apm/plugin/xmemcached/v2/XMemcachedConstructorWithInetSocketAddressListArgInterceptorTest.java @@ -0,0 +1,57 @@ +/* + * Copyright 2017, OpenSkywalking Organization All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * Project repository: https://github.com/OpenSkywalking/skywalking + */ + +package org.skywalking.apm.plugin.xmemcached.v2; + +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; + +import java.net.InetSocketAddress; +import java.util.ArrayList; +import java.util.List; + +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mock; +import org.mockito.runners.MockitoJUnitRunner; +import org.skywalking.apm.agent.core.plugin.interceptor.enhance.EnhancedInstance; + +@RunWith(MockitoJUnitRunner.class) +public class XMemcachedConstructorWithInetSocketAddressListArgInterceptorTest { + + private XMemcachedConstructorWithInetSocketAddressListArgInterceptor interceptor; + + @Mock + private EnhancedInstance enhancedInstance; + + @Before + public void setUp() throws Exception { + interceptor = new XMemcachedConstructorWithInetSocketAddressListArgInterceptor(); + } + + @Test + public void onConstructWithInetSocketAddressList() { + List inetSocketAddressList = new ArrayList(); + inetSocketAddressList.add(new InetSocketAddress("127.0.0.1", 11211)); + inetSocketAddressList.add(new InetSocketAddress("127.0.0.2", 11211)); + interceptor.onConstruct(enhancedInstance, new Object[]{inetSocketAddressList}); + + verify(enhancedInstance, times(1)).setSkyWalkingDynamicField("127.0.0.1:11211;127.0.0.2:11211"); + } +} \ No newline at end of file diff --git a/apm-sniffer/apm-sdk-plugin/xmemcached-2.x-plugin/src/test/java/org/skywalking/apm/plugin/xmemcached/v2/XMemcachedMethodInterceptorTest.java b/apm-sniffer/apm-sdk-plugin/xmemcached-2.x-plugin/src/test/java/org/skywalking/apm/plugin/xmemcached/v2/XMemcachedMethodInterceptorTest.java new file mode 100644 index 0000000000000000000000000000000000000000..96f66d25ee62f9595926b5d2e3ffd185103b7c12 --- /dev/null +++ b/apm-sniffer/apm-sdk-plugin/xmemcached-2.x-plugin/src/test/java/org/skywalking/apm/plugin/xmemcached/v2/XMemcachedMethodInterceptorTest.java @@ -0,0 +1,131 @@ +/* + * Copyright 2017, OpenSkywalking Organization All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * Project repository: https://github.com/OpenSkywalking/skywalking + */ + +package org.skywalking.apm.plugin.xmemcached.v2; + +import static junit.framework.TestCase.assertNotNull; +import static org.hamcrest.CoreMatchers.is; +import static org.hamcrest.MatcherAssert.assertThat; +import static org.mockito.Mockito.when; + +import java.lang.reflect.Method; +import java.util.List; + +import org.hamcrest.CoreMatchers; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Rule; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mock; +import org.powermock.modules.junit4.PowerMockRunner; +import org.powermock.modules.junit4.PowerMockRunnerDelegate; +import org.skywalking.apm.agent.core.context.trace.AbstractTracingSpan; +import org.skywalking.apm.agent.core.context.trace.LogDataEntity; +import org.skywalking.apm.agent.core.context.trace.SpanLayer; +import org.skywalking.apm.agent.core.context.trace.TraceSegment; +import org.skywalking.apm.agent.core.context.util.KeyValuePair; +import org.skywalking.apm.agent.core.plugin.interceptor.enhance.EnhancedInstance; +import org.skywalking.apm.agent.test.helper.SegmentHelper; +import org.skywalking.apm.agent.test.helper.SpanHelper; +import org.skywalking.apm.agent.test.tools.AgentServiceRule; +import org.skywalking.apm.agent.test.tools.SegmentStorage; +import org.skywalking.apm.agent.test.tools.SegmentStoragePoint; +import org.skywalking.apm.agent.test.tools.TracingSegmentRunner; + +import net.rubyeye.xmemcached.XMemcachedClient; + +@RunWith(PowerMockRunner.class) +@PowerMockRunnerDelegate(TracingSegmentRunner.class) +public class XMemcachedMethodInterceptorTest { + + @SegmentStoragePoint + private SegmentStorage segmentStorage; + + @Rule + public AgentServiceRule serviceRule = new AgentServiceRule(); + + @Mock + private EnhancedInstance enhancedInstance; + private XMemcachedMethodInterceptor interceptor; + + private Object[] allArgument; + private Class[] argumentType; + + @Before + public void setUp() throws Exception { + allArgument = new Object[] {"OperationKey", "OperationValue"}; + argumentType = new Class[] {String.class, String.class}; + + interceptor = new XMemcachedMethodInterceptor(); + when(enhancedInstance.getSkyWalkingDynamicField()).thenReturn("127.0.0.1:11211"); + } + + @Test + public void testIntercept() throws Throwable { + interceptor.beforeMethod(enhancedInstance, getMockSetMethod(), allArgument, argumentType, null); + interceptor.afterMethod(enhancedInstance, getMockGetMethod(), allArgument, argumentType, null); + + TraceSegment traceSegment = segmentStorage.getTraceSegments().get(0); + List spans = SegmentHelper.getSpans(traceSegment); + assertThat(spans.size(), is(1)); + assertMemcacheSpan(spans.get(0)); + } + + @Test + public void testInterceptWithException() throws Throwable { + interceptor.beforeMethod(enhancedInstance, getMockSetMethod(), allArgument, argumentType, null); + interceptor.handleMethodException(enhancedInstance, getMockSetMethod(), allArgument, argumentType, new RuntimeException()); + interceptor.afterMethod(enhancedInstance, getMockSetMethod(), allArgument, argumentType, null); + + TraceSegment traceSegment = segmentStorage.getTraceSegments().get(0); + List spans = SegmentHelper.getSpans(traceSegment); + assertThat(spans.size(), is(1)); + assertMemcacheSpan(spans.get(0)); + + assertLogData(SpanHelper.getLogs(spans.get(0))); + } + + private void assertLogData(List logDataEntities) { + assertThat(logDataEntities.size(), is(1)); + LogDataEntity logData = logDataEntities.get(0); + Assert.assertThat(logData.getLogs().size(), is(4)); + Assert.assertThat(logData.getLogs().get(0).getValue(), CoreMatchers.is("error")); + Assert.assertThat(logData.getLogs().get(1).getValue(), CoreMatchers.is(RuntimeException.class.getName())); + Assert.assertNull(logData.getLogs().get(2).getValue()); + assertNotNull(logData.getLogs().get(3).getValue()); + } + + private void assertMemcacheSpan(AbstractTracingSpan span) { + assertThat(span.getOperationName(), is("XMemcached/set")); + assertThat(span.isExit(), is(true)); + assertThat(SpanHelper.getComponentId(span), is(20)); + List tags = SpanHelper.getTags(span); + assertThat(tags.get(0).getValue(), is("Memcached")); + assertThat(tags.get(1).getValue(), is("set OperationKey")); + assertThat(SpanHelper.getLayer(span), is(SpanLayer.DB)); + } + + private Method getMockSetMethod() throws Exception { + return XMemcachedClient.class.getMethod("set", String.class, int.class, Object.class); + } + + private Method getMockGetMethod() throws Exception { + return XMemcachedClient.class.getMethod("get", String.class); + } +} \ No newline at end of file