JavaRush /Java Blog /Random EN /Why do you need logging

Why do you need logging

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, WARNING! The topic that we will touch on today will definitely come in handy for you on all your projects from the first day of work. We'll talk about logging. This topic is not difficult at all (I would even say easy). But at the first job, there will already be enough stress to deal with the obvious things, so it's better to thoroughly analyze it now :) So, let's start. What is logging? Logging is a record somewhere of data about the operation of the program. The place where this data is written is called " log" .". Two questions arise at once - where and what data is recorded? Let's start with where. You can record data about the program's operation 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. Of course, this is not very convenient for a client or a product support team: they obviously do not want to install an IDE and monitor the console :) There is also a more familiar format for writing information to a text file. It is much more convenient for people to read them in this form, and certainly much more convenient to store! Now the second question: what data about the program's operation should be logged? And here everything depends on you! The logging system in Java is very flexible. You can configure it in such a way that the entire course of your program's work gets into the log. 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 at all. Such large companies certainly have the ability to store even this amount of information. But imagine how difficult it will be to find information about one critical error in the logs for 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 true. The fact is that the need for logging arose among programmers earlier, than 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, you can read at your leisurethis 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 with a dozen different libraries with different interfaces, the slf4j abstraction framework was created("Service Logging Facade For Java"). It is called abstract because although you use slf4j classes and call their methods, all previous logging frameworks work under the hood: log4j, standard java.util.logging and others. If you currently need some specific log4j feature that other libraries do not have, but you would not like to hard-link the project to this particular library, just use slf4j. And oh, she already “pulls” the log4j methods. If you change your mind and decide that you no longer need the log4j features, you only need to reconfigure the "wrapper" (that is, slf4j) to use a different library. Your code won't stop working because you're calling slf4j methods in it, not a specific library. A small digression. For the following examples to work, you need to download the slf4j libraryfrom here , and the log4j library from here . Next, you need to unpack the archive and add the jar files we need to the classpath via Intellij IDEA. Menu items: File -> Project Structure -> Libraries You select the necessary jar-nicknames and add them to the project (the archives that we downloaded contain a lot of jar'nick, see the ones you need in the pictures) Note - this Why do you need logging - 2Why logging is needed - 3instruction is for those students who do not know how to use maven. If you know how to use it, you better try to start with it: it's usually much easier. If you're using 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 got the settings sorted :) Let's take a look at how slf4j works. How can we make sure that the progress of the program is recorded somewhere? To do this, we need two things - a logger and an appender . Let's start with the first one. A logger is an entity that fully 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 the 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 now we lack the necessary settings. Therefore, our logger is now able to display only error messages (ERROR) and only to the console. The method logger.info()was not executed. But logger.error()it worked! The current date appeared in the console, 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 has occurred at this point in the program. If the entry is marked with the word INFO, then this is just 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. Managing them is very easy: all the necessary logic is already included in the Logger. You just need to call the necessary methods. If you want to pledge 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 where your data comes in.We can say that the opposite of the 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 at the same time, the logger from the log4j library can only output messages of the ERROR level 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 . First, 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 look like:
<?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 too difficult :) But let's go through the content anyway.
<Configuration status="INFO">
This is the so-called status-logger. It has nothing to do with our logger and is used internally by log4j processes. You can set status=”TRACE” instead of status=”INFO”, and all the information about the inner workings of log4j will be output to the console (status-logger outputs data to the console, even if our appender for the program is a file appender). We don't need it now, so let's leave it 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>
This is where we create our appender. The tag <File>indicates that it will be a file. name="MyFileAppender"is the name of our appender. fileName="C:\Users\Username\Desktop\testlog.txt"- the path to the log file where all data will be written. append="true"- whether it is necessary to add data to the end of the file. In our case, it will. If set to false , the old log content will be deleted each time the program is restarted. <PatternLayout pattern="%d{yyy-MM-dd HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n"/>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 of levels higher than INFO (according to the table that we considered above) will not be included in the log. We will have 3 messages in the program: one INFO, one WARN and one ERROR. With the current configuration, all 3 messages will be logged. 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 also 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 a RuntimeException is a so-so 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. You do not 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 of the programs you wrote earlier by adding logger calls to all methods, and look at the resulting log :) As an additional reading, I highly recommend this article to you. There, the topic of logging is considered in depth, and it will not be easy to read it at a time. But it contains a lot of useful additional information. For example, you will learn how to configure the logger so that it creates a new text file if our testlog.txt file has reached a certain size :) And our lesson is over! Today you got acquainted with a very important topic, and this knowledge will definitely be useful to you in your future work. See you soon! :)
Comments
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION