Merge pull request #813 from koo-taejin/active_thread

Trace current active requests info. #751
This commit is contained in:
koo-taejin
2015-08-05 16:44:15 +09:00
14 changed files with 675 additions and 0 deletions
+5
View File
@@ -207,6 +207,11 @@
<artifactId>spring-webmvc</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-websocket</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
@@ -30,6 +30,11 @@ public class TimerFactory {
public static HashedWheelTimer createHashedWheelTimer(String threadName, long tickDuration, TimeUnit unit, int ticksPerWheel) {
final PinpointThreadFactory threadFactory = new PinpointThreadFactory(threadName, true);
return createHashedWheelTimer(threadFactory, tickDuration, unit, ticksPerWheel);
}
public static HashedWheelTimer createHashedWheelTimer(PinpointThreadFactory threadFactory, long tickDuration, TimeUnit unit, int ticksPerWheel) {
return new HashedWheelTimer(threadFactory, ThreadNameDeterminer.CURRENT, tickDuration, unit, ticksPerWheel);
}
}
+4
View File
@@ -121,6 +121,10 @@
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-websocket</artifactId>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
@@ -0,0 +1,55 @@
/*
*
* * Copyright 2014 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.config;
import com.navercorp.pinpoint.web.websocket.PinpointWebSocketHandler;
import com.navercorp.pinpoint.web.websocket.WebSocketHandlerRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.stereotype.Component;
import org.springframework.web.socket.WebSocketHandler;
import org.springframework.web.socket.config.annotation.EnableWebSocket;
import org.springframework.web.socket.config.annotation.WebSocketConfigurer;
import org.springframework.web.socket.config.annotation.WebSocketHandlerRegistry;
import org.springframework.web.socket.server.support.HttpSessionHandshakeInterceptor;
/**
* @Author Taejin Koo
*/
@Configuration
@EnableWebSocket
@Component
public class WebSocketConfig implements WebSocketConfigurer {
private static final String WEBSOCKET_SUFFIX = ".pinpointws";
@Autowired
private WebSocketHandlerRepository handlerRepository;
@Override
public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) {
for (PinpointWebSocketHandler handler : handlerRepository.getWebSocketHandlerRepository()) {
registry.addHandler(handler, handler.getRequestMapping() + WEBSOCKET_SUFFIX).addInterceptors(new HttpSessionHandshakeInterceptor());
}
}
}
@@ -26,6 +26,7 @@ import java.util.Map;
import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
import com.navercorp.pinpoint.common.bo.AgentInfoBo;
import org.apache.zookeeper.KeeperException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -113,6 +114,10 @@ public class PinpointSocketManager {
return serverAcceptor.getWritableServerList();
}
public PinpointServer getCollector(AgentInfoBo agentInfo) {
return getCollector(agentInfo.getApplicationName(), agentInfo.getAgentId(), agentInfo.getStartTime());
}
public PinpointServer getCollector(String applicationName, String agentId, long startTimeStamp) {
List<String> agentNameList = clusterManager.getRegisteredAgentList(applicationName, agentId, startTimeStamp);
@@ -0,0 +1,41 @@
/*
*
* * Copyright 2014 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 com.navercorp.pinpoint.common.bo.AgentInfoBo;
import com.navercorp.pinpoint.thrift.dto.command.TActiveThreadResponse;
import org.apache.thrift.TBase;
import org.apache.thrift.TException;
import java.util.List;
import java.util.Map;
/**
* @Author Taejin Koo
*/
public interface AgentService {
List<AgentInfoBo> get(String applicationName);
Map<String, TActiveThreadResponse> getActiveThreadStatus(List<AgentInfoBo> agentInfoList) throws TException;
Map<String, TActiveThreadResponse> getActiveThreadStatus(List<AgentInfoBo> agentInfoList, byte[] payload) throws TException;
}
@@ -0,0 +1,133 @@
/*
*
* * Copyright 2014 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 com.navercorp.pinpoint.common.bo.AgentInfoBo;
import com.navercorp.pinpoint.rpc.Future;
import com.navercorp.pinpoint.rpc.ResponseMessage;
import com.navercorp.pinpoint.rpc.server.PinpointServer;
import com.navercorp.pinpoint.rpc.util.ListUtils;
import com.navercorp.pinpoint.thrift.dto.command.TActiveThread;
import com.navercorp.pinpoint.thrift.dto.command.TActiveThreadResponse;
import com.navercorp.pinpoint.thrift.dto.command.TCommandTransfer;
import com.navercorp.pinpoint.thrift.io.DeserializerFactory;
import com.navercorp.pinpoint.thrift.io.HeaderTBaseDeserializer;
import com.navercorp.pinpoint.thrift.io.HeaderTBaseSerializer;
import com.navercorp.pinpoint.thrift.io.SerializerFactory;
import com.navercorp.pinpoint.thrift.util.SerializationUtils;
import com.navercorp.pinpoint.web.server.PinpointSocketManager;
import com.navercorp.pinpoint.web.vo.Range;
import org.apache.thrift.TBase;
import org.apache.thrift.TException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.*;
/**
* @Author Taejin Koo
*/
@Service
public class AgentServiceImpl implements AgentService {
@Autowired
private AgentInfoService agentInfoService;
@Autowired
private PinpointSocketManager pinpointSocketManager;
@Autowired
private SerializerFactory<HeaderTBaseSerializer> commandSerializerFactory;
@Autowired
private DeserializerFactory<HeaderTBaseDeserializer> commandDeserializerFactory;
@Override
public List<AgentInfoBo> get(String applicationName) {
List<AgentInfoBo> agentInfoList = new ArrayList<AgentInfoBo>();
long currentTime = System.currentTimeMillis();
Range range = new Range(currentTime, currentTime);
SortedMap<String, List<AgentInfoBo>> applicationAgentList = agentInfoService.getApplicationAgentList(applicationName, range);
for (Map.Entry<String, List<AgentInfoBo>> entry : applicationAgentList.entrySet()) {
AgentInfoBo agentInfo = ListUtils.getFirst(entry.getValue(), null);
ListUtils.addIfValueNotNull(agentInfoList, agentInfo);
}
return agentInfoList;
}
@Override
public Map<String, TActiveThreadResponse> getActiveThreadStatus(List<AgentInfoBo> agentInfoList) throws TException {
byte[] activeThread = serialize(new TActiveThread());
return getActiveThreadStatus(agentInfoList, activeThread);
}
@Override
public Map<String, TActiveThreadResponse> getActiveThreadStatus(List<AgentInfoBo> agentInfoList, byte[] payload) throws TException {
Map<String, Future<ResponseMessage>> futureMap = invoke(agentInfoList, payload);
Map<String, TActiveThreadResponse> responseMap = new HashMap<String, TActiveThreadResponse>();
for (Map.Entry<String, Future<ResponseMessage>> futureEntry : futureMap.entrySet()) {
String hostName = futureEntry.getKey();
Future<ResponseMessage> future = futureEntry.getValue();
future.await();
ResponseMessage responseMessage = future.getResult();
TBase result = deserialize(responseMessage.getMessage());
if (result instanceof TActiveThreadResponse) {
responseMap.put(hostName, (TActiveThreadResponse) result);
}
}
return responseMap;
}
private Map<String, Future<ResponseMessage>> invoke(List<AgentInfoBo> agentInfoList, byte[] payload) throws TException {
Map<String, Future<ResponseMessage>> futureMap = new HashMap<String, Future<ResponseMessage>>();
for (AgentInfoBo agentInfo : agentInfoList) {
TCommandTransfer transferObject = createCommandTransferObject(agentInfo, payload);
PinpointServer collector = pinpointSocketManager.getCollector(agentInfo);
Future<ResponseMessage> future = collector.request(serialize(transferObject));
futureMap.put(agentInfo.getHostName(), future);
}
return futureMap;
}
private byte[] serialize(TBase tBase) throws TException {
return SerializationUtils.serialize(tBase, commandSerializerFactory);
}
private TBase deserialize(byte[] objectData) throws TException {
return SerializationUtils.deserialize(objectData, commandDeserializerFactory);
}
private TCommandTransfer createCommandTransferObject(AgentInfoBo agentInfo, byte[] payload) {
TCommandTransfer transferObject = new TCommandTransfer();
transferObject.setApplicationName(agentInfo.getApplicationName());
transferObject.setAgentId(agentInfo.getAgentId());
transferObject.setStartTime(agentInfo.getStartTime());
transferObject.setPayload(payload);
return transferObject;
}
}
@@ -0,0 +1,97 @@
/*
*
* * Copyright 2014 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 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.fasterxml.jackson.databind.annotation.JsonSerialize;
import com.navercorp.pinpoint.thrift.dto.command.TActiveThreadResponse;
import java.io.IOException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* @Author Taejin Koo
*/
@JsonSerialize(using = AgentActiveThreadStatusListSerializer.class)
public class AgentActiveThreadStatusList {
private final Map<String, TActiveThreadResponse> agentActiveThreadReposioty;
public AgentActiveThreadStatusList(Map<String, TActiveThreadResponse> agentActiveThreadReposioty) {
this.agentActiveThreadReposioty = new HashMap<String, TActiveThreadResponse>();
}
public AgentActiveThreadStatusList(int initialCapacity) {
agentActiveThreadReposioty = new HashMap<String, TActiveThreadResponse>(initialCapacity);
}
public void add(String hostName, TActiveThreadResponse activeThreadStatus) {
agentActiveThreadReposioty.put(hostName, activeThreadStatus);
}
public void addAll(Map<String, TActiveThreadResponse> activeThreadStatuses) {
agentActiveThreadReposioty.putAll(activeThreadStatuses);
}
public Map<String, TActiveThreadResponse> getAgentActiveThreadReposioty() {
return agentActiveThreadReposioty;
}
}
class AgentActiveThreadStatusListSerializer extends JsonSerializer<AgentActiveThreadStatusList>
{
@Override
public void serialize(AgentActiveThreadStatusList agentActiveThreadStatusList, JsonGenerator jgen, SerializerProvider provider) throws IOException, JsonProcessingException {
Map<String, TActiveThreadResponse> agentActiveThreadReposioty = agentActiveThreadStatusList.getAgentActiveThreadReposioty();
jgen.writeStartObject();
for (Map.Entry<String, TActiveThreadResponse> entry : agentActiveThreadReposioty.entrySet()) {
List<Integer> activeThreadStatus = entry.getValue().getActiveThreadCount();
if (activeThreadStatus == null || activeThreadStatus.size() < 4) {
continue;
}
jgen.writeFieldName(entry.getKey());
jgen.writeStartObject();
jgen.writeFieldName("status");
jgen.writeStartArray();
jgen.writeNumber(activeThreadStatus.get(0));
jgen.writeNumber(activeThreadStatus.get(1));
jgen.writeNumber(activeThreadStatus.get(2));
jgen.writeNumber(activeThreadStatus.get(3));
jgen.writeEndArray();
jgen.writeNumberField("code", 0);
// will be added codeMessage
jgen.writeEndObject();
}
jgen.writeEndObject();
}
}
@@ -0,0 +1,208 @@
/*
*
* * Copyright 2014 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.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.thrift.dto.command.TActiveThreadResponse;
import com.navercorp.pinpoint.web.service.AgentService;
import com.navercorp.pinpoint.web.vo.AgentActiveThreadStatusList;
import org.apache.http.NameValuePair;
import org.apache.http.client.utils.URLEncodedUtils;
import org.jboss.netty.util.Timeout;
import org.jboss.netty.util.Timer;
import org.jboss.netty.util.TimerTask;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.socket.CloseStatus;
import org.springframework.web.socket.TextMessage;
import org.springframework.web.socket.WebSocketSession;
import org.springframework.web.socket.handler.TextWebSocketHandler;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReadWriteLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;
/**
* @Author Taejin Koo
*/
public class ActiveThreadHandler extends TextWebSocketHandler implements PinpointWebSocketHandler {
private static final String APPLICATION_NAME_KEY = "applicationName";
private static final String DEFAULT_REQUEST_MAPPING = "/agent/activeThread";
private final String requestMapping;
private final AgentService agentSerivce;
// it will be changed.
private final long time = 1000;
private final PinpointThreadFactory threadFactory = new PinpointThreadFactory("ActiveThread Handler", true);
private final TimerFactory timerFactory = new TimerFactory();
private final Map<String, List<WebSocketSession>> applicationGroup = new HashMap<String, List<WebSocketSession>>();
private final ReadWriteLock lock = new ReentrantReadWriteLock();
private final Lock readLock = lock.readLock();
private final Lock writeLock = lock.writeLock();
private final ObjectMapper jsonConverter = new ObjectMapper();
private final Logger logger = LoggerFactory.getLogger(this.getClass());
private Timer timer;
public ActiveThreadHandler(AgentService agentSerivce) {
this(DEFAULT_REQUEST_MAPPING, agentSerivce);
}
public ActiveThreadHandler(String requestMapping, AgentService agentSerivce) {
this.requestMapping = requestMapping;
this.agentSerivce = agentSerivce;
}
@Override
public String getRequestMapping() {
return requestMapping;
}
@Override
public void afterConnectionEstablished(WebSocketSession newSession) throws Exception {
logger.info("ConnectionEstablished : {}", newSession);
List<NameValuePair> params = URLEncodedUtils.parse(newSession.getUri(), "UTF-8");
String applicationName = getValue(params, APPLICATION_NAME_KEY);
if (applicationName == null) {
logger.warn("Connection established refused. required parameter is missiong({}).", APPLICATION_NAME_KEY);
newSession.close(CloseStatus.POLICY_VIOLATION);
}
newSession.getAttributes().put(APPLICATION_NAME_KEY, applicationName);
writeLock.lock();
try {
List<WebSocketSession> webSocketSessions = applicationGroup.get(applicationName);
if (webSocketSessions == null) {
webSocketSessions = new ArrayList<WebSocketSession>();
applicationGroup.put(applicationName, webSocketSessions);
}
webSocketSessions.add(newSession);
if (timer == null) {
timer = timerFactory.createHashedWheelTimer(threadFactory, 100, TimeUnit.MILLISECONDS, 512);
Timeout timeout = timer.newTimeout(new ActiveThreadTimerTask(), time, TimeUnit.MILLISECONDS);
}
} finally {
writeLock.unlock();
}
super.afterConnectionEstablished(newSession);
}
@Override
public void afterConnectionClosed(WebSocketSession closeSession, CloseStatus status) throws Exception {
logger.info("ConnectionClosed : {}, caused : {}", closeSession, status);
String applicationName = (String) closeSession.getAttributes().get(APPLICATION_NAME_KEY);
writeLock.lock();
try {
if (applicationName != null) {
List<WebSocketSession> webSocketSessions = applicationGroup.get(applicationName);
if (webSocketSessions == null) {
webSocketSessions = new ArrayList<WebSocketSession>();
}
webSocketSessions.remove(closeSession);
if (webSocketSessions.size() == 0) {
applicationGroup.remove(applicationName);
}
if (applicationGroup.size() == 0) {
if (timer != null) {
timer.stop();
timer = null;
}
}
}
} finally {
writeLock.unlock();
}
super.afterConnectionClosed(closeSession, status);
}
@Override
protected void handleTextMessage(WebSocketSession session, TextMessage message) throws Exception {
logger.info("handleTextMessage. session : {}, message : {}.", session, message);
// this method will be checked socket status.
super.handleTextMessage(session, message);
}
private String getValue(List<NameValuePair> params, String key) {
for (NameValuePair nv : params) {
if (key.equals(nv.getName())) {
return nv.getValue();
}
}
return null;
}
private class ActiveThreadTimerTask implements TimerTask {
@Override
public void run(Timeout timeout) throws Exception {
logger.info("ActiveThreadTimerTask started.");
readLock.lock();
try {
for (Map.Entry<String, List<WebSocketSession>> applicationEntry : applicationGroup.entrySet()) {
List<AgentInfoBo> agentInfoList = agentSerivce.get(applicationEntry.getKey());
Map<String, TActiveThreadResponse> activeThreadStatuses = agentSerivce.getActiveThreadStatus(agentInfoList);
AgentActiveThreadStatusList agentActiveThreadStatusList = new AgentActiveThreadStatusList(activeThreadStatuses.size());
agentActiveThreadStatusList.addAll(activeThreadStatuses);
String textMessage = jsonConverter.writeValueAsString(agentActiveThreadStatusList);
for (WebSocketSession session : applicationEntry.getValue()) {
session.sendMessage(new TextMessage(textMessage));
}
}
if (timer != null) {
timer.newTimeout(new ActiveThreadTimerTask(), time, TimeUnit.MILLISECONDS);
}
} finally {
readLock.unlock();
}
}
}
}
@@ -0,0 +1,31 @@
/*
*
* * Copyright 2014 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.websocket;
import org.springframework.web.socket.WebSocketHandler;
/**
* @Author Taejin Koo
*/
public interface PinpointWebSocketHandler extends WebSocketHandler {
String getRequestMapping();
}
@@ -0,0 +1,40 @@
/*
*
* * Copyright 2014 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.websocket;
import java.util.ArrayList;
import java.util.List;
/**
* @Author Taejin Koo
*/
public class WebSocketHandlerRepository {
private final List<PinpointWebSocketHandler> webSocketHandlerRepository;
public WebSocketHandlerRepository(List<PinpointWebSocketHandler> webSocketHandlerRepository) {
this.webSocketHandlerRepository = webSocketHandlerRepository;
}
public List<PinpointWebSocketHandler> getWebSocketHandlerRepository() {
return new ArrayList<PinpointWebSocketHandler>(webSocketHandlerRepository);
}
}
@@ -58,6 +58,8 @@
<import resource="classpath:applicationContext-cache.xml" />
<import resource="classpath:applicationContext-websocket.xml" />
<bean id="spanMapper" class="com.navercorp.pinpoint.web.mapper.SpanMapper"></bean>
<bean id="annotationMapper" class="com.navercorp.pinpoint.web.mapper.AnnotationMapper"></bean>
<bean id="spanAnnotationMapper" class="com.navercorp.pinpoint.web.mapper.SpanMapper">
@@ -0,0 +1,44 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
~ /*
~ * Copyright 2014 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.
~ */
~
-->
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
">
<bean id="remoteService" class="com.navercorp.pinpoint.web.service.AgentServiceImpl">
</bean>
<bean id="activeThreadHandler" class="com.navercorp.pinpoint.web.websocket.ActiveThreadHandler">
<!-- default value.
<constructor-arg value="/agent/activeThread" />
-->
<constructor-arg ref="remoteService" />
</bean>
<bean id="handlerRepository" class="com.navercorp.pinpoint.web.websocket.WebSocketHandlerRepository">
<constructor-arg>
<list>
<ref bean="activeThreadHandler" />
</list>
</constructor-arg>
</bean>
</beans>
+5
View File
@@ -37,6 +37,11 @@
<url-pattern>*.pinpoint</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>pinpoint-web</servlet-name>
<url-pattern>*.pinpointws</url-pattern>
</servlet-mapping>
<filter>
<filter-name>encodingFilter</filter-name>
<filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>