Извлечение удобных для пользователя деталей исключений в Java - PullRequest
3 голосов
/ 07 мая 2010

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

Будет ли лучше использовать e.getMessage() для входа? Спасибо.

Ответы [ 5 ]

3 голосов
/ 08 мая 2010

Я сделал что-то очень похожее. Но, во-первых, вам вообще не нужно передавать сообщение об ошибке пользователю. Нет смысла рассказывать им, как произошла ошибка, так как вы все равно будете ее регистрировать. (Имеет ли смысл, если пользователь знает, что ошибка произошла из-за NPE или ошибки ввода-вывода, даже если вы переименуете ее в более «дружественные» термины)?

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

    try{
        conn.close();
    } catch(SQLException ex){
        //logger.error("Cannot close connection"); //don't log this here, do it centrally
        throw new RuntimeException(ex);
    }

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

<error-page>
  <error-code>500</error-code>
  <location>/Error.jsp</location>
</error-page>

Далее на странице error.jsp (или в сервлете) зарегистрируйте ошибку здесь, если ваш контейнер позволяет ссылаться на трассировку стека как request.getAttribute("javax.servlet.error.message"));.

ИЛИ , создайте фильтр, который действует только на ответ, и выполните следующие действия:

try {
    chain.doFilter(req, res);
 } catch (Exception e) {
    logger.error("pass any Mapped Diagnostic Context here", e); //log here, centrally
    throw new RuntimeException(e); //throws back to the container so that the error page will be seen
}

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

  1. Точный (один журнал на экземпляр ошибки)
  2. Надежно (если пользователь получил ошибку, вы получите данные регистрации
  3. Непротиворечивый (стандартизированный, если вы реализуете повторную передачу проверенных исключений как непроверенную, вы сможете увидеть все исключения, а также запретить пользователям перемещаться по подверженной ошибкам территории, где вы рискуете выполнить катастрофические миссии по очистке данных, потому что они вставили дерьмо в таблицы или таблицы ключей слева не заселены)

Наконец, вы можете рассмотреть возможность использования log4j и использования приложения, которое выводит куда-то, что вы можете просмотреть ошибки, не дожидаясь, пока операционные команды отправят их вам. Гораздо проще, если вы регулярно поддерживаете приложение.

3 голосов
/ 07 мая 2010

Возможно. Проблема в том, что, по крайней мере, без информации о методе вызова, это не очень полезно

Рассмотрим что-то вроде следующего

/**
 * Returns <i>class.method:linenumber</i> of the caller (or, more accurately
 * the caller of the caller).
 * </p>
 *
 * <p>
 * Returns unknown if stacktrace is mucked up. Uses reflection and string
 * concatenation, so don't overuse this for trivial matters. For exception
 * handling and for logging, on the other hand, it is useful.
 *
 * @return method name of caller's caller and line number (String)
 */
public static String returnCaller( Class ignoreMe )
{

    String              ignoreClass = ignoreMe.getName();
    StackTraceElement[] steArr      = new Throwable().getStackTrace();

    if (steArr != null)
    {
        // subscript 1 is returnCaller().
        // subscript 2 is the caller of returnCaller()
        // subscript 3 is the caller of the caller of returnCaller()...
        for( int i = 0; i < steArr.length; i++)
        {
            if (steArr[i] == null)
                break;

            String myclass = steArr[i].getClassName();

            if (myclass.equals(ErrorHandle.class.getName()))
                continue;

            if (ignoreClass.equals(myclass))
                continue;

            return steArr[i].getClassName()
                    + "."
                    + steArr[i].getMethodName()
                    + ":"
                    + steArr[i].getLineNumber();
        }
    }

    return "unknown";
}
2 голосов
/ 07 мая 2010

Регистрация только сообщения об исключении - не очень хорошая идея; вы теряете строку, в которой произошло исключение, что в большинстве случаев делает зарегистрированное исключение в коде кошмарным.

Записать всю исключительную ситуацию / трассировку стека.

1 голос
/ 07 мая 2010

Я по умолчанию получаю всю трассировку стека, таким образом я могу видеть больше контекста того, что происходило, когда произошла ошибка.

Если вы используете log4j и передаете исключение в один из методов ведения журнала, оно напечатает любое сообщение, которое вы ему дадите, плюс сообщение об исключении и его трассировку стека:

log.error("caught an exception", throwable);

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

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

0 голосов
/ 07 мая 2010

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...