Throttling works

Throttling works

import net.winstone.core.WinstoneConstant;
import org.slf4j.LoggerFactory;

// Java EE servlet API
import javax.servlet.Servlet;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServlet;

// Used to scope pointcuts
import net.winstone.core.listener.RequestHandlerThread;
import net.winstone.core.ServletConfiguration;
import net.winstone.core.SimpleRequestDispatcher;

// Rate Limiter
import edu.utwente.aop.tools.RateLimiter;
import java.util.concurrent.TimeUnit;

// exceptions from Servlet.service(..)
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletResponse;

// We redirect the call flow to error servlet
import net.winstone.servlet.ErrorServlet;

/**
 * Ensure that the request is allowed by the RateLimiter before continuing..
 */
public aspect RateLimitingAspect  percflow(processRequest()) {
    private enum State { UNINITIALIZED, NOTICKET, TICKET, NOTICKET_AVAILABLE };

    public final int RESPONSE_TIME_MS = 1000;

    /** public because it is implicitly accessed from WebAppConfiguration */
    public State state = State.UNINITIALIZED;

    static org.slf4j.Logger logger = LoggerFactory.getLogger(Servlet.class);
    // Allow 5 requests per limit
    private static RateLimiter limits = new RateLimiter(5, 1, TimeUnit.MINUTES);

    pointcut processRequest(): call(* processRequest(..)) && within(RequestHandlerThread);

    pointcut servletCallService(Servlet servlet, ServletRequest req, ServletResponse resp): call(void Servlet.service(..)) && target(servlet) && args(req, resp);

    pointcut inWinstoneServletConfiguration(): within(ServletConfiguration);

    before(): processRequest() {
        logger.info("Processrequest!");
        state = State.NOTICKET;
    }

    // TODO: Rewrite to around and call service on different type.
    // TODO: Voor cflowbelow
    before(ServletRequest req, ServletResponse resp) throws ServletException, IOException: inWinstoneServletConfiguration() && call(void Servlet.service(..)) && args(req, resp) {
        logger.info(this.toString() + req + resp);

        getTicket();

        if (state != State.TICKET) {
            // Instantiate new 503-UNAVAILABLE
            ((HttpServletResponse) resp).sendError(HttpServletResponse.SC_SERVICE_UNAVAILABLE, "Rate limit reached - Throttled");

            // TODO: Should not continue the regular call on service.
        }
    }

    public void getTicket() {
        switch (state) {
            case TICKET:
                logger.info("Re-using ticket");
                break;
            case NOTICKET:
                logger.info("Trying to acquire ticket for " + this);
                if (limits.acquire(RESPONSE_TIME_MS)) {
                    logger.info("Acquired ticket");
                    state = State.TICKET;
                } else {
                    state = State.NOTICKET_AVAILABLE;
                }
                break;
            case NOTICKET_AVAILABLE:
                logger.info("No tickets available");
                break;
            case UNINITIALIZED: // ensure this does not happen
                throw new IllegalStateException("Should not receive request before init");
        }
    }
}

import edu.utwente.aop.tools.RateLimiter;
import net.winstone.core.ServletConfiguration;
import net.winstone.core.SimpleRequestDispatcher;
import net.winstone.servlet.StaticResourceServlet;
import org.aspectj.lang.Aspects;
import org.aspectj.lang.Aspects14;
import org.slf4j.LoggerFactory;

import javax.servlet.Servlet;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServlet;
import java.util.concurrent.TimeUnit;

import net.winstone.core.listener.RequestHandlerThread;

/**
 * Ensure that the request is allowed by the RateLimiter before continuing..
 */
public aspect RateLimitingAspect  percflow(processRequest()) {
    private enum State { UNINITIALIZED, NOTICKET, TICKET, NOTICKET_AVAILABLE };

    public final int RESPONSE_TIME_MS = 1000;

    private State state = State.UNINITIALIZED;

    static org.slf4j.Logger logger = LoggerFactory.getLogger(Servlet.class);
    // Allow 5 requests per limit
    private static RateLimiter limits = new RateLimiter(5, 1, TimeUnit.MINUTES);

    pointcut processRequest(): call(* processRequest(..)) && within(RequestHandlerThread);

    pointcut servletCallService(Servlet servlet): call(* Servlet.service(..)) && target(servlet);

    pointcut inWinstoneServletConfiguration(): within(ServletConfiguration);

    pointcut rateLimit(Servlet servlet): servletCallService(servlet) && inWinstoneServletConfiguration();

    before(): processRequest() {
        logger.info("Processrequest!");
        state = State.NOTICKET;
    }

     // TODO: Rewrite to around and call service on different type.
    // TODO: Voor cflowbelow
    before(Servlet servlet): rateLimit(servlet) {
        logger.info(this.toString());

        switch (state) {
            case TICKET:
                logger.info("Re-using ticket");
                break;
            case NOTICKET:
                logger.info("Trying to acquire ticket for " + servlet);
                if (limits.acquire(RESPONSE_TIME_MS)) {
                    logger.info("Acquired ticket");
                    state = State.TICKET;
                } else {
                    state = State.NOTICKET_AVAILABLE;
                }
                break;
            case NOTICKET_AVAILABLE:
                logger.info("No tickets available");
                break;
            case UNINITIALIZED: // ensure this does not happen
                throw new IllegalStateException("Should not receive request before init");
        }
    }
}


comments for ImportDealer

comments for ImportDealer

import view.GUI;

public privileged aspect ImportDealer {
    declare precedence : ImportDealer, Import;

    private GUI gui;

    /**
     * catch constructor call, so that we have the correct gui, to refer to everywhere
     */
    after() returning(GUI gui): call(GUI.new(*)) {
        this.gui = gui;
    }

    /** reset the dealer index to the appropriate value after importing */
    after() : execution(* LoadFileListener.actionPerformed(*)) {
        Dealer.dealerIndex = (gui.model.gameDB.size()-1) % 4;
        Dealer.updateShownDealer();
    }
}

import view.GUI;

public privileged aspect ImportDealer {
    declare precedence : ImportDealer, Import;

    private GUI gui;

    /**
     * catch constructor call, so that we have the correct gui, to refer to everywhere
     */
    after() returning(GUI gui): call(GUI.new(*)) {
        this.gui = gui;
    }

    after() : execution(* LoadFileListener.actionPerformed(*)) {
        Dealer.dealerIndex = (gui.model.gameDB.size()-1) % 4;
        Dealer.updateShownDealer();
    }
}


Fix Javadoc formatting in AnnotationBeanConfigurerAspect

/*
 * Copyright 2002-2017 the original author or authors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.springframework.beans.factory.aspectj;

import java.io.Serializable;

import org.aspectj.lang.annotation.control.CodeGenerationHint;

import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.BeanFactoryAware;
import org.springframework.beans.factory.DisposableBean;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.AnnotationBeanWiringInfoResolver;
import org.springframework.beans.factory.annotation.Configurable;
import org.springframework.beans.factory.wiring.BeanConfigurerSupport;

/**
 * Concrete aspect that uses the {@link Configurable} annotation to identify
 * which classes need autowiring.
 *
 * <p>The bean name to look up will be taken from the {@code @Configurable}
 * annotation if specified; otherwise, the default bean name to look up will be
 * the fully qualified name of the class being configured.
 *
 * @author Rod Johnson
 * @author Ramnivas Laddad
 * @author Juergen Hoeller
 * @author Adrian Colyer
 * @since 2.0
 * @see org.springframework.beans.factory.annotation.Configurable
 * @see org.springframework.beans.factory.annotation.AnnotationBeanWiringInfoResolver
 */
public aspect AnnotationBeanConfigurerAspect extends AbstractInterfaceDrivenDependencyInjectionAspect
		implements BeanFactoryAware, InitializingBean, DisposableBean {

	private BeanConfigurerSupport beanConfigurerSupport = new BeanConfigurerSupport();

	public void setBeanFactory(BeanFactory beanFactory) {
		this.beanConfigurerSupport.setBeanWiringInfoResolver(new AnnotationBeanWiringInfoResolver());
		this.beanConfigurerSupport.setBeanFactory(beanFactory);
	}

	public void afterPropertiesSet() {
		this.beanConfigurerSupport.afterPropertiesSet();
	}

	public void configureBean(Object bean) {
		this.beanConfigurerSupport.configureBean(bean);
	}

	public void destroy() {
		this.beanConfigurerSupport.destroy();
	}

	public pointcut inConfigurableBean() : @this(Configurable);

	public pointcut preConstructionConfiguration() : preConstructionConfigurationSupport(*);

	/*
	 * An intermediary to match preConstructionConfiguration signature (that doesn't expose the annotation object)
	 */
	@CodeGenerationHint(ifNameSuffix="bb0")
	private pointcut preConstructionConfigurationSupport(Configurable c) : @this(c) && if (c.preConstruction());

	declare parents: @Configurable * implements ConfigurableObject;

	/*
	 * This declaration shouldn't be needed,
	 * except for an AspectJ bug (https://bugs.eclipse.org/bugs/show_bug.cgi?id=214559)
	 */
	declare parents: @Configurable Serializable+ implements ConfigurableDeserializationSupport;

}

/*
 * Copyright 2002-2014 the original author or authors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.springframework.beans.factory.aspectj;

import java.io.Serializable;

import org.aspectj.lang.annotation.control.CodeGenerationHint;

import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.BeanFactoryAware;
import org.springframework.beans.factory.DisposableBean;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.AnnotationBeanWiringInfoResolver;
import org.springframework.beans.factory.annotation.Configurable;
import org.springframework.beans.factory.wiring.BeanConfigurerSupport;

/**
 * Concrete aspect that uses the {@link Configurable} annotation to identify
 * which classes need autowiring.
 *
 * <p>The bean name to look up will be taken from the {@code @Configurable}
 * annotation if specified, otherwise the default bean name to look up will be
 * the fully qualified name of the class being configured.
 *
 * @author Rod Johnson
 * @author Ramnivas Laddad
 * @author Juergen Hoeller
 * @author Adrian Colyer
 * @since 2.0
 * @see org.springframework.beans.factory.annotation.Configurable
 * @see org.springframework.beans.factory.annotation.AnnotationBeanWiringInfoResolver
 */
public aspect AnnotationBeanConfigurerAspect extends AbstractInterfaceDrivenDependencyInjectionAspect
		implements BeanFactoryAware, InitializingBean, DisposableBean {

	private BeanConfigurerSupport beanConfigurerSupport = new BeanConfigurerSupport();

	public void setBeanFactory(BeanFactory beanFactory) {
		this.beanConfigurerSupport.setBeanWiringInfoResolver(new AnnotationBeanWiringInfoResolver());
		this.beanConfigurerSupport.setBeanFactory(beanFactory);
	}

	public void afterPropertiesSet() {
		this.beanConfigurerSupport.afterPropertiesSet();
	}

	public void configureBean(Object bean) {
		this.beanConfigurerSupport.configureBean(bean);
	}

	public void destroy() {
		this.beanConfigurerSupport.destroy();
	}

	public pointcut inConfigurableBean() : @this(Configurable);

	public pointcut preConstructionConfiguration() : preConstructionConfigurationSupport(*);

	/*
	 * An intermediary to match preConstructionConfiguration signature (that doesn't expose the annotation object)
	 */
	@CodeGenerationHint(ifNameSuffix="bb0")
	private pointcut preConstructionConfigurationSupport(Configurable c) : @this(c) && if (c.preConstruction());

	declare parents: @Configurable * implements ConfigurableObject;

	/*
	 * This declaration shouldn't be needed,
	 * except for an AspectJ bug (https://bugs.eclipse.org/bugs/show_bug.cgi?id=214559)
	 */
	declare parents: @Configurable Serializable+ implements ConfigurableDeserializationSupport;

}


What even is life?

What even is life?

package flow;

/**
 * Created by Chris on 5/3/2015.
 */
public aspect FlowAspect {

    int methodCount = 0;

    public pointcut flow() : cflow(call( * FlowA.methodA() ) ) && !within(FlowAspect);
    public pointcut method() : call(* Flow*.method*());

    before() : flow() {
        //System.out.println( thisJoinPoint );
    }

    before() : method(){
        methodCount++;
    }

    after() returning: call(void FlowC.methodC()){
        System.out.println(methodCount);
    }
}

package flow;

/**
 * Created by Chris on 5/3/2015.
 */
public aspect FlowAspect {

    public pointcut flow() : cflow(call( * FlowA.methodA() ) ) && !within(FlowAspect);

    before() : flow() {
        System.out.println( thisJoinPoint );
    }
}


attempt to change injection of aspects

attempt to change injection of aspects

/**
 * palava - a java-php-bridge
 * Copyright (C) 2007-2010  CosmoCode GmbH
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version 2
 * of the License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
 * MA  02110-1301, USA.
 */

package de.cosmocode.palava.scope;

import org.aspectj.lang.annotation.SuppressAjWarnings;

import com.google.common.base.Preconditions;
import com.google.inject.Inject;

import de.cosmocode.palava.core.aop.AbstractPalavaAspect;

final aspect UnitOfWorkScopeAspect extends AbstractPalavaAspect issingleton() {

    private UnitOfWorkScope scope;

    @Inject
    void setUnitOfWorkScope(UnitOfWorkScope scope) {
        this.scope = Preconditions.checkNotNull(scope, "Scope");
    }

    pointcut unitOfWork(): execution(@UnitOfWork * *.*(..));

    @SuppressAjWarnings("adviceDidNotMatch")
    Object around(): unitOfWork() {
        if (scope.inProgress()) return proceed();
        scope.begin();
        try {
            return proceed();
        } finally {
            scope.end();
        }
    }

}

/**
 * palava - a java-php-bridge
 * Copyright (C) 2007-2010  CosmoCode GmbH
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version 2
 * of the License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
 * MA  02110-1301, USA.
 */

package de.cosmocode.palava.scope;

import org.aspectj.lang.annotation.SuppressAjWarnings;

import com.google.common.base.Preconditions;
import com.google.inject.Inject;

import de.cosmocode.palava.core.aop.AbstractPalavaAspect;

public final aspect UnitOfWorkScopeAspect extends AbstractPalavaAspect issingleton() {

    private UnitOfWorkScope scope;

    @Inject
    void setUnitOfWorkScope(UnitOfWorkScope scope) {
        this.scope = Preconditions.checkNotNull(scope, "Scope");
    }

    pointcut unitOfWork(): execution(@UnitOfWork * *.*(..));

    @SuppressAjWarnings("adviceDidNotMatch")
    Object around(): unitOfWork() {
        if (scope.inProgress()) return proceed();
        scope.begin();
        try {
            return proceed();
        } finally {
            scope.end();
        }
    }

}


Fixed error on reduce phases + other minor fixes

import java.io.*;
import java.util.*;
import java.lang.management.ManagementFactory;
import java.sql.Timestamp;
import java.text.SimpleDateFormat;
import java.net.InetAddress;
import java.lang.ClassLoader;
import org.apache.hadoop.io.DataInputBuffer;
import org.apache.hadoop.mapred.TaskStatus;
import org.apache.hadoop.fs.permission.FsPermission;
import org.apache.hadoop.util.Progressable;
import org.apache.hadoop.hdfs.protocol.DatanodeInfo;
import org.apache.hadoop.util.DataChecksum;
import java.net.Socket;

import org.apache.hadoop.security.token.Token;
import org.apache.hadoop.security.token.TokenIdentifier;
import org.apache.hadoop.hdfs.security.token.block.BlockTokenIdentifier;

import org.apache.hadoop.fs.FSDataInputStream;
import org.apache.hadoop.hdfs.DFSClient;

import org.apache.hadoop.mapred.TaskTrackerStatus;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import org.apache.hadoop.conf.Configuration;

/**
 *
 * @author Alejandro
 */

aspect AlojaAspect {

	private static final Log LOG = LogFactory.getLog(AlojaAspect.class);

	/*
	TYPES
	######################################################################################################################################
	######################################################################################################################################
	*/

    public static class Events {

        public static final int JobTracker = 11111;
        public static final int TaskTracker = 11112;
        public static final int NameNode = 11113;
        public static final int SecondaryNameNode = 11114;
        public static final int DataNode = 11115;
        public static final int Task = 11116;
        public static final int HeartBeat = 11119;
        public static final int MapOutputBuffer = 33333;
        public static final int MapTaskOutputSize = 44444;
    }

    public static class Values {

       	// Generic
		public static final int End = 0;
        public static final int Start = 1;

        // Events.TaskTracker
		public static final int RunMapper = 8;
        public static final int RunReducer = 9;
        public static final int ReducerCopyPhase = 10;
        public static final int ReducerSortPhase = 11;
        public static final int ReducerReducePhase = 12;

		// Events.MapOutputBuffer
        public static final int Flush = 1;
        public static final int SortAndSpill = 2;
        public static final int Sort = 3;
        public static final int CreateSpillIndexFile = 5;
        //public static final int TotalIndexCacheMemory = 6;
        public static final int SpillRecordDumped = 7;
        public static final int Combine = 4;
    }

	/*
	FUNCTIONS
	######################################################################################################################################
	######################################################################################################################################
	*/

	private static long getPID() {
		String name = java.lang.management.ManagementFactory.getRuntimeMXBean().getName();
		return Long.parseLong(name.split("@")[0]);
	}

	private void generateEvent(Integer key, Integer value) {
		//2:cpu:app:task:thread:time:type:value
		try{
			String hostname = InetAddress.getLocalHost().getHostName();
			long pid = getPID();
			//LOG.info(hostname+","+pid+",2:"+hostname+":2:"+pid+":1:"+System.currentTimeMillis()+":"+key+":"+value);
			LOG.info("AOPLOG,"+hostname+","+pid+","+System.currentTimeMillis()+","+key+","+value);
		}
		catch (Exception e) {
			LOG.error(e, e);

		}
	}

	private void generateEvent(Integer key, String value) {
		//2:cpu:app:task:thread:time:type:value
		try{
			String hostname = InetAddress.getLocalHost().getHostName();
			long pid = getPID();
			//LOG.info(hostname+","+pid+",2:"+hostname+":2:"+pid+":1:"+System.currentTimeMillis()+":"+key+":"+value);
			LOG.info("AOPLOG,"+hostname+","+pid+","+System.currentTimeMillis()+","+key+","+value);
		}
		catch (Exception e) {
			LOG.error(e, e);

		}
	}

/*	private void writeLog(Integer key, Integer value) {

		try {
			String hostname = InetAddress.getLocalHost().getHostName();
			long pid = getPID();
			BufferedWriter bw = new BufferedWriter(new FileWriter(new File("/tmp/aloja-"+getPID()+".log"),true));
			bw.write("AOPLOG,"+hostname+","+pid+","+System.currentTimeMillis()+","+key+","+value);
			bw.close();
		}
		catch (IOException e) {
			e.printStackTrace();
		}
	}

	private void writeLog(Integer key, String value) {

		try {
			String hostname = InetAddress.getLocalHost().getHostName();
			long pid = getPID();
			BufferedWriter bw = new BufferedWriter(new FileWriter(new File("/tmp/aloja-"+getPID()+".log"),true));
			bw.write("AOPLOG,"+hostname+","+pid+","+System.currentTimeMillis()+","+key+","+value);
			bw.close();
		}
		catch (IOException e) {
			e.printStackTrace();
		}
	}*/

	/*private void generateEVent(Integer key[], Integer value) {

		StringBuffer output = new StringBuffer();

		output.append()

	}*/

	private void instrumentation(String event, String when) {

		instrumentation(event, when, "");

	}
	private void instrumentation(String event, String when, String additional) {
		try {
			//Add hostname
			String log = InetAddress.getLocalHost().getHostName();
			//Add PID
			log += "," + getPID();
			//Specify event
			log += "," + when + "," + event;
			//Specify event
			log += additional;
			//LOG.info(log);
			//writeLog(logFile,log);

		}
		catch (IOException e) {
			e.printStackTrace();
		}
	}

	/*
	POINTCUTS
	######################################################################################################################################
	######################################################################################################################################
	*/

	//RegisterDataNode Pointcut

	pointcut startDataNode(): execution(* org.apache.hadoop.hdfs.server.datanode.DataNode.startDataNode(..));

	//RegisterTaskTracker Pointcut

	pointcut registerTaskTracker(): execution(* org.apache.hadoop.mapred.TaskTracker.initialize(..));

	//RegisterNameNode Pointcut

	pointcut initializeNameNode():  execution(* org.apache.hadoop.hdfs.server.namenode.NameNode.initialize(..));

	//RegisterSecondaryNamenode Pointcut

	pointcut initializeSecondaryNameNode(): execution(* org.apache.hadoop.hdfs.server.namenode.SecondaryNameNode.initialize(..));

	//RegisterTask - CHILD

	//pointcut initializeChild(): call(* org.apache.hadoop.mapred.Child.initMetrics(..)) && withincode(* org.apache.hadoop.mapred.Child.main(..));

	pointcut initializeChild(): execution(* org.apache.hadoop.mapred.Child.main(..));

	//Register JobTracker Pointcut

	pointcut registerJobTracker(): execution(* org.apache.hadoop.mapred.JobTracker.startTracker(..));

	//HEARTBEAT

	pointcut heartbeat(TaskTrackerStatus status,boolean restarted,boolean initialContact,boolean acceptNewTasks,short responseId): execution(* org.apache.hadoop.mapred.JobTracker.heartbeat(..)) && args(status, restarted, initialContact, acceptNewTasks,responseId);

	/*
		###########################################################################
		############################Task###########################################
		###########################################################################
	*/

	pointcut outputSize(): call (* *.getLen(..)) && withincode(* org.apache.hadoop.mapred.Task.calculateOutputSize());

	/*
		###########################################################################
		############################MAPPER#########################################
		###########################################################################
	*/

	//pointcut maptask(): execution(* org.apache.hadoop.mapred.MapTask.run(..));
	pointcut mapper(): call(* org.apache.hadoop.mapred.MapTask.runNewMapper(..)) && withincode(* org.apache.hadoop.mapred.MapTask.run(..));

	//  ############################SORT AND SPILL#################################

	//Start-End
	pointcut taskSortAndSpill(): execution(* org.apache.hadoop.mapred.MapTask.MapOutputBuffer.sortAndSpill());

	pointcut flush(): execution(* org.apache.hadoop.mapred.MapTask.MapOutputBuffer.flush());

	//Spill File Size
	pointcut sortAndSpillSpillFile(int numSpills, long size) : call (* *.getSpillFileForWrite(..)) && withincode(* org.apache.hadoop.mapred.MapTask.MapOutputBuffer.sortAndSpill()) && args(numSpills, size);

	//SpillIndex File Size
	pointcut sortAndSpillSpillIndexFile(int numSpills, long partitions) : call (* *.getSpillIndexFileForWrite(..)) && withincode(* org.apache.hadoop.mapred.MapTask.MapOutputBuffer.sortAndSpill()) && args(numSpills, partitions);

	//Sort
	pointcut sortAndSpillSort(int kvstart, int endPosition, Object reporter): call(* *.sort(..)) && withincode(* org.apache.hadoop.mapred.MapTask.MapOutputBuffer.sortAndSpill()) && args(..,kvstart,endPosition,reporter);

	//Init Writer
	//pointcut sortAndSpillInitWriter() : call (org.apache.hadoop.mapred.IFile.Writer.new(..)) && withincode(* org.apache.hadoop.mapred.MapTask.MapOutputBuffer.sortAndSpill());

	//Close Writer
	//pointcut sortAndSpillCloseWriter() : call (void org.apache.hadoop.mapred.IFile.Writer.close(..)) && withincode(* org.apache.hadoop.mapred.MapTask.MapOutputBuffer.sortAndSpill());

	//Write key-value
	pointcut sortAndSpillWrite(DataInputBuffer key, DataInputBuffer value): call (* *.append(..)) && withincode(* org.apache.hadoop.mapred.MapTask.MapOutputBuffer.sortAndSpill()) && args(key,value);

	//Combiner
	pointcut sortAndSpillCombiner(): call(* *.combine(..)) && withincode(* org.apache.hadoop.mapred.MapTask.MapOutputBuffer.sortAndSpill());

	//Spill Index File
	pointcut sortAndSpillSpillIndexWrite(): call(* *.writeToFile(..)) && withincode(* org.apache.hadoop.mapred.MapTask.MapOutputBuffer.sortAndSpill());

	/*
		###########################################################################
		############################REDUCER########################################
		###########################################################################
	*/

	//REDUCETASK RUN
	pointcut reducer(): execution(* org.apache.hadoop.mapred.ReduceTask.run(..));
	pointcut initCodec(): call(* *.initCodec(..)) && withincode(* org.apache.hadoop.mapred.ReduceTask.run(..));
	pointcut setPhase(TaskStatus.Phase phase): call(* *.setPhase(..)) && withincode(* org.apache.hadoop.mapred.ReduceTask.run(..)) && args(phase);

	//pointcut endCopy(): call(* *.setPhase(..)) && withincode(* org.apache.hadoop.mapred.ReduceTask.run(..));
	//pointcut endSort(): call(* *.getMapOutputKeyClass(..)) && withincode(* org.apache.hadoop.mapred.ReduceTask.run(..));

	/*
		###########################################################################
		############################NETWORK########################################
		###########################################################################
	*/

	pointcut defaultBlockSize(): call(* org.apache.hadoop.hdfs.DFSClient.getDefaultBlockSize());
	//pointcut blockSize(): call(* org.apache.hadoop.hdfs.DFSClient.getBlockSize(..));
	pointcut createDFSFile(String src,FsPermission permission,boolean overwrite,boolean createParent,short replication,long blockSize,Progressable progress, int buffersize): execution (* org.apache.hadoop.hdfs.DFSClient.create(..)) && args(src,permission,overwrite,createParent,replication,blockSize,progress,buffersize);
	pointcut runDataStreamer(): execution (* org.apache.hadoop.hdfs.DFSClient.DFSOutputStream.DataStreamer.run());
	//pointcut readEntireBufferFromDataNode(byte buf[],int off,int len): execution(* org.apache.hadoop.hdfs.DFSClient.DFSInputStream.read(..)) && args(buf[],off,len);
	//pointcut readFromDataNode(): call (* org.apache.hadoop.hdfs.DFSClient.DFSInputStream.blockSeekTo(..)) && withincode(* org.apache.hadoop.hdfs.DFSClient.DFSInputStream.read(..));
	pointcut newBlockReader(Socket sock, String file, long blockId, Token<BlockTokenIdentifier> accessToken, long genStamp, long startOffset, long len, int bufferSize, boolean verifyChecksum, String clientName): execution (* org.apache.hadoop.hdfs.DFSClient.BlockReader.newBlockReader(..)) && args(sock,file,blockId,accessToken,genStamp,startOffset,len,bufferSize,verifyChecksum,clientName);

	/*
	Advices
	######################################################################################################################################
	######################################################################################################################################
	*/

	// RegiterJobTracker

	after() : registerJobTracker(){
		generateEvent(Events.JobTracker, Values.Start);

	}

	//RegisterTaskTracker
	after() : registerTaskTracker(){
		generateEvent(Events.TaskTracker, Values.Start);

	}

	//RegisterNameNode

	after() : initializeNameNode(){
		generateEvent(Events.NameNode, Values.Start);
	}

	//RegisterDataNode

	after() : startDataNode(){
		generateEvent(Events.DataNode, Values.Start);
	}

	//RegisterSecondaryNamenode

	after() : initializeSecondaryNameNode(){
		generateEvent(Events.SecondaryNameNode, Values.Start);
	}

	//HEARTBEAT
	after(TaskTrackerStatus status,boolean restarted,boolean initialContact,boolean acceptNewTasks,short responseId) : heartbeat(status, restarted, initialContact, acceptNewTasks,responseId){
		// SAMPLE trackername: tracker_vagrant-99-01:localhost/127.0.0.1:38149
		generateEvent(Events.HeartBeat, status.getTrackerName().replace(':','-').replace('/','_'));
	}

	/*
		###########################################################################
		############################Task###########################################
		###########################################################################
	*/

	//RegisterTask CHILD
	after() : initializeChild() { //We need the  PID of this task to be registered
		generateEvent(Events.Task, Values.Start);
	}

/*	after() returning(long size) : outputSize() {
		String s = "Task-outputSize";
		instrumentation(s,"after",", size: " + Long.toString(size));
	}

	/*
		###########################################################################
		############################Mapper#########################################
		###########################################################################
	*/

	/*before() : maptask(){
		generateEvent(Events.MapTask, Values.Start);
	}*/

	before() : mapper(){
		generateEvent(Events.TaskTracker, Values.RunMapper);
	}

	after() : mapper(){
		generateEvent(Events.TaskTracker, Values.End);
	}

	//  ############################SORT AND SPILL#################################

	before() : taskSortAndSpill(){
		generateEvent(Events.MapOutputBuffer, Values.SortAndSpill);
	}

	after() : taskSortAndSpill(){
		generateEvent(Events.MapOutputBuffer, Values.End);
	}

	//flush

	before() : flush(){
		generateEvent(Events.MapOutputBuffer, Values.Flush);
	}

	after() : flush(){
		generateEvent(Events.MapOutputBuffer, Values.End);
	}

	// Spill File Size

	after(int numSpills, long size) returning : sortAndSpillSpillFile(numSpills, size){
		String s = "sortAndSpillSpillFile";
		instrumentation(s,"after",", numSpills: " +Integer.toString(numSpills) + ";size: " + Long.toString((size*numSpills) + size));
	}

	// SpillIndex File Size

	after(int numSpills, long partitions) returning : sortAndSpillSpillIndexFile(numSpills, partitions){
		String s = "sortAndSpillSpillIndexFile";
		instrumentation(s,"after","," + Long.toString(numSpills * partitions));
	}

/*
	before(int length) : kvbufferState(length){

		String s = "kvbufferState";
		File logFile = getFile();
		instrumentation(logFile,s,"before");
		writeLog(logFile,Integer.toString(length));
	}

*/

	before(int kvstart, int endPosition, Object reporter) : sortAndSpillSort(kvstart,endPosition,reporter){
		generateEvent(Events.MapOutputBuffer, Values.Sort);
		//instrumentation(s,"before","," + Integer.toString(endPosition - kvstart));
	}
	after(int kvstart, int endPosition, Object reporter) returning : sortAndSpillSort(kvstart,endPosition,reporter){
		generateEvent(Events.MapOutputBuffer, Values.End);
		//instrumentation(s,"after","," + Integer.toString(endPosition - kvstart));
	}

	// Init writer
/*	after() returning : sortAndSpillInitWriter(){
		String s = "sortAndSpillInitWriter";
		instrumentation(s,"after");
	}

	// Close writer
	after() returning : sortAndSpillCloseWriter(){
		String s = "sortAndSpillCloseWriter";
		instrumentation(s,"after");
	}
*/

	after(DataInputBuffer key, DataInputBuffer value) returning : sortAndSpillWrite(key,value){
		generateEvent(Events.MapOutputBuffer, Values.SpillRecordDumped);
	}

	before() : sortAndSpillCombiner(){
		generateEvent(Events.MapOutputBuffer, Values.Combine);
	}

	after() returning : sortAndSpillCombiner(){
		generateEvent(Events.MapOutputBuffer, Values.End);
	}

	before() : sortAndSpillSpillIndexWrite(){
		generateEvent(Events.MapOutputBuffer, Values.CreateSpillIndexFile);
	}

	after() returning : sortAndSpillSpillIndexWrite(){
		generateEvent(Events.MapOutputBuffer, Values.End);
	}

	/*
		###########################################################################
		############################REDUCER########################################
		###########################################################################
	*/

/*	before() : reducer(){
		String s = "Reducer";
		instrumentation(s,"before");
	}
*/

	before() : initCodec() {
		generateEvent(Events.TaskTracker, Values.RunReducer);
	}

	after() returning : initCodec() {
		generateEvent(Events.TaskTracker, Values.ReducerCopyPhase);
	}

	before(TaskStatus.Phase phase) : setPhase(phase) { //END OF A PHASE (SORT OR COPY)
		generateEvent(Events.TaskTracker, Values.End);
		if (phase == TaskStatus.Phase.SORT) {
			generateEvent(Events.TaskTracker, Values.ReducerSortPhase);
		}
		else if (phase == TaskStatus.Phase.REDUCE) {
			generateEvent(Events.TaskTracker, Values.ReducerReducePhase);
		}
	}

	//after(TaskStatus.Phase phase) returning: setPhase(phase) {

	//}

	after() : reducer(){ //END OF REDUCE PHASE
			generateEvent(Events.TaskTracker, Values.End);	}

	/*
		###########################################################################
		############################NETWORK########################################
		###########################################################################
	*/

	after() returning(long blockSize) : defaultBlockSize() {
		String s = "Network-defaultBlockSize";
		instrumentation(s,"after",", size: " + Long.toString(blockSize));
	}
	// after() returning(long blockSize) : blockSize() {
	// 	String s = "Network-blockSize";
	// 	File logFile = getFile();
	// 	instrumentation(logFile,s,"after");
	// 	String log = ", size: " + Long.toString(blockSize);
	// 	writeLog(logFile,log);
	// }

	after(String src,FsPermission permission,boolean overwrite, boolean createParent,short replication,long blockSize,Progressable progress, int buffersize): createDFSFile(src,permission,overwrite,createParent,replication,blockSize,progress,buffersize) {
		String s = "Network-CreateDFSFile";

		//MODIFIED!!!!!!-----!!!!!!!!!!!
		instrumentation(s,"after",", path: " + src + ";permission: " + permission.toString() + ";overwrite: " + String.valueOf(overwrite) + ";createParent: " + String.valueOf(createParent) + ";replication: " + Short.toString(replication) + ";blockSize: " + Long.toString(blockSize) + ";buffersize: " + Integer.toString(buffersize));
	}
	before(): runDataStreamer() {
		String s = "DataStreamer";
		instrumentation(s,"after");
	}

	// before(byte buf[],int off, int len) : readEntireBufferFromDataNode(buf[],off,len){
	// 	String s = "Network-ReadEntireBuffer";
	// 	instrumentation(s,"after",", bufferLength: " + Integer.toString(len));
	// }

	// after() returning(DatanodeInfo datanode) : readFromDataNode(){
	// 	String s = "Network-fromDataNode";
	// 	instrumentation(s,"after", ", from : " + datanode.getHostName());
	// }

	after(Socket sock, String file, long blockId, Token<BlockTokenIdentifier> accessToken, long genStamp, long startOffset, long len, int bufferSize, boolean verifyChecksum, String clientName) : newBlockReader(sock,file,blockId,accessToken,genStamp,startOffset,len,bufferSize,verifyChecksum,clientName) {
		String s = "Network-NewBlockReader";
		String extra = ", DataNode: " + sock.getInetAddress().getCanonicalHostName();
		extra += ";file: " + file;
		//extra += ", length: " + Long.toString(len) + "B";
		extra += ";" + Long.toString(len);
		extra += ";blockId: " + Long.toString(blockId);
		extra += ";startOffset: " + Long.toString(startOffset);
		instrumentation(s,"after",extra);
	}
}

