diff --git a/commons/src/main/java/com/navercorp/pinpoint/common/util/AgentEventType.java b/commons/src/main/java/com/navercorp/pinpoint/common/util/AgentEventType.java index c3a3c85d8715a..6ae5eb97162eb 100644 --- a/commons/src/main/java/com/navercorp/pinpoint/common/util/AgentEventType.java +++ b/commons/src/main/java/com/navercorp/pinpoint/common/util/AgentEventType.java @@ -85,7 +85,7 @@ public static AgentEventType getTypeByCode(int code) { return eventType; } } - return OTHER; + return null; } public static Set getTypesByCatgory(AgentEventTypeCategory category) { diff --git a/web/src/main/java/com/navercorp/pinpoint/web/applicationmap/ApplicationMapBuilder.java b/web/src/main/java/com/navercorp/pinpoint/web/applicationmap/ApplicationMapBuilder.java index ca161d21aa214..8efa4938b3550 100644 --- a/web/src/main/java/com/navercorp/pinpoint/web/applicationmap/ApplicationMapBuilder.java +++ b/web/src/main/java/com/navercorp/pinpoint/web/applicationmap/ApplicationMapBuilder.java @@ -379,7 +379,7 @@ private void appendServerInfo(Node node, LinkDataDuplexMap linkDataDuplexMap, Ag ServerInstanceList serverInstanceList = builder.build(); node.setServerInstanceList(serverInstanceList); } else if (nodeServiceType.isWas()) { - Set agentList = agentInfoService.selectAgent(node.getApplication().getName(), range); + Set agentList = agentInfoService.getAgentsByApplicationName(node.getApplication().getName(), range.getTo()); if (agentList.isEmpty()) { logger.warn("agentInfo not found. applicationName:{}", node.getApplication()); // avoid NPE diff --git a/web/src/main/java/com/navercorp/pinpoint/web/controller/AgentStatController.java b/web/src/main/java/com/navercorp/pinpoint/web/controller/AgentStatController.java index 28627666c9910..5c7df5f31d7da 100644 --- a/web/src/main/java/com/navercorp/pinpoint/web/controller/AgentStatController.java +++ b/web/src/main/java/com/navercorp/pinpoint/web/controller/AgentStatController.java @@ -17,14 +17,19 @@ package com.navercorp.pinpoint.web.controller; +import com.navercorp.pinpoint.web.service.AgentEventService; import com.navercorp.pinpoint.web.service.AgentInfoService; import com.navercorp.pinpoint.web.service.AgentStatService; import com.navercorp.pinpoint.web.util.TimeWindow; import com.navercorp.pinpoint.web.util.TimeWindowSlotCentricSampler; +import com.navercorp.pinpoint.web.vo.AgentEvent; +import com.navercorp.pinpoint.web.vo.AgentInfo; import com.navercorp.pinpoint.web.vo.AgentStat; +import com.navercorp.pinpoint.web.vo.AgentStatus; import com.navercorp.pinpoint.web.vo.ApplicationAgentList; import com.navercorp.pinpoint.web.vo.Range; import com.navercorp.pinpoint.web.vo.linechart.agentstat.AgentStatChartGroup; + import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; @@ -40,6 +45,7 @@ /** * @author emeroad * @author minwoo.jung + * @author HyunGil Jeong */ @Controller public class AgentStatController { @@ -51,6 +57,9 @@ public class AgentStatController { @Autowired private AgentInfoService agentInfoService; + + @Autowired + private AgentEventService agentEventService; @RequestMapping(value = "/getAgentStat", method = RequestMethod.GET) @ResponseBody @@ -72,12 +81,6 @@ public AgentStatChartGroup getAgentStat( logger.info("getAgentStat(agentId={}, from={}, to={}) : {}ms", agentId, from, to, watch.getLastTaskTimeMillis()); } - // FIXME dummy -// int nPoints = (int) (to - from) / 5000; -// if (sampleRate == null) { -// sampleRate = nPoints < 300 ? 1 : nPoints / 300; -// } - AgentStatChartGroup chartGroup = new AgentStatChartGroup(timeWindow); chartGroup.addAgentStats(agentStatList); chartGroup.buildCharts(); @@ -85,13 +88,55 @@ public AgentStatChartGroup getAgentStat( return chartGroup; } - @RequestMapping(value = "/getAgentList", method = RequestMethod.GET) + @RequestMapping(value = "/getAgentList", method = RequestMethod.GET, params={"application", "from", "to"}) @ResponseBody public ApplicationAgentList getApplicationAgentList( @RequestParam("application") String applicationName, @RequestParam("from") long from, @RequestParam("to") long to) { + return this.getApplicationAgentList(applicationName, to); + } + + @RequestMapping(value = "/getAgentList", method = RequestMethod.GET, params={"application", "timestamp"}) + @ResponseBody + public ApplicationAgentList getApplicationAgentList( + @RequestParam("application") String applicationName, + @RequestParam("timestamp") long timestamp) { + return this.agentInfoService.getApplicationAgentList(applicationName, timestamp); + } + + @RequestMapping(value = "/getAgentInfo", method = RequestMethod.GET) + @ResponseBody + public AgentInfo getAgentInfo( + @RequestParam("agentId") String agentId, + @RequestParam("timestamp") long timestamp) { + return this.agentInfoService.getAgentInfo(agentId, timestamp); + } + + @RequestMapping(value="/getAgentStatus", method=RequestMethod.GET) + @ResponseBody + public AgentStatus getAgentStatus( + @RequestParam("agentId") String agentId, + @RequestParam("timestamp") long timestamp) { + return this.agentInfoService.getAgentStatus(agentId, timestamp); + } + + @RequestMapping(value="/getAgentEvent", method=RequestMethod.GET) + @ResponseBody + public AgentEvent getAgentEvent( + @RequestParam("agentId") String agentId, + @RequestParam("eventTimestamp") long eventTimestamp, + @RequestParam("eventTypeCode") int eventTypeCode) { + return this.agentEventService.getAgentEvent(agentId, eventTimestamp, eventTypeCode); + } + + @RequestMapping(value="/getAgentEvents", method=RequestMethod.GET) + @ResponseBody + public List getAgentEvents( + @RequestParam("agentId") String agentId, + @RequestParam("from") long from, + @RequestParam("to") long to) { Range range = new Range(from, to); - return new ApplicationAgentList(agentInfoService.getApplicationAgentList(applicationName, range)); + return this.agentEventService.getAgentEvents(agentId, range); } } diff --git a/web/src/main/java/com/navercorp/pinpoint/web/controller/CommandController.java b/web/src/main/java/com/navercorp/pinpoint/web/controller/CommandController.java index b646f89f33cf2..581aab5169444 100644 --- a/web/src/main/java/com/navercorp/pinpoint/web/controller/CommandController.java +++ b/web/src/main/java/com/navercorp/pinpoint/web/controller/CommandController.java @@ -16,7 +16,6 @@ package com.navercorp.pinpoint.web.controller; -import com.navercorp.pinpoint.common.bo.AgentInfoBo; import com.navercorp.pinpoint.thrift.dto.TResult; import com.navercorp.pinpoint.thrift.dto.command.*; import com.navercorp.pinpoint.thrift.io.DeserializerFactory; @@ -26,6 +25,8 @@ import com.navercorp.pinpoint.web.cluster.PinpointRouteResponse; import com.navercorp.pinpoint.web.server.PinpointSocketManager; import com.navercorp.pinpoint.web.service.AgentService; +import com.navercorp.pinpoint.web.vo.AgentInfo; + import org.apache.commons.lang3.StringUtils; import org.apache.thrift.TBase; import org.apache.thrift.TException; @@ -67,7 +68,7 @@ public class CommandController { public ModelAndView echo(@RequestParam("application") String applicationName, @RequestParam("agent") String agentId, @RequestParam("startTimeStamp") long startTimeStamp, @RequestParam("message") String message) throws TException { - AgentInfoBo agentInfo = agentService.getAgentInfo(applicationName, agentId, startTimeStamp); + AgentInfo agentInfo = agentService.getAgentInfo(applicationName, agentId, startTimeStamp); if (agentInfo == null) { return createResponse(false, String.format("Can't find suitable PinpointServer(%s/%s/%d).", applicationName, agentId, startTimeStamp)); } @@ -78,7 +79,7 @@ public ModelAndView echo(@RequestParam("application") String applicationName, @R try { PinpointRouteResponse pinpointRouteResponse = agentService.invoke(agentInfo, echo); if (pinpointRouteResponse != null && pinpointRouteResponse.getRouteResult() == TRouteResult.OK) { - TBase result = pinpointRouteResponse.getResponse(); + TBase result = pinpointRouteResponse.getResponse(); if (result == null) { return createResponse(false, "result null."); } else if (result instanceof TCommandEcho) { @@ -100,7 +101,7 @@ public ModelAndView echo(@RequestParam("application") String applicationName, @R public ModelAndView echo(@RequestParam("application") String applicationName, @RequestParam("agent") String agentId, @RequestParam("startTimeStamp") long startTimeStamp) throws TException { - AgentInfoBo agentInfo = agentService.getAgentInfo(applicationName, agentId, startTimeStamp); + AgentInfo agentInfo = agentService.getAgentInfo(applicationName, agentId, startTimeStamp); if (agentInfo == null) { return createResponse(false, String.format("Can't find suitable PinpointServer(%s/%s/%d).", applicationName, agentId, startTimeStamp)); } @@ -110,7 +111,7 @@ public ModelAndView echo(@RequestParam("application") String applicationName, @R try { PinpointRouteResponse pinpointRouteResponse = agentService.invoke(agentInfo, threadDump); if (pinpointRouteResponse != null && pinpointRouteResponse.getRouteResult() == TRouteResult.OK) { - TBase result = pinpointRouteResponse.getResponse(); + TBase result = pinpointRouteResponse.getResponse(); if (result == null) { return createResponse(false, "result null."); } else if (result instanceof TCommandThreadDumpResponse) { diff --git a/web/src/main/java/com/navercorp/pinpoint/web/dao/AgentEventDao.java b/web/src/main/java/com/navercorp/pinpoint/web/dao/AgentEventDao.java new file mode 100644 index 0000000000000..81d9d4c270d56 --- /dev/null +++ b/web/src/main/java/com/navercorp/pinpoint/web/dao/AgentEventDao.java @@ -0,0 +1,34 @@ +/* + * 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.dao; + +import java.util.List; + +import com.navercorp.pinpoint.common.bo.AgentEventBo; +import com.navercorp.pinpoint.common.util.AgentEventType; +import com.navercorp.pinpoint.web.vo.Range; + +/** + * @author HyunGil Jeong + */ +public interface AgentEventDao { + + public AgentEventBo getAgentEvent(String agentId, long eventTimestamp, AgentEventType eventType); + + public List getAgentEvents(String agentId, Range range); + +} diff --git a/web/src/main/java/com/navercorp/pinpoint/web/dao/AgentInfoDao.java b/web/src/main/java/com/navercorp/pinpoint/web/dao/AgentInfoDao.java index 0aabf101b6c49..4f6964c851c70 100644 --- a/web/src/main/java/com/navercorp/pinpoint/web/dao/AgentInfoDao.java +++ b/web/src/main/java/com/navercorp/pinpoint/web/dao/AgentInfoDao.java @@ -17,16 +17,14 @@ package com.navercorp.pinpoint.web.dao; import com.navercorp.pinpoint.common.bo.AgentInfoBo; -import com.navercorp.pinpoint.web.vo.Range; - -import java.util.List; /** * @author emeroad + * @author HyunGil Jeong */ public interface AgentInfoDao { - @Deprecated - AgentInfoBo findAgentInfoBeforeStartTime(String agentId, long currentTime); - - List getAgentInfo(String agentId, Range range); + + AgentInfoBo getAgentInfo(String agentId, long timestamp); + + AgentInfoBo getInitialAgentInfo(String agentId); } diff --git a/web/src/main/java/com/navercorp/pinpoint/web/dao/AgentLifeCycleDao.java b/web/src/main/java/com/navercorp/pinpoint/web/dao/AgentLifeCycleDao.java new file mode 100644 index 0000000000000..8a73ce91f1bf7 --- /dev/null +++ b/web/src/main/java/com/navercorp/pinpoint/web/dao/AgentLifeCycleDao.java @@ -0,0 +1,28 @@ +/* + * 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.dao; + +import com.navercorp.pinpoint.common.bo.AgentLifeCycleBo; + +/** + * @author HyunGil Jeong + */ +public interface AgentLifeCycleDao { + + AgentLifeCycleBo getAgentLifeCycle(String agentId, long timestamp); + +} diff --git a/web/src/main/java/com/navercorp/pinpoint/web/dao/hbase/HbaseAgentEventDao.java b/web/src/main/java/com/navercorp/pinpoint/web/dao/hbase/HbaseAgentEventDao.java new file mode 100644 index 0000000000000..f0efe36cacd9c --- /dev/null +++ b/web/src/main/java/com/navercorp/pinpoint/web/dao/hbase/HbaseAgentEventDao.java @@ -0,0 +1,129 @@ +/* + * 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.dao.hbase; + +import java.util.ArrayList; +import java.util.List; + +import org.apache.hadoop.hbase.client.Result; +import org.apache.hadoop.hbase.client.ResultScanner; +import org.apache.hadoop.hbase.client.Scan; +import org.apache.hadoop.hbase.util.Bytes; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Qualifier; +import org.springframework.data.hadoop.hbase.ResultsExtractor; +import org.springframework.data.hadoop.hbase.RowMapper; +import org.springframework.stereotype.Repository; + +import com.navercorp.pinpoint.common.bo.AgentEventBo; +import com.navercorp.pinpoint.common.hbase.HBaseTables; +import com.navercorp.pinpoint.common.hbase.HbaseOperations2; +import com.navercorp.pinpoint.common.util.AgentEventType; +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.web.dao.AgentEventDao; +import com.navercorp.pinpoint.web.vo.Range; + +/** + * @author HyunGil Jeong + */ +@Repository +public class HbaseAgentEventDao implements AgentEventDao { + + private static final int SCANNER_CACHE_SIZE = 20; + + private final Logger logger = LoggerFactory.getLogger(this.getClass()); + + @Autowired + private HbaseOperations2 hbaseOperations2; + + @Autowired + @Qualifier("agentEventMapper") + private RowMapper> agentEventMapper; + + @Override + public List getAgentEvents(String agentId, Range range) { + if (agentId == null) { + throw new NullPointerException("agentId must not be null"); + } + if (range == null) { + throw new NullPointerException("range must not be null"); + } + + Scan scan = new Scan(); + scan.setMaxVersions(1); + scan.setCaching(SCANNER_CACHE_SIZE); + + scan.setStartRow(createRowKey(agentId, range.getTo())); + scan.setStopRow(createRowKey(agentId, range.getFrom())); + scan.addFamily(HBaseTables.AGENT_EVENT_CF_EVENTS); + + List agentEvents = this.hbaseOperations2.find(HBaseTables.AGENT_EVENT, scan, + new AgentEventResultsExtractor()); + logger.debug("agentEvents found. {}", agentEvents); + return agentEvents; + } + + @Override + public AgentEventBo getAgentEvent(String agentId, long eventTimestamp, AgentEventType eventType) { + if (agentId == null) { + throw new NullPointerException("agentId must not be null"); + } + if (eventTimestamp < 0) { + throw new IllegalArgumentException("eventTimestamp must not be less than 0"); + } + if (eventType == null) { + throw new NullPointerException("eventType must not be null"); + } + + final byte[] rowKey = createRowKey(agentId, eventTimestamp); + byte[] qualifier = Bytes.toBytes(eventType.getCode()); + List events = this.hbaseOperations2.get(HBaseTables.AGENT_EVENT, rowKey, + HBaseTables.AGENT_EVENT_CF_EVENTS, qualifier, this.agentEventMapper); + if (events == null || events.isEmpty()) { + return null; + } + return events.get(0); + } + + private byte[] createRowKey(String agentId, long timestamp) { + byte[] agentIdKey = BytesUtils.toBytes(agentId); + long reverseTimestamp = TimeUtils.reverseTimeMillis(timestamp); + return RowKeyUtils.concatFixedByteAndLong(agentIdKey, HBaseTables.AGENT_NAME_MAX_LEN, reverseTimestamp); + } + + private class AgentEventResultsExtractor implements ResultsExtractor> { + + @Override + public List extractData(ResultScanner results) throws Exception { + List agentEvents = new ArrayList(); + int rowNum = 0; + for (Result result : results) { + List intermediateEvents = agentEventMapper.mapRow(result, rowNum++); + if (!intermediateEvents.isEmpty()) { + agentEvents.addAll(intermediateEvents); + } + } + return agentEvents; + } + + } + +} diff --git a/web/src/main/java/com/navercorp/pinpoint/web/dao/hbase/HbaseAgentInfoDao.java b/web/src/main/java/com/navercorp/pinpoint/web/dao/hbase/HbaseAgentInfoDao.java index 0a9bfd4bf0780..b0df8c7c51c50 100644 --- a/web/src/main/java/com/navercorp/pinpoint/web/dao/hbase/HbaseAgentInfoDao.java +++ b/web/src/main/java/com/navercorp/pinpoint/web/dao/hbase/HbaseAgentInfoDao.java @@ -25,7 +25,6 @@ import com.navercorp.pinpoint.common.util.RowKeyUtils; import com.navercorp.pinpoint.common.util.TimeUtils; import com.navercorp.pinpoint.web.dao.AgentInfoDao; -import com.navercorp.pinpoint.web.vo.Range; import org.apache.hadoop.hbase.client.*; import org.apache.hadoop.hbase.util.Bytes; @@ -35,11 +34,9 @@ import org.springframework.data.hadoop.hbase.ResultsExtractor; import org.springframework.stereotype.Repository; -import java.util.ArrayList; -import java.util.List; - /** * @author emeroad + * @author HyunGil Jeong */ @Repository public class HbaseAgentInfoDao implements AgentInfoDao { @@ -53,151 +50,105 @@ public class HbaseAgentInfoDao implements AgentInfoDao { private ServiceTypeRegistryService registry; /** - * get a unique id based on agentId and startTime + * Returns the information of the agent with its start time closest to the given timestamp + * * @param agentId - * @param range + * @param timestamp * @return */ @Override - public List getAgentInfo(final String agentId, final Range range) { + public AgentInfoBo getAgentInfo(final String agentId, final long timestamp) { if (agentId == null) { throw new NullPointerException("agentId must not be null"); } - if (range == null) { - throw new NullPointerException("range must not be null"); - } - - - logger.debug("get agentInfo with, agentId={}, {}", agentId, range); - - Scan scan = new Scan(); - scan.setCaching(20); - - long fromTime = TimeUtils.reverseTimeMillis(range.getTo()); - long toTime = TimeUtils.reverseTimeMillis(1); - - byte[] agentIdBytes = Bytes.toBytes(agentId); - byte[] startKeyBytes = RowKeyUtils.concatFixedByteAndLong(agentIdBytes, HBaseTables.AGENT_NAME_MAX_LEN, fromTime); - byte[] endKeyBytes = RowKeyUtils.concatFixedByteAndLong(agentIdBytes, HBaseTables.AGENT_NAME_MAX_LEN, toTime); - scan.setStartRow(startKeyBytes); - scan.setStopRow(endKeyBytes); - scan.addFamily(HBaseTables.AGENTINFO_CF_INFO); - - List found = hbaseOperations2.find(HBaseTables.AGENTINFO, scan, new ResultsExtractor>() { - @Override - public List extractData(ResultScanner results) throws Exception { - final List result = new ArrayList(); - int found = 0; - for (Result next : results) { - found++; - byte[] row = next.getRow(); - long reverseStartTime = BytesUtils.bytesToLong(row, HBaseTables.AGENT_NAME_MAX_LEN); - long startTime = TimeUtils.recoveryTimeMillis(reverseStartTime); - byte[] serializedAgentInfo = next.getValue(HBaseTables.AGENTINFO_CF_INFO, HBaseTables.AGENTINFO_CF_INFO_IDENTIFIER); - byte[] serializedServerMetaData = next.getValue(HBaseTables.AGENTINFO_CF_INFO, HBaseTables.AGENTINFO_CF_INFO_SERVER_META_DATA); - - logger.debug("found={}, {}, start={}", found, range, startTime); - - if (found > 1 && startTime <= range.getFrom()) { - logger.debug("stop finding agentInfo."); - break; - } - - final AgentInfoBo.Builder agentInfoBoBuilder = new AgentInfoBo.Builder(serializedAgentInfo); - agentInfoBoBuilder.setAgentId(agentId); - agentInfoBoBuilder.setStartTime(startTime); - // TODO fix - agentInfoBoBuilder.setServiceType(registry.findServiceType(agentInfoBoBuilder.getServiceTypeCode())); - - if (serializedServerMetaData != null) { - agentInfoBoBuilder.setServerMetaData(new ServerMetaDataBo.Builder(serializedServerMetaData).build()); - } - final AgentInfoBo agentInfoBo = agentInfoBoBuilder.build(); - - logger.debug("found agentInfoBo {}", agentInfoBo); - result.add(agentInfoBo); - } - logger.debug("extracted agentInfoBo {}", result); - return result; - } - }); - - logger.debug("get agentInfo result, {}", found); - - return found; + // TODO need to be cached + Scan scan = createScan(agentId, timestamp); + scan.setMaxVersions(1); + scan.setCaching(1); + + AgentInfoBo result = this.hbaseOperations2.find(HBaseTables.AGENTINFO, scan, new AgentInfoBoResultsExtractor(agentId)); + if (result == null) { + logger.warn("agentInfo not found. agentId={}, time={}", agentId, timestamp); + } + return result; } - + /** - * find the closest agent startTime from current time + * Returns the very first information of the agent * * @param agentId - * @param currentTime - * @return */ @Override - @Deprecated - public AgentInfoBo findAgentInfoBeforeStartTime(final String agentId, final long currentTime) { + public AgentInfoBo getInitialAgentInfo(final String agentId) { if (agentId == null) { throw new NullPointerException("agentId must not be null"); } - - // TODO need to be cached - Scan scan = createScan(agentId, currentTime); - AgentInfoBo agentInfoBo = hbaseOperations2.find(HBaseTables.AGENTINFO, scan, new ResultsExtractor() { - @Override - public AgentInfoBo extractData(ResultScanner results) throws Exception { - for (Result next : results) { - byte[] row = next.getRow(); - long reverseStartTime = BytesUtils.bytesToLong(row, HBaseTables.AGENT_NAME_MAX_LEN); - long startTime = TimeUtils.recoveryTimeMillis(reverseStartTime); - logger.debug("agent:{} startTime value {}", agentId, startTime); - // should find just BEFORE the start time - if (startTime < currentTime) { - byte[] serializedAgentInfo = next.getValue(HBaseTables.AGENTINFO_CF_INFO, HBaseTables.AGENTINFO_CF_INFO_IDENTIFIER); - byte[] serializedServerMetaData = next.getValue(HBaseTables.AGENTINFO_CF_INFO, HBaseTables.AGENTINFO_CF_INFO_SERVER_META_DATA); - - final AgentInfoBo.Builder agentInfoBoBuilder = new AgentInfoBo.Builder(serializedAgentInfo); - agentInfoBoBuilder.setAgentId(agentId); - agentInfoBoBuilder.setStartTime(startTime); - // TODO fix - agentInfoBoBuilder.setServiceType(registry.findServiceType(agentInfoBoBuilder.getServiceTypeCode())); - if (serializedServerMetaData != null) { - agentInfoBoBuilder.setServerMetaData(new ServerMetaDataBo.Builder(serializedServerMetaData).build()); - } - final AgentInfoBo agentInfoBo = agentInfoBoBuilder.build(); - - logger.debug("agent:{} startTime find {}", agentId, startTime); - - return agentInfoBo; - } - } - - logger.warn("agentInfo not found. agentId={}, time={}", agentId, currentTime); - - return null; - } - }); - -// if (startTime == null) { -// return -1; -// } - return agentInfoBo; + Scan scan = new Scan(); + byte[] agentIdBytes = Bytes.toBytes(agentId); + byte[] reverseStartKey = RowKeyUtils.concatFixedByteAndLong(agentIdBytes, HBaseTables.AGENT_NAME_MAX_LEN, Long.MAX_VALUE); + scan.setStartRow(reverseStartKey); + scan.setReversed(true); + scan.setMaxVersions(1); + scan.setCaching(1); + + AgentInfoBo result = this.hbaseOperations2.find(HBaseTables.AGENTINFO, scan, new AgentInfoBoResultsExtractor(agentId)); + if (result == null) { + logger.warn("agentInfo not found. agentId={}, time={}", agentId, 0); + } + return result; } - private Scan createScan(String agentInfo, long currentTime) { + private Scan createScan(String agentId, long currentTime) { Scan scan = new Scan(); - scan.setCaching(20); - byte[] agentIdBytes = Bytes.toBytes(agentInfo); + byte[] agentIdBytes = Bytes.toBytes(agentId); long startTime = TimeUtils.reverseTimeMillis(currentTime); byte[] startKeyBytes = RowKeyUtils.concatFixedByteAndLong(agentIdBytes, HBaseTables.AGENT_NAME_MAX_LEN, startTime); - scan.setStartRow(startKeyBytes); - byte[] endKeyBytes = RowKeyUtils.concatFixedByteAndLong(agentIdBytes, HBaseTables.AGENT_NAME_MAX_LEN, Long.MAX_VALUE); + + scan.setStartRow(startKeyBytes); scan.setStopRow(endKeyBytes); scan.addFamily(HBaseTables.AGENTINFO_CF_INFO); return scan; } + + private class AgentInfoBoResultsExtractor implements ResultsExtractor { + + private final String agentId; + + private AgentInfoBoResultsExtractor(String agentId) { + this.agentId = agentId; + } + + @Override + public AgentInfoBo extractData(ResultScanner results) throws Exception { + for (Result next : results) { + byte[] row = next.getRow(); + long reverseStartTime = BytesUtils.bytesToLong(row, HBaseTables.AGENT_NAME_MAX_LEN); + long startTime = TimeUtils.recoveryTimeMillis(reverseStartTime); + + byte[] serializedAgentInfo = next.getValue(HBaseTables.AGENTINFO_CF_INFO, HBaseTables.AGENTINFO_CF_INFO_IDENTIFIER); + byte[] serializedServerMetaData = next.getValue(HBaseTables.AGENTINFO_CF_INFO, HBaseTables.AGENTINFO_CF_INFO_SERVER_META_DATA); + + final AgentInfoBo.Builder agentInfoBoBuilder = new AgentInfoBo.Builder(serializedAgentInfo); + agentInfoBoBuilder.setAgentId(this.agentId); + agentInfoBoBuilder.setStartTime(startTime); + // TODO fix + agentInfoBoBuilder.setServiceType(registry.findServiceType(agentInfoBoBuilder.getServiceTypeCode())); + if (serializedServerMetaData != null) { + agentInfoBoBuilder.setServerMetaData(new ServerMetaDataBo.Builder(serializedServerMetaData).build()); + } + final AgentInfoBo agentInfoBo = agentInfoBoBuilder.build(); + + logger.debug("agent:{} startTime value {}", agentId, startTime); + + return agentInfoBo; + } + + return null; + } + + } } diff --git a/web/src/main/java/com/navercorp/pinpoint/web/dao/hbase/HbaseAgentLifeCycleDao.java b/web/src/main/java/com/navercorp/pinpoint/web/dao/hbase/HbaseAgentLifeCycleDao.java new file mode 100644 index 0000000000000..4c537dba219e7 --- /dev/null +++ b/web/src/main/java/com/navercorp/pinpoint/web/dao/hbase/HbaseAgentLifeCycleDao.java @@ -0,0 +1,114 @@ +/* + * 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.dao.hbase; + +import java.util.ArrayList; +import java.util.List; + +import org.apache.hadoop.hbase.client.Result; +import org.apache.hadoop.hbase.client.ResultScanner; +import org.apache.hadoop.hbase.client.Scan; +import org.apache.hadoop.hbase.util.Bytes; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Qualifier; +import org.springframework.data.hadoop.hbase.ResultsExtractor; +import org.springframework.data.hadoop.hbase.RowMapper; +import org.springframework.stereotype.Repository; + +import com.navercorp.pinpoint.common.bo.AgentLifeCycleBo; +import com.navercorp.pinpoint.common.hbase.HBaseTables; +import com.navercorp.pinpoint.common.hbase.HbaseOperations2; +import com.navercorp.pinpoint.common.util.RowKeyUtils; +import com.navercorp.pinpoint.common.util.TimeUtils; +import com.navercorp.pinpoint.web.dao.AgentLifeCycleDao; + +/** + * @author HyunGil Jeong + */ +@Repository +public class HbaseAgentLifeCycleDao implements AgentLifeCycleDao { + + private static final int NUM_LIFE_CYCLES_TO_SCAN = 1; + + private final Logger logger = LoggerFactory.getLogger(this.getClass()); + + @Autowired + private HbaseOperations2 hbaseOperations2; + + @Autowired + @Qualifier("agentLifeCycleMapper") + private RowMapper agentLifeCycleMapper; + + @Override + public AgentLifeCycleBo getAgentLifeCycle(String agentId, long timestamp) { + if (agentId == null) { + throw new NullPointerException("agentId must not be null"); + } + if (timestamp < 0) { + throw new IllegalArgumentException("timestamp must not be less than 0"); + } + + Scan scan = new Scan(); + scan.setMaxVersions(1); + scan.setCaching(NUM_LIFE_CYCLES_TO_SCAN); + + long fromTime = TimeUtils.reverseTimeMillis(timestamp); + + byte[] agentIdBytes = Bytes.toBytes(agentId); + byte[] startKeyBytes = RowKeyUtils.concatFixedByteAndLong(agentIdBytes, HBaseTables.AGENT_NAME_MAX_LEN, fromTime); + byte[] endKeyBytes = RowKeyUtils.concatFixedByteAndLong(agentIdBytes, HBaseTables.AGENT_NAME_MAX_LEN, Long.MAX_VALUE); + + scan.setStartRow(startKeyBytes); + scan.setStopRow(endKeyBytes); + scan.addColumn(HBaseTables.AGENT_LIFECYCLE_CF_STATUS, HBaseTables.AGENT_LIFECYCLE_CF_STATUS_QUALI_STATES); + + try { + List agentLifeCycles = this.hbaseOperations2.find(HBaseTables.AGENT_LIFECYCLE, scan, new AgentLifeCycleResultsExtractor()); + if (agentLifeCycles.isEmpty()) { + logger.debug("agentLifeCycle not found for agentId={}, timestamp={}", agentId, timestamp); + return null; + } + + AgentLifeCycleBo latestLifeCycle = agentLifeCycles.get(0); + logger.debug("agentLifeCycle found for agentId={}, timestamp={}, value={}", agentId, timestamp, latestLifeCycle); + return latestLifeCycle; + } catch (Exception e) { + logger.warn("could not retrieve agentLifeCycle for agentId={}, timestamp={}", agentId, timestamp); + return null; + } + } + + private class AgentLifeCycleResultsExtractor implements ResultsExtractor> { + + @Override + public List extractData(ResultScanner results) throws Exception { + int found = 0; + List agentLifeCycles = new ArrayList(); + for (Result result : results) { + agentLifeCycles.add(agentLifeCycleMapper.mapRow(result, found++)); + if (found >= NUM_LIFE_CYCLES_TO_SCAN) { + break; + } + } + return agentLifeCycles; + } + + } + +} diff --git a/web/src/main/java/com/navercorp/pinpoint/web/mapper/AgentEventMapper.java b/web/src/main/java/com/navercorp/pinpoint/web/mapper/AgentEventMapper.java new file mode 100644 index 0000000000000..bcf6746932b1b --- /dev/null +++ b/web/src/main/java/com/navercorp/pinpoint/web/mapper/AgentEventMapper.java @@ -0,0 +1,74 @@ +/* + * 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 java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +import org.apache.hadoop.hbase.Cell; +import org.apache.hadoop.hbase.CellUtil; +import org.apache.hadoop.hbase.client.Result; +import org.springframework.data.hadoop.hbase.RowMapper; +import org.springframework.stereotype.Component; + +import com.navercorp.pinpoint.common.bo.AgentEventBo; +import com.navercorp.pinpoint.common.buffer.Buffer; +import com.navercorp.pinpoint.common.buffer.FixedBuffer; +import com.navercorp.pinpoint.common.util.AgentEventType; +import com.navercorp.pinpoint.common.util.BytesUtils; + +/** + * @author HyunGil Jeong + */ +@Component +public class AgentEventMapper implements RowMapper> { + + @Override + public List mapRow(Result result, int rowNum) throws Exception { + if (result.isEmpty()) { + return Collections.emptyList(); + } + + List agentEvents = new ArrayList(); + for (Cell cell : result.rawCells()) { + byte[] qualifier = CellUtil.cloneQualifier(cell); + final AgentEventType eventType = AgentEventType.getTypeByCode(BytesUtils.bytesToInt(qualifier, 0)); + + byte[] value = CellUtil.cloneValue(cell); + final Buffer buffer = new FixedBuffer(value); + + final int version = buffer.readInt(); + switch (version) { + case 0 : + final String agentId = buffer.readPrefixedString(); + final long startTimestamp = buffer.readLong(); + final long eventTimestamp = buffer.readLong(); + final byte[] eventMessage = buffer.readPrefixedBytes(); + final AgentEventBo agentEvent = new AgentEventBo(version, agentId, startTimestamp, eventTimestamp, eventType); + agentEvent.setEventBody(eventMessage); + agentEvents.add(agentEvent); + break; + default : + break; + } + } + + return agentEvents; + } + +} diff --git a/web/src/main/java/com/navercorp/pinpoint/web/mapper/AgentLifeCycleMapper.java b/web/src/main/java/com/navercorp/pinpoint/web/mapper/AgentLifeCycleMapper.java new file mode 100644 index 0000000000000..ec87197509a0b --- /dev/null +++ b/web/src/main/java/com/navercorp/pinpoint/web/mapper/AgentLifeCycleMapper.java @@ -0,0 +1,70 @@ +/* + * 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 org.apache.hadoop.hbase.Cell; +import org.apache.hadoop.hbase.CellUtil; +import org.apache.hadoop.hbase.client.Result; +import org.springframework.data.hadoop.hbase.RowMapper; +import org.springframework.stereotype.Component; + +import com.navercorp.pinpoint.common.bo.AgentLifeCycleBo; +import com.navercorp.pinpoint.common.buffer.Buffer; +import com.navercorp.pinpoint.common.buffer.FixedBuffer; +import com.navercorp.pinpoint.common.hbase.HBaseTables; +import com.navercorp.pinpoint.common.util.AgentLifeCycleState; + +/** + * @author HyunGil Jeong + */ +@Component +public class AgentLifeCycleMapper implements RowMapper { + + @Override + public AgentLifeCycleBo mapRow(Result result, int rowNum) throws Exception { + if (result.isEmpty()) { + return null; + } + + Cell valueCell = result.getColumnLatestCell(HBaseTables.AGENT_LIFECYCLE_CF_STATUS, HBaseTables.AGENT_LIFECYCLE_CF_STATUS_QUALI_STATES); + + return createAgentLifeCycleBo(valueCell); + } + + private AgentLifeCycleBo createAgentLifeCycleBo(Cell valueCell) { + if (valueCell == null) { + return null; + } + byte[] value = CellUtil.cloneValue(valueCell); + final Buffer buffer = new FixedBuffer(value); + + final int version = buffer.readInt(); + switch (version) { + case 0 : + final String agentId = buffer.readPrefixedString(); + final long startTimestamp = buffer.readLong(); + final long eventTimestamp = buffer.readLong(); + final long eventIdentifier = buffer.readLong(); + final AgentLifeCycleState agentLifeCycleState = AgentLifeCycleState.getStateByCode(buffer.readShort()); + final AgentLifeCycleBo agentLifeCycleBo = new AgentLifeCycleBo(agentId, startTimestamp, eventTimestamp, eventIdentifier, agentLifeCycleState); + return agentLifeCycleBo; + default : + return null; + } + } + +} diff --git a/web/src/main/java/com/navercorp/pinpoint/web/server/PinpointSocketManager.java b/web/src/main/java/com/navercorp/pinpoint/web/server/PinpointSocketManager.java index 30cd4ad3e94b8..e95322c9acfa7 100644 --- a/web/src/main/java/com/navercorp/pinpoint/web/server/PinpointSocketManager.java +++ b/web/src/main/java/com/navercorp/pinpoint/web/server/PinpointSocketManager.java @@ -27,6 +27,7 @@ import javax.annotation.PreDestroy; import com.navercorp.pinpoint.common.bo.AgentInfoBo; + import org.apache.zookeeper.KeeperException; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -43,6 +44,7 @@ import com.navercorp.pinpoint.web.cluster.ClusterManager; import com.navercorp.pinpoint.web.cluster.zookeeper.ZookeeperClusterManager; import com.navercorp.pinpoint.web.config.WebConfig; +import com.navercorp.pinpoint.web.vo.AgentInfo; /** * @author koo.taejin @@ -114,8 +116,8 @@ public List getCollectorList() { return serverAcceptor.getWritableServerList(); } - public PinpointServer getCollector(AgentInfoBo agentInfo) { - return getCollector(agentInfo.getApplicationName(), agentInfo.getAgentId(), agentInfo.getStartTime()); + public PinpointServer getCollector(AgentInfo agentInfo) { + return getCollector(agentInfo.getApplicationName(), agentInfo.getAgentId(), agentInfo.getStartTimestamp()); } public PinpointServer getCollector(String applicationName, String agentId, long startTimeStamp) { diff --git a/web/src/main/java/com/navercorp/pinpoint/web/service/AgentEventService.java b/web/src/main/java/com/navercorp/pinpoint/web/service/AgentEventService.java new file mode 100644 index 0000000000000..02e40bf657b34 --- /dev/null +++ b/web/src/main/java/com/navercorp/pinpoint/web/service/AgentEventService.java @@ -0,0 +1,33 @@ +/* + * 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.service; + +import java.util.List; + +import com.navercorp.pinpoint.web.vo.AgentEvent; +import com.navercorp.pinpoint.web.vo.Range; + +/** + * @author HyunGil Jeong + */ +public interface AgentEventService { + + AgentEvent getAgentEvent(String agentId, long eventTimestamp, int eventTypeCode); + + List getAgentEvents(String agentId, Range range); + +} diff --git a/web/src/main/java/com/navercorp/pinpoint/web/service/AgentEventServiceImpl.java b/web/src/main/java/com/navercorp/pinpoint/web/service/AgentEventServiceImpl.java new file mode 100644 index 0000000000000..98bcbb92916dc --- /dev/null +++ b/web/src/main/java/com/navercorp/pinpoint/web/service/AgentEventServiceImpl.java @@ -0,0 +1,104 @@ +/* + * 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.service; + +import java.io.UnsupportedEncodingException; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import com.navercorp.pinpoint.common.bo.AgentEventBo; +import com.navercorp.pinpoint.common.util.AgentEventMessageDeserializer; +import com.navercorp.pinpoint.common.util.AgentEventType; +import com.navercorp.pinpoint.web.dao.AgentEventDao; +import com.navercorp.pinpoint.web.vo.AgentEvent; +import com.navercorp.pinpoint.web.vo.Range; + +/** + * @author HyunGil Jeong + */ +@Service +public class AgentEventServiceImpl implements AgentEventService { + + private final Logger logger = LoggerFactory.getLogger(this.getClass()); + + @Autowired + private AgentEventDao agentEventDao; + + @Autowired + private AgentEventMessageDeserializer agentEventMessageDeserializer; + + @Override + public List getAgentEvents(String agentId, Range range) { + if (agentId == null) { + throw new NullPointerException("agentId must not be null"); + } + final boolean includeEventMessage = false; + List agentEventBos = this.agentEventDao.getAgentEvents(agentId, range); + List agentEvents = new ArrayList(agentEventBos.size()); + for (AgentEventBo agentEventBo : agentEventBos) { + if (agentEventBo != null) { + agentEvents.add(createAgentEvent(agentEventBo, includeEventMessage)); + } + } + Collections.sort(agentEvents, AgentEvent.EVENT_TIMESTAMP_DESC_COMPARATOR); + return agentEvents; + } + + @Override + public AgentEvent getAgentEvent(String agentId, long eventTimestamp, int eventTypeCode) { + if (agentId == null) { + throw new NullPointerException("agentId must not be null"); + } + if (eventTimestamp < 0) { + throw new IllegalArgumentException("eventTimeTimestamp must not be less than 0"); + } + final AgentEventType eventType = AgentEventType.getTypeByCode(eventTypeCode); + if (eventType == null) { + throw new IllegalArgumentException("invalid eventTypeCode [" + eventTypeCode + "]"); + } + final boolean includeEventMessage = true; + AgentEventBo agentEventBo = this.agentEventDao.getAgentEvent(agentId, eventTimestamp, eventType); + if (agentEventBo != null) { + return createAgentEvent(agentEventBo, includeEventMessage); + } + return null; + } + + private AgentEvent createAgentEvent(AgentEventBo agentEventBo, boolean includeEventMessage) { + final String agentId = agentEventBo.getAgentId(); + final long eventTimestamp = agentEventBo.getEventTimestamp(); + final AgentEventType eventType = agentEventBo.getEventType(); + AgentEvent agentEvent = new AgentEvent(agentId, eventTimestamp, eventType); + agentEvent.setStartTimestamp(agentEventBo.getStartTimestamp()); + if (includeEventMessage) { + try { + agentEvent.setEventMessage(this.agentEventMessageDeserializer.deserialize(eventType, + agentEventBo.getEventBody())); + } catch (UnsupportedEncodingException e) { + logger.warn("error deserializing event message", e); + } + } + return agentEvent; + } + +} diff --git a/web/src/main/java/com/navercorp/pinpoint/web/service/AgentInfoService.java b/web/src/main/java/com/navercorp/pinpoint/web/service/AgentInfoService.java index a60bec812f89e..bb7d5ca25d196 100644 --- a/web/src/main/java/com/navercorp/pinpoint/web/service/AgentInfoService.java +++ b/web/src/main/java/com/navercorp/pinpoint/web/service/AgentInfoService.java @@ -16,19 +16,23 @@ package com.navercorp.pinpoint.web.service; -import java.util.List; import java.util.Set; -import java.util.SortedMap; import com.navercorp.pinpoint.common.bo.AgentInfoBo; -import com.navercorp.pinpoint.web.vo.Range; +import com.navercorp.pinpoint.web.vo.AgentInfo; +import com.navercorp.pinpoint.web.vo.AgentStatus; +import com.navercorp.pinpoint.web.vo.ApplicationAgentList; /** * @author netspider + * @author HyunGil Jeong */ public interface AgentInfoService { - SortedMap> getApplicationAgentList(String applicationName, Range range); + ApplicationAgentList getApplicationAgentList(String applicationName, long timestamp); + Set getAgentsByApplicationName(String applicationName, long timestamp); + + AgentInfo getAgentInfo(String agentId, long timestamp); - Set selectAgent(String applicationId, Range range); + AgentStatus getAgentStatus(String agentId, long timestamp); } diff --git a/web/src/main/java/com/navercorp/pinpoint/web/service/AgentInfoServiceImpl.java b/web/src/main/java/com/navercorp/pinpoint/web/service/AgentInfoServiceImpl.java index 6d167822e6024..e6d8bd42d66a6 100644 --- a/web/src/main/java/com/navercorp/pinpoint/web/service/AgentInfoServiceImpl.java +++ b/web/src/main/java/com/navercorp/pinpoint/web/service/AgentInfoServiceImpl.java @@ -19,9 +19,14 @@ import java.util.*; import com.navercorp.pinpoint.common.bo.AgentInfoBo; +import com.navercorp.pinpoint.common.bo.AgentLifeCycleBo; +import com.navercorp.pinpoint.common.util.AgentLifeCycleState; import com.navercorp.pinpoint.web.dao.AgentInfoDao; +import com.navercorp.pinpoint.web.dao.AgentLifeCycleDao; import com.navercorp.pinpoint.web.dao.ApplicationIndexDao; -import com.navercorp.pinpoint.web.vo.Range; +import com.navercorp.pinpoint.web.vo.AgentInfo; +import com.navercorp.pinpoint.web.vo.AgentStatus; +import com.navercorp.pinpoint.web.vo.ApplicationAgentList; import org.apache.commons.collections.CollectionUtils; import org.slf4j.Logger; @@ -32,7 +37,7 @@ /** * * @author netspider - * + * @author HyunGil Jeong */ @Service public class AgentInfoServiceImpl implements AgentInfoService { @@ -45,73 +50,117 @@ public class AgentInfoServiceImpl implements AgentInfoService { @Autowired private AgentInfoDao agentInfoDao; - /** - * FIXME from/to present in the interface but these values are not currently used. They should be used when agent list snapshot is implemented - */ + @Autowired + private AgentLifeCycleDao agentLifeCycleDao; + @Override - public SortedMap> getApplicationAgentList(String applicationName, Range range) { + public ApplicationAgentList getApplicationAgentList(String applicationName, long timestamp) { if (applicationName == null) { throw new NullPointerException("applicationName must not be null"); } - final List agentIdList = applicationIndexDao.selectAgentIds(applicationName); + final List agentIdList = this.applicationIndexDao.selectAgentIds(applicationName); if (logger.isDebugEnabled()) { logger.debug("agentIdList={}", agentIdList); } if (CollectionUtils.isEmpty(agentIdList)) { - logger.debug("agentIdList is empty. applicationName={}, {}", applicationName, range); - return new TreeMap>(); + logger.debug("agentIdList is empty. applicationName={}", applicationName); + return new ApplicationAgentList(new TreeMap>()); } // key = hostname // value= list fo agentinfo - SortedMap> result = new TreeMap>(); + SortedMap> result = new TreeMap>(); for (String agentId : agentIdList) { - List agentInfoList = agentInfoDao.getAgentInfo(agentId, range); + AgentInfoBo agentInfoBo = this.agentInfoDao.getAgentInfo(agentId, timestamp); - if (agentInfoList.isEmpty()) { - logger.debug("agentinfolist is empty. agentid={}, {}", agentId, range); + if (agentInfoBo == null) { continue; } + + final AgentInfo agentInfo = new AgentInfo(agentInfoBo); + + final AgentStatus currentStatus = this.getAgentStatus(agentId, Long.MAX_VALUE); + agentInfo.setStatus(currentStatus); + + final AgentInfoBo initialAgentInfo = this.agentInfoDao.getInitialAgentInfo(agentId); + if (initialAgentInfo != null) { + agentInfo.setInitialStartTimestamp(initialAgentInfo.getStartTime()); + } - // FIXME just using the first value for now. Might need to check and pick which one to use. - AgentInfoBo agentInfo = agentInfoList.get(0); - String hostname = agentInfo.getHostName(); - + String hostname = agentInfoBo.getHostName(); + if (result.containsKey(hostname)) { result.get(hostname).add(agentInfo); } else { - List list = new ArrayList(); + List list = new ArrayList(); list.add(agentInfo); result.put(hostname, list); } } - for (List agentInfoBoList : result.values()) { - Collections.sort(agentInfoBoList, AgentInfoBo.AGENT_NAME_ASC_COMPARATOR); + for (List agentInfoList : result.values()) { + Collections.sort(agentInfoList, AgentInfo.AGENT_NAME_ASC_COMPARATOR); } logger.info("getApplicationAgentList={}", result); - return result; + return new ApplicationAgentList(result); } - public Set selectAgent(String applicationId, Range range) { - if (applicationId == null) { - throw new NullPointerException("applicationId must not be null"); + @Override + public Set getAgentsByApplicationName(String applicationName, long timestamp) { + if (applicationName == null) { + throw new NullPointerException("applicationName must not be null"); } - List agentIds = applicationIndexDao.selectAgentIds(applicationId); + List agentIds = this.applicationIndexDao.selectAgentIds(applicationName); Set agentSet = new HashSet(); for (String agentId : agentIds) { // TODO Temporarily scans for the most recent AgentInfo row starting from range's to value. // (As we do not yet have a way to accurately record the agent's lifecycle.) - AgentInfoBo info = agentInfoDao.findAgentInfoBeforeStartTime(agentId, range.getTo()); + AgentInfoBo info = this.agentInfoDao.getAgentInfo(agentId, timestamp); if (info != null) { agentSet.add(info); } } return agentSet; } + + @Override + public AgentInfo getAgentInfo(String agentId, long timestamp) { + if (agentId == null) { + throw new NullPointerException("agentId must not be null"); + } + if (timestamp < 0) { + throw new IllegalArgumentException("timestamp must not be less than 0"); + } + AgentInfoBo agentInfoBo = this.agentInfoDao.getAgentInfo(agentId, timestamp); + if (agentInfoBo == null) { + return null; + } + AgentInfo agentInfo = new AgentInfo(agentInfoBo); + agentInfo.setStatus(this.getAgentStatus(agentId, timestamp)); + return agentInfo; + } + + @Override + public AgentStatus getAgentStatus(String agentId, long timestamp) { + if (agentId == null) { + throw new NullPointerException("agentId must not be null"); + } + if (timestamp < 0) { + throw new IllegalArgumentException("timestamp must not be less than 0"); + } + AgentLifeCycleBo agentLifeCycleBo = this.agentLifeCycleDao.getAgentLifeCycle(agentId, timestamp); + if (agentLifeCycleBo == null) { + AgentStatus agentStatus = new AgentStatus(); + agentStatus.setAgentId(agentId); + agentStatus.setState(AgentLifeCycleState.UNKNOWN); + return agentStatus; + } else { + return new AgentStatus(agentLifeCycleBo); + } + } } diff --git a/web/src/main/java/com/navercorp/pinpoint/web/service/AgentService.java b/web/src/main/java/com/navercorp/pinpoint/web/service/AgentService.java index 042034b4d85b5..ff529939966f5 100644 --- a/web/src/main/java/com/navercorp/pinpoint/web/service/AgentService.java +++ b/web/src/main/java/com/navercorp/pinpoint/web/service/AgentService.java @@ -19,9 +19,10 @@ package com.navercorp.pinpoint.web.service; -import com.navercorp.pinpoint.common.bo.AgentInfoBo; import com.navercorp.pinpoint.web.cluster.PinpointRouteResponse; import com.navercorp.pinpoint.web.vo.AgentActiveThreadStatusList; +import com.navercorp.pinpoint.web.vo.AgentInfo; + import org.apache.thrift.TBase; import org.apache.thrift.TException; @@ -33,21 +34,21 @@ */ public interface AgentService { - AgentInfoBo getAgentInfo(String applicationName, String agentId, long startTimeStamp); - AgentInfoBo getAgentInfo(String applicationName, String agentId, long startTimeStamp, boolean checkDB); - List getAgentInfoList(String applicationName); + AgentInfo getAgentInfo(String applicationName, String agentId, long startTimeStamp); + AgentInfo getAgentInfo(String applicationName, String agentId, long startTimeStamp, boolean checkDB); + List getAgentInfoList(String applicationName); - PinpointRouteResponse invoke(AgentInfoBo agentInfoList, TBase tBase) throws TException; - PinpointRouteResponse invoke(AgentInfoBo agentInfoList, TBase tBase, long timeout) throws TException; - PinpointRouteResponse invoke(AgentInfoBo agentInfoList, byte[] payload) throws TException; - PinpointRouteResponse invoke(AgentInfoBo agentInfoList, byte[] payload, long timeout) throws TException; + PinpointRouteResponse invoke(AgentInfo agentInfoList, TBase tBase) throws TException; + PinpointRouteResponse invoke(AgentInfo agentInfoList, TBase tBase, long timeout) throws TException; + PinpointRouteResponse invoke(AgentInfo agentInfoList, byte[] payload) throws TException; + PinpointRouteResponse invoke(AgentInfo agentInfoList, byte[] payload, long timeout) throws TException; - Map invoke(List agentInfoList, TBase tBase) throws TException; - Map invoke(List agentInfoList, TBase tBase, long timeout) throws TException; - Map invoke(List agentInfoList, byte[] payload) throws TException; - Map invoke(List agentInfoList, byte[] payload, long timeout) throws TException; + Map invoke(List agentInfoList, TBase tBase) throws TException; + Map invoke(List agentInfoList, TBase tBase, long timeout) throws TException; + Map invoke(List agentInfoList, byte[] payload) throws TException; + Map invoke(List agentInfoList, byte[] payload, long timeout) throws TException; - AgentActiveThreadStatusList getActiveThreadStatus(List agentInfoList) throws TException; - AgentActiveThreadStatusList getActiveThreadStatus(List agentInfoList, byte[] payload) throws TException; + AgentActiveThreadStatusList getActiveThreadStatus(List agentInfoList) throws TException; + AgentActiveThreadStatusList getActiveThreadStatus(List agentInfoList, byte[] payload) throws TException; } diff --git a/web/src/main/java/com/navercorp/pinpoint/web/service/AgentServiceImpl.java b/web/src/main/java/com/navercorp/pinpoint/web/service/AgentServiceImpl.java index eecd0d3ab0c5d..c7106c4e7a6e0 100644 --- a/web/src/main/java/com/navercorp/pinpoint/web/service/AgentServiceImpl.java +++ b/web/src/main/java/com/navercorp/pinpoint/web/service/AgentServiceImpl.java @@ -39,7 +39,8 @@ import com.navercorp.pinpoint.web.server.PinpointSocketManager; import com.navercorp.pinpoint.web.vo.AgentActiveThreadStatus; import com.navercorp.pinpoint.web.vo.AgentActiveThreadStatusList; -import com.navercorp.pinpoint.web.vo.Range; +import com.navercorp.pinpoint.web.vo.AgentInfo; + import org.apache.thrift.TBase; import org.apache.thrift.TException; import org.slf4j.Logger; @@ -51,6 +52,7 @@ /** * @Author Taejin Koo + * @author HyunGil Jeong */ @Service public class AgentServiceImpl implements AgentService { @@ -72,17 +74,16 @@ public class AgentServiceImpl implements AgentService { @Override - public AgentInfoBo getAgentInfo(String applicationName, String agentId, long startTimeStamp) { + public AgentInfo getAgentInfo(String applicationName, String agentId, long startTimeStamp) { return getAgentInfo(applicationName, agentId, startTimeStamp, false); } @Override - public AgentInfoBo getAgentInfo(String applicationName, String agentId, long startTimeStamp, boolean checkDB) { + public AgentInfo getAgentInfo(String applicationName, String agentId, long startTimeStamp, boolean checkDB) { if (checkDB) { long currentTime = System.currentTimeMillis(); - Range range = new Range(currentTime, currentTime); - Set agentInfoBos = agentInfoService.selectAgent(applicationName, range); + Set agentInfoBos = agentInfoService.getAgentsByApplicationName(applicationName, currentTime); for (AgentInfoBo agentInfo : agentInfoBos) { if (agentInfo == null) { continue; @@ -97,51 +98,50 @@ public AgentInfoBo getAgentInfo(String applicationName, String agentId, long sta continue; } - return agentInfo; + return new AgentInfo(agentInfo); } return null; } else { - AgentInfoBo.Builder builder = new AgentInfoBo.Builder(); - builder.setApplicationName(applicationName); - builder.setAgentId(agentId); - builder.setStartTime(startTimeStamp); - return builder.build(); + AgentInfo agentInfo = new AgentInfo(); + agentInfo.setApplicationName(applicationName); + agentInfo.setAgentId(agentId); + agentInfo.setStartTimestamp(startTimeStamp); + return agentInfo; } } @Override - public List getAgentInfoList(String applicationName) { - List agentInfoList = new ArrayList(); + public List getAgentInfoList(String applicationName) { + List agentInfoList = new ArrayList(); long currentTime = System.currentTimeMillis(); - Range range = new Range(currentTime, currentTime); - Set agentInfoBos = agentInfoService.selectAgent(applicationName, range); - for (AgentInfoBo agentInfo : agentInfoBos) { - ListUtils.addIfValueNotNull(agentInfoList, agentInfo); + Set agentInfoBos = agentInfoService.getAgentsByApplicationName(applicationName, currentTime); + for (AgentInfoBo agentInfoBo : agentInfoBos) { + ListUtils.addIfValueNotNull(agentInfoList, new AgentInfo(agentInfoBo)); } return agentInfoList; } @Override - public PinpointRouteResponse invoke(AgentInfoBo agentInfo, TBase tBase) throws TException { + public PinpointRouteResponse invoke(AgentInfo agentInfo, TBase tBase) throws TException { byte[] payload = serialize(tBase); return invoke(agentInfo, payload); } @Override - public PinpointRouteResponse invoke(AgentInfoBo agentInfo, TBase tBase, long timeout) throws TException { + public PinpointRouteResponse invoke(AgentInfo agentInfo, TBase tBase, long timeout) throws TException { byte[] payload = serialize(tBase); return invoke(agentInfo, payload, timeout); } @Override - public PinpointRouteResponse invoke(AgentInfoBo agentInfo, byte[] payload) throws TException { + public PinpointRouteResponse invoke(AgentInfo agentInfo, byte[] payload) throws TException { return invoke(agentInfo, payload, DEFUALT_FUTURE_TIMEOUT); } @Override - public PinpointRouteResponse invoke(AgentInfoBo agentInfo, byte[] payload, long timeout) throws TException { + public PinpointRouteResponse invoke(AgentInfo agentInfo, byte[] payload, long timeout) throws TException { TCommandTransfer transferObject = createCommandTransferObject(agentInfo, payload); PinpointServer collector = pinpointSocketManager.getCollector(agentInfo); @@ -151,26 +151,26 @@ public PinpointRouteResponse invoke(AgentInfoBo agentInfo, byte[] payload, long } @Override - public Map invoke(List agentInfoList, TBase tBase) throws TException { + public Map invoke(List agentInfoList, TBase tBase) throws TException { byte[] payload = serialize(tBase); return invoke(agentInfoList, payload); } @Override - public Map invoke(List agentInfoList, TBase tBase, long timeout) throws TException { + public Map invoke(List agentInfoList, TBase tBase, long timeout) throws TException { byte[] payload = serialize(tBase); return invoke(agentInfoList, payload, timeout); } @Override - public Map invoke(List agentInfoList, byte[] payload) throws TException { + public Map invoke(List agentInfoList, byte[] payload) throws TException { return invoke(agentInfoList, payload, DEFUALT_FUTURE_TIMEOUT); } @Override - public Map invoke(List agentInfoList, byte[] payload, long timeout) throws TException { - Map> futureMap = new HashMap>(); - for (AgentInfoBo agentInfo : agentInfoList) { + public Map invoke(List agentInfoList, byte[] payload, long timeout) throws TException { + Map> futureMap = new HashMap>(); + for (AgentInfo agentInfo : agentInfoList) { TCommandTransfer transferObject = createCommandTransferObject(agentInfo, payload); PinpointServer collector = pinpointSocketManager.getCollector(agentInfo); Future future = collector.request(serialize(transferObject)); @@ -179,9 +179,9 @@ public Map invoke(List agentInf long startTime = System.currentTimeMillis(); - Map result = new HashMap(); - for (Map.Entry> futureEntry : futureMap.entrySet()) { - AgentInfoBo agentInfo = futureEntry.getKey(); + Map result = new HashMap(); + for (Map.Entry> futureEntry : futureMap.entrySet()) { + AgentInfo agentInfo = futureEntry.getKey(); Future future = futureEntry.getValue(); PinpointRouteResponse response = getResponse(future, getTimeoutMillis(startTime, timeout)); result.put(agentInfo, response); @@ -191,18 +191,18 @@ public Map invoke(List agentInf } @Override - public AgentActiveThreadStatusList getActiveThreadStatus(List agentInfoList) throws TException { + public AgentActiveThreadStatusList getActiveThreadStatus(List agentInfoList) throws TException { byte[] activeThread = serialize(new TActiveThread()); return getActiveThreadStatus(agentInfoList, activeThread); } @Override - public AgentActiveThreadStatusList getActiveThreadStatus(List agentInfoList, byte[] payload) throws TException { + public AgentActiveThreadStatusList getActiveThreadStatus(List agentInfoList, byte[] payload) throws TException { AgentActiveThreadStatusList agentActiveThreadStatusList = new AgentActiveThreadStatusList(agentInfoList.size()); - Map responseList = invoke(agentInfoList, payload); - for (Map.Entry entry : responseList.entrySet()) { - AgentInfoBo agentInfo = entry.getKey(); + Map responseList = invoke(agentInfoList, payload); + for (Map.Entry entry : responseList.entrySet()) { + AgentInfo agentInfo = entry.getKey(); PinpointRouteResponse response = entry.getValue(); AgentActiveThreadStatus agentActiveThreadStatus = new AgentActiveThreadStatus(agentInfo.getHostName(), response.getRouteResult(), response.getResponse(TActiveThreadResponse.class, null)); @@ -211,23 +211,23 @@ public AgentActiveThreadStatusList getActiveThreadStatus(List agent return agentActiveThreadStatusList; } - private byte[] serialize(TBase tBase) throws TException { + private byte[] serialize(TBase tBase) throws TException { return SerializationUtils.serialize(tBase, commandSerializerFactory); } - private TBase deserialize(byte[] objectData) throws TException { + private TBase deserialize(byte[] objectData) throws TException { return SerializationUtils.deserialize(objectData, commandDeserializerFactory); } - private TBase deserialize(byte[] objectData, TBase defaultValue) throws TException { + private TBase deserialize(byte[] objectData, TBase defaultValue) throws TException { return SerializationUtils.deserialize(objectData, commandDeserializerFactory, defaultValue); } - private TCommandTransfer createCommandTransferObject(AgentInfoBo agentInfo, byte[] payload) { + private TCommandTransfer createCommandTransferObject(AgentInfo agentInfo, byte[] payload) { TCommandTransfer transferObject = new TCommandTransfer(); transferObject.setApplicationName(agentInfo.getApplicationName()); transferObject.setAgentId(agentInfo.getAgentId()); - transferObject.setStartTime(agentInfo.getStartTime()); + transferObject.setStartTime(agentInfo.getStartTimestamp()); transferObject.setPayload(payload); return transferObject; diff --git a/web/src/main/java/com/navercorp/pinpoint/web/view/AgentLifeCycleStateSerializer.java b/web/src/main/java/com/navercorp/pinpoint/web/view/AgentLifeCycleStateSerializer.java new file mode 100644 index 0000000000000..512fea0986619 --- /dev/null +++ b/web/src/main/java/com/navercorp/pinpoint/web/view/AgentLifeCycleStateSerializer.java @@ -0,0 +1,40 @@ +/* + * 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.view; + +import java.io.IOException; + +import com.fasterxml.jackson.core.JsonGenerator; +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.JsonSerializer; +import com.fasterxml.jackson.databind.SerializerProvider; +import com.navercorp.pinpoint.common.util.AgentLifeCycleState; + +/** + * @author HyunGil Jeong + */ +public class AgentLifeCycleStateSerializer extends JsonSerializer { + + @Override + public void serialize(AgentLifeCycleState value, JsonGenerator jgen, SerializerProvider provider) throws IOException, JsonProcessingException { + jgen.writeStartObject(); + jgen.writeNumberField("code", value.getCode()); + jgen.writeStringField("desc", value.getDesc()); + jgen.writeEndObject(); + } + +} diff --git a/web/src/main/java/com/navercorp/pinpoint/web/view/ApplicationAgentListSerializer.java b/web/src/main/java/com/navercorp/pinpoint/web/view/ApplicationAgentListSerializer.java index 80b3fa3ad568a..75519573cb810 100644 --- a/web/src/main/java/com/navercorp/pinpoint/web/view/ApplicationAgentListSerializer.java +++ b/web/src/main/java/com/navercorp/pinpoint/web/view/ApplicationAgentListSerializer.java @@ -20,10 +20,13 @@ import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.JsonSerializer; import com.fasterxml.jackson.databind.SerializerProvider; -import com.navercorp.pinpoint.common.bo.AgentInfoBo; +import com.navercorp.pinpoint.common.util.AgentLifeCycleState; import com.navercorp.pinpoint.web.applicationmap.link.MatcherGroup; import com.navercorp.pinpoint.web.applicationmap.link.ServerMatcher; +import com.navercorp.pinpoint.web.vo.AgentInfo; +import com.navercorp.pinpoint.web.vo.AgentStatus; import com.navercorp.pinpoint.web.vo.ApplicationAgentList; + import org.springframework.beans.factory.annotation.Autowired; import java.io.IOException; @@ -32,48 +35,58 @@ /** * @author minwoo.jung + * @author HyunGil Jeong */ public class ApplicationAgentListSerializer extends JsonSerializer { - @Autowired(required=false) + @Autowired(required = false) private MatcherGroup matcherGroup; - @Override - public void serialize(ApplicationAgentList applicationAgentList, JsonGenerator jgen, SerializerProvider provider) throws IOException, JsonProcessingException { + public void serialize(ApplicationAgentList applicationAgentList, JsonGenerator jgen, SerializerProvider provider) throws IOException, + JsonProcessingException { jgen.writeStartObject(); - Map> map = applicationAgentList.getApplicationAgentList(); - - for (Map.Entry> entry : map.entrySet()) { + Map> map = applicationAgentList.getApplicationAgentList(); + + for (Map.Entry> entry : map.entrySet()) { jgen.writeFieldName(entry.getKey()); writeAgentList(jgen, entry.getValue(), getMatcherGroup()); } - jgen.writeEndObject(); } - - private void writeAgentList(JsonGenerator jgen, List agentList, MatcherGroup matcherGroup) throws IOException { + + private void writeAgentList(JsonGenerator jgen, List agentList, MatcherGroup matcherGroup) throws IOException { jgen.writeStartArray(); - for (AgentInfoBo agentInfoBo : agentList) { + for (AgentInfo agentInfo : agentList) { jgen.writeStartObject(); - jgen.writeStringField("hostName", agentInfoBo.getHostName()); - jgen.writeStringField("ip", agentInfoBo.getIp()); - jgen.writeStringField("ports", agentInfoBo.getPorts()); - jgen.writeStringField("agentId", agentInfoBo.getAgentId()); - jgen.writeStringField("applicationName", agentInfoBo.getApplicationName()); - jgen.writeStringField("serviceType", agentInfoBo.getServiceType().toString()); - jgen.writeNumberField("pid", agentInfoBo.getPid()); - jgen.writeStringField("version", agentInfoBo.getVersion()); - jgen.writeNumberField("startTime", agentInfoBo.getStartTime()); - jgen.writeNumberField("endTimeStamp", agentInfoBo.getEndTimeStamp()); - jgen.writeNumberField("endStatus", agentInfoBo.getEndStatus()); - jgen.writeObjectField("serverMetaData", agentInfoBo.getServerMetaData()); + jgen.writeStringField("applicationName", agentInfo.getApplicationName()); + jgen.writeStringField("agentId", agentInfo.getAgentId()); + jgen.writeNumberField("startTime", agentInfo.getStartTimestamp()); + jgen.writeStringField("hostName", agentInfo.getHostName()); + jgen.writeStringField("ip", agentInfo.getIp()); + jgen.writeStringField("ports", agentInfo.getPorts()); + jgen.writeStringField("serviceType", agentInfo.getServiceType().toString()); + jgen.writeNumberField("pid", agentInfo.getPid()); + jgen.writeStringField("version", agentInfo.getVersion()); + jgen.writeObjectField("serverMetaData", agentInfo.getServerMetaData()); + + AgentStatus agentStatus = agentInfo.getStatus(); + if (agentStatus == null) { + jgen.writeNumberField("endTimeStamp", 0); + jgen.writeStringField("endStatus", AgentLifeCycleState.UNKNOWN.getDesc()); + } else { + jgen.writeNumberField("endTimeStamp", agentStatus.getEventTimestamp()); + jgen.writeStringField("endStatus", agentStatus.getState().getDesc()); + } + jgen.writeObjectField("status", agentStatus); - ServerMatcher serverMatcher = matcherGroup.match(agentInfoBo.getHostName()); + jgen.writeNumberField("initialStartTime", agentInfo.getInitialStartTimestamp()); + + ServerMatcher serverMatcher = matcherGroup.match(agentInfo.getHostName()); jgen.writeStringField("linkName", serverMatcher.getLinkName()); - jgen.writeStringField("linkURL", serverMatcher.getLink(agentInfoBo.getHostName())); - + jgen.writeStringField("linkURL", serverMatcher.getLink(agentInfo.getHostName())); + jgen.writeEndObject(); } jgen.writeEndArray(); diff --git a/web/src/main/java/com/navercorp/pinpoint/web/vo/AgentEvent.java b/web/src/main/java/com/navercorp/pinpoint/web/vo/AgentEvent.java new file mode 100644 index 0000000000000..91737a998c6e2 --- /dev/null +++ b/web/src/main/java/com/navercorp/pinpoint/web/vo/AgentEvent.java @@ -0,0 +1,166 @@ +/* + * 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; + +import java.util.Comparator; + +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonInclude.Include; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.navercorp.pinpoint.common.util.AgentEventType; + +/** + * @author HyunGil Jeong + */ +@JsonInclude(Include.NON_NULL) +public class AgentEvent { + + public static final Comparator EVENT_TIMESTAMP_DESC_COMPARATOR = new Comparator() { + @Override + public int compare(AgentEvent o1, AgentEvent o2) { + int eventTimestampComparison = Long.compare(o2.eventTimestamp, o1.eventTimestamp); + if (eventTimestampComparison == 0) { + return o1.eventTypeCode - o2.eventTypeCode; + } + return eventTimestampComparison; + } + }; + + @JsonProperty + private final String agentId; + + @JsonProperty + private final long eventTimestamp; + + @JsonProperty + private final int eventTypeCode; + + @JsonProperty + private final String eventTypeDesc; + + @JsonProperty + private final boolean hasEventMessage; + + @JsonProperty + private long startTimestamp; + + @JsonProperty + private Object eventMessage; + + public AgentEvent(String agentId, long eventTimestamp, AgentEventType eventType) { + if (agentId == null) { + throw new NullPointerException("agentId must not be null"); + } + if (eventTimestamp < 0) { + throw new IllegalArgumentException("eventTimestamp must not be null"); + } + if (eventType == null) { + throw new NullPointerException("eventType must not be null"); + } + this.agentId = agentId; + this.eventTimestamp = eventTimestamp; + this.eventTypeCode = eventType.getCode(); + this.eventTypeDesc = eventType.getDesc(); + this.hasEventMessage = eventType.getMessageType() != Void.class; + } + + public String getAgentId() { + return agentId; + } + + public long getEventTimestamp() { + return eventTimestamp; + } + + public int getEventTypeCode() { + return eventTypeCode; + } + + public String getEventTypeDesc() { + return eventTypeDesc; + } + + public boolean hasEventMessage() { + return this.hasEventMessage; + } + + public long getStartTimestamp() { + return startTimestamp; + } + + public void setStartTimestamp(long startTimestamp) { + this.startTimestamp = startTimestamp; + } + + public Object getEventMessage() { + return eventMessage; + } + + public void setEventMessage(Object eventMessage) { + this.eventMessage = eventMessage; + } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + ((agentId == null) ? 0 : agentId.hashCode()); + result = prime * result + (int)(eventTimestamp ^ (eventTimestamp >>> 32)); + result = prime * result + eventTypeCode; + result = prime * result + ((eventTypeDesc == null) ? 0 : eventTypeDesc.hashCode()); + result = prime * result + (hasEventMessage ? 1231 : 1237); + result = prime * result + (int)(startTimestamp ^ (startTimestamp >>> 32)); + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) + return true; + if (obj == null) + return false; + if (getClass() != obj.getClass()) + return false; + AgentEvent other = (AgentEvent)obj; + if (agentId == null) { + if (other.agentId != null) + return false; + } else if (!agentId.equals(other.agentId)) + return false; + if (eventTimestamp != other.eventTimestamp) + return false; + if (eventTypeCode != other.eventTypeCode) + return false; + if (eventTypeDesc == null) { + if (other.eventTypeDesc != null) + return false; + } else if (!eventTypeDesc.equals(other.eventTypeDesc)) + return false; + if (hasEventMessage != other.hasEventMessage) + return false; + if (startTimestamp != other.startTimestamp) + return false; + return true; + } + + @Override + public String toString() { + return "AgentEvent [agentId=" + agentId + ", eventTimestamp=" + eventTimestamp + ", eventTypeCode=" + + eventTypeCode + ", eventTypeDesc=" + eventTypeDesc + ", hasEventMessage=" + hasEventMessage + + ", startTimestamp=" + startTimestamp + ", eventMessage=" + eventMessage + "]"; + } +} diff --git a/web/src/main/java/com/navercorp/pinpoint/web/vo/AgentInfo.java b/web/src/main/java/com/navercorp/pinpoint/web/vo/AgentInfo.java new file mode 100644 index 0000000000000..4423c6d7c199d --- /dev/null +++ b/web/src/main/java/com/navercorp/pinpoint/web/vo/AgentInfo.java @@ -0,0 +1,258 @@ +/* + * 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; + +import java.util.Comparator; + +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonInclude.Include; +import com.navercorp.pinpoint.common.bo.AgentInfoBo; +import com.navercorp.pinpoint.common.bo.ServerMetaDataBo; + +/** + * @author HyunGil Jeong + */ +public class AgentInfo { + + public static final Comparator AGENT_NAME_ASC_COMPARATOR = new Comparator() { + @Override + public int compare(AgentInfo lhs, AgentInfo rhs) { + final String lhsAgentId = lhs.agentId == null ? "" : lhs.agentId; + final String rhsAgentId = rhs.agentId == null ? "" : rhs.agentId; + return lhsAgentId.compareTo(rhsAgentId); + } + }; + + private String applicationName; + private String agentId; + private long startTimestamp; + private String hostName; + private String ip; + private String ports; + private String serviceType; + private int pid; + private String version; + private ServerMetaDataBo serverMetaData; + + @JsonInclude(Include.NON_DEFAULT) + private long initialStartTimestamp; + + @JsonInclude(Include.NON_NULL) + private AgentStatus status; + + public AgentInfo() { + } + + public AgentInfo(AgentInfoBo agentInfoBo) { + this.applicationName = agentInfoBo.getApplicationName(); + this.agentId = agentInfoBo.getAgentId(); + this.startTimestamp = agentInfoBo.getStartTime(); + this.hostName = agentInfoBo.getHostName(); + this.ip = agentInfoBo.getIp(); + this.ports = agentInfoBo.getPorts(); + this.serviceType = agentInfoBo.getServiceType().getName(); + this.pid = agentInfoBo.getPid(); + this.version = agentInfoBo.getVersion(); + this.serverMetaData = agentInfoBo.getServerMetaData(); + } + + public String getApplicationName() { + return applicationName; + } + + public void setApplicationName(String applicationName) { + this.applicationName = applicationName; + } + + public String getAgentId() { + return agentId; + } + + public void setAgentId(String agentId) { + this.agentId = agentId; + } + + public long getStartTimestamp() { + return startTimestamp; + } + + public void setStartTimestamp(long startTimestamp) { + this.startTimestamp = startTimestamp; + } + + public String getHostName() { + return hostName; + } + + public void setHostName(String hostName) { + this.hostName = hostName; + } + + public String getIp() { + return ip; + } + + public void setIp(String ip) { + this.ip = ip; + } + + public String getPorts() { + return ports; + } + + public void setPorts(String ports) { + this.ports = ports; + } + + public String getServiceType() { + return serviceType; + } + + public void setServiceType(String serviceType) { + this.serviceType = serviceType; + } + + public int getPid() { + return pid; + } + + public void setPid(int pid) { + this.pid = pid; + } + + public String getVersion() { + return version; + } + + public void setVersion(String version) { + this.version = version; + } + + public ServerMetaDataBo getServerMetaData() { + return serverMetaData; + } + + public void setServerMetaData(ServerMetaDataBo serverMetaData) { + this.serverMetaData = serverMetaData; + } + + public long getInitialStartTimestamp() { + return initialStartTimestamp; + } + + public void setInitialStartTimestamp(long initialStartTimestamp) { + this.initialStartTimestamp = initialStartTimestamp; + } + + public AgentStatus getStatus() { + return status; + } + + public void setStatus(AgentStatus status) { + this.status = status; + } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + ((agentId == null) ? 0 : agentId.hashCode()); + result = prime * result + ((applicationName == null) ? 0 : applicationName.hashCode()); + result = prime * result + ((hostName == null) ? 0 : hostName.hashCode()); + result = prime * result + (int)(initialStartTimestamp ^ (initialStartTimestamp >>> 32)); + result = prime * result + ((ip == null) ? 0 : ip.hashCode()); + result = prime * result + pid; + result = prime * result + ((ports == null) ? 0 : ports.hashCode()); + result = prime * result + ((serverMetaData == null) ? 0 : serverMetaData.hashCode()); + result = prime * result + ((serviceType == null) ? 0 : serviceType.hashCode()); + result = prime * result + (int)(startTimestamp ^ (startTimestamp >>> 32)); + result = prime * result + ((status == null) ? 0 : status.hashCode()); + result = prime * result + ((version == null) ? 0 : version.hashCode()); + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) + return true; + if (obj == null) + return false; + if (getClass() != obj.getClass()) + return false; + AgentInfo other = (AgentInfo)obj; + if (agentId == null) { + if (other.agentId != null) + return false; + } else if (!agentId.equals(other.agentId)) + return false; + if (applicationName == null) { + if (other.applicationName != null) + return false; + } else if (!applicationName.equals(other.applicationName)) + return false; + if (hostName == null) { + if (other.hostName != null) + return false; + } else if (!hostName.equals(other.hostName)) + return false; + if (initialStartTimestamp != other.initialStartTimestamp) + return false; + if (ip == null) { + if (other.ip != null) + return false; + } else if (!ip.equals(other.ip)) + return false; + if (pid != other.pid) + return false; + if (ports == null) { + if (other.ports != null) + return false; + } else if (!ports.equals(other.ports)) + return false; + if (serverMetaData == null) { + if (other.serverMetaData != null) + return false; + } else if (!serverMetaData.equals(other.serverMetaData)) + return false; + if (serviceType == null) { + if (other.serviceType != null) + return false; + } else if (!serviceType.equals(other.serviceType)) + return false; + if (startTimestamp != other.startTimestamp) + return false; + if (status == null) { + if (other.status != null) + return false; + } else if (!status.equals(other.status)) + return false; + if (version == null) { + if (other.version != null) + return false; + } else if (!version.equals(other.version)) + return false; + return true; + } + + @Override + public String toString() { + return "AgentInfo [applicationName=" + applicationName + ", agentId=" + agentId + ", startTimestamp=" + startTimestamp + ", hostName=" + hostName + + ", ip=" + ip + ", ports=" + ports + ", serviceType=" + serviceType + ", pid=" + pid + ", version=" + version + ", serverMetaData=" + + serverMetaData + ", initialStartTimestamp=" + initialStartTimestamp + ", status=" + status + "]"; + } + +} diff --git a/web/src/main/java/com/navercorp/pinpoint/web/vo/AgentStatus.java b/web/src/main/java/com/navercorp/pinpoint/web/vo/AgentStatus.java index 8dbd4a788ad43..6f19ee3e029d2 100644 --- a/web/src/main/java/com/navercorp/pinpoint/web/vo/AgentStatus.java +++ b/web/src/main/java/com/navercorp/pinpoint/web/vo/AgentStatus.java @@ -16,34 +16,109 @@ package com.navercorp.pinpoint.web.vo; -import com.navercorp.pinpoint.common.bo.AgentInfoBo; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonInclude.Include; +import com.fasterxml.jackson.databind.annotation.JsonSerialize; +import com.navercorp.pinpoint.common.bo.AgentLifeCycleBo; +import com.navercorp.pinpoint.common.util.AgentLifeCycleState; +import com.navercorp.pinpoint.web.view.AgentLifeCycleStateSerializer; /** * * @author netspider - * + * @author HyunGil Jeong */ public class AgentStatus { - private final boolean exists; - private final long checkTime; - private final AgentInfoBo agentInfo; + private String agentId; + + @JsonInclude(Include.NON_DEFAULT) + private long startTimestamp; + + @JsonInclude(Include.NON_DEFAULT) + private long eventTimestamp; + + @JsonSerialize(using = AgentLifeCycleStateSerializer.class) + private AgentLifeCycleState state; + + public AgentStatus() { + } + + public AgentStatus(AgentLifeCycleBo agentLifeCycleBo) { + this.agentId = agentLifeCycleBo.getAgentId(); + this.startTimestamp = agentLifeCycleBo.getStartTimestamp(); + this.eventTimestamp = agentLifeCycleBo.getEventTimestamp(); + this.state = agentLifeCycleBo.getAgentLifeCycleState(); + } + + public String getAgentId() { + return agentId; + } + + public void setAgentId(String agentId) { + this.agentId = agentId; + } + + public long getStartTimestamp() { + return startTimestamp; + } + + public void setStartTimestamp(long startTimestamp) { + this.startTimestamp = startTimestamp; + } + + public long getEventTimestamp() { + return eventTimestamp; + } + + public void setEventTimestamp(long eventTimestamp) { + this.eventTimestamp = eventTimestamp; + } + + public AgentLifeCycleState getState() { + return state; + } - public AgentStatus(AgentInfoBo agentInfoBo) { - this.exists = agentInfoBo != null; - this.agentInfo = agentInfoBo; - this.checkTime = System.currentTimeMillis(); + public void setState(AgentLifeCycleState state) { + this.state = state; } - public boolean isExists() { - return exists; + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + ((agentId == null) ? 0 : agentId.hashCode()); + result = prime * result + (int)(eventTimestamp ^ (eventTimestamp >>> 32)); + result = prime * result + (int)(startTimestamp ^ (startTimestamp >>> 32)); + result = prime * result + ((state == null) ? 0 : state.hashCode()); + return result; } - public AgentInfoBo getAgentInfo() { - return agentInfo; + @Override + public boolean equals(Object obj) { + if (this == obj) + return true; + if (obj == null) + return false; + if (getClass() != obj.getClass()) + return false; + AgentStatus other = (AgentStatus)obj; + if (agentId == null) { + if (other.agentId != null) + return false; + } else if (!agentId.equals(other.agentId)) + return false; + if (eventTimestamp != other.eventTimestamp) + return false; + if (startTimestamp != other.startTimestamp) + return false; + if (state != other.state) + return false; + return true; } - public long getCheckTime() { - return checkTime; + @Override + public String toString() { + return "AgentStatus [agentId=" + agentId + ", startTimestamp=" + startTimestamp + ", eventTimestamp=" + eventTimestamp + ", state=" + state + "]"; } } diff --git a/web/src/main/java/com/navercorp/pinpoint/web/vo/ApplicationAgentList.java b/web/src/main/java/com/navercorp/pinpoint/web/vo/ApplicationAgentList.java index c9cfdb9ff85b2..c2364bddb59f0 100644 --- a/web/src/main/java/com/navercorp/pinpoint/web/vo/ApplicationAgentList.java +++ b/web/src/main/java/com/navercorp/pinpoint/web/vo/ApplicationAgentList.java @@ -17,7 +17,6 @@ package com.navercorp.pinpoint.web.vo; import com.fasterxml.jackson.databind.annotation.JsonSerialize; -import com.navercorp.pinpoint.common.bo.AgentInfoBo; import com.navercorp.pinpoint.web.view.ApplicationAgentListSerializer; import java.util.List; @@ -29,13 +28,13 @@ @JsonSerialize(using = ApplicationAgentListSerializer.class) public class ApplicationAgentList { - SortedMap> applicationAgentList; + SortedMap> applicationAgentList; - public ApplicationAgentList(SortedMap> applicationAgentList) { + public ApplicationAgentList(SortedMap> applicationAgentList) { this.applicationAgentList = applicationAgentList; } - public SortedMap> getApplicationAgentList() { + public SortedMap> getApplicationAgentList() { return this.applicationAgentList; } diff --git a/web/src/main/java/com/navercorp/pinpoint/web/websocket/ActiveThreadHandler.java b/web/src/main/java/com/navercorp/pinpoint/web/websocket/ActiveThreadHandler.java index 4b66cce2c660e..8517191e78910 100644 --- a/web/src/main/java/com/navercorp/pinpoint/web/websocket/ActiveThreadHandler.java +++ b/web/src/main/java/com/navercorp/pinpoint/web/websocket/ActiveThreadHandler.java @@ -20,11 +20,12 @@ package com.navercorp.pinpoint.web.websocket; import com.fasterxml.jackson.databind.ObjectMapper; -import com.navercorp.pinpoint.common.bo.AgentInfoBo; import com.navercorp.pinpoint.common.util.PinpointThreadFactory; import com.navercorp.pinpoint.rpc.util.TimerFactory; import com.navercorp.pinpoint.web.service.AgentService; import com.navercorp.pinpoint.web.vo.AgentActiveThreadStatusList; +import com.navercorp.pinpoint.web.vo.AgentInfo; + import org.apache.http.NameValuePair; import org.apache.http.client.utils.URLEncodedUtils; import org.jboss.netty.util.Timeout; @@ -181,7 +182,7 @@ public void run(Timeout timeout) throws Exception { readLock.lock(); try { for (Map.Entry> applicationEntry : applicationGroup.entrySet()) { - List agentInfoList = agentSerivce.getAgentInfoList(applicationEntry.getKey()); + List agentInfoList = agentSerivce.getAgentInfoList(applicationEntry.getKey()); AgentActiveThreadStatusList agentActiveThreadStatusList = agentSerivce.getActiveThreadStatus(agentInfoList); String textMessage = jsonConverter.writeValueAsString(agentActiveThreadStatusList); diff --git a/web/src/main/resources/applicationContext-web.xml b/web/src/main/resources/applicationContext-web.xml index a706b4defa621..ae3018d23ad48 100644 --- a/web/src/main/resources/applicationContext-web.xml +++ b/web/src/main/resources/applicationContext-web.xml @@ -81,6 +81,10 @@ + + + +