Package com.dianping.cat.report.task.alert

Source Code of com.dianping.cat.report.task.alert.BaseAlert

package com.dianping.cat.report.task.alert;

import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;

import org.codehaus.plexus.logging.Logger;
import org.unidal.lookup.annotation.Inject;
import org.unidal.tuple.Pair;

import com.dianping.cat.Cat;
import com.dianping.cat.advanced.metric.config.entity.MetricItemConfig;
import com.dianping.cat.consumer.company.model.entity.ProductLine;
import com.dianping.cat.consumer.metric.MetricAnalyzer;
import com.dianping.cat.consumer.metric.ProductLineConfigManager;
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.Segment;
import com.dianping.cat.helper.TimeHelper;
import com.dianping.cat.home.rule.entity.Condition;
import com.dianping.cat.home.rule.entity.Config;
import com.dianping.cat.report.baseline.BaselineService;
import com.dianping.cat.report.task.alert.sender.AlertEntity;
import com.dianping.cat.report.task.alert.sender.AlertManager;
import com.dianping.cat.service.ModelPeriod;
import com.dianping.cat.service.ModelRequest;
import com.dianping.cat.system.config.BaseRuleConfigManager;

public abstract class BaseAlert {

  @Inject
  protected BaseRuleConfigManager m_ruleConfigManager;

  @Inject
  protected AlertInfo m_alertInfo;

  @Inject
  protected DataChecker m_dataChecker;

  @Inject
  protected ProductLineConfigManager m_productLineConfigManager;

  @Inject
  protected BaselineService m_baselineService;

  @Inject
  protected RemoteMetricReportService m_service;

  @Inject
  protected AlertManager m_sendManager;

  protected static final int DATA_AREADY_MINUTE = 1;

  protected static final long DURATION = TimeHelper.ONE_MINUTE;

  protected Logger m_logger;

  protected Map<String, MetricReport> m_currentReports = new HashMap<String, MetricReport>();

  protected Map<String, MetricReport> m_lastReports = new HashMap<String, MetricReport>();

  protected String buildMetricName(String metricKey) {
    try {
      return metricKey.split(":")[2];
    } catch (Exception ex) {
      Cat.logError("get metric name error:" + metricKey, ex);
      return null;
    }
  }

  protected String extractDomain(String metricKey) {
    try {
      return metricKey.split(":")[0];
    } catch (Exception ex) {
      Cat.logError("extract domain error:" + metricKey, ex);
      return null;
    }
  }

  protected List<AlertResultEntity> computeAlertInfo(int minute, String product, String metricKey, MetricType type) {
    double[] value = null;
    double[] baseline = null;
    List<Config> configs = m_ruleConfigManager.queryConfigs(product, metricKey, type);
    Pair<Integer, List<Condition>> resultPair = queryCheckMinuteAndConditions(configs);
    int maxMinute = resultPair.getKey();
    List<Condition> conditions = resultPair.getValue();

    if (minute >= maxMinute - 1) {
      MetricReport report = fetchMetricReport(product, ModelPeriod.CURRENT);

      if (report != null) {
        int start = minute + 1 - maxMinute;
        int end = minute;

        value = queryRealData(start, end, metricKey, report, type);
        baseline = queryBaseLine(start, end, metricKey, new Date(ModelPeriod.CURRENT.getStartTime()), type);

        return m_dataChecker.checkData(value, baseline, conditions);
      }
    } else if (minute < 0) {
      MetricReport lastReport = fetchMetricReport(product, ModelPeriod.LAST);

      if (lastReport != null) {
        int start = 60 + minute + 1 - (maxMinute);
        int end = 60 + minute;

        value = queryRealData(start, end, metricKey, lastReport, type);
        baseline = queryBaseLine(start, end, metricKey, new Date(ModelPeriod.LAST.getStartTime()), type);
        return m_dataChecker.checkData(value, baseline, conditions);
      }
    } else {
      MetricReport currentReport = fetchMetricReport(product, ModelPeriod.CURRENT);
      MetricReport lastReport = fetchMetricReport(product, ModelPeriod.LAST);

      if (currentReport != null && lastReport != null) {
        int currentStart = 0, currentEnd = minute;
        double[] currentValue = queryRealData(currentStart, currentEnd, metricKey, currentReport, type);
        double[] currentBaseline = queryBaseLine(currentStart, currentEnd, metricKey,
              new Date(ModelPeriod.CURRENT.getStartTime()), type);

        int lastStart = 60 + 1 - (maxMinute - minute);
        int lastEnd = 59;
        double[] lastValue = queryRealData(lastStart, lastEnd, metricKey, lastReport, type);
        double[] lastBaseline = queryBaseLine(lastStart, lastEnd, metricKey,
              new Date(ModelPeriod.LAST.getStartTime()), type);

        value = mergerArray(lastValue, currentValue);
        baseline = mergerArray(lastBaseline, currentBaseline);
        return m_dataChecker.checkData(value, baseline, conditions);
      }
    }
    return new ArrayList<AlertResultEntity>();
  }

  protected MetricReport fetchMetricReport(String product, ModelPeriod period) {
    if (period == ModelPeriod.CURRENT) {
      MetricReport report = m_currentReports.get(product);

      if (report != null) {
        return report;
      } else {
        ModelRequest request = new ModelRequest(product, ModelPeriod.CURRENT.getStartTime()).setProperty(
              "requireAll", "ture");

        report = m_service.invoke(request);
        if (report != null) {
          m_currentReports.put(product, report);
        }
        return report;
      }
    } else if (period == ModelPeriod.LAST) {
      MetricReport report = m_lastReports.get(product);

      if (report != null) {
        return report;
      } else {
        ModelRequest request = new ModelRequest(product, ModelPeriod.LAST.getStartTime()).setProperty("requireAll",
              "ture");

        report = m_service.invoke(request);
        if (report != null) {
          m_lastReports.put(product, report);
        }
        return report;
      }
    } else {
      throw new RuntimeException("internal error, this can't be reached.");
    }
  }