import java.io.*;
import java.util.*;
import java.lang.management.ManagementFactory;
import java.sql.Timestamp;
import java.text.SimpleDateFormat;
import java.net.InetAddress;
import java.lang.ClassLoader;
import org.apache.hadoop.io.DataInputBuffer;
import org.apache.hadoop.mapred.TaskStatus;
import org.apache.hadoop.fs.permission.FsPermission;
import org.apache.hadoop.util.Progressable;
import org.apache.hadoop.hdfs.protocol.DatanodeInfo;
import org.apache.hadoop.util.DataChecksum;
import java.net.Socket;

import org.apache.hadoop.security.token.Token;
import org.apache.hadoop.security.token.TokenIdentifier;
import org.apache.hadoop.hdfs.security.token.block.BlockTokenIdentifier;

import org.apache.hadoop.fs.FSDataInputStream;
import org.apache.hadoop.hdfs.DFSClient;

import org.apache.hadoop.mapred.TaskTrackerStatus;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import org.apache.hadoop.conf.Configuration;

/**
 *
 * @author Alejandro
 */

aspect AlojaAspect {

	private static final Log LOG = LogFactory.getLog(AlojaAspect.class);

	/*
	TYPES
	######################################################################################################################################
	######################################################################################################################################
	*/

    public static class Events {

        public static final int JobTracker = 11111;
        public static final int TaskTracker = 11112;
        public static final int NameNode = 11113;
        public static final int SecondaryNameNode = 11114;
        public static final int DataNode = 11115;
        public static final int Task = 11116;
        public static final int HeartBeat = 11119;
//        public static final int MapTask = 11117;
//        public static final int ReduceTask = 11118;
        public static final int MapOutputBuffer = 33333;
        public static final int MapTaskOutputSize = 44444;
    }

    public static class Values {

       	// Generic
		public static final int End = 0;
        public static final int Start = 1;

        // Events.TaskTracker
		public static final int RunMapper = 8;
        public static final int RunReducer = 9;
        public static final int ReducerCopyPhase = 10;
        public static final int ReducerSortPhase = 11;
        public static final int ReducerReducePhase = 12;

		// Events.MapOutputBuffer
        public static final int Flush = 1;
        public static final int SortAndSpill = 2;
        public static final int Sort = 3;
        public static final int CreateSpillIndexFile = 5;
        //public static final int TotalIndexCacheMemory = 6;
        public static final int SpillRecordDumped = 7;
        public static final int Combine = 4;
    }

	/*
	FUNCTIONS
	######################################################################################################################################
	######################################################################################################################################
	*/

	private static long getPID() {
		String name = java.lang.management.ManagementFactory.getRuntimeMXBean().getName();
		return Long.parseLong(name.split("@")[0]);
	}

	private void generateEvent(Integer key, Integer value) {
		//2:cpu:app:task:thread:time:type:value
		try{
			String hostname = InetAddress.getLocalHost().getHostName();
			long pid = getPID();
			//LOG.info(hostname+","+pid+",2:"+hostname+":2:"+pid+":1:"+System.currentTimeMillis()+":"+key+":"+value);
			LOG.info("AOPLOG,"+hostname+","+pid+","+System.currentTimeMillis()+","+key+","+value);
		}
		catch (Exception e) {
			LOG.error(e, e);

		}
	}

	private void generateEvent(Integer key, String value) {
		//2:cpu:app:task:thread:time:type:value
		try{
			String hostname = InetAddress.getLocalHost().getHostName();
			long pid = getPID();
			//LOG.info(hostname+","+pid+",2:"+hostname+":2:"+pid+":1:"+System.currentTimeMillis()+":"+key+":"+value);
			LOG.info("AOPLOG,"+hostname+","+pid+","+System.currentTimeMillis()+","+key+","+value);
		}
		catch (Exception e) {
			LOG.error(e, e);

		}
	}

	/*private void generateEVent(Integer key[], Integer value) {

		StringBuffer output = new StringBuffer();

		output.append()

	}*/

	private void instrumentation(String event, String when) {

		instrumentation(event, when, "");

	}
	private void instrumentation(String event, String when, String additional) {
		try {
			//Add hostname
			String log = InetAddress.getLocalHost().getHostName();
			//Add PID
			log += "," + getPID();
			//Specify event
			log += "," + when + "," + event;
			//Specify event
			log += additional;
			//LOG.info(log);
			//writeLog(logFile,log);

		}
		catch (IOException e) {
			e.printStackTrace();
		}
	}

	/*
	POINTCUTS
	######################################################################################################################################
	######################################################################################################################################
	*/

	//RegisterDataNode Pointcut

	pointcut startDataNode(): execution(* org.apache.hadoop.hdfs.server.datanode.DataNode.startDataNode(..));

	//RegisterTaskTracker Pointcut

	pointcut registerTaskTracker(): execution(* org.apache.hadoop.mapred.TaskTracker.initialize(..));

	//RegisterNameNode Pointcut

	pointcut initializeNameNode():  execution(* org.apache.hadoop.hdfs.server.namenode.NameNode.initialize(..));

	//RegisterSecondaryNamenode Pointcut

	pointcut initializeSecondaryNameNode(): execution(* org.apache.hadoop.hdfs.server.namenode.SecondaryNameNode.initialize(..));

	//RegisterTask - CHILD

	//pointcut initializeChild(): call(* org.apache.hadoop.mapred.Child.initMetrics(..)) && withincode(* org.apache.hadoop.mapred.Child.main(..));

	pointcut initializeChild(): execution(* org.apache.hadoop.mapred.Child.main(..));

	//Register JobTracker Pointcut

	pointcut registerJobTracker(): execution(* org.apache.hadoop.mapred.JobTracker.startTracker(..));

	//HEARTBEAT

	pointcut heartbeat(TaskTrackerStatus status,boolean restarted,boolean initialContact,boolean acceptNewTasks,short responseId): execution(* org.apache.hadoop.mapred.JobTracker.heartbeat(..)) && args(status, restarted, initialContact, acceptNewTasks,responseId);

	/*
		###########################################################################
		############################Task###########################################
		###########################################################################
	*/

	pointcut outputSize(): call (* *.getLen(..)) && withincode(* org.apache.hadoop.mapred.Task.calculateOutputSize());

	/*
		###########################################################################
		############################MAPPER#########################################
		###########################################################################
	*/

	//pointcut maptask(): execution(* org.apache.hadoop.mapred.MapTask.run(..));
	pointcut mapper(): call(* org.apache.hadoop.mapred.MapTask.runNewMapper(..)) && withincode(* org.apache.hadoop.mapred.MapTask.run(..));

	//  ############################SORT AND SPILL#################################

	//Start-End
	pointcut taskSortAndSpill(): execution(* org.apache.hadoop.mapred.MapTask.MapOutputBuffer.sortAndSpill());

	pointcut flush(): execution(* org.apache.hadoop.mapred.MapTask.MapOutputBuffer.flush());

	//Spill File Size
	pointcut sortAndSpillSpillFile(int numSpills, long size) : call (* *.getSpillFileForWrite(..)) && withincode(* org.apache.hadoop.mapred.MapTask.MapOutputBuffer.sortAndSpill()) && args(numSpills, size);

	//SpillIndex File Size
	pointcut sortAndSpillSpillIndexFile(int numSpills, long partitions) : call (* *.getSpillIndexFileForWrite(..)) && withincode(* org.apache.hadoop.mapred.MapTask.MapOutputBuffer.sortAndSpill()) && args(numSpills, partitions);

	//Sort
	pointcut sortAndSpillSort(int kvstart, int endPosition, Object reporter): call(* *.sort(..)) && withincode(* org.apache.hadoop.mapred.MapTask.MapOutputBuffer.sortAndSpill()) && args(..,kvstart,endPosition,reporter);

	//Init Writer
	//pointcut sortAndSpillInitWriter() : call (org.apache.hadoop.mapred.IFile.Writer.new(..)) && withincode(* org.apache.hadoop.mapred.MapTask.MapOutputBuffer.sortAndSpill());

	//Close Writer
	//pointcut sortAndSpillCloseWriter() : call (void org.apache.hadoop.mapred.IFile.Writer.close(..)) && withincode(* org.apache.hadoop.mapred.MapTask.MapOutputBuffer.sortAndSpill());

	//Write key-value
	pointcut sortAndSpillWrite(DataInputBuffer key, DataInputBuffer value): call (* *.append(..)) && withincode(* org.apache.hadoop.mapred.MapTask.MapOutputBuffer.sortAndSpill()) && args(key,value);

	//Combiner
	pointcut sortAndSpillCombiner(): call(* *.combine(..)) && withincode(* org.apache.hadoop.mapred.MapTask.MapOutputBuffer.sortAndSpill());

	//Spill Index File
	pointcut sortAndSpillSpillIndexWrite(): call(* *.writeToFile(..)) && withincode(* org.apache.hadoop.mapred.MapTask.MapOutputBuffer.sortAndSpill());

	/*
		###########################################################################
		############################REDUCER########################################
		###########################################################################
	*/

	//REDUCETASK RUN
	pointcut reducer(): execution(* org.apache.hadoop.mapred.ReduceTask.run(..));
	pointcut initCodec(): call(* *.initCodec(..)) && withincode(* org.apache.hadoop.mapred.ReduceTask.run(..));
	pointcut setPhase(TaskStatus.Phase phase): call(* *.setPhase(..)) && withincode(* org.apache.hadoop.mapred.ReduceTask.run(..)) && args(phase);

	//pointcut endCopy(): call(* *.setPhase(..)) && withincode(* org.apache.hadoop.mapred.ReduceTask.run(..));
	//pointcut endSort(): call(* *.getMapOutputKeyClass(..)) && withincode(* org.apache.hadoop.mapred.ReduceTask.run(..));

	/*
		###########################################################################
		############################NETWORK########################################
		###########################################################################
	*/

	pointcut defaultBlockSize(): call(* org.apache.hadoop.hdfs.DFSClient.getDefaultBlockSize());
	//pointcut blockSize(): call(* org.apache.hadoop.hdfs.DFSClient.getBlockSize(..));
	pointcut createDFSFile(String src,FsPermission permission,boolean overwrite,boolean createParent,short replication,long blockSize,Progressable progress, int buffersize): execution (* org.apache.hadoop.hdfs.DFSClient.create(..)) && args(src,permission,overwrite,createParent,replication,blockSize,progress,buffersize);
	pointcut runDataStreamer(): execution (* org.apache.hadoop.hdfs.DFSClient.DFSOutputStream.DataStreamer.run());
	//pointcut readEntireBufferFromDataNode(byte buf[],int off,int len): execution(* org.apache.hadoop.hdfs.DFSClient.DFSInputStream.read(..)) && args(buf[],off,len);
	//pointcut readFromDataNode(): call (* org.apache.hadoop.hdfs.DFSClient.DFSInputStream.blockSeekTo(..)) && withincode(* org.apache.hadoop.hdfs.DFSClient.DFSInputStream.read(..));
	pointcut newBlockReader(Socket sock, String file, long blockId, Token<BlockTokenIdentifier> accessToken, long genStamp, long startOffset, long len, int bufferSize, boolean verifyChecksum, String clientName): execution (* org.apache.hadoop.hdfs.DFSClient.BlockReader.newBlockReader(..)) && args(sock,file,blockId,accessToken,genStamp,startOffset,len,bufferSize,verifyChecksum,clientName);

	/*
	Advices
	######################################################################################################################################
	######################################################################################################################################
	*/

	// RegiterJobTracker

	after() : registerJobTracker(){
		generateEvent(Events.JobTracker, Values.Start);

	}

	//RegisterTaskTracker
	after() : registerTaskTracker(){
		generateEvent(Events.TaskTracker, Values.Start);

	}

	//RegisterNameNode

	after() : initializeNameNode(){
		generateEvent(Events.NameNode, Values.Start);
	}

	//RegisterDataNode

	after() : startDataNode(){
		generateEvent(Events.DataNode, Values.Start);
	}

	//RegisterSecondaryNamenode

	after() : initializeSecondaryNameNode(){
		generateEvent(Events.SecondaryNameNode, Values.Start);
	}

	//HEARTBEAT
	after(TaskTrackerStatus status,boolean restarted,boolean initialContact,boolean acceptNewTasks,short responseId) : heartbeat(status, restarted, initialContact, acceptNewTasks,responseId){
		// SAMPLE trackername: tracker_vagrant-99-01:localhost/127.0.0.1:38149
		generateEvent(Events.HeartBeat, status.getTrackerName().replace(':','-').replace('/','_'));
	}

	/*
		###########################################################################
		############################Task###########################################
		###########################################################################
	*/

	//RegisterTask CHILD
	after() : initializeChild() { //We need the  PID of this task to be registered
		generateEvent(Events.Task, Values.Start);
	}

/*	after() returning(long size) : outputSize() {
		String s = "Task-outputSize";
		instrumentation(s,"after",", size: " + Long.toString(size));
	}

	/*
		###########################################################################
		############################Mapper#########################################
		###########################################################################
	*/

	/*before() : maptask(){
		generateEvent(Events.MapTask, Values.Start);
	}*/

	before() : mapper(){
		generateEvent(Events.TaskTracker, Values.RunMapper);
	}

	after() : mapper(){
		generateEvent(Events.TaskTracker, Values.End);
	}

	//  ############################SORT AND SPILL#################################

	before() : taskSortAndSpill(){
		generateEvent(Events.MapOutputBuffer, Values.SortAndSpill);
	}

	after() : taskSortAndSpill(){
		generateEvent(Events.MapOutputBuffer, Values.End);
	}

	//flush

	before() : flush(){
		generateEvent(Events.MapOutputBuffer, Values.Flush);
	}

	after() : flush(){
		generateEvent(Events.MapOutputBuffer, Values.End);
	}

	// Spill File Size

	after(int numSpills, long size) returning : sortAndSpillSpillFile(numSpills, size){
		String s = "sortAndSpillSpillFile";
		instrumentation(s,"after",", numSpills: " +Integer.toString(numSpills) + ";size: " + Long.toString((size*numSpills) + size));
	}

	// SpillIndex File Size

	after(int numSpills, long partitions) returning : sortAndSpillSpillIndexFile(numSpills, partitions){
		String s = "sortAndSpillSpillIndexFile";
		instrumentation(s,"after","," + Long.toString(numSpills * partitions));
	}

/*
	before(int length) : kvbufferState(length){

		String s = "kvbufferState";
		File logFile = getFile();
		instrumentation(logFile,s,"before");
		writeLog(logFile,Integer.toString(length));
	}

*/

	before(int kvstart, int endPosition, Object reporter) : sortAndSpillSort(kvstart,endPosition,reporter){
		generateEvent(Events.MapOutputBuffer, Values.Sort);
		//instrumentation(s,"before","," + Integer.toString(endPosition - kvstart));
	}
	after(int kvstart, int endPosition, Object reporter) returning : sortAndSpillSort(kvstart,endPosition,reporter){
		generateEvent(Events.MapOutputBuffer, Values.End);
		//instrumentation(s,"after","," + Integer.toString(endPosition - kvstart));
	}

	// Init writer
/*	after() returning : sortAndSpillInitWriter(){
		String s = "sortAndSpillInitWriter";
		instrumentation(s,"after");
	}

	// Close writer
	after() returning : sortAndSpillCloseWriter(){
		String s = "sortAndSpillCloseWriter";
		instrumentation(s,"after");
	}
*/

	after(DataInputBuffer key, DataInputBuffer value) returning : sortAndSpillWrite(key,value){
		generateEvent(Events.MapOutputBuffer, Values.SpillRecordDumped);
	}

	before() : sortAndSpillCombiner(){
		generateEvent(Events.MapOutputBuffer, Values.Combine);
	}

	after() returning : sortAndSpillCombiner(){
		generateEvent(Events.MapOutputBuffer, Values.End);
	}

	before() : sortAndSpillSpillIndexWrite(){
		generateEvent(Events.MapOutputBuffer, Values.CreateSpillIndexFile);
	}

	after() returning : sortAndSpillSpillIndexWrite(){
		generateEvent(Events.MapOutputBuffer, Values.End);
	}

	/*
		###########################################################################
		############################REDUCER########################################
		###########################################################################
	*/

/*	before() : reducer(){
		String s = "Reducer";
		instrumentation(s,"before");
	}
*/

	before() : initCodec() {
		generateEvent(Events.TaskTracker, Values.RunReducer);
	}

	after() returning : initCodec() {
		generateEvent(Events.TaskTracker, Values.ReducerCopyPhase);
	}

	before(TaskStatus.Phase phase) : setPhase(phase) { //END OF A PHASE (SORT OR COPY)
			generateEvent(Events.TaskTracker, Values.End);
	}

	after(TaskStatus.Phase phase) returning: setPhase(phase) {
		if (phase == TaskStatus.Phase.SORT) {
			generateEvent(Events.TaskTracker, Values.ReducerSortPhase);
		}
		else if (phase == TaskStatus.Phase.REDUCE) {
			generateEvent(Events.TaskTracker, Values.ReducerReducePhase);
		}
	}

	after() : reducer(){ //END OF REDUCE PHASE
			generateEvent(Events.TaskTracker, Values.End);	}

	/*
		###########################################################################
		############################NETWORK########################################
		###########################################################################
	*/

	after() returning(long blockSize) : defaultBlockSize() {
		String s = "Network-defaultBlockSize";
		instrumentation(s,"after",", size: " + Long.toString(blockSize));
	}
	// after() returning(long blockSize) : blockSize() {
	// 	String s = "Network-blockSize";
	// 	File logFile = getFile();
	// 	instrumentation(logFile,s,"after");
	// 	String log = ", size: " + Long.toString(blockSize);
	// 	writeLog(logFile,log);
	// }

	after(String src,FsPermission permission,boolean overwrite, boolean createParent,short replication,long blockSize,Progressable progress, int buffersize): createDFSFile(src,permission,overwrite,createParent,replication,blockSize,progress,buffersize) {
		String s = "Network-CreateDFSFile";

		//MODIFIED!!!!!!-----!!!!!!!!!!!
		instrumentation(s,"after",", path: " + src + ";permission: " + permission.toString() + ";overwrite: " + String.valueOf(overwrite) + ";createParent: " + String.valueOf(createParent) + ";replication: " + Short.toString(replication) + ";blockSize: " + Long.toString(blockSize) + ";buffersize: " + Integer.toString(buffersize));
	}
	before(): runDataStreamer() {
		String s = "DataStreamer";
		instrumentation(s,"after");
	}

	// before(byte buf[],int off, int len) : readEntireBufferFromDataNode(buf[],off,len){
	// 	String s = "Network-ReadEntireBuffer";
	// 	instrumentation(s,"after",", bufferLength: " + Integer.toString(len));
	// }

	// after() returning(DatanodeInfo datanode) : readFromDataNode(){
	// 	String s = "Network-fromDataNode";
	// 	instrumentation(s,"after", ", from : " + datanode.getHostName());
	// }

	after(Socket sock, String file, long blockId, Token<BlockTokenIdentifier> accessToken, long genStamp, long startOffset, long len, int bufferSize, boolean verifyChecksum, String clientName) : newBlockReader(sock,file,blockId,accessToken,genStamp,startOffset,len,bufferSize,verifyChecksum,clientName) {
		String s = "Network-NewBlockReader";
		String extra = ", DataNode: " + sock.getInetAddress().getCanonicalHostName();
		extra += ";file: " + file;
		//extra += ", length: " + Long.toString(len) + "B";
		extra += ";" + Long.toString(len);
		extra += ";blockId: " + Long.toString(blockId);
		extra += ";startOffset: " + Long.toString(startOffset);
		instrumentation(s,"after",extra);
	}
}


