TracerAspect.java

130 lines | 5.177 kB Blame History Raw Download
/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */
package br.ufrgs.inf.prosoft.applicationtracer;

import br.ufrgs.inf.prosoft.jsonserialiser.JSONSerialiser;
import br.ufrgs.inf.prosoft.trace.Parameter;
import br.ufrgs.inf.prosoft.trace.Return;
import br.ufrgs.inf.prosoft.trace.Trace;
import br.ufrgs.inf.prosoft.trace.TraceConcrete;
import java.io.FileWriter;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;

/**
 *
 * @author romulo
 */
@Aspect
public class TracerAspect {

    @Pointcut("execution(!void *(..))")
    public void anyMethodExecution() {
    }

    @Around("anyMethodExecution()")
    public Object serializeMethodCall(ProceedingJoinPoint joinPoint) throws Throwable {
        long startTime = System.currentTimeMillis();
        Object proceed = joinPoint.proceed();
        long endTime = System.currentTimeMillis();
        if (startTime == endTime) {
            return proceed;
        }
        String blacklistPath = System.getenv("TRACER_BLACKLIST");
        if (blacklistPath == null) {
            blacklistPath = "./blacklist";
        }
        List<String> blacklist;
        try {
            blacklist = Files.readAllLines(Paths.get(blacklistPath));
        } catch (IOException ex) {
            blacklist = new ArrayList<>();
        }
        try {
            String longsignature = joinPoint.getSignature().toLongString();
            if (blacklist.contains(longsignature)) {
                System.out.println("[ApplicationTracer] skipping " + longsignature);
                return proceed;
            }
            boolean verbose = endTime - startTime > 5;
            if (verbose) {
                String verboseTracer = System.getenv("TRACER_VERBOSE");
                if (verboseTracer == null) {
                    verboseTracer = "true";
                }
                if (verboseTracer.equals("false")) {
                    verbose = false;
                }
            }
            if (verbose) {
                System.out.print("[ApplicationTracer] tracing " + longsignature + " ... ");
            }
            String[] split = longsignature.substring(0, longsignature.length() - 1).split("\\(");
            String[] modifiersReturnAndName = split[0].split(" ");
            String[] modifiers = Arrays.copyOf(modifiersReturnAndName, modifiersReturnAndName.length - 2);
            String methodName = modifiersReturnAndName[modifiersReturnAndName.length - 1];
            String returnType = modifiersReturnAndName[modifiersReturnAndName.length - 2];
            List<Parameter> parameters = new ArrayList<>();
            if (split.length > 1) {
                String[] parameterTypes = split[1].split(", ");
                Object[] parametersData = joinPoint.getArgs();
                for (int i = 0; i < parametersData.length; i++) {
                    parameters.add(new Parameter(parameterTypes[i], parametersData[i]));
                }
            }
            Return returnValue = new Return(returnType, proceed);
            String instance;
            try {
                instance = String.valueOf(joinPoint.getThis().hashCode());
            } catch (Exception ex) {
                instance = "s";
            }
            String userId = getUserId();
            Trace trace = new TraceConcrete(instance, Arrays.asList(modifiers), returnValue, methodName, parameters, startTime, endTime, userId);
            String tracesPath = System.getenv("TRACER_TRACES");
            if (tracesPath == null) {
                tracesPath = "./traces";
            }
            synchronized (TracerAspect.class) {
                if (verbose) {
                    System.out.print(System.currentTimeMillis() + " ... ");
                }
                String jsonTrace = JSONSerialiser.serialiseAcyclicObject(trace);
                jsonTrace += "\n";
                System.out.println("[ApplicationTracer] serialised " + System.currentTimeMillis());
                try (FileWriter fileWriter = new FileWriter(tracesPath, true)) {
                    fileWriter.write(jsonTrace);
                }
                if (verbose){
                    System.out.println(System.currentTimeMillis());
                }
            }
        } catch (Exception ex) {
            System.err.println("[ApplicationTracer] exception: " + ex);
        }
        return proceed;
    }

    private String getUserId() {
        try {
            Object contextHolder = Class.forName("org.springframework.security.core.context.SecurityContextHolder").newInstance();
            Object context = contextHolder.getClass().getMethod("getContext").invoke(contextHolder);
            Object auth = context.getClass().getMethod("getAuthentication").invoke(context);
            return (String) auth.getClass().getMethod("getName").invoke(auth);
        } catch (Exception ex) {
            return "";
        }
    }
}