  private boolean judgeCurrentInConfigRange(Config config) {
    try {
      if (compareTime(config.getStarttime(), config.getEndtime())) {
        return true;
      } else {
        return false;
      }
    } catch (Exception ex) {
      Cat.logError("throw exception when judge time: " + config.toString(), ex);
      return false;
    }
  }

  private boolean compareTime(String start, String end) {
    String[] startTime = start.split(":");
    int hourStart = Integer.parseInt(startTime[0]);
    int minuteStart = Integer.parseInt(startTime[1]);
    int startMinute = hourStart * 60 + minuteStart;

    String[] endTime = end.split(":");
    int hourEnd = Integer.parseInt(endTime[0]);
    int minuteEnd = Integer.parseInt(endTime[1]);
    int endMinute = hourEnd * 60 + minuteEnd;

    Calendar cal = Calendar.getInstance();
    int current = cal.get(Calendar.HOUR_OF_DAY) * 60 + cal.get(Calendar.MINUTE);

    return current >= startMinute && current <= endMinute;
  }

  protected double[] mergerArray(double[] from, double[] to) {
    int fromLength = from.length;
    int toLength = to.length;
    double[] result = new double[fromLength + toLength];
    int index = 0;

    for (int i = 0; i < fromLength; i++) {
      result[i] = from[i];
      index++;
    }
    for (int i = 0; i < toLength; i++) {
      result[i + index] = to[i];
    }
    return result;
  }

  protected boolean needAlert(MetricItemConfig config) {
    return true;
  }

  private void processMetricItem(int minute, ProductLine productLine, String metricKey) {
    for (MetricType type : MetricType.values()) {
      String productlineName = productLine.getId();
      List<AlertResultEntity> alertResults = computeAlertInfo(minute, productlineName, metricKey, type);

      for (AlertResultEntity alertResult : alertResults) {
        m_alertInfo.addAlertInfo(productlineName, metricKey, new Date().getTime());

        String metricName = buildMetricName(metricKey);
        AlertEntity entity = new AlertEntity();

        entity.setDate(alertResult.getAlertTime()).setContent(alertResult.getContent())
              .setLevel(alertResult.getAlertLevel());
        entity.setMetric(metricName).setType(getName()).setGroup(productlineName);

        m_sendManager.addAlert(entity);
      }
    }
  }

  protected void processProductLine(ProductLine productLine) {
    int minute = getAlreadyMinute();
    String product = productLine.getId();
    MetricReport report = fetchMetricReport(product, ModelPeriod.CURRENT);

    if (report != null) {
      for (Entry<String, MetricItem> entry : report.getMetricItems().entrySet()) {
        try {
          processMetricItem(minute, productLine, entry.getKey());
        } catch (Exception e) {
          Cat.logError(e);
        }
      }
    }
  }

  protected int getAlreadyMinute() {
    long current = (System.currentTimeMillis()) / 1000 / 60;
    int minute = (int) (current % (60)) - DATA_AREADY_MINUTE;

    return minute;
  }

  private double[] queryBaseLine(int start, int end, String baseLineKey, Date date, MetricType type) {
    double[] baseline = m_baselineService.queryHourlyBaseline(MetricAnalyzer.ID, baseLineKey + ":" + type, date);
    int length = end - start + 1;
    double[] result = new double[length];

    if (baseline != null) {
      System.arraycopy(baseline, start, result, 0, length);
    }

    return result;
  }

  protected Pair<Integer, List<Condition>> queryCheckMinuteAndConditions(List<Config> configs) {
    int maxMinute = 0;
    List<Condition> conditions = new ArrayList<Condition>();
    Iterator<Config> iterator = configs.iterator();

    while (iterator.hasNext()) {
      Config config = iterator.next();

      if (judgeCurrentInConfigRange(config)) {
        List<Condition> tmpConditions = config.getConditions();
        conditions.addAll(tmpConditions);

        for (Condition con : tmpConditions) {
          int tmpMinute = con.getMinute();

          if (tmpMinute > maxMinute) {
            maxMinute = tmpMinute;
          }
        }
      }
    }

    return new Pair<Integer, List<Condition>>(maxMinute, conditions);
  }

  private double[] queryRealData(int start, int end, String metricKey, MetricReport report, MetricType type) {
    double[] all = new double[60];
    Map<Integer, Segment> map = report.findOrCreateMetricItem(metricKey).getSegments();

    for (Entry<Integer, Segment> entry : map.entrySet()) {
      Integer minute = entry.getKey();
      Segment seg = entry.getValue();

      if (type == MetricType.AVG) {
        all[minute] = seg.getAvg();
      } else if (type == MetricType.COUNT) {
        all[minute] = (double) seg.getCount();
      } else if (type == MetricType.SUM) {
        all[minute] = seg.getSum();
      }
    }
    int length = end - start + 1;
    double[] result = new double[length];
    System.arraycopy(all, start, result, 0, length);

    return result;
  }

  protected abstract String getName();
}
TOP

Related Classes of com.dianping.cat.report.task.alert.BaseAlert

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.