grammar

grammar

/*
 * Copyright (c) 2013 original authors
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.eigengo.monitor.agent.akka;

import akka.actor.*;
import org.eigengo.monitor.agent.AgentConfiguration;
import org.eigengo.monitor.output.CounterInterface;
import scala.Option;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.atomic.AtomicLong;
import java.util.concurrent.ConcurrentHashMap;

/**
 * Contains advices for monitoring behaviour of an actor; typically imprisoned in an {@code ActorCell}.
 */
public aspect ActorCellMonitoringAspect extends AbstractMonitoringAspect issingleton() {
    private AkkaAgentConfiguration agentConfiguration;
    private final CounterInterface counterInterface;
    private final Option<String> noActorClazz = Option.empty();
    private final ConcurrentHashMap<Option<String>, AtomicLong> concurrentCounters;

    /**
     * Constructs this aspect
     */
    public ActorCellMonitoringAspect() {
        AgentConfiguration<AkkaAgentConfiguration> configuration = getAgentConfiguration("akka", AkkaAgentConfigurationJapi.apply());
        this.agentConfiguration = configuration.agent();
        this.counterInterface = createCounterInterface(configuration.common());
        this.concurrentCounters = new ConcurrentHashMap<Option<String>, AtomicLong>();
    }

    /**
     * Injects the new {@code AkkaAgentConfiguration} instance.
     *
     * @param agentConfiguration the new configuration
     */
    synchronized final void setAgentConfiguration(AkkaAgentConfiguration agentConfiguration) {
        this.agentConfiguration = agentConfiguration;
    }

    // decide whether to include this ActorCell in our measurements
    private boolean includeActorPath(final PathAndClass pathAndClass) {
        if (!this.agentConfiguration.incuded().accept(pathAndClass)) return false;
        if (this.agentConfiguration.excluded().accept(pathAndClass)) return false;

        if (this.agentConfiguration.includeSystemAgents()) return true;

        String userOrSystem = pathAndClass.actorPath().getElements().iterator().next();
        return "user".equals(userOrSystem);
    }

    // get the sample rate for an actor
    private int getSampleRate(final PathAndClass pathAndClass) {
        return this.agentConfiguration.sampling().getRate(pathAndClass);
    }

    // decide whether to sample an actor on a particular occasion
    private final boolean sampleMessage(final PathAndClass pathAndClass) {
        int sampleRate = getSampleRate(pathAndClass);
        if (sampleRate == 1) return true;

        this.concurrentCounters.putIfAbsent(pathAndClass.actorClassName(), new AtomicLong(0));
        long timesSeenSoFar = this.concurrentCounters.get(pathAndClass.actorClassName()).incrementAndGet();
        return (timesSeenSoFar % sampleRate == 1); // == 1 to log first value (incrementAndGet returns updated value)
    }

    // get the tags for the cell
    private String[] getTags(final ActorPath actorPath, final Actor actor) {
        List<String> tags = new ArrayList<String>();

        // TODO: Improve detection of routed actors. This relies only on the naming :(.
        String lastPathElement = actorPath.elements().last();
        if (lastPathElement.startsWith("$")) {
            // this is routed actor.
            tags.add(actorPath.parent().toString());
            if (this.agentConfiguration.includeRoutees()) tags.add(actorPath.toString());
        } else {
            // there is no supervisor
            tags.add(actorPath.toString());
        }
        if (actor != null) {
            tags.add(String.format("akka:%s.%s", actor.context().system().name(), actor.getClass().getCanonicalName()));
        }

        return tags.toArray(new String[tags.size()]);
    }

    /**
     * Advises the {@code ActorCell.receiveMessage(message: Object): Unit}
     * We proceed with the pointcut if the actor is to be included in the monitoring *and* this is
     * the 'multiple-of-n'th time we've seen a message for an actor with a sample rate of n.
     *
     * Currently, we sample queue size, the fact that the message is delivered, the simple name of the class of the
     * message, and the time taken to complete the actor's reactive action.
     *
     * @param actorCell the ActorCell where the actor that receives the message "lives"
     * @param msg the incoming message
     */
    Object around(ActorCell actorCell, Object msg) : Pointcuts.actorCellReceiveMessage(actorCell, msg) {
        final ActorPath actorPath = actorCell.self().path();
        final PathAndClass pathAndClass = new PathAndClass(actorPath, Option.apply(actorCell.actor().getClass().getCanonicalName()));
        if (!includeActorPath(pathAndClass) || !sampleMessage(pathAndClass)) return proceed(actorCell, msg);

        int samplingRate = getSampleRate(pathAndClass);

        // we tag by actor name
        final String[] tags = getTags(actorPath, actorCell.actor());

        // record the queue size
        this.counterInterface.recordGaugeValue("akka.queue.size", actorCell.numberOfMessages(), tags);
        // record the message, general and specific
        this.counterInterface.incrementCounter("akka.actor.delivered", samplingRate, tags);
        this.counterInterface.incrementCounter("akka.actor.delivered." + msg.getClass().getSimpleName(), samplingRate, tags);

        // measure the time. we're using the ``nanoTime`` call to access the high-precision timer.
        // since we're not really interested in wall time, but just some increasing measure of
        // elapsed time
        Object result = null;
        final long start = System.nanoTime();
        // result will always be ``null``, because target returns ``Unit``
        result = proceed(actorCell, msg);
        // ns or µs is too fine. ms will do for now.
        final long duration = (System.nanoTime() - start) / 1000000;

        // record the actor duration
        this.counterInterface.recordExecutionTime("akka.actor.duration", (int)duration, tags);

        // return null would do the trick, but we want to be _proper_.
        return result;
    }

    /**
     * Advises the {@code ActorCell.handleInvokeFailure(_, failure: Throwable): Unit}
     *
     * @param actorCell the ActorCell where the error spreads from
     * @param failure the exception that escaped from the {@code receive} method
     */
    before(ActorCell actorCell, Throwable failure) : Pointcuts.actorCellHandleInvokeFailure(actorCell, failure) {
        // record the error, general and specific
        String[] tags = getTags(actorCell.self().path(), actorCell.actor());
        this.counterInterface.incrementCounter("akka.actor.error", tags);
        this.counterInterface.incrementCounter(String.format("akka.actor.error.%s", failure.getMessage()), tags);
    }

    /**
     * Advises the {@code EventStream.publish(event: Any): Unit}
     *
     * @param event the received event
     */
    before(Object event) : Pointcuts.eventStreamPublish(event) {
        if (event instanceof UnhandledMessage) {
            UnhandledMessage unhandledMessage = (UnhandledMessage)event;
            String[] tags = getTags(unhandledMessage.recipient().path(), null);
            this.counterInterface.incrementCounter("akka.actor.undelivered", tags);
            this.counterInterface.incrementCounter("akka.actor.undelivered." + unhandledMessage.getMessage().getClass().getSimpleName(), tags);
        }
    }

    /**
     * Advises the {@code actorOf} method of {@code ActorCell} and {@code ActorSystem}
     *
     * @param actor the {@code ActorRef} returned from the call
     */
    after() returning (ActorRef actor): Pointcuts.anyActorOf() {
        if (!includeActorPath(new PathAndClass(actor.path(), this.noActorClazz))) return;

        final String tag = actor.path().root().toString();
        this.counterInterface.incrementCounter("akka.actor.count", tag);
    }

    /**
     * Advises the {@code ActorCell.stop} method
     *
     * @param actor the actor being stopped
     */
    after(ActorRef actor) : Pointcuts.actorCellStop(actor) {
        if (!includeActorPath(new PathAndClass(actor.path(), this.noActorClazz))) return;

        final String tag = actor.path().root().toString();
        this.counterInterface.decrementCounter("akka.actor.count", tag);
    }

}

