Package my.home.agent

Source Code of my.home.agent.TraceAllAgent

package my.home.agent;


import java.util.logging.Logger;

import my.home.agent.ctx.CommandProcessor;
import my.home.agent.ctx.ExecutionContext;
import my.home.agent.ctx.TraceSnapshot;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;

/**
* Advice all methods of the intercepted application. This method is called by
* AspectJ Load Time Weaver. See aop.xml in META-INF. This class defines what
* methods and classes to trace, the maximum scope. The tracing scope can be
* externally restricted in aop.xml.
* <p>
* AspectJ JVM agent initialise {@link TraceAllAgent} before any code from
* intercepted application is called, that is very early on.
* <p>
* This class in turn serves as a bootstrap class for trace agent - an
* application on its own; as bootstrap object for {@link ExecutionContext}, the
* whole agent, socket server start and other stuff.
* <p>
* This implementation of trace agent is based on Socket Server Listener. It
* listens on certain port, 4444 is default. It listens for commands like
* "start", "stop", "print". See {@link CommandProcessor} for full list. This
* enables to record method calls only in specific time, only for a specific
* functionality.
* <p>
* The application is suspended by default on the first traced method, on the
* first cross cut. This is important for tracing even very short lived
* application. User needs to issue "resume" command to start intercepted
* application. Tracing is also switched off by default. User has to issue
* "start" command.
* <p>
* Command can be issued by any socket send/receive capable application. On UNIX
* you can use basic shell command "echo" available in every distribution.
* Example: <code>echo "start" > /dev/tcp/127.0.0.1/4444</code>.
* <p>
* This trace agent can be used to trace any JVM based application, not just
* Java, but also Groovy or Scala.
*
* @author Jan Uhlir
*/
@Aspect
public class TraceAllAgent implements TraceSnapshotProvider {

  private final TraceSnapshot traceSnapshot;

  private final ExecutionContext ctx;
 
  private final Logger logger = Logger.getLogger("TraceAgent");

  /**
   * Main constructor. Called by AspectJ LTW just in time, before any cross
   * cut is reached. Bootstrap whole trace agent execution environment - the
   * {@link ExecutionContext}.
   */
  public TraceAllAgent() {
    ctx = ExecutionContext.BOOTSTRAP.get(this);
    traceSnapshot = new TraceSnapshot(ctx.getTraceWriter());
  }

  /**
   * Define AOP point cut. Intercept all public methods on all classes,
   * including library ones. Define only one essential exception, to avoid
   * circular reference to itself, exclude whole 'my.home.agent' package
   */
  @Pointcut("execution(public * *(..)) && !within(my.home.agent..*)")
  public void anyMethod() {}

  /**
   * Define AOP point cut. Intercept all public methods on all classes,
   * including library ones. Define only one essential exception, to avoid
   * circular reference to itself, exclude whole 'my.home.agent' package
   */
  @Pointcut("execution(public * *.main(..)) && !within(my.home.agent..*)")
  public void mainMethod() {}

  @Before("anyMethod()")
  public void beforeTraceMethods(JoinPoint joinPoint) {
    ctx.waitIfAppExecutionSuspended();
    if (ctx.isTracingActive()) {
      String className = joinPoint.getStaticPart().getSignature().getDeclaringTypeName();
      String methodName = joinPoint.getStaticPart().getSignature().getName();
      traceSnapshot.addClass(className);
      traceSnapshot.addClassAndMethod(className + "#" + methodName + "(..)");
    }
  }

  @After("mainMethod()")
  public void afterMainMethod(JoinPoint joinPoint) {
    // Register actions needed to be done when application ends.
    // For multi-threaded applications it cannot be done in after main() advice,
    // since threads can outlive then main() method.
    Runtime.getRuntime().addShutdownHook(new Thread() {
      @Override
      public void run() {
        logger.fine(">>> application ends");
        ctx.waitIfAppExecutionSuspended();
        // kill socket listener
        ctx.stop();
        logger.fine(">>> application ended");
      }
    });
  }

  /**
   * {@inheritDoc}
   */
  @Override
  public void flush() {
    traceSnapshot.flush();
  }
}
TOP

Related Classes of my.home.agent.TraceAllAgent

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.