package org.skywalking.apm.collector.worker.segment.persistence; import com.google.gson.Gson; import com.google.gson.JsonArray; import com.google.gson.JsonObject; import org.elasticsearch.action.get.GetResponse; import org.elasticsearch.client.Client; import org.skywalking.apm.collector.actor.*; import org.skywalking.apm.collector.actor.selector.RollingSelector; import org.skywalking.apm.collector.actor.selector.WorkerSelector; import org.skywalking.apm.collector.worker.globaltrace.GlobalTraceIndex; import org.skywalking.apm.collector.worker.segment.SegmentCostIndex; import org.skywalking.apm.collector.worker.segment.SegmentExceptionIndex; import org.skywalking.apm.collector.worker.segment.SegmentIndex; import org.skywalking.apm.collector.worker.segment.entity.GlobalTraceId; import org.skywalking.apm.collector.worker.segment.entity.Segment; import org.skywalking.apm.collector.worker.segment.entity.SegmentDeserialize; import org.skywalking.apm.collector.worker.storage.EsClient; import org.skywalking.apm.collector.worker.storage.JoinAndSplitData; import org.skywalking.apm.collector.worker.tools.CollectionTools; import java.util.List; /** * @author pengys5 */ public class SegmentTopSearchWithGlobalTraceId extends AbstractLocalSyncWorker { private Gson gson = new Gson(); private SegmentTopSearchWithGlobalTraceId(Role role, ClusterWorkerContext clusterContext, LocalWorkerContext selfContext) { super(role, clusterContext, selfContext); } @Override public void preStart() throws ProviderNotFoundException { getClusterContext().findProvider(SegmentExceptionWithSegId.WorkerRole.INSTANCE).create(this); } @Override protected void onWork(Object request, Object response) throws Exception { if (request instanceof RequestEntity) { RequestEntity search = (RequestEntity) request; Client client = EsClient.INSTANCE.getClient(); String globalTraceData = client.prepareGet(GlobalTraceIndex.INDEX, GlobalTraceIndex.TYPE_RECORD, search.globalTraceId).get().getSourceAsString(); JsonObject globalTraceObj = gson.fromJson(globalTraceData, JsonObject.class); JsonObject topSegPaging = new JsonObject(); topSegPaging.addProperty("recordsTotal", 0); JsonArray topSegArray = new JsonArray(); topSegPaging.add("data", topSegArray); if (globalTraceObj != null && globalTraceObj.has(GlobalTraceIndex.SUB_SEG_IDS)) { String subSegIdsStr = globalTraceObj.get(GlobalTraceIndex.SUB_SEG_IDS).getAsString(); String[] subSegIds = subSegIdsStr.split(JoinAndSplitData.SPLIT); topSegPaging.addProperty("recordsTotal", subSegIds.length); int num = search.from; int limit = search.limit; if (search.limit >= subSegIds.length) { limit = subSegIds.length; } for (int i = num; i < limit; i++) { GetResponse getResponse = client.prepareGet(SegmentCostIndex.INDEX, SegmentCostIndex.TYPE_RECORD, subSegIds[num]).get(); JsonObject topSegmentJson = new JsonObject(); topSegmentJson.addProperty("num", num); String segId = (String) getResponse.getSource().get(SegmentCostIndex.SEG_ID); topSegmentJson.addProperty(SegmentCostIndex.SEG_ID, segId); topSegmentJson.addProperty(SegmentCostIndex.START_TIME, (Number) getResponse.getSource().get(SegmentCostIndex.START_TIME)); if (getResponse.getSource().containsKey(SegmentCostIndex.END_TIME)) { topSegmentJson.addProperty(SegmentCostIndex.END_TIME, (Number) getResponse.getSource().get(SegmentCostIndex.END_TIME)); } topSegmentJson.addProperty(SegmentCostIndex.OPERATION_NAME, (String) getResponse.getSource().get(SegmentCostIndex.OPERATION_NAME)); topSegmentJson.addProperty(SegmentCostIndex.COST, (Number) getResponse.getSource().get(SegmentCostIndex.COST)); String segmentSource = client.prepareGet(SegmentIndex.INDEX, SegmentIndex.TYPE_RECORD, segId).get().getSourceAsString(); Segment segment = SegmentDeserialize.INSTANCE.deserializeSingle(segmentSource); List<GlobalTraceId> distributedTraceIdList = segment.getRelatedGlobalTraces(); JsonArray distributedTraceIdArray = new JsonArray(); if (CollectionTools.isNotEmpty(distributedTraceIdList)) { for (GlobalTraceId distributedTraceId : distributedTraceIdList) { distributedTraceIdArray.add(distributedTraceId.get()); } } topSegmentJson.add("traceIds", distributedTraceIdArray); boolean isError = false; JsonObject resJsonObj = new JsonObject(); getSelfContext().lookup(SegmentExceptionWithSegId.WorkerRole.INSTANCE).ask(new SegmentExceptionWithSegId.RequestEntity(segId), resJsonObj); if (resJsonObj.has("result")) { JsonObject segExJson = resJsonObj.get("result").getAsJsonObject(); if (segExJson.has(SegmentExceptionIndex.IS_ERROR)) { isError = segExJson.get(SegmentExceptionIndex.IS_ERROR).getAsBoolean(); } } topSegmentJson.addProperty(SegmentExceptionIndex.IS_ERROR, isError); num++; topSegArray.add(topSegmentJson); } } JsonObject resJsonObj = (JsonObject) response; resJsonObj.add("result", topSegPaging); } } public static class RequestEntity { private int from; private int limit; private String globalTraceId; public RequestEntity(String globalTraceId, int from, int limit) { this.from = from; this.limit = limit; this.globalTraceId = globalTraceId; } public int getFrom() { return from; } public int getLimit() { return limit; } public String getGlobalTraceId() { return globalTraceId; } } public static class Factory extends AbstractLocalSyncWorkerProvider<SegmentTopSearchWithGlobalTraceId> { @Override public Role role() { return WorkerRole.INSTANCE; } @Override public SegmentTopSearchWithGlobalTraceId workerInstance(ClusterWorkerContext clusterContext) { return new SegmentTopSearchWithGlobalTraceId(role(), clusterContext, new LocalWorkerContext()); } } public enum WorkerRole implements Role { INSTANCE; @Override public String roleName() { return SegmentTopSearchWithGlobalTraceId.class.getSimpleName(); } @Override public WorkerSelector workerSelector() { return new RollingSelector(); } } }