/*
 * Copyright (c) 2013 original authors
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.eigengo.monitor.agent.akka;

import akka.actor.*;
import org.eigengo.monitor.agent.AgentConfiguration;
import org.eigengo.monitor.output.CounterInterface;
import scala.Option;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.atomic.AtomicLong;
import java.util.concurrent.ConcurrentHashMap;

/**
 * Contains advices for monitoring behaviour of an actor; typically imprisoned in an {@code ActorCell}.
 */
public aspect ActorCellMonitoringAspect extends AbstractMonitoringAspect issingleton() {
    private AkkaAgentConfiguration agentConfiguration;
    private final CounterInterface counterInterface;
    private final Option<String> noActorClazz = Option.empty();
    private final ConcurrentHashMap<Option<String>, AtomicLong> concurrentCounters;

    /**
     * Constructs this aspect
     */
    public ActorCellMonitoringAspect() {
        AgentConfiguration<AkkaAgentConfiguration> configuration = getAgentConfiguration("akka", AkkaAgentConfigurationJapi.apply());
        this.agentConfiguration = configuration.agent();
        this.counterInterface = createCounterInterface(configuration.common());
        this.concurrentCounters = new ConcurrentHashMap<Option<String>, AtomicLong>();
    }

    /**
     * Injects the new {@code AkkaAgentConfiguration} instance.
     *
     * @param agentConfiguration the new configuration
     */
    synchronized final void setAgentConfiguration(AkkaAgentConfiguration agentConfiguration) {
        this.agentConfiguration = agentConfiguration;
    }

    // decide whether to include this ActorCell in our measurements
    private boolean includeActorPath(final PathAndClass pathAndClass) {
        if (!this.agentConfiguration.incuded().accept(pathAndClass)) return false;
        if (this.agentConfiguration.excluded().accept(pathAndClass)) return false;

        if (this.agentConfiguration.includeSystemAgents()) return true;

        String userOrSystem = pathAndClass.actorPath().getElements().iterator().next();
        return "user".equals(userOrSystem);
    }

    // get the sample rate for an actor
    private int getSampleRate(final PathAndClass pathAndClass) {
        return this.agentConfiguration.sampling().getRate(pathAndClass);
    }

    // decide whether to sample an actor on a particular occasion
    private final boolean sampleMessage(final PathAndClass pathAndClass) {
        int sampleRate = getSampleRate(pathAndClass);
        if (sampleRate == 1) return true;

        this.concurrentCounters.putIfAbsent(pathAndClass.actorClassName(), new AtomicLong(0));
        long timesSeenSoFar = this.concurrentCounters.get(pathAndClass.actorClassName()).incrementAndGet();
        return (timesSeenSoFar % sampleRate == 1); // == 1 to log first value (incrementAndGet returns updated value)
    }

    // get the tags for the cell
    private String[] getTags(final ActorPath actorPath, final Actor actor) {
        List<String> tags = new ArrayList<String>();

        // TODO: Improve detection of routed actors. This relies only on the naming :(.
        String lastPathElement = actorPath.elements().last();
        if (lastPathElement.startsWith("$")) {
            // this is routed actor.
            tags.add(actorPath.parent().toString());
            if (this.agentConfiguration.includeRoutees()) tags.add(actorPath.toString());
        } else {
            // there is no supervisor
            tags.add(actorPath.toString());
        }
        if (actor != null) {
            tags.add(String.format("akka:%s.%s", actor.context().system().name(), actor.getClass().getCanonicalName()));
        }

        return tags.toArray(new String[tags.size()]);
    }

    /**
     * Advises the {@code ActorCell.receiveMessage(message: Object): Unit}
     * We proceed with the pointcut if the actor is to be included in the monitoring, *and* if
     * this is the 'multiple-of-n'th time we've seen a message for an actor with a sample rate of n.
     *
     * Currently, we sample queue size, the fact that the message is delivered, the simple name of the class of the
     * message, and the time taken to complete the actor's reactive action.
     *
     * @param actorCell the ActorCell where the actor that receives the message "lives"
     * @param msg the incoming message
     */
    Object around(ActorCell actorCell, Object msg) : Pointcuts.actorCellReceiveMessage(actorCell, msg) {
        final ActorPath actorPath = actorCell.self().path();
        final PathAndClass pathAndClass = new PathAndClass(actorPath, Option.apply(actorCell.actor().getClass().getCanonicalName()));
        if (!includeActorPath(pathAndClass) || !sampleMessage(pathAndClass)) return proceed(actorCell, msg);

        int samplingRate = getSampleRate(pathAndClass);

        // we tag by actor name
        final String[] tags = getTags(actorPath, actorCell.actor());

        // record the queue size
        this.counterInterface.recordGaugeValue("akka.queue.size", actorCell.numberOfMessages(), tags);
        // record the message, general and specific
        this.counterInterface.incrementCounter("akka.actor.delivered", samplingRate, tags);
        this.counterInterface.incrementCounter("akka.actor.delivered." + msg.getClass().getSimpleName(), samplingRate, tags);

        // measure the time. we're using the ``nanoTime`` call to access the high-precision timer.
        // since we're not really interested in wall time, but just some increasing measure of
        // elapsed time
        Object result = null;
        final long start = System.nanoTime();
        // result will always be ``null``, because target returns ``Unit``
        result = proceed(actorCell, msg);
        // ns or µs is too fine. ms will do for now.
        final long duration = (System.nanoTime() - start) / 1000000;

        // record the actor duration
        this.counterInterface.recordExecutionTime("akka.actor.duration", (int)duration, tags);

        // return null would do the trick, but we want to be _proper_.
        return result;
    }

    /**
     * Advises the {@code ActorCell.handleInvokeFailure(_, failure: Throwable): Unit}
     *
     * @param actorCell the ActorCell where the error spreads from
     * @param failure the exception that escaped from the {@code receive} method
     */
    before(ActorCell actorCell, Throwable failure) : Pointcuts.actorCellHandleInvokeFailure(actorCell, failure) {
        // record the error, general and specific
        String[] tags = getTags(actorCell.self().path(), actorCell.actor());
        this.counterInterface.incrementCounter("akka.actor.error", tags);
        this.counterInterface.incrementCounter(String.format("akka.actor.error.%s", failure.getMessage()), tags);
    }

    /**
     * Advises the {@code EventStream.publish(event: Any): Unit}
     *
     * @param event the received event
     */
    before(Object event) : Pointcuts.eventStreamPublish(event) {
        if (event instanceof UnhandledMessage) {
            UnhandledMessage unhandledMessage = (UnhandledMessage)event;
            String[] tags = getTags(unhandledMessage.recipient().path(), null);
            this.counterInterface.incrementCounter("akka.actor.undelivered", tags);
            this.counterInterface.incrementCounter("akka.actor.undelivered." + unhandledMessage.getMessage().getClass().getSimpleName(), tags);
        }
    }

    /**
     * Advises the {@code actorOf} method of {@code ActorCell} and {@code ActorSystem}
     *
     * @param actor the {@code ActorRef} returned from the call
     */
    after() returning (ActorRef actor): Pointcuts.anyActorOf() {
        if (!includeActorPath(new PathAndClass(actor.path(), this.noActorClazz))) return;

        final String tag = actor.path().root().toString();
        this.counterInterface.incrementCounter("akka.actor.count", tag);
    }

    /**
     * Advises the {@code ActorCell.stop} method
     *
     * @param actor the actor being stopped
     */
    after(ActorRef actor) : Pointcuts.actorCellStop(actor) {
        if (!includeActorPath(new PathAndClass(actor.path(), this.noActorClazz))) return;

        final String tag = actor.path().root().toString();
        this.counterInterface.decrementCounter("akka.actor.count", tag);
    }

}


