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 7c254f1ff..1d650b6ea 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 @@ -29,12 +29,12 @@ import com.navercorp.pinpoint.thrift.dto.command.TCommandThreadDumpResponse; * @author HyunGil Jeong */ public enum AgentEventType { - AGENT_CONNECTED(10100, "Agent connected", Void.class, AGENT_LIFECYCLE), + AGENT_CONNECTED(10100, "Agent connected", Void.class, DURATIONAL, AGENT_LIFECYCLE), AGENT_PING(10199, "Agent ping", Void.class, AGENT_LIFECYCLE), - AGENT_SHUTDOWN(10200, "Agent shutdown", Void.class, AGENT_LIFECYCLE), - AGENT_UNEXPECTED_SHUTDOWN(10201, "Agent unexpected shutdown", Void.class, AGENT_LIFECYCLE), - AGENT_CLOSED_BY_SERVER(10300, "Agent connection closed by server", Void.class, AGENT_LIFECYCLE), - AGENT_UNEXPECTED_CLOSE_BY_SERVER(10301, "Agent connection unexpectedly closed by server", Void.class, AGENT_LIFECYCLE), + AGENT_SHUTDOWN(10200, "Agent shutdown", Void.class, DURATIONAL, AGENT_LIFECYCLE), + AGENT_UNEXPECTED_SHUTDOWN(10201, "Agent unexpected shutdown", Void.class, DURATIONAL, AGENT_LIFECYCLE), + AGENT_CLOSED_BY_SERVER(10300, "Agent connection closed by server", Void.class, DURATIONAL, AGENT_LIFECYCLE), + AGENT_UNEXPECTED_CLOSE_BY_SERVER(10301, "Agent connection unexpectedly closed by server", Void.class, DURATIONAL, AGENT_LIFECYCLE), USER_THREAD_DUMP(20100, "Thread dump by user", TCommandThreadDumpResponse.class, USER_REQUEST, THREAD_DUMP), OTHER(-1, "Other event", String.class, AgentEventTypeCategory.OTHER); diff --git a/commons/src/main/java/com/navercorp/pinpoint/common/util/AgentEventTypeCategory.java b/commons/src/main/java/com/navercorp/pinpoint/common/util/AgentEventTypeCategory.java index 1fabb4cbd..6f7b8d869 100644 --- a/commons/src/main/java/com/navercorp/pinpoint/common/util/AgentEventTypeCategory.java +++ b/commons/src/main/java/com/navercorp/pinpoint/common/util/AgentEventTypeCategory.java @@ -20,6 +20,7 @@ package com.navercorp.pinpoint.common.util; * @author HyunGil Jeong */ public enum AgentEventTypeCategory { + DURATIONAL, AGENT_LIFECYCLE, USER_REQUEST, THREAD_DUMP, 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 index c3dc4e5f6..c7e28415a 100644 --- a/web/src/main/java/com/navercorp/pinpoint/web/service/AgentEventServiceImpl.java +++ b/web/src/main/java/com/navercorp/pinpoint/web/service/AgentEventServiceImpl.java @@ -19,8 +19,12 @@ package com.navercorp.pinpoint.web.service; import java.io.UnsupportedEncodingException; import java.util.ArrayList; import java.util.Collections; +import java.util.Iterator; import java.util.List; +import java.util.PriorityQueue; +import com.navercorp.pinpoint.common.util.AgentEventTypeCategory; +import com.navercorp.pinpoint.web.vo.DurationalAgentEvent; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; @@ -54,13 +58,8 @@ public class AgentEventServiceImpl implements AgentEventService { } 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); + List agentEvents = createAgentEvents(agentEventBos, includeEventMessage); + Collections.sort(agentEvents, AgentEvent.EVENT_TIMESTAMP_ASC_COMPARATOR); return agentEvents; } @@ -84,21 +83,54 @@ public class AgentEventServiceImpl implements AgentEventService { 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); + private List createAgentEvents(List agentEventBos, boolean includeEventMessage) { + List agentEvents = new ArrayList<>(agentEventBos.size()); + PriorityQueue durationalAgentEvents = new PriorityQueue<>(agentEventBos.size(), AgentEvent.EVENT_TIMESTAMP_ASC_COMPARATOR); + for (AgentEventBo agentEventBo : agentEventBos) { + if (agentEventBo.getEventType().isCategorizedAs(AgentEventTypeCategory.DURATIONAL)) { + durationalAgentEvents.add(createDurationalAgentEvent(agentEventBo, includeEventMessage)); + } else { + agentEvents.add(createAgentEvent(agentEventBo, includeEventMessage)); } } + long durationStartTimestamp = DurationalAgentEvent.UNKNOWN_TIMESTAMP; + while (!durationalAgentEvents.isEmpty()) { + DurationalAgentEvent currentEvent = durationalAgentEvents.remove(); + currentEvent.setDurationStartTimestamp(durationStartTimestamp); + DurationalAgentEvent nextEvent = durationalAgentEvents.peek(); + if (nextEvent != null) { + long nextEventTimestamp = nextEvent.getEventTimestamp(); + currentEvent.setDurationEndTimestamp(nextEventTimestamp); + durationStartTimestamp = nextEventTimestamp; + } + agentEvents.add(currentEvent); + } + return agentEvents; + } + + private AgentEvent createAgentEvent(AgentEventBo agentEventBo, boolean includeEventMessage) { + AgentEvent agentEvent = new AgentEvent(agentEventBo); + if (includeEventMessage) { + agentEvent.setEventMessage(deserializeEventMessage(agentEventBo)); + } return agentEvent; } + private DurationalAgentEvent createDurationalAgentEvent(AgentEventBo agentEventBo, boolean includeEventMessage) { + DurationalAgentEvent durationalAgentEvent = new DurationalAgentEvent(agentEventBo); + if (includeEventMessage) { + durationalAgentEvent.setEventMessage(deserializeEventMessage(agentEventBo)); + } + return durationalAgentEvent; + } + + private Object deserializeEventMessage(AgentEventBo agentEventBo) { + try { + return this.agentEventMessageDeserializer.deserialize(agentEventBo.getEventType(), agentEventBo.getEventBody()); + } catch (UnsupportedEncodingException e) { + logger.warn("error deserializing event message", e); + return null; + } + } + } 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 index 91737a998..da9630207 100644 --- a/web/src/main/java/com/navercorp/pinpoint/web/vo/AgentEvent.java +++ b/web/src/main/java/com/navercorp/pinpoint/web/vo/AgentEvent.java @@ -21,6 +21,7 @@ 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.bo.AgentEventBo; import com.navercorp.pinpoint.common.util.AgentEventType; /** @@ -29,6 +30,17 @@ import com.navercorp.pinpoint.common.util.AgentEventType; @JsonInclude(Include.NON_NULL) public class AgentEvent { + public static final Comparator EVENT_TIMESTAMP_ASC_COMPARATOR = new Comparator() { + @Override + public int compare(AgentEvent o1, AgentEvent o2) { + int eventTimestampComparison = Long.compare(o1.eventTimestamp, o2.eventTimestamp); + if (eventTimestampComparison == 0) { + return o2.eventTypeCode - o1.eventTypeCode; + } + return eventTimestampComparison; + } + }; + public static final Comparator EVENT_TIMESTAMP_DESC_COMPARATOR = new Comparator() { @Override public int compare(AgentEvent o1, AgentEvent o2) { @@ -56,23 +68,16 @@ public class AgentEvent { private final boolean hasEventMessage; @JsonProperty - private long startTimestamp; + private final 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; + public AgentEvent(AgentEventBo agentEventBo) { + this.agentId = agentEventBo.getAgentId(); + this.eventTimestamp = agentEventBo.getEventTimestamp(); + this.startTimestamp = agentEventBo.getStartTimestamp(); + AgentEventType eventType = agentEventBo.getEventType(); this.eventTypeCode = eventType.getCode(); this.eventTypeDesc = eventType.getDesc(); this.hasEventMessage = eventType.getMessageType() != Void.class; @@ -102,10 +107,6 @@ public class AgentEvent { return startTimestamp; } - public void setStartTimestamp(long startTimestamp) { - this.startTimestamp = startTimestamp; - } - public Object getEventMessage() { return eventMessage; } @@ -161,6 +162,6 @@ public class AgentEvent { public String toString() { return "AgentEvent [agentId=" + agentId + ", eventTimestamp=" + eventTimestamp + ", eventTypeCode=" + eventTypeCode + ", eventTypeDesc=" + eventTypeDesc + ", hasEventMessage=" + hasEventMessage - + ", startTimestamp=" + startTimestamp + ", eventMessage=" + eventMessage + "]"; + + ", eventMessage=" + eventMessage + ", startTimestamp=" + startTimestamp + "]"; } } diff --git a/web/src/main/java/com/navercorp/pinpoint/web/vo/DurationalAgentEvent.java b/web/src/main/java/com/navercorp/pinpoint/web/vo/DurationalAgentEvent.java new file mode 100644 index 000000000..1300f0320 --- /dev/null +++ b/web/src/main/java/com/navercorp/pinpoint/web/vo/DurationalAgentEvent.java @@ -0,0 +1,72 @@ +/* + * 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 com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.navercorp.pinpoint.common.bo.AgentEventBo; +import com.navercorp.pinpoint.common.util.AgentEventType; + +/** + * @author HyunGil Jeong + */ +@JsonInclude(JsonInclude.Include.NON_NULL) +public class DurationalAgentEvent extends AgentEvent { + + public static final long UNKNOWN_TIMESTAMP = -1; + + @JsonProperty + private long durationStartTimestamp = UNKNOWN_TIMESTAMP; + + @JsonProperty + private long durationEndTimestamp = UNKNOWN_TIMESTAMP; + + public DurationalAgentEvent(AgentEventBo agentEventBo) { + super(agentEventBo); + } + + public long getDurationStartTimestamp() { + return this.durationStartTimestamp; + } + + public void setDurationStartTimestamp(long durationStartTimestamp) { + this.durationStartTimestamp = durationStartTimestamp; + } + + public long getDurationEndTimestamp() { + return this.durationEndTimestamp; + } + + public void setDurationEndTimestamp(long durationEndTimestamp) { + this.durationEndTimestamp = durationEndTimestamp; + } + + @Override + public String toString() { + return "DurationalAgentEvent{" + + "agentId=" + super.getAgentId() + + ", eventTimestamp=" + super.getEventTimestamp() + + ", eventTypeCode=" + super.getEventTypeCode() + + ", eventTypeDesc=" + super.getEventTypeDesc() + + ", hasEventMessage=" + super.hasEventMessage() + + ", eventMessage=" + super.getEventMessage() + + ", startTimestamp=" + super.getStartTimestamp() + + ", durationStartTimestamp=" + durationStartTimestamp + + ", durationEndTimestamp=" + durationEndTimestamp + + '}'; + } +}