/**
* (c) Copyright 2013 WibiData, Inc.
*
* See the NOTICE file distributed with this work for additional
* information regarding copyright ownership.
*
* 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.kiji.mapreduce.util;
import java.util.concurrent.ConcurrentHashMap;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.ProceedingJoinPoint;
import org.kiji.annotations.ApiAudience;
import org.kiji.annotations.ApiStability;
import org.kiji.schema.util.LoggingInfo;
/**
* Aspect to measure encoding and decoding of Kiji cells and time spent
* accessing the meta table.
*/
@ApiAudience.Framework
@ApiStability.Experimental
@Aspect
public class MRLogTimerAspect {
/**
* The ConcurrentHashMap containing information about a function call, the aggregate
* time spent within this function and the number of times it was invoked.
*/
private ConcurrentHashMap<String, LoggingInfo> mSignatureTimeMap = null;
/**
* Default constructor.
*/
protected MRLogTimerAspect() {
mSignatureTimeMap = new ConcurrentHashMap<String, LoggingInfo>();
}
/**
* Get the HashMap of functions to information stored about them.
*
* @return HashMap containing function calls and time spent in them.
*/
public ConcurrentHashMap<String, LoggingInfo> getSignatureTimeMap() {
return mSignatureTimeMap;
}
/**
* Advice around functions that match PointCut "profile".
*
* @param thisJoinPoint The JoinPoint that matched the pointcut.
* @return Object returned by function which matched PointCut "profile".
* @throws Throwable if there is an exception in the function the advice surrounds.
*/
@Around("execution(* org.kiji.mapreduce.impl.HFileWriterContext.put(..)) || "
+ "execution(* org.kiji.mapreduce.framework.KijiTableInputFormat.KijiTableRecordReader.nextKeyValue(..))")
public Object aroundProfileMethods(final ProceedingJoinPoint thisJoinPoint) throws Throwable {
final long start, end;
start = System.nanoTime();
Object returnanswer = thisJoinPoint.proceed();
end = System.nanoTime();
String funcSig = thisJoinPoint.getSignature().toLongString();
final LoggingInfo existing =
mSignatureTimeMap.putIfAbsent(funcSig, new LoggingInfo(end - start, 1));
if (existing != null) {
existing.increment(end - start);
}
return returnanswer;
}
}