Encapsulate constraint registration from class loading

/**
 * Copyright (c) 2011 Sourcepit.org contributors and others. All rights reserved. This program and the accompanying
 * materials are made available under the terms of the Eclipse Public License v1.0 which accompanies this distribution,
 * and is available at http://www.eclipse.org/legal/epl-v10.html
 */

package org.sourcepit.common.constraints;

import java.lang.annotation.Annotation;
import java.lang.reflect.Constructor;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Map;

import javax.validation.constraints.NotNull;

import org.aspectj.lang.reflect.ConstructorSignature;
import org.aspectj.lang.reflect.MethodSignature;

public aspect MethodAspects
{
   private static final Map<String, AbstractConstraint> CONSTRAINTS = new HashMap<String, AbstractConstraint>();
   static
   {
      CONSTRAINTS.put(NotNull.class.getName(), new NotNullConstraint());
   }

   pointcut constraintedConstructorCall() : execution(* .new(..,@javax.validation.constraints.NotNull (*),..));

   pointcut constraintedMethodArgs() : execution(* *(..,@javax.validation.constraints.NotNull (*),..));

   pointcut constraintedMethodReturnValue() : execution(@javax.validation.constraints.NotNull !void *(..));

   before() : constraintedConstructorCall() {
      final Object target = thisJoinPoint.getTarget();
      final Constructor<?> constructor = ((ConstructorSignature) thisJoinPoint.getSignature()).getConstructor();
      final Annotation[][] parametersAnnotations = constructor.getParameterAnnotations();
      final Object[] args = thisJoinPoint.getArgs();
      for (int i = 0; i < args.length; i++)
      {
         final Annotation[] parameterAnnotations = parametersAnnotations[i];
         if (parameterAnnotations.length > 0)
         {
            final Object arg = args[i];
            for (Annotation annotation : parameterAnnotations)
            {
               final AbstractConstraint constraint = getConstraint(annotation);
               if (constraint != null)
               {
                  constraint.validateConstructorArgument(target, constructor, i, annotation, arg);
               }
            }
         }
      }
   }

   before() : constraintedMethodArgs() {
      final Object target = thisJoinPoint.getTarget();
      final Method method = ((MethodSignature) thisJoinPoint.getSignature()).getMethod();
      final Annotation[][] parametersAnnotations = method.getParameterAnnotations();
      final Object[] args = thisJoinPoint.getArgs();
      for (int i = 0; i < args.length; i++)
      {
         final Annotation[] parameterAnnotations = parametersAnnotations[i];
         if (parameterAnnotations.length > 0)
         {
            final Object arg = args[i];
            for (Annotation annotation : parameterAnnotations)
            {
               final AbstractConstraint constraint = getConstraint(annotation);
               if (constraint != null)
               {
                  constraint.validateMethodArgument(target, method, i, annotation, arg);
               }
            }
         }
      }
   }

   after() returning(Object returnedValue): constraintedMethodReturnValue()
   {
      final Object target = thisJoinPoint.getTarget();
      final Method method = ((MethodSignature) thisJoinPoint.getSignature()).getMethod();
      final Annotation[] annotations = method.getAnnotations();
      if (annotations.length > 0)
      {
         for (Annotation annotation : annotations)
         {
            final AbstractConstraint constraint = getConstraint(annotation);
            if (constraint != null)
            {
               constraint.validateReturnedValue(target, method, annotation, returnedValue);
            }
         }
      }
   }

   private AbstractConstraint getConstraint(Annotation annotation)
   {
      return CONSTRAINTS.get(annotation.annotationType().getName());
   }
}

/**
 * Copyright (c) 2011 Sourcepit.org contributors and others. All rights reserved. This program and the accompanying
 * materials are made available under the terms of the Eclipse Public License v1.0 which accompanies this distribution,
 * and is available at http://www.eclipse.org/legal/epl-v10.html
 */

package org.sourcepit.common.constraints;

import java.lang.annotation.Annotation;
import java.lang.reflect.Constructor;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Map;

import javax.validation.constraints.NotNull;

import org.aspectj.lang.reflect.ConstructorSignature;
import org.aspectj.lang.reflect.MethodSignature;

public aspect MethodAspects
{
   private static final Map<Class<?>, AbstractConstraint> CONSTRAINTS = new HashMap<Class<?>, AbstractConstraint>();
   static
   {
      CONSTRAINTS.put(NotNull.class, new NotNullConstraint());
   }

   pointcut constraintedConstructorCall() : execution(* .new(..,@javax.validation.constraints.NotNull (*),..));

   pointcut constraintedMethodArgs() : execution(* *(..,@javax.validation.constraints.NotNull (*),..));

   pointcut constraintedMethodReturnValue() : execution(@javax.validation.constraints.NotNull !void *(..));

   before() : constraintedConstructorCall() {
      final Object target = thisJoinPoint.getTarget();
      final Constructor<?> constructor = ((ConstructorSignature) thisJoinPoint.getSignature()).getConstructor();
      final Annotation[][] parametersAnnotations = constructor.getParameterAnnotations();
      final Object[] args = thisJoinPoint.getArgs();
      for (int i = 0; i < args.length; i++)
      {
         final Annotation[] parameterAnnotations = parametersAnnotations[i];
         if (parameterAnnotations.length > 0)
         {
            final Object arg = args[i];
            for (Annotation annotation : parameterAnnotations)
            {
               final AbstractConstraint constraint = CONSTRAINTS.get(annotation.annotationType());
               if (constraint != null)
               {
                  constraint.validateConstructorArgument(target, constructor, i, annotation, arg);
               }
            }
         }
      }
   }

   before() : constraintedMethodArgs() {
      final Object target = thisJoinPoint.getTarget();
      final Method method = ((MethodSignature) thisJoinPoint.getSignature()).getMethod();
      final Annotation[][] parametersAnnotations = method.getParameterAnnotations();
      final Object[] args = thisJoinPoint.getArgs();
      for (int i = 0; i < args.length; i++)
      {
         final Annotation[] parameterAnnotations = parametersAnnotations[i];
         if (parameterAnnotations.length > 0)
         {
            final Object arg = args[i];
            for (Annotation annotation : parameterAnnotations)
            {
               final AbstractConstraint constraint = CONSTRAINTS.get(annotation.annotationType());
               if (constraint != null)
               {
                  constraint.validateMethodArgument(target, method, i, annotation, arg);
               }
            }
         }
      }
   }

   after() returning(Object returnedValue): constraintedMethodReturnValue()
   {
      final Object target = thisJoinPoint.getTarget();
      final Method method = ((MethodSignature) thisJoinPoint.getSignature()).getMethod();
      final Annotation[] annotations = method.getAnnotations();
      if (annotations.length > 0)
      {
         for (Annotation annotation : annotations)
         {
            final AbstractConstraint constraint = CONSTRAINTS.get(annotation.annotationType());
            if (constraint != null)
            {
               constraint.validateReturnedValue(target, method, annotation, returnedValue);
            }
         }
      }
   }
}


some version of aspectj has bug, it will not match correct parameter. so try to use aspectj as clearly as possible.

package org.zstack.core.aspect;

import org.zstack.core.log.LogSafeGson;
import org.zstack.header.message.Event;
import org.zstack.header.message.Message;
import org.zstack.header.message.MessageReply;
import org.zstack.header.message.NeedReplyMessage;
import org.zstack.utils.Utils;

import java.util.Collections;
import java.util.Map;

/**
 * Created by MaJin on 2019/9/23.
 */
