2009-10-01 4 views
1

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

  1. Я настроил свойство, добавил 2 appenders, а ConsoleAppender и RollingFileAppender.
  2. Я создал новый экземпляр журнала, используя мой основной класс: Logger mainLogger = Logger.getLogger(Main.class);
  3. У меня есть эта коллекция общего назначения, ручные, Java утилиты, в библиотеке, называется MyUtils.jar, добавляет к классам моего основного приложения. В основном приложении я вызвал статический метод от MyUtils.jar. Этот метод имеет блок try-catch {}, и там обрабатывается исключение, печатая трассировку стека, используя System.err. Теперь, используя мою IDE и ConsoleAppender, я смог обнаружить проблему, однако событие не было зарегистрировано в моем журнале файлов. Есть 2 проблемы, которые нуждаются в ответах здесь: a. В настоящее время я использую мой mainLogger для регистрации событий из всех классов моего приложения. Это хорошая практика? Или я должен использовать экземпляры X-регистратора для 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(); 
        } 
    } 
    

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


ответ

0

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

+0

Предлагаю вам удалить этот ответ и добавить его в качестве комментария к вашему вопросу. – SingleShot

+0

Я бы сделал это, если бы знал, где находится кнопка удаления здесь :-(. – 2009-10-01 22:27:30

+0

У вас нет ссылки «link | edit | delete | flag» (да, ссылки, а не кнопки) ниже ответа? –

3

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

  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(). Мне нравится то, что должен сказать this article.

+0

Спасибо за быстрый ответ. Я согласен, регистратор дает вам больше свободы. Но остается 1 вопрос, и у вас еще один вопрос :-): 1. Можно зарегистрировать выход класса Utils, используя что-то вроде Logger l = Logger.getLogger (Utils.class), вне Utils? 2. Мне действительно нужно получить вывод Sys.err/Sys.out, чтобы сохранить его в моем файле журнала настроенных для каждого приложения, независимо от класса, который генерирует этот вывод. Я проверю его slf4j, звучит здорово, однако я сомневаюсь, что скоро изменю свой регистратор ... но ... просто чтобы иметь указанный вариант в будущем .. – 2009-10-01 22:16:10

+0

Logger.getLogger (Utils.class) просто создает регистратор с именем «your.package.Utils». Он не будет перехватывать вывод каким-либо образом. Вам нужно добавить к нему записи журнала. Что касается out/err, вы можете иметь каждый журнал экземпляра приложения с log4j, используя собственный файл конфигурации или собственный файл-приложение. Также - см. Комментарий по обработке исключений, добавленный выше. – SingleShot

+0

Я предполагал, что использование Logger.getLogger (Utils.class) сделает именно это, посмотрев метод Logger.getLogger (String s). Да, я согласен, обработка исключений - слабая область для меня, но я улучшусь. Добавив 1 logger к каждому классу (допустим, в целом 2000 классов), разве это не слишком много ресурсов? Что я должен делать, если библиотека SWT, например, выбрасывает и исключает, и я этого не понимал? Приложение может закрыться, и я не знаю, почему и где это происходит :-( – 2009-10-01 22:43:18

0

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

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

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

+0

Как я вижу, люди, которые писали библиотеки, уделяют гораздо больше внимания, которые я обычно делаю, когда занимаюсь некоторыми аспектами, такими как обработка исключений И это хорошо ... это означает, что есть большое пространство для усвоения более хороших практик и падения вредных привычек. Я решил написать один класс и жестко закодировал параметры журнала. Если мне когда-либо понадобится изменить параметр, я может просто отредактировать этот файл, а не файл .properties, что даст мне лучший контроль за механизмом ведения журнала (на мой взгляд, он не должен быть настроен кем-либо). Это хорошая или плохая идея, вообще? – 2009-10-01 23:01:29

+0

Нет, я не думайте, что вы улучшаете ведение журнала с помощью своего класса. Log4J - очень хорошее решение. Ваши инстинкты хороши в том, что вы хотите, чтобы один журнал обработки журнала выполнялся. Плохая часть заключается в том, что вы должны вставлять ее в каждый класс, который хочет службы. Вот почему лучший способ пойти. Они декларативные и сквозные. – duffymo

0

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

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

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

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

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

1

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

0

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

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; 
    } 

и Вэл 0, генерируя ArithmeticException, не бросил и не поймала.

Смежные вопросы