diff --git a/src/main/java/com/nhn/pinpoint/web/controller/AgentStatController.java b/src/main/java/com/nhn/pinpoint/web/controller/AgentStatController.java index 46bcab8ed..6df3fdaa7 100644 --- a/src/main/java/com/nhn/pinpoint/web/controller/AgentStatController.java +++ b/src/main/java/com/nhn/pinpoint/web/controller/AgentStatController.java @@ -3,13 +3,13 @@ package com.nhn.pinpoint.web.controller; import java.util.List; import java.util.SortedMap; - +import com.nhn.pinpoint.web.vo.AgentStat; import com.nhn.pinpoint.web.vo.Range; + import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Controller; -import org.springframework.ui.Model; import org.springframework.util.StopWatch; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; @@ -17,7 +17,6 @@ import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.ResponseBody; import com.nhn.pinpoint.common.bo.AgentInfoBo; -import com.nhn.pinpoint.thrift.dto.TAgentStat; import com.nhn.pinpoint.web.service.AgentInfoService; import com.nhn.pinpoint.web.service.AgentStatService; import com.nhn.pinpoint.web.vo.linechart.agentstat.AgentStatChartGroup; @@ -25,53 +24,51 @@ import com.nhn.pinpoint.web.vo.linechart.agentstat.AgentStatChartGroup; @Controller public class AgentStatController { - private final Logger logger = LoggerFactory.getLogger(this.getClass()); + private final Logger logger = LoggerFactory.getLogger(this.getClass()); - @Autowired - private AgentStatService agentStatService; - - @Autowired - private AgentInfoService agentInfoService; - - @RequestMapping(value = "/getAgentStat", method = RequestMethod.GET) + @Autowired + private AgentStatService agentStatService; + + @Autowired + private AgentInfoService agentInfoService; + + @RequestMapping(value = "/getAgentStat", method = RequestMethod.GET) @ResponseBody - public AgentStatChartGroup getAgentStat( - @RequestParam("agentId") String agentId, - @RequestParam("from") long from, - @RequestParam("to") long to, - @RequestParam(value = "sampleRate", required = false) Integer sampleRate) throws Exception { - StopWatch watch = new StopWatch(); - watch.start("agentStatService.selectAgentStatList"); + public AgentStatChartGroup getAgentStat( + @RequestParam("agentId") String agentId, + @RequestParam("from") long from, + @RequestParam("to") long to, + @RequestParam(value = "sampleRate", required = false) Integer sampleRate) throws Exception { + StopWatch watch = new StopWatch(); + watch.start("agentStatService.selectAgentStatList"); Range range = new Range(from, to); - List agentStatList = agentStatService.selectAgentStatList(agentId, range); - watch.stop(); - - if (logger.isInfoEnabled()) { - logger.info("getAgentStat(agentId={}, from={}, to={}) : {}ms", agentId, from, to, watch.getLastTaskTimeMillis()); - } + List agentStatList = agentStatService.selectAgentStatList(agentId, range); + watch.stop(); - // FIXME dummy - int nPoints = (int) (to - from) / 5000; - if (sampleRate == null) { - sampleRate = nPoints < 300 ? 1 : nPoints / 300; - } - - AgentStatChartGroup chart = new AgentStatChartGroup(); - for (TAgentStat each : agentStatList) { - chart.addData(each, sampleRate); - } + if (logger.isInfoEnabled()) { + logger.info("getAgentStat(agentId={}, from={}, to={}) : {}ms", agentId, from, to, watch.getLastTaskTimeMillis()); + } - return chart; - } + // FIXME dummy + int nPoints = (int) (to - from) / 5000; + if (sampleRate == null) { + sampleRate = nPoints < 300 ? 1 : nPoints / 300; + } - @RequestMapping(value = "/getAgentList", method = RequestMethod.GET) + AgentStatChartGroup chart = new AgentStatChartGroup(sampleRate); + chart.addAgentStats(agentStatList); + + return chart; + } + + @RequestMapping(value = "/getAgentList", method = RequestMethod.GET) @ResponseBody public SortedMap> getApplicationAgentList( - @RequestParam("application") String applicationName, - @RequestParam("from") long from, - @RequestParam("to") long to) { + @RequestParam("application") String applicationName, + @RequestParam("from") long from, + @RequestParam("to") long to) { Range range = new Range(from, to); - SortedMap> applicationAgentList = agentInfoService.getApplicationAgentList(applicationName, range); - return applicationAgentList; - } + SortedMap> applicationAgentList = agentInfoService.getApplicationAgentList(applicationName, range); + return applicationAgentList; + } } diff --git a/src/main/java/com/nhn/pinpoint/web/dao/AgentStatDao.java b/src/main/java/com/nhn/pinpoint/web/dao/AgentStatDao.java index 60036744c..fbc1ff66f 100644 --- a/src/main/java/com/nhn/pinpoint/web/dao/AgentStatDao.java +++ b/src/main/java/com/nhn/pinpoint/web/dao/AgentStatDao.java @@ -2,12 +2,14 @@ package com.nhn.pinpoint.web.dao; import java.util.List; -import com.nhn.pinpoint.thrift.dto.TAgentStat; +import com.nhn.pinpoint.web.vo.AgentStat; import com.nhn.pinpoint.web.vo.Range; +/** + * @author hyungil.jeong + */ public interface AgentStatDao { - - List scanAgentStatList(String agentId, Range range); -// List scanAgentStatList(String agentId, long start, long end, final int limit); - + + List scanAgentStatList(String agentId, Range range); + } diff --git a/src/main/java/com/nhn/pinpoint/web/dao/hbase/HbaseAgentStatDao.java b/src/main/java/com/nhn/pinpoint/web/dao/hbase/HbaseAgentStatDao.java index 5a9b72967..86925ad1e 100644 --- a/src/main/java/com/nhn/pinpoint/web/dao/hbase/HbaseAgentStatDao.java +++ b/src/main/java/com/nhn/pinpoint/web/dao/hbase/HbaseAgentStatDao.java @@ -5,8 +5,9 @@ import static com.nhn.pinpoint.common.hbase.HBaseTables.AGENT_NAME_MAX_LEN; import java.util.ArrayList; import java.util.List; -import com.nhn.pinpoint.thrift.dto.TAgentStat; +import com.nhn.pinpoint.web.vo.AgentStat; import com.nhn.pinpoint.web.vo.Range; + import org.apache.hadoop.hbase.client.Scan; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -25,30 +26,31 @@ import com.sematext.hbase.wd.AbstractRowKeyDistributor; /** * @author emeroad + * @author hyungil.jeong */ @Repository public class HbaseAgentStatDao implements AgentStatDao { - private final Logger logger = LoggerFactory.getLogger(this.getClass()); + private final Logger logger = LoggerFactory.getLogger(this.getClass()); - @Autowired - private HbaseOperations2 hbaseOperations2; + @Autowired + private HbaseOperations2 hbaseOperations2; + + @Autowired + @Qualifier("agentStatMapper") + private RowMapper> agentStatMapper; - @Autowired - @Qualifier("agentStatMapper") - private RowMapper> agentStatMapper; - @Autowired @Qualifier("agentStatRowKeyDistributor") private AbstractRowKeyDistributor rowKeyDistributor; - private int scanCacheSize = 256; + private int scanCacheSize = 256; - public void setScanCacheSize(int scanCacheSize) { - this.scanCacheSize = scanCacheSize; - } - - public List scanAgentStatList(String agentId, Range range) { + public void setScanCacheSize(int scanCacheSize) { + this.scanCacheSize = scanCacheSize; + } + + public List scanAgentStatList(String agentId, Range range) { if (agentId == null) { throw new NullPointerException("agentId must not be null"); } @@ -57,85 +59,86 @@ public class HbaseAgentStatDao implements AgentStatDao { } if (logger.isDebugEnabled()) { - logger.debug("scanAgentStat : agentId={}, {}", agentId, range); - } - + logger.debug("scanAgentStat : agentId={}, {}", agentId, range); + } - Scan scan = createScan(agentId, range); - - List> intermediate = hbaseOperations2.find(HBaseTables.AGENT_STAT, scan, rowKeyDistributor, agentStatMapper); - - int expectedSize = (int)(range.getRange() / 5000); // 5초간 데이터 - List merged = new ArrayList(expectedSize); - - for(List each : intermediate) { + + Scan scan = createScan(agentId, range); + + List> intermediate = hbaseOperations2.find(HBaseTables.AGENT_STAT, scan, rowKeyDistributor, agentStatMapper); + + int expectedSize = (int)(range.getRange() / 5000); // 5초간 데이터 + List merged = new ArrayList(expectedSize); + + for(List each : intermediate) { merged.addAll(each); } - + return merged; - } - - /** - * timestamp 기반의 row key를 만든다. - * FIXME collector에 있는 DAO에도 동일한 코드가 중복되어 있으니 참고. - */ - private byte[] getRowKey(String agentId, long timestamp) { - if (agentId == null) { - throw new IllegalArgumentException("agentId must not null"); - } - byte[] bAgentId = BytesUtils.toBytes(agentId); - return RowKeyUtils.concatFixedByteAndLong(bAgentId, AGENT_NAME_MAX_LEN, TimeUtils.reverseTimeMillis(timestamp)); - } + } - private Scan createScan(String agentId, Range range) { - Scan scan = new Scan(); - scan.setCaching(this.scanCacheSize); + /** + * timestamp 기반의 row key를 만든다. + * FIXME collector에 있는 DAO에도 동일한 코드가 중복되어 있으니 참고. + */ + private byte[] getRowKey(String agentId, long timestamp) { + if (agentId == null) { + throw new IllegalArgumentException("agentId must not null"); + } + byte[] bAgentId = BytesUtils.toBytes(agentId); + return RowKeyUtils.concatFixedByteAndLong(bAgentId, AGENT_NAME_MAX_LEN, TimeUtils.reverseTimeMillis(timestamp)); + } - byte[] startKey = getRowKey(agentId, range.getFrom()); - byte[] endKey = getRowKey(agentId, range.getTo()); + private Scan createScan(String agentId, Range range) { + Scan scan = new Scan(); + scan.setCaching(this.scanCacheSize); - // key가 reverse되었기 떄문에 start, end가 뒤바뀌게 된다. - scan.setStartRow(endKey); - scan.setStopRow(startKey); + byte[] startKey = getRowKey(agentId, range.getFrom()); + byte[] endKey = getRowKey(agentId, range.getTo()); - scan.addColumn(HBaseTables.AGENT_STAT_CF_STATISTICS, HBaseTables.AGENT_STAT_CF_STATISTICS_V1); - scan.setId("AgentStatScan"); + // key가 reverse되었기 떄문에 start, end가 뒤바뀌게 된다. + scan.setStartRow(endKey); + scan.setStopRow(startKey); - // json으로 변화해서 로그를 찍어서. 최초 변환 속도가 느림. - logger.debug("create scan:{}", scan); - return scan; - } + // scan.addColumn(HBaseTables.AGENT_STAT_CF_STATISTICS, HBaseTables.AGENT_STAT_CF_STATISTICS_V1); + scan.addFamily(HBaseTables.AGENT_STAT_CF_STATISTICS); + scan.setId("AgentStatScan"); + + // json으로 변화해서 로그를 찍어서. 최초 변환 속도가 느림. + logger.debug("create scan:{}", scan); + return scan; + } + + // public List scanAgentStatList(String agentId, long start, long end, final int limit) { + // if (logger.isDebugEnabled()) { + // logger.debug("scanAgentStatList"); + // } + // Scan scan = createScan(agentId, start, end); + // + // List list = hbaseOperations2.find(HBaseTables.AGENT_STAT, scan, rowKeyDistributor, new ResultsExtractor>() { + // @Override + // public List extractData(ResultScanner results) throws Exception { + // TDeserializer deserializer = new TDeserializer(); + // List list = new ArrayList(); + // for (Result result : results) { + // if (result == null) { + // continue; + // } + // + // if (list.size() >= limit) { + // break; + // } + // + // for (KeyValue kv : result.raw()) { + // AgentStat agentStat = new AgentStat(); + // deserializer.deserialize(agentStat, kv.getBuffer()); + // list.add(agentStat); + // } + // } + // return list; + // } + // }); + // return list; + // } -// public List scanAgentStatList(String agentId, long start, long end, final int limit) { -// if (logger.isDebugEnabled()) { -// logger.debug("scanAgentStatList"); -// } -// Scan scan = createScan(agentId, start, end); -// -// List list = hbaseOperations2.find(HBaseTables.AGENT_STAT, scan, rowKeyDistributor, new ResultsExtractor>() { -// @Override -// public List extractData(ResultScanner results) throws Exception { -// TDeserializer deserializer = new TDeserializer(); -// List list = new ArrayList(); -// for (Result result : results) { -// if (result == null) { -// continue; -// } -// -// if (list.size() >= limit) { -// break; -// } -// -// for (KeyValue kv : result.raw()) { -// AgentStat agentStat = new AgentStat(); -// deserializer.deserialize(agentStat, kv.getBuffer()); -// list.add(agentStat); -// } -// } -// return list; -// } -// }); -// return list; -// } - } diff --git a/src/main/java/com/nhn/pinpoint/web/mapper/AgentStatMapper.java b/src/main/java/com/nhn/pinpoint/web/mapper/AgentStatMapper.java index b8f71ca5a..88e87c0fc 100644 --- a/src/main/java/com/nhn/pinpoint/web/mapper/AgentStatMapper.java +++ b/src/main/java/com/nhn/pinpoint/web/mapper/AgentStatMapper.java @@ -1,13 +1,24 @@ package com.nhn.pinpoint.web.mapper; +import static com.nhn.pinpoint.common.hbase.HBaseTables.AGENT_STAT_CF_STATISTICS; +import static com.nhn.pinpoint.common.hbase.HBaseTables.AGENT_STAT_CF_STATISTICS_V1; +import static com.nhn.pinpoint.common.hbase.HBaseTables.AGENT_STAT_CF_STATISTICS_MEMORY_GC; +import static com.nhn.pinpoint.common.hbase.HBaseTables.AGENT_STAT_CF_STATISTICS_CPU_LOAD; + import java.util.ArrayList; import java.util.Collections; import java.util.List; +import java.util.Map; +import com.nhn.pinpoint.common.bo.AgentStatCpuLoadBo; +import com.nhn.pinpoint.common.bo.AgentStatMemoryGcBo; import com.nhn.pinpoint.thrift.dto.TAgentStat; -import org.apache.hadoop.hbase.KeyValue; +import com.nhn.pinpoint.thrift.dto.TJvmGc; +import com.nhn.pinpoint.web.vo.AgentStat; + import org.apache.hadoop.hbase.client.Result; 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.data.hadoop.hbase.RowMapper; @@ -15,30 +26,55 @@ import org.springframework.stereotype.Component; /** * @author harebox + * @author hyungil.jeong */ @Component -public class AgentStatMapper implements RowMapper> { +public class AgentStatMapper implements RowMapper> { - private TProtocolFactory factory = new TCompactProtocol.Factory(); - - public List mapRow(Result result, int rowNum) throws Exception { - if (result.isEmpty()) { - return Collections.emptyList(); - } - - KeyValue[] raw = result.raw(); - List list = new ArrayList(raw.length); - - // CompactProtocol을 사용하고 있음. - TDeserializer deserializer = new TDeserializer(factory); + private TProtocolFactory factory = new TCompactProtocol.Factory(); - for (KeyValue kv : raw) { - TAgentStat each = new TAgentStat(); - deserializer.deserialize(each, kv.getValue()); - list.add(each); - } + public List mapRow(Result result, int rowNum) throws Exception { + if (result.isEmpty()) { + return Collections.emptyList(); + } - return list; - } + Map qualifierMap = result.getFamilyMap(AGENT_STAT_CF_STATISTICS); + // FIXME (2014.08) Legacy support for TAgentStat Thrift DTO stored directly into hbase. + if (qualifierMap.containsKey(AGENT_STAT_CF_STATISTICS_V1)) { + return readAgentStatThriftDto(qualifierMap.get(AGENT_STAT_CF_STATISTICS_V1)); + } + + AgentStat agentStat = new AgentStat(); + if (qualifierMap.containsKey(AGENT_STAT_CF_STATISTICS_MEMORY_GC)) { + agentStat.setMemoryGc(new AgentStatMemoryGcBo.Builder(qualifierMap.get(AGENT_STAT_CF_STATISTICS_MEMORY_GC)).build()); + } + if (qualifierMap.containsKey(AGENT_STAT_CF_STATISTICS_CPU_LOAD)) { + agentStat.setCpuLoad(new AgentStatCpuLoadBo.Builder(qualifierMap.get(AGENT_STAT_CF_STATISTICS_CPU_LOAD)).build()); + } + List agentStats = new ArrayList(); + agentStats.add(agentStat); + return agentStats; + } + + // FIXME (2014.08) Legacy support for TAgentStat Thrift DTO stored directly into hbase. + private List readAgentStatThriftDto(byte[] tAgentStatByteArray) throws TException { + // CompactProtocol을 사용하고 있음. + TDeserializer deserializer = new TDeserializer(factory); + TAgentStat tAgentStat = new TAgentStat(); + deserializer.deserialize(tAgentStat, tAgentStatByteArray); + TJvmGc gc = tAgentStat.getGc(); + + AgentStatMemoryGcBo.Builder memoryGcBoBuilder = new AgentStatMemoryGcBo.Builder(tAgentStat.getAgentId(), tAgentStat.getStartTimestamp(), tAgentStat.getTimestamp()); + memoryGcBoBuilder.gcType(gc.getType().name()); + memoryGcBoBuilder.jvmMemoryHeapUsed(gc.getJvmMemoryHeapUsed()).jvmMemoryHeapMax(gc.getJvmMemoryHeapMax()); + memoryGcBoBuilder.jvmMemoryNonHeapUsed(gc.getJvmMemoryNonHeapUsed()).jvmMemoryNonHeapMax(gc.getJvmMemoryNonHeapMax()); + memoryGcBoBuilder.jvmGcOldCount(gc.getJvmGcOldCount()).jvmGcOldTime(gc.getJvmGcOldTime()); + + AgentStat agentStat = new AgentStat(); + agentStat.setMemoryGc(memoryGcBoBuilder.build()); + List result = new ArrayList(1); + result.add(agentStat); + return result; + } } diff --git a/src/main/java/com/nhn/pinpoint/web/service/AgentStatService.java b/src/main/java/com/nhn/pinpoint/web/service/AgentStatService.java index ddea77595..ad234c86d 100644 --- a/src/main/java/com/nhn/pinpoint/web/service/AgentStatService.java +++ b/src/main/java/com/nhn/pinpoint/web/service/AgentStatService.java @@ -2,17 +2,20 @@ package com.nhn.pinpoint.web.service; import java.util.List; -import com.nhn.pinpoint.thrift.dto.TAgentStat; +import com.nhn.pinpoint.web.vo.AgentStat; import com.nhn.pinpoint.web.vo.Range; +/** + * @author hyungil.jeong + */ public interface AgentStatService { - /** - * 주어진 시간 범위에 따라 특정 agentId에 해당하는 시스템 통계 정보를 조회한다. - * @param agentId - * @param range - * @return - */ - List selectAgentStatList(String agentId, Range range); - + /** + * 주어진 시간 범위에 따라 특정 agentId에 해당하는 시스템 통계 정보를 조회한다. + * @param agentId + * @param range + * @return + */ + List selectAgentStatList(String agentId, Range range); + } diff --git a/src/main/java/com/nhn/pinpoint/web/service/AgentStatServiceImpl.java b/src/main/java/com/nhn/pinpoint/web/service/AgentStatServiceImpl.java index 486d37b06..cd40ac0f1 100644 --- a/src/main/java/com/nhn/pinpoint/web/service/AgentStatServiceImpl.java +++ b/src/main/java/com/nhn/pinpoint/web/service/AgentStatServiceImpl.java @@ -2,8 +2,9 @@ package com.nhn.pinpoint.web.service; import java.util.List; -import com.nhn.pinpoint.thrift.dto.TAgentStat; +import com.nhn.pinpoint.web.vo.AgentStat; import com.nhn.pinpoint.web.vo.Range; + import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; @@ -11,18 +12,19 @@ import com.nhn.pinpoint.web.dao.AgentStatDao; /** * @author harebox + * @author hyungil.jeong */ @Service public class AgentStatServiceImpl implements AgentStatService { - - @Autowired - private AgentStatDao agentStatDao; - public List selectAgentStatList(String agentId, Range range) { + @Autowired + private AgentStatDao agentStatDao; + + public List selectAgentStatList(String agentId, Range range) { if (agentId == null) { throw new NullPointerException("agentId must not be null"); } return agentStatDao.scanAgentStatList(agentId, range); - } + } } diff --git a/src/main/java/com/nhn/pinpoint/web/vo/AgentStat.java b/src/main/java/com/nhn/pinpoint/web/vo/AgentStat.java new file mode 100644 index 000000000..d12838405 --- /dev/null +++ b/src/main/java/com/nhn/pinpoint/web/vo/AgentStat.java @@ -0,0 +1,29 @@ +package com.nhn.pinpoint.web.vo; + +import com.nhn.pinpoint.common.bo.AgentStatCpuLoadBo; +import com.nhn.pinpoint.common.bo.AgentStatMemoryGcBo; + +/** + * @author hyungil.jeong + */ +public class AgentStat { + + private AgentStatMemoryGcBo memoryGc; + private AgentStatCpuLoadBo cpuLoad; + + public AgentStatMemoryGcBo getMemoryGc() { + return memoryGc; + } + + public void setMemoryGc(AgentStatMemoryGcBo memoryGc) { + this.memoryGc = memoryGc; + } + + public AgentStatCpuLoadBo getCpuLoad() { + return cpuLoad; + } + + public void setCpuLoad(AgentStatCpuLoadBo cpuLoad) { + this.cpuLoad = cpuLoad; + } +} diff --git a/src/main/java/com/nhn/pinpoint/web/vo/linechart/Chart.java b/src/main/java/com/nhn/pinpoint/web/vo/linechart/Chart.java index 9236ab271..0e8140c8c 100644 --- a/src/main/java/com/nhn/pinpoint/web/vo/linechart/Chart.java +++ b/src/main/java/com/nhn/pinpoint/web/vo/linechart/Chart.java @@ -5,53 +5,53 @@ import java.util.List; public abstract class Chart { - private String title; - private String xAxisName; - private String yAxisName; + private String title; + private String xAxisName; + private String yAxisName; - public String getTitle() { - return title; - } + public String getTitle() { + return title; + } - public void setTitle(String title) { - this.title = title; - } + public void setTitle(String title) { + this.title = title; + } - public void setXAxisName(String name) { - this.xAxisName = name; - } + public void setXAxisName(String name) { + this.xAxisName = name; + } - public void setYAxisName(String name) { - this.yAxisName = name; - } + public void setYAxisName(String name) { + this.yAxisName = name; + } - public String getxAxisName() { - return xAxisName; - } + public String getxAxisName() { + return xAxisName; + } - public void setxAxisName(String xAxisName) { - this.xAxisName = xAxisName; - } + public void setxAxisName(String xAxisName) { + this.xAxisName = xAxisName; + } - public String getyAxisName() { - return yAxisName; - } + public String getyAxisName() { + return yAxisName; + } - public void setyAxisName(String yAxisName) { - this.yAxisName = yAxisName; - } - - public static final class Points { - - private List points = new LinkedList(); + public void setyAxisName(String yAxisName) { + this.yAxisName = yAxisName; + } - public Points() { - } + public static final class Points { - public List getPoints() { - return points; - } + private List points = new LinkedList(); - } + public Points() { + } + + public List getPoints() { + return points; + } + + } } diff --git a/src/main/java/com/nhn/pinpoint/web/vo/linechart/LineChart.java b/src/main/java/com/nhn/pinpoint/web/vo/linechart/LineChart.java index b8d4df21b..2bd731c23 100644 --- a/src/main/java/com/nhn/pinpoint/web/vo/linechart/LineChart.java +++ b/src/main/java/com/nhn/pinpoint/web/vo/linechart/LineChart.java @@ -2,24 +2,22 @@ package com.nhn.pinpoint.web.vo.linechart; import java.util.List; -public class LineChart extends Chart { +public abstract class LineChart extends Chart { - protected Chart.Points points; + protected Chart.Points points; - public LineChart() { - this.points = new Points(); - } - - public void addPoint(Long[] point) { - points.getPoints().add(point); - } + public LineChart() { + this.points = new Points(); + } - public void setPoints(Points points) { - this.points = points; - } - - public List getPoints() { - return this.points.getPoints(); - } + public abstract void addPoint(X xVal, Y yVal); + + public void setPoints(Points points) { + this.points = points; + } + + public List getPoints() { + return this.points.getPoints(); + } } diff --git a/src/main/java/com/nhn/pinpoint/web/vo/linechart/SampledDoubleLineChart.java b/src/main/java/com/nhn/pinpoint/web/vo/linechart/SampledDoubleLineChart.java new file mode 100644 index 000000000..a89916e8d --- /dev/null +++ b/src/main/java/com/nhn/pinpoint/web/vo/linechart/SampledDoubleLineChart.java @@ -0,0 +1,37 @@ +package com.nhn.pinpoint.web.vo.linechart; + +/** + * @author hyungil.jeong + */ +public class SampledDoubleLineChart extends LineChart { + + int sampleRate; + int sampleIndex; + Double[] sampleBuffer; + + public SampledDoubleLineChart(int sampleRate) { + this.sampleRate = sampleRate; + this.sampleBuffer = new Double[sampleRate]; + this.sampleIndex = 0; + } + + @Override + public void addPoint(Long xVal, Double yVal) { + sampleBuffer[sampleIndex++] = yVal; + + // FIXME 선택 가능하게. 모두 다 하는 경우에는 그냥 메소드 한번으로 끝낼 수도 있지만 일단... + if (sampleIndex == sampleRate) { + // point[x, minY, maxY, avgY] + Number[] samplePoint = new Number[4]; + samplePoint[0] = xVal; + samplePoint[1] = DownSamplers.MIN.sampleDouble(sampleBuffer); + samplePoint[2] = DownSamplers.MAX.sampleDouble(sampleBuffer); + samplePoint[3] = DownSamplers.AVG.sampleDouble(sampleBuffer); + + getPoints().add(samplePoint); + sampleIndex = 0; + } + } + + +} diff --git a/src/main/java/com/nhn/pinpoint/web/vo/linechart/SampledLineChart.java b/src/main/java/com/nhn/pinpoint/web/vo/linechart/SampledLineChart.java deleted file mode 100644 index 805b0486d..000000000 --- a/src/main/java/com/nhn/pinpoint/web/vo/linechart/SampledLineChart.java +++ /dev/null @@ -1,40 +0,0 @@ -package com.nhn.pinpoint.web.vo.linechart; - -import java.security.InvalidParameterException; - - -public final class SampledLineChart extends LineChart { - - int sampleRate; - int sampleIndex; - Long[] sampleBuffer; - - public SampledLineChart(int sampleRate) { - this.sampleRate = sampleRate; - this.sampleBuffer = new Long[sampleRate]; - this.sampleIndex = 0; - } - - @Override - public void addPoint(Long[] point) { - if (point == null || point.length != 2) { - throw new InvalidParameterException("point array should be Number[2]"); - } - - sampleBuffer[sampleIndex++] = point[1]; - - // FIXME 선택 가능하게. 모두 다 하는 경우에는 그냥 메소드 한번으로 끝낼 수도 있지만 일단... - if (sampleIndex == sampleRate) { - // point[x, minY, maxY, avgY] - Long[] samplePoint = new Long[4]; - samplePoint[0] = point[0]; - samplePoint[1] = DownSamplers.MIN.sampleLong(sampleBuffer); - samplePoint[2] = DownSamplers.MAX.sampleLong(sampleBuffer); - samplePoint[3] = DownSamplers.AVG.sampleLong(sampleBuffer); - - getPoints().add(samplePoint); - sampleIndex = 0; - } - } - -} diff --git a/src/main/java/com/nhn/pinpoint/web/vo/linechart/SampledLongLineChart.java b/src/main/java/com/nhn/pinpoint/web/vo/linechart/SampledLongLineChart.java new file mode 100644 index 000000000..03db726bf --- /dev/null +++ b/src/main/java/com/nhn/pinpoint/web/vo/linechart/SampledLongLineChart.java @@ -0,0 +1,36 @@ +package com.nhn.pinpoint.web.vo.linechart; + +/** + * @author hyungil.jeong + */ +public final class SampledLongLineChart extends LineChart { + + int sampleRate; + int sampleIndex; + Long[] sampleBuffer; + + public SampledLongLineChart(int sampleRate) { + this.sampleRate = sampleRate; + this.sampleBuffer = new Long[sampleRate]; + this.sampleIndex = 0; + } + + @Override + public void addPoint(Long xVal, Long yVal) { + sampleBuffer[sampleIndex++] = yVal; + + // FIXME 선택 가능하게. 모두 다 하는 경우에는 그냥 메소드 한번으로 끝낼 수도 있지만 일단... + if (sampleIndex == sampleRate) { + // point[x, minY, maxY, avgY] + Number[] samplePoint = new Number[4]; + samplePoint[0] = xVal; + samplePoint[1] = DownSamplers.MIN.sampleLong(sampleBuffer); + samplePoint[2] = DownSamplers.MAX.sampleLong(sampleBuffer); + samplePoint[3] = DownSamplers.AVG.sampleLong(sampleBuffer); + + getPoints().add(samplePoint); + sampleIndex = 0; + } + } + +} diff --git a/src/main/java/com/nhn/pinpoint/web/vo/linechart/agentstat/AgentStatChartGroup.java b/src/main/java/com/nhn/pinpoint/web/vo/linechart/agentstat/AgentStatChartGroup.java index 2b6a322bf..910398c90 100644 --- a/src/main/java/com/nhn/pinpoint/web/vo/linechart/agentstat/AgentStatChartGroup.java +++ b/src/main/java/com/nhn/pinpoint/web/vo/linechart/agentstat/AgentStatChartGroup.java @@ -1,60 +1,109 @@ package com.nhn.pinpoint.web.vo.linechart.agentstat; import java.util.HashMap; +import java.util.Iterator; +import java.util.List; import java.util.Map; -import com.nhn.pinpoint.thrift.dto.TAgentStat; -import com.nhn.pinpoint.thrift.dto.TJvmGc; +import org.springframework.util.CollectionUtils; + +import com.nhn.pinpoint.common.bo.AgentStatCpuLoadBo; +import com.nhn.pinpoint.common.bo.AgentStatMemoryGcBo; +import com.nhn.pinpoint.web.vo.AgentStat; import com.nhn.pinpoint.web.vo.linechart.LineChart; -import com.nhn.pinpoint.web.vo.linechart.SampledLineChart; +import com.nhn.pinpoint.web.vo.linechart.SampledDoubleLineChart; +import com.nhn.pinpoint.web.vo.linechart.SampledLongLineChart; /** * @author harebox + * @author hyungil.jeong */ public class AgentStatChartGroup { - private String type; - private Map charts = new HashMap(); - - public void addData(TAgentStat data, int sampleRate) { - if (data == null) { - return; - } + private static final String JVM_MEMORY_HEAP_USED_KEY = "jvmMemoryHeapUsed"; + private static final String JVM_MEMORY_HEAP_MAX_KEY = "jvmMemoryHeapMax"; + private static final String JVM_MEMORY_NON_HEAP_USED_KEY = "jvmMemoryNonHeapUsed"; + private static final String JVM_MEMORY_NON_HEAP_MAX_KEY = "jvmMemoryNonHeapMax"; + private static final String JVM_GC_OLD_COUNT_KEY = "jvmGcOldCount"; + private static final String JVM_GC_OLD_TIME_KEY = "jvmGcOldTime"; - // 먼저 메시지에 포함된 데이터 타입을 알아낸다. - TJvmGc gc = data.getGc(); - - for (TJvmGc._Fields each : TJvmGc.metaDataMap.keySet()) { - Object fieldValue = gc.getFieldValue(each); - if (! (fieldValue instanceof Long)) { - continue; - } - - if (! charts.containsKey(each.getFieldName())) { - charts.put(each.getFieldName(), new SampledLineChart(sampleRate)); - } - - LineChart chart = charts.get(each.getFieldName()); - chart.addPoint(new Long[]{ data.getTimestamp(), (Long) fieldValue }); - } - - this.type = gc.getType().name(); - } + private static final String CPU_LOAD_JVM_KEY = "jvmCpuLoad"; + private static final String CPU_LOAD_SYSTEM_KEY = "systemCpuLoad"; - public String getType() { - return type; - } + private String type; + private Map> charts = new HashMap>(); - public void setType(String type) { - this.type = type; - } + public AgentStatChartGroup(int sampleRate) { + charts.put(JVM_MEMORY_HEAP_USED_KEY, new SampledLongLineChart(sampleRate)); + charts.put(JVM_MEMORY_HEAP_MAX_KEY, new SampledLongLineChart(sampleRate)); + charts.put(JVM_MEMORY_NON_HEAP_USED_KEY, new SampledLongLineChart(sampleRate)); + charts.put(JVM_MEMORY_NON_HEAP_MAX_KEY, new SampledLongLineChart(sampleRate)); + charts.put(JVM_GC_OLD_COUNT_KEY, new SampledLongLineChart(sampleRate)); + charts.put(JVM_GC_OLD_TIME_KEY, new SampledLongLineChart(sampleRate)); + charts.put(CPU_LOAD_JVM_KEY, new SampledDoubleLineChart(sampleRate)); + charts.put(CPU_LOAD_SYSTEM_KEY, new SampledDoubleLineChart(sampleRate)); + } - public Map getCharts() { - return charts; - } + public void addAgentStats(List agentStats) { + for (AgentStat agentStat : agentStats) { + addMemoryGcData(agentStat.getMemoryGc()); + addCpuLoadData(agentStat.getCpuLoad()); + } + removeUncollectedCharts(); + } - public void setCharts(Map charts) { - this.charts = charts; - } + private void addMemoryGcData(AgentStatMemoryGcBo data) { + if (data == null) { + return; + } + this.type = data.getGcType(); + long timestamp = data.getTimestamp(); + ((SampledLongLineChart)charts.get(JVM_MEMORY_HEAP_USED_KEY)).addPoint(timestamp, data.getJvmMemoryHeapUsed()); + ((SampledLongLineChart)charts.get(JVM_MEMORY_HEAP_MAX_KEY)).addPoint(timestamp, data.getJvmMemoryHeapMax()); + ((SampledLongLineChart)charts.get(JVM_MEMORY_NON_HEAP_USED_KEY)).addPoint(timestamp, data.getJvmMemoryNonHeapUsed()); + ((SampledLongLineChart)charts.get(JVM_MEMORY_NON_HEAP_MAX_KEY)).addPoint(timestamp, data.getJvmMemoryNonHeapMax()); + ((SampledLongLineChart)charts.get(JVM_GC_OLD_COUNT_KEY)).addPoint(timestamp, data.getJvmGcOldCount()); + ((SampledLongLineChart)charts.get(JVM_GC_OLD_TIME_KEY)).addPoint(timestamp, data.getJvmGcOldTime()); + } + + private void addCpuLoadData(AgentStatCpuLoadBo data) { + if (data == null) { + return; + } + long timestamp = data.getTimestamp(); + double jvmCpuLoadPercentage = data.getJvmCpuLoad() * 100; + double systemCpuLoadPercentage = data.getSystemCpuLoad() * 100; + if (!(jvmCpuLoadPercentage < 0)) { + ((SampledDoubleLineChart)charts.get(CPU_LOAD_JVM_KEY)).addPoint(timestamp, jvmCpuLoadPercentage); + } + if (!(systemCpuLoadPercentage < 0)) { + ((SampledDoubleLineChart)charts.get(CPU_LOAD_SYSTEM_KEY)).addPoint(timestamp, systemCpuLoadPercentage); + } + } + + private void removeUncollectedCharts() { + for (Iterator>> iter = charts.entrySet().iterator(); iter.hasNext();) { + Map.Entry> chartEntry = iter.next(); + if (CollectionUtils.isEmpty(chartEntry.getValue().getPoints())) { + iter.remove(); + } + } + } + + public String getType() { + return type; + } + + public void setType(String type) { + this.type = type; + } + + public Map> getCharts() { + return charts; + } + + public void setCharts(Map> charts) { + this.charts = charts; + } } \ No newline at end of file diff --git a/src/test/java/com/nhn/pinpoint/web/dao/hbase/HbaseAgentStatDaoTest.java b/src/test/java/com/nhn/pinpoint/web/dao/hbase/HbaseAgentStatDaoTest.java index 1bf102b4c..4b5eae677 100644 --- a/src/test/java/com/nhn/pinpoint/web/dao/hbase/HbaseAgentStatDaoTest.java +++ b/src/test/java/com/nhn/pinpoint/web/dao/hbase/HbaseAgentStatDaoTest.java @@ -2,8 +2,9 @@ package com.nhn.pinpoint.web.dao.hbase; import java.util.List; -import com.nhn.pinpoint.thrift.dto.TAgentStat; +import com.nhn.pinpoint.web.vo.AgentStat; import com.nhn.pinpoint.web.vo.Range; + import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.beans.factory.annotation.Autowired; @@ -12,20 +13,21 @@ import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; /** * @author harebox + * @author hyungil.jeong */ @RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration("classpath:applicationContext.xml") public class HbaseAgentStatDaoTest { - @Autowired - private HbaseAgentStatDao dao; - - @Test - public void selectAgentStat() { - long timestamp = System.currentTimeMillis(); + @Autowired + private HbaseAgentStatDao dao; + + @Test + public void selectAgentStat() { + long timestamp = System.currentTimeMillis(); Range range = new Range(timestamp - 100000, timestamp); - List result = dao.scanAgentStatList("FRONT-WEB1", range); - System.out.println(result); - } - + List result = dao.scanAgentStatList("FRONT-WEB1", range); + System.out.println(result); + } + } diff --git a/src/test/java/com/nhn/pinpoint/web/vo/linechart/SampledLineChartTest.java b/src/test/java/com/nhn/pinpoint/web/vo/linechart/SampledLineChartTest.java index 69dca9a67..8ccd7ca32 100644 --- a/src/test/java/com/nhn/pinpoint/web/vo/linechart/SampledLineChartTest.java +++ b/src/test/java/com/nhn/pinpoint/web/vo/linechart/SampledLineChartTest.java @@ -4,25 +4,47 @@ import static org.junit.Assert.assertTrue; import org.codehaus.jackson.map.ObjectMapper; import org.junit.Test; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; public class SampledLineChartTest { - @Test - public void tdd() throws Exception { - int sampleRate = 60; - int totalPoints = 10000; - - LineChart lineChart = new SampledLineChart(sampleRate); - - for (long i = 0; i < totalPoints; i++) { - lineChart.addPoint(new Long[]{i, i}); - } - - assertTrue(lineChart.getPoints().size() == totalPoints / sampleRate); - - ObjectMapper mapper = new ObjectMapper(); - String result = mapper.writeValueAsString(lineChart); - System.out.println(result); - } + private final Logger logger = LoggerFactory.getLogger(this.getClass()); + + @Test + public void testSampledLongLineChart() throws Exception { + int sampleRate = 60; + int totalPoints = 10000; + + SampledLongLineChart lineChart = new SampledLongLineChart(sampleRate); + + for (long i = 0; i < totalPoints; i++) { + lineChart.addPoint(i, i); + } + + assertTrue(lineChart.getPoints().size() == totalPoints / sampleRate); + + ObjectMapper mapper = new ObjectMapper(); + String result = mapper.writeValueAsString(lineChart); + logger.debug(result); + } + + @Test + public void testSampledDoubleLineChart() throws Exception { + int sampleRate = 60; + int totalPoints = 10000; + + SampledDoubleLineChart lineChart = new SampledDoubleLineChart(sampleRate); + + for (long i = 0; i < totalPoints; i++) { + lineChart.addPoint(i, (double)i); + } + + assertTrue(lineChart.getPoints().size() == totalPoints / sampleRate); + + ObjectMapper mapper = new ObjectMapper(); + String result = mapper.writeValueAsString(lineChart); + logger.debug(result); + } }