Log4J - как записать исключение, пойманное в импортированной библиотеке? - PullRequest
1 голос
/ 02 октября 2009

Я довольно новый пользователь Log4J v. 1.2.15, поскольку мой друг убедил меня в преимуществах по сравнению с консолью или другими формами ведения журнала. Однако, поскольку я делал некоторые тесты, я столкнулся с тестовым примером, который заставил меня задуматься. Вот что я сделал:

  1. Я настроил свойства, добавил 2 приложения, ConsoleAppender и RollingFileAppender.
  2. Я создал новый экземпляр журнала, используя мой основной класс: Logger mainLogger = Logger.getLogger(Main.class);
  3. У меня есть эта коллекция утилит java общего назначения, сделанных вручную, в библиотеке, которая называется MyUtils.jar, добавлено в classpath моего основного приложения. В основном приложении я вызвал статический метод из MyUtils.jar. У этого метода есть блок try-catch {}, и там была обработана исключительная ситуация, которая выводит трассировку стека с использованием System.err. Теперь, используя мою IDE и ConsoleAppender, я смог обнаружить проблему, однако событие НЕ было зарегистрировано в моем файловом журнале. Здесь есть 2 проблемы, на которые нужно найти ответы: a. В настоящее время я использую mainLogger для записи событий из всех классов моего приложения. Это хорошая практика? Или я должен использовать экземпляры X logger для X классов? b. Что я могу сделать, чтобы иметь возможность регистрировать ошибки, уже обнаруженные при импорте? Это может звучать тривиально, но я использовал Object foo = MyLibrary.composeObjectFoo(), и внутри метод выглядит аналогично этому примеру:

    public static Object composeObjectFoo() {
        try {
            .....statements.....
            .
            .
            //    something stupid here
            int a = 100/0; //an AritmethicException will be thrown 
        } catch Exception(e) {
            e.printStackTrace();
        }
    }
    

Спасибо за ваши ответы и, пожалуйста, извините за длину этого ...


Ответы [ 6 ]

3 голосов
/ 02 октября 2009

Есть несколько вещей, которые я рекомендую для ведения журнала:

  1. Никогда не используйте System.out.println(), System.err.println() или e.printStackTrace(). Вместо этого используйте регистратор. Вместо этого вы можете настроить регистратор на печать в stdout или stderr, не говоря уже о фильтрации неважной информации. Гораздо более гибкий.
  2. Лучше всего создать регистратор в каждом классе, который может генерировать события, которые вы хотите зарегистрировать, и использовать этот класс для создания имени регистратора (например, Logger.getLogger(Main.class)). Сделав это, вы сможете использовать все эти уникальные имена регистраторов для точной настройки фильтрации журналов. Например, вы можете установить класс A на debug и класс B на info, если необходимо.
  3. Используйте слой абстракции логгера, такой как slf4j (мне это очень нравится) или commons-logging. Это позволит вам изменить реализацию вашего регистратора без необходимости проходить через весь ваш код и менять каждое место, откуда вы входите.

Относительно исключений:

Я также рекомендую вам немного ознакомиться с рекомендациями по обработке исключений. Все будут спорить о том, что является «лучшим», но все должны согласиться с тем, что вы должны сделать больше, чем позволить всему просочиться до main(). Мне нравится, что говорит эта статья .

1 голос
/ 02 октября 2009

В своем основном классе вы можете изменить System.out и System.err для печати потоков, которые берут то, что напечатано, и передают их в регистратор. Это немного сложнее, чем кажется, но это было сделано в проектах с открытым исходным кодом (например, у JBoss есть реализация), поэтому вы можете узнать, как это сделать.

0 голосов
/ 04 октября 2009

ОК, после дополнительной документации я наткнулся на это решение, чтобы регистрировать все, независимо от того, находится ли источник в вашем коде где-то еще:

Thread.setDefaultUncaughtExceptionHandler(new UncaughtExceptionHandler() {
    @Override
    public void uncaughtException(Thread t, Throwable exc) {
              //do something about it
              }
        });

Таким образом, я смог отловить и сообщить о ненормальном состоянии, которое возникает в импортированной библиотеке, но не было обработано или повторно обработано. Это случай чего-то глупого типа

   public double computeValue(int val){
      double a = 15/val;
     return a;
   }

и val был 0, создавая ArithmeticException, не выброшенный и не перехваченный.

0 голосов
/ 02 октября 2009

а. Я в настоящее время использую мой mainLogger регистрировать события из всех классов моего приложение. Это хорошая практика? Или же я должен использовать экземпляры X logger для X классы?

Как правило, лучше создать и использовать несколько Logger. Это дает вам (или кому-то, кто придет позже) более точный контроль над уровнями ведения журнала и т. Д. Через конфигурацию ведения журнала. Но я бы не рекомендовал создавать (статический) экземпляр Logger в каждом классе.

б. Что я могу сделать, чтобы иметь возможность войти ошибки уже обнаружены в моем импорте?

Мало что можно с этим поделать ... кроме как пересмотреть импортированную кодовую базу, чтобы улучшить ее внутренние отчеты об ошибках и ведение журнала.

С другой стороны, если вы создаете библиотечный код, который может быть повторно использован в другом месте, вам следует обратить внимание на правильное составление отчетов об ошибках и ведение журнала. В частности, вычеркните нецелевое использование System.err, printStackTrace() и так далее. Также неплохо использовать уровень абстракции журналирования, чтобы у людей не возникало проблем при интеграции вашей библиотеки.

0 голосов
/ 02 октября 2009

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

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

Мне не нравится идея, что основной класс ведет журналирование. Ваш инстинкт хорош, а ваша реализация - нет. Ведение журнала является сквозной задачей, которая должна выполняться с использованием аспектно-ориентированного программирования.

0 голосов
/ 02 октября 2009

Я сделал одну логическую вещь ... я удалил блок try-> catch {} из моего класса Utils. Созданное исключение теперь было перехвачено основным приложением и зарегистрировано. Потрясающие! Но ... есть ли гарантии, что ситуация не повторится при использовании libs / utils, созданных третьими участниками?

...