package foodtruck.monitoring;

import com.google.inject.Inject;

import org.aopalliance.intercept.MethodInterceptor;
import org.aopalliance.intercept.MethodInvocation;

import foodtruck.dao.SystemStatDAO;
import foodtruck.model.SystemStats;
import foodtruck.util.Clock;

/**
 * @author aviolette@gmail.com
 * @since 7/5/12
 */
public class MonitorInterceptor implements MethodInterceptor {
  private SystemStatDAO systemStatDAO;
  private Clock clock;

  @Inject
  public MonitorInterceptor() {
  }

  @Inject
  public void initialize(SystemStatDAO dao, Clock clock) {
    this.systemStatDAO = dao;
    this.clock = clock;
  }

  @Override public Object invoke(MethodInvocation invocation) throws Throwable {
    String methodName = invocation.getMethod().getName();
    String className = invocation.getMethod().getDeclaringClass().getName();
    // TODO: This is not thread-safe!
    SystemStats stats = systemStatDAO.findByTimestamp(clock.now());
    String prefix = className + "_" + methodName;
    stats.incrementCount(prefix + "_total");
    try {
      return invocation.proceed();
    } catch (Exception e) {
      stats.incrementCount(prefix + "_failed");
      throw e;
    } finally {
      systemStatDAO.save(stats);
    }
  }
}

@@ -160,16 +160,47 @@
 ocation;
+%0Aimport org.joda.time.DateTime;
 %0A%0Aimport
@@ -910,76 +910,8 @@
 fe!%0A
-    SystemStats stats = systemStatDAO.findByTimestamp(clock.now());%0A
     
@@ -964,46 +964,33 @@
     
-stats.incrementCount(prefix + %22_total%22
+DateTime now = clock.now(
 );%0A 
@@ -1071,80 +1071,284 @@
     
-stats.incrementCount(prefix + %22_failed%22);%0A      throw e;%0A    %7D finally %7B
+SystemStats stats = systemStatDAO.findByTimestamp(now);%0A      stats.incrementCount(prefix + %22_failed%22);%0A      systemStatDAO.save(stats);%0A      throw e;%0A    %7D finally %7B%0A      SystemStats stats = systemStatDAO.findByTimestamp(now);%0A      stats.incrementCount(prefix + %22_total%22);
 %0A   

Make stats reading and writing somewhat atomic.