Вход Java: покажите исходный номер строки вызывающей стороны (не регистрирующийся вспомогательный метод)

В основном узел в Вашем графике должен не только представить местоположение, но также и самое раннее время, которое можно получить там. Можно думать о нем как об исследовании графика в (место, время) пространство. Кроме того, если Вы имеете (место, t1) и (место, t2) где t1< t2, отбрасывание (место, t2).

Теоретически, это получит самое раннее время поступления для всех возможных мест назначения от Вашего стартового узла. На практике Вам нужна некоторая эвристика для сокращения дорог, которые берут Вас слишком далеко от Вашего места назначения.

Вам также нужна некоторая эвристика для рассмотрения многообещающих маршрутов перед менее многообещающими - если маршрут уводит от места назначения, это менее вероятно (но не полностью вряд ли) быть хорошим.

43
задан skaffman 17 May 2012 в 15:18
поделиться

6 ответов

Альтернативный ответ.

Можно попросить log4j исключить вспомогательный класс с помощью метода

Category.log (String callerFQCN, Priority level, Object message, Throwable t)

и указав вспомогательный класс как 'callerFQCN'.

Например, вот класс, использующий помощник:

public class TheClass {
    public static void main(String...strings) {
        LoggingHelper.log("Message using full log method in logging helper.");
        LoggingHelper.logNotWorking("Message using class info method");
}}

и код помощника:

public class LoggingHelper {
private static Logger LOG = Logger.getLogger(LoggingHelper.class);

public static void log(String message) {
    LOG.log(LoggingHelper.class.getCanonicalName(), Level.INFO, message, null);
}

public static void logNotWorking(String message) {
    LOG.info(message);
} }

Первый метод выдаст ожидаемый результат.

Line(TheClass.main(TheClass.java:4)) Message using full log method in logging helper.
Line(LoggingHelper.logNotWorking(LoggingHelper.java:12)) Message using class info method

При использовании этого метода Log4j будет работать как обычно, избегая вычисления трассировки стека, если это не требуется.

34
ответ дан 26 November 2019 в 23:07
поделиться

Добавление деталей в ответ KLE. (извините, пользователь noob, не знаю лучшего способа, чем создать отдельный ответ)

Вместо того, чтобы прикреплять номер строки к сообщению, вы можете поместить его в контекст MDC. См. Org.apache.log4j.MDC

Например:

StackTraceElement[] stackTraces = Thread.currentThread().getStackTrace();
StackTraceElement stackTraceElement = ...;
int l = stackTraceElement.getLineNumber();

MDC.put("myLineNumber", l);

Это позволяет пользователям использовать mylineNumber в их файле конфигурации log4j

<layout class="org.apache.log4j.PatternLayout">
    <param name="ConversionPattern" 
           value="Line(%X{myLineNumber})- %m%n"/>
</layout>

Примечание: это позволяет пользователю контролировать, где и как номер строки появляется в сообщении. Однако, поскольку получение трассировки стека очень дорого, вам все равно нужно найти способ отключить эту функцию.

2
ответ дан 26 November 2019 в 23:07
поделиться

Обратите внимание, что указывать номер строки очень дорого , либо для того, что вы получаете естественным образом от Log4j, либо для следующего. Вы должны принять эту стоимость ...

Вы можете использовать следующие API:

    StackTraceElement[] stackTraces = Thread.currentThread().getStackTrace();
    StackTraceElement stackTraceElement = ...;
    stackTraceElement.getLineNumber();

Обновлено:

Вам придется рассчитать ее самостоятельно. Итак:

  • попросите log4j не выводить его (в вашем формате ведения журнала),
  • и вставьте себе указание номера строки в начало вашего сообщения (строка, которую вы отправляете в log4j).

В зависимости от того, как вы предпочитаете ваши регистраторы, ваш вспомогательный метод может:

  • используйте явный регистратор (я полагаю, переданный как параметр), когда это необходимо (мы иногда определяем определенные регистраторы для конкретного контекста; например, у нас есть регистратор для отправки запросов к нашей базе данных, независимо от того, какой класс это делает; это позволяет чтобы сократить до одного места изменения, внесенные в наш файл конфигурации, когда мы хотим (де-) активировать их ...)
  • используйте регистратор для вызывающего класса: в этом случае вместо передачи параметра , вы можете вывести имя класса вызывающего аналогичным образом ...
5
ответ дан 26 November 2019 в 23:07
поделиться

Это невозможно из коробки. Лучшее, что вы можете сделать в этом случае, - это создать регистратор в вызывающей программе и передать его методу util. Таким образом, вы сможете хотя бы понять, откуда поступил звонок.

1
ответ дан 26 November 2019 в 23:07
поделиться

Если у вас есть собственные служебные методы ведения журнала, вы можете добавить номер и имя файла в список аргументов ведения журнала и выбрать путь cpp. т.е. предварительно обработайте исходный код для замены тегов, таких как _ LINE _ и ​​_ FILE _, прежде чем выполнять компиляцию. В качестве дополнительного бонуса это не потребует столько ресурсов, сколько вычисление во время выполнения.

1
ответ дан 26 November 2019 в 23:07
поделиться

Возможно, вы сможете реализовать вспомогательную функцию журнала с помощью элемента трассировки стека, получить номера строк и обойти фреймы с помощью метода с некоторыми конкретными аннотациями, например,

public @interface SkipFrame {}

// helper function
@SkipFrame // not necessary on the concrete log function
void log(String... message) {
    // getStackTrace()...
    int callerDepth = 2;  // a constant number depends on implementation
    StackTraceElement callerElement = null; 
    for (StackTraceElement e: stackTrace) {
         String className, methodName = e.getClassName, getMethodName()...
         Class callClass = Class.forName(className);
         // since there maybe several methods with the same name
         // here skip those overloaded methods
         Method callMethod = guessWhichMethodWithoutSignature(callClass, methodName);
         SkipFrame skipFrame = callMethod.getAnnotation(SkipFrame.class); 
         if (skipFrame != null)
             continue; // skip this stack trace element
         if (callerDepth-- == 0) {
             callerElement = e; 
             break;
         }
     }
     assert callerDepth == 0; 
     assert callerElement != null;
     Log4j.info(callerElement.getLineNumber()... + "message... "); 
}

@SkipFrame
void logSendMail(Mail mailObject) {
    log("Send mail " + mailObject.getSubject()); 
}

Таким образом, если помощник функция является вложенной, или есть более используемые вспомогательные функции, просто отметьте аннотацию SkipFrame на всех из них, и вы получите правильный номер строки исходного текста, который вам действительно нужен.

0
ответ дан 26 November 2019 в 23:07
поделиться
Другие вопросы по тегам:

Похожие вопросы: