diff --git a/apm-collector/apm-collector-storage/collector-storage-define/src/main/java/org/apache/skywalking/apm/collector/storage/dao/ui/IInstanceUIDAO.java b/apm-collector/apm-collector-storage/collector-storage-define/src/main/java/org/apache/skywalking/apm/collector/storage/dao/ui/IInstanceUIDAO.java index bd22f65d2..102715477 100644 --- a/apm-collector/apm-collector-storage/collector-storage-define/src/main/java/org/apache/skywalking/apm/collector/storage/dao/ui/IInstanceUIDAO.java +++ b/apm-collector/apm-collector-storage/collector-storage-define/src/main/java/org/apache/skywalking/apm/collector/storage/dao/ui/IInstanceUIDAO.java @@ -39,4 +39,8 @@ public interface IInstanceUIDAO extends DAO { List searchServer(String keyword, long start, long end); List getAllServer(int applicationId, long startSecondTimeBucket, long endSecondTimeBucket); + + long getEarliestRegisterTime(int applicationId); + + long getLatestHeartBeatTime(int applicationId); } diff --git a/apm-collector/apm-collector-storage/collector-storage-es-provider/src/main/java/org/apache/skywalking/apm/collector/storage/es/dao/ui/InstanceEsUIDAO.java b/apm-collector/apm-collector-storage/collector-storage-es-provider/src/main/java/org/apache/skywalking/apm/collector/storage/es/dao/ui/InstanceEsUIDAO.java index 37d370855..918945f8c 100644 --- a/apm-collector/apm-collector-storage/collector-storage-es-provider/src/main/java/org/apache/skywalking/apm/collector/storage/es/dao/ui/InstanceEsUIDAO.java +++ b/apm-collector/apm-collector-storage/collector-storage-es-provider/src/main/java/org/apache/skywalking/apm/collector/storage/es/dao/ui/InstanceEsUIDAO.java @@ -171,7 +171,8 @@ public class InstanceEsUIDAO extends EsDAO implements IInstanceUIDAO { return buildAppServerInfo(searchHits); } - @Override public List getAllServer(int applicationId, long startSecondTimeBucket, long endSecondTimeBucket) { + @Override + public List getAllServer(int applicationId, long startSecondTimeBucket, long endSecondTimeBucket) { logger.debug("get instances info, applicationId: {}, start: {}, end: {}", applicationId, startSecondTimeBucket, endSecondTimeBucket); SearchRequestBuilder searchRequestBuilder = getClient().prepareSearch(InstanceTable.TABLE); searchRequestBuilder.setTypes(InstanceTable.TABLE_TYPE); @@ -192,6 +193,46 @@ public class InstanceEsUIDAO extends EsDAO implements IInstanceUIDAO { return buildAppServerInfo(searchHits); } + @Override public long getEarliestRegisterTime(int applicationId) { + SearchRequestBuilder searchRequestBuilder = getClient().prepareSearch(InstanceTable.TABLE); + searchRequestBuilder.setTypes(InstanceTable.TABLE_TYPE); + searchRequestBuilder.setSearchType(SearchType.DFS_QUERY_THEN_FETCH); + searchRequestBuilder.setSize(1); + + searchRequestBuilder.setQuery(QueryBuilders.termQuery(InstanceTable.COLUMN_APPLICATION_ID, applicationId)); + searchRequestBuilder.addSort(SortBuilders.fieldSort(InstanceTable.COLUMN_REGISTER_TIME).sortMode(SortMode.MIN)); + + SearchResponse searchResponse = searchRequestBuilder.execute().actionGet(); + + SearchHit[] searchHits = searchResponse.getHits().getHits(); + + if (searchHits.length > 0) { + return ((Number)searchHits[0].getSource().get(InstanceTable.COLUMN_REGISTER_TIME)).longValue(); + } + + return Long.MIN_VALUE; + } + + @Override public long getLatestHeartBeatTime(int applicationId) { + SearchRequestBuilder searchRequestBuilder = getClient().prepareSearch(InstanceTable.TABLE); + searchRequestBuilder.setTypes(InstanceTable.TABLE_TYPE); + searchRequestBuilder.setSearchType(SearchType.DFS_QUERY_THEN_FETCH); + searchRequestBuilder.setSize(1); + + searchRequestBuilder.setQuery(QueryBuilders.termQuery(InstanceTable.COLUMN_APPLICATION_ID, applicationId)); + searchRequestBuilder.addSort(SortBuilders.fieldSort(InstanceTable.COLUMN_HEARTBEAT_TIME).sortMode(SortMode.MAX)); + + SearchResponse searchResponse = searchRequestBuilder.execute().actionGet(); + + SearchHit[] searchHits = searchResponse.getHits().getHits(); + + if (searchHits.length > 0) { + return ((Number)searchHits[0].getSource().get(InstanceTable.COLUMN_HEARTBEAT_TIME)).longValue(); + } + + return Long.MAX_VALUE; + } + private List buildAppServerInfo(SearchHit[] searchHits) { List appServerInfos = new LinkedList<>(); for (SearchHit searchHit : searchHits) { diff --git a/apm-collector/apm-collector-storage/collector-storage-h2-provider/src/main/java/org/apache/skywalking/apm/collector/storage/h2/dao/ui/InstanceH2UIDAO.java b/apm-collector/apm-collector-storage/collector-storage-h2-provider/src/main/java/org/apache/skywalking/apm/collector/storage/h2/dao/ui/InstanceH2UIDAO.java index 413ce19b5..68f3255d1 100644 --- a/apm-collector/apm-collector-storage/collector-storage-h2-provider/src/main/java/org/apache/skywalking/apm/collector/storage/h2/dao/ui/InstanceH2UIDAO.java +++ b/apm-collector/apm-collector-storage/collector-storage-h2-provider/src/main/java/org/apache/skywalking/apm/collector/storage/h2/dao/ui/InstanceH2UIDAO.java @@ -164,4 +164,14 @@ public class InstanceH2UIDAO extends H2DAO implements IInstanceUIDAO { } return appServerInfos; } + + //TODO + @Override public long getEarliestRegisterTime(int applicationId) { + return 0; + } + + //TODO + @Override public long getLatestHeartBeatTime(int applicationId) { + return 0; + } } diff --git a/apm-collector/apm-collector-ui/collector-ui-jetty-provider/src/main/java/org/apache/skywalking/apm/collector/ui/service/SecondBetweenService.java b/apm-collector/apm-collector-ui/collector-ui-jetty-provider/src/main/java/org/apache/skywalking/apm/collector/ui/service/SecondBetweenService.java new file mode 100644 index 000000000..f4db0a00a --- /dev/null +++ b/apm-collector/apm-collector-ui/collector-ui-jetty-provider/src/main/java/org/apache/skywalking/apm/collector/ui/service/SecondBetweenService.java @@ -0,0 +1,58 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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 org.apache.skywalking.apm.collector.ui.service; + +import java.text.ParseException; +import java.text.SimpleDateFormat; +import java.util.Date; +import org.apache.skywalking.apm.collector.core.module.ModuleManager; +import org.apache.skywalking.apm.collector.storage.StorageModule; +import org.apache.skywalking.apm.collector.storage.dao.ui.IInstanceUIDAO; +import org.joda.time.DateTime; +import org.joda.time.Seconds; + +/** + * @author peng-yongsheng + */ +class SecondBetweenService { + + private final IInstanceUIDAO instanceUIDAO; + + SecondBetweenService(ModuleManager moduleManager) { + this.instanceUIDAO = moduleManager.find(StorageModule.NAME).getService(IInstanceUIDAO.class); + } + + int calculate(int applicationId, long startSecondTimeBucket, + long endSecondTimeBucket) throws ParseException { + long registerTime = instanceUIDAO.getEarliestRegisterTime(applicationId); + if (startSecondTimeBucket < registerTime) { + startSecondTimeBucket = registerTime; + } + + long heartBeatTime = instanceUIDAO.getLatestHeartBeatTime(applicationId); + if (endSecondTimeBucket > heartBeatTime) { + endSecondTimeBucket = heartBeatTime; + } + + Date startDate = new SimpleDateFormat("yyyyMMddHHmmss").parse(String.valueOf(startSecondTimeBucket)); + Date endDate = new SimpleDateFormat("yyyyMMddHHmmss").parse(String.valueOf(endSecondTimeBucket)); + + return Seconds.secondsBetween(new DateTime(startDate), new DateTime(endDate)).getSeconds(); + } +} diff --git a/apm-collector/apm-collector-ui/collector-ui-jetty-provider/src/main/java/org/apache/skywalking/apm/collector/ui/service/TopologyBuilder.java b/apm-collector/apm-collector-ui/collector-ui-jetty-provider/src/main/java/org/apache/skywalking/apm/collector/ui/service/TopologyBuilder.java index c971f9946..fc4deefba 100644 --- a/apm-collector/apm-collector-ui/collector-ui-jetty-provider/src/main/java/org/apache/skywalking/apm/collector/ui/service/TopologyBuilder.java +++ b/apm-collector/apm-collector-ui/collector-ui-jetty-provider/src/main/java/org/apache/skywalking/apm/collector/ui/service/TopologyBuilder.java @@ -18,6 +18,7 @@ package org.apache.skywalking.apm.collector.ui.service; +import java.text.ParseException; import java.util.HashMap; import java.util.LinkedList; import java.util.List; @@ -41,18 +42,24 @@ import org.apache.skywalking.apm.collector.storage.ui.common.VisualUserNode; import org.apache.skywalking.apm.collector.ui.utils.ApdexCalculator; import org.apache.skywalking.apm.collector.ui.utils.SLACalculator; import org.apache.skywalking.apm.network.trace.component.ComponentsDefine; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; /** * @author peng-yongsheng */ class TopologyBuilder { + private final Logger logger = LoggerFactory.getLogger(TopologyBuilder.class); + private final ApplicationCacheService applicationCacheService; private final ServerService serverService; + private final SecondBetweenService secondBetweenService; TopologyBuilder(ModuleManager moduleManager) { this.applicationCacheService = moduleManager.find(CacheModule.NAME).getService(ApplicationCacheService.class); this.serverService = new ServerService(moduleManager); + this.secondBetweenService = new SecondBetweenService(moduleManager); } Topology build(List applicationComponents, @@ -76,7 +83,11 @@ class TopologyBuilder { applicationNode.setType(components.getOrDefault(application.getApplicationId(), Const.UNKNOWN)); applicationNode.setSla(SLACalculator.INSTANCE.calculate(applicationMetric.getErrorCalls(), applicationMetric.getCalls())); - applicationNode.setCallsPerSec(100L); + try { + applicationNode.setCallsPerSec(applicationMetric.getCalls() / secondBetweenService.calculate(applicationId, startSecondTimeBucket, endSecondTimeBucket)); + } catch (ParseException e) { + logger.error(e.getMessage(), e); + } applicationNode.setAvgResponseTime((applicationMetric.getDurations() - applicationMetric.getErrorDurations()) / (applicationMetric.getCalls() - applicationMetric.getErrorCalls())); applicationNode.setApdex(ApdexCalculator.INSTANCE.calculate(applicationMetric.getSatisfiedCount(), applicationMetric.getToleratingCount(), applicationMetric.getFrustratedCount())); applicationNode.setAlarm(false); @@ -108,7 +119,11 @@ class TopologyBuilder { call.setTargetName(applicationCacheService.getApplicationById(actualTargetId).getApplicationCode()); call.setAlert(true); call.setCallType(components.get(referenceMetric.getTarget())); - call.setCallsPerSec(1); + try { + call.setCallsPerSec(referenceMetric.getCalls() / secondBetweenService.calculate(source.getApplicationId(), startSecondTimeBucket, endSecondTimeBucket)); + } catch (ParseException e) { + logger.error(e.getMessage(), e); + } call.setAvgResponseTime((referenceMetric.getDurations() - referenceMetric.getErrorDurations()) / (referenceMetric.getCalls() - referenceMetric.getErrorCalls())); calls.add(call); }); @@ -145,7 +160,11 @@ class TopologyBuilder { } else { call.setCallType(components.get(referenceMetric.getTarget())); } - call.setCallsPerSec(1); + try { + call.setCallsPerSec(referenceMetric.getCalls() / secondBetweenService.calculate(target.getApplicationId(), startSecondTimeBucket, endSecondTimeBucket)); + } catch (ParseException e) { + logger.error(e.getMessage(), e); + } call.setAvgResponseTime((referenceMetric.getDurations() - referenceMetric.getErrorDurations()) / (referenceMetric.getCalls() - referenceMetric.getErrorCalls())); calls.add(call); });