JavaRush /Java Blog /Random-KO /자바 로깅. stectrace 공 풀기

자바 로깅. stectrace 공 풀기

Random-KO 그룹에 게시되었습니다
"안녕하세요. 오늘 산업 현장에서 사건이 기록되었습니다. 개발자에게 분석 그룹에 참여해 주시기 바랍니다." 직장에서의 하루가 이렇게 시작될 수도 있고, 아침이 될 수도 있습니다. 상관없습니다. 하지만 처음부터 시작해보자. JavaRush에서 문제를 해결함으로써 작동하고 예상되는 작업을 수행하는 코드를 작성하는 방법을 배웁니다. 도움말 섹션을 보면 이것이 항상 처음에 해결되는 것은 아니라는 것이 분명합니다. 직장에서도 마찬가지일 것이다. 처음부터 문제를 항상 해결할 수는 없습니다. 버그는 우리의 영원한 동반자입니다. 버그 이벤트를 복원할 수 있는 것이 중요합니다. 벌채 반출.  stectrace 공 풀기 - 1예부터 시작해 보겠습니다. 당신이 경찰이라고 상상해 봅시다. 귀하는 사건 현장(상점 유리가 깨짐)으로 호출되어 도착했으며, 그들은 무슨 일이 일어났는지에 대한 귀하의 답변을 기다리고 있습니다. 어디서부터 시작해야 할까요? 경찰이 어떻게 일하는지 모르겠어요. 매우 조건부로 그들은 증인, 증거 및 기타 모든 것을 찾기 시작합니다. 그 장소 자체에서 무슨 일이 일어났는지 자세히 말해 줄 수 있다면 어떨까요? 예를 들어 다음과 같습니다.
  • 21:59 주인이 알람을 켰습니다(완전히 활성화될 때까지 5분 소요)
  • 22:00 주인이 문을 닫았습니다
  • 22:05 전체 알람 활성화
  • 22:06 주인이 손잡이를 당겼다
  • 23:15 소음 센서 켜짐
  • 23:15 한 무리의 개들이 큰 소리로 짖으며 달려왔습니다.
  • 23:15 소음 센서 꺼짐
  • 01:17 진열장 외부유리 충격센서가 켜졌네요
  • 01:17 비둘기가 유리창 속으로 날아갔습니다
  • 01:17 유리가 깨졌어요
  • 01:17 사이렌 켜기
  • 01:17 비둘기가 몸을 흔들더니 날아갔습니다
글쎄, 그러한 세부 사항을 오랫동안 조사할 필요는 없으며 무슨 일이 일어났는지 즉시 알 수 있습니다. 개발도 마찬가지다. 무슨 일이 일어났는지 녹음을 통해 알 수 있다는 것은 매우 멋진 일입니다. 이제 모든 것을 디버깅할 수 있으므로 디버깅을 기억하고 있을 것입니다. 하지만. 집에 갔는데 밤에 모든 것이 고장났고 디버깅할 것이 없습니다. 고장난 이유를 이해하고 고쳐야 합니다. 이것은 로그가 작동하는 곳, 즉 밤새 일어난 모든 일의 기록입니다. 기사가 진행되는 동안 뉴스를 듣는(시청하는) 모든 사람이 들어봤을 가장 유명한 로거(실제로는 로거가 아니라 모니터링에 더 가까움) 중 하나가 무엇인지 생각해 보시기 바랍니다. 그 덕분에 일부 이벤트가 복원되었습니다. 이제 진지해 봅시다. Java에서 로그인은 코드에서 발생하는 모든 이벤트를 기록하는 프로세스입니다. 코드가 수행한 작업을 기록하는 것은 프로그래머로서 귀하의 책임입니다. 왜냐하면 분석을 위해 이러한 로그가 제공되기 때문입니다. 모든 것이 잘 완료되면 모든 버그가 매우 빠르게 정리되고 수정됩니다. 여기서는 어떤 종류의 로거가 있는지 탐구하지 않을 것입니다. 이 기사에서 우리는 단순한 것에만 국한할 것입니다 java.util.Logger. 그것은 서로를 알아가는 데 충분합니다. 각 로그 항목에는 날짜-시간, 이벤트 수준, 메시지가 포함됩니다. 날짜와 시간은 자동으로 입력됩니다. 이벤트 수준은 메시지 작성자가 선택합니다. 여러 수준이 있습니다. 주요 항목은 정보, 디버그, 오류입니다.
  • INFO - 일반적으로 이는 무슨 일이 일어나고 있는지에 대한 정보 메시지입니다. 날짜별 기록과 같은 것입니다: 1915 - 무슨 일이 일어났습니다, 1916 - 다른 일.
  • DEBUG - 특정 순간의 이벤트를 더 자세히 설명합니다. 예를 들어, 역사상 전투의 세부 사항은 디버그 수준에 있습니다." Takoytovich 사령관은 군대와 함께 Selovicha 마을을 향해 전진했습니다 ."
  • ERROR - 발생하는 오류는 일반적으로 여기에 기록됩니다. 무언가를 로 감싸면 try-catch블록이 catch로 대체된다는 것을 눈치챘을 것입니다 e.printStacktrace(). 콘솔에만 항목을 출력합니다. 로거를 사용하면 이 항목을 로거에 보낼 수 있습니다(하하). 이해가 되실 겁니다.
  • WARN - 경고가 여기에 기록됩니다. 예를 들어, 자동차의 과열된 조명입니다. 이것은 단지 경고일 뿐이며 무언가를 변경하는 것이 더 좋지만 이것은 고장이 아닙니다. 기계가 고장나면 ERROR 수준으로 기록됩니다.
레벨을 정리했습니다. 하지만 걱정하지 마세요. 둘 사이의 경계는 매우 얇습니다. 모든 사람이 설명할 수 있는 것은 아닙니다. 게다가 프로젝트마다 다를 수도 있습니다. 선임 개발자가 어떤 수준에서 무엇을 기록할지 설명할 것입니다. 가장 중요한 것은 이러한 기록이 향후 분석에 충분하다는 것입니다. 그리고 이것은 즉석에서 이해됩니다. 다음은 설정입니다. 로거는 어디에 쓸지(콘솔, 파일, jms 또는 다른 곳) 알려주고 수준(정보, 오류, 디버그...)을 지정할 수 있습니다. 간단한 로거 설정의 예는 다음과 같습니다.
handlers = java.util.logging.FileHandler, java.util.logging.ConsoleHandler

java.util.logging.FileHandler.level     = INFO
java.util.logging.FileHandler.formatter = java.util.logging.SimpleFormatter
java.util.logging.FileHandler.append    = true
java.util.logging.FileHandler.pattern   = log.%u.%g.txt

java.util.logging.ConsoleHandler.level     = INFO
java.util.logging.ConsoleHandler.formatter = java.util.logging.SimpleFormatter
이 경우 로거가 파일과 콘솔에 동시에 쓰도록 모든 것이 구성됩니다. 그렇다면? 콘솔에서 무언가가 지워지면 파일로 검색하기가 더 쉽습니다. 둘 다에 대한 INFO 수준입니다. 파일에 대한 이름 패턴도 지정됩니다. 이는 콘솔과 파일에 동시에 쓸 수 있는 최소한의 구성입니다. 파일의 이전 항목이 지워지지 않도록 truejava.util.logging.FileHandler.append 로 설정합니다 . 사용 예는 다음과 같습니다(코멘트가 없으면 로거가 자체적으로 코멘트합니다).
public class Main {
    static Logger LOGGER;
    static {
        try(FileInputStream ins = new FileInputStream("C:\\log.config")){ \\полный путь до file с конфигами
            LogManager.getLogManager().readConfiguration(ins);
            LOGGER = Logger.getLogger(Main.class.getName());
        }catch (Exception ignore){
            ignore.printStackTrace();
        }
    }
    public static void main(String[] args) {
        try {
            LOGGER.log(Level.INFO,"Начало main, создаем лист с типизацией Integers");
            List<Integer> ints = new ArrayList<Integer>();
            LOGGER.log(Level.INFO,"присваиваем лист Integers листу без типипзации");
            List empty = ints;
            LOGGER.log(Level.INFO,"присваиваем лист без типипзации листу строк");
            List<String> string = empty;
            LOGGER.log(Level.WARNING,"добавляем строку \"бла бла\" в наш переприсвоенный лист, возможна ошибка");
            string.add("бла бла");
            LOGGER.log(Level.WARNING,"добавляем строку \"бла 23\" в наш переприсвоенный лист, возможна ошибка");
            string.add("бла 23");
            LOGGER.log(Level.WARNING,"добавляем строку \"бла 34\" в наш переприсвоенный лист, возможна ошибка");
            string.add("бла 34");


            LOGGER.log(Level.INFO,"выводим все элементы листа с типизацией Integers в консоль");
            for (Object anInt : ints) {
                System.out.println(anInt);
            }

            LOGGER.log(Level.INFO,"Размер equals " + ints.size());
            LOGGER.log(Level.INFO,"Получим первый элемент");
            Integer integer = ints.get(0);
            LOGGER.log(Level.INFO,"выведем его в консоль");
            System.out.println(integer);

        }catch (Exception e){
            LOGGER.log(Level.WARNING,"что-то пошло не так" , e);
        }
    }
}
이것은 가장 좋은 예가 아닙니다. 나는 가까이에 있는 예를 취했습니다. 출력 예:
апр 19, 2019 1:10:14 AM generics.Main main
INFO: Начало main, создаем лист с типизацией Integers
апр 19, 2019 1:10:14 AM generics.Main main
INFO: присваиваем лист Integers листу без типипзации
апр 19, 2019 1:10:14 AM generics.Main main
INFO: присваиваем лист без типипзации листу строк
апр 19, 2019 1:10:14 AM generics.Main main
WARNING: добавляем строку "бла бла" в наш переприсвоенный лист, возможна ошибка
апр 19, 2019 1:10:14 AM generics.Main main
WARNING: добавляем строку "бла 23" в наш переприсвоенный лист, возможна ошибка
апр 19, 2019 1:10:14 AM generics.Main main
WARNING: добавляем строку "бла 34" в наш переприсвоенный лист, возможна ошибка
апр 19, 2019 1:10:14 AM generics.Main main
INFO: выводим все элементы листа с типизацией Integers в консоль
апр 19, 2019 1:10:14 AM generics.Main main
INFO: Размер equals 3
апр 19, 2019 1:10:14 AM generics.Main main
INFO: Получим первый элемент
апр 19, 2019 1:10:14 AM generics.Main main
WARNING: что-то пошло не так
java.lang.ClassCastException: java.lang.String cannot be cast to java.lang.Integer
	at generics.Main.main(Main.java:45)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.lang.reflect.Method.invoke(Method.java:498)
	at com.intellij.rt.execution.application.AppMain.main(AppMain.java:147)
여기서는 메모에 중점을 두고 싶습니다.
апр 19, 2019 1:10:14 AM generics.Main main
INFO: Размер equals 3
апр 19, 2019 1:10:14 AM generics.Main main
INFO: Получим первый элемент
이 항목은 매우 쓸모없고 유익하지 않습니다. 오류 항목과 같습니다.
WARNING: что-то пошло не так
이런 글을 쓰면 안 됩니다. 로그를 위한 로그이므로 방해만 될 뿐입니다. 항상 의미 있는 글을 쓰려고 노력하세요. System.out.println이 정도면 사용을 중단 하고 성인용 장난감으로 넘어가도 충분할 것 같습니다 . 단점이 있습니다 java.util.logging. 예를 들어 위에서 설명한 레벨은 여기에는 없지만 가장 많이 사용되는 로거에는 있습니다. java.util.logging이 기사에서는 연결에 대한 추가 조작이 필요하지 않기 때문에 선택했습니다 . 여기에 이미 나타난 단점 중 하나 는 LOGGER.info다음과 같습니다 . - 메시지와 개체를 전송할 수 있으며 로거 자체가 이를 아름답게 기록합니다. 동시에 메시지만 수신합니다. 예외를 전달할 수 없으므로 직접 문자열로 변환해야 합니다. 이 예제가 Java 로깅에 익숙해지기에 충분하기를 바랍니다. 그런 다음 다른 로거(log4j, slf4j, Logback...)를 연결할 수 있습니다. 많은 로거가 있지만 작업 기록을 기록하는 본질은 동일합니다. 공식 튜토리얼LOGGER.log(Level.INFO...LOGGER.log(Level.WARNING,"что-то пошло не так" , e);ExceptionLOGGER.warning("");
코멘트
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION