当前位置:网站首页>Oh, my God! Printing log only knows log4j?

Oh, my God! Printing log only knows log4j?

2020-11-09 12:09:00 Silent king two

When it's empty , I would sneak in a group , To every move of my friends 、 Word by word screening diagnosis . A head teacher's sense of immediacy , It makes me feel very happy , It's a little bit boring .

see , I found such a series of chatting records among readers during the Warring States period :

Even a little partner didn't know “ Log ” What does that mean? , I don't know how to learn , And the little friend said , Only know Log4j!

For a moment , I took 10000 critical hits , I feel so sad in my heart , Like a despondent dog . Because there are always some malicious people attacking me on the Internet , Tell me about the introduction to my article , No depth —— They are the sunspots of my destiny , If you don't believe it, search for it “ Silent king two ”, You can see their insipid attack .

I just want to ask , What's up? , The entry article has the entry group need , And I happened to help such a large number of beginners , I should be praised, OK ?

( I don't care what I said , Why do you care about it ? Manual formation )

What about him , I did it my way Well , It's right to keep your original mind ! This article will talk about Log4j, The originator of this print log .Java The journal printing in is actually an art work , by my troth , This sentence is by no means a hoax .

The fact proved that , Printing log will affect the performance of the program , This is undeniable , After all, one more job . Especially in programs where transactions are very frequent , It's really inefficient to have a lot of logs .

Based on performance considerations , It's necessary for my friends to learn how to print gracefully Java journal . After all , performance It is an important consideration whether a programmer is good or not .

01、 Why do you need to be in Java Print log in

System.out.println() I'm afraid we are learning Java When , The most common way to print a log , Almost every Java All beginners have done this , Even some old birds .

The reason why the log is printed like this , Because it's convenient , It's very difficult to get started , Especially in IDEA With the help of the , Just press... On the keyboard so Two letters will call up System.out.println().

In the local environment , Use System.out.println() It's OK to print the log , You can see the information on the console . But if it's in a production environment ,System.out.println() It becomes useless .

The information printed out by the console is not saved to the log file , Can only be viewed instantly , In the case of one screen log, you can also accept . If the log volume is very large , The console doesn't fit . So you need more advanced logging API( such as Log4j and java.util.logging).

They can save a lot of log information to files , And control the size of each file , If the full , Just store it to the next one , Easy to find .

02、 The importance of choosing different log levels

Use Java In the Journal , Be sure to pay attention to the level of the log , For example, the common DEBUG、INFO、WARN and ERROR.

DEBUG The lowest level , When you need to print debugging information , Use this level , It is not recommended to use in a production environment .

INFO Higher level , When important information needs to be printed , Just use this. .

WARN, Used to record some warning information , For example, the connection between the client and the server is disconnected , Database connection lost .

ERROR Than WARN A higher level , Information used to record errors or exceptions .

FATAL, Use when a program has a fatal error , This means that the program may have stopped abnormally .

OFF, highest level , It means that all messages will not be output .

This level is based on Log4j Of , and java.util.logging Somewhat different , The latter provides more logging levels , for instance SEVERE、FINER、FINEST.

03、 How bad logging affects performance

Why does the wrong logging affect the performance of the program ? Because the more times you log , It means executing files IO The more times you operate , This means that it will affect the performance of the program , can get Well ?

Although the ordinary hard disk upgrade to solid-state disk , Reading and writing speed is much faster , But disk is relative to memory and CPU Come on , Still too slow ! It's like the speed gap between a carriage and a Benz .

That's why it's important to choose the log level . For the program , Logging is required , So what you can control is the level of the log , And the logs printed at this level .

about DEBUG Level of the log , Be sure to record in the following way :

if(logger.isDebugEnabled()){ 
    logger.debug("DEBUG  Is open "); 

When DEBUG The level is to print the log when it is on , This way can be found when you look at a lot of source code , Very common .

Bear in mind , In production environment , Never turn it on DEBUG Level of logging , Otherwise, the program will slow down when it logs a lot , There's also the possibility that you don't notice , Quietly bursting disk space .

04、 Why choose Log4j instead of java.util.logging

java.util.logging Native log API,Log4j Belongs to the third party class library , But I suggest using Log4j, because Log4j Better to use .java.util.logging Log level ratio of Log4j more , But you don't have to , It becomes redundant .

Log4j Another good thing about , No need to restart Java The program can adjust the level of logging , Very flexible . Can pass log4j.properties File to configure Log4j Log level of 、 Output environment 、 How log files are recorded .

Log4j Is it thread safe , It can be used safely in a multithreaded environment .

Let's take a look first java.util.logging How to use :

package com.itwanger;

import java.io.IOException;
import java.util.logging.FileHandler;
import java.util.logging.Logger;
import java.util.logging.SimpleFormatter;

/**
 * @author  Wechat search 「 Silent king two 」, Reply key  PDF
 */

public class JavaUtilLoggingDemo {
    public static void main(String[] args) throws IOException {
        Logger logger = Logger.getLogger("test");
        FileHandler fileHandler = new FileHandler("javautillog.txt");
        fileHandler.setFormatter(new SimpleFormatter());
        logger.addHandler(fileHandler);
        logger.info(" Little information ");
    }
}

The program will run in target Create a directory called javautillog.txt The file of , The contents are shown below :

Let's take a look at Log4j How to use .

First step , stay pom.xml Introduce in the file Log4j package :

<dependency>
    <groupId>log4j</groupId>
    <artifactId>log4j</artifactId>
    <version>1.2.17</version>
</dependency>

The second step , stay resources Create under directory log4j.properties file , The contents are shown below :

###  Set up ###
log4j.rootLogger = debug,stdout,D,E

###  Output information to console  ###
log4j.appender.stdout = org.apache.log4j.ConsoleAppender
log4j.appender.stdout.Target = System.out
log4j.appender.stdout.layout = org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern = [%-5p] %d{yyyy-MM-dd HH:mm:ss,SSS} method:%l%n%m%n

###  Output DEBUG  Log above level to =debug.log ###
log4j.appender.D = org.apache.log4j.DailyRollingFileAppender
log4j.appender.D.File = debug.log
log4j.appender.D.Append = true
log4j.appender.D.Threshold = DEBUG 
log4j.appender.D.layout = org.apache.log4j.PatternLayout
log4j.appender.D.layout.ConversionPattern = %d{yyyy-MM-dd HH:mm:ss}  [ %t:%r ] - [ %p ]  %m%n

###  Output ERROR  Log above level to =error.log ###
log4j.appender.E = org.apache.log4j.DailyRollingFileAppender
log4j.appender.E.File =error.log 
log4j.appender.E.Append = true
log4j.appender.E.Threshold = ERROR 
log4j.appender.E.layout = org.apache.log4j.PatternLayout
log4j.appender.E.layout.ConversionPattern = %d{yyyy-MM-dd HH:mm:ss}  [ %t:%r ] - [ %p ]  %m%n

1) Configuration root Logger, The syntax is shown below :

log4j.rootLogger = [ level ] , appenderName, appenderName, …

level It's the priority of the log , The order from high to low is ERROR、WARN、INFO、DEBUG. If this is defined as INFO, So low level DEBUG Log information will not be printed out .

appenderName It refers to where to output log information , You can specify multiple places , The current configuration file contains 3 A place to , Namely stdout、D、E.

2) Configure the destination of the log output , The syntax is shown below :

log4j.appender.appenderName = fully.qualified.name.of.appender.class  
log4j.appender.appenderName.option1 = value1  
…  
log4j.appender.appenderName.option = valueN

Log4j The following destinations are offered 5 Kind of :

  • org.apache.log4j.ConsoleAppender: Console
  • org.apache.log4j.FileAppender: file
  • org.apache.log4j.DailyRollingFileAppender: Produce a file every day
  • org.apache.log4j.RollingFileAppender: A new file is generated when the file size exceeds the threshold
  • org.apache.log4j.WriterAppender: Send log information in stream format to any specified place

3) Configure the format of log information , The syntax is shown below :

log4j.appender.appenderName.layout = fully.qualified.name.of.layout.class  
log4j.appender.appenderName.layout.option1 = value1  
…  
log4j.appender.appenderName.layout.option = valueN

Log4j The format provided is as follows 4 Kind of :

  • org.apache.log4j.HTMLLayout:HTML form
  • org.apache.log4j.PatternLayout: Customize
  • org.apache.log4j.SimpleLayout: Contains the level of log information and the information string
  • org.apache.log4j.TTCCLayout: Include the time when the log was generated 、 Threads 、 Categories and so on

The parameters of the custom format are as follows :

  • %m: The message specified in the output code
  • %p: Output priority
  • %r: The number of milliseconds it took to output the log information from the start of the output application
  • %c: Output the full name of the class
  • %t: Output the name of the thread where the log is located
  • %n: Output a carriage return line feed
  • %d: The point in time when the log is output
  • %l: Where the output log occurs , Including the name of the class 、 The thread of 、 Method name 、 Lines of code , such as :method:com.itwanger.Log4jDemo.main(Log4jDemo.java:14)

The third step , Write a usage Demo:

package com.itwanger;

import org.apache.log4j.LogManager;
import org.apache.log4j.Logger;

/**
 * @author  Wechat search 「 Silent king two 」, Reply key  PDF
 */

public class Log4jDemo {
    private static final Logger logger = LogManager.getLogger(Log4jDemo.class);

    public static void main(String[] args) {
        //  Record debug Level information
        logger.debug("debug.");

        //  Record info Level information
        logger.info("info.");

        //  Record error Level information
        logger.error("error.");
    }
}

