/* * 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.collector.rpc.handler; import com.navercorp.pinpoint.collector.cluster.route.ResponseEvent; import com.navercorp.pinpoint.collector.dao.AgentEventDao; import com.navercorp.pinpoint.common.server.bo.AgentEventBo; import com.navercorp.pinpoint.common.server.util.AgentEventMessageSerializer; import com.navercorp.pinpoint.common.server.util.AgentEventType; import com.navercorp.pinpoint.common.server.util.AgentEventTypeCategory; import com.navercorp.pinpoint.rpc.packet.HandshakePropertyType; import com.navercorp.pinpoint.rpc.server.PinpointServer; import com.navercorp.pinpoint.thrift.dto.command.TCommandTransfer; import com.navercorp.pinpoint.thrift.dto.command.TCommandTransferResponse; import com.navercorp.pinpoint.thrift.dto.command.TRouteResult; import com.navercorp.pinpoint.thrift.io.DeserializerFactory; import com.navercorp.pinpoint.thrift.io.HeaderTBaseDeserializer; import com.navercorp.pinpoint.thrift.util.SerializationUtils; import org.apache.commons.collections.MapUtils; import org.apache.thrift.TException; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import javax.annotation.Resource; import java.util.Map; import java.util.Set; import java.util.concurrent.Executor; /** * @author HyunGil Jeong */ public class AgentEventHandler { private static final Set<AgentEventType> RESPONSE_EVENT_TYPES = AgentEventType .getTypesByCatgory(AgentEventTypeCategory.USER_REQUEST); private final Logger logger = LoggerFactory.getLogger(this.getClass()); @Resource(name = "agentEventWorker") private Executor executor; @Resource private AgentEventDao agentEventDao; @Resource private AgentEventMessageSerializer agentEventMessageSerializer; @Resource private DeserializerFactory<HeaderTBaseDeserializer> commandDeserializerFactory; public void handleEvent(PinpointServer pinpointServer, long eventTimestamp, AgentEventType eventType) { handleEvent(pinpointServer, eventTimestamp, eventType, null); } public void handleEvent(PinpointServer pinpointServer, long eventTimestamp, AgentEventType eventType, Object eventMessage) { if (pinpointServer == null) { throw new NullPointerException("pinpointServer may not be null"); } if (eventType == null) { throw new NullPointerException("eventType may not be null"); } Map<Object, Object> channelProperties = pinpointServer.getChannelProperties(); final String agentId = MapUtils.getString(channelProperties, HandshakePropertyType.AGENT_ID.getName()); final long startTimestamp = MapUtils.getLong(channelProperties, HandshakePropertyType.START_TIMESTAMP.getName()); this.executor.execute(new AgentEventHandlerDispatch(agentId, startTimestamp, eventTimestamp, eventType, eventMessage)); } public void handleResponseEvent(ResponseEvent responseEvent, long eventTimestamp) { if (responseEvent == null) { throw new NullPointerException("responseEvent may not be null"); } TCommandTransferResponse response = responseEvent.getRouteResult(); if (response.getRouteResult() != TRouteResult.OK) { return; } this.executor.execute(new AgentResponseEventHandlerDispatch(responseEvent, eventTimestamp)); } private class AgentEventHandlerDispatch implements Runnable { private final String agentId; private final long startTimestamp; private final long eventTimestamp; private final AgentEventType eventType; private final Object eventMessage; private AgentEventHandlerDispatch(String agentId, long startTimestamp, long eventTimestamp, AgentEventType eventType, Object eventMessage) { this.agentId = agentId; this.startTimestamp = startTimestamp; this.eventTimestamp = eventTimestamp; this.eventType = eventType; this.eventMessage = eventMessage; } @Override public void run() { AgentEventBo event = new AgentEventBo(this.agentId, this.startTimestamp, this.eventTimestamp, this.eventType); try { byte[] eventBody = agentEventMessageSerializer.serialize(this.eventType, this.eventMessage); event.setEventBody(eventBody); } catch (Exception e) { logger.warn("error handling agent event", e); return; } logger.info("handle event: {}", event); agentEventDao.insert(event); } } private class AgentResponseEventHandlerDispatch implements Runnable { private final String agentId; private final long startTimestamp; private final long eventTimestamp; private final byte[] payload; private AgentResponseEventHandlerDispatch(ResponseEvent responseEvent, long eventTimestamp) { final TCommandTransfer command = responseEvent.getDeliveryCommand(); this.agentId = command.getAgentId(); this.startTimestamp = command.getStartTime(); this.eventTimestamp = eventTimestamp; final TCommandTransferResponse response = responseEvent.getRouteResult(); this.payload = response.getPayload(); } @Override public void run() { Class<?> payloadType = Void.class; if (this.payload != null) { try { payloadType = SerializationUtils.deserialize(this.payload, commandDeserializerFactory).getClass(); } catch (TException e) { logger.warn("Error deserializing ResponseEvent payload", e); return; } } for (AgentEventType eventType : RESPONSE_EVENT_TYPES) { if (eventType.getMessageType() == payloadType) { AgentEventBo agentEventBo = new AgentEventBo(this.agentId, this.startTimestamp, this.eventTimestamp, eventType); agentEventBo.setEventBody(this.payload); agentEventDao.insert(agentEventBo); } } } } }