Package com.dianping.cat.report.page.transaction

Source Code of com.dianping.cat.report.page.transaction.Handler

package com.dianping.cat.report.page.transaction;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Date;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;

import javax.servlet.ServletException;

import org.unidal.lookup.annotation.Inject;
import org.unidal.lookup.util.StringUtils;
import org.unidal.web.mvc.PageHandler;
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.Constants;
import com.dianping.cat.consumer.transaction.TransactionAnalyzer;
import com.dianping.cat.consumer.transaction.model.entity.Machine;
import com.dianping.cat.consumer.transaction.model.entity.Range;
import com.dianping.cat.consumer.transaction.model.entity.TransactionName;
import com.dianping.cat.consumer.transaction.model.entity.TransactionReport;
import com.dianping.cat.consumer.transaction.model.entity.TransactionType;
import com.dianping.cat.helper.TimeHelper;
import com.dianping.cat.report.ReportPage;
import com.dianping.cat.report.graph.GraphBuilder;
import com.dianping.cat.report.page.JsonBuilder;
import com.dianping.cat.report.page.PayloadNormalizer;
import com.dianping.cat.report.page.PieChart;
import com.dianping.cat.report.page.PieChart.Item;
import com.dianping.cat.report.page.model.spi.ModelService;
import com.dianping.cat.report.page.transaction.DisplayNames.TransactionNameModel;
import com.dianping.cat.report.page.transaction.GraphPayload.AverageTimePayload;
import com.dianping.cat.report.page.transaction.GraphPayload.DurationPayload;
import com.dianping.cat.report.page.transaction.GraphPayload.FailurePayload;
import com.dianping.cat.report.page.transaction.GraphPayload.HitPayload;
import com.dianping.cat.report.service.ReportServiceManager;
import com.dianping.cat.service.ModelRequest;
import com.dianping.cat.service.ModelResponse;
import com.dianping.cat.system.config.DomainGroupConfigManager;

public class Handler implements PageHandler<Context> {

  @Inject
  private GraphBuilder m_builder;

  @Inject
  private HistoryGraphs m_historyGraph;

  @Inject
  private JspViewer m_jspViewer;

  @Inject
  private XmlViewer m_xmlViewer;

  @Inject
  private ReportServiceManager m_reportService;

  @Inject
  private TransactionMergeManager m_mergeManager;

  @Inject
  private PayloadNormalizer m_normalizePayload;

  @Inject
  private DomainGroupConfigManager m_configManager;

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

  private void buildTransactionMetaInfo(Model model, Payload payload, TransactionReport report) {
    String type = payload.getType();
    String sorted = payload.getSortBy();
    String queryName = payload.getQueryName();
    String ip = payload.getIpAddress();

    if (!StringUtils.isEmpty(type)) {
      DisplayNames displayNames = new DisplayNames();

      model.setDisplayNameReport(displayNames.display(sorted, type, ip, report, queryName));
      buildTransactionNamePieChart(displayNames.getResults(), model);
    } else {
      model.setDisplayTypeReport(new DisplayTypes().display(sorted, ip, report));
    }
  }

  private void buildTransactionNameGraph(Model model, TransactionReport report, String type, String name, String ip) {
    TransactionType t = report.findOrCreateMachine(ip).findOrCreateType(type);
    TransactionName transactionName = t.findOrCreateName(name);
    transformTo60MinuteData(transactionName);

    if (transactionName != null) {
      String graph1 = m_builder.build(new DurationPayload("Duration Distribution", "Duration (ms)", "Count",
            transactionName));
      String graph2 = m_builder.build(new HitPayload("Hits Over Time", "Time (min)", "Count", transactionName));
      String graph3 = m_builder.build(new AverageTimePayload("Average Duration Over Time", "Time (min)",
            "Average Duration (ms)", transactionName));
      String graph4 = m_builder.build(new FailurePayload("Failures Over Time", "Time (min)", "Count",
            transactionName));

      model.setGraph1(graph1);
      model.setGraph2(graph2);
      model.setGraph3(graph3);
      model.setGraph4(graph4);
    }
  }

  private void buildTransactionNamePieChart(List<TransactionNameModel> names, Model model) {
    PieChart chart = new PieChart();
    List<Item> items = new ArrayList<Item>();

    for (int i = 1; i < names.size(); i++) {
      TransactionNameModel name = names.get(i);
      Item item = new Item();
      TransactionName transaction = name.getDetail();
      item.setNumber(transaction.getTotalCount()).setTitle(transaction.getId());
      items.add(item);
    }

    chart.addItems(items);
    model.setPieChart(new JsonBuilder().toJson(chart));
  }

