Another new feature of the ApiBoot interface service framework

Keywords: Programming Java Spring log4j curl

What is the concept of global logging?

It's easy to understand. Like one of the parts of the logging framework we've always used like logback and log4j, the minbox-logging distributed logging framework is now independent of api-boot-plugins and has joined the minbox-projects open source organization. The blog has a series of articles explaining ApiBoot Logging.) Log component usage and minimal configuration, accessible ApiBoot Component Series Articles Usage Summary Learn more about using the log component.

<hr/>

What is a global log?

Previously, the ApiBoot Logging distributed logging component implemented functions such as log collection, log reporting, log unified storage, integrated Spring Security, integrated Openfeign, and so on. With the release of ApiBoot Logging 2.2.1.RELEASE, a new concept was introduced, that is, GlobalLog.

Students who have used the ApiBoot Logging log component should know that it only records some information related to each send request, such as request parameters, request address, request header information, response content, etc. It does not provide a collection method for debug, info, error level logs in business code, so do not report this log to Logging Admin.

The new version of ApiBoot Logging brings us the spring. In order to facilitate code debugging, monitor business data during execution, it supports the collection of different levels of logs within business code, and also supports the collection of stack information for Exception, so as to locate errors and correct them in time.

Understanding the GlobalLogging interface

To support business global logging, the GlobalLogging interface has been introduced in the new version. Let's first look at the source code for this interface, as follows:


/**
 * Global log collection interface
 * Provide debug, info, and error log collection
 *
 * @author Hengyu Youth
 */
public interface GlobalLogging {
    /**
     * Collect Debug Level Logs
     *
     * @param msg log content
     */
    void debug(String msg);

    /**
     * Collect Debug Level Logs
     *
     * @param format    Unformatted log content
     * @param arguments List of parameters corresponding to log content
     */
    void debug(String format, Object... arguments);

    /**
     * Collect Info Level Logs
     *
     * @param msg log content
     */
    void info(String msg);

    /**
     * Collect Info Level Logs
     *
     * @param format    Unformatted log content
     * @param arguments List of parameters corresponding to log content
     */
    void info(String format, Object... arguments);

    /**
     * Collect Error Level Logs
     *
     * @param msg log content
     */
    void error(String msg);

    /**
     * Collect Error Level Logs
     *
     * @param msg       log content
     * @param throwable Exception object instance
     */
    void error(String msg, Throwable throwable);

    /**
     * Collect Error Level Logs
     *
     * @param format    Unformatted log content
     * @param arguments List of parameters corresponding to log content
     */
    void error(String format, Object... arguments);
}

There are three types of log collection methods available within the GlobalLogging interface: debug, info, error. This version only classifies the levels of logs without adding restrictions or filtering mechanisms.

The current version of GlobalLogging has an implementation class, org.minbox.framework.logging.client.global.support.GlobalLoggingMemoryStorage, which implements all methods within GlobalLogging and saves the collected logs to GlobalLoggingThreadLocal for uniform reporting to Logging Admin.

To facilitate later modifications to the storage of the Global Log, ApiBoot Logging provides a configuration parameter, api.boot.logging.global-logging-storage-away, which defaults to memory and corresponds to the GlobalLoggingMemoryStorage implementation class.

GlobalLogging Automation Configuration

Based on the api.boot.logging.global-logging-storage-away configuration parameters, ApiBoot Logging conditionally determines the implementation class that automatically configures the GlobalLogging interface, as follows:

package org.minbox.framework.api.boot.autoconfigure.logging;
import ...
/**
 * the "minbox-logging" global log storage configuration
 *
 * @author Hengyu Youth
 */
@Configuration
@ConditionalOnClass(GlobalLogging.class)
public class ApiBootLoggingGlobalLogStorageAutoConfiguration {
    /**
     * Instance global log memory mode storage
     *
     * @return {@link GlobalLoggingMemoryStorage}
     */
    @Bean
    @ConditionalOnProperty(prefix = API_BOOT_LOGGING_PREFIX,
        name = "global-logging-storage-away", havingValue = "memory", matchIfMissing = true)
    public GlobalLogging globalLogging() {
        return new GlobalLoggingMemoryStorage();
    }
}

Injecting the annotation @ConditionalOnProperty configuration content based on the conditions on the globalLogging() method tells you that when we add api.boot.logging.global-logging-storage-away=memory to the application.yml configuration file or when the configuration is missing, the method is called, creates a GlobalLoggingMemoryStorage object instance, and writes the instance object to the IOC contentInside, so that when we use a GlobalLogging instance, all we need to do is inject it, as shown below:

/**
  * {@link GlobalLogging}
  *
  * @see org.minbox.framework.logging.client.global.AbstractGlobalLogging
  * @see org.minbox.framework.logging.client.global.support.GlobalLoggingMemoryStorage
  */
@Autowired
private GlobalLogging logging;

Using GlobalLogging

The collection method is simple, we only need to inject the GlobalLogging object, using the method provided by the interface, as follows:

/**
 * Test User Controller
 *
 * @author Hengyu Youth
 */
@RestController
@RequestMapping(value = "/user")
public class UserController {
    /**
     * {@link GlobalLogging}
     *
     * @see org.minbox.framework.logging.client.global.AbstractGlobalLogging
     * @see org.minbox.framework.logging.client.global.support.GlobalLoggingMemoryStorage
     */
    @Autowired
    private GlobalLogging logging;

    /**
     * Test Get User Name
     *
     * @return
     */
    @GetMapping(value = "/name")
    public String getUserName() {
        logging.debug("This is one debug Level Log");
        logging.info("This is one info Level Log");
        return "User name: Hengyu Youth";
    }
}

When we invoke the methods of different log levels provided by GlobalLogging, log-related information is automatically written to the collection of GlobalLoggingThreadLocal and submitted to Logging Admin when the request log is reported, which is saved by Logging Admin.

GlobalLogging table structure

GlobalLogging-related global log collection to Logging Admin needs to be saved, and a table named logging_global_logs is added for all of them, structured as follows:

CREATE TABLE `logging_global_logs` (
  `lgl_id` varchar(36) COLLATE utf8mb4_general_ci NOT NULL COMMENT 'Log Primary Key',
  `lgl_request_log_id` varchar(36) COLLATE utf8mb4_general_ci NOT NULL COMMENT 'Request log number, Association logging_request_logs Primary key',
  `lgl_level` varchar(20) COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT 'Log Level',
  `lgl_content` mediumtext COLLATE utf8mb4_general_ci COMMENT 'Log Content',
  `lgl_caller_class` varchar(200) COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT 'Class name of log output',
  `lgl_caller_method` varchar(50) COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT 'Method name for log output',
  `lgl_caller_code_line_number` int(11) DEFAULT NULL COMMENT 'Code line number of log output',
  `lgl_exception_stack` mediumtext COLLATE utf8mb4_general_ci COMMENT 'error Level Log Exception Stack Information',
  `lgl_create_time` mediumtext COLLATE utf8mb4_general_ci COMMENT 'Log generation time',
  PRIMARY KEY (`lgl_id`),
  KEY `logging_global_logs_logging_request_logs_lrl_id_fk` (`lgl_request_log_id`),
  CONSTRAINT `logging_global_logs_logging_request_logs_lrl_id_fk` FOREIGN KEY (`lgl_request_log_id`) REFERENCES `logging_request_logs` (`lrl_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci COMMENT='Global Log Information Table';

Collect Exception Stack Information

Using GlobalLogging, you can collect detailed stack information that encounters exceptions, allowing us to directly locate where the problem occurs, and solve it in the first place, using the following:

try {
  int a = 5 / 0;
} catch (Exception e) {
  logging.error(e.getMessage(), e);
}

Run tests

Let's run the source code for this chapter and see how the log collection works.

Output Collection Log

{
	"endTime":1576561372604,
	"globalLogs":[{
		"callerClass":"org.minbox.chapter.user.service.UserController",
		"callerCodeLineNumber":33,
		"callerMethod":"getUserName",
		"content":"This is one debug Level log, when:{}",
		"createTime":1576561372585,
		"level":"debug"
	},{
		"callerClass":"org.minbox.chapter.user.service.UserController",
		"callerCodeLineNumber":34,
		"callerMethod":"getUserName",
		"content":"This is one info Level log, time of occurrence: 1576561372586",
		"createTime":1576561372586,
		"level":"info"
	},{
		"callerClass":"org.minbox.chapter.user.service.UserController",
		"callerCodeLineNumber":43,
		"callerMethod":"aa",
		"content":"An exception occurred.",
		"createTime":1576561372586,
		"exceptionStack":"java.lang.ArithmeticException: / by zero\n\tat org.minbox.chapter.user.service.UserController.aa(UserController.java:41)\n\tat org.minbox.chapter.user.service.UserController.getUserName(UserController.java:35)\n\tat sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)\n\tat sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)\n\t....",
		"level":"error"
	}],
	"httpStatus":200,
	"requestBody":"",
	"requestHeaders":{
		"accept":"*/*",
		"host":"localhost:10000",
		"user-agent":"curl/7.64.1"
	},
	"requestIp":"0:0:0:0:0:0:0:1",
	"requestMethod":"GET",
	"requestParam":"{}",
	"requestUri":"/user/name",
	"responseBody":"User name: Hengyu Youth",
	"responseHeaders":{},
	"serviceId":"user-service",
	"serviceIp":"127.0.0.1",
	"servicePort":"10000",
	"spanId":"41a0c852-812b-4a2e-aa4a-228b87ce52f6",
	"startTime":1576561372577,
	"timeConsuming":27,
	"traceId":"42ca9f5a-5977-49cf-909d-a23614a47a6b"
}

The above is the details of a request log that the console outputs, where the globalLogs field is the list of global logs that we collect.

Stored collection logs

Let's confirm if the collection log is saved in the logging_global_logs log table after it is reported to Logging Admin, as follows:

mysql> select * from logging_global_logs order by lgl_create_time asc\G;
*************************** 1. row ***************************
                     lgl_id: 112e36ff-e781-4f11-8f21-2196823cde38
         lgl_request_log_id: f91382e2-2d79-499e-b1df-4757c1ffdbc5
                  lgl_level: info
                lgl_content: This is one info Level log, time of occurrence: 1576561856333
           lgl_caller_class: org.minbox.chapter.user.service.UserController
          lgl_caller_method: getUserName
lgl_caller_code_line_number: 34
        lgl_exception_stack: NULL
            lgl_create_time: 1576561856333
*************************** 2. row ***************************
                     lgl_id: f1d172a6-5cce-4df0-bc29-fe27ac441089
         lgl_request_log_id: f91382e2-2d79-499e-b1df-4757c1ffdbc5
                  lgl_level: debug
                lgl_content: This is one debug Level log, when:{}
           lgl_caller_class: org.minbox.chapter.user.service.UserController
          lgl_caller_method: getUserName
lgl_caller_code_line_number: 33
        lgl_exception_stack: NULL
            lgl_create_time: 1576561856333
*************************** 3. row ***************************
                     lgl_id: d95d850d-3bc9-4689-928a-32c6089ff7a2
         lgl_request_log_id: f91382e2-2d79-499e-b1df-4757c1ffdbc5
                  lgl_level: error
                lgl_content: An exception occurred.
           lgl_caller_class: org.minbox.chapter.user.service.UserController
          lgl_caller_method: getUserName
lgl_caller_code_line_number: 38
        lgl_exception_stack: java.lang.ArithmeticException: / by zero
        at org.minbox.chapter.user.service.UserController.getUserName(UserController.java:36)
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
						...
            lgl_create_time: 1576561856334
3 rows in set (0.01 sec)

There is a lot of stack information abnormal here, which has been omitted.

Knock on the blackboard and lay emphasis on it

This chapter describes the concept of GlobalLog global log in detail, and suggests collecting and reporting GlobalLogs of some important logical judgment to prevent excessive data in the logging_global_logs table.

Refer to the source code in this chapter for detailed usage.

Code Samples

If you like this article, please order Star for Source Warehouse, thank you!!! The sample source code for this article can be obtained in apiboot-logging-use-global-log:

Author Personal Blog Using an open source framework ApiBoot Help you become an Api Interface Service Architect

Posted by xSN1PERxEL1TEx on Tue, 17 Dec 2019 18:12:12 -0800