"Good afternoon, an incident was recorded on the prom today, I ask the developer to join the analysis group." Something like this may start one of your days at work, or maybe the morning - it doesn’t matter. But let's start in order. By solving problems here on CodeGym, you learn how 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 the first time. It will be the same at work. You will not always solve the problem the first time: bugs are our eternal companions. It is important that you can restore the events of the appearance of the bug. Let's just take an example. Imagine that you are a police officer. You were called to the scene (glass was broken in the 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 conditional - they start looking for witnesses, evidence and all that stuff. What if the place itself could tell in detail what happened? For example, like this:
Got it with the levels. But don't worry: the line between them is very thin - not everyone can explain it. Plus, it may differ from project to project. The senior developer will explain to you at what level and what to log. The main thing is that these records are enough for you for future analysis. And this is understood on the go. Next is the settings. You can tell loggers where to write (to the console, file, jms or somewhere else), specify the level (info, error, debug...). An example of settings for our simple logger looks like this:
- 21:59 the owner turned on the alarm (5 minutes before full activation)
- 22:00 the owner closed the door
- 22:05 full activation of the alarm
- 22:06 the owner pulled the handle
- 23:15 noise sensor turned on
- 23:15 a flock of dogs ran past, loudly barking
- 23:15 noise sensor turned off
- 01:17 the shock sensor on the outer glass of the showcase turned on
- 01:17 dove flew into the glass
- 01:17 glass broke
- 01:17 siren on
- 01:17 the dove shook itself off and flew away
java.util.Logger
: it is more than enough for dating. Each log entry contains date-time, event level, message. Date-time is set automatically. The level of the event is chosen by the author of the message. There are several levels. The main ones are info, debug, error.
- INFO - usually these are informational 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 any battle in history is the debug level. " Commander Taikitovich advanced with his army towards the village of Selovich ."
- ERROR - errors that occur are usually written here. You probably noticed that when you wrap something in
try-catch
, the blockcatch
is substituted withe.printStacktrace()
. It only outputs the entry to the console. With the help of a logger, you can send this entry to the logger (ha ha), you understand. - 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 yet. That's 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 set up so that the logger writes to the file and to the console at the same time. For that case? if something is erased in the console, plus it's easier to search by file. INFO level for both. The file name pattern is also set. This is the minimum config that allows you to write both to the console and to the file at once. java.util.logging.FileHandler.append
set to true so that old records are not erased from the file. An example of using 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. Sample 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 records:
апр 19, 2019 1:10:14 AM generics.Main main
INFO: Размер equals 3
апр 19, 2019 1:10:14 AM generics.Main main
INFO: Получим первый элемент
Such a record is rather useless, not informative. Like the error entry:
WARNING: что-то пошло не так
You should not write this: this is a log for the sake of a log, it will only interfere. Try to always write meaningful things. I think this is enough to stop using System.out.println
and move on to adult toys. We java.util.logging
have flaws. For example, levels, those that I described above, are not here, but they are in most used loggers. For the article, I chose java.util.logging
because it does not require additional connection manipulations. I also note that it can be used LOGGER.info
instead . LOGGER.log(Level.INFO...
One of the drawbacks pops up already here: LOGGER.log(Level.WARNING,"что-то пошло не так" , e);
- allows you to send a message and an object Exception
, the logger will write it down beautifully. At the same time asLOGGER.warning("");
only accepts a message, i.e. You cannot pass an exception, you must 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