1) obtain Logger object

To use Log4j Words , You need to get Logger object , It is used to print log information . The usual format is as follows :

private static final Logger logger = LogManager.getLogger(Log4jDemo.class);

2) Print log

With Logger After the object , You can print the log according to different priorities . The common ones are the following 4 Kind of :

Logger.debug() ;  
Logger.info() ;  
Logger.warn() ;  
Logger.error() ;

The program will run in target Two files are generated in the directory , A man named debug.log, The contents are shown below :

2020-10-20 20:53:27  [ main:0 ] - [ DEBUG ]  debug.
2020-10-20 20:53:27  [ main:3 ] - [ INFO ]  info.
2020-10-20 20:53:27  [ main:3 ] - [ ERROR ]  error.

The other is called error.log, The contents are shown below :

2020-10-20 20:53:27  [ main:3 ] - [ ERROR ]  error.

05、 Print log's 8 A little trick

1) In print DEBUG Level of logging , Remember to use isDebugEnabled()! The guys must be very curious , Why do this ?

Let's take a look first isDebugEnabled() Method source code :

  public
  boolean isDebugEnabled() 
{
    if(repository.isDisabled( Level.DEBUG_INT))
      return false;
    return Level.DEBUG.isGreaterOrEqual(this.getEffectiveLevel());
  }

Internal use isDisabled() Method to judge the log level , If DEBUG If it's forbidden , Just return false 了 .

Let's take a look at debug() Method source code :

  public
  void debug(Object message) 
{
    if(repository.isDisabled(Level.DEBUG_INT))
      return;
    if(Level.DEBUG.isGreaterOrEqual(this.getEffectiveLevel())) {
      forcedLog(FQCN, Level.DEBUG, message, null);
    }
  }

Why , It doesn't work isDisabled() Method judgment ? Don't use isDebugEnabled() Isn't it just to add to the lily ? Direct use logger.debug() Is it not fragrant ? Let me explain to my friends .

If we need to attach a method to get the parameter value when printing log information , It looks like this :

logger.debug(" User name is :" + getName());

If getName() The method takes as long as 6 second , That's over ! Although the log level in the configuration file defines INFO,getName() The method will still carry out stubbornly 6 second , After that debug(), It's going to collapse !

Mingming INFO When debug() It's not enforced , signify getName() It doesn't need to be implemented , But it was executed 6 second , Isn't it stupid ?

if(logger.isDebugEnabled()) {
    logger.debug(" User name is :" + getName());
}

Change to the way above , So make sure this is the moment getName() It's not enforced , Right ?

For the sake of program performance ,isDebugEnabled() It becomes necessary ! If say debug() There was no reference , There is no need to judge DEBUG Is enabled .

2) Choose the printing level of log information carefully , Because it's so important ! If you can only use the log to see what's wrong with the program , The necessary information must be printed , But it prints too much , It will affect the performance of the program .

therefore , The INFO Of info(), The DEBUG Of debug(), Don't use it casually .

3) Use Log4j instead of System.outSystem.err perhaps e.printStackTrace() To print logs , The reason has been mentioned before , I won't go back to .

4) Use log4j.properties File to configure the log , Even though it's not required , Using this file makes the program more flexible , There's a taste of my own territory that I'm in charge of .

5) Don't forget to print the log with the full name of the class and the thread name , In multithreaded environment , This is especially important , Otherwise, it will be too difficult to locate the problem .

6) Try to be complete when printing log information , Don't be too default , Especially when there are exceptions or errors ( There are two types of information to keep : Crime scene information and exception stack information , If you don't do it , adopt throws Keywords up ), In order to avoid some useless log information when looking for problems .

7) To distinguish between log information , Add a prefix to the output of a certain type of log information , For example, add... To all database level logs DB_LOG, When such a log is very large, you can use grep In this way Linux Command quick positioning .

8) Don't print the password in the log file 、 Bank account number and other sensitive information .

06、 summary

Printing a journal is really an art work , It will seriously affect the performance of the server . The most terrible thing is , Logged , But it turns out that fart doesn't work , It's just a day ! Especially in the production environment , The problem is not recorded , But there is a certain randomness in the recurrence , By then , It's really called that every day should not , It's not working !

Uh huh , Actually, I've finished writing the entire log system , Include Log4j、 SLF4J、Logback、Log4j His brother Log4j 2, But I think if I send them separately , More favorable SEO( Look at my heart for the flow , Manual formation ). If you really need to see the full version , I have also prepared for you , Click on the link below to download PDF:

https://pan.baidu.com/s/1dPwsQhT5OMVapE7hGi7vww Extraction code :fxxy

It's not easy to code words , Ask for a compliment every day , Move your golden finger ,bug One less ( flee .

版权声明
本文为[Silent king two]所创,转载请带上原文链接,感谢