提交 30ae9a37 编写于 作者: R Renyuan Sun

refactor metric report

上级 bbc41820
package com.dianping.cat.report.page.metric;
public class BaselineExtractor{
}
package com.dianping.cat.report.page.metric;
import java.util.List;
public class DataExtractor {
private int m_timeRange;
private int m_interval;
private static final int MINUTE = 60;
public DataExtractor(int timeRange, int interval) {
super();
this.m_timeRange = timeRange;
this.m_interval = interval;
}
public double[] extract(List<double[]> datas, int offset) {
int pointNumber = (m_timeRange * MINUTE) / m_interval;
double[] result = new double[pointNumber];
if(datas == null){
return result;
}
int size = datas.size();
double[] hourData = null;
int length = 0;
for (int i = 0, j = -1; i < pointNumber; i++) {
int insideOffset = i * m_interval + offset;
while (length <= insideOffset) {
insideOffset = insideOffset - length;
offset = offset - length;
j++;
if (j >= size) {
return result;
}
hourData = datas.get(j);
if (hourData == null) {
length = 0;
continue;
}
length = hourData.length;
}
result[i] = avgOfArray(hourData, insideOffset, m_interval);
}
return result;
}
private double avgOfArray(double[] values, int index, int interval) {
double result = 0;
for (int i = index; i < index + interval; i++) {
if (values[i] >= 0) {
result += values[i];
}
}
return result / interval;
}
// private double sumOfArray(double[] values, int index, int interval) {
//
// double result = 0;
//
// for (int i = index; i < index + interval; i++) {
// if (values[i] >= 0) {
// result += values[i];
// }
// }
// return result;
// }
}
......@@ -5,10 +5,7 @@ import java.util.ArrayList;
import java.util.Collection;
import java.util.Date;
import java.util.HashSet;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import javax.servlet.ServletException;
......@@ -18,7 +15,6 @@ import org.unidal.web.mvc.annotation.InboundActionMeta;
import org.unidal.web.mvc.annotation.OutboundActionMeta;
import org.unidal.web.mvc.annotation.PayloadMeta;
import com.dianping.cat.Cat;
import com.dianping.cat.advanced.metric.config.entity.MetricItemConfig;
import com.dianping.cat.consumer.advanced.MetricConfigManager;
import com.dianping.cat.consumer.advanced.ProductLineConfigManager;
......@@ -31,10 +27,6 @@ import com.dianping.cat.report.page.LineChart;
import com.dianping.cat.report.page.PayloadNormalizer;
import com.dianping.cat.report.page.model.spi.ModelService;
import com.dianping.cat.report.service.ReportService;
import com.dianping.cat.service.ModelPeriod;
import com.dianping.cat.service.ModelRequest;
import com.dianping.cat.service.ModelResponse;
import com.dianping.cat.system.page.abtest.service.ABTestService;
public class Handler implements PageHandler<Context> {
@Inject
......@@ -52,9 +44,6 @@ public class Handler implements PageHandler<Context> {
@Inject
private ProductLineConfigManager m_productLineConfigManager;
@Inject
private ABTestService m_abtestService;
@Inject
private ReportService m_reportService;
......@@ -63,47 +52,6 @@ public class Handler implements PageHandler<Context> {
private static final String TUAN = "TuanGou";
private final Map<String, MetricReport> m_metricReportMap = new LinkedHashMap<String, MetricReport>() {
private static final long serialVersionUID = 1L;
@Override
protected boolean removeEldestEntry(Entry<String, MetricReport> eldest) {
return size() > 1000;
}
};
private MetricReport getReportFromDB(String product, long date) {
String key = product + date;
MetricReport result = m_metricReportMap.get(key);
if (result == null) {
Date start = new Date(date);
Date end = new Date(date + TimeUtil.ONE_HOUR);
try {
result = m_reportService.queryMetricReport(product, start, end);
m_metricReportMap.put(key, result);
} catch (Exception e) {
Cat.logError(e);
}
}
return result;
}
private MetricReport getReport(ModelPeriod period, String product, long date) {
if (period == ModelPeriod.CURRENT || period == ModelPeriod.LAST) {
ModelRequest request = new ModelRequest(product, date);
if (m_service.isEligable(request)) {
ModelResponse<MetricReport> response = m_service.invoke(request);
MetricReport report = response.getModel();
return report;
} else {
throw new RuntimeException("Internal error: no eligable metric service registered for " + request + "!");
}
} else {
return getReportFromDB(product, date);
}
}
@Override
@PayloadMeta(Payload.class)
@InboundActionMeta(name = "metric")
......@@ -144,38 +92,25 @@ public class Handler implements PageHandler<Context> {
m_jspViewer.view(ctx, model);
}
private MetricDisplay buildProductLineMetrics(String product, Payload payload, boolean isDashboard) {
private MetricDisplay buildProductLineMetrics(String product,
Payload payload, boolean isDashboard) {
long date = payload.getDate();
String abtestID = payload.getTest();
int timeRange = payload.getTimeRange();
Date startTime = new Date(date - (timeRange - 1) * TimeUtil.ONE_HOUR);
List<String> domains = m_productLineConfigManager.queryProductLineDomains(product);
List<MetricItemConfig> metricConfigs = m_configManager.queryMetricItemConfigs(new HashSet<String>(domains));
MetricDisplay display = new MetricDisplay(abtestID, startTime, isDashboard, timeRange);
List<String> domains = m_productLineConfigManager
.queryProductLineDomains(product);
List<MetricItemConfig> metricConfigs = m_configManager
.queryMetricItemConfigs(new HashSet<String>(domains));
MetricDisplay display = new MetricDisplay(product, abtestID, startTime,
isDashboard, timeRange);
display.initializeLineCharts(metricConfigs);
MetricDisplayMerger displayMerger = new MetricDisplayMerger(abtestID, isDashboard);
long time = startTime.getTime();
displayMerger.setAbtestService(m_abtestService);
display.setBaselineService(m_baselineService);
display.setDisplayMerger(displayMerger);
for (int index = 0; index < timeRange; index++) {
ModelPeriod period = ModelPeriod.getByTime(time);
MetricReport report = getReport(period, product, time);
display.setBaselineService(m_baselineService).setReportService(m_reportService).setService(m_service);
if (report != null) {
displayMerger.visitMetricReport(index, report);
}
time = time + TimeUtil.ONE_HOUR;
}
display.generateLineCharts();
if (abtestID.equals("-1")) {
display.generateBaselineChart();
}
display.generateAllCharts();
return display;
}
......
package com.dianping.cat.report.page.metric;
public enum MetricDate {
CURRENT(0,"当前时段"),
LAST_DAY(-1,"前一天相同时段"),
LAST_WEEK(-7,"上周相同时段");
int m_index;
String m_title;
private MetricDate(int index,String title){
m_index = index;
m_title = title;
}
public int getIndex() {
return m_index;
}
public String getTitle() {
return m_title;
}
}
......@@ -8,14 +8,21 @@ import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import com.dianping.cat.Cat;
import com.dianping.cat.advanced.metric.config.entity.MetricItemConfig;
import com.dianping.cat.consumer.metric.model.entity.MetricReport;
import com.dianping.cat.consumer.metric.model.transform.BaseVisitor;
import com.dianping.cat.helper.Chinese;
import com.dianping.cat.helper.TimeUtil;
import com.dianping.cat.report.baseline.BaselineService;
import com.dianping.cat.report.page.LineChart;
import com.dianping.cat.report.page.model.spi.ModelService;
import com.dianping.cat.report.service.ReportService;
import com.dianping.cat.report.task.TaskHelper;
import com.dianping.cat.report.task.metric.MetricType;
import com.dianping.cat.service.ModelPeriod;
import com.dianping.cat.service.ModelRequest;
import com.dianping.cat.service.ModelResponse;
public class MetricDisplay extends BaseVisitor {
......@@ -23,21 +30,25 @@ public class MetricDisplay extends BaseVisitor {
private Map<Integer, com.dianping.cat.home.dal.abtest.Abtest> m_abtests = new HashMap<Integer, com.dianping.cat.home.dal.abtest.Abtest>();
private Date m_start;
private BaselineService m_baselineService;
private boolean m_isDashboard;
private DataExtractor m_dataExtractor;
private MetricDisplayMerger m_displayMerger;
private Date m_start;
private boolean m_isDashboard;
private int m_timeRange;
private int m_pointNumber;
private int m_interval = 1;
private String m_abtest;
private int m_realPointNumber;
private String m_product;
private int m_interval = 1;
private static final int MIN_POINT_NUMBER = 60;
private static final int MAX_POINT_NUMBER = 180;
private static final String SUM = MetricType.SUM.name();
......@@ -45,19 +56,21 @@ public class MetricDisplay extends BaseVisitor {
private static final String AVG = MetricType.AVG.name();
private static final int HOUR = 24;
private static final String METRIC_STRING = "metric";
private static final int MINUTE = 60;
private ReportService m_reportService;
private static final String METRIC_STRING = "metric";
private ModelService<MetricReport> m_service;
public MetricDisplayMerger getDisplayMerger() {
return m_displayMerger;
}
private final Map<String, MetricReport> m_metricReportMap = new LinkedHashMap<String, MetricReport>() {
public void setDisplayMerger(MetricDisplayMerger displayMerger) {
m_displayMerger = displayMerger;
}
private static final long serialVersionUID = 1L;
@Override
protected boolean removeEldestEntry(Entry<String, MetricReport> eldest) {
return size() > 1000;
}
};
private boolean showAvg(MetricItemConfig config) {
if (m_isDashboard) {
......@@ -83,18 +96,61 @@ public class MetricDisplay extends BaseVisitor {
}
}
public MetricDisplay(String abtest, Date start, boolean isDashboard, int timeRange) {
int minute = (int) (System.currentTimeMillis() % TimeUtil.ONE_HOUR / TimeUtil.ONE_MINUTE);
private MetricReport getReportFromDB(String product, long date) {
String key = product + date;
MetricReport result = m_metricReportMap.get(key);
if (result == null) {
Date start = new Date(date);
Date end = new Date(date + TimeUtil.ONE_HOUR);
try {
result = m_reportService.queryMetricReport(product, start, end);
m_metricReportMap.put(key, result);
} catch (Exception e) {
Cat.logError(e);
}
}
return result;
}
private MetricReport getReport(ModelPeriod period, String product, long date) {
if (period == ModelPeriod.CURRENT || period == ModelPeriod.LAST) {
ModelRequest request = new ModelRequest(product, date);
if (m_service.isEligable(request)) {
ModelResponse<MetricReport> response = m_service.invoke(request);
MetricReport report = response.getModel();
return report;
} else {
throw new RuntimeException("Internal error: no eligable metric service registered for " + request + "!");
}
} else {
return getReportFromDB(product, date);
}
}
public MetricDisplay(String product, String abtest, Date start, boolean isDashboard, int timeRange) {
m_product = product;
m_isDashboard = isDashboard;
m_start = start;
m_timeRange = timeRange;
if (m_timeRange == 24) {
m_interval = 6;
m_abtest = abtest;
m_interval = intervalCalculate(m_timeRange);
m_dataExtractor = new DataExtractor(m_timeRange, m_interval);
}
private int intervalCalculate(int timeRange) {
int[] values = { 1, 2, 3, 6, 10, 20, 30, 60 };
for (int value : values) {
int pm = timeRange * 60 / value;
if (pm >= MIN_POINT_NUMBER && pm < MAX_POINT_NUMBER) {
return value;
}
}
int pm = timeRange * 60 / 60;
if (pm > MAX_POINT_NUMBER) {
return 60;
} else {
m_interval = 1;
return 1;
}
m_pointNumber = m_timeRange * MINUTE / m_interval;
m_realPointNumber = (m_timeRange * MINUTE - 60 + minute) / m_interval;
}
public void initializeLineCharts(List<MetricItemConfig> configs) {
......@@ -117,87 +173,99 @@ public class MetricDisplay extends BaseVisitor {
private LineChart createLineChart(String title) {
LineChart lineChart = new LineChart();
int pointNumber = m_timeRange * 60 / m_interval;
lineChart.setTitle(title);
lineChart.setStart(m_start);
lineChart.setSize(m_pointNumber);
lineChart.setSize(pointNumber);
lineChart.setStep(TimeUtil.ONE_MINUTE * m_interval);
return lineChart;
}
public void generateBaselineChart() {
public void generateAllCharts() {
long startTime = m_start.getTime();
for (MetricDate metricDate : MetricDate.values()) {
MetricReportMerger merger = new MetricReportMerger(m_abtest, metricDate.getTitle());
long time = startTime + metricDate.getIndex() * TimeUtil.ONE_DAY;
for (int index = 0; index < m_timeRange; index++) {
ModelPeriod period = ModelPeriod.getByTime(time);
MetricReport report = getReport(period, m_product, time);
if (report != null) {
merger.visitMetricReport(index, report);
}
time = time + TimeUtil.ONE_HOUR;
}
generateLineCharts(merger);
if (metricDate.equals(MetricDate.CURRENT) && m_abtest.equals("-1")) {
generateBaselineChart(merger);
}
}
}
public void generateBaselineChart(MetricReportMerger merger) {
long time = m_start.getTime();
for (int index = 0; index < m_timeRange; index++) {
ModelPeriod period = ModelPeriod.getByTime(time);
MetricReport report = getReport(period, m_product, time);
if (report != null) {
merger.visitMetricReport(index, report);
}
time = time + TimeUtil.ONE_HOUR;
}
for (String key : m_lineCharts.keySet()) {
LineChart lineChart = m_lineCharts.get(key);
Date yesterday = TaskHelper.todayZero(m_start);
boolean isAvg = key.toUpperCase().endsWith(AVG);
int index = (int) ((m_start.getTime() + 8 * TimeUtil.ONE_HOUR) % TimeUtil.ONE_DAY / TimeUtil.ONE_MINUTE);
int offset = (int) ((m_start.getTime() + 8 * TimeUtil.ONE_HOUR) % TimeUtil.ONE_DAY / TimeUtil.ONE_MINUTE);
double[] yesterdayBaseline = m_baselineService.queryDailyBaseline(METRIC_STRING, key, yesterday);
Date today = TaskHelper.tomorrowZero(m_start);
double[] todayBaseline = m_baselineService.queryDailyBaseline(METRIC_STRING, key, today);
double[] value = new double[m_realPointNumber];
double[] day = yesterdayBaseline;
for (int i = 0; i < m_realPointNumber; i++) {
int j = (index + i * m_interval) % (HOUR * MINUTE);
if (j == 0 && index != 0) {
day = todayBaseline;
}
if (day == null) {
continue;
}
if (isAvg) {
value[i] = avgOfArray(day, i * m_interval);
} else {
value[i] = sumOfArray(day, i * m_interval);
}
List<double[]> datas = new ArrayList<double[]>();
if (yesterdayBaseline != null) {
datas.add(yesterdayBaseline);
} else if(todayBaseline != null){
datas.add(todayBaseline);
}
double[] value = m_dataExtractor.extract(datas, offset);
lineChart.addSubTitle("Baseline");
lineChart.addValue(value);
}
}
public void generateLineCharts() {
Map<String, Map<String, double[][]>> metricDatas = m_displayMerger.getMetricStatistic();
public void generateLineCharts(MetricReportMerger merger) {
Map<String, Map<String, double[][]>> metricDatas = merger.getMetricStatistic();
for (Entry<String, Map<String, double[][]>> entry : metricDatas.entrySet()) {
String key = entry.getKey();
Map<String, double[][]> value = entry.getValue();
LineChart lineChart = m_lineCharts.get(key);
List<double[]> resultValues = new ArrayList<double[]>();
List<String> subTitles = new ArrayList<String>();
boolean isAvg = key.toUpperCase().endsWith(AVG);
if (lineChart == null) {
lineChart = createLineChart(key);
m_lineCharts.put(key, lineChart);
}
lineChart.setSubTitles(subTitles);
lineChart.setValues(resultValues);
for (Entry<String, double[][]> metricItem : value.entrySet()) {
String subTitle = metricItem.getKey();
double[][] metricItemData = metricItem.getValue();
double[] resultValue = new double[m_realPointNumber];
subTitles.add(subTitle);
resultValues.add(resultValue);
for (int hour = 0; hour < metricItemData.length; hour++) {
for (int i = 0; i < MINUTE / m_interval; i++) {
int index = hour * MINUTE / m_interval + i;
if (metricItemData[hour] == null) {
continue;
}
if (index >= m_realPointNumber) {
break;
}
if (isAvg) {
resultValue[index] = avgOfArray(metricItemData[hour], i * m_interval);
} else {
resultValue[index] = sumOfArray(metricItemData[hour], i * m_interval);
}
List<double[]> datas = new ArrayList<double[]>();
for (double[] data : metricItemData) {
if(data == null){
data = new double[60];
}
datas.add(data);
}
double[] resultValue = m_dataExtractor.extract(datas, 0);
lineChart.addSubTitle(subTitle);
lineChart.addValue(resultValue);
}
}
......@@ -216,24 +284,14 @@ public class MetricDisplay extends BaseVisitor {
return this;
}
private double avgOfArray(double[] values, int j) {
double result = 0;
for (int i = j; i < j + m_interval; i++) {
if (values[i] >= 0) {
result += values[i];
}
}
return result / m_interval;
public MetricDisplay setReportService(ReportService m_reportService) {
this.m_reportService = m_reportService;
return this;
}
private double sumOfArray(double[] values, int j) {
double result = 0;
for (int i = j; i < j + m_interval; i++) {
if (values[i] >= 0) {
result += values[i];
}
}
return result;
public MetricDisplay setService(ModelService<MetricReport> m_service) {
this.m_service = m_service;
return this;
}
}
package com.dianping.cat.report.page.metric;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.Map;
......@@ -11,22 +10,18 @@ import com.dianping.cat.consumer.metric.model.entity.MetricReport;
import com.dianping.cat.consumer.metric.model.entity.Point;
import com.dianping.cat.consumer.metric.model.transform.BaseVisitor;
import com.dianping.cat.report.task.metric.MetricType;
import com.dianping.cat.system.page.abtest.service.ABTestService;
public class MetricDisplayMerger extends BaseVisitor {
public class MetricReportMerger extends BaseVisitor {
private Map<String, Map<String, double[][]>> m_metricStatistic = new LinkedHashMap<String, Map<String, double[][]>>();
private Map<Integer, com.dianping.cat.home.dal.abtest.Abtest> m_abtests = new HashMap<Integer, com.dianping.cat.home.dal.abtest.Abtest>();
private String m_abtest;
private String m_subtitle;
private String m_metricKey;
private String m_currentComputeType;
private ABTestService m_abtestService;
private int m_index;
private static final String SUM = MetricType.SUM.name();
......@@ -35,18 +30,17 @@ public class MetricDisplayMerger extends BaseVisitor {
private static final String AVG = MetricType.AVG.name();
private boolean m_isDashboard;
public MetricDisplayMerger(String abtest, boolean isDashboard) {
public MetricReportMerger(String abtest,String subtitle) {
m_abtest = abtest;
m_isDashboard = isDashboard;
m_subtitle = subtitle;
}
private Map<String, double[][]> findOrCreateStatistic(String type, String metricKey, String computeType) {
private Map<String, double[][]> findOrCreateStatistic(String type,
String metricKey, String computeType) {
String key = metricKey + ":" + computeType;
Map<String, double[][]> statisticItem = m_metricStatistic.get(key);
if (statisticItem == null && !m_isDashboard) {
if (statisticItem == null) {
if (computeType.equals(COUNT)) {
if (type.equals("C") || type.equals("S,C")) {
statisticItem = createMetricStatistic(key);
......@@ -66,11 +60,6 @@ public class MetricDisplayMerger extends BaseVisitor {
}
return statisticItem;
}
public MetricDisplayMerger setAbtestService(ABTestService service) {
m_abtestService = service;
return this;
}
private Map<String, double[][]> createMetricStatistic(String key) {
Map<String, double[][]> value = new LinkedHashMap<String, double[][]>();
......@@ -78,27 +67,9 @@ public class MetricDisplayMerger extends BaseVisitor {
return value;
}
private com.dianping.cat.home.dal.abtest.Abtest findAbTest(int id) {
com.dianping.cat.home.dal.abtest.Abtest abtest = null;
if (id >= 0) {
abtest = m_abtestService.getABTestByRunId(id);
}
if (abtest == null) {
abtest = new com.dianping.cat.home.dal.abtest.Abtest();
abtest.setId(id);
abtest.setName(String.valueOf(id));
}
return abtest;
}
@Override
public void visitAbtest(Abtest abtest) {
String abtestId = abtest.getRunId();
int id = Integer.parseInt(abtestId);
com.dianping.cat.home.dal.abtest.Abtest temp = findAbTest(id);
m_abtests.put(id, temp);
if (m_abtest.equals(abtestId)) {
super.visitAbtest(abtest);
}
......@@ -109,7 +80,7 @@ public class MetricDisplayMerger extends BaseVisitor {
String id = group.getName();
if ("".equals(id)) {
id = "Current";
id = m_subtitle;
}
double[] sum = new double[60];
......@@ -124,21 +95,24 @@ public class MetricDisplayMerger extends BaseVisitor {
count[index] = point.getCount();
}
Map<String, double[][]> sumLines = findOrCreateStatistic(m_currentComputeType, m_metricKey, SUM);
Map<String, double[][]> sumLines = findOrCreateStatistic(
m_currentComputeType, m_metricKey, SUM);
if (sumLines != null) {
double[][] sumLine = findOrCreateLine(sumLines, id);
sumLine[m_index] = sum;
}
Map<String, double[][]> countLines = findOrCreateStatistic(m_currentComputeType, m_metricKey, COUNT);
Map<String, double[][]> countLines = findOrCreateStatistic(
m_currentComputeType, m_metricKey, COUNT);
if (countLines != null) {
double[][] countLine = findOrCreateLine(countLines, id);
countLine[m_index] = count;
}
Map<String, double[][]> avgLines = findOrCreateStatistic(m_currentComputeType, m_metricKey, AVG);
Map<String, double[][]> avgLines = findOrCreateStatistic(
m_currentComputeType, m_metricKey, AVG);
if (avgLines != null) {
double[][] avgLine = findOrCreateLine(avgLines, id);
......
......@@ -2811,9 +2811,6 @@
<requirement>
<role>com.dianping.cat.consumer.advanced.ProductLineConfigManager</role>
</requirement>
<requirement>
<role>com.dianping.cat.system.page.abtest.service.ABTestService</role>
</requirement>
<requirement>
<role>com.dianping.cat.report.service.ReportService</role>
</requirement>
......
......@@ -78,9 +78,6 @@
</div><!--/.well -->
</div><!--/span-->
<div class="span10">
<c:if test="${payload.timeRange eq 24 }">
<h3 class='text-red'>说明:图中纵轴数据为10分钟数据之和</h3>
</c:if>
<c:forEach var="item" items="${model.lineCharts}" varStatus="status">
<div style="float:left;">
<div id="${item.title}" class="metricGraph"></div>
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册