From 4a933e183224335c146da43f837bbc6fa0eb27f8 Mon Sep 17 00:00:00 2001 From: peng-yongsheng <8082209@qq.com> Date: Wed, 31 Jan 2018 11:00:25 +0800 Subject: [PATCH] Provide the getResponseTimeTrend query. --- .../storage/dao/IInstanceMetricUIDAO.java | 4 +- .../storage/ui/common/ResponseTimeTrend.java | 8 ++ .../storage/es/dao/InstanceMetricEsUIDAO.java | 31 ++++---- .../storage/h2/dao/InstanceMetricH2UIDAO.java | 34 ++++---- .../apm/collector/ui/query/ServerQuery.java | 6 +- .../ui/service/InstanceJVMService.java | 1 - .../collector/ui/service/ServerService.java | 18 ++++- .../apm/collector/ui/utils/DurationUtils.java | 77 +++++++++++++++++++ .../ui/utils/DurationUtilsTestCase.java | 58 ++++++++++++++ 9 files changed, 201 insertions(+), 36 deletions(-) create mode 100644 apm-collector/apm-collector-ui/collector-ui-jetty-provider/src/test/java/org/apache/skywalking/apm/collector/ui/utils/DurationUtilsTestCase.java diff --git a/apm-collector/apm-collector-storage/collector-storage-define/src/main/java/org/apache/skywalking/apm/collector/storage/dao/IInstanceMetricUIDAO.java b/apm-collector/apm-collector-storage/collector-storage-define/src/main/java/org/apache/skywalking/apm/collector/storage/dao/IInstanceMetricUIDAO.java index e1b1d850b..a2df9ff98 100644 --- a/apm-collector/apm-collector-storage/collector-storage-define/src/main/java/org/apache/skywalking/apm/collector/storage/dao/IInstanceMetricUIDAO.java +++ b/apm-collector/apm-collector-storage/collector-storage-define/src/main/java/org/apache/skywalking/apm/collector/storage/dao/IInstanceMetricUIDAO.java @@ -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 getResponseTimeTrend(int instanceId, Step step, Long[] timeBuckets); class InstanceMetric { private final int instanceId; diff --git a/apm-collector/apm-collector-storage/collector-storage-define/src/main/java/org/apache/skywalking/apm/collector/storage/ui/common/ResponseTimeTrend.java b/apm-collector/apm-collector-storage/collector-storage-define/src/main/java/org/apache/skywalking/apm/collector/storage/ui/common/ResponseTimeTrend.java index 018892d64..dc08516c0 100644 --- a/apm-collector/apm-collector-storage/collector-storage-define/src/main/java/org/apache/skywalking/apm/collector/storage/ui/common/ResponseTimeTrend.java +++ b/apm-collector/apm-collector-storage/collector-storage-define/src/main/java/org/apache/skywalking/apm/collector/storage/ui/common/ResponseTimeTrend.java @@ -25,4 +25,12 @@ import java.util.List; */ public class ResponseTimeTrend { private List trendList; + + public List getTrendList() { + return trendList; + } + + public void setTrendList(List trendList) { + this.trendList = trendList; + } } diff --git a/apm-collector/apm-collector-storage/collector-storage-es-provider/src/main/java/org/apache/skywalking/apm/collector/storage/es/dao/InstanceMetricEsUIDAO.java b/apm-collector/apm-collector-storage/collector-storage-es-provider/src/main/java/org/apache/skywalking/apm/collector/storage/es/dao/InstanceMetricEsUIDAO.java index 591e8e32d..d997d0314 100644 --- a/apm-collector/apm-collector-storage/collector-storage-es-provider/src/main/java/org/apache/skywalking/apm/collector/storage/es/dao/InstanceMetricEsUIDAO.java +++ b/apm-collector/apm-collector-storage/collector-storage-es-provider/src/main/java/org/apache/skywalking/apm/collector/storage/es/dao/InstanceMetricEsUIDAO.java @@ -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 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 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; } } diff --git a/apm-collector/apm-collector-storage/collector-storage-h2-provider/src/main/java/org/apache/skywalking/apm/collector/storage/h2/dao/InstanceMetricH2UIDAO.java b/apm-collector/apm-collector-storage/collector-storage-h2-provider/src/main/java/org/apache/skywalking/apm/collector/storage/h2/dao/InstanceMetricH2UIDAO.java index 77b3185bb..d52f8f9ee 100644 --- a/apm-collector/apm-collector-storage/collector-storage-h2-provider/src/main/java/org/apache/skywalking/apm/collector/storage/h2/dao/InstanceMetricH2UIDAO.java +++ b/apm-collector/apm-collector-storage/collector-storage-h2-provider/src/main/java/org/apache/skywalking/apm/collector/storage/h2/dao/InstanceMetricH2UIDAO.java @@ -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 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 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 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; } } diff --git a/apm-collector/apm-collector-ui/collector-ui-jetty-provider/src/main/java/org/apache/skywalking/apm/collector/ui/query/ServerQuery.java b/apm-collector/apm-collector-ui/collector-ui-jetty-provider/src/main/java/org/apache/skywalking/apm/collector/ui/query/ServerQuery.java index 9a6f32135..e7a6f604b 100644 --- a/apm-collector/apm-collector-ui/collector-ui-jetty-provider/src/main/java/org/apache/skywalking/apm/collector/ui/query/ServerQuery.java +++ b/apm-collector/apm-collector-ui/collector-ui-jetty-provider/src/main/java/org/apache/skywalking/apm/collector/ui/query/ServerQuery.java @@ -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) { diff --git a/apm-collector/apm-collector-ui/collector-ui-jetty-provider/src/main/java/org/apache/skywalking/apm/collector/ui/service/InstanceJVMService.java b/apm-collector/apm-collector-ui/collector-ui-jetty-provider/src/main/java/org/apache/skywalking/apm/collector/ui/service/InstanceJVMService.java index bf14afd97..182388026 100644 --- a/apm-collector/apm-collector-ui/collector-ui-jetty-provider/src/main/java/org/apache/skywalking/apm/collector/ui/service/InstanceJVMService.java +++ b/apm-collector/apm-collector-ui/collector-ui-jetty-provider/src/main/java/org/apache/skywalking/apm/collector/ui/service/InstanceJVMService.java @@ -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())) { diff --git a/apm-collector/apm-collector-ui/collector-ui-jetty-provider/src/main/java/org/apache/skywalking/apm/collector/ui/service/ServerService.java b/apm-collector/apm-collector-ui/collector-ui-jetty-provider/src/main/java/org/apache/skywalking/apm/collector/ui/service/ServerService.java index 6df24adf4..d7b3af08b 100644 --- a/apm-collector/apm-collector-ui/collector-ui-jetty-provider/src/main/java/org/apache/skywalking/apm/collector/ui/service/ServerService.java +++ b/apm-collector/apm-collector-ui/collector-ui-jetty-provider/src/main/java/org/apache/skywalking/apm/collector/ui/service/ServerService.java @@ -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 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 trends = instanceMetricUIDAO.getResponseTimeTrend(instanceId, step, timeBuckets); + responseTimeTrend.setTrendList(trends); + return responseTimeTrend; + } + private void buildAppServerInfo(List serverInfos) { serverInfos.forEach(serverInfo -> { if (StringUtils.isNotEmpty(serverInfo.getOsInfo())) { diff --git a/apm-collector/apm-collector-ui/collector-ui-jetty-provider/src/main/java/org/apache/skywalking/apm/collector/ui/utils/DurationUtils.java b/apm-collector/apm-collector-ui/collector-ui-jetty-provider/src/main/java/org/apache/skywalking/apm/collector/ui/utils/DurationUtils.java index 0bb562220..53a7b3793 100644 --- a/apm-collector/apm-collector-ui/collector-ui-jetty-provider/src/main/java/org/apache/skywalking/apm/collector/ui/utils/DurationUtils.java +++ b/apm-collector/apm-collector-ui/collector-ui-jetty-provider/src/main/java/org/apache/skywalking/apm/collector/ui/utils/DurationUtils.java @@ -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 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()]); + } } diff --git a/apm-collector/apm-collector-ui/collector-ui-jetty-provider/src/test/java/org/apache/skywalking/apm/collector/ui/utils/DurationUtilsTestCase.java b/apm-collector/apm-collector-ui/collector-ui-jetty-provider/src/test/java/org/apache/skywalking/apm/collector/ui/utils/DurationUtilsTestCase.java new file mode 100644 index 000000000..30abe75be --- /dev/null +++ b/apm-collector/apm-collector-ui/collector-ui-jetty-provider/src/test/java/org/apache/skywalking/apm/collector/ui/utils/DurationUtilsTestCase.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.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); + } +}