From a40af8554e76b653b7a3be1d807f8a3ecf2cf5cb Mon Sep 17 00:00:00 2001 From: HyunGil Jeong Date: Wed, 14 Oct 2015 11:59:27 +0900 Subject: [PATCH] #1069 Add backend support for storing and retrieving tps --- .../dao/hbase/HbaseAgentStatDao.java | 5 + .../pinpoint/common/hbase/HBaseTables.java | 1 + .../common/bo/AgentStatCpuLoadBo.java | 2 +- .../common/bo/AgentStatMemoryGcBo.java | 2 +- .../collector/AgentStatDataCollector.java | 10 +- .../web/dao/hbase/HbaseAgentStatDao.java | 1 + .../pinpoint/web/mapper/AgentStatMapper.java | 110 +++++++-- .../navercorp/pinpoint/web/vo/AgentStat.java | 129 +++++++++-- .../web/vo/linechart/DownSampler.java | 5 +- .../web/vo/linechart/DownSamplers.java | 52 ++++- .../SampledTimeSeriesIntegerChartBuilder.java | 52 +++++ .../agentstat/AgentStatChartGroup.java | 76 +++--- .../web/alarm/checker/GcCountCheckerTest.java | 31 +-- .../checker/HeapUsageRateCheckerTest.java | 21 +- .../checker/JvmCpuUsageRateCheckerTest.java | 21 +- .../web/mapper/AgentStatMapperTest.java | 219 ++++++++++++++++++ 16 files changed, 596 insertions(+), 141 deletions(-) create mode 100644 web/src/main/java/com/navercorp/pinpoint/web/vo/linechart/SampledTimeSeriesIntegerChartBuilder.java create mode 100644 web/src/test/java/com/navercorp/pinpoint/web/mapper/AgentStatMapperTest.java diff --git a/collector/src/main/java/com/navercorp/pinpoint/collector/dao/hbase/HbaseAgentStatDao.java b/collector/src/main/java/com/navercorp/pinpoint/collector/dao/hbase/HbaseAgentStatDao.java index c645a351a..9816c26a3 100644 --- a/collector/src/main/java/com/navercorp/pinpoint/collector/dao/hbase/HbaseAgentStatDao.java +++ b/collector/src/main/java/com/navercorp/pinpoint/collector/dao/hbase/HbaseAgentStatDao.java @@ -85,6 +85,11 @@ public class HbaseAgentStatDao implements AgentStatDao { put.addColumn(AGENT_STAT_CF_STATISTICS, AGENT_STAT_CF_STATISTICS_COL_JVM_CPU, Bytes.toBytes(cpuLoad.getJvmCpuLoad())); put.addColumn(AGENT_STAT_CF_STATISTICS, AGENT_STAT_CF_STATISTICS_COL_SYS_CPU, Bytes.toBytes(cpuLoad.getSystemCpuLoad())); } + // Transaction + if (agentStat.isSetTransaction()) { + TTransaction transaction = agentStat.getTransaction(); + put.addColumn(AGENT_STAT_CF_STATISTICS, AGENT_STAT_CF_STATISTICS_COL_TPS, Bytes.toBytes(transaction.getTps())); + } return put; } diff --git a/commons-hbase/src/main/java/com/navercorp/pinpoint/common/hbase/HBaseTables.java b/commons-hbase/src/main/java/com/navercorp/pinpoint/common/hbase/HBaseTables.java index 48858f784..b662dd73d 100644 --- a/commons-hbase/src/main/java/com/navercorp/pinpoint/common/hbase/HBaseTables.java +++ b/commons-hbase/src/main/java/com/navercorp/pinpoint/common/hbase/HBaseTables.java @@ -49,6 +49,7 @@ public final class HBaseTables { public static final byte[] AGENT_STAT_CF_STATISTICS_COL_NON_HEAP_MAX = Bytes.toBytes("nHpM"); // qualifier for non-heap max public static final byte[] AGENT_STAT_CF_STATISTICS_COL_JVM_CPU = Bytes.toBytes("jvmCpu"); // qualifier for JVM CPU usage public static final byte[] AGENT_STAT_CF_STATISTICS_COL_SYS_CPU = Bytes.toBytes("sysCpu"); // qualifier for system CPU usage + public static final byte[] AGENT_STAT_CF_STATISTICS_COL_TPS = Bytes.toBytes("tps"); // qualifier for tps public static final int AGENT_STAT_ROW_DISTRIBUTE_SIZE = 1; // agent statistics hash size public static final String TRACES = "Traces"; diff --git a/commons/src/main/java/com/navercorp/pinpoint/common/bo/AgentStatCpuLoadBo.java b/commons/src/main/java/com/navercorp/pinpoint/common/bo/AgentStatCpuLoadBo.java index 8e72cb8cc..24fd8e7a6 100644 --- a/commons/src/main/java/com/navercorp/pinpoint/common/bo/AgentStatCpuLoadBo.java +++ b/commons/src/main/java/com/navercorp/pinpoint/common/bo/AgentStatCpuLoadBo.java @@ -23,7 +23,7 @@ import com.navercorp.pinpoint.common.buffer.FixedBuffer; /** * @author hyungil.jeong */ -//FIXME (2015.10) Legacy column for storing serialzied Bos separately. +// FIXME (2015.10) Legacy column for storing serialzied Bos separately. @Deprecated public class AgentStatCpuLoadBo { diff --git a/commons/src/main/java/com/navercorp/pinpoint/common/bo/AgentStatMemoryGcBo.java b/commons/src/main/java/com/navercorp/pinpoint/common/bo/AgentStatMemoryGcBo.java index 10815cffb..e85a55628 100644 --- a/commons/src/main/java/com/navercorp/pinpoint/common/bo/AgentStatMemoryGcBo.java +++ b/commons/src/main/java/com/navercorp/pinpoint/common/bo/AgentStatMemoryGcBo.java @@ -23,7 +23,7 @@ import com.navercorp.pinpoint.common.buffer.FixedBuffer; /** * @author hyungil.jeong */ -//FIXME (2015.10) Legacy column for storing serialzied Bos separately. +// FIXME (2015.10) Legacy column for storing serialzied Bos separately. @Deprecated public class AgentStatMemoryGcBo { diff --git a/web/src/main/java/com/navercorp/pinpoint/web/alarm/collector/AgentStatDataCollector.java b/web/src/main/java/com/navercorp/pinpoint/web/alarm/collector/AgentStatDataCollector.java index 0b3ab3ada..6f057e0ca 100644 --- a/web/src/main/java/com/navercorp/pinpoint/web/alarm/collector/AgentStatDataCollector.java +++ b/web/src/main/java/com/navercorp/pinpoint/web/alarm/collector/AgentStatDataCollector.java @@ -70,10 +70,10 @@ public class AgentStatDataCollector extends DataCollector { long jvmCpuUsaged = 0; for (AgentStat agentStat : scanAgentStatList) { - totalHeapSize += agentStat.getMemoryGc().getJvmMemoryHeapMax(); - usedHeapSize += agentStat.getMemoryGc().getJvmMemoryHeapUsed(); + totalHeapSize += agentStat.getHeapMax(); + usedHeapSize += agentStat.getHeapUsed(); - jvmCpuUsaged += agentStat.getCpuLoad().getJvmCpuLoad() * 100; + jvmCpuUsaged += agentStat.getJvmCpuUsage() * 100; } if(listSize > 0) { @@ -83,8 +83,8 @@ public class AgentStatDataCollector extends DataCollector { percent = calculatePercent(jvmCpuUsaged, 100*scanAgentStatList.size()); agentJvmCpuUsageRate.put(agentId, percent); - long accruedLastGCcount = scanAgentStatList.get(0).getMemoryGc().getJvmGcOldCount(); - long accruedFirstGCcount= scanAgentStatList.get(listSize - 1).getMemoryGc().getJvmGcOldCount(); + long accruedLastGCcount = scanAgentStatList.get(0).getGcOldCount(); + long accruedFirstGCcount= scanAgentStatList.get(listSize - 1).getGcOldCount(); agentGcCount.put(agentId, accruedLastGCcount - accruedFirstGCcount); } diff --git a/web/src/main/java/com/navercorp/pinpoint/web/dao/hbase/HbaseAgentStatDao.java b/web/src/main/java/com/navercorp/pinpoint/web/dao/hbase/HbaseAgentStatDao.java index 2caaed459..33c4a5b8a 100644 --- a/web/src/main/java/com/navercorp/pinpoint/web/dao/hbase/HbaseAgentStatDao.java +++ b/web/src/main/java/com/navercorp/pinpoint/web/dao/hbase/HbaseAgentStatDao.java @@ -80,6 +80,7 @@ public class HbaseAgentStatDao implements AgentStatDao { Scan scan = createScan(agentId, range); + scan.addFamily(HBaseTables.AGENT_STAT_CF_STATISTICS); List> intermediate = hbaseOperations2.find(HBaseTables.AGENT_STAT, scan, rowKeyDistributor, agentStatMapper); diff --git a/web/src/main/java/com/navercorp/pinpoint/web/mapper/AgentStatMapper.java b/web/src/main/java/com/navercorp/pinpoint/web/mapper/AgentStatMapper.java index 633ec2480..d104a2e9e 100644 --- a/web/src/main/java/com/navercorp/pinpoint/web/mapper/AgentStatMapper.java +++ b/web/src/main/java/com/navercorp/pinpoint/web/mapper/AgentStatMapper.java @@ -22,57 +22,130 @@ import java.util.ArrayList; import java.util.Collections; import java.util.List; import java.util.Map; +import java.util.NavigableMap; import com.navercorp.pinpoint.common.bo.AgentStatCpuLoadBo; import com.navercorp.pinpoint.common.bo.AgentStatMemoryGcBo; +import com.navercorp.pinpoint.common.util.BytesUtils; +import com.navercorp.pinpoint.common.util.TimeUtils; import com.navercorp.pinpoint.thrift.dto.TAgentStat; import com.navercorp.pinpoint.thrift.dto.TJvmGc; import com.navercorp.pinpoint.web.vo.AgentStat; +import com.sematext.hbase.wd.RowKeyDistributorByHashPrefix; import org.apache.hadoop.hbase.client.Result; +import org.apache.hadoop.hbase.util.Bytes; import org.apache.thrift.TDeserializer; import org.apache.thrift.TException; import org.apache.thrift.protocol.TCompactProtocol; import org.apache.thrift.protocol.TProtocolFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.data.hadoop.hbase.RowMapper; import org.springframework.stereotype.Component; /** * @author harebox - * @author hyungil.jeong + * @author HyunGil Jeong */ @Component public class AgentStatMapper implements RowMapper> { private TProtocolFactory factory = new TCompactProtocol.Factory(); + @Autowired + @Qualifier("agentStatRowKeyDistributor") + private RowKeyDistributorByHashPrefix rowKeyDistributorByHashPrefix; + public List mapRow(Result result, int rowNum) throws Exception { if (result.isEmpty()) { return Collections.emptyList(); } + final byte[] rowKey = getOriginalKey(result.getRow()); + final String agentId = BytesUtils.toString(rowKey, 0, AGENT_NAME_MAX_LEN).trim(); + final long reverseTimestamp = BytesUtils.bytesToLong(rowKey, AGENT_NAME_MAX_LEN); + final long timestamp = TimeUtils.recoveryTimeMillis(reverseTimestamp); + - Map qualifierMap = result.getFamilyMap(AGENT_STAT_CF_STATISTICS); - // FIXME (2014.08) Legacy support for TAgentStat Thrift DTO stored directly into hbase. + NavigableMap qualifierMap = result.getFamilyMap(AGENT_STAT_CF_STATISTICS); if (qualifierMap.containsKey(AGENT_STAT_CF_STATISTICS_V1)) { - return readAgentStatThriftDto(qualifierMap.get(AGENT_STAT_CF_STATISTICS_V1)); + // FIXME (2014.08) Legacy support for TAgentStat Thrift DTO stored directly into hbase. + return readAgentStatThriftDto(agentId, timestamp, qualifierMap.get(AGENT_STAT_CF_STATISTICS_V1)); + } else if (qualifierMap.containsKey(AGENT_STAT_CF_STATISTICS_MEMORY_GC) || qualifierMap.containsKey(AGENT_STAT_CF_STATISTICS_CPU_LOAD)) { + // FIXME (2015.10) Legacy column for storing serialzied Bos separately. + return readSerializedBos(agentId, timestamp, qualifierMap); } - - AgentStat agentStat = new AgentStat(); - if (qualifierMap.containsKey(AGENT_STAT_CF_STATISTICS_MEMORY_GC)) { - AgentStatMemoryGcBo.Builder builder = new AgentStatMemoryGcBo.Builder(qualifierMap.get(AGENT_STAT_CF_STATISTICS_MEMORY_GC)); - agentStat.setMemoryGc(builder.build()); + + AgentStat agentStat = new AgentStat(agentId, timestamp); + if (qualifierMap.containsKey(AGENT_STAT_CF_STATISTICS_COL_GC_TYPE)) { + agentStat.setGcType(Bytes.toString(qualifierMap.get(AGENT_STAT_CF_STATISTICS_COL_GC_TYPE))); } - if (qualifierMap.containsKey(AGENT_STAT_CF_STATISTICS_CPU_LOAD)) { - AgentStatCpuLoadBo.Builder builder = new AgentStatCpuLoadBo.Builder(qualifierMap.get(AGENT_STAT_CF_STATISTICS_CPU_LOAD)); - agentStat.setCpuLoad(builder.build()); + if (qualifierMap.containsKey(AGENT_STAT_CF_STATISTICS_COL_GC_OLD_COUNT)) { + agentStat.setGcOldCount(Bytes.toLong(qualifierMap.get(AGENT_STAT_CF_STATISTICS_COL_GC_OLD_COUNT))); } + if (qualifierMap.containsKey(AGENT_STAT_CF_STATISTICS_COL_GC_OLD_TIME)) { + agentStat.setGcOldTime(Bytes.toLong(qualifierMap.get(AGENT_STAT_CF_STATISTICS_COL_GC_OLD_TIME))); + } + if (qualifierMap.containsKey(AGENT_STAT_CF_STATISTICS_COL_HEAP_USED)) { + agentStat.setHeapUsed(Bytes.toLong(qualifierMap.get(AGENT_STAT_CF_STATISTICS_COL_HEAP_USED))); + } + if (qualifierMap.containsKey(AGENT_STAT_CF_STATISTICS_COL_HEAP_MAX)) { + agentStat.setHeapMax(Bytes.toLong(qualifierMap.get(AGENT_STAT_CF_STATISTICS_COL_HEAP_MAX))); + } + if (qualifierMap.containsKey(AGENT_STAT_CF_STATISTICS_COL_NON_HEAP_USED)) { + agentStat.setNonHeapUsed(Bytes.toLong(qualifierMap.get(AGENT_STAT_CF_STATISTICS_COL_NON_HEAP_USED))); + } + if (qualifierMap.containsKey(AGENT_STAT_CF_STATISTICS_COL_NON_HEAP_MAX)) { + agentStat.setNonHeapMax(Bytes.toLong(qualifierMap.get(AGENT_STAT_CF_STATISTICS_COL_NON_HEAP_MAX))); + } + if (qualifierMap.containsKey(AGENT_STAT_CF_STATISTICS_COL_JVM_CPU)) { + agentStat.setJvmCpuUsage(Bytes.toDouble(qualifierMap.get(AGENT_STAT_CF_STATISTICS_COL_JVM_CPU))); + } + if (qualifierMap.containsKey(AGENT_STAT_CF_STATISTICS_COL_SYS_CPU)) { + agentStat.setSystemCpuUsage(Bytes.toDouble(qualifierMap.get(AGENT_STAT_CF_STATISTICS_COL_SYS_CPU))); + } + if (qualifierMap.containsKey(AGENT_STAT_CF_STATISTICS_COL_TPS)) { + agentStat.setTps(Bytes.toInt(qualifierMap.get(AGENT_STAT_CF_STATISTICS_COL_TPS))); + } + List agentStats = new ArrayList(); agentStats.add(agentStat); return agentStats; } + private byte[] getOriginalKey(byte[] rowKey) { + return rowKeyDistributorByHashPrefix.getOriginalKey(rowKey); + } + + // FIXME (2015.10) Legacy column for storing serialzied Bos separately. + @Deprecated + private List readSerializedBos(String agentId, long timestamp, Map qualifierMap) { + AgentStat agentStat = new AgentStat(agentId, timestamp); + if (qualifierMap.containsKey(AGENT_STAT_CF_STATISTICS_MEMORY_GC)) { + AgentStatMemoryGcBo.Builder builder = new AgentStatMemoryGcBo.Builder(qualifierMap.get(AGENT_STAT_CF_STATISTICS_MEMORY_GC)); + AgentStatMemoryGcBo agentStatMemoryGcBo = builder.build(); + agentStat.setGcType(agentStatMemoryGcBo.getGcType()); + agentStat.setGcOldCount(agentStatMemoryGcBo.getJvmGcOldCount()); + agentStat.setGcOldTime(agentStatMemoryGcBo.getJvmGcOldTime()); + agentStat.setHeapUsed(agentStatMemoryGcBo.getJvmMemoryHeapUsed()); + agentStat.setHeapMax(agentStatMemoryGcBo.getJvmMemoryHeapMax()); + agentStat.setNonHeapUsed(agentStatMemoryGcBo.getJvmMemoryNonHeapUsed()); + agentStat.setNonHeapMax(agentStatMemoryGcBo.getJvmMemoryNonHeapMax()); + } + if (qualifierMap.containsKey(AGENT_STAT_CF_STATISTICS_CPU_LOAD)) { + AgentStatCpuLoadBo.Builder builder = new AgentStatCpuLoadBo.Builder(qualifierMap.get(AGENT_STAT_CF_STATISTICS_CPU_LOAD)); + AgentStatCpuLoadBo agentStatCpuLoadBo = builder.build(); + agentStat.setJvmCpuUsage(agentStatCpuLoadBo.getJvmCpuLoad()); + agentStat.setSystemCpuUsage(agentStatCpuLoadBo.getSystemCpuLoad()); + } + List result = new ArrayList(1); + result.add(agentStat); + return result; + } + // FIXME (2014.08) Legacy support for TAgentStat Thrift DTO stored directly into hbase. - private List readAgentStatThriftDto(byte[] tAgentStatByteArray) throws TException { + @Deprecated + private List readAgentStatThriftDto(String agentId, long timestamp, byte[] tAgentStatByteArray) throws TException { // CompactProtocol used TDeserializer deserializer = new TDeserializer(factory); TAgentStat tAgentStat = new TAgentStat(); @@ -90,8 +163,15 @@ public class AgentStatMapper implements RowMapper> { memoryGcBoBuilder.jvmGcOldCount(gc.getJvmGcOldCount()); memoryGcBoBuilder.jvmGcOldTime(gc.getJvmGcOldTime()); - AgentStat agentStat = new AgentStat(); - agentStat.setMemoryGc(memoryGcBoBuilder.build()); + AgentStat agentStat = new AgentStat(agentId, timestamp); + AgentStatMemoryGcBo agentStatMemoryGcBo = memoryGcBoBuilder.build(); + agentStat.setGcType(agentStatMemoryGcBo.getGcType()); + agentStat.setGcOldCount(agentStatMemoryGcBo.getJvmGcOldCount()); + agentStat.setGcOldTime(agentStatMemoryGcBo.getJvmGcOldTime()); + agentStat.setHeapUsed(agentStatMemoryGcBo.getJvmMemoryHeapUsed()); + agentStat.setHeapMax(agentStatMemoryGcBo.getJvmMemoryHeapMax()); + agentStat.setNonHeapUsed(agentStatMemoryGcBo.getJvmMemoryNonHeapUsed()); + agentStat.setNonHeapMax(agentStatMemoryGcBo.getJvmMemoryNonHeapMax()); List result = new ArrayList(1); result.add(agentStat); diff --git a/web/src/main/java/com/navercorp/pinpoint/web/vo/AgentStat.java b/web/src/main/java/com/navercorp/pinpoint/web/vo/AgentStat.java index cc75c60da..a157c9a9a 100644 --- a/web/src/main/java/com/navercorp/pinpoint/web/vo/AgentStat.java +++ b/web/src/main/java/com/navercorp/pinpoint/web/vo/AgentStat.java @@ -16,30 +16,129 @@ package com.navercorp.pinpoint.web.vo; -import com.navercorp.pinpoint.common.bo.AgentStatCpuLoadBo; -import com.navercorp.pinpoint.common.bo.AgentStatMemoryGcBo; - /** - * @author hyungil.jeong + * @author HyunGil Jeong */ public class AgentStat { + + public static final int NOT_COLLECTED = -1; + + private final String agentId; + private final long timestamp; - private AgentStatMemoryGcBo memoryGc; - private AgentStatCpuLoadBo cpuLoad; - - public AgentStatMemoryGcBo getMemoryGc() { - return memoryGc; + private String gcType; + private long gcOldCount = NOT_COLLECTED; + private long gcOldTime = NOT_COLLECTED; + private long heapUsed = NOT_COLLECTED; + private long heapMax = NOT_COLLECTED; + private long nonHeapUsed = NOT_COLLECTED; + private long nonHeapMax = NOT_COLLECTED; + private double jvmCpuUsage = NOT_COLLECTED; + private double systemCpuUsage = NOT_COLLECTED; + private int tps = NOT_COLLECTED; + + public AgentStat(String agentId, long timestamp) { + if (agentId == null) { + throw new NullPointerException("agentId must not be null"); + } + if (timestamp < 0) { + throw new NullPointerException("timestamp must not be negative"); + } + this.agentId = agentId; + this.timestamp = timestamp; + } + + public String getAgentId() { + return this.agentId; + } + + public long getTimestamp() { + return this.timestamp; } - public void setMemoryGc(AgentStatMemoryGcBo memoryGc) { - this.memoryGc = memoryGc; + public String getGcType() { + return gcType; } - public AgentStatCpuLoadBo getCpuLoad() { - return cpuLoad; + public void setGcType(String gcType) { + this.gcType = gcType; } - public void setCpuLoad(AgentStatCpuLoadBo cpuLoad) { - this.cpuLoad = cpuLoad; + public long getGcOldCount() { + return gcOldCount; } + + public void setGcOldCount(long gcOldCount) { + this.gcOldCount = gcOldCount; + } + + public long getGcOldTime() { + return gcOldTime; + } + + public void setGcOldTime(long gcOldTime) { + this.gcOldTime = gcOldTime; + } + + public long getHeapUsed() { + return heapUsed; + } + + public void setHeapUsed(long heapUsed) { + this.heapUsed = heapUsed; + } + + public long getHeapMax() { + return heapMax; + } + + public void setHeapMax(long heapMax) { + this.heapMax = heapMax; + } + + public long getNonHeapUsed() { + return nonHeapUsed; + } + + public void setNonHeapUsed(long nonHeapUsed) { + this.nonHeapUsed = nonHeapUsed; + } + + public long getNonHeapMax() { + return nonHeapMax; + } + + public void setNonHeapMax(long nonHeapMax) { + this.nonHeapMax = nonHeapMax; + } + + public double getJvmCpuUsage() { + return jvmCpuUsage; + } + + public void setJvmCpuUsage(double jvmCpuUsage) { + this.jvmCpuUsage = jvmCpuUsage; + } + + public double getSystemCpuUsage() { + return systemCpuUsage; + } + + public void setSystemCpuUsage(double systemCpuUsage) { + this.systemCpuUsage = systemCpuUsage; + } + + public int getTps() { + return tps; + } + + public void setTps(int tps) { + this.tps = tps; + } + + @Override + public String toString() { + return "AgentStat [agentId=" + agentId + ", timestamp=" + timestamp + ", tps=" + tps + "]"; + } + } diff --git a/web/src/main/java/com/navercorp/pinpoint/web/vo/linechart/DownSampler.java b/web/src/main/java/com/navercorp/pinpoint/web/vo/linechart/DownSampler.java index d66ca1b85..058f7327e 100644 --- a/web/src/main/java/com/navercorp/pinpoint/web/vo/linechart/DownSampler.java +++ b/web/src/main/java/com/navercorp/pinpoint/web/vo/linechart/DownSampler.java @@ -18,13 +18,14 @@ package com.navercorp.pinpoint.web.vo.linechart; import java.util.Collection; - /** * @author harebox - * @author hyungil.jeong + * @author HyunGil Jeong */ public interface DownSampler { + int sampleInt(Collection values); + long sampleLong(Collection values); double sampleDouble(Collection values); diff --git a/web/src/main/java/com/navercorp/pinpoint/web/vo/linechart/DownSamplers.java b/web/src/main/java/com/navercorp/pinpoint/web/vo/linechart/DownSamplers.java index 0fd4ce603..fe23754c9 100644 --- a/web/src/main/java/com/navercorp/pinpoint/web/vo/linechart/DownSamplers.java +++ b/web/src/main/java/com/navercorp/pinpoint/web/vo/linechart/DownSamplers.java @@ -16,6 +16,7 @@ package com.navercorp.pinpoint.web.vo.linechart; +import static org.apache.commons.lang3.math.NumberUtils.INTEGER_ZERO; import static org.apache.commons.lang3.math.NumberUtils.LONG_ZERO; import static org.apache.commons.lang3.math.NumberUtils.DOUBLE_ZERO; @@ -24,12 +25,11 @@ import java.util.Collections; import org.apache.commons.collections.CollectionUtils; - /** * Down samples consecutive data points, such as a time-series dataset. * * @author harebox - * @author hyungil.jeong + * @author HyunGil Jeong */ public class DownSamplers { @@ -42,6 +42,14 @@ public class DownSamplers { static class Min implements DownSampler { + @Override + public int sampleInt(Collection values) { + if (CollectionUtils.isEmpty(values)) { + return INTEGER_ZERO; + } + return Collections.min(values); + } + @Override public long sampleLong(Collection values) { if (CollectionUtils.isEmpty(values)) { @@ -62,6 +70,14 @@ public class DownSamplers { static class Max implements DownSampler { + @Override + public int sampleInt(Collection values) { + if (CollectionUtils.isEmpty(values)) { + return INTEGER_ZERO; + } + return Collections.max(values); + } + @Override public long sampleLong(Collection values) { if (CollectionUtils.isEmpty(values)) { @@ -77,20 +93,37 @@ public class DownSamplers { } return Collections.max(values); } + } static class Avg implements DownSampler { + @Override + public int sampleInt(Collection values) { + if (CollectionUtils.isEmpty(values)) { + return INTEGER_ZERO; + } + double avg = 0; + int cnt = 1; + for (int value : values) { + avg += (value - avg) / cnt; + ++cnt; + } + return (int)Math.round(avg); + } + @Override public long sampleLong(Collection values) { if (CollectionUtils.isEmpty(values)) { return LONG_ZERO; } - long total = 0L; + double avg = 0; + int cnt = 1; for (long value : values) { - total += value; + avg += (value - avg) / cnt; + ++cnt; } - return total / values.size(); + return (long)Math.round(avg); } @Override @@ -98,12 +131,15 @@ public class DownSamplers { if (CollectionUtils.isEmpty(values)) { return DOUBLE_ZERO; } - double total = 0D; + double avg = 0; + int cnt = 1; for (double value : values) { - total += value; + avg += (value - avg) / cnt; + ++cnt; } - return total / values.size(); + return avg; } + } } diff --git a/web/src/main/java/com/navercorp/pinpoint/web/vo/linechart/SampledTimeSeriesIntegerChartBuilder.java b/web/src/main/java/com/navercorp/pinpoint/web/vo/linechart/SampledTimeSeriesIntegerChartBuilder.java new file mode 100644 index 000000000..bc68c6b4c --- /dev/null +++ b/web/src/main/java/com/navercorp/pinpoint/web/vo/linechart/SampledTimeSeriesIntegerChartBuilder.java @@ -0,0 +1,52 @@ +/* + * Copyright 2015 NAVER Corp. + * + * 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. + */ + +package com.navercorp.pinpoint.web.vo.linechart; + +import java.util.List; + +import com.navercorp.pinpoint.web.util.TimeWindow; + +/** + * @author HyunGil Jeong + */ +public class SampledTimeSeriesIntegerChartBuilder extends SampledTimeSeriesChartBuilder { + + private static final int DEFAULT_VALUE = 0; + + public SampledTimeSeriesIntegerChartBuilder(TimeWindow timeWindow) { + super(timeWindow, DEFAULT_VALUE); + } + + public SampledTimeSeriesIntegerChartBuilder(TimeWindow timeWindow, int defaultValue) { + super(timeWindow, defaultValue); + } + + @Override + protected Integer sampleMin(List sampleBuffer) { + return DownSamplers.MIN.sampleInt(sampleBuffer); + } + + @Override + protected Integer sampleMax(List sampleBuffer) { + return DownSamplers.MAX.sampleInt(sampleBuffer); + } + + @Override + protected Integer sampleAvg(List sampleBuffer) { + return DownSamplers.AVG.sampleInt(sampleBuffer); + } +} diff --git a/web/src/main/java/com/navercorp/pinpoint/web/vo/linechart/agentstat/AgentStatChartGroup.java b/web/src/main/java/com/navercorp/pinpoint/web/vo/linechart/agentstat/AgentStatChartGroup.java index 2b5f5208f..a87dc0262 100644 --- a/web/src/main/java/com/navercorp/pinpoint/web/vo/linechart/agentstat/AgentStatChartGroup.java +++ b/web/src/main/java/com/navercorp/pinpoint/web/vo/linechart/agentstat/AgentStatChartGroup.java @@ -20,19 +20,18 @@ import java.util.EnumMap; import java.util.List; import java.util.Map; -import com.navercorp.pinpoint.common.bo.AgentStatCpuLoadBo; -import com.navercorp.pinpoint.common.bo.AgentStatMemoryGcBo; import com.navercorp.pinpoint.web.util.TimeWindow; import com.navercorp.pinpoint.web.vo.AgentStat; import com.navercorp.pinpoint.web.vo.linechart.Chart; import com.navercorp.pinpoint.web.vo.linechart.DataPoint; import com.navercorp.pinpoint.web.vo.linechart.SampledTimeSeriesDoubleChartBuilder; +import com.navercorp.pinpoint.web.vo.linechart.SampledTimeSeriesIntegerChartBuilder; import com.navercorp.pinpoint.web.vo.linechart.SampledTimeSeriesLongChartBuilder; import com.navercorp.pinpoint.web.vo.linechart.Chart.ChartBuilder; /** * @author harebox - * @author hyungil.jeong + * @author HyunGil Jeong */ public class AgentStatChartGroup { @@ -44,10 +43,11 @@ public class AgentStatChartGroup { JVM_GC_OLD_COUNT, JVM_GC_OLD_TIME, CPU_LOAD_JVM, - CPU_LOAD_SYSTEM + CPU_LOAD_SYSTEM, + TPS } - private static final int uncollectedData = -1; + private static final int UNCOLLECTED_DATA = AgentStat.NOT_COLLECTED; private String type; @@ -57,21 +57,25 @@ public class AgentStatChartGroup { public AgentStatChartGroup(TimeWindow timeWindow) { this.chartBuilders = new EnumMap>(ChartType.class); - this.chartBuilders.put(ChartType.JVM_MEMORY_HEAP_USED, new SampledTimeSeriesLongChartBuilder(timeWindow, uncollectedData)); - this.chartBuilders.put(ChartType.JVM_MEMORY_HEAP_MAX, new SampledTimeSeriesLongChartBuilder(timeWindow, uncollectedData)); - this.chartBuilders.put(ChartType.JVM_MEMORY_NON_HEAP_USED, new SampledTimeSeriesLongChartBuilder(timeWindow, uncollectedData)); - this.chartBuilders.put(ChartType.JVM_MEMORY_NON_HEAP_MAX, new SampledTimeSeriesLongChartBuilder(timeWindow, uncollectedData)); - this.chartBuilders.put(ChartType.JVM_GC_OLD_COUNT, new SampledTimeSeriesLongChartBuilder(timeWindow, uncollectedData)); - this.chartBuilders.put(ChartType.JVM_GC_OLD_TIME, new SampledTimeSeriesLongChartBuilder(timeWindow, uncollectedData)); - this.chartBuilders.put(ChartType.CPU_LOAD_JVM, new SampledTimeSeriesDoubleChartBuilder(timeWindow, uncollectedData)); - this.chartBuilders.put(ChartType.CPU_LOAD_SYSTEM, new SampledTimeSeriesDoubleChartBuilder(timeWindow, uncollectedData)); + this.chartBuilders.put(ChartType.JVM_MEMORY_HEAP_USED, new SampledTimeSeriesLongChartBuilder(timeWindow, UNCOLLECTED_DATA)); + this.chartBuilders.put(ChartType.JVM_MEMORY_HEAP_MAX, new SampledTimeSeriesLongChartBuilder(timeWindow, UNCOLLECTED_DATA)); + this.chartBuilders.put(ChartType.JVM_MEMORY_NON_HEAP_USED, new SampledTimeSeriesLongChartBuilder(timeWindow, UNCOLLECTED_DATA)); + this.chartBuilders.put(ChartType.JVM_MEMORY_NON_HEAP_MAX, new SampledTimeSeriesLongChartBuilder(timeWindow, UNCOLLECTED_DATA)); + this.chartBuilders.put(ChartType.JVM_GC_OLD_COUNT, new SampledTimeSeriesLongChartBuilder(timeWindow, UNCOLLECTED_DATA)); + this.chartBuilders.put(ChartType.JVM_GC_OLD_TIME, new SampledTimeSeriesLongChartBuilder(timeWindow, UNCOLLECTED_DATA)); + this.chartBuilders.put(ChartType.CPU_LOAD_JVM, new SampledTimeSeriesDoubleChartBuilder(timeWindow, UNCOLLECTED_DATA)); + this.chartBuilders.put(ChartType.CPU_LOAD_SYSTEM, new SampledTimeSeriesDoubleChartBuilder(timeWindow, UNCOLLECTED_DATA)); + this.chartBuilders.put(ChartType.TPS, new SampledTimeSeriesIntegerChartBuilder(timeWindow, UNCOLLECTED_DATA)); this.charts = new EnumMap(ChartType.class); } public void addAgentStats(List agentStats) { for (AgentStat agentStat : agentStats) { - addMemoryGcData(agentStat.getMemoryGc()); - addCpuLoadData(agentStat.getCpuLoad()); + if (agentStat != null) { + addMemoryGcData(agentStat); + addCpuLoadData(agentStat); + addTransactionData(agentStat); + } } } @@ -81,29 +85,28 @@ public class AgentStatChartGroup { } } - private void addMemoryGcData(AgentStatMemoryGcBo data) { - if (data == null) { - return; - } - this.type = data.getGcType(); - long timestamp = data.getTimestamp(); - ((SampledTimeSeriesLongChartBuilder)this.chartBuilders.get(ChartType.JVM_MEMORY_HEAP_USED)).addDataPoint(new DataPoint(timestamp, data.getJvmMemoryHeapUsed())); - ((SampledTimeSeriesLongChartBuilder)this.chartBuilders.get(ChartType.JVM_MEMORY_HEAP_MAX)).addDataPoint(new DataPoint(timestamp, data.getJvmMemoryHeapMax())); - ((SampledTimeSeriesLongChartBuilder)this.chartBuilders.get(ChartType.JVM_MEMORY_NON_HEAP_USED)).addDataPoint(new DataPoint(timestamp, data.getJvmMemoryNonHeapUsed())); - ((SampledTimeSeriesLongChartBuilder)this.chartBuilders.get(ChartType.JVM_MEMORY_NON_HEAP_MAX)).addDataPoint(new DataPoint(timestamp, data.getJvmMemoryNonHeapMax())); - ((SampledTimeSeriesLongChartBuilder)this.chartBuilders.get(ChartType.JVM_GC_OLD_COUNT)).addDataPoint(new DataPoint(timestamp, data.getJvmGcOldCount())); - ((SampledTimeSeriesLongChartBuilder)this.chartBuilders.get(ChartType.JVM_GC_OLD_TIME)).addDataPoint(new DataPoint(timestamp, data.getJvmGcOldTime())); + private void addMemoryGcData(AgentStat agentStat) { + this.type = agentStat.getGcType(); + long timestamp = agentStat.getTimestamp(); + ((SampledTimeSeriesLongChartBuilder)this.chartBuilders.get(ChartType.JVM_MEMORY_HEAP_USED)).addDataPoint(new DataPoint(timestamp, agentStat.getHeapUsed())); + ((SampledTimeSeriesLongChartBuilder)this.chartBuilders.get(ChartType.JVM_MEMORY_HEAP_MAX)).addDataPoint(new DataPoint(timestamp, agentStat.getHeapMax())); + ((SampledTimeSeriesLongChartBuilder)this.chartBuilders.get(ChartType.JVM_MEMORY_NON_HEAP_USED)).addDataPoint(new DataPoint(timestamp, agentStat.getNonHeapUsed())); + ((SampledTimeSeriesLongChartBuilder)this.chartBuilders.get(ChartType.JVM_MEMORY_NON_HEAP_MAX)).addDataPoint(new DataPoint(timestamp, agentStat.getNonHeapMax())); + ((SampledTimeSeriesLongChartBuilder)this.chartBuilders.get(ChartType.JVM_GC_OLD_COUNT)).addDataPoint(new DataPoint(timestamp, agentStat.getGcOldCount())); + ((SampledTimeSeriesLongChartBuilder)this.chartBuilders.get(ChartType.JVM_GC_OLD_TIME)).addDataPoint(new DataPoint(timestamp, agentStat.getGcOldTime())); } - private void addCpuLoadData(AgentStatCpuLoadBo data) { - if (data == null) { - return; - } - long timestamp = data.getTimestamp(); - double jvmCpuLoadPercentage = data.getJvmCpuLoad() * 100; - double systemCpuLoadPercentage = data.getSystemCpuLoad() * 100; - ((SampledTimeSeriesDoubleChartBuilder)this.chartBuilders.get(ChartType.CPU_LOAD_JVM)).addDataPoint(new DataPoint(timestamp, jvmCpuLoadPercentage)); - ((SampledTimeSeriesDoubleChartBuilder)this.chartBuilders.get(ChartType.CPU_LOAD_SYSTEM)).addDataPoint(new DataPoint(timestamp, systemCpuLoadPercentage)); + private void addCpuLoadData(AgentStat agentStat) { + long timestamp = agentStat.getTimestamp(); + double jvmCpuUsagePercentage = agentStat.getJvmCpuUsage() * 100; + double systemCpuUsagePercentage = agentStat.getSystemCpuUsage() * 100; + ((SampledTimeSeriesDoubleChartBuilder)this.chartBuilders.get(ChartType.CPU_LOAD_JVM)).addDataPoint(new DataPoint(timestamp, jvmCpuUsagePercentage)); + ((SampledTimeSeriesDoubleChartBuilder)this.chartBuilders.get(ChartType.CPU_LOAD_SYSTEM)).addDataPoint(new DataPoint(timestamp, systemCpuUsagePercentage)); + } + + private void addTransactionData(AgentStat agentStat) { + long timestamp = agentStat.getTimestamp(); + ((SampledTimeSeriesIntegerChartBuilder)this.chartBuilders.get(ChartType.TPS)).addDataPoint(new DataPoint(timestamp, agentStat.getTps())); } public String getType() { @@ -113,5 +116,4 @@ public class AgentStatChartGroup { public Map getCharts() { return charts; } - } \ No newline at end of file diff --git a/web/src/test/java/com/navercorp/pinpoint/web/alarm/checker/GcCountCheckerTest.java b/web/src/test/java/com/navercorp/pinpoint/web/alarm/checker/GcCountCheckerTest.java index 80619bfbd..b3890aae2 100644 --- a/web/src/test/java/com/navercorp/pinpoint/web/alarm/checker/GcCountCheckerTest.java +++ b/web/src/test/java/com/navercorp/pinpoint/web/alarm/checker/GcCountCheckerTest.java @@ -16,24 +16,11 @@ package com.navercorp.pinpoint.web.alarm.checker; -import static org.junit.Assert.*; - import java.util.LinkedList; import java.util.List; import org.junit.BeforeClass; -import org.junit.Test; -import com.navercorp.pinpoint.common.bo.AgentStatCpuLoadBo; -import com.navercorp.pinpoint.common.bo.AgentStatMemoryGcBo; -import com.navercorp.pinpoint.common.trace.ServiceType; -import com.navercorp.pinpoint.web.alarm.CheckerCategory; -import com.navercorp.pinpoint.web.alarm.DataCollectorFactory; -import com.navercorp.pinpoint.web.alarm.DataCollectorFactory.DataCollectorCategory; -import com.navercorp.pinpoint.web.alarm.checker.AgentChecker; -import com.navercorp.pinpoint.web.alarm.checker.GcCountChecker; -import com.navercorp.pinpoint.web.alarm.collector.AgentStatDataCollector; -import com.navercorp.pinpoint.web.alarm.vo.Rule; import com.navercorp.pinpoint.web.dao.AgentStatDao; import com.navercorp.pinpoint.web.dao.ApplicationIndexDao; import com.navercorp.pinpoint.web.vo.AgentStat; @@ -56,23 +43,15 @@ public class GcCountCheckerTest { @Override public List scanAgentStatList(String agentId, Range range) { - List AgentStatList = new LinkedList(); + List agentStatList = new LinkedList(); for (int i = 36; i > 0; i--) { - AgentStatMemoryGcBo.Builder memoryBuilder = new AgentStatMemoryGcBo.Builder("AGETNT_NAME", 0L, 1L); - memoryBuilder.jvmGcOldCount(i); - AgentStatMemoryGcBo memoryBo = memoryBuilder.build(); - AgentStatCpuLoadBo.Builder cpuBuilder = new AgentStatCpuLoadBo.Builder("AGETNT_NAME", 0L, 1L); - AgentStatCpuLoadBo cpuLoadBo = cpuBuilder.build(); - - AgentStat stat = new AgentStat(); - stat.setMemoryGc(memoryBo); - stat.setCpuLoad(cpuLoadBo); - - AgentStatList.add(stat); + AgentStat stat = new AgentStat("AGENT_NAME", 1L); + stat.setGcOldCount(i); + agentStatList.add(stat); } - return AgentStatList; + return agentStatList; } }; diff --git a/web/src/test/java/com/navercorp/pinpoint/web/alarm/checker/HeapUsageRateCheckerTest.java b/web/src/test/java/com/navercorp/pinpoint/web/alarm/checker/HeapUsageRateCheckerTest.java index e3a0826aa..64c9a96a3 100644 --- a/web/src/test/java/com/navercorp/pinpoint/web/alarm/checker/HeapUsageRateCheckerTest.java +++ b/web/src/test/java/com/navercorp/pinpoint/web/alarm/checker/HeapUsageRateCheckerTest.java @@ -25,8 +25,6 @@ import java.util.List; import org.junit.BeforeClass; import org.junit.Test; -import com.navercorp.pinpoint.common.bo.AgentStatCpuLoadBo; -import com.navercorp.pinpoint.common.bo.AgentStatMemoryGcBo; import com.navercorp.pinpoint.common.trace.ServiceType; import com.navercorp.pinpoint.web.alarm.CheckerCategory; import com.navercorp.pinpoint.web.alarm.DataCollectorFactory; @@ -56,24 +54,17 @@ public class HeapUsageRateCheckerTest { @Override public List scanAgentStatList(String agentId, Range range) { - List AgentStatList = new LinkedList(); + List agentStatList = new LinkedList(); for (int i = 0; i < 36; i++) { - AgentStatMemoryGcBo.Builder memoryBuilder = new AgentStatMemoryGcBo.Builder("AGETNT_NAME", 0L, 1L); - memoryBuilder.jvmMemoryHeapUsed(70L); - memoryBuilder.jvmMemoryHeapMax(100L); - AgentStatMemoryGcBo memoryBo = memoryBuilder.build(); - AgentStatCpuLoadBo.Builder cpuBuilder = new AgentStatCpuLoadBo.Builder("AGETNT_NAME", 0L, 1L); - AgentStatCpuLoadBo cpuLoadBo = cpuBuilder.build(); + AgentStat stat = new AgentStat("AGENT_NAME", 1L); + stat.setHeapUsed(70L); + stat.setHeapMax(100L); - AgentStat stat = new AgentStat(); - stat.setMemoryGc(memoryBo); - stat.setCpuLoad(cpuLoadBo); - - AgentStatList.add(stat); + agentStatList.add(stat); } - return AgentStatList; + return agentStatList; } }; diff --git a/web/src/test/java/com/navercorp/pinpoint/web/alarm/checker/JvmCpuUsageRateCheckerTest.java b/web/src/test/java/com/navercorp/pinpoint/web/alarm/checker/JvmCpuUsageRateCheckerTest.java index 86ce284a5..318aeb1bc 100644 --- a/web/src/test/java/com/navercorp/pinpoint/web/alarm/checker/JvmCpuUsageRateCheckerTest.java +++ b/web/src/test/java/com/navercorp/pinpoint/web/alarm/checker/JvmCpuUsageRateCheckerTest.java @@ -24,8 +24,6 @@ import java.util.List; import org.junit.BeforeClass; import org.junit.Test; -import com.navercorp.pinpoint.common.bo.AgentStatCpuLoadBo; -import com.navercorp.pinpoint.common.bo.AgentStatMemoryGcBo; import com.navercorp.pinpoint.common.trace.ServiceType; import com.navercorp.pinpoint.web.alarm.CheckerCategory; import com.navercorp.pinpoint.web.alarm.DataCollectorFactory; @@ -55,24 +53,15 @@ public class JvmCpuUsageRateCheckerTest { @Override public List scanAgentStatList(String agentId, Range range) { - List AgentStatList = new LinkedList(); + List agentStatList = new LinkedList(); for (int i = 0; i < 36; i++) { - AgentStatCpuLoadBo.Builder cpuLoadBoBuilder = new AgentStatCpuLoadBo.Builder("AGETNT_NAME", 0L, 1L); - cpuLoadBoBuilder.jvmCpuLoad(0.6); - AgentStatCpuLoadBo cpuLoadBo = cpuLoadBoBuilder.build(); - - AgentStatMemoryGcBo.Builder memoryGcBobuilder = new AgentStatMemoryGcBo.Builder("AGETNT_NAME", 0L, 1L); - AgentStatMemoryGcBo memoryGcBo = memoryGcBobuilder.build(); - - AgentStat stat = new AgentStat(); - stat.setCpuLoad(cpuLoadBo); - stat.setMemoryGc(memoryGcBo); - - AgentStatList.add(stat); + AgentStat stat = new AgentStat("AGENT_NAME", 1L); + stat.setJvmCpuUsage(0.6); + agentStatList.add(stat); } - return AgentStatList; + return agentStatList; } }; diff --git a/web/src/test/java/com/navercorp/pinpoint/web/mapper/AgentStatMapperTest.java b/web/src/test/java/com/navercorp/pinpoint/web/mapper/AgentStatMapperTest.java new file mode 100644 index 000000000..bb5f0de64 --- /dev/null +++ b/web/src/test/java/com/navercorp/pinpoint/web/mapper/AgentStatMapperTest.java @@ -0,0 +1,219 @@ +/* + * Copyright 2015 NAVER Corp. + * + * 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. + */ + +package com.navercorp.pinpoint.web.mapper; + +import static org.hamcrest.core.Is.*; +import static org.junit.Assert.*; +import static org.mockito.Matchers.*; +import static org.mockito.Mockito.*; +import static com.navercorp.pinpoint.common.hbase.HBaseTables.*; + +import java.util.Arrays; +import java.util.List; + +import org.apache.hadoop.hbase.Cell; +import org.apache.hadoop.hbase.CellUtil; +import org.apache.hadoop.hbase.HConstants; +import org.apache.hadoop.hbase.KeyValue; +import org.apache.hadoop.hbase.client.Result; +import org.apache.hadoop.hbase.util.Bytes; +import org.apache.thrift.TException; +import org.apache.thrift.TSerializer; +import org.apache.thrift.protocol.TCompactProtocol; +import org.apache.thrift.protocol.TProtocolFactory; +import org.junit.Before; +import org.junit.Test; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; + +import com.navercorp.pinpoint.common.bo.AgentStatCpuLoadBo; +import com.navercorp.pinpoint.common.bo.AgentStatMemoryGcBo; +import com.navercorp.pinpoint.common.util.BytesUtils; +import com.navercorp.pinpoint.common.util.RowKeyUtils; +import com.navercorp.pinpoint.common.util.TimeUtils; +import com.navercorp.pinpoint.thrift.dto.TAgentStat; +import com.navercorp.pinpoint.thrift.dto.TJvmGc; +import com.navercorp.pinpoint.thrift.dto.TJvmGcType; +import com.navercorp.pinpoint.web.vo.AgentStat; +import com.sematext.hbase.wd.RowKeyDistributorByHashPrefix; + +/** + * @author HyunGil Jeong + */ +public class AgentStatMapperTest { + + // for comparing CPU Usage up to 2 decimal places + private static final double DELTA = 1e-4; + + private static final String AGENT_ID = "agentId"; + private static final long TIMESTAMP = System.currentTimeMillis(); + private static final byte[] ROW_KEY = RowKeyUtils.concatFixedByteAndLong(BytesUtils.toBytes(AGENT_ID), AGENT_NAME_MAX_LEN, TimeUtils.reverseTimeMillis(TIMESTAMP)); + + private static final TJvmGcType GC_TYPE = TJvmGcType.G1; + private static final long GC_OLD_COUNT = 0L; + private static final long GC_OLD_TIME = Long.MAX_VALUE; + private static final long HEAP_USED = 1024L; + private static final long HEAP_MAX = 4096L; + private static final long NON_HEAP_USED = 52L; + private static final long NON_HEAP_MAX = -1L; + + private static final double JVM_CPU_USAGE = 10; + private static final double SYS_CPU_USAGE = 20; + + private static final int TPS = 100; + + @Mock + private RowKeyDistributorByHashPrefix rowKeyDistributorByHashPrefix; + + @InjectMocks + private AgentStatMapper mapper = new AgentStatMapper(); + + @Before + public void setUp() throws Exception { + MockitoAnnotations.initMocks(this); + when(this.rowKeyDistributorByHashPrefix.getOriginalKey(any(byte[].class))).thenReturn(ROW_KEY); + } + + @Test + public void test_current() throws Exception { + // Given + final Result result = Result.create(Arrays.asList( + createCell(AGENT_STAT_CF_STATISTICS_COL_GC_TYPE, Bytes.toBytes(GC_TYPE.name())), + createCell(AGENT_STAT_CF_STATISTICS_COL_GC_OLD_COUNT, Bytes.toBytes(GC_OLD_COUNT)), + createCell(AGENT_STAT_CF_STATISTICS_COL_GC_OLD_TIME, Bytes.toBytes(GC_OLD_TIME)), + createCell(AGENT_STAT_CF_STATISTICS_COL_HEAP_USED, Bytes.toBytes(HEAP_USED)), + createCell(AGENT_STAT_CF_STATISTICS_COL_HEAP_MAX, Bytes.toBytes(HEAP_MAX)), + createCell(AGENT_STAT_CF_STATISTICS_COL_NON_HEAP_USED, Bytes.toBytes(NON_HEAP_USED)), + createCell(AGENT_STAT_CF_STATISTICS_COL_NON_HEAP_MAX, Bytes.toBytes(NON_HEAP_MAX)), + createCell(AGENT_STAT_CF_STATISTICS_COL_JVM_CPU, Bytes.toBytes(JVM_CPU_USAGE)), + createCell(AGENT_STAT_CF_STATISTICS_COL_SYS_CPU, Bytes.toBytes(SYS_CPU_USAGE)), + createCell(AGENT_STAT_CF_STATISTICS_COL_TPS, Bytes.toBytes(TPS)) + )); + // When + List agentStats = this.mapper.mapRow(result, 0); + // Then + assertNotNull(agentStats); + assertThat(agentStats.size(), is(1)); + AgentStat agentStat = agentStats.get(0); + + assertJvmGc(agentStat); + assertCpuUsage(agentStat); + assertTransaction(agentStat); + } + + @Test + public void test_legacy_with_AGENT_STAT_CF_STATISTICS_V1() throws Exception { + // Given + final Result result = createResultForLegacyWith_AGENT_STAT_CF_STATISTICS_V1(); + // When + List agentStats = this.mapper.mapRow(result, 0); + // Then + assertNotNull(agentStats); + assertThat(agentStats.size(), is(1)); + AgentStat agentStat = agentStats.get(0); + + assertJvmGc(agentStat); + assertEquals(AgentStat.NOT_COLLECTED, agentStat.getJvmCpuUsage(), DELTA); + assertEquals(AgentStat.NOT_COLLECTED, agentStat.getSystemCpuUsage(), DELTA); + assertEquals(AgentStat.NOT_COLLECTED, agentStat.getTps()); + } + + @Test + public void test_legacy_serialized_BOs() throws Exception { + // Given + final Result result = createResultForLegacy_serialized_BOs(); + // When + List agentStats = this.mapper.mapRow(result, 0); + // Then + assertNotNull(agentStats); + assertThat(agentStats.size(), is(1)); + AgentStat agentStat = agentStats.get(0); + + assertJvmGc(agentStat); + assertCpuUsage(agentStat); + assertEquals(AgentStat.NOT_COLLECTED, agentStat.getTps()); + } + + private void assertJvmGc(AgentStat agentStat) { + assertEquals(AGENT_ID, agentStat.getAgentId()); + assertEquals(TIMESTAMP, agentStat.getTimestamp()); + assertEquals(GC_TYPE.name(), agentStat.getGcType()); + assertEquals(GC_OLD_COUNT, agentStat.getGcOldCount()); + assertEquals(GC_OLD_TIME, agentStat.getGcOldTime()); + assertEquals(HEAP_USED, agentStat.getHeapUsed()); + assertEquals(HEAP_MAX, agentStat.getHeapMax()); + assertEquals(NON_HEAP_USED, agentStat.getNonHeapUsed()); + assertEquals(NON_HEAP_MAX, agentStat.getNonHeapMax()); + } + + private void assertCpuUsage(AgentStat agentStat) { + assertEquals(JVM_CPU_USAGE, agentStat.getJvmCpuUsage(), DELTA); + assertEquals(SYS_CPU_USAGE, agentStat.getSystemCpuUsage(), DELTA); + } + + private void assertTransaction(AgentStat agentStat) { + assertEquals(TPS, agentStat.getTps()); + } + + private Result createResultForLegacyWith_AGENT_STAT_CF_STATISTICS_V1() throws TException { + final TAgentStat agentStat = new TAgentStat(); + final TJvmGc gc = new TJvmGc(); + gc.setType(GC_TYPE); + gc.setJvmGcOldCount(GC_OLD_COUNT); + gc.setJvmGcOldTime(GC_OLD_TIME); + gc.setJvmMemoryHeapUsed(HEAP_USED); + gc.setJvmMemoryHeapMax(HEAP_MAX); + gc.setJvmMemoryNonHeapUsed(NON_HEAP_USED); + gc.setJvmMemoryNonHeapMax(NON_HEAP_MAX); + agentStat.setGc(gc); + + final TProtocolFactory factory = new TCompactProtocol.Factory(); + final TSerializer serializer = new TSerializer(factory); + final byte[] qualifier = AGENT_STAT_CF_STATISTICS_V1; + final byte[] value = serializer.serialize(agentStat); + return Result.create(Arrays.asList(createCell(qualifier, value))); + } + + private Result createResultForLegacy_serialized_BOs() { + final AgentStatMemoryGcBo.Builder jvmGcBuilder = new AgentStatMemoryGcBo.Builder(AGENT_ID, 0L, TIMESTAMP); + jvmGcBuilder.gcType(GC_TYPE.name()); + jvmGcBuilder.jvmGcOldCount(GC_OLD_COUNT); + jvmGcBuilder.jvmGcOldTime(GC_OLD_TIME); + jvmGcBuilder.jvmMemoryHeapUsed(HEAP_USED); + jvmGcBuilder.jvmMemoryHeapMax(HEAP_MAX); + jvmGcBuilder.jvmMemoryNonHeapUsed(NON_HEAP_USED); + jvmGcBuilder.jvmMemoryNonHeapMax(NON_HEAP_MAX); + final AgentStatCpuLoadBo.Builder cpuLoadBuilder = new AgentStatCpuLoadBo.Builder(AGENT_ID, 0L, TIMESTAMP); + cpuLoadBuilder.jvmCpuLoad(JVM_CPU_USAGE); + cpuLoadBuilder.systemCpuLoad(SYS_CPU_USAGE); + final AgentStatMemoryGcBo jvmGc = jvmGcBuilder.build(); + final AgentStatCpuLoadBo cpuLoad = cpuLoadBuilder.build(); + + final Cell jvmGcCell = createCell(AGENT_STAT_CF_STATISTICS_MEMORY_GC, jvmGc.writeValue()); + final Cell cpuLoadCell = createCell(AGENT_STAT_CF_STATISTICS_CPU_LOAD, cpuLoad.writeValue()); + + return Result.create(Arrays.asList(jvmGcCell, cpuLoadCell)); + + } + + private Cell createCell(byte[] qualifier, byte[] value) { + return CellUtil.createCell(ROW_KEY, AGENT_STAT_CF_STATISTICS, qualifier, HConstants.LATEST_TIMESTAMP, + KeyValue.Type.Maximum.getCode(), value); + } + +}