@CompileStatic
@Phase(CompilePhase.SEMANTIC_ANALYSIS)
class TymitTraceTransformation extends AbstractLocalTransformation<TymitTrace, MethodNode> {
static private List pool = ['a'..'z', 'A'..'Z', '0'..'9', '_'].flatten()
@Override
void doVisit(final AnnotationNode annotation, final MethodNode methodNode) {
def oldCode = methodNode.code
def className = methodNode.declaringClass.name
def methodName = methodNode.name
def parameters = Utils.NODE.get(annotation, 'value', String) ?: ''
def rand = new Random(System.currentTimeMillis())
def randomVariableName = '_' + (0..10).collect { pool[rand.nextInt(pool.size())] }.join('')
methodNode.code = blockS(
declareMeterMethod(randomVariableName, className, methodName),
declareClosure(randomVariableName, parameters.split(','), meter),
tryCatchSBuilder()
.tryStmt(
oldCode
)
.finallyStmt(
callFinish(randomVariableName)
)
.build()
)
}
// generamos código similar a
// def _a12BadF123 = new MeterMethod('BusinessService', 'calculoCostoso')
Statement declareMeterMethod(String randomVariableName, String className, String methodName) {
stmt(varDeclarationX(randomVariableName, MeterMethod,
newX(MeterMethod, constX(className), constX(methodName))
))
}
// generamos código similar a
/**
def _a12BadF123Closure = {
_a12BadF123.addTag('param1', param1)
_a12BadF123.addPayload()
log.info _a12BadF123.toString()
_a12BadF123.removePayload()
}*/
Statement declareClosure(String randomVariableName, String[] parameters, Boolean meter) {
String closureStr = parameters.findAll { it }.collect { String p ->
"${randomVariableName}.addTag('$p',$p)"
}.join('\n')
closureStr += """
${randomVariableName}.addPayload()
log.info ${randomVariableName}.toString()
${randomVariableName}.removePayload()
"""
Statement closure = blockSFromString(closureStr)
stmt(varDeclarationX(randomVariableName + 'Closure', Closure, closureX(closure)))
}
// generamos código similar a :
// _a12BadF123Closure.call()
Statement callFinish(String randomVariableName) {
stmt(callX(varX("${randomVariableName}Closure"), 'call'))
}
}