  private void calculateTps(Payload payload, TransactionReport report) {
    try {
      if (payload != null && report != null) {
        boolean isCurrent = payload.getPeriod().isCurrent();
        double seconds;

        if (isCurrent) {
          seconds = (System.currentTimeMillis() - payload.getCurrentDate()) / (double) 1000;
        } else {
          if (report.getEndTime() != null && report.getStartTime() != null) {
            seconds = (report.getEndTime().getTime() - report.getStartTime().getTime()) / (double) 1000;
          } else {
            seconds = 60;
          }
        }
        new TpsStatistics(seconds).visitTransactionReport(report);
      }
    } catch (Exception e) {
      Cat.logError(e);
    }
  }

  private TransactionReport filterReportByGroup(TransactionReport report, String domain, String group) {
    List<String> ips = m_configManager.queryIpByDomainAndGroup(domain, group);
    List<String> removes = new ArrayList<String>();

    for (Machine machine : report.getMachines().values()) {
      String ip = machine.getIp();

      if (!ips.contains(ip)) {
        removes.add(ip);
      }
    }
    for (String ip : removes) {
      report.getMachines().remove(ip);
    }
    return report;
  }

  private TransactionReport getHourlyReport(Payload payload) {
    String domain = payload.getDomain();
    String ipAddress = payload.getIpAddress();
    ModelRequest request = new ModelRequest(domain, payload.getDate()).setProperty("type", payload.getType())
          .setProperty("ip", ipAddress);

    if (m_service.isEligable(request)) {
      ModelResponse<TransactionReport> response = m_service.invoke(request);
      TransactionReport report = response.getModel();

      if (payload.getPeriod().isLast()) {
        Date start = new Date(payload.getDate());
        Date end = new Date(payload.getDate() + TimeHelper.ONE_HOUR);

        if (Constants.ALL.equals(domain)) {
          report = m_reportService.queryTransactionReport(domain, start, end);
        }
        Set<String> domains = m_reportService.queryAllDomainNames(start, end, TransactionAnalyzer.ID);
        Set<String> domainNames = report.getDomainNames();

        domainNames.addAll(domains);
      }
      return report;
    } else {
      throw new RuntimeException("Internal error: no eligable transaction service registered for " + request + "!");
    }
  }

  private TransactionReport getTransactionGraphReport(Model model, Payload payload) {
    String domain = payload.getDomain();
    String ipAddress = payload.getIpAddress();
    String name = payload.getName();
    ModelRequest request = new ModelRequest(domain, payload.getDate()) //
          .setProperty("type", payload.getType()) //
          .setProperty("name", payload.getName())//
          .setProperty("ip", ipAddress);

    if (name == null || name.length() == 0) {
      request.setProperty("name", "*");
      request.setProperty("all", "true");
      name = Constants.ALL;
    }
    ModelResponse<TransactionReport> response = m_service.invoke(request);
    TransactionReport report = response.getModel();
    return report;
  }

  @Override
  @PayloadMeta(Payload.class)
  @InboundActionMeta(name = "t")
  public void handleInbound(Context ctx) throws ServletException, IOException {
    // display only, no action here
  }

  @Override
  @OutboundActionMeta(name = "t")
  public void handleOutbound(Context ctx) throws ServletException, IOException {
    Model model = new Model(ctx);
    Payload payload = ctx.getPayload();

    normalize(model, payload);
    String domain = payload.getDomain();
    Action action = payload.getAction();
    String ipAddress = payload.getIpAddress();
    String group = payload.getGroup();
    String type = payload.getType();
    String name = payload.getName();
    String ip = payload.getIpAddress();

    if (StringUtils.isEmpty(group)) {
      group = m_configManager.queryDefaultGroup(domain);
      payload.setGroup(group);
    }
    model.setGroupIps(m_configManager.queryIpByDomainAndGroup(domain, group));
    model.setGroups(m_configManager.queryDomainGroup(payload.getDomain()));
    switch (action) {
    case HOURLY_REPORT:
      TransactionReport report = getHourlyReport(payload);

      report = m_mergeManager.mergerAllIp(report, ipAddress);
      calculateTps(payload, report);
      if (report != null) {
        model.setReport(report);
        buildTransactionMetaInfo(model, payload, report);
      }
      break;
    case HISTORY_REPORT:
      report = m_reportService.queryTransactionReport(domain, payload.getHistoryStartDate(),
            payload.getHistoryEndDate());
      calculateTps(payload, report);

      if (report != null) {
        model.setReport(report);
        buildTransactionMetaInfo(model, payload, report);
      }
      break;
    case HISTORY_GRAPH:
      m_historyGraph.buildTrendGraph(model, payload);
      break;
    case GRAPHS:
      report = getTransactionGraphReport(model, payload);

      if (name == null || name.length() == 0) {
        name = Constants.ALL;
      }
      report = m_mergeManager.mergerAllName(report, ip, name);
      model.setReport(report);
      buildTransactionNameGraph(model, report, type, name, ip);
      break;
    case HOURLY_GROUP_REPORT:
      report = getHourlyReport(payload);
      report = filterReportByGroup(report, domain, group);
      report = m_mergeManager.mergerAllIp(report, ipAddress);
      calculateTps(payload, report);
      if (report != null) {
        model.setReport(report);

        buildTransactionMetaInfo(model, payload, report);
      }
      break;
    case HISTORY_GROUP_REPORT:
      report = m_reportService.queryTransactionReport(domain, payload.getHistoryStartDate(),
            payload.getHistoryEndDate());

      calculateTps(payload, report);
      report = filterReportByGroup(report, domain, group);
      report = m_mergeManager.mergerAllIp(report, ipAddress);
      if (report != null) {
        model.setReport(report);
        buildTransactionMetaInfo(model, payload, report);
      }
      break;
    case GROUP_GRAPHS:
      report = getTransactionGraphReport(model, payload);
      report = filterReportByGroup(report, domain, group);

      if (name == null || name.length() == 0) {
        name = Constants.ALL;
      }
      report = m_mergeManager.mergerAllName(report, ip, name);
      model.setReport(report);
      buildTransactionNameGraph(model, report, type, name, ip);
      break;
    case HISTORY_GROUP_GRAPH:
      List<String> ips = m_configManager.queryIpByDomainAndGroup(domain, group);

      m_historyGraph.buildGroupTrendGraph(model, payload, ips);
      break;
    }

    if (payload.isXml()) {
      m_xmlViewer.view(ctx, model);
    } else {
      m_jspViewer.view(ctx, model);
    }
  }

  private void normalize(Model model, Payload payload) {
    model.setPage(ReportPage.TRANSACTION);
    m_normalizePayload.normalize(model, payload);

    if (StringUtils.isEmpty(payload.getQueryName())) {
      payload.setQueryName(null);
    }
    if (StringUtils.isEmpty(payload.getType())) {
      payload.setType(null);
    }

    String queryName = payload.getQueryName();
    if (queryName != null) {
      model.setQueryName(queryName);
    }
  }

  private void transformTo60MinuteData(TransactionName transactionName) {
    Map<Integer, Range> rangeMap = transactionName.getRanges();
    Map<Integer, Range> rangeMapCopy = new LinkedHashMap<Integer, Range>();
    Set<Integer> keys = rangeMap.keySet();
    int minute, completeMinute, count, fails;
    double sum, avg;
    boolean tranform = true;

    if (keys.size() <= 12) {
      for (int key : keys) {
        if (key % 5 != 0) {
          tranform = false;
          break;
        }
      }
    } else {
      tranform = false;
    }

    if (tranform) {
      for (Entry<Integer, Range> entry : rangeMap.entrySet()) {
        Range range = entry.getValue();
        Range r = new Range(range.getValue()).setCount(range.getCount()).setSum(range.getSum())
              .setFails(range.getFails()).setAvg(range.getAvg());

        rangeMapCopy.put(entry.getKey(), r);
      }

      for (Entry<Integer, Range> entry : rangeMapCopy.entrySet()) {
        Range range = entry.getValue();
        minute = range.getValue();
        count = range.getCount() / 5;
        fails = range.getFails() / 5;
        sum = range.getSum() / 5;
        avg = range.getAvg();

        for (int i = 0; i < 5; i++) {
          completeMinute = minute + i;

          transactionName.findOrCreateRange(completeMinute).setCount(count).setFails(fails).setSum(sum)
                .setAvg(avg);
        }
      }
    }
  }

  public enum DetailOrder {
    TYPE, NAME, TOTAL_COUNT, FAILURE_COUNT, MIN, MAX, SUM, SUM2
  }

  public enum SummaryOrder {
    TYPE, TOTAL_COUNT, FAILURE_COUNT, MIN, MAX, SUM, SUM2
  }

}
TOP

Related Classes of com.dianping.cat.report.page.transaction.Handler

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.