mirror of
https://github.com/wahyd4/pinpoint.git
synced 2026-08-20 10:16:13 +10:00
Merge branch 'hyungil.jeong/pinpoint-profiler/issue-73' of hyungil.jeong/pinpoint-web
from pull-request 3 * refs/heads/hyungil.jeong/pinpoint-profiler/issue-73: [Pinpoint/pinpoint-profiler#73] Added support for AgentStats batch. Reviewed-by: 정현길 <hyungil.jeong@navercorp.com>
This commit is contained in:
@@ -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<TAgentStat> agentStatList = agentStatService.selectAgentStatList(agentId, range);
|
||||
watch.stop();
|
||||
|
||||
if (logger.isInfoEnabled()) {
|
||||
logger.info("getAgentStat(agentId={}, from={}, to={}) : {}ms", agentId, from, to, watch.getLastTaskTimeMillis());
|
||||
}
|
||||
List<AgentStat> 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<String, List<AgentInfoBo>> 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<String, List<AgentInfoBo>> applicationAgentList = agentInfoService.getApplicationAgentList(applicationName, range);
|
||||
return applicationAgentList;
|
||||
}
|
||||
SortedMap<String, List<AgentInfoBo>> applicationAgentList = agentInfoService.getApplicationAgentList(applicationName, range);
|
||||
return applicationAgentList;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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<TAgentStat> scanAgentStatList(String agentId, Range range);
|
||||
// List<AgentStat> scanAgentStatList(String agentId, long start, long end, final int limit);
|
||||
|
||||
|
||||
List<AgentStat> scanAgentStatList(String agentId, Range range);
|
||||
|
||||
}
|
||||
|
||||
@@ -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<List<AgentStat>> agentStatMapper;
|
||||
|
||||
@Autowired
|
||||
@Qualifier("agentStatMapper")
|
||||
private RowMapper<List<TAgentStat>> 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<TAgentStat> scanAgentStatList(String agentId, Range range) {
|
||||
public void setScanCacheSize(int scanCacheSize) {
|
||||
this.scanCacheSize = scanCacheSize;
|
||||
}
|
||||
|
||||
public List<AgentStat> 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<List<TAgentStat>> intermediate = hbaseOperations2.find(HBaseTables.AGENT_STAT, scan, rowKeyDistributor, agentStatMapper);
|
||||
|
||||
int expectedSize = (int)(range.getRange() / 5000); // 5초간 데이터
|
||||
List<TAgentStat> merged = new ArrayList<TAgentStat>(expectedSize);
|
||||
|
||||
for(List<TAgentStat> each : intermediate) {
|
||||
|
||||
Scan scan = createScan(agentId, range);
|
||||
|
||||
List<List<AgentStat>> intermediate = hbaseOperations2.find(HBaseTables.AGENT_STAT, scan, rowKeyDistributor, agentStatMapper);
|
||||
|
||||
int expectedSize = (int)(range.getRange() / 5000); // 5초간 데이터
|
||||
List<AgentStat> merged = new ArrayList<AgentStat>(expectedSize);
|
||||
|
||||
for(List<AgentStat> 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<AgentStat> scanAgentStatList(String agentId, long start, long end, final int limit) {
|
||||
// if (logger.isDebugEnabled()) {
|
||||
// logger.debug("scanAgentStatList");
|
||||
// }
|
||||
// Scan scan = createScan(agentId, start, end);
|
||||
//
|
||||
// List<AgentStat> list = hbaseOperations2.find(HBaseTables.AGENT_STAT, scan, rowKeyDistributor, new ResultsExtractor<List<AgentStat>>() {
|
||||
// @Override
|
||||
// public List<AgentStat> extractData(ResultScanner results) throws Exception {
|
||||
// TDeserializer deserializer = new TDeserializer();
|
||||
// List<AgentStat> list = new ArrayList<AgentStat>();
|
||||
// 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<AgentStat> scanAgentStatList(String agentId, long start, long end, final int limit) {
|
||||
// if (logger.isDebugEnabled()) {
|
||||
// logger.debug("scanAgentStatList");
|
||||
// }
|
||||
// Scan scan = createScan(agentId, start, end);
|
||||
//
|
||||
// List<AgentStat> list = hbaseOperations2.find(HBaseTables.AGENT_STAT, scan, rowKeyDistributor, new ResultsExtractor<List<AgentStat>>() {
|
||||
// @Override
|
||||
// public List<AgentStat> extractData(ResultScanner results) throws Exception {
|
||||
// TDeserializer deserializer = new TDeserializer();
|
||||
// List<AgentStat> list = new ArrayList<AgentStat>();
|
||||
// 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;
|
||||
// }
|
||||
|
||||
}
|
||||
|
||||
@@ -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<List<TAgentStat>> {
|
||||
public class AgentStatMapper implements RowMapper<List<AgentStat>> {
|
||||
|
||||
private TProtocolFactory factory = new TCompactProtocol.Factory();
|
||||
|
||||
public List<TAgentStat> mapRow(Result result, int rowNum) throws Exception {
|
||||
if (result.isEmpty()) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
KeyValue[] raw = result.raw();
|
||||
List<TAgentStat> list = new ArrayList<TAgentStat>(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<AgentStat> mapRow(Result result, int rowNum) throws Exception {
|
||||
if (result.isEmpty()) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
return list;
|
||||
}
|
||||
Map<byte[], byte[]> 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<AgentStat> agentStats = new ArrayList<AgentStat>();
|
||||
agentStats.add(agentStat);
|
||||
return agentStats;
|
||||
}
|
||||
|
||||
// FIXME (2014.08) Legacy support for TAgentStat Thrift DTO stored directly into hbase.
|
||||
private List<AgentStat> 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<AgentStat> result = new ArrayList<AgentStat>(1);
|
||||
result.add(agentStat);
|
||||
return result;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -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<TAgentStat> selectAgentStatList(String agentId, Range range);
|
||||
|
||||
/**
|
||||
* 주어진 시간 범위에 따라 특정 agentId에 해당하는 시스템 통계 정보를 조회한다.
|
||||
* @param agentId
|
||||
* @param range
|
||||
* @return
|
||||
*/
|
||||
List<AgentStat> selectAgentStatList(String agentId, Range range);
|
||||
|
||||
}
|
||||
|
||||
@@ -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<TAgentStat> selectAgentStatList(String agentId, Range range) {
|
||||
@Autowired
|
||||
private AgentStatDao agentStatDao;
|
||||
|
||||
public List<AgentStat> selectAgentStatList(String agentId, Range range) {
|
||||
if (agentId == null) {
|
||||
throw new NullPointerException("agentId must not be null");
|
||||
}
|
||||
return agentStatDao.scanAgentStatList(agentId, range);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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<Long[]> points = new LinkedList<Long[]>();
|
||||
public void setyAxisName(String yAxisName) {
|
||||
this.yAxisName = yAxisName;
|
||||
}
|
||||
|
||||
public Points() {
|
||||
}
|
||||
public static final class Points {
|
||||
|
||||
public List<Long[]> getPoints() {
|
||||
return points;
|
||||
}
|
||||
private List<Number[]> points = new LinkedList<Number[]>();
|
||||
|
||||
}
|
||||
public Points() {
|
||||
}
|
||||
|
||||
public List<Number[]> getPoints() {
|
||||
return points;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -2,24 +2,22 @@ package com.nhn.pinpoint.web.vo.linechart;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class LineChart extends Chart {
|
||||
public abstract class LineChart<X extends Number, Y extends Number> 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<Long[]> getPoints() {
|
||||
return this.points.getPoints();
|
||||
}
|
||||
public abstract void addPoint(X xVal, Y yVal);
|
||||
|
||||
public void setPoints(Points points) {
|
||||
this.points = points;
|
||||
}
|
||||
|
||||
public List<Number[]> getPoints() {
|
||||
return this.points.getPoints();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,37 @@
|
||||
package com.nhn.pinpoint.web.vo.linechart;
|
||||
|
||||
/**
|
||||
* @author hyungil.jeong
|
||||
*/
|
||||
public class SampledDoubleLineChart extends LineChart<Long, Double> {
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
package com.nhn.pinpoint.web.vo.linechart;
|
||||
|
||||
/**
|
||||
* @author hyungil.jeong
|
||||
*/
|
||||
public final class SampledLongLineChart extends LineChart<Long, Long> {
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
+90
-41
@@ -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<String, LineChart> charts = new HashMap<String, LineChart>();
|
||||
|
||||
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<String, LineChart<?, ?>> charts = new HashMap<String, LineChart<? extends Number, ? extends Number>>();
|
||||
|
||||
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<String, LineChart> getCharts() {
|
||||
return charts;
|
||||
}
|
||||
public void addAgentStats(List<AgentStat> agentStats) {
|
||||
for (AgentStat agentStat : agentStats) {
|
||||
addMemoryGcData(agentStat.getMemoryGc());
|
||||
addCpuLoadData(agentStat.getCpuLoad());
|
||||
}
|
||||
removeUncollectedCharts();
|
||||
}
|
||||
|
||||
public void setCharts(Map<String, LineChart> 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<Map.Entry<String, LineChart<?, ?>>> iter = charts.entrySet().iterator(); iter.hasNext();) {
|
||||
Map.Entry<String, LineChart<?, ?>> 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<String, LineChart<?, ?>> getCharts() {
|
||||
return charts;
|
||||
}
|
||||
|
||||
public void setCharts(Map<String, LineChart<?, ?>> charts) {
|
||||
this.charts = charts;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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<TAgentStat> result = dao.scanAgentStatList("FRONT-WEB1", range);
|
||||
System.out.println(result);
|
||||
}
|
||||
|
||||
List<AgentStat> result = dao.scanAgentStatList("FRONT-WEB1", range);
|
||||
System.out.println(result);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user