У меня есть какая-то ошибка в производственном приложении, но я не могу найти причину этого. Я пытаюсь получить какой-нибудь журнал, чтобы найти метод, который вызывает мой method(). Но так как я использую threadPool, я не могу просто получить Thread.currentThread().getStackTrace() и перебрать StackTraceElements, он показывает только несколько строк перед ThreadPool. Если я воспользуюсь следующим кодом, я получу каждый метод, который мне нужен, но он очень дорогой. Только 1 вызов метода стоил 400+ Кбайт в текстовом файле в моей тестовой среде. Я думаю, что в производстве это будет около 1 Мб в секунду.

private final ExecutorService completableFutureExecutor =
            new ThreadPoolExecutor(10, 2000, 60L, TimeUnit.SECONDS, new SynchronousQueue<>());

public void firstMethod(){

    secondMethod();    
}

private CompletableFuture<Void> secondMethod(){

    return CompletableFuture.supplyAsync(()->method(),threadPool);

}

void method(){
    Map<Thread, StackTraceElement[]> map = Thread.getAllStackTraces();
        for (Thread thread : map.keySet()) {
            printLog(thread);
        }
}
private void printLog(Thread thread) {
        StringBuilder builder = new StringBuilder();
        for (StackTraceElement s : thread.getStackTrace()) {
            builder.append("\n getClass = " + s.getClass());
            builder.append("\n getClassName = " + s.getClassName());
            builder.append("\n getFileName = " + s.getFileName());
            builder.append("\n getLineNumber = " + s.getLineNumber());
            builder.append("\n getMethodName = " + s.getMethodName());
            builder.append("\n  ---------------------------- \n ");
        }
        ownLogger.info("SomeThread = {} ", builder);
    }

Как найти того firstMethod(), который звонит secondMethod()?

0
Dred 16 Апр 2019 в 11:57

2 ответа

Лучший ответ

Поскольку я не нашел ни одного хорошего решения, я бы поставил регистратор до и после вызова CompletableFuture

Это выглядит как

Logger beforeAsync= LoggerFactory.getLogger("beforeAsync");
Logger afterAsync= LoggerFactory.getLogger("afterAsync");

private CompletableFuture<Void> secondMethod(){
    printLongerTrace(Thread.currentThread(),beforeAsync);
    return CompletableFuture.supplyAsync(()->method(),threadPool);
}

private void methodWithException(){
    try{
    //do something
    }
    catch(Exception e){ 
      printLongerTrace(e,"methodWithException", afterAsync);
    }
}

public void printLongerTrace(Throwable t, String methodName, Logger ownlogger) {

    if (t.getCause() != null) {
        printLongerTrace(t.getCause(), methodName, fields, ownlogger);
    }
    StringBuilder builder = new StringBuilder();
    builder.append("\n Thread = " + Thread.currentThread().getName());
    builder.append("ERROR CAUSE = " + t.getCause() + "\n");
    builder.append("ERROR MESSAGE = " + t.getMessage() + "\n");

    printLog(t.getStackTrace(), builder);
    ownlogger.info(methodName + "Trace ----- {}", builder);
}

public void printLongerTrace(Thread t, Logger ownlogger) {

    StringBuilder builder = new StringBuilder();
    builder.append("\n Thread = " + Thread.currentThread().getName());

    printLog(t.getStackTrace(), builder);
    ownlogger.info("Trace ----- {}", builder);
}

private StringBuilder printLog(StackTraceElement[] elements, StringBuilder builder) {

    int size = elements.length > 15 ? 15 : elements.length;

    for (int i = 0; i < size; i++) {
        builder.append("Line " + i + " = " + elements[i] + "   with method = " + elements[i].getMethodName() + "\n");
    }
    return builder;
}

printLongerTrace(Throwable t, String methodName, Logger ownlogger) необходимо распечатать исключение при каждой причине в рекурсии.

printLongerTrace(Thread t, Logger ownlogger) необходимо распечатать вызов какого метода перед CompletableFuture

0
Dred 17 Апр 2019 в 07:15

Просто выгрузите стек, вызвав Thread.dumpStack(), но это только для отладки и имеет большие накладные расходы, поскольку выгрузка стека требует много ресурсов процессора

-1
Starmixcraft 16 Апр 2019 в 09:04