public aspect LogSafeAspect {
    pointcut send() : execution(void org.zstack.core.cloudbus.CloudBus.send(Message));
    pointcut sendCallBack() : execution(void org.zstack.core.cloudbus.CloudBus.send(NeedReplyMessage, CloudBusCallBack));
    pointcut reply(MessageReply obj) : args(*, obj) && execution(void org.zstack.core.cloudbus.CloudBus.reply(Message, MessageReply));
    pointcut publish() : execution(void org.zstack.core.cloudbus.CloudBus.publish(Event));
    pointcut handle() : execution(void *.handle(Message+));

    void around(org.zstack.core.thread.ChainTask obj) : target(obj) && execution(void org.zstack.core.thread.ChainTask+.run(..)) {
        if (obj.maskWords.isEmpty()) {
            proceed(obj);
            return;
        }

        try (Utils.MaskWords h = new Utils.MaskWords(obj.maskWords)) {
            proceed(obj);
        }
    }

    Void around(org.zstack.core.thread.Task obj) : target(obj) && execution(Void org.zstack.core.thread.Task+.call()) {
        if (obj.maskWords.isEmpty()) {
            return proceed(obj);
        }

        try (Utils.MaskWords h = new Utils.MaskWords(obj.maskWords)) {
            return proceed(obj);
        }
    }

    Object around(org.zstack.core.thread.Task obj) : target(obj) && execution(Object org.zstack.core.thread.Task+.call()) {
        if (obj.maskWords.isEmpty()) {
            return proceed(obj);
        }

        try (Utils.MaskWords h = new Utils.MaskWords(obj.maskWords)) {
            return proceed(obj);
        }
    }

    void around() : send() || sendCallBack() || publish() || handle() {
        Object obj = thisJoinPoint.getArgs()[0];
        Map<String, String> maskWords = getValuesToMask(obj);
        if (maskWords.isEmpty()) {
            proceed();
            return;
        }

        boolean extend = !thisJoinPoint.getSignature().getName().equals("handle");
        try (Utils.MaskWords h = new Utils.MaskWords(maskWords, extend)) {
            proceed();
        }
    }

    void around(org.zstack.header.message.MessageReply obj) : reply(obj) {
        Map<String, String> maskWords = getValuesToMask(obj);
        if (maskWords.isEmpty()) {
            proceed(obj);
            return;
        }

        try (Utils.MaskWords h = new Utils.MaskWords(maskWords, true)) {
            proceed(obj);
        }
    }

    void around() : execution(void org.zstack.header.rest.RESTFacade+.asyncJsonPost(String, Object, java.util.Map, org.zstack.header.rest.AsyncRESTCallback, java.util.concurrent.TimeUnit, long)) {
        Object cmd = thisJoinPoint.getArgs()[1];
        Map<String, String> maskWords = getValuesToMask(cmd);
        if (maskWords.isEmpty()) {
            proceed();
            return;
        }

        try (Utils.MaskWords h = new Utils.MaskWords(maskWords, true)) {
            proceed();
        }
    }

    MessageReply around(org.zstack.header.message.Message obj) : args(obj, ..) && execution(MessageReply org.zstack.core.cloudbus.CloudBus.call(Message+, ..)) {
        Map<String, String> maskWords = getValuesToMask(obj);
        if (maskWords.isEmpty()) {
            return proceed(obj);
        }

        try (Utils.MaskWords h = new Utils.MaskWords(maskWords, true)) {
            return proceed(obj);
        }
    }

    private Map<String, String> getValuesToMask(Object obj) {
        try {
            return LogSafeGson.getValuesToMask(obj);
        } catch (Throwable t) {
            return Collections.emptyMap();
        }
    }
}

package org.zstack.core.aspect;

import org.zstack.core.log.LogSafeGson;
import org.zstack.header.message.Message;
import org.zstack.header.message.MessageReply;
import org.zstack.utils.Utils;

import java.util.Collections;
import java.util.Map;

/**
 * Created by MaJin on 2019/9/23.
 */
public aspect LogSafeAspect {
    pointcut send(Message obj) : args(obj, ..) && execution(void org.zstack.core.cloudbus.CloudBus.send(Message+, ..));
    pointcut reply(MessageReply obj) : args(.., obj) && execution(void org.zstack.core.cloudbus.CloudBus.reply(.., MessageReply+));
    pointcut publish(Message obj) : args(obj, ..) && execution(void org.zstack.core.cloudbus.CloudBus.publish(Message+, ..));
    pointcut handle(Message obj) : args(obj) && execution(void *.handle(Message+));

    void around(org.zstack.core.thread.ChainTask obj) : target(obj) && execution(void org.zstack.core.thread.ChainTask+.run(..)) {
        if (obj.maskWords.isEmpty()) {
            proceed(obj);
            return;
        }

        try (Utils.MaskWords h = new Utils.MaskWords(obj.maskWords)) {
            proceed(obj);
        }
    }

    Void around(org.zstack.core.thread.Task obj) : target(obj) && execution(Void org.zstack.core.thread.Task+.call()) {
        if (obj.maskWords.isEmpty()) {
            return proceed(obj);
        }

        try (Utils.MaskWords h = new Utils.MaskWords(obj.maskWords)) {
            return proceed(obj);
        }
    }

    Object around(org.zstack.core.thread.Task obj) : target(obj) && execution(Object org.zstack.core.thread.Task+.call()) {
        if (obj.maskWords.isEmpty()) {
            return proceed(obj);
        }

        try (Utils.MaskWords h = new Utils.MaskWords(obj.maskWords)) {
            return proceed(obj);
        }
    }

    void around(org.zstack.header.message.Message obj) : send(obj) || reply(obj) || publish(obj) || handle(obj) {
        Map<String, String> maskWords = getValuesToMask(obj);
        if (maskWords.isEmpty()) {
            proceed(obj);
            return;
        }

        boolean extend = !thisJoinPoint.getSignature().getName().equals("handle");
        try (Utils.MaskWords h = new Utils.MaskWords(maskWords, extend)) {
            proceed(obj);
        }
    }

    void around() : execution(void org.zstack.header.rest.RESTFacade+.asyncJsonPost(String, Object, java.util.Map, org.zstack.header.rest.AsyncRESTCallback, java.util.concurrent.TimeUnit, long)) {
        Object cmd = thisJoinPoint.getArgs()[1];
        Map<String, String> maskWords = getValuesToMask(cmd);
        if (maskWords.isEmpty()) {
            proceed();
            return;
        }

        try (Utils.MaskWords h = new Utils.MaskWords(maskWords, true)) {
            proceed();
        }
    }

    MessageReply around(org.zstack.header.message.Message obj) : args(obj, ..) && execution(MessageReply org.zstack.core.cloudbus.CloudBus.call(Message+, ..)) {
        Map<String, String> maskWords = getValuesToMask(obj);
        if (maskWords.isEmpty()) {
            return proceed(obj);
        }

        try (Utils.MaskWords h = new Utils.MaskWords(maskWords, true)) {
            return proceed(obj);
        }
    }

    private Map<String, String> getValuesToMask(Object obj) {
        try {
            return LogSafeGson.getValuesToMask(obj);
        } catch (Throwable t) {
            return Collections.emptyMap();
        }
    }
}


added tx to some log messages, added log.error to rollback catch

/**
 * Copyright 2010 CosmoCode GmbH
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package de.cosmocode.palava.jpa.aspectj;

import javax.persistence.EntityManager;
import javax.persistence.EntityTransaction;
import javax.persistence.PersistenceException;

import org.aspectj.lang.annotation.SuppressAjWarnings;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.google.common.base.Preconditions;
import com.google.inject.Inject;
import com.google.inject.Provider;

import de.cosmocode.palava.core.aop.AbstractPalavaAspect;
import de.cosmocode.palava.jpa.Transactional;

public final aspect EntityTransactionAspect extends AbstractPalavaAspect issingleton() {

    private static final Logger LOG = LoggerFactory.getLogger(EntityTransactionAspect.class);

    private Provider<EntityManager> currentManager;

    @Inject
    public void setProvider(Provider<EntityManager> manager) {
        this.currentManager = Preconditions.checkNotNull(manager, "Manager");
    }

    pointcut transactional(): execution(@Transactional * *.*(..));

    @SuppressAjWarnings("adviceDidNotMatch")
    Object around(): transactional() {
        final EntityManager manager = currentManager.get();
        LOG.trace("Retrieved entitymanager {}", manager);
        final EntityTransaction tx = manager.getTransaction();
        LOG.trace("Using transaction {}", tx);
        final boolean localTx = !tx.isActive();

        if (localTx) {
            LOG.trace("Beginning automatic transaction {}", tx);
            tx.begin();
        } else {
            LOG.trace("Transaction {} already active", tx);
        }

        final Object returnValue;

        try {
            returnValue = proceed();
        } catch (RuntimeException e) {
            LOG.debug("Exception inside automatic transaction context; rolling back", e);
            tx.rollback();
            throw e;
        }

        if (localTx && tx.isActive()) {
            if (tx.getRollbackOnly()) {
                LOG.debug("Transaction {} was marked as rollback only. Rolling back...", tx);
                tx.rollback();
            } else {
                try {
                    tx.commit();
                    LOG.trace("Committed automatic transaction {}", tx);
                } catch (PersistenceException e) {
                    LOG.debug("Commit in automatic transaction context failed", e);
                    if (tx.isActive()) {
                        LOG.debug("Rolling back {}", tx);
                        try {
                            tx.rollback();
                        } catch (PersistenceException e2) {
                            LOG.error("Commit in automatic transaction context failed", e);
                            throw e2;
                        }
                    } else {
                        LOG.debug("Can't roll back inactive transaction {}", tx);
                    }
                    throw e;
                }
            }
        } else {
            LOG.trace("Not committing non-local transaction {}", tx);
        }

        return returnValue;
    }

}

/**
 * Copyright 2010 CosmoCode GmbH
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package de.cosmocode.palava.jpa.aspectj;

import javax.persistence.EntityManager;
import javax.persistence.EntityTransaction;
import javax.persistence.PersistenceException;

import org.aspectj.lang.annotation.SuppressAjWarnings;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.google.common.base.Preconditions;
import com.google.inject.Inject;
import com.google.inject.Provider;

import de.cosmocode.palava.core.aop.AbstractPalavaAspect;
import de.cosmocode.palava.jpa.Transactional;

public final aspect EntityTransactionAspect extends AbstractPalavaAspect issingleton() {

    private static final Logger LOG = LoggerFactory.getLogger(EntityTransactionAspect.class);

    private Provider<EntityManager> currentManager;

    @Inject
    public void setProvider(Provider<EntityManager> manager) {
        this.currentManager = Preconditions.checkNotNull(manager, "Manager");
    }

    pointcut transactional(): execution(@Transactional * *.*(..));

    @SuppressAjWarnings("adviceDidNotMatch")
    Object around(): transactional() {
        final EntityManager manager = currentManager.get();
        LOG.trace("Retrieved entitymanager {}", manager);
        final EntityTransaction tx = manager.getTransaction();
        LOG.trace("Using transaction {}", tx);
        final boolean localTx = !tx.isActive();

        if (localTx) {
            LOG.trace("Beginning automatic transaction");
            tx.begin();
        } else {
            LOG.trace("Transaction already active");
        }

        final Object returnValue;

        try {
            returnValue = proceed();
        } catch (RuntimeException e) {
            LOG.debug("Exception inside automatic transaction context; rolling back", e);
            tx.rollback();
            throw e;
        }

        if (localTx && tx.isActive()) {
            if (tx.getRollbackOnly()) {
                LOG.debug("Transaction was marked as rollback only. Rolling back...");
                tx.rollback();
            } else {
                try {
                    tx.commit();
                    LOG.trace("Committed automatic transaction");
                } catch (PersistenceException e) {
                    LOG.debug("Commit in automatic transaction context failed", e);
                    if (tx.isActive()) {
                        LOG.debug("Rolling back {}", tx);
                        tx.rollback();
                    } else {
                        LOG.debug("Can't roll back inactive transaction {}", tx);
                    }
                    throw e;
                }
            }
        } else {
            LOG.trace("Not committing non-local transaction {}", tx);
        }

        return returnValue;
    }

}