AopLog is based on Spring Aop and ThreadLocal implementation of a special request method content log interception and processing logging toolkit.

Scene:

  1. Using Spring Aop to intercept parameter logging is basically the same as most of the current practices. I don’t want every project to write a copy of such Aop interception processing logging code, or even code intrusion.
  2. I would like to know some relatively important request method request parameters, response parameters, request headers, as well as internal time, method success or failure, etc. When an error occurs, I do not know which step is abnormal and whether it is a logical problem caused by a parameter.
  3. Normal log.info or WARN information does not have a hierarchical relationship with the request to which it belongs and is not easy to view and analyze.
  4. In a formal environment, I don’t want to print too many pointless INFO logs (some are just logs for troubleshooting, which are meaningless when the program is running properly), only when an exception occurs or only one sub-critical request per request.
  5. Log collection, I want to record these requests to log, record the implementation of my own decision, such as normal log printing, common log written to the database, log written to a file, log into the queue and so on.
  6. The recording of the whole log does not interfere with the process of the normal request method, and the collection and processing of the log is asynchronous, which does not affect the performance and response of the normal request method.
  7. You just have to go through@AopLogAnnotations determine whether to record.

Quick start

Projects are introduced through Maven’s POM.xml


<dependency>
    <groupId>com.github.ealenxie</groupId>
    <artifactId>aop-log</artifactId>
    <version>2.4</version>
</dependency>

Copy the code

Or through Gradle

compile group: 'com.github.ealenxie', name: 'aop-log', version: '2.4'
Copy the code

The @aoplog annotation is used for log recording

Log directly by annotating @aoplog on a class (which acts on all methods of the class) or a class method (which acts on methods)

Such as:

import com.github.AopLog;
import name.ealen.infra.base.resp.RespBody;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

/ * * *@author EalenXie create on 2020/6/22 14:28
 */
@aoplog (type = "test ",stackTraceOnErr = true)
@RestController
public class AppController {

    @GetMapping("/app/sayHello")
    public RespBody<String> sayHello(a) {
        return RespBody.ok("hello EalenXie"); }}Copy the code

A custom global LogCollector implementation collects LogCollector

Such as simply printing, or writing to a library, etc.


import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.github.LogData;
import com.github.collector.LogCollector;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;

/ * * *@authorEalenXie create on 2020/9/15 13:46 * This is a sample reference * Configure a simple log collector here just do a log.info print, can be written to the database or write */
@Slf4j
@Component
public class AopLogCollector implements LogCollector {
    private ObjectMapper objectMapper = new ObjectMapper();
    @Override
    public void collect(LogData logData) {
        try {
            log.info(objectMapper.writeValueAsString(logData));
        } catch(JsonProcessingException e) { e.printStackTrace(); }}}Copy the code

Only one global log collector can be configured for @Component.

Interface call /say/hello test to see the console print the result:

The 2020-09-16 16:01:04. 2012-782 the INFO [AsyncExecutor - 2] name. Ealen. Infra. Advice. AopLogCollector: {" appName ", "app - the template", "the host" : "127.0.0.1", "port" : 8080, "clientIp" : "192.168.110.1", "reqUrl" : "http://localhost:8080/app/ SayHello ", "httpMethod" : "GET", "headers" : {" the user-agent ":" the Apache HttpClient / 4.5.10 (Java / 11.0.5) "}, "type" : "test", "content" : ""," method ":" name. Ealen. API. The facade. AppController# sayHello ", "args", null, "respBody" : {" code ":" 200 ", "desc" : "OK", "message" : "request is successful", "dateTime" : "the 2020-09-16 16:01:04", "body" : "hello EalenXie"},"logDate":1600243264780,"costTime":1,"threadName":"http-nio-8080-exec-3","threadId":33,"success":true}Copy the code

This section describes the properties of the log object LogData

LogData Indicates the content of the log

field type annotation
appName String The application name
host String The host
port int The port number
clientIp String Request the Ip address of the client
reqUrl String Request the address
headers Object Request header information (optional record) The default record is user-agent and Content-type
type String Operation type, default value undefined
content String Method step content, the default is empty, you can use logdata.step to record the content step
method String The local Java method requested
args Object Method request parameter
respBody Object Method response parameter
costTime long The whole method takes time
logDate Date Log generation time,LogData object initialization time
threadName String Name of the thread
threadId long Thread Id
success boolean Execution status, success (true)/ Exception (false)

AopLog annotation options description

options type instructions The default
logOnErr boolean Only record the collection when an exception occurs false
type String Operation type The default value of “undefined”
headers String[] Record header information. Select which header information to record The default “the user-agent”, “the content-type”
args boolean Whether to record request parameters true
respBody boolean Whether to record response parameters true
stackTraceOnErr boolean Whether to append exception stack information to the LogData content when an exception occurs in the target method false
asyncMode boolean Asynchronous Collection true
collector Class<? extends LogCollector> Specifying the log collector By default, the collector is not tuned and a global logging collector is used

Step method of LogData.

Record the steps. (if some important steps are to be recorded) example:

import com.github.AopLog; import com.github.LogData; import name.ealen.infra.base.resp.RespBody; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RestController; /** * @author EalenXie create on 2020/6/22 14:28 */ @aoplog (type = "test ",stackTraceOnErr = true) @restController public class AppController { @GetMapping("/app/sayHello") public RespBody<String> sayHello() { LogData.step("1. The first step is completed "); / /... Logdata.step ("2. Step 2 is completed "); / /... Logdata.step ("3. Service method completed "); / /... return RespBody.ok("hello EalenXie"); }}Copy the code

Note: If this method is not used in the whole invocation link of the @aoplog annotated method, the LogData in the ThreadLocal of the current thread will not be freed and logData.removecurrent () will need to be manually called;

/say/hello = “/say/hello”;

The 2020-09-16 17:26:20. 3284-285 the INFO [AsyncExecutor - 2] name. Ealen. Infra. Advice. AopLogCollector: {" appName ", "app - the template", "the host" : "127.0.0.1", "port" : 8080, "clientIp" : "192.168.110.1", "reqUrl" : "http://localhost:8080/app/ SayHello ", "httpMethod" : "GET", "headers" : {" the user-agent ":" the Apache HttpClient / 4.5.10 (Java / 11.0.5) "}, "type" : "test", "content" : "1.  Step 1 execution completed \n2. Step 2 Execution completed \n3. Service method completes \ n ", "method" : "name. Ealen. API. The facade. AppController# sayHello", "args", null, "respBody" : {" code ":" 200 ", "desc" : "O K ", "message" : "request", "success dateTime" : "the 2020-09-16 17:26:20", "body", "hello EalenXie"},"logDate":1600248380283,"costTime":1,"threadName":"http-nio-8080-exec-2","threadId":32,"success":true}Copy the code

about

Open source Github address: github.com/EalenXie/aop-log

Thank you for your comments and support.