"Good afternoon, today an incident was recorded at the industrial site, I ask the developer to join the analysis group." One of your days at work could start something like this, or it could be the morning – it doesn’t matter. But let's start from the beginning. By solving problems here in JavaRush, you learn to write code that works and does what is expected of it. If you look at the help section , it is clear that this does not always work out the first time. It will be the same at work. You won’t always solve a problem the first time: bugs are our eternal companions. It is important that you can restore the events of the bug. Let's start with an example. Let's imagine that you are a policeman. You were called to the scene of the incident (glass was broken in a store), you arrived, and they are waiting for answers from you about what happened. Where to begin? I don't know how the police work. Very conditionally - they start looking for witnesses, evidence and all that stuff. What if the place itself could tell you in detail what happened? For example, like this:
- 21:59 owner turned on the alarm (5 minutes until fully activated)
- 22:00 owner closed the door
- 22:05 full alarm activation
- 22:06 owner pulled the handle
- 23:15 noise sensor turned on
- 23:15 a pack of dogs ran past, barking loudly
- 23:15 noise sensor switched off
- 01:17 the shock sensor on the outer glass of the display case turned on
- 01:17 a pigeon flew into the glass
- 01:17 glass broke
- 01:17 siren on
- 01:17 the pigeon shook itself off and flew away
java.util.Logger
: it is more than enough for getting to know each other. Each log entry contains date-time, event level, message. The date and time are entered automatically. The event level is chosen by the message author. There are several levels. The main ones are info, debug, error.
- INFO - usually these are information messages about what is happening, something like a history by date: 1915 - something happened, 1916 - something else.
- DEBUG - describes the events of a particular moment in more detail. For example, the details of a battle in history are at the debug level." Commander Takoytovich advanced with his army towards the village of Selovicha ."
- ERROR - errors that occur are usually written here. You've probably noticed that when you wrap something in
try-catch
, the blockcatch
is substituted withe.printStacktrace()
. It only outputs the entry to the console. Using a logger, you can send this entry to the logger (haha), you get the idea. - WARN - warnings are written here. For example, an overheating light in a car. This is just a warning, and it is better to change something, but this is not a breakdown. When the machine breaks down, then we will log with the ERROR level.
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
In this case, everything is configured so that the logger writes to a file and to the console at the same time. In that case? if something is erased in the console, plus it’s easier to search by file. INFO level for both. A name pattern is also specified for the file. This is a minimal config that allows you to write to both the console and a file at once. java.util.logging.FileHandler.append
set to true so that old entries in the file are not erased. An example of use is this (without comments, the logger comments on itself):
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);
}
}
}
This is not the best example, I took the one that was at hand. Example output:
апр 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)
Here I want to focus on the notes:
апр 19, 2019 1:10:14 AM generics.Main main
INFO: Размер equals 3
апр 19, 2019 1:10:14 AM generics.Main main
INFO: Получим первый элемент
This entry is quite useless and not informative. Like the error entry:
WARNING: что-то пошло не так
You shouldn’t write this: it’s a log for the sake of a log, it will only get in the way. Try to always write meaningful things. I think this is enough to stop using it System.out.println
and move on to adult toys. It java.util.logging
has disadvantages. For example, the levels that I described above are not here, but they are in most used loggers. I chose it for this article java.util.logging
because it does not require additional manipulations with the connection. I will also note that it can be used LOGGER.info
instead of LOGGER.log(Level.INFO...
One of the disadvantages already appears here: LOGGER.log(Level.WARNING,"что-то пошло не так" , e);
- it allows you to transmit a message and an object Exception
, the logger itself will write it down beautifully. At the same time, LOGGER.warning("");
it only receives a message, i.e. The exception cannot be passed, you have to translate it into a string yourself. I hope this example is enough to get acquainted with Java logging. Then you can connect other loggers (log4j, slf4j, Logback...) - there are many of them, but the essence is the same^ to record the history of actions. Official tutorial
GO TO FULL VERSION