Logger своими руками

Разрабатывая приложение и пытаясь улучшить код, приходится разбивать функционал приложения на большое количество классов. Каждый класс содержит методы. Каждый метод для его лучшего понимания должен содержать не очень много кода. В результате такого разбиения получаются ситуации когда один метод одного класса вызывает метод второго класса, а тот в свою очередь другой метод третьего класса и так далее. Отследить затем, кто кого вызвал бывает сложновато. Возможно конечно продебажить код, но иногда в дебаге всего не увидишь и нужен «реальный» проход по методам. Причем при таком реальном проходе необходимо отследить весь стэк вызовов методов классов и отобразить значения требуемых переменных и полей. При разработке приложения у меня возникла такая необходимость – отследить какой метод какого класса что вызывает. Для этого я написал простой логер. Конечно, можно было использовать уже известные, но так не хотелось разгребаться с ними, настраивать и подключать к своему приложению.

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

Рассмотрим методы логера. Метод log просто выводит сообщение в консоль. Возможно конечно переписать его, чтобы вывод осуществлялся в файл например. Метод openStack. Он как бы «открывает стэк» и говорит, что все последующие показы лог сообщений прибавят в отступе. Это нужно для того, чтобы человеческому глазу проще было видно, что внутри такого то метода произошли такие то вызовы. Далее я приведу пример вывода логера, в котором всё станет понятно. Есть еще один метод openStack, только уже со строковым параметром. Этот метод делает тоже самое, что и предыдущий, но в добавок к этому еще и выводит лог сообщение «во главе» стэка. Далее следуют методы для закрытия стэка — closeStack. Они делают отступ меньше. Метод logIntoStack выводит сообщение внутри стэка. Методы enable и disable говорят, отображать лог сообщения или нет — не бегать же в конце концов по всем методам и не вылавливать оттуда вызовы нашего логера. Для этого в начале работы приложения вызовем disable и консоль будет чиста. И последний метод setShowLineNumbers — говорит логеру, показывать строчки с порядковыми номерами или нет. Номера строк бывают очень удобными, так как привносят некий порядок и позволяют легко идентифицировать требуемую строку.

Посмотрим простой пример использования логера. Пример из моего приложения. Здесь мы в начале метода вызываем Logger.openStack и передаем сообщения для показа. Удобно передавать строку, у которой вначале идет название класса, а затем название метода. Так, глядя в логи приложения, можно сразу же понять, где произошел вызов.

public void valueChanged(TreeSelectionEvent e) {
     Logger.openStack("ActiveTreeNodeListener: valueChanged()");
     
     TreePath path = tree.getSelectionPath();
     ITreeNode selectedNode = null;
     if (path != null && !tree.isSelectionEmpty()) {
          selectedNode = (ITreeNode) path.getLastPathComponent();
     }

     …

     Logger.closeStack();
}

Мне кажется, что вывод очень наглядный и информативный. Ниже представлен примерный вывод логера.

21     ActiveTreeNodeListener: valueChanged()
22          DBTreeModel: setOpenedNode()
23          DBTreeModel: setActiveNode()
24          DBTreeModel: fireChangeOpenedNode()
25               CustomListModel: openedNodeWasChanged()
26          DBTreeModel: fireChangeActiveNode()
27               ActionManager: activeNodeWasChanged()
28               ListItemsChangingListener: activeNodeWasChanged()
29                    activeNode is not null
30                    clear selection

Ну и собственно исходный код самого логгера.

public class Logger {
     
     private static int depth = 0;
     private static int lineNumber = 0;
     private static boolean isEnabled = false;
     private static boolean showLineNumbers = false;
     
     public synchronized static void log(String message) {
          if(isEnabled) {
               if(showLineNumbers) {
                    System.out.println(lineNumber++ + message);                    
               } else {
                    System.out.println(message);
               }
          }                    
     }
     
     public synchronized static void openStack() {
          if(isEnabled) {
               depth++;                              
          }          
     }
     
     public synchronized static void openStack(String message) {
          if(isEnabled) {
               depth++;
               log(getTabs() + message);               
          }          
     }
     
     public synchronized static void closeStack(String message) {
          if(isEnabled) {
               log(getTabs() + message);
               depth—;               
          }          
     }
     
     public synchronized static void closeStack() {
          if(isEnabled) {               
               depth—;               
          }          
     }
     
     public synchronized static void logIntoStack(String message) {
          if(isEnabled) {
               depth++;
               log(getTabs() + message);
               depth—;
          }                              
     }
     
     private static String getTabs() {
          String tabs = "";
          for(int i = 1; i <= depth; i++) {
               tabs += "\t";               
          }          
          return tabs;
     }
     
     public static void enable() {
          isEnabled = true;
     }
     
     public static void disable() {
          isEnabled = false;
     }
     
     public static void setShowLineNumbers(boolean newValue) {
          showLineNumbers = newValue;                    
     }
}

Добавить комментарий

Заполните поля или щелкните по значку, чтобы оставить свой комментарий:

Логотип WordPress.com

Для комментария используется ваша учётная запись WordPress.com. Выход / Изменить )

Фотография Twitter

Для комментария используется ваша учётная запись Twitter. Выход / Изменить )

Фотография Facebook

Для комментария используется ваша учётная запись Facebook. Выход / Изменить )

Google+ photo

Для комментария используется ваша учётная запись Google+. Выход / Изменить )

Connecting to %s

%d такие блоггеры, как: