„Dzień dobry, dzisiaj na terenie zakładu przemysłowego zarejestrowano zdarzenie, proszę dewelopera o dołączenie do grupy analitycznej.” Jeden z Twoich dni w pracy może rozpocząć się mniej więcej w ten sposób lub może to być poranek – to nie ma znaczenia. Ale zacznijmy od początku. Rozwiązując problemy w JavaRush, uczysz się pisać kod, który działa i robi to, czego się od niego oczekuje. Jeśli spojrzysz na sekcję pomocy , jasne jest, że nie zawsze działa to za pierwszym razem. W pracy będzie tak samo. Nie zawsze rozwiążesz problem za pierwszym razem: robaki są naszymi wiecznymi towarzyszami. Ważne jest, aby można było przywrócić zdarzenia związane z błędem. Zacznijmy od przykładu. Wyobraźmy sobie, że jesteś policjantem. Wezwano Cię na miejsce zdarzenia (w sklepie rozbito szybę), przyjechałeś i czekają na Twoją odpowiedź w sprawie tego, co się stało. Gdzie zacząć? Nie wiem, jak pracuje policja. Bardzo warunkowo – zaczynają szukać świadków, dowodów i tak dalej. A co by było, gdyby samo miejsce mogło szczegółowo opowiedzieć Ci, co się wydarzyło? Na przykład tak:
- 21:59 właściciel włączył alarm (5 minut do pełnego uruchomienia)
- 22:00 właściciel zamknął drzwi
- 22:05 pełna aktywacja alarmu
- 22:06 właściciel pociągnął za klamkę
- 23:15 Włączono czujnik hałasu
- 23:15 obok przebiegła sfora psów, głośno szczekając
- 23:15 czujnik hałasu wyłączony
- 01:17 włączył się czujnik wstrząsów na zewnętrznej szybie gabloty
- 01:17 gołąb wleciał do szklanki
- 01:17 pękło szkło
- 01:17 włączona syrena
- 01:17 gołąb otrząsnął się i odleciał
java.util.Logger
: to więcej niż wystarczy, aby się poznać. Każdy wpis dziennika zawiera datę i godzinę, poziom zdarzenia i komunikat. Data i godzina są wprowadzane automatycznie. Poziom zdarzenia wybierany jest przez autora wiadomości. Istnieje kilka poziomów. Najważniejsze z nich to informacja, debugowanie, błąd.
- INFO - zazwyczaj są to komunikaty informacyjne o tym, co się dzieje, coś w rodzaju historii według dat: 1915 - coś się wydarzyło, 1916 - coś innego.
- DEBUGOWANIE - bardziej szczegółowo opisuje wydarzenia w danym momencie. Na przykład szczegóły historycznej bitwy są na etapie debugowania.” Komendant Takojtowicz ruszył ze swoją armią w kierunku wsi Selovicha .
- BŁĄD - w tym miejscu zazwyczaj zapisywane są występujące błędy. Prawdopodobnie zauważyłeś, że kiedy coś zawijasz w
try-catch
, blokcatch
jest zastępowany przeze.printStacktrace()
. Wyświetla tylko wpis do konsoli. Używając rejestratora, możesz wysłać ten wpis do rejestratora (haha), masz pomysł. - OSTRZEŻENIE – tutaj zapisywane są ostrzeżenia. Na przykład przegrzanie światła w samochodzie. To tylko ostrzeżenie i lepiej coś zmienić, ale to jeszcze nie awaria. Gdy maszyna się zepsuje, wówczas będziemy logować się z poziomem BŁĄD.
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
W tym przypadku wszystko jest skonfigurowane tak, aby logger zapisywał jednocześnie do pliku i do konsoli. W tym wypadku? jeśli coś zostanie usunięte w konsoli, a ponadto łatwiej jest wyszukiwać według plików. Poziom INFO dla obu. Dla pliku określony jest także wzorzec nazwy. Jest to minimalna konfiguracja, która pozwala na jednoczesne zapisywanie zarówno w konsoli, jak i w pliku. java.util.logging.FileHandler.append
ustaw na true , aby stare wpisy w pliku nie zostały usunięte. Oto przykład użycia (bez komentarzy, rejestrator komentuje sam siebie):
public class Main {
static Logger LOGGER;
static {
try(FileInputStream ins = new FileInputStream("C:\\log.config")){ \\полный путь до plik с конфигами
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,"Размер równa się " + 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);
}
}
}
To nie jest najlepszy przykład, wziąłem ten, który był pod ręką. Przykładowe wyjście:
апр 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: Размер równa się 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)
Tutaj chcę się skupić na notatkach:
апр 19, 2019 1:10:14 AM generics.Main main
INFO: Размер równa się 3
апр 19, 2019 1:10:14 AM generics.Main main
INFO: Получим первый элемент
Ten wpis jest zupełnie bezużyteczny i nie zawiera informacji. Podobnie jak wpis o błędzie:
WARNING: что-то пошло не так
Nie powinieneś tego pisać: to dziennik dla samego dziennika, tylko będzie przeszkadzał. Staraj się zawsze pisać sensowne rzeczy. Myślę, że to wystarczy, aby przestać go używać System.out.println
i przejść do zabawek dla dorosłych. Ma java.util.logging
wady. Przykładowo poziomów, które opisałem powyżej nie ma tutaj, ale są w większości używanych logerów. Wybrałem go do tego artykułu, java.util.logging
ponieważ nie wymaga dodatkowych manipulacji przy połączeniu. Zwrócę też uwagę, że można go zastosować LOGGER.info
zamiast. LOGGER.log(Level.INFO...
Jedna z wad już się tu pojawia: LOGGER.log(Level.WARNING,"что-то пошло не так" , e);
- pozwala na przesłanie wiadomości i obiektu Exception
, sam rejestrator pięknie to zapisze. Jednocześnie LOGGER.warning("");
odbiera jedynie komunikat, tj. Wyjątku nie można przekazać, musisz samodzielnie przetłumaczyć go na ciąg znaków. Mam nadzieję, że ten przykład wystarczy, aby zapoznać się z logowaniem w Javie. Następnie możesz podłączyć inne rejestratory (log4j, slf4j, Logback...) - jest ich wiele, ale istota jest ta sama^, aby rejestrować historię działań. Oficjalny poradnik
GO TO FULL VERSION