Package com.dianping.cat.report.task.product

Source Code of com.dianping.cat.report.task.product.ProjectUpdateTask

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

import java.io.InputStream;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;

import org.codehaus.plexus.logging.LogEnabled;
import org.codehaus.plexus.logging.Logger;
import org.unidal.helper.Files;
import org.unidal.helper.Threads.Task;
import org.unidal.helper.Urls;
import org.unidal.lookup.annotation.Inject;
import org.unidal.webres.json.JsonArray;
import org.unidal.webres.json.JsonObject;

import com.dianping.cat.Cat;
import com.dianping.cat.consumer.transaction.TransactionAnalyzer;
import com.dianping.cat.consumer.transaction.model.entity.TransactionReport;
import com.dianping.cat.core.dal.Hostinfo;
import com.dianping.cat.core.dal.Project;
import com.dianping.cat.helper.TimeHelper;
import com.dianping.cat.message.Transaction;
import com.dianping.cat.report.service.ReportService;
import com.dianping.cat.service.HostinfoService;
import com.dianping.cat.service.ProjectService;
import com.site.lookup.util.StringUtils;

public class ProjectUpdateTask implements Task, LogEnabled {

  @Inject
  private HostinfoService m_hostInfoService;

  @Inject
  private ProjectService m_projectService;

  @Inject(type = ReportService.class, value = TransactionAnalyzer.ID)
  private ReportService<TransactionReport> m_reportService;

  private Logger m_logger;

  private static final long DURATION = 60 * 60 * 1000L;

  private static final String CMDB_DOMAIN_URL = "http://api.cmdb.dp/api/v0.1/projects/s?private_ip=%s";

  private static final String CMDB_INFO_URL = "http://api.cmdb.dp/api/v0.1/projects/%s";

  private static final String CMDB_BU_URL = "http://api.cmdb.dp/api/v0.1/projects/%s/bu";

  private static final String CMDB_PRODUCT_URL = "http://api.cmdb.dp/api/v0.1/projects/%s/product";

  private static final String CMDB_HOSTNAME_URL = "http://api.cmdb.dp/api/v0.1/ci/s?q=_type:(vserver;server),private_ip:%s&fl=hostname";

  private boolean checkIfNullOrEqual(String source, int target) {
    if (source == null || source.equals("null")) {
      return true;
    } else {
      return Integer.parseInt(source) == target;
    }
  }

  private boolean checkIfNullOrEqual(String source, String target) {
    if (source == null || source.equals("null")) {
      return true;
    } else {
      return source.equals(target);
    }
  }

  private boolean checkIfValid(String source) {
    if (source == null || "".equals(source) || "null".equals(source)) {
      return false;
    }
    return true;
  }

  @Override
  public void enableLogging(Logger logger) {
    m_logger = logger;
  }

  private String extractStringFromJsonElement(String str) {
    if (str != null && str.startsWith("[\"")) {
      return str.replace("[\"", "").replace("\"]", "");
    } else {
      return str;
    }
  }

  @Override
  public String getName() {
    return "product_update_task";
  }

  private String mergeAndBuildUniqueString(String baseStr, String appendStr) {
    if (StringUtils.isEmpty(appendStr)) {
      return baseStr;
    }

    StringBuilder builder = new StringBuilder(256);
    builder.append(baseStr);

    for (String str : appendStr.split(",")) {
      String tmpStr = extractStringFromJsonElement(str);

      if (builder.indexOf(tmpStr) < 0) {
        builder.append(",");
        builder.append(tmpStr);
      }
    }

    return builder.toString();
  }

  public String parseDomain(String content) throws Exception {
    JsonObject object = new JsonObject(content);
    JsonArray projectArray = object.getJSONArray("projects");

    if (projectArray.length() > 0) {
      JsonObject firstProject = projectArray.getJSONObject(0);
      return firstProject.get("project_name").toString();
    }
    return null;
  }

  public String parseHostname(String content) throws Exception {
    JsonObject object = new JsonObject(content);
    JsonArray resultArray = object.getJSONArray("result");

    if (resultArray.length() > 0) {
      JsonObject firstResult = resultArray.getJSONObject(0);
      return firstResult.get("hostname").toString();
    }
    return null;
  }

  private Map<String, String> parseInfos(String content) throws Exception {
    Map<String, String> infosMap = new HashMap<String, String>();
    JsonObject project = new JsonObject(content).getJSONObject("project");

    if (project == null) {
      return infosMap;
    }

    Object owner = project.get("rd_duty");
    Object email = project.get("project_email");
    Object phone = project.get("rd_mobile");
    Object level = project.get("project_level");

    if (email != null) {
      infosMap.put("owner", owner.toString());
    } else {
      infosMap.put("owner", null);
    }

    if (email != null) {
      infosMap.put("email", email.toString());
    } else {
      infosMap.put("email", null);
    }

    if (phone != null) {
      infosMap.put("phone", phone.toString());
    } else {
      infosMap.put("phone", null);
    }

    if (level != null) {
      infosMap.put("level", level.toString());
    } else {
      infosMap.put("level", null);
    }
    return infosMap;
  }

  private String parseInfo(String content, String jsonName, String attrName) throws Exception {
    JsonObject json = new JsonObject(content).getJSONObject(jsonName);

    if (json != null) {
      Object obj = json.get(attrName);

      if (obj != null) {
        return obj.toString();
      }
    }
    return null;
  }

  private String queryCmdbName(List<String> ips) {
    if (ips != null) {
      Map<String, Integer> nameCountMap = new HashMap<String, Integer>();

      for (String ip : ips) {
        String cmdbDomain = queryDomainFromCMDB(ip);

        if (checkIfValid(cmdbDomain)) {
          Integer count = nameCountMap.get(cmdbDomain);
          if (count == null) {
            nameCountMap.put(cmdbDomain, 1);
          } else {
            nameCountMap.put(cmdbDomain, count + 1);
          }
        }
      }

      String probableDomain = null;
      int maxCount = 0;
      for (Entry<String, Integer> entry : nameCountMap.entrySet()) {
        int currentCount = entry.getValue();

        if (currentCount > maxCount) {
          maxCount = currentCount;
          probableDomain = entry.getKey();
        }
      }

      return probableDomain;
    } else {
      return null;
    }
  }

  private String queryDomainFromCMDB(String ip) {
    Transaction t = Cat.newTransaction("CMDB", "queryDomain");

    try {
      String cmdb = String.format(CMDB_DOMAIN_URL, ip);
      InputStream in = Urls.forIO().readTimeout(1000).connectTimeout(1000).openStream(cmdb);
      String content = Files.forIO().readFrom(in, "utf-8");

      t.setStatus(Transaction.SUCCESS);
      t.addData(content);
      return parseDomain(content.trim());
    } catch (Exception e) {
      Cat.logError(e);
      t.setStatus(e);
    } finally {
      t.complete();
    }
    return null;
  }

  private String queryHostnameFromCMDB(String ip) {
    Transaction t = Cat.newTransaction("CMDB", "queryHostname");
    try {
      String cmdb = String.format(CMDB_HOSTNAME_URL, ip);
      InputStream in = Urls.forIO().readTimeout(1000).connectTimeout(1000).openStream(cmdb);
      String content = Files.forIO().readFrom(in, "utf-8");

      t.setStatus(Transaction.SUCCESS);
      t.addData(content);
      return parseHostname(content.trim());
    } catch (Exception e) {
      t.setStatus(e);
    } finally {
      t.complete();
    }
    return null;
  }

  private List<String> queryIpsFromReport(String domain) {
    Date startDate = TimeHelper.getCurrentDay(-2);
    Date endDate = TimeHelper.getCurrentDay();
    TransactionReport report = m_reportService.queryDailyReport(domain, startDate, endDate);
    Set<String> ipSet = report.getMachines().keySet();
    List<String> ipList = new ArrayList<String>();
    ipList.addAll(ipSet);

    return ipList;
  }

  private Map<String, String> queryProjectInfoFromCMDB(String cmdbDomain) {
    Transaction t = Cat.newTransaction("CMDB", "queryProjectInfo");
    try {
      String cmdb = String.format(CMDB_INFO_URL, cmdbDomain);
      InputStream in = Urls.forIO().readTimeout(1000).connectTimeout(1000).openStream(cmdb);
      String content = Files.forIO().readFrom(in, "utf-8");

      t.setStatus(Transaction.SUCCESS);
      t.addData(content);
      return parseInfos(content.trim());
    } catch (Exception e) {
      t.setStatus(e);
    } finally {
      t.complete();
    }
    return new HashMap<String, String>();
  }

  private String queryProjectInfoFromCMDB(String url, String jsonName, String attrName) {
    Transaction t = Cat.newTransaction("CMDB", "queryProjectInfo");
    try {
      InputStream in = Urls.forIO().readTimeout(1000).connectTimeout(1000).openStream(url);
      String content = Files.forIO().readFrom(in, "utf-8");

      t.setStatus(Transaction.SUCCESS);
      t.addData(content);
      return parseInfo(content, jsonName, attrName);
    } catch (Exception e) {
      t.setStatus(e);
    } finally {
      t.complete();
    }
    return null;
  }

  @Override
  public void run() {
    boolean active = true;

    while (active) {
      long startMill = System.currentTimeMillis();
      int hour = Calendar.getInstance().get(Calendar.HOUR);
      String hourStr = String.valueOf(hour);

      if (hour < 10) {
        hourStr = "0" + hourStr;
      }

      Transaction t1 = Cat.newTransaction("UpdateHostname", "H" + hourStr);
      try {
        updateHostNameInfo();
        t1.setStatus(Transaction.SUCCESS);
      } catch (Exception e) {
        t1.setStatus(e);
      } finally {
        t1.complete();
      }

      Transaction t2 = Cat.newTransaction("UpdateProjectInfo", "H" + hourStr);
      try {
        updateProjectInfo();
        t2.setStatus(Transaction.SUCCESS);
      } catch (Exception e) {
        t1.setStatus(e);
      } finally {
        t2.complete();
      }

      try {
        long executeMills = System.currentTimeMillis() - startMill;

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

  @Override
  public void shutdown() {
  }

  private void updateHostNameInfo() {
    try {
      List<Hostinfo> infos = m_hostInfoService.findAll();

      for (Hostinfo info : infos) {
        try {
          String hostname = info.getHostname();
          String ip = info.getIp();
          String cmdbHostname = queryHostnameFromCMDB(ip);

          if (StringUtils.isEmpty(cmdbHostname)) {
            continue;
          }

          if (StringUtils.isEmpty(hostname) || !hostname.equals(cmdbHostname)) {
            info.setHostname(cmdbHostname);
            m_hostInfoService.updateHostinfo(info);
          } else {
            m_logger.error("can't find hostname for ip: " + ip);
          }
        } catch (Exception e) {
          Cat.logError(e);
        }
      }
    } catch (Throwable e) {
      Cat.logError(e);
    }
  }

  private boolean updateProject(Project pro) {
    String cmdbDomain = pro.getCmdbDomain();
    Map<String, String> infosMap = queryProjectInfoFromCMDB(cmdbDomain);
    String cmdbOwner = infosMap.get("owner");
    String cmdbEmail = infosMap.get("email");
    String cmdbPhone = infosMap.get("phone");
    String cmdbLevel = infosMap.get("level");
    String dbOwner = pro.getOwner();
    String dbEmail = pro.getEmail();
    String dbPhone = pro.getPhone();
    int dbLevel = pro.getLevel();
    boolean isProjChanged = false;

    if (!checkIfNullOrEqual(cmdbOwner, dbOwner)) {
      pro.setOwner(mergeAndBuildUniqueString(cmdbOwner, dbOwner));
      isProjChanged = true;
    }
    if (!checkIfNullOrEqual(cmdbEmail, dbEmail)) {
      pro.setEmail(mergeAndBuildUniqueString(cmdbEmail, dbEmail));
      isProjChanged = true;
    }
    if (!checkIfNullOrEqual(cmdbPhone, dbPhone)) {
      pro.setPhone(mergeAndBuildUniqueString(cmdbPhone, dbPhone));
      isProjChanged = true;
    }
    if (!checkIfNullOrEqual(cmdbLevel, dbLevel)) {
      pro.setLevel(Integer.parseInt(cmdbLevel));
      isProjChanged = true;
    }

    String buUrl = String.format(CMDB_BU_URL, cmdbDomain);
    String productlineUrl = String.format(CMDB_PRODUCT_URL, cmdbDomain);
    String cmdbBu = queryProjectInfoFromCMDB(buUrl, "bu", "bu_name");
    String cmdbProductline = queryProjectInfoFromCMDB(productlineUrl, "product", "product_name");
    String dbBu = pro.getBu();
    String dbProductline = pro.getCmdbProductline();

    if (!checkIfNullOrEqual(cmdbBu, dbBu)) {
      pro.setBu(cmdbBu);
      isProjChanged = true;
    }

    if (!checkIfNullOrEqual(cmdbProductline, dbProductline)) {
      pro.setCmdbProductline(cmdbProductline);
      isProjChanged = true;
    }

    return isProjChanged;
  }

  private void updateProjectInfo() {
    try {
      List<Project> projects = m_projectService.findAll();

      for (Project pro : projects) {
        try {
          List<String> ips = queryIpsFromReport(pro.getDomain());
          String originCmdbDomain = pro.getCmdbDomain();
          String cmdbDomain = queryCmdbName(ips);

          if (cmdbDomain != null) {
            boolean isChange = !cmdbDomain.equals(originCmdbDomain);

            pro.setCmdbDomain(cmdbDomain);
            boolean isProjectInfoChange = updateProject(pro);

            if (isProjectInfoChange || isChange) {
              m_projectService.updateProject(pro);
            }
          }
        } catch (Exception e) {
          Cat.logError(e);
        }
      }
    } catch (Throwable e) {
      Cat.logError(e);
    }
  }

}
TOP

Related Classes of com.dianping.cat.report.task.product.ProjectUpdateTask

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.