提交 9002ec29 编写于 作者: F Frankie Wu

Merge branch 'biz' of github.com:dianping/cat into biz

......@@ -19,6 +19,7 @@ import com.dianping.cat.core.config.ConfigDao;
import com.dianping.cat.core.dal.ProjectDao;
import com.dianping.cat.home.dal.report.EventDao;
import com.dianping.cat.home.dal.report.TopologyGraphDao;
import com.dianping.cat.report.baseline.BaselineService;
import com.dianping.cat.report.graph.DefaultGraphBuilder;
import com.dianping.cat.report.graph.DefaultValueTranslater;
import com.dianping.cat.report.graph.GraphBuilder;
......@@ -29,6 +30,13 @@ import com.dianping.cat.report.page.dependency.graph.TopologyGraphConfigManager;
import com.dianping.cat.report.page.dependency.graph.TopologyGraphItemBuilder;
import com.dianping.cat.report.page.dependency.graph.TopologyGraphManager;
import com.dianping.cat.report.page.externalError.EventCollectManager;
import com.dianping.cat.report.page.metric.chart.CachedMetricReportService;
import com.dianping.cat.report.page.metric.chart.DataExtractor;
import com.dianping.cat.report.page.metric.chart.GraphCreator;
import com.dianping.cat.report.page.metric.chart.MetricDataFetcher;
import com.dianping.cat.report.page.metric.chart.impl.CachedMetricReportServiceImpl;
import com.dianping.cat.report.page.metric.chart.impl.DataExtractorImpl;
import com.dianping.cat.report.page.metric.chart.impl.MetricDataFetcherImpl;
import com.dianping.cat.report.page.model.spi.ModelService;
import com.dianping.cat.report.page.state.StateGraphs;
import com.dianping.cat.report.service.ReportService;
......@@ -64,11 +72,11 @@ public class ComponentsConfigurator extends AbstractResourceConfigurator {
all.add(C(EventCollectManager.class).req(EventDao.class, ServerConfigManager.class));
all.add(C(TopologyGraphConfigManager.class).req(ConfigDao.class));
all.add(C(ExceptionThresholdConfigManager.class).req(ConfigDao.class));
all.add(C(BugConfigManager.class).req(ConfigDao.class));
all.add(C(UtilizationConfigManager.class).req(ConfigDao.class));
all.add(C(TopologyGraphItemBuilder.class).req(TopologyGraphConfigManager.class));
......@@ -81,6 +89,15 @@ public class ComponentsConfigurator extends AbstractResourceConfigurator {
all.add(C(ConfigReloadTask.class).req(MetricConfigManager.class, ProductLineConfigManager.class));
all.add(C(CachedMetricReportService.class, CachedMetricReportServiceImpl.class).req(ModelService.class, "metric")
.req(ReportService.class));
all.add(C(DataExtractor.class, DataExtractorImpl.class));
all.add(C(MetricDataFetcher.class, MetricDataFetcherImpl.class));
all.add(C(GraphCreator.class).req(CachedMetricReportService.class, DataExtractor.class, MetricDataFetcher.class)
.req(BaselineService.class, MetricConfigManager.class, ProductLineConfigManager.class));
// report serivce
all.addAll(new ReportServiceComponentConfigurator().defineComponents());
// task
......
......@@ -9,11 +9,11 @@ public class Chinese {
public static final String RESPONSE_TIME = "响应时间";
public static final String EXCEPTION_COUNT = "错误数";
public static final String TOTAL_COUNT = "访问量";
public static final String EXCEPTION_INFO = "异常信息";
public static final String ZABBIX_ERROR = "Zabbix告警";
public static final String Suffix_SUM = "(总和)";
......@@ -21,5 +21,13 @@ public class Chinese {
public static final String Suffix_COUNT = "(次数)";
public static final String Suffix_AVG = "(平均)";
public static final String CURRENT_VALUE = "当前值";
public static final String BASELINE_VALUE = "基线值";
public static final String ONEDAY_VALUE = "前一天值";
public static final String ONEWEEK_VALUE = "前一个星期值";
}
......@@ -29,6 +29,12 @@ public class LineChart {
public LineChart() {
}
public LineChart add(String title,double[] value){
this.subTitles.add(title);
this.values.add(value);
return this;
}
public LineChart addSubTitle(String title) {
this.subTitles.add(title);
return this;
......
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) {
m_timeRange = timeRange;
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;
}
}
......@@ -4,11 +4,7 @@ import java.io.IOException;
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,92 +14,29 @@ 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;
import com.dianping.cat.consumer.company.model.entity.ProductLine;
import com.dianping.cat.consumer.metric.model.entity.MetricReport;
import com.dianping.cat.helper.TimeUtil;
import com.dianping.cat.report.ReportPage;
import com.dianping.cat.report.baseline.BaselineService;
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;
import com.dianping.cat.report.page.metric.chart.GraphCreator;
public class Handler implements PageHandler<Context> {
@Inject
private JspViewer m_jspViewer;
@Inject(type = ModelService.class, value = "metric")
private ModelService<MetricReport> m_service;
@Inject
private PayloadNormalizer m_normalizePayload;
@Inject
private MetricConfigManager m_configManager;
@Inject
private ProductLineConfigManager m_productLineConfigManager;
@Inject
private ABTestService m_abtestService;
@Inject
private ReportService m_reportService;
@Inject
private BaselineService m_baselineService;
private GraphCreator m_graphCreator;
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")
......@@ -118,66 +51,28 @@ public class Handler implements PageHandler<Context> {
Action action = payload.getAction();
normalize(model, payload);
MetricDisplay metricDisplay = null;
Collection<ProductLine> productLines = m_productLineConfigManager.queryProductLines().values();
long date = payload.getDate();
int timeRange = payload.getTimeRange();
Date start = new Date(date - (timeRange - 1) * TimeUtil.ONE_HOUR);
Date end = new Date(date + TimeUtil.ONE_HOUR);
switch (action) {
case METRIC:
metricDisplay = buildProductLineMetrics(payload.getProduct(), payload, false);
Map<String, LineChart> charts = m_graphCreator.build(payload.getProduct(), start, end, payload.getTest());
model.setLineCharts(metricDisplay.getLineCharts());
model.setAbtests(metricDisplay.getAbtests());
model.setLineCharts(new ArrayList<LineChart>(charts.values()));
break;
case DASHBOARD:
List<LineChart> allCharts = new ArrayList<LineChart>();
for (ProductLine productLine : productLines) {
metricDisplay = buildProductLineMetrics(productLine.getId(), payload, true);
List<LineChart> charts = metricDisplay.getLineCharts();
allCharts.addAll(charts);
}
model.setLineCharts(allCharts);
Map<String, LineChart> allCharts = m_graphCreator.build(true, start, end, payload.getTest());
model.setLineCharts(new ArrayList<LineChart>(allCharts.values()));
break;
}
model.setProductLines(productLines);
m_jspViewer.view(ctx, model);
}
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);
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);
if (report != null) {
displayMerger.visitMetricReport(index, report);
}
time = time + TimeUtil.ONE_HOUR;
}
display.generateLineCharts();
if (abtestID.equals("-1")) {
display.generateBaselineChart();
}
return display;
}
private void normalize(Model model, Payload payload) {
model.setPage(ReportPage.METRIC);
m_normalizePayload.normalize(model, payload);
......
package com.dianping.cat.report.page.metric;
public enum MetricDate {
CURRENT(0, "当前时段"),
LAST_DAY(-1, "前一天相同时段"),
LAST_WEEK(-7, "上周相同时段");
private int m_index;
private 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,89 +173,91 @@ 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) {
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 +274,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,16 @@ 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) {
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 +59,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 +66,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 +79,7 @@ public class MetricDisplayMerger extends BaseVisitor {
String id = group.getName();
if ("".equals(id)) {
id = "Current";
id = m_subtitle;
}
double[] sum = new double[60];
......
......@@ -18,17 +18,18 @@ public class Payload extends AbstractReportPayload<Action> {
@FieldMeta("frequency")
private int m_frequency = 10;
@FieldMeta("refresh")
private boolean m_refresh = false;
@FieldMeta("refresh")
private boolean m_refresh = false;
@FieldMeta("test")
private String m_test = "-1";
@FieldMeta("timeRange")
private int m_timeRange = 2;
@FieldMeta("fullScreen")
private boolean m_fullScreen = false;
@FieldMeta("fullScreen")
private boolean m_fullScreen = false;
public Payload() {
super(ReportPage.METRIC);
}
......@@ -67,34 +68,34 @@ public class Payload extends AbstractReportPayload<Action> {
public void setTest(String test) {
m_test = test;
}
public int getTimeRange() {
return m_timeRange;
}
public int getFrequency() {
return m_frequency;
}
return m_frequency;
}
public void setFrequency(int frequency) {
m_frequency = frequency;
}
m_frequency = frequency;
}
public boolean isRefresh() {
return m_refresh;
}
return m_refresh;
}
public void setRefresh(boolean refresh) {
m_refresh = refresh;
}
m_refresh = refresh;
}
public boolean isFullScreen() {
return m_fullScreen;
}
return m_fullScreen;
}
public void setFullScreen(boolean fullScreen) {
m_fullScreen = fullScreen;
}
m_fullScreen = fullScreen;
}
@Override
public void validate(ActionContext<?> ctx) {
......@@ -102,6 +103,5 @@ public class Payload extends AbstractReportPayload<Action> {
m_action = Action.METRIC;
}
}
}
......@@ -9,8 +9,8 @@ public enum Range {
NINE("9小时", 9),
THELVE("12小时", 12),
THELVE("12小时", 12),
ONE_DAY("24小时", 24), ;
private Range(String title, int duration) {
......
package com.dianping.cat.report.page.metric.chart;
import java.util.Date;
import com.dianping.cat.consumer.metric.model.entity.MetricReport;
public interface CachedMetricReportService {
public MetricReport query(String product,Date date);
}
package com.dianping.cat.report.page.metric.chart;
import java.util.Map;
public interface DataExtractor {
public double[] extractor(double[] values);
public Map<String, double[]> extractor(Map<String, double[]> values);
public int getStep();
}
package com.dianping.cat.report.page.metric.chart;
import java.util.Collection;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import org.unidal.lookup.annotation.Inject;
import com.dianping.cat.advanced.metric.config.entity.MetricItemConfig;
import com.dianping.cat.consumer.advanced.MetricAnalyzer;
import com.dianping.cat.consumer.advanced.MetricConfigManager;
import com.dianping.cat.consumer.advanced.ProductLineConfigManager;
import com.dianping.cat.consumer.company.model.entity.ProductLine;
import com.dianping.cat.consumer.metric.model.entity.MetricReport;
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.task.metric.MetricType;
public class GraphCreator {
@Inject
private BaselineService m_baselineService;
@Inject
private DataExtractor m_dataExtractor;
@Inject
private MetricDataFetcher m_pruductDataFetcher;
@Inject
private CachedMetricReportService m_metricReportService;
@Inject
private MetricConfigManager m_configManager;
@Inject
private ProductLineConfigManager m_productLineConfigManager;
private double[] queryBaseline(String key, Date start, Date end) {
int size = (int) ((end.getTime() - start.getTime()) / TimeUtil.ONE_MINUTE);
double[] result = new double[size];
int index = 0;
long startLong = start.getTime();
long endLong = end.getTime();
for (; startLong < endLong; startLong += TimeUtil.ONE_HOUR) {
double[] values = m_baselineService.queryHourlyBaseline(MetricAnalyzer.ID, key, new Date(startLong));
for (int j = 0; j < values.length; j++) {
result[index * 60 + j] = values[j];
}
index++;
}
return result;
}
public Map<String, LineChart> build(boolean isDashbord, Date start, Date end, String abtestId) {
Collection<ProductLine> productLines = m_productLineConfigManager.queryProductLines().values();
Map<String, LineChart> allCharts = new LinkedHashMap<String, LineChart>();
Map<String, LineChart> result = new LinkedHashMap<String, LineChart>();
for (ProductLine productLine : productLines) {
allCharts.putAll(build(productLine.getId(), start, end, abtestId));
}
Collection<MetricItemConfig> configs = m_configManager.getMetricConfig().getMetricItemConfigs().values();
for (MetricItemConfig config : configs) {
String key = config.getId();
if (config.getShowAvg() && config.getShowAvgDashboard()) {
String avgKey = key + ":" + MetricType.AVG.name();
put(allCharts, result, avgKey);
}
if (config.getShowCount() && config.getShowCountDashboard()) {
String countKey = key + ":" + MetricType.COUNT.name();
put(allCharts, result, countKey);
}
if (config.getShowSum() && config.getShowSumDashboard()) {
String sumKey = key + ":" + MetricType.SUM.name();
put(allCharts, result, sumKey);
}
}
return result;
}
private void put(Map<String, LineChart> allCharts, Map<String, LineChart> result, String key) {
LineChart value = allCharts.get(key);
System.out.println("====" + key + "====");
if (value != null) {
result.put(key, allCharts.get(key));
}
}
public Map<String, LineChart> build(String productLine, Date start, Date end, String abtestID) {
long startLong = start.getTime();
long endLong = end.getTime();
int totalSize = (int) ((endLong - startLong) / TimeUtil.ONE_MINUTE);
Map<String, double[]> allCurrentValues = new HashMap<String, double[]>();
Map<String, double[]> allOneDayValues = new HashMap<String, double[]>();
Map<String, double[]> allSevenDayValues = new HashMap<String, double[]>();
int index = 0;
for (; startLong < endLong; startLong += TimeUtil.ONE_HOUR) {
List<String> domains = m_productLineConfigManager.queryProductLineDomains(productLine);
List<MetricItemConfig> metricConfigs = m_configManager.queryMetricItemConfigs(new HashSet<String>(domains));
MetricReport metricReport = m_metricReportService.query(productLine, new Date(startLong));
MetricReport oneDayReport = m_metricReportService.query(productLine, new Date(startLong - TimeUtil.ONE_DAY));
MetricReport sevenDayReport = m_metricReportService.query(productLine, new Date(startLong - TimeUtil.ONE_DAY
* 7));
Map<String, double[]> currentValues = m_pruductDataFetcher.buildGraphData(metricReport, metricConfigs,
abtestID);
Map<String, double[]> oneDayValues = m_pruductDataFetcher
.buildGraphData(oneDayReport, metricConfigs, abtestID);
Map<String, double[]> sevenDayValues = m_pruductDataFetcher.buildGraphData(sevenDayReport, metricConfigs,
abtestID);
mergeMap(allCurrentValues, currentValues, totalSize, index);
mergeMap(allOneDayValues, oneDayValues, totalSize, index);
mergeMap(allSevenDayValues, sevenDayValues, totalSize, index);
index++;
}
allCurrentValues = m_dataExtractor.extractor(allCurrentValues);
allOneDayValues = m_dataExtractor.extractor(allOneDayValues);
allSevenDayValues = m_dataExtractor.extractor(allSevenDayValues);
int step = m_dataExtractor.getStep();
Map<String, LineChart> charts = new LinkedHashMap<String, LineChart>();
for (Entry<String, double[]> entry : allCurrentValues.entrySet()) {
String key = entry.getKey();
double[] value = entry.getValue();
LineChart lineChart = new LineChart();
lineChart.setTitle(findTitle(key));
lineChart.setStart(start);
lineChart.setSize(value.length);
lineChart.setStep(step * TimeUtil.ONE_MINUTE);
double[] baselines = queryBaseline(key, start, end);
lineChart.add(Chinese.CURRENT_VALUE, allCurrentValues.get(key));
lineChart.add(Chinese.BASELINE_VALUE, m_dataExtractor.extractor(baselines));
lineChart.add(Chinese.ONEDAY_VALUE, allOneDayValues.get(key));
lineChart.add(Chinese.ONEWEEK_VALUE, allSevenDayValues.get(key));
System.out.println(key);
charts.put(key, lineChart);
}
return charts;
}
private String findTitle(String key) {
int index = key.lastIndexOf(":");
String id = key.substring(0, index);
String type = key.substring(index + 1);
MetricItemConfig config = m_configManager.queryMetricItemConfig(id);
String des = "";
if (MetricType.AVG.name().equals(type)) {
des = Chinese.Suffix_AVG;
} else if (MetricType.SUM.name().equals(type)) {
des = Chinese.Suffix_SUM;
} else if (MetricType.COUNT.name().equals(type)) {
des = Chinese.Suffix_COUNT;
}
return config.getTitle() + des;
}
private void mergeMap(Map<String, double[]> all, Map<String, double[]> item, int size, int index) {
for (Entry<String, double[]> entry : item.entrySet()) {
String key = entry.getKey();
double[] value = entry.getValue();
double[] result = all.get(key);
if (result == null) {
result = new double[size];
all.put(key, result);
}
if (value != null) {
int length = value.length;
for (int i = 0; i < length; i++) {
result[index * 60 + i] = value[i];
}
}
}
}
}
package com.dianping.cat.report.page.metric.chart;
import java.util.List;
import java.util.Map;
import com.dianping.cat.advanced.metric.config.entity.MetricItemConfig;
import com.dianping.cat.consumer.metric.model.entity.MetricReport;
public interface MetricDataFetcher {
public Map<String, double[]> buildGraphData(MetricReport report, List<MetricItemConfig> metricConfigs,
String abtestID);
}
package com.dianping.cat.report.page.metric.chart.impl;
import java.util.Date;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Map.Entry;
import org.unidal.lookup.annotation.Inject;
import com.dianping.cat.Cat;
import com.dianping.cat.consumer.metric.model.entity.MetricReport;
import com.dianping.cat.helper.TimeUtil;
import com.dianping.cat.report.page.metric.chart.CachedMetricReportService;
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;
public class CachedMetricReportServiceImpl implements CachedMetricReportService {
@Inject
private ReportService m_reportService;
@Inject
private ModelService<MetricReport> m_service;
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;
}
};
@Override
public MetricReport query(String product, Date start) {
long time = start.getTime();
ModelPeriod period = ModelPeriod.getByTime(time);
if (period == ModelPeriod.CURRENT || period == ModelPeriod.LAST) {
ModelRequest request = new ModelRequest(product, time);
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, time);
}
}
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;
}
}
package com.dianping.cat.report.page.metric.chart.impl;
import java.util.HashMap;
import java.util.Map;
import java.util.Map.Entry;
import com.dianping.cat.report.page.metric.chart.DataExtractor;
public class DataExtractorImpl implements DataExtractor {
private int m_step;
private static final int MIN_POINT_NUMBER = 60;
private static final int MAX_POINT_NUMBER = 180;
private int intervalCalculate(int length) {
int[] values = { 1, 2, 3, 6, 10, 20, 30, 60 };
for (int value : values) {
int pm = length / value;
if (pm >= MIN_POINT_NUMBER && pm < MAX_POINT_NUMBER) {
return value;
}
}
int pm = length / 60;
if (pm > MAX_POINT_NUMBER) {
return 60;
} else {
return 1;
}
}
@Override
public double[] extractor(double[] values) {
int length = values.length;
m_step = intervalCalculate(length);
int size = length / m_step;
double[] result = new double[size];
for (int i = 0; i < length; i = i + m_step) {
double sum = 0;
for (int j = 0; j < m_step; j++) {
if (i + j <= length - 1) {
sum = sum + values[i + j];
}
}
result[i / m_step] = sum / m_step;
}
return result;
}
@Override
public Map<String, double[]> extractor(Map<String, double[]> values) {
Map<String, double[]> result = new HashMap<String, double[]>();
for (Entry<String, double[]> entry : values.entrySet()) {
result.put(entry.getKey(), extractor(entry.getValue()));
}
return result;
}
@Override
public int getStep() {
return m_step;
}
}
package com.dianping.cat.report.page.metric.chart.impl;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import com.dianping.cat.advanced.metric.config.entity.MetricItemConfig;
import com.dianping.cat.consumer.metric.model.entity.Abtest;
import com.dianping.cat.consumer.metric.model.entity.Group;
import com.dianping.cat.consumer.metric.model.entity.MetricItem;
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.page.metric.chart.MetricDataFetcher;
import com.dianping.cat.report.task.metric.MetricType;
public class MetricDataFetcherImpl implements MetricDataFetcher {
private final String SUM = MetricType.SUM.name();
private final String COUNT = MetricType.COUNT.name();
private final String AVG = MetricType.AVG.name();
@Override
public Map<String, double[]> buildGraphData(MetricReport metricReport, List<MetricItemConfig> metricConfigs,
String abtestId) {
MetricDataBuilder builder = new MetricDataBuilder(abtestId);
builder.visitMetricReport(metricReport);
Map<String, double[]> datas = builder.getDatas();
Map<String, double[]> values = new HashMap<String, double[]>();
for (MetricItemConfig config : metricConfigs) {
String key = config.getId();
if (config.getShowAvg()) {
String avgKey = key + ":" + AVG;
putKey(datas, values, avgKey);
}
if (config.getShowCount()) {
String countKey = key + ":" + COUNT;
putKey(datas, values, countKey);
}
if (config.getShowSum()) {
String sumKey = key + ":" + SUM;
putKey(datas, values, sumKey);
}
}
return values;
}
private void putKey(Map<String, double[]> datas, Map<String, double[]> values, String sumKey) {
double[] value = datas.get(sumKey);
if(value ==null){
value = new double[60];
}
values.put(sumKey, value);
}
public class MetricDataBuilder extends BaseVisitor {
private Map<String, double[]> m_datas = new LinkedHashMap<String, double[]>();
private String m_abtestId;
private String m_metricKey;
private String m_currentComputeType;
public MetricDataBuilder(String abtest) {
m_abtestId = abtest;
}
private double[] findOrCreateStatistic(String type, String metricKey, String computeType) {
String key = metricKey + ":" + computeType;
double[] statisticItem = m_datas.get(key);
if (statisticItem == null) {
statisticItem = new double[60];
m_datas.put(key, statisticItem);
}
return statisticItem;
}
public Map<String, double[]> getDatas() {
return m_datas;
}
@Override
public void visitAbtest(Abtest abtest) {
String abtestId = abtest.getRunId();
if (m_abtestId.equals(abtestId)) {
super.visitAbtest(abtest);
}
}
@Override
public void visitGroup(Group group) {
double[] sum = findOrCreateStatistic(m_currentComputeType, m_metricKey, SUM);
double[] count = findOrCreateStatistic(m_currentComputeType, m_metricKey, COUNT);
double[] avg = findOrCreateStatistic(m_currentComputeType, m_metricKey, AVG);
for (Point point : group.getPoints().values()) {
int index = point.getId();
sum[index] = point.getSum();
avg[index] = point.getAvg();
count[index] = point.getCount();
}
}
@Override
public void visitMetricItem(MetricItem metricItem) {
m_metricKey = metricItem.getId();
m_currentComputeType = metricItem.getType();
super.visitMetricItem(metricItem);
}
public void visitMetricReport(int index, MetricReport report) {
visitMetricReport(report);
}
@Override
public void visitMetricReport(MetricReport metricReport) {
super.visitMetricReport(metricReport);
}
}
}
......@@ -156,6 +156,51 @@
</requirement>
</requirements>
</component>
<component>
<role>com.dianping.cat.report.page.metric.chart.CachedMetricReportService</role>
<implementation>com.dianping.cat.report.page.metric.chart.impl.CachedMetricReportServiceImpl</implementation>
<requirements>
<requirement>
<role>com.dianping.cat.report.page.model.spi.ModelService</role>
<role-hint>metric</role-hint>
</requirement>
<requirement>
<role>com.dianping.cat.report.service.ReportService</role>
</requirement>
</requirements>
</component>
<component>
<role>com.dianping.cat.report.page.metric.chart.DataExtractor</role>
<implementation>com.dianping.cat.report.page.metric.chart.impl.DataExtractorImpl</implementation>
</component>
<component>
<role>com.dianping.cat.report.page.metric.chart.MetricDataFetcher</role>
<implementation>com.dianping.cat.report.page.metric.chart.impl.MetricDataFetcherImpl</implementation>
</component>
<component>
<role>com.dianping.cat.report.page.metric.chart.GraphCreator</role>
<implementation>com.dianping.cat.report.page.metric.chart.GraphCreator</implementation>
<requirements>
<requirement>
<role>com.dianping.cat.report.page.metric.chart.CachedMetricReportService</role>
</requirement>
<requirement>
<role>com.dianping.cat.report.page.metric.chart.DataExtractor</role>
</requirement>
<requirement>
<role>com.dianping.cat.report.page.metric.chart.MetricDataFetcher</role>
</requirement>
<requirement>
<role>com.dianping.cat.report.baseline.BaselineService</role>
</requirement>
<requirement>
<role>com.dianping.cat.consumer.advanced.MetricConfigManager</role>
</requirement>
<requirement>
<role>com.dianping.cat.consumer.advanced.ProductLineConfigManager</role>
</requirement>
</requirements>
</component>
<component>
<role>com.dianping.cat.report.service.impl.TransactionReportService</role>
<implementation>com.dianping.cat.report.service.impl.TransactionReportService</implementation>
......@@ -2811,15 +2856,15 @@
<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>
<requirement>
<role>com.dianping.cat.report.baseline.BaselineService</role>
</requirement>
<requirement>
<role>com.dianping.cat.report.page.metric.chart.GraphCreator</role>
</requirement>
</requirements>
</component>
<component>
......@@ -2849,6 +2894,30 @@
</requirement>
</requirements>
</component>
<component>
<role>com.dianping.cat.report.page.metric.chart.GraphCreator</role>
<implementation>com.dianping.cat.report.page.metric.chart.GraphCreator</implementation>
<requirements>
<requirement>
<role>com.dianping.cat.report.baseline.BaselineService</role>
</requirement>
<requirement>
<role>com.dianping.cat.report.page.metric.chart.DataExtractor</role>
</requirement>
<requirement>
<role>com.dianping.cat.report.page.metric.chart.MetricDataFetcher</role>
</requirement>
<requirement>
<role>com.dianping.cat.report.page.metric.chart.CachedMetricReportService</role>
</requirement>
<requirement>
<role>com.dianping.cat.consumer.advanced.MetricConfigManager</role>
</requirement>
<requirement>
<role>com.dianping.cat.consumer.advanced.ProductLineConfigManager</role>
</requirement>
</requirements>
</component>
<component>
<role>com.dianping.cat.report.page.jsError.Handler</role>
<implementation>com.dianping.cat.report.page.jsError.Handler</implementation>
......
......@@ -7,7 +7,6 @@
<jsp:useBean id="payload" type="com.dianping.cat.report.page.metric.Payload" scope="request"/>
<jsp:useBean id="model" type="com.dianping.cat.report.page.metric.Model" scope="request"/>
<c:choose>
<c:when test="${payload.fullScreen}">
<res:bean id="res" />
......
......@@ -13,7 +13,6 @@
</div><!--/.well -->
</div><!--/span-->
<div class="span10">
<h4 class='text-center text-error'>说明:图中纵轴数据为10分钟数据之和</h4>
<c:forEach var="item" items="${model.lineCharts}" varStatus="status">
<div style="float:left;">
<div id="${item.title}" class="metricGraph"></div>
......
......@@ -54,7 +54,6 @@
</th>
</tr>
</table>
<div class="container-fluid">
<div class="row-fluid">
<div class="span2">
<div class="well sidebar-nav">
......@@ -76,15 +75,11 @@
</div><!--/.well -->
</div><!--/span-->
<div class="span10">
<c:if test="${payload.timeRange eq 24 }">
<h4 class='text-red'>说明:图中纵轴数据为10分钟数据之和</h4>
</c:if>
<c:forEach var="item" items="${model.lineCharts}" varStatus="status">
<div style="float:left;">
<div id="${item.title}" class="metricGraph"></div>
</div>
</c:forEach>
</div>
</div>
</a:body>
<style type="text/css">
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册