/**
   * This method is called after every method execution
   *
   * @param staticPart
   * @param result
   */
  @AfterReturning(pointcut = "firstPointcut() && secondPointcut()", returning = "result")
  public void logMethodExit(StaticPart staticPart, Object result) {
    if (!this.isBugEnabled()) {
      return;
    }

    Date endDate = new Date();

    MessageDigest md = null;
    try {
      md = MessageDigest.getInstance("SHA");
    } catch (NoSuchAlgorithmException e) {
      throw new RuntimeException(e);
    }

    String key = new String(md.digest(staticPart.getSignature().toShortString().getBytes()));
    Statistic stat = new Statistic();

    if (allStats.containsKey(key)) {
      stat = allStats.get(key);
    }
    long elapsedTime = getElapsedTime(stat.lastDate, endDate);
    if (stat.min > elapsedTime) {
      stat.min = elapsedTime;
    }
    if (stat.max < elapsedTime) {
      stat.max = elapsedTime;
    }
    stat.callCount++;
    stat.sum += elapsedTime;
    allStats.put(key, stat);

    String className = staticPart.getSignature().getDeclaringType().getCanonicalName();
    String method = staticPart.getSignature().toShortString();
    StringBuffer sb =
        new StringBuffer("OUT: Class: ")
            .append(className)
            .append(" Method: ")
            .append(method)
            .append(" result: [");
    sb.append(result.toString()).append("] finished at [");
    sb.append(formatDate(endDate));
    sb.append("]");
    sb.append("]\n elapsed time: ").append(elapsedTime).append("ms");
    sb.append(" min time: ").append(stat.min).append("ms");
    sb.append(" max time: ").append(stat.max).append("ms");
    sb.append(" avg time: ").append(stat.sum / stat.callCount).append("ms");
    sb.append(" Called ").append(stat.callCount).append(" times");

    LOGGER.debug(sb.toString());
  }
  /**
   * This method is called before every method execution
   *
   * @param joinPoint
   */
  @Before("firstPointcut() && secondPointcut()")
  public void logMethodEntry(JoinPoint joinPoint) {
    // If the bug is disabled, do not log anything
    if (!this.isBugEnabled()) {
      return;
    }

    Date date = new Date();

    MessageDigest md = null;
    try {
      md = MessageDigest.getInstance("SHA");
    } catch (NoSuchAlgorithmException e) {
      throw new RuntimeException(e);
    }
    String key = new String(md.digest(joinPoint.getSignature().toShortString().getBytes()));
    Statistic stat = new Statistic();
    if (allStats.containsKey(key)) {
      stat = allStats.get(key);
    }
    stat.lastDate = date;
    allStats.put(key, stat);

    String className = joinPoint.getSignature().getDeclaringType().getCanonicalName();
    String method = joinPoint.getSignature().toShortString();
    StringBuffer sb =
        new StringBuffer("IN: Class: ")
            .append(className)
            .append(" Method: ")
            .append(method)
            .append(" called with args: [");
    for (Object o : joinPoint.getArgs()) {
      sb.append(o.toString()).append(", ");
    }
    sb.append("] at [");
    sb.append(formatDate(date));
    sb.append("]");

    LOGGER.debug(sb.toString());
  }