Wechat public number: Orange Pine Java technology nest article first gold platform, the subsequent synchronous update of the public number, after attention to reply to “plus group” can join the Internet technology exchange & push group, and a group of big factory leaders to discuss interview questions. Reply to “666” to get all the information packages available on the First line Internet (including development software, development specifications, classic e-PDF, and some quality learning courses).

preface

We must have encountered in the development of such a few cases, the interface log is difficult to check ah, server log too much to see dazzling. Fortunately, I can get familiar with these Java troubleshooting tools as mentioned above, and some tools are enough. The key is the server log accumulation alarm, especially the QUALITY assurance environment. After receiving this SMS alarm, you immediately log in to the machine and start an RM operation to solve the problem. You get another SMS alert, familiar, this one again…

Out of curiosity, you open the dock IDEA, look at the screen full of code, and occasionally slightly right click to see the Git master submitter. You want to smash your computer when you know the truth.

Debug logs are not deleted. There is a Warn log with the word ‘xxxTest’. There is a Warn log with the word ‘xxxTest’. Suddenly see a file with a class ending in xxxAspect? Oh? Is this the business side? Just out of curiosity, take a look at the log section, the entry point is all the BIZ business code methods…


So, for the log is not standard, too many server logs, log governance we have a solution, so suddenly, everything and configurable, whether this thing can be configured, so you started to design up,

So many classes, so many methods, I am not each interface log print how can make switch control good? Done!

Switch control is done, so what about the content of the print log? What content should I print? The refs? The return value?

The logs contain the input parameters of the interface, response results, and response time.. Extensible parameters and so on. Done!

The log print content is set, what about the log print level? Every method and every situation may be different. I don’t think it’s the same in different circumstances. What should I do?

Understand, not everything is configured, I make the configuration is not good, configure several different strategies, done!

* the configuration? What do I use for configuration? My project is a distributed project, so after a search in Balabala you may see options like Diamond, Apollo, Disconf, etc., so you roll the dice and choose Apollo

In fact, can hahaha, understand understanding

Dynamic log printing through the control interface blacklist and whitelist log printing, done!

Ok, we have the idea, so let’s start coding

Apollo dynamic configuration enables interface log printing

First, we define an enumeration LogSwitch that controls the switching policy

Description: Need source file plus QQ group [572411121] free request */
public enum LogSwitch {
    /** * completely closed */
    OFF(1."off"),
    /** * open */
    PART_ON(2."part on"),
    /** * partially closed */
    PART_OFF(3."part off"),
    /** * fully open */
    ON(4."on");
    
    LogSwitch(int code ,String name){
        this.code = code;
        this.name = name;
    }

    public static LogSwitch of(int code) {
        for(LogSwitch logSwitch : LogSwitch.values()) {
            if(logSwitch.getCode() == code) {
                returnlogSwitch; }}return null;
    }

    @Getter
    @Setter
    private int code;

    @Getter
    @Setter
    private String name;
}
Copy the code

Second, we also define an enumeration LogDimension for the log print content

Description: Need source file plus QQ group [572411121] free request */
public enum  LogDimension {

    NONE(1."none"),
    TIME_ELAPSE(2."time elapse"),
    PARAM(3."param"),
    RESULT(4."result"),
    ALL(5."all");
    
    LogDimension(int code,String name) {
        this.code = code;
        this.name = name;
    }

    public static LogDimension of(int code) {
        for(LogDimension logDimension : values()) {
            if(logDimension.getCode() == code) {
                returnlogDimension; }}return null;
    }

    @Getter
    @Setter
    private int code;

    @Getter
    @Setter
    private String name;
}
Copy the code

Ok, now that the key elements of the next print log have been formed, we need to define a section class to do it.

Now that we have an aspect, we can use a pointcut annotation to do our aspect, define the log print annotation LogAnnotation doesn’t need any properties, it’s just a facet identifier for us.

/** * @Creator: Gold digging account "Tangerine Pine Java" * @ Created at 2021/7/9 * @ Description: Need to source file to add QQ group [572411121] for free * / @ Retention (RetentionPolicy. RUNTIME) @ Target ({ElementType METHOD, ElementType. TYPE}) @Documented public @interface LogAnnotation { }Copy the code

So now we can write our section class, so we define LogAspect.

Description: Need source file plus QQ group [572411121] free request */
@Component
@Aspect
public class LogAspect {

    /** * Log switch level * 1.OFF 2.PART_ON 3.PART_OFF 4.ON *@see LogSwitch
     */
    @Value("${log_aspect_switch_level:1}")
    private int logSwitch;

    NONE 2.TIME_ELAPSE 3.PARAM 4.RESULT *@see LogDimension
     */
    @Value("${log_aspect_dimension_level:1}")
    private int logDimension;

    /** * Method to be processed when logSwitch is 2 signature comma separated * eg. "com.orange.application.xxxClient#getXXX,com.orange.application.xxxClient#getYYY" */
    @Value("{log_aspect_part_on_method}")
    private String partOnMethods;

    /** * Method to exclude when logSwitch is 3 Signature comma separated * eg. "com.orange.application.xxxClient#getXXX,com.orange.application.xxxClient#getYYY" */
    @Value("${log_aspect_part_off_method}")
    private String partOffMethods;
    
    
    
    @Around("@annotation(logAnnotation)")
    // Take around notification
    public Object processLog (ProceedingJoinPoint joinPoint,LogAnnotation logAnnotation) throws Exception {
        // Get the method signature service
        String serviceName = joinPoint.getSignature().getDeclaringTypeName();
        // Get the method signature method name
        String methodName = joinPoint.getSignature().getName();
        String methodSignature = serviceName + "#" + methodName;
        // Check whether the switch is hit
        Boolean isHit = judgeIsHit(methodSignature);
        Object obj = null;
        // Define log output
        List<String> logArray = Lists.newArrayList();
        try {
            if(! isHit) {// If there is no need to print, execute the logic
                obj = joinPoint.proceed();
            }else{
                // Output the log details according to the enumeration level.
                logArray.add(formatParam(joinPoint.getArgs()));
                Stopwatch stopwatch =Stopwatch.createStarted();
                obj = joinPoint.proceed();
                stopwatch.stop();
                // Log statistics Time added to logArray Details Log formatting omitted...
                logArray.add(formatTimeElapse(stopwatch.toString()));
                // Statistics response return value added to logArray details Specific log formatting omitted...logArray.add(formatResult(obj.toString())); }}catch (Exception e) {
            // Handle service exceptions
            dealBizException(e,joinPoint);
        } catch (Throwable throwable) {
            dealException(joinPoint);
        } finally {
            if(isHit){
                // If a match is found, a log is printedlog.info(formatLog(methodSignature,logArray)); }}return obj;
    }
    
    /** * Check whether the signature matches */
    private Boolean judgeIsHit(String methodSignature) {
        if(LogSwitch.of(logSwitch) == null || LogDimension.of(logDimension) == null) {
            // sign log.... No configuration
            return false;
        }
        if(LogSwitch.ON.getCode() == logSwitch){
            // Open all configurations
            return true;
        }
        if(LogSwitch.PART_ON.getCode() == logSwitch) {
            // The configuration part is open, matching partOnMethods
            return! StringUtils.isEmpty(partOnMethods) && partOnMethods.contains(methodSignature); }if(LogSwitch.PART_OFF.getCode() == logSwitch) {
            // The configuration part is open, matching partOffMethods
            return! StringUtils.isEmpty(partOffMethods) && ! partOffMethods.contains(methodSignature); }return false;
    }  
 
Copy the code

To summarize

Dynamic log printing The unified log output by the corresponding Aspect mainly solves the problem that the log output logic is fixed and the log output is excessive. When troubleshooting, the log content cannot be dynamically adjusted. A unified aspect tool that combines Apollo with annotations to dynamically adjust concerns and control log output. It’s also very easy to use, and you need to annotate @LogAnnotation with LogAspect’s method of dynamically managing logs in your code.

With all the above done, you don’t have to worry about checking the interface log anymore. You can configure it as you want.

Those of you who are interested in more about encapsulation, common components, and common code should check out the common Component encapsulation column on the home page.

Original is not easy, like the students of the blogger a little praise, attention attention, well, see you next time.

The last

  • The article is original, original is not easy, thanks for digging gold platform, feel harvest, help three lianha, thank you
  • Wechat search public number: Orange pine Java technology nest, make a friend, into the Internet technology exchange group
  • All code, sequence diagrams and architecture diagrams involved in the article are shared and can be requested free of charge through the public account plus group
  • If the article has the error, welcome the comment message points out, also welcome to reprint, trouble to mark the source is good