AopLog is based on Spring Aop and ThreadLocal implementation of a special request method content log interception and processing logging toolkit.
Scene:
- 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.
- 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.
- 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.
- 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.
- 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.
- 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.
- You just have to go through
@AopLog
Annotations 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.