Hello, I’m 3Y. Before the main body, I would like to report the progress of Austin project to shareholders:
Overall, I felt the response was good, although the reading was not high. However, there are many people who leave comments, and many people are worried that I will not drop the pigeon (update half broke).
I can only say: don’t panic, absolutely not pigeon, you just chase better.
I have decided to carry my computer home every weekend and go to the nearby library when I am free.
No more BB, today continue to talk about a topic: log
01. What is a log
The so-called log, in my understanding is: record the information when the program is running
In the earliest days of Java, or in our early days, we printed logs with system.out.println ();
Does this work? Debatable.
For most beginners, easy to use! The information I want to see can be seen directly on the console, which is very convenient. The first result of learning Java is system.out.println (); It doesn’t cost you anything to learn.
For most workers, local debugging is fine, but not if the program is deployed to the server.
There are differences between a production environment and a local environment:
- Production environments need to log more (after all, running as a system/project online, you can’t just print a little bit of content)
- The log content in the production environment needs to be saved to a file (for retention, online will not say the problem was discovered at the first time, many need to find historical log data).
- Production environment log content needs to have a standard format (at least when it is logged)
- …
System.out.println(); You don’t have them.
So, we can see that projects written in companies do not use system.out.println (); journaling
02. Java Logging Architecture
As you work on it, you will find that every time you introduce a framework, there will be a corresponding log package under that framework.
In my previous company, I have integrated several projects (combining several existing projects into one project).
At that time, it was thought that my former colleague divided the project into too many details, which caused a certain waste of resources (after all, each project would deploy at least two online machines), so the company hoped us to merge some small projects sometime.
I won’t talk about the rightness or wrongness of it.
In the process of merging, the most troublesome problem is resolving dependency conflicts (all Maven projects, there will be Maven mediation issues), and here, the most obvious problem is the Java log package.
If you’ve ever had a chance to understand Java logging, you’ve probably heard some of the following names: Log4j(log for Java), JUL(Java Util Logging), JCL(Jakarta Commons Logging), Slf4j(Simple Logging Facade for Java, Logback, Log4j2
If you are careful, you will find that Java logging implementations are likely to be different for different technical frameworks.
Since the implementation is different, is the corresponding API call different? (It’s not like JDBC, after all. There is a set of interface specifications that are implemented by database vendors, and programmers are done programming for JDBC interfaces.)
So this this this is not a mess? The blood pressure starts to go up, right? Don’t panic, the Java Logging Facade Slf4j(Simple Logging Facade for Java) mentioned above does something similar to JDBC.
It defines the logging interface (facade mode), so when the project uses another logging framework, adapt it! Note: JDBC is a defined interface implemented by the database vendor. Slf4j also defines interfaces, but it works with other Java logging implementations.
Slf4j: Slf4j: Slf4j
Slf4j can be used to bridge the actual LOG implementation. (This way, if you want to switch from log4j to Logback at some point in the future, the code will stay the same.)
03. What’s the use of a journal?
Those of you who have not developed in a production environment may think that logging is all about locating problems, but it is not.
On the one hand, we use logs to locate problems, on the other hand, a lot of our data comes from logs
Don’t think it’s the data in the database that’s important. The log data that we record when our program is running is equally important.
In big data, there are many sources of data: relational databases, crawlers, logs, and so on
For example, my previous company had a framework for handling logging:
- We normally output log information to a file
- The framework provides the background to give us the configuration (file path and Kafka Topic Name)
What the framework does in plain English is convert the contents of our log files into Kafka messages (if the user needs to convert the contents of any log files into MQ messages, it is configured on the platform).
With Kafka messaging, is it possible to generate valuable data with a streaming platform (Storm/Spark/Flink) that cleans logs
04. Austin Logs
Pulled so long log basis, just want to let the students who do not understand the log have a cognition.
Without further ado, let’s go back to the Austin project where we were still in the “New folder” phase.
SpringBoot is used to build the technical framework of the Austin project. The default log combination of SpringBoot is Slf4j + Logback
Almost every project I work on in my company is this combination, so I’m going to stick with it and use Logback as Austin’s logging framework (if I ever change to another logging implementation, in theory I’ll just have to introduce the corresponding bridging package).
05. Logback Log Initial experience
Without any configuration, as long as we import the SpringBoot package, we can use the logging function directly. The specific effect is shown below
SpringBoot is a framework where convention is greater than configuration
By default, SpringBoot will load a configuration file named **logback. XML ** or logback-spring. XML from resources.
If none is present, logBack by default calls BasicConfigurator to create a minimal configuration.
The minimize configuration consists of a ConsoleAppender associated with the root Logger. The output is formatted with PatternLayoutEncoder with pattern **%d{HH:mm: ss.sss} [%thread] %-5level % Logger {36} – % MSG %n**
06. Logback configuration
As you can see from the above, the default logback configuration does not meet our requirements (it is printed on the console), and we want to keep the log in a file.
So, we will create a new logback configuration under Resources. Common configurations are as follows:
<configuration scan="true" scanPeriod="10 seconds">
<contextName>austin</contextName>
<! -- Setting the log output path allows variables to be used by "${}". TODO -->
<property name="log.path" value="logs"/>
<appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
<encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
<! Format output: %d indicates the date, %thread indicates the thread name, %-5level indicates the level of 5 characters from the left. % MSG indicates the log message, %n indicates the newline character.
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n</pattern>
<! -- Set character set -->
<charset>UTF-8</charset>
</encoder>
</appender>
<! -- Log level = INFO -->
<appender name="INFO_FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
<! -- The path and name of the log file being recorded -->
<file>${log.path}/austin-info.log</file>
<! Log file output format -->
<encoder>
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n</pattern>
<charset>UTF-8</charset>
</encoder>
<! -- Logger scroll policy, by date, by size -->
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<! -- Daily log archive path and format -->
<fileNamePattern>${log.path}/logs/austin-info-%d{yyyy-MM-dd}.%i.log</fileNamePattern>
<timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
<maxFileSize>1000MB</maxFileSize>
</timeBasedFileNamingAndTriggeringPolicy>
<! -- Log file retention days -->
<maxHistory>15</maxHistory>
</rollingPolicy>
<! -- This log file only records info level -->
<filter class="ch.qos.logback.classic.filter.LevelFilter">
<level>info</level>
<onMatch>ACCEPT</onMatch>
<onMismatch>DENY</onMismatch>
</filter>
</appender>
<! -- Log level = ERROR -->
<appender name="ERROR_FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
<! -- The path and name of the log file being recorded -->
<file>${log.path}/austin-error.log</file>
<! Log file output format -->
<encoder>
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n</pattern>
<charset>UTF-8</charset> <! -- Set character set -->
</encoder>
<! -- Logger scroll policy, by date, by size -->
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<fileNamePattern>${log.path}/austin-error-%d{yyyy-MM-dd}.%i.log</fileNamePattern>
<timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
<maxFileSize>1000MB</maxFileSize>
</timeBasedFileNamingAndTriggeringPolicy>
<! -- Log file retention days -->
<maxHistory>15</maxHistory>
</rollingPolicy>
<! -- This log file only records ERROR levels -->
<filter class="ch.qos.logback.classic.filter.LevelFilter">
<level>ERROR</level>
<onMatch>ACCEPT</onMatch>
<onMismatch>DENY</onMismatch>
</filter>
</appender>
<root level="info">
<! -- TODO Console can be printed for dev only -->
<appender-ref ref="CONSOLE"/>
<appender-ref ref="INFO_FILE"/>
<appender-ref ref="ERROR_FILE"/>
</root>
</configuration>
Copy the code
The log configuration will not be static, now that the project has just been built, it will be as simple as possible.
07, eggs,
The night before this article was published, ZhenDong asked me out of the blue what MQ I was using most, and I answered offhand: Kafka. Kafka is what I do with MQ
He said he was writing something good to send out. I must have been interested when I heard it.
ZhenDong post link: mp.weixin.qq.com/s/JC51S_bI0…
They use AOP+ dynamic templates to encapsulate a set of SDK, and then elegantly record operation logs (in human terms: the leaders do not want to log on business code, difficult to manage. Abstract the journaling action and use annotations to unify journaling.)
The article is excellent and I recommend reading it.
After reading the article, ZhenDong implemented a set of his own, which is almost finished. By the way, I discussed the usage scenarios with him and felt that my project could also use that set of things (there is an elegant way to log, who doesn’t love).
I have booked, when he sent me the source code, I will learn the realization of the idea (the following project also uses the SDK he provides to play log, there is a problem on the open spray 🐶[dog head.jpg]). When he finishes writing his essay, I will reprint it and study it with you.
Like this wheel or experience train of thought, after learning, you can blow in the interview. Just say that you have transformed the project system, from the original broken ghost (background) to now so elegant (results), and this process interspersed with their own implementation ideas and encountered pits (difficult process), this kind of highlight which interviewer does not love it?
08,
Log in a project, I think it is in a relatively important position. Our data and location problems are inseparable from the log, and some project logs are quite chaotic, which is very, very difficult to maintain.
In fact, I could write my own logback configuration and ignore this, but I insist on sorting it out, this article according to the “project” dimension to comb through the log knowledge, I hope it is helpful.
Project source Gitee link: gitee.com/austin
Project source GitHub link: github.com/austin
Follow my wechat official account [Java3y] to talk about something different!
Online Interviewers + Write Java projects from scratchContinuous high intensity update! O star,
Original is not easy!! Three times!!