Package com.dianping.cat.consumer.transaction

Source Code of com.dianping.cat.consumer.transaction.TransactionAnalyzer

package com.dianping.cat.consumer.transaction;

import java.util.ConcurrentModificationException;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.codehaus.plexus.logging.LogEnabled;
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.Constants;
import com.dianping.cat.ServerConfigManager;
import com.dianping.cat.analysis.AbstractMessageAnalyzer;
import com.dianping.cat.consumer.transaction.model.entity.Duration;
import com.dianping.cat.consumer.transaction.model.entity.Range;
import com.dianping.cat.consumer.transaction.model.entity.Range2;
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.message.Event;
import com.dianping.cat.message.Message;
import com.dianping.cat.message.Transaction;
import com.dianping.cat.message.spi.MessageTree;
import com.dianping.cat.service.DefaultReportManager.StoragePolicy;
import com.dianping.cat.service.ReportManager;

public class TransactionAnalyzer extends AbstractMessageAnalyzer<TransactionReport> implements LogEnabled {
  private TransactionStatisticsComputer m_computer = new TransactionStatisticsComputer();

  @Inject
  private TransactionDelegate m_delegate;

  @Inject(ID)
  private ReportManager<TransactionReport> m_reportManager;

  @Inject
  private ServerConfigManager m_serverConfigManager;

  public static final String ID = "transaction";

  private Pair<Boolean, Long> checkForTruncatedMessage(MessageTree tree, Transaction t) {
    Pair<Boolean, Long> pair = new Pair<Boolean, Long>(true, t.getDurationInMicros());
    List<Message> children = t.getChildren();
    int size = children.size();

    if (tree.getMessage() == t && size > 0) { // root transaction with children
      Message last = children.get(size - 1);

      if (last instanceof Event) {
        String type = last.getType();
        String name = last.getName();

        if (type.equals("RemoteCall") && name.equals("Next")) {
          pair.setKey(false);
        } else if (type.equals("TruncatedTransaction") && name.equals("TotalDuration")) {
          try {
            long delta = Long.parseLong(last.getData().toString());

            pair.setValue(delta);
          } catch (Exception e) {
            Cat.logError(e);
          }
        }
      }
    }

    return pair;
  }

  private double computeDuration(double duration) {
    if (duration < 20) {
      return duration;
    } else if (duration < 200) {
      return duration - duration % 5;
    } else if (duration < 2000) {
      return duration - duration % 50;
    } else {
      return duration - duration % 500;
    }
  }

  @Override
  public void doCheckpoint(boolean atEnd) {
    if (atEnd && !isLocalMode()) {
      m_reportManager.storeHourlyReports(getStartTime(), StoragePolicy.FILE_AND_DB);
    } else {
      m_reportManager.storeHourlyReports(getStartTime(), StoragePolicy.FILE);
    }
  }

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

  public Set<String> getDomains() {
    return m_reportManager.getDomains(getStartTime());
  }

  public TransactionReport getRawReport(String domain) {
    TransactionReport report = m_reportManager.getHourlyReport(getStartTime(), domain, false);

    return report;
  }

  @Override
  public TransactionReport getReport(String domain) {
    if (!Constants.ALL.equals(domain)) {
      try {
        return queryReport(domain);
      } catch (Exception e) {
        try {
          return queryReport(domain);
          // for concurrent modify exception
        } catch (ConcurrentModificationException ce) {
          Cat.logEvent("ConcurrentModificationException", domain, Event.SUCCESS, null);
          return new TransactionReport(domain);
        }
      }
    } else {
      Map<String, TransactionReport> reports = m_reportManager.getHourlyReports(getStartTime());

      return m_delegate.createAggregatedReport(reports);
    }
  }

  @Override
  protected void loadReports() {
    m_reportManager.loadHourlyReports(getStartTime(), StoragePolicy.FILE);
  }

  @Override
  public void process(MessageTree tree) {
    String domain = tree.getDomain();
    TransactionReport report = m_reportManager.getHourlyReport(getStartTime(), domain, true);
    Message message = tree.getMessage();

    report.addIp(tree.getIpAddress());

    if (message instanceof Transaction) {
      Transaction root = (Transaction) message;

      processTransaction(report, tree, root);
    }
  }

  private void processNameGraph(Transaction t, TransactionName name, int min, double d) {
    int dk = 1;

    while (dk < d) {
      dk <<= 1;
    }

    Duration duration = name.findOrCreateDuration(dk);
    Range range = name.findOrCreateRange(min);

    duration.incCount();
    range.incCount();

    if (!t.isSuccess()) {
      range.incFails();
    }

    range.setSum(range.getSum() + d);
  }

  protected void processTransaction(TransactionReport report, MessageTree tree, Transaction t) {
    if (m_serverConfigManager.discardTransaction(t)) {
      return;
    } else if ("ABTest".equals(t.getType())) {
      return;
    } else {
      Pair<Boolean, Long> pair = checkForTruncatedMessage(tree, t);

      if (pair.getKey().booleanValue()) {
        String ip = tree.getIpAddress();
        TransactionType type = report.findOrCreateMachine(ip).findOrCreateType(t.getType());
        TransactionName name = type.findOrCreateName(t.getName());
        String messageId = tree.getMessageId();
       
        processTypeAndName(t, type, name, messageId, pair.getValue().doubleValue() / 1000d);
      }

      List<Message> children = t.getChildren();

      for (Message child : children) {
        if (child instanceof Transaction) {
          processTransaction(report, tree, (Transaction) child);
        }
      }
    }
  }

  protected void processTypeAndName(Transaction t, TransactionType type, TransactionName name, String messageId,
        double duration) {
    type.incTotalCount();
    name.incTotalCount();

    if (t.isSuccess()) {
      if (type.getSuccessMessageUrl() == null) {
        type.setSuccessMessageUrl(messageId);
      }

      if (name.getSuccessMessageUrl() == null) {
        name.setSuccessMessageUrl(messageId);
      }
    } else {
      type.incFailCount();
      name.incFailCount();

      if (type.getFailMessageUrl() == null) {
        type.setFailMessageUrl(messageId);
      }

      if (name.getFailMessageUrl() == null) {
        name.setFailMessageUrl(messageId);
      }
    }

    int allDuration = ((int) computeDuration(duration));

    name.setMax(Math.max(name.getMax(), duration));
    name.setMin(Math.min(name.getMin(), duration));
    name.setSum(name.getSum() + duration);
    name.setSum2(name.getSum2() + duration * duration);
    name.findOrCreateAllDuration(allDuration).incCount();

    type.setMax(Math.max(type.getMax(), duration));
    type.setMin(Math.min(type.getMin(), duration));
    type.setSum(type.getSum() + duration);
    type.setSum2(type.getSum2() + duration * duration);
    type.findOrCreateAllDuration(allDuration).incCount();

    long current = t.getTimestamp() / 1000 / 60;
    int min = (int) (current % (60));

    processNameGraph(t, name, min, duration);
    processTypeRange(t, type, min, duration);
  }

  private void processTypeRange(Transaction t, TransactionType type, int min, double d) {
    Range2 range = type.findOrCreateRange2(min);

    if (!t.isSuccess()) {
      range.incFails();
    }

    range.incCount();
    range.setSum(range.getSum() + d);
  }

  private TransactionReport queryReport(String domain) {
    TransactionReport report = m_reportManager.getHourlyReport(getStartTime(), domain, false);

    report.getDomainNames().addAll(m_reportManager.getDomains(getStartTime()));
    report.accept(m_computer);

    return report;
  }
}
TOP

Related Classes of com.dianping.cat.consumer.transaction.TransactionAnalyzer

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.