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

Source Code of com.dianping.cat.report.task.alert.web.WebAlert

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

import java.util.ArrayList;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.unidal.helper.Splitters;
import org.unidal.helper.Threads.Task;
import org.unidal.lookup.annotation.Inject;
import org.unidal.tuple.Pair;

import com.dianping.cat.Cat;
import com.dianping.cat.Constants;
import com.dianping.cat.Monitor;
import com.dianping.cat.config.app.AppDataService;
import com.dianping.cat.config.url.UrlPatternConfigManager;
import com.dianping.cat.configuration.url.pattern.entity.PatternItem;
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.home.rule.entity.Rule;
import com.dianping.cat.message.Transaction;
import com.dianping.cat.report.task.alert.AlertResultEntity;
import com.dianping.cat.report.task.alert.AlertType;
import com.dianping.cat.report.task.alert.BaseAlert;
import com.dianping.cat.report.task.alert.sender.AlertEntity;
import com.dianping.cat.service.ModelPeriod;
import com.dianping.cat.service.ModelRequest;

public class WebAlert extends BaseAlert implements Task {

  @Inject
  private UrlPatternConfigManager m_urlPatternConfigManager;

  @Override
  public void run() {
    boolean active = true;
    try {
      Thread.sleep(5000);
    } catch (InterruptedException e) {
      active = false;
    }
    while (active) {
      Transaction t = Cat.newTransaction("AlertWeb", TimeHelper.getMinuteStr());
      long current = System.currentTimeMillis();

      try {
        for (PatternItem item : m_urlPatternConfigManager.queryUrlPatternRules()) {
          try {
            processUrl(item);
          } catch (Exception e) {
            Cat.logError(e);
          }
        }
        t.setStatus(Transaction.SUCCESS);
      } catch (Exception e) {
        t.setStatus(e);
        Cat.logError(e);
      } finally {
        m_currentReports.clear();
        m_lastReports.clear();
        t.complete();
      }
      long duration = System.currentTimeMillis() - current;

      try {
        if (duration < DURATION) {
          Thread.sleep(DURATION - duration);
        }
      } catch (InterruptedException e) {
        active = false;
      }
    }
  }

  private void processUrl(PatternItem item) {
    String url = item.getName();
    String group = item.getGroup();
    List<AlertResultEntity> alertResults = new ArrayList<AlertResultEntity>();
    List<Rule> rules = queryRuelsForUrl(url);
    long current = (System.currentTimeMillis()) / 1000 / 60;
    int minute = (int) (current % (60)) - DATA_AREADY_MINUTE;

    for (Rule rule : rules) {
      String id = rule.getId();
      int index1 = id.indexOf(":");
      int index2 = id.indexOf(":", index1 + 1);
      String idPrefix = id.substring(0, index1);
      String type = id.substring(index1 + 1, index2);
      String name = id.substring(index2 + 1);
     
      alertResults = computeAlertForRule(idPrefix, type, rule.getConfigs(), url, minute);

      for (AlertResultEntity alertResult : alertResults) {
        Map<String, Object> par = new HashMap<String, Object>();
        par.put("type", queryType(type));
        par.put("name", name);
        AlertEntity entity = new AlertEntity();

        entity.setDate(alertResult.getAlertTime()).setContent(alertResult.getContent())
              .setLevel(alertResult.getAlertLevel());
        entity.setMetric(group).setType(getName()).setGroup(url).setParas(par);
        m_sendManager.addAlert(entity);
      }
    }
  }

  private String queryType(String type) {
    String title = "";

    if (AppDataService.SUCCESS.equals(type)) {
      title = "成功率(%/分钟)";
    } else if (AppDataService.REQUEST.equals(type)) {
      title = "请求数(个/分钟)";
    } else if (AppDataService.DELAY.equals(type)) {
      title = "延时平均值(毫秒/分钟)";
    }
    return title;
  }

  protected MetricReport fetchMetricReport(String idPrefix, ModelPeriod period) {
    MetricReport report = null;

    if (period == ModelPeriod.CURRENT) {
      report = m_currentReports.get(idPrefix);
    } else if (period == ModelPeriod.LAST) {
      report = m_lastReports.get(idPrefix);
    } else {
      throw new RuntimeException("Unknown ModelPeriod: " + period);
    }

    if (report == null) {
      List<String> fields = Splitters.by(";").split(idPrefix);
      String url = fields.get(0);
      String city = fields.get(1);
      String channel = fields.get(2);

      ModelRequest request = new ModelRequest(url, period.getStartTime());
      Map<String, String> pars = new HashMap<String, String>();

      pars.put("metricType", Constants.METRIC_USER_MONITOR);
      pars.put("type", Monitor.TYPE_INFO);
      pars.put("city", city);
      pars.put("channel", channel);
      request.getProperties().putAll(pars);

      report = m_service.invoke(request);

      if (period == ModelPeriod.CURRENT) {
        m_currentReports.put(idPrefix, report);
      } else if (period == ModelPeriod.LAST) {
        m_lastReports.put(idPrefix, report);
      }
    }

    return report;
  }

  private List<Rule> queryRuelsForUrl(String url) {
    List<Rule> rules = new ArrayList<Rule>();

    for (Entry<String, Rule> rule : m_ruleConfigManager.getMonitorRules().getRules().entrySet()) {
      String id = rule.getKey();
      String regexText = id.split(";")[0];

      if (validateRegex(url, regexText)) {
        rules.add(rule.getValue());
      }
    }
    return rules;
  }

  public boolean validateRegex(String regexText, String text) {
    Pattern p = Pattern.compile(regexText);
    Matcher m = p.matcher(text);

    if (m.find()) {
      return true;
    } else {
      return false;
    }
  }

  private List<AlertResultEntity> computeAlertForCondition(Map<String, double[]> datas, Condition condition,
        String type) {
    List<AlertResultEntity> results = new LinkedList<AlertResultEntity>();
    double[] data = datas.get(type);

    if (data != null) {
      results.addAll(m_dataChecker.checkData(data, condition));
    }
    return results;
  }

  private List<AlertResultEntity> computeAlertForRule(String idPrefix, String type, List<Config> configs, String url,
        int minute) {
    List<AlertResultEntity> results = new ArrayList<AlertResultEntity>();
    Pair<Integer, List<Condition>> resultPair = queryCheckMinuteAndConditions(configs);
    int maxMinute = resultPair.getKey();
    List<Condition> conditions = resultPair.getValue();

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

      if (report != null) {
        int start = minute + 1 - maxMinute;
        int end = minute;
        Map<String, double[]> datas = fetchMetricInfoData(start, end, report);

        for (Condition condition : conditions) {
          results.addAll(computeAlertForCondition(datas, condition, type));
        }
      }
    } else if (minute < 0) {
      MetricReport report = fetchMetricReport(idPrefix, ModelPeriod.LAST);

      if (report != null) {
        int start = 60 + minute + 1 - (maxMinute);
        int end = 60 + minute;
        Map<String, double[]> datas = fetchMetricInfoData(start, end, report);

        for (Condition condition : conditions) {
          results.addAll(computeAlertForCondition(datas, condition, type));
        }
      }
    } else {
      MetricReport currentReport = fetchMetricReport(idPrefix, ModelPeriod.CURRENT);
      MetricReport lastReport = fetchMetricReport(idPrefix, ModelPeriod.LAST);

      if (currentReport != null && lastReport != null) {
        int currentStart = 0, currentEnd = minute;
        Map<String, double[]> currentValue = fetchMetricInfoData(currentStart, currentEnd, currentReport);

        int lastStart = 60 + 1 - (maxMinute - minute);
        int lastEnd = 59;
        Map<String, double[]> lastValue = fetchMetricInfoData(lastStart, lastEnd, currentReport);
        Map<String, double[]> datas = new LinkedHashMap<String, double[]>();

        for (Entry<String, double[]> entry : currentValue.entrySet()) {
          String key = entry.getKey();
          double[] current = currentValue.get(key);
          double[] last = lastValue.get(key);

          if (current != null && last != null) {
            datas.put(key, mergerArray(last, current));
          }
        }
        for (Condition condition : conditions) {
          results.addAll(computeAlertForCondition(datas, condition, type));
        }
      }
    }
    return results;
  }

  private Map<String, double[]> fetchMetricInfoData(int start, int end, MetricReport report) {
    Map<String, double[]> datas = new LinkedHashMap<String, double[]>();
    Map<String, double[]> results = new LinkedHashMap<String, double[]>();
    double[] count = new double[60];
    double[] avg = new double[60];
    double[] error = new double[60];
    double[] successPercent = new double[60];

    datas.put("request", count);
    datas.put("delay", avg);
    datas.put("success", successPercent);

    Map<String, MetricItem> items = report.getMetricItems();

    for (Entry<String, MetricItem> item : items.entrySet()) {
      String key = item.getKey();
      Map<Integer, Segment> segments = item.getValue().getSegments();

      for (Segment segment : segments.values()) {
        int id = segment.getId();

        if (key.endsWith(Monitor.HIT)) {
          count[id] = segment.getCount();
        } else if (key.endsWith(Monitor.ERROR)) {
          error[id] = segment.getCount();
        } else if (key.endsWith(Monitor.AVG)) {
          avg[id] = segment.getAvg();
        }
      }
    }

    for (int i = 0; i < 60; i++) {
      double sum = count[i] + error[i];

      if (sum > 0) {
        successPercent[i] = count[i] / sum * 100.0;
      } else {
        successPercent[i] = 100;
      }
    }

    for (Entry<String, double[]> entry : datas.entrySet()) {
      String key = entry.getKey();
      double[] data = entry.getValue();
      int length = end - start + 1;
      double[] result = new double[length];

      System.arraycopy(data, start, result, 0, length);
      results.put(key, result);
    }
    return results;
  }

  @Override
  public String getName() {
    return AlertType.Web.getName();
  }

  @Override
  public void shutdown() {
  }

}
TOP

Related Classes of com.dianping.cat.report.task.alert.web.WebAlert

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.