JavaRush /Java Blog /Random EN /Why is logging needed?

Why is logging needed?

Published in the Random EN group
Hello! When writing lectures, I especially note if a particular topic will definitely be used in real work. Why do you need logging - 1 So, ATTENTION! The topic we will touch on today will definitely be useful to you on all your projects from the first day of work. We'll talk about logging. This topic is not at all difficult (I would even say easy). But at your first job there will already be enough stress to still deal with the obvious things, so it’s better to thoroughly sort it out now :) So, let's get started. What is logging? Logging is recording somewhere data about the operation of a program. The place where this data is written is called the “ log ”. Two questions arise at once: where and what data is recorded? Let's start with "where". You can record program operation data in many different places. For example, during your studies you often output data to the console using System.out.println(). This is real logging, albeit the simplest one. Of course, this is not very convenient for the client or product support team: they obviously will not want to install the IDE and monitor the console :) There is also a more familiar format for recording information - in a text file. It’s much easier for people to read them this way, and certainly much easier to store! Now the second question: what data about the operation of the program should be recorded in the log? But here everything depends on you! The Java logging system is very flexible. You can configure it in such a way that the entire progress of your program will be logged. On the one hand, this is good. But on the other hand, imagine what size Facebook or Twitter logs can reach if everything is written there. Such large companies probably have the ability to store even this amount of information. But imagine how difficult it would be to search for information about one critical error in logs containing 500 gigabytes of text? It's even worse than a needle in a haystack. Therefore, logging in Java can be configured so that only error data is written to the log (log). Or even just about critical errors! Although, saying “logging in Java” is not entirely correct. The fact is that the need for logging arose among programmers before this functionality was added to the language. And by the time Java had its own logging library, everyone was already using the log4j library. The history of the appearance of logging in Java is actually very long and informative; at your leisure, you can read this post on Habré . In short, Java has its own logging library, but almost no one uses it :) Later, when several different logging libraries appeared, and all programmers began to use different ones, a compatibility problem arose. To prevent people from doing the same thing using a dozen different libraries with different interfaces, the slf4j abstraction framework was created(“Service Logging Facade For Java”). It is called abstracting because although you use slf4j classes and call their methods, under the hood they have all the previous logging frameworks running: log4j, standard java.util.logging and others. If you currently need some specific feature of log4j that other libraries do not have, but you would not like to strictly link the project to this particular library, just use slf4j. And she will already “pull” the log4j methods. If you change your mind and decide that you no longer need the log4j features, you just need to reconfigure the “wrapper” (that is, slf4j) to use another library. Your code will not stop working, because in it you call methods of slf4j, and not of a specific library. A small digression. For the following examples to work, you need to download the slf4j library from here , and the log4j library from here . Next, we need to unpack the archive and add the jar files we need to the classpath via Intellij IDEA. Menu items: File -> Project Structure -> Libraries Select the necessary jars and add them to the project (there are many jars in the archives that we downloaded, look at the ones you need in the pictures) Why do you need logging - 2Why do you need logging - 3Note - this instruction is for those students who do not know how to use Maven. If you know how to use it, it's better to try starting with it: it's usually much easier. If you use Maven , add this dependency:
<dependency>
            <groupId>org.apache.logging.log4j</groupId>
            <artifactId>log4j-slf4j-impl</artifactId>
            <version>2.14.0</version>
</dependency>
Great, we've sorted out the settings :) Let's look at how slf4j works. How can we make sure that the progress of the program is recorded somewhere? For this we need two things - a logger and an appender . Let's start with the first one. A logger is an object that completely manages record keeping . Creating a logger is very easy: it is done using a static method - LoggerFactory.getLogger(). As a parameter to the method, you need to pass a class whose work will be logged. Let's run our code:
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class MyTestClass {

   public static final Logger LOGGER = LoggerFactory.getLogger(MyTestClass.class);

   public static void main(String[] args) {

       LOGGER.info("Test log record!!!");
       LOGGER.error("В программе возникла ошибка!");
   }
}
Console output: ERROR StatusLogger No Log4j 2 configuration file found. Using default configuration (logging only errors to the console), or user programmatically provided configurations. Set system property 'log4j2.debug' to show Log4j 2 internal initialization logging. See https://logging.apache.org/log4j/2.x/manual/configuration.html for instructions on how to configure Log4j 2 15:49:08.907 [main] ERROR MyTestClass - An error has occurred in the program! What do we see here? First we see an error message. It appeared because we currently lack the necessary settings. Therefore, our logger can now only output error messages (ERROR) and only to the console. The method logger.info()was not executed. But logger.error()it worked! The console displays the current date, the method where the error occurred ( main), the word ERROR and our message! ERROR is the logging level. In general, if a log entry is marked with the word ERROR, it means that an error occurred at that point in the program. If an entry is marked with the word INFO, it means it is simply current information about the normal operation of the program. The SLF4J library has quite a few different logging levels that allow you to flexibly configure logging. They are very easy to manage: all the necessary logic is already included in the class Logger. You just need to call the necessary methods. If you want to post a regular message, call the logger.info(). Error message - logger.error(). Display a warning - logger.warn() Now let's talk about the appender . The appender is the place where your data comes. You could say the opposite of a data source is “point B.” By default, data is output to the console. Please note that in the previous example we did not have to configure anything: the text appeared in the console itself, but the logger from the log4j library can only output ERROR level messages to the console. It is obviously more convenient for people to read logs from a text file and store logs in the same files. To change the default behavior of the logger, we need to configure our file appender . To begin with, you need to create a log4j.xml file right in the src folder , or in the resources folder, if you use Maven, or in the resources folder, in case you use Maven. You are already familiar with the xml format, we recently had a lecture about it :) This is what its content will be:
<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="INFO">
   <Appenders>
       <File name="MyFileAppender" fileName="C:\Users\Username\Desktop\testlog.txt" immediateFlush="false" append="false">
           <PatternLayout pattern="%d{yyy-MM-dd HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n"/>
       </File>
   </Appenders>
   <Loggers>
       <Root level="INFO">
           <AppenderRef ref="MyFileAppender"/>
       </Root>
   </Loggers>
</Configuration>
It doesn't look particularly complicated :) But let's still go through the contents.
<Configuration status="INFO">
This is the so-called status-logger. It is not related to our logger and is used internally by log4j. You can set status=”TRACE” instead of status=”INFO”, and all information about the internal workings of log4j will be output to the console (status-logger outputs data to the console, even if our appender for the program is file-based). We don't need this now, so we'll leave everything as it is.
<Appenders>
   <File name="MyFileAppender" fileName="C:\Users\Евгений\Desktop\testlog.txt" append="true">
       <PatternLayout pattern="%d{yyy-MM-dd HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n"/>
   </File>
</Appenders>
Here we create our appender. The tag <File>indicates that it will be a file. name="MyFileAppender"- the name of our appender. fileName="C:\Users\Username\Desktop\testlog.txt"— path to the log file where all data will be written. append="true"— whether it is necessary to write additional data to the end of the file. In our case this will be the case. If set to false , the old log contents will be deleted each time the program is started again. <PatternLayout pattern="%d{yyy-MM-dd HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n"/>- These are formatting settings. Here we can use regular expressions to customize the format of the text in our log.
<Loggers>
       <Root level="INFO">
           <AppenderRef ref="MyFileAppender"/>
       </Root>
</Loggers>
Here we specify the logging level (root level). We have the INFO level set: that is, all messages at levels higher than INFO (according to the table we looked at above) will not be included in the log. We will have 3 messages in our program: one INFO, one WARN and one ERROR. With the current configuration, all 3 messages will be written to the log. If you change the root level to ERROR, only the last message from LOGGER.error() will be logged. In addition, a link to the appender is placed here. To create such a link, you need to <Root>create a tag inside the tag <ApprenderRef>and add the parameter to it ref=”Name твоего аппендера”. We created the name of the appender here, in case you forgot: <File name="MyFileAppender" And here is the code of our program!
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class MyTestClass {

   public static final Logger LOGGER = LoggerFactory.getLogger(MyTestClass.class);

   public static void main(String[] args) {

       LOGGER.info("Начало работы программы!!!");

       try {
           LOGGER.warn("Внимание! Программа пытается разделить одно число на другое");
           System.out.println(12/0);
       } catch (ArithmeticException x) {

           LOGGER.error("Ошибка! Произошло деление на ноль!");
       }
   }
}
Of course, it’s a little crooked (catching RuntimeException is a mediocre idea), but it’s perfect for our purposes :) Let’s run our method main()4 times in a row and look at our testlog.txt file. There is no need to create it in advance: the library will do it automatically. Everything worked! :) Now you have a configured logger. You can play around with some programs you wrote earlier, adding logger calls to all methods, and look at the resulting log :) For additional reading, I highly recommend this article . There, the topic of logging is discussed in depth, and it will not be easy to read it in one sitting. But it contains a lot of useful additional information. For example, you will learn how to configure a logger so that it creates a new text file if our testlog.txt file reaches a certain size :) And this is the end of our lesson! Today you learned about a very important topic, and this knowledge will definitely be useful to you in your future work. See you again! :)
Comments
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION