Provide the getResponseTimeTrend query.

This commit is contained in:
peng-yongsheng 2018-01-31 11:00:25 +08:00
parent 0ee4b1c30d
commit 4a933e1832
9 changed files with 201 additions and 36 deletions

View File

@ -19,7 +19,9 @@
package org.apache.skywalking.apm.collector.storage.dao;
import com.google.gson.JsonArray;
import java.util.List;
import org.apache.skywalking.apm.collector.storage.base.dao.DAO;
import org.apache.skywalking.apm.collector.storage.ui.common.Step;
/**
* @author peng-yongsheng
@ -33,7 +35,7 @@ public interface IInstanceMetricUIDAO extends DAO {
long getRespTimeMetric(int instanceId, long timeBucket);
JsonArray getRespTimeMetric(int instanceId, long startTimeBucket, long endTimeBucket);
List<Integer> getResponseTimeTrend(int instanceId, Step step, Long[] timeBuckets);
class InstanceMetric {
private final int instanceId;

View File

@ -25,4 +25,12 @@ import java.util.List;
*/
public class ResponseTimeTrend {
private List<Integer> trendList;
public List<Integer> getTrendList() {
return trendList;
}
public void setTrendList(List<Integer> trendList) {
this.trendList = trendList;
}
}

View File

@ -19,11 +19,16 @@
package org.apache.skywalking.apm.collector.storage.es.dao;
import com.google.gson.JsonArray;
import java.util.LinkedList;
import java.util.List;
import org.apache.skywalking.apm.collector.client.elasticsearch.ElasticSearchClient;
import org.apache.skywalking.apm.collector.core.util.Const;
import org.apache.skywalking.apm.collector.storage.dao.IInstanceMetricUIDAO;
import org.apache.skywalking.apm.collector.storage.es.base.dao.EsDAO;
import org.apache.skywalking.apm.collector.storage.table.MetricSource;
import org.apache.skywalking.apm.collector.storage.table.instance.InstanceMetricTable;
import org.apache.skywalking.apm.collector.storage.ui.common.Step;
import org.apache.skywalking.apm.collector.storage.utils.TimePyramidTableNameBuilder;
import org.elasticsearch.action.get.GetResponse;
import org.elasticsearch.action.get.MultiGetItemResponse;
import org.elasticsearch.action.get.MultiGetRequestBuilder;
@ -113,30 +118,28 @@ public class InstanceMetricEsUIDAO extends EsDAO implements IInstanceMetricUIDAO
return 0;
}
@Override public JsonArray getRespTimeMetric(int instanceId, long startTimeBucket, long endTimeBucket) {
@Override public List<Integer> getResponseTimeTrend(int instanceId, Step step, Long[] timeBuckets) {
MultiGetRequestBuilder prepareMultiGet = getClient().prepareMultiGet();
String tableName = TimePyramidTableNameBuilder.build(step, InstanceMetricTable.TABLE);
int i = 0;
long timeBucket = 0;
do {
// timeBucket = TimeBucketUtils.INSTANCE.addSecondForSecondTimeBucket(TimeBucketUtils.TimeBucketType.SECOND, startTimeBucket, i);
String id = timeBucket + Const.ID_SPLIT + instanceId;
prepareMultiGet.add(InstanceMetricTable.TABLE, InstanceMetricTable.TABLE_TYPE, id);
i++;
for (long timeBucket : timeBuckets) {
String id = timeBucket + Const.ID_SPLIT + instanceId + Const.ID_SPLIT + MetricSource.Callee.getValue();
prepareMultiGet.add(tableName, InstanceMetricTable.TABLE_TYPE, id);
}
while (timeBucket <= endTimeBucket);
JsonArray metrics = new JsonArray();
List<Integer> responseTimeTrends = new LinkedList<>();
MultiGetResponse multiGetResponse = prepareMultiGet.get();
for (MultiGetItemResponse response : multiGetResponse.getResponses()) {
if (response.getResponse().isExists()) {
long callTimes = ((Number)response.getResponse().getSource().get(InstanceMetricTable.COLUMN_TRANSACTION_CALLS)).longValue();
long costTotal = ((Number)response.getResponse().getSource().get(InstanceMetricTable.COLUMN_TRANSACTION_DURATION_SUM)).longValue();
metrics.add(costTotal / callTimes);
long errorCallTimes = ((Number)response.getResponse().getSource().get(InstanceMetricTable.COLUMN_TRANSACTION_ERROR_CALLS)).longValue();
long durationSum = ((Number)response.getResponse().getSource().get(InstanceMetricTable.COLUMN_TRANSACTION_DURATION_SUM)).longValue();
long errorDurationSum = ((Number)response.getResponse().getSource().get(InstanceMetricTable.COLUMN_BUSINESS_TRANSACTION_ERROR_DURATION_SUM)).longValue();
responseTimeTrends.add((int)((durationSum - errorDurationSum) / (callTimes - errorCallTimes)));
} else {
metrics.add(0);
responseTimeTrends.add(0);
}
}
return metrics;
return responseTimeTrends;
}
}

View File

@ -22,6 +22,7 @@ import com.google.gson.JsonArray;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
import org.apache.skywalking.apm.collector.client.h2.H2Client;
import org.apache.skywalking.apm.collector.client.h2.H2ClientException;
@ -29,7 +30,10 @@ import org.apache.skywalking.apm.collector.core.util.Const;
import org.apache.skywalking.apm.collector.storage.base.sql.SqlBuilder;
import org.apache.skywalking.apm.collector.storage.dao.IInstanceMetricUIDAO;
import org.apache.skywalking.apm.collector.storage.h2.base.dao.H2DAO;
import org.apache.skywalking.apm.collector.storage.table.MetricSource;
import org.apache.skywalking.apm.collector.storage.table.instance.InstanceMetricTable;
import org.apache.skywalking.apm.collector.storage.ui.common.Step;
import org.apache.skywalking.apm.collector.storage.utils.TimePyramidTableNameBuilder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@ -135,33 +139,29 @@ public class InstanceMetricH2UIDAO extends H2DAO implements IInstanceMetricUIDAO
return 0;
}
@Override public JsonArray getRespTimeMetric(int instanceId, long startTimeBucket, long endTimeBucket) {
@Override public List<Integer> getResponseTimeTrend(int instanceId, Step step, Long[] timeBuckets) {
H2Client client = getClient();
String sql = SqlBuilder.buildSql(GET_TPS_METRIC_SQL, InstanceMetricTable.TABLE, InstanceMetricTable.COLUMN_ID);
long timeBucket = startTimeBucket;
List<String> idList = new ArrayList<>();
do {
String id = timeBucket + Const.ID_SPLIT + instanceId;
// timeBucket = TimeBucketUtils.INSTANCE.addSecondForSecondTimeBucket(TimeBucketUtils.TimeBucketType.SECOND, timeBucket, 1);
idList.add(id);
}
while (timeBucket <= endTimeBucket);
String tableName = TimePyramidTableNameBuilder.build(step, InstanceMetricTable.TABLE);
String sql = SqlBuilder.buildSql(GET_TPS_METRIC_SQL, tableName, InstanceMetricTable.COLUMN_ID);
JsonArray metrics = new JsonArray();
idList.forEach(id -> {
List<Integer> responseTimeTrends = new LinkedList<>();
for (long timeBucket : timeBuckets) {
String id = timeBucket + Const.ID_SPLIT + instanceId + Const.ID_SPLIT + MetricSource.Callee.getValue();
try (ResultSet rs = client.executeQuery(sql, new Object[] {id})) {
if (rs.next()) {
long callTimes = rs.getLong(InstanceMetricTable.COLUMN_TRANSACTION_CALLS);
long costTotal = rs.getLong(InstanceMetricTable.COLUMN_TRANSACTION_DURATION_SUM);
metrics.add(costTotal / callTimes);
long errorCallTimes = rs.getLong(InstanceMetricTable.COLUMN_TRANSACTION_ERROR_CALLS);
long durationSum = rs.getLong(InstanceMetricTable.COLUMN_TRANSACTION_DURATION_SUM);
long errorDurationSum = rs.getLong(InstanceMetricTable.COLUMN_BUSINESS_TRANSACTION_ERROR_DURATION_SUM);
responseTimeTrends.add((int)((durationSum - errorDurationSum) / (callTimes - errorCallTimes)));
} else {
metrics.add(0);
responseTimeTrends.add(0);
}
} catch (SQLException | H2ClientException e) {
logger.error(e.getMessage(), e);
}
});
return metrics;
}
return responseTimeTrends;
}
}

View File

@ -64,8 +64,10 @@ public class ServerQuery implements Query {
return getServerService().getAllServer(applicationId, start, end);
}
public ResponseTimeTrend getServerResponseTimeTrend(int serverId, Duration duration) {
return null;
public ResponseTimeTrend getServerResponseTimeTrend(int serverId, Duration duration) throws ParseException {
long start = DurationUtils.INSTANCE.exchangeToTimeBucket(duration.getStart());
long end = DurationUtils.INSTANCE.exchangeToTimeBucket(duration.getEnd());
return getServerService().getServerResponseTimeTrend(serverId, duration.getStep(), start, end);
}
public ThroughputTrend getServerTPSTrend(int serverId, Duration duration) {

View File

@ -114,7 +114,6 @@ public class InstanceJVMService {
} else if (metricType.toLowerCase().equals(MetricType.tps.name())) {
metrics.add(MetricType.tps.name(), instanceMetricUIDAO.getTpsMetric(instanceId, startTimeBucket, endTimeBucket));
} else if (metricType.toLowerCase().equals(MetricType.resptime.name())) {
metrics.add(MetricType.resptime.name(), instanceMetricUIDAO.getRespTimeMetric(instanceId, startTimeBucket, endTimeBucket));
} else if (metricType.toLowerCase().equals(MetricType.heapmemory.name())) {
metrics.add(MetricType.heapmemory.name(), memoryMetricDAO.getMetric(instanceId, startTimeBucket, endTimeBucket, true));
} else if (metricType.toLowerCase().equals(MetricType.nonheapmemory.name())) {

View File

@ -21,14 +21,19 @@ package org.apache.skywalking.apm.collector.ui.service;
import com.google.gson.Gson;
import com.google.gson.JsonArray;
import com.google.gson.JsonObject;
import java.text.ParseException;
import java.util.LinkedList;
import java.util.List;
import org.apache.skywalking.apm.collector.core.module.ModuleManager;
import org.apache.skywalking.apm.collector.core.util.Const;
import org.apache.skywalking.apm.collector.core.util.StringUtils;
import org.apache.skywalking.apm.collector.storage.StorageModule;
import org.apache.skywalking.apm.collector.storage.dao.IInstanceMetricUIDAO;
import org.apache.skywalking.apm.collector.storage.dao.IInstanceUIDAO;
import org.apache.skywalking.apm.collector.storage.ui.common.ResponseTimeTrend;
import org.apache.skywalking.apm.collector.storage.ui.common.Step;
import org.apache.skywalking.apm.collector.storage.ui.server.AppServerInfo;
import org.apache.skywalking.apm.collector.ui.utils.DurationUtils;
/**
* @author peng-yongsheng
@ -37,9 +42,11 @@ public class ServerService {
private final Gson gson = new Gson();
private final IInstanceUIDAO instanceDAO;
private final IInstanceMetricUIDAO instanceMetricUIDAO;
public ServerService(ModuleManager moduleManager) {
this.instanceDAO = moduleManager.find(StorageModule.NAME).getService(IInstanceUIDAO.class);
this.instanceMetricUIDAO = moduleManager.find(StorageModule.NAME).getService(IInstanceMetricUIDAO.class);
}
public List<AppServerInfo> searchServer(String keyword, long start, long end) {
@ -49,7 +56,7 @@ public class ServerService {
serverInfos.remove(serverInfo);
}
});
buildAppServerInfo(serverInfos);
return serverInfos;
}
@ -60,6 +67,15 @@ public class ServerService {
return serverInfos;
}
public ResponseTimeTrend getServerResponseTimeTrend(int instanceId, Step step, long start,
long end) throws ParseException {
ResponseTimeTrend responseTimeTrend = new ResponseTimeTrend();
Long[] timeBuckets = DurationUtils.INSTANCE.getDurationPoints(step, start, end);
List<Integer> trends = instanceMetricUIDAO.getResponseTimeTrend(instanceId, step, timeBuckets);
responseTimeTrend.setTrendList(trends);
return responseTimeTrend;
}
private void buildAppServerInfo(List<AppServerInfo> serverInfos) {
serverInfos.forEach(serverInfo -> {
if (StringUtils.isNotEmpty(serverInfo.getOsInfo())) {

View File

@ -20,6 +20,9 @@ package org.apache.skywalking.apm.collector.ui.utils;
import java.text.ParseException;
import java.util.Date;
import java.util.LinkedList;
import java.util.List;
import org.apache.skywalking.apm.collector.core.UnexpectedException;
import org.apache.skywalking.apm.collector.core.util.Const;
import org.apache.skywalking.apm.collector.core.util.TimeBucketUtils;
import org.apache.skywalking.apm.collector.storage.ui.common.Step;
@ -88,4 +91,78 @@ public enum DurationUtils {
return Seconds.secondsBetween(new DateTime(startDate), new DateTime(endDate)).getSeconds();
}
public DateTime parseToDateTime(Step step, long time) throws ParseException {
DateTime dateTime = null;
switch (step) {
case MONTH:
Date date = TimeBucketUtils.MONTH_DATE_FORMAT.parse(String.valueOf(time));
dateTime = new DateTime(date);
break;
case DAY:
date = TimeBucketUtils.DAY_DATE_FORMAT.parse(String.valueOf(time));
dateTime = new DateTime(date);
break;
case HOUR:
date = TimeBucketUtils.HOUR_DATE_FORMAT.parse(String.valueOf(time));
dateTime = new DateTime(date);
break;
case MINUTE:
date = TimeBucketUtils.MINUTE_DATE_FORMAT.parse(String.valueOf(time));
dateTime = new DateTime(date);
break;
case SECOND:
date = TimeBucketUtils.SECOND_DATE_FORMAT.parse(String.valueOf(time));
dateTime = new DateTime(date);
break;
}
return dateTime;
}
public Long[] getDurationPoints(Step step, long start, long end) throws ParseException {
DateTime dateTime = parseToDateTime(step, start);
List<Long> durations = new LinkedList<>();
durations.add(start);
int i = 0;
do {
switch (step) {
case MONTH:
dateTime = dateTime.plusMonths(1);
String timeBucket = TimeBucketUtils.MONTH_DATE_FORMAT.format(dateTime.toDate());
durations.add(Long.valueOf(timeBucket));
break;
case DAY:
dateTime = dateTime.plusDays(1);
timeBucket = TimeBucketUtils.DAY_DATE_FORMAT.format(dateTime.toDate());
durations.add(Long.valueOf(timeBucket));
break;
case HOUR:
dateTime = dateTime.plusHours(1);
timeBucket = TimeBucketUtils.HOUR_DATE_FORMAT.format(dateTime.toDate());
durations.add(Long.valueOf(timeBucket));
break;
case MINUTE:
dateTime = dateTime.plusMinutes(1);
timeBucket = TimeBucketUtils.MINUTE_DATE_FORMAT.format(dateTime.toDate());
durations.add(Long.valueOf(timeBucket));
break;
case SECOND:
dateTime = dateTime.plusSeconds(1);
timeBucket = TimeBucketUtils.SECOND_DATE_FORMAT.format(dateTime.toDate());
durations.add(Long.valueOf(timeBucket));
break;
}
i++;
if (i > 500) {
throw new UnexpectedException("Duration data error, step: " + step.name() + ", start: " + start + ", end: " + end);
}
}
while (end != durations.get(durations.size() - 1));
return durations.toArray(new Long[durations.size()]);
}
}

View File

@ -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.utils;
import java.text.ParseException;
import org.apache.skywalking.apm.collector.core.UnexpectedException;
import org.apache.skywalking.apm.collector.storage.ui.common.Step;
import org.junit.Assert;
import org.junit.Test;
/**
* @author peng-yongsheng
*/
public class DurationUtilsTestCase {
@Test
public void test() throws ParseException {
}
@Test
public void testGetDurationPoints() throws ParseException {
Long[] durationPoints = DurationUtils.INSTANCE.getDurationPoints(Step.MONTH, 201710, 201803);
Assert.assertArrayEquals(new Long[] {201710L, 201711L, 201712L, 201801L, 201802L, 201803L}, durationPoints);
durationPoints = DurationUtils.INSTANCE.getDurationPoints(Step.DAY, 20180129, 20180202);
Assert.assertArrayEquals(new Long[] {20180129L, 20180130L, 20180131L, 20180201L, 20180202L}, durationPoints);
durationPoints = DurationUtils.INSTANCE.getDurationPoints(Step.HOUR, 2018012922, 2018013002);
Assert.assertArrayEquals(new Long[] {2018012922L, 2018012923L, 2018013000L, 2018013001L, 2018013002L}, durationPoints);
durationPoints = DurationUtils.INSTANCE.getDurationPoints(Step.MINUTE, 201801292258L, 201801292302L);
Assert.assertArrayEquals(new Long[] {201801292258L, 201801292259L, 201801292300L, 201801292301L, 201801292302L}, durationPoints);
durationPoints = DurationUtils.INSTANCE.getDurationPoints(Step.SECOND, 20180129225858L, 20180129225902L);
Assert.assertArrayEquals(new Long[] {20180129225858L, 20180129225859L, 20180129225900L, 20180129225901L, 20180129225902L}, durationPoints);
}
@Test(expected = UnexpectedException.class)
public void testGetDurationPointsErrorDuration() throws ParseException {
DurationUtils.INSTANCE.getDurationPoints(Step.MONTH, 20171001, 20180301);
}
}