Skip to content

Commit

Permalink
pinpoint-apm#84 Add web support for handling Agent lifecycle and events
Browse files Browse the repository at this point in the history
  • Loading branch information
Xylus committed Aug 31, 2015
1 parent 3f1a789 commit 72ec81b
Show file tree
Hide file tree
Showing 27 changed files with 1,471 additions and 278 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@ public static AgentEventType getTypeByCode(int code) {
return eventType;
}
}
return OTHER;
return null;
}

public static Set<AgentEventType> getTypesByCatgory(AgentEventTypeCategory category) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -379,7 +379,7 @@ private void appendServerInfo(Node node, LinkDataDuplexMap linkDataDuplexMap, Ag
ServerInstanceList serverInstanceList = builder.build();
node.setServerInstanceList(serverInstanceList);
} else if (nodeServiceType.isWas()) {
Set<AgentInfoBo> agentList = agentInfoService.selectAgent(node.getApplication().getName(), range);
Set<AgentInfoBo> agentList = agentInfoService.getAgentsByApplicationName(node.getApplication().getName(), range.getTo());
if (agentList.isEmpty()) {
logger.warn("agentInfo not found. applicationName:{}", node.getApplication());
// avoid NPE
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -40,6 +45,7 @@
/**
* @author emeroad
* @author minwoo.jung
* @author HyunGil Jeong
*/
@Controller
public class AgentStatController {
Expand All @@ -51,6 +57,9 @@ public class AgentStatController {

@Autowired
private AgentInfoService agentInfoService;

@Autowired
private AgentEventService agentEventService;

@RequestMapping(value = "/getAgentStat", method = RequestMethod.GET)
@ResponseBody
Expand All @@ -72,26 +81,62 @@ 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();

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<AgentEvent> 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);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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;
Expand Down Expand Up @@ -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));
}
Expand All @@ -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) {
Expand All @@ -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));
}
Expand All @@ -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) {
Expand Down
Original file line number Diff line number Diff line change
@@ -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<AgentEventBo> getAgentEvents(String agentId, Range range);

}
Original file line number Diff line number Diff line change
Expand Up @@ -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<AgentInfoBo> getAgentInfo(String agentId, Range range);

AgentInfoBo getAgentInfo(String agentId, long timestamp);
AgentInfoBo getInitialAgentInfo(String agentId);
}
Original file line number Diff line number Diff line change
@@ -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);

}
Original file line number Diff line number Diff line change
@@ -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<List<AgentEventBo>> agentEventMapper;

@Override
public List<AgentEventBo> 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<AgentEventBo> 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<AgentEventBo> 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<List<AgentEventBo>> {

@Override
public List<AgentEventBo> extractData(ResultScanner results) throws Exception {
List<AgentEventBo> agentEvents = new ArrayList<AgentEventBo>();
int rowNum = 0;
for (Result result : results) {
List<AgentEventBo> intermediateEvents = agentEventMapper.mapRow(result, rowNum++);
if (!intermediateEvents.isEmpty()) {
agentEvents.addAll(intermediateEvents);
}
}
return agentEvents;
}

}

}
Loading

0 comments on commit 72ec81b

Please # to comment.