An overview of the

SpringBoot integration ELK single finger push SpringBoot log to Logstash and use tutorial.

The log process

Export Log files to Elasticsearch — Kibana graphic display

The flow chart is as follows:

Logstash configuration

TCP way

input {
TCP input, Json format encoding UTF-8
    tcp {
     port => 9400
      codec => json {
             charset => "UTF-8"
      }
    }
    stdin{}
}
filter {
}

output {
  elasticsearch {
    action => "index"
Here is the address of es, multiple es to be written as an array
    hosts  => "elasticsearch-server:9200"
# For Kibana filter, you can fill in the name of the item, according to the date generated index
    index  => "vosp-log-%{+YYYY-MM-dd}"
# es user name
    user => vosp
# es password
    password => vosp123
# timeout
    timeout => 300
  }
}
Copy the code

SpringBoot+Log4j2

Introduction of depend on

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
            <exclusions><! -- Remove springBoot default configuration -->
                <exclusion>
                    <groupId>org.springframework.boot</groupId>
                    <artifactId>spring-boot-starter-logging</artifactId>
                </exclusion>
            </exclusions>
        </dependency>

        <dependency> <! Log4j2 dependency -->
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-log4j2</artifactId>
        </dependency>
        
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>
Copy the code

Write SpringBoot boot and configuration classes

Create a new configuration class,


import org.slf4j.MDC;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.context.event.ApplicationEnvironmentPreparedEvent;
import org.springframework.boot.context.event.ApplicationFailedEvent;
import org.springframework.boot.context.event.ApplicationPreparedEvent;
import org.springframework.boot.context.event.ApplicationStartingEvent;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationEvent;
import org.springframework.context.event.ContextClosedEvent;
import org.springframework.context.event.GenericApplicationListener;
import org.springframework.core.Ordered;
import org.springframework.core.ResolvableType;
import org.springframework.core.env.ConfigurableEnvironment;
import org.springframework.core.env.MutablePropertySources;
import org.springframework.core.env.PropertySource;


/ * * *@Author HuangKang
 * @Date2021/4/22 5:44 PM *@Summarize* SpringApplication Application = new SpringApplication(vospapiApplication.class); * Set<ApplicationListener<? >> ls = application.getListeners(); * Log4j2PropertiesEventListener eventListener = new Log4j2PropertiesEventListener(); * application.addListeners(eventListener); * application.run(args); The startup class starts the registration listener */
public class Log4j2PropertiesEventListener implements GenericApplicationListener {

    public static final int DEFAULT_ORDER = Ordered.HIGHEST_PRECEDENCE + 10;

    private staticClass<? >[] EVENT_TYPES = {ApplicationStartingEvent.class, ApplicationEnvironmentPreparedEvent.class, ApplicationPreparedEvent.class, ContextClosedEvent.class, ApplicationFailedEvent.class};private staticClass<? >[] SOURCE_TYPES = {SpringApplication.class, ApplicationContext.class};@Override
    public void onApplicationEvent(ApplicationEvent event) {
        if (event instanceof ApplicationEnvironmentPreparedEvent) {
            ConfigurableEnvironment envi = ((ApplicationEnvironmentPreparedEvent) event).getEnvironment();
            MutablePropertySources mps = envi.getPropertySources();
            Note The SpringBoot configuration source name may be different depending on the version. You can DEBUG the configuration filePropertySource<? > ps = mps.get("configurationProperties");
            // Set the logstash address for log4j2 log collection
            if(ps ! =null && ps.containsProperty("log4j2.logstash.address")) {
                Object address = ps.getProperty("log4j2.logstash.address");
                if(address ! =null && !address.toString().trim().isEmpty()) {
                    MDC.put("log4j2.logstash.address", address.toString()); }}// Set the log4j2 log collection logstash port
            if(ps ! =null && ps.containsProperty("log4j2.logstash.port")) {
                Object port = ps.getProperty("log4j2.logstash.port");
                if(port ! =null && !port.toString().trim().isEmpty()) {
                    MDC.put("log4j2.logstash.port", port.toString()); }}// Set the log4j2 log collection logstash log formatting expression
            if(ps ! =null && ps.containsProperty("log4j2.logstash.pattern")) {
                Object pattern = ps.getProperty("log4j2.logstash.pattern");
                if(pattern ! =null && !pattern.toString().trim().isEmpty()) {
                    // Get the project name
                    String appName = ps.getProperty("spring.application.name").toString();
                    // Get the project name
                    String profile = ps.getProperty("spring.profiles.active").toString();
                    MDC.put("log4j2.logstash.pattern", pattern.toString().replace("${spring.application.name}", appName).replace("${spring.profiles.active}",profile)); }}}}@Override
    public int getOrder(a) {
        return DEFAULT_ORDER;
    }

    @Override
    public boolean supportsEventType(ResolvableType resolvableType) {
        return isAssignableFrom(resolvableType.getRawClass(), EVENT_TYPES);
    }

    @Override
    public boolean supportsSourceType(Class
        sourceType) {
        return isAssignableFrom(sourceType, SOURCE_TYPES);
    }

    private boolean isAssignableFrom(Class
        type, Class
       ... supportedTypes) {
        if(type ! =null) {
            for(Class<? > supportedType : supportedTypes) {if (supportedType.isAssignableFrom(type)) {
                    return true; }}}return false; }}Copy the code

Modify the SpringBoot boot class to add listeners

    public static void main(String[] args) {
        SpringApplication application = new SpringApplication(BootK8sApplication.class);
        // Add Log4j2 configuration file listener
        Log4j2PropertiesEventListener eventListener = new Log4j2PropertiesEventListener();
        application.addListeners(eventListener);
        application.run(args);
    }		
Copy the code

Writing configuration files

Write the following parameters in Yaml

spring:
  application:
Log4j2 is passed as the app name when the project name starts
    name: test-k8s

logging:
# Log4j2 config file XML address
  config: classpath:log4j2-spring.xml
log4j2:
  logstash:
Configure the Logstash address
    address: 124.71.9.101
Configure the Logstash port number
    port: 9400
# Customize Json messages
    # {
# "app": "${spring.application. Name}", the current project name
# "class": "%c", class fully qualified name
# "method": "%M", output log method
# "traceId": "%X{traceId}", traceId tracing
# "level": "%level", log level
Thread # "message" : "[%] [% c: % L] - % replace {% MSG}} {{\ '\ \ \"} \ "body of the message content, will" replace with escape, prevent the log output Json parsing exceptions
# "profile":"${spring.profiles. Active}" The current boot environment
#}
# Json writes attributes to ELK
    pattern: "{\"app\":\"${spring.application.name}\", \"profile\":\"${spring.profiles.active}\", \"class\":\"%c\",\"method\":\"%M\",\"traceId\":\"%X{traceId}\",\"level\": \"%level\", \"message\": \"[%thread] [%c:%L] --- %replace{%msg}{\\\"}{\\\\\\\"}\\\"}%n"
Copy the code

Write the log4j2-xml file


      

<configuration status="info" monitorInterval="30">

    <properties>
        <! -- Log path -->
        <property name="log.path">./logs</property>
        <! -- Log print format -->
        <property name="pattern">%d{yyyy-MM-dd HH:mm:ss,SSS} [%-5level] [%X{traceId}] [%t] [%C{1.}] %msg%n</property>

        <! --SpringBoot read configuration address, port and log format -->
        <Property name="logstashAddress">${ctx:log4j2.logstash.address}</Property>
        <Property name="logstashPort">${ctx:log4j2.logstash.port}</Property>
        <Property name="logstashPattern">${ctx:log4j2.logstash.pattern}</Property>
    </properties>
    <! Define all appenders -->
    <appenders>
        <! -- Configuration of the output console -->
        <console name="console" target="SYSTEM_OUT">
            <! -- Output log format -->
            <PatternLayout>
                <! Console color log format -->
                <Pattern>%style{%d{yyyy-MM-dd HH:mm:ss,SSS}}{bright,white} %highlight{%-5level} %style{[%X{traceId}]}{cyan} [%style{%t}{bright,blue}] [%style{%C{1.}}{bright,yellow}:%L] %msg%n%style{%throwable}{red}</Pattern>
                <! Console unified log format -->
                <! -- <Pattern>${pattern}</Pattern>-->
            </PatternLayout>
            <ThresholdFilter level="info" onMatch="ACCEPT" onMismatch="DENY"/>
        </console>
        <RollingFile name="infoLog" immediateFlush="true" fileName="${sys:log.path}/info.log"
                     filePattern="${sys:log.path}/$${date:yyyy-MM}/info-%d{yyyy-MM-dd}-%i.log.zip">
            <Filters>
                <! -- Console only outputs messages of level and above (onMatch).
                <ThresholdFilter level="INFO" onMatch="ACCEPT" onMismatch="DENY"/>
            </Filters>
            <PatternLayout>
                <Pattern>${pattern}</Pattern>
            </PatternLayout>
            <Policies>
                <TimeBasedTriggeringPolicy interval="1"/>
                <SizeBasedTriggeringPolicy size="100 MB"/>
            </Policies>
        </RollingFile>

        <RollingFile name="warnLog" immediateFlush="true" fileName="${sys:log.path}/warn.log"
                     filePattern="${sys:log.path}/$${date:yyyy-MM}/warn-%d{yyyy-MM-dd}-%i.log.zip">
            <Filters>
                <! -- Console only outputs messages of level and above (onMatch).
                <ThresholdFilter level="warn" onMatch="ACCEPT" onMismatch="DENY"/>
            </Filters>
            <PatternLayout>
                <Pattern>${pattern}</Pattern>
            </PatternLayout>
            <Policies>
                <TimeBasedTriggeringPolicy interval="1"/>
                <SizeBasedTriggeringPolicy size="100 MB"/>
            </Policies>
        </RollingFile>

        <RollingFile name="errorLog" immediateFlush="true" fileName="${sys:log.path}/error.log"
                     filePattern="${sys:log.path}/$${date:yyyy-MM}/error-%d{yyyy-MM-dd}-%i.log.zip">
            <Filters>
                <! -- Console only outputs messages of level and above (onMatch).
                <ThresholdFilter level="ERROR" onMatch="ACCEPT" onMismatch="DENY"/>
            </Filters>
            <PatternLayout>
                <Pattern>${pattern}</Pattern>
            </PatternLayout>
            <Policies>
                <TimeBasedTriggeringPolicy interval="1"/>
                <SizeBasedTriggeringPolicy size="100 MB"/>
            </Policies>
        </RollingFile>
        <! -- Socket TCP pushes log to Logstash. Only INFO and above logs are pushed.
        <Socket>
            <name>logstash</name>
            <protocol>TCP</protocol>
            <port>${logstashPort}</port>
            <host>${logstashAddress}</host>
            <PatternLayout pattern="${logstashPattern}"/>
            <reconnectionDelay>5000</reconnectionDelay>
            <ThresholdFilter level="INFO" onMatch="ACCEPT" onMismatch="DENY"/>
        </Socket>
    </appenders>
    <! An appender will not work until logger is defined and appender is appended.
    <loggers>
        <! -- Filter out useless debug messages -->
        <logger name="org.springframework" level="INFO"/>
        <logger name="org.mybatis" level="INFO"/>
        <logger name="cn.binarywang" level="ERROR"/>
        <! If logger is specified, use logger, if not specified, use root.
        <logger name="com.botpy.vosp.client" level="debug" additivity="false">
            <appender-ref ref="console"/>
            <appender-ref ref="infoLog"/>
            <appender-ref ref="warnLog"/>
            <appender-ref ref="errorLog"/>
        </logger>
        <logger name="logstashLog" level="info" additivity="false">
            <appender-ref ref="logstash"/>
        </logger>
        <root level="debug">
            <appender-ref ref="console"/>
            <appender-ref ref="infoLog"/>
            <appender-ref ref="warnLog"/>
            <appender-ref ref="errorLog"/>
            <appender-ref ref="logstash" />
        </root>
    </loggers>
</configuration>
Copy the code

Added traceId interceptor

Creating an Interceptor


import org.slf4j.MDC;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerInterceptor;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.UUID;

/ * * *@Author HuangKang
 * @Date2021/4/23 2:23 PM *@SummarizeRequest TraceId interceptor */
@Component
public class RequestTraceIdInterceptor implements HandlerInterceptor {
    /** * TRACE_ID Name constant */
    private static final String LOG_TRACE_ID_NAME = "traceId";

    / * * * *@param request
     * @param response
     * @param handler
     * @return
     * @throws Exception
     */
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        MDC.put(LOG_TRACE_ID_NAME, UUID.randomUUID().toString().replace("-".""));
        return true; }}Copy the code

New Mvc configuration interceptor

package com.kang.test.k8s.config;

import com.kang.test.k8s.interceptor.RequestTraceIdInterceptor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

/ * * *@Author HuangKang
 * @Date 2021/4/23 下午4:00
 * @SummarizeCustom WebMvc configuration */
@Configuration
public class CustomWebMvcConfig  implements WebMvcConfigurer {

    final RequestTraceIdInterceptor requestTraceIdInterceptor;

    @Autowired
    public CustomWebMvcConfig(RequestTraceIdInterceptor requestTraceIdInterceptor) {
        this.requestTraceIdInterceptor = requestTraceIdInterceptor;
    }

    /** * Add interceptor *@param registry
     */
    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        // Add TraceId interceptorregistry.addInterceptor(requestTraceIdInterceptor); }}Copy the code

How to use, new Controller test function

    @RequestMapping("/")
    public Map index(a) throws UnknownHostException {
        Map<String, Object> map = new HashMap<>();
        InetAddress localHost = InetAddress.getLocalHost();
        String hostName = localHost.getHostName();
        String hostAddress = localHost.getHostAddress();
        map.put("Host name",hostName);
        map.put("Host address",hostAddress);
        log.info("Test log");
        return map;
    }
Copy the code

The following log is displayed after the interface is invoked

Can see the INFO d9e051ceafe4e59bce8aa6ac2972fda [3] successful print traceId 16:21:13 2021-04-23, 929 INFO d9e051ceafe4e59bce8aa6ac2972fda [3] [HTTP - nio - 8080 - exec - 1] [C.K.T.K.C.T estK8sController: 37] test logCopy the code

SpringBoot+Logback

Introduction of depend on

Introduce dependency normal can

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>

        <dependency>
            <groupId>net.logstash.logback</groupId>
            <artifactId>logstash-logback-encoder</artifactId>
            <version>6.1</version>
        </dependency>
Copy the code

Writing configuration files

spring:
  application:
Write ELK is isolated by app name
    name: test-k8s
  profiles:
Start the environment, ELK isolation separates DEV and PROD by the profile attribute
    active: log
server:
  port: 8080
logging:
Log file address
  config: classpath:logback-spring.xml
Configure the Logstash address
  logstash:
    address: 124.71.9.101:9400
Copy the code

Writing an XML file

Create an XML file, focusing on the ELK Json attribute. You can customize the extension to create logback-spring.xml


      
<configuration>
    <! -- Read configuration path from configuration file and add default value -->
    <! -- Log Global Settings -->
    <springProperty scope="context" name="log.charset" source="log.charset" defaultValue="UTF-8"/>

    <springProperty scope="context" name="log.pattern" source="log.pattern"
                    defaultValue="%d{yyyy-MM-dd HH:mm:ss,SSS} [%-5level] [%X{traceId}] [%t] [%C{1.}] %msg%n"/>

    <! --INFO Log Settings -->
    <springProperty scope="context" name="info.path" source="log.info.path" defaultValue="logs/info"/>
    <springProperty scope="context" name="info.history" source="log.info.history" defaultValue="10"/>
    <springProperty scope="context" name="info.maxsize" source="log.info.maxsize" defaultValue="1GB"/>
    <springProperty scope="context" name="info.filesize" source="log.info.filesize" defaultValue="10MB"/>
    <springProperty scope="context" name="info.pattern" source="log.info.pattern"
                    defaultValue="%date [%thread] %-5level [%logger{50}] %file:%line - %msg%n"/>

    <! --ERROR log Settings -->
    <springProperty scope="context" name="error.path" source="log.error.path" defaultValue="logs/error"/>
    <springProperty scope="context" name="error.history" source="log.error.history" defaultValue="10"/>
    <springProperty scope="context" name="error.maxsize" source="log.error.maxsize" defaultValue="1GB"/>
    <springProperty scope="context" name="error.filesize" source="log.error.filesize" defaultValue="10MB"/>
    <springProperty scope="context" name="error.pattern" source="log.error.pattern"
                    defaultValue="%date [%thread] %-5level [%logger{50}] %file:%line - %msg%n"/>

    <! Read the project name, environment, and logstash address from the SpringBoot configuration file.
    <springProperty scope="context" name="springAppName" source="spring.application.name"/>
    <springProperty scope="context" name="springProfile" source="spring.profiles.active"/>
    <springProperty scope="context" name="logstashAddress" source="logging.logstash.address"/>

    <! -- Color log -->
    <! -- Color log dependent render class -->
    <conversionRule conversionWord="clr" converterClass="org.springframework.boot.logging.logback.ColorConverter"/>
    <conversionRule conversionWord="wex"
                    converterClass="org.springframework.boot.logging.logback.WhitespaceThrowableProxyConverter"/>
    <conversionRule conversionWord="wEx"
                    converterClass="org.springframework.boot.logging.logback.ExtendedWhitespaceThrowableProxyConverter"/>
    <! -- Define color log format template -->

    <! Console log print format -->
    <appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
        <filter class="ch.qos.logback.classic.filter.LevelFilter">
            <level>INFO</level>
        </filter>
        <encoder>
            <pattern>${log.pattern}</pattern>
            <charset>${log.charset}</charset>
        </encoder>
    </appender>

    <! --INFO Log print -->
    <appender name="FILE_INFO" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <! If you only want Info level logs, you will still get Error logs if you only want Info level logs. Because the Error level is high, you can use the following policy to avoid Error logs.
        <filter class="ch.qos.logback.classic.filter.LevelFilter">
            <! - the filtering Error -- -- >
            <level>ERROR</level>
            <! -->
            <onMatch>DENY</onMatch>
            <! --> < span style = "color: RGB (51, 51, 51);
            <onMismatch>ACCEPT</onMismatch>
        </filter>
        <! If there is both <File> and <FileNamePattern>, then the current log is <File>, and tomorrow it will automatically rename today's log to today's date. That is, the logs in <File> are from the current day. -->
        <! --<File>logs/info.spring-boot-demo-logback.log</File>-->
        <! TimeBasedRollingPolicy-->
        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
            <! File path, which defines how to split logs -- archive logs for each day into a file to prevent logs from filling the disk space -->
            <FileNamePattern>${info.path}/info_%d{yyyy-MM-dd}.part_%i.log</FileNamePattern>
            <! Save only logs generated in the last 10 days.
            <maxHistory>${info.history}</maxHistory>
            <! -- Specifies the maximum size of the log file, at which the old log file will be deleted -->
            <totalSizeCap>${info.maxsize}</totalSizeCap>
            <timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
                <! -- maxFileSize: This is the size of the active file. The default value is 10MB, and this is set to 1KB for demonstration purposes -->
                <maxFileSize>${info.filesize}</maxFileSize>
            </timeBasedFileNamingAndTriggeringPolicy>
        </rollingPolicy>
        <! --<triggeringPolicy class="ch.qos.logback.core.rolling.SizeBasedTriggeringPolicy">-->
        <! --<maxFileSize>1KB</maxFileSize>-->
        <! --</triggeringPolicy>-->
        <encoder>
            <pattern>${info.pattern}</pattern>
            <charset>${log.charset}</charset> <! -- Set character set -->
        </encoder>
    </appender>
    <! --ERROR log print -->
    <appender name="FILE_ERROR" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <! ThresholdFilter--> ThresholdFilter-->
        <filter class="ch.qos.logback.classic.filter.ThresholdFilter">
            <level>ERROR</level>
        </filter>
        <! If there is both <File> and <FileNamePattern>, then the current log is <File>, and tomorrow it will automatically rename today's log to today's date. That is, the logs in <File> are from the current day. -->
        <! --<File>logs/error.spring-boot-demo-logback.log</File>-->
        <! TimeBasedRollingPolicy-->
        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
            <! File path, which defines how to split logs -- archive logs for each day into a file to prevent logs from filling the disk space -->
            <FileNamePattern>${error.path}/error_%d{yyyy-MM-dd}.part_%i.log</FileNamePattern>
            <! Save only logs generated in the last 90 days.
            <maxHistory>${error.history}</maxHistory>
            <! -- Specifies the maximum size of the log file, at which the old log file will be deleted -->
            <totalSizeCap>${error.maxsize}</totalSizeCap>
            <timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
                <! -- maxFileSize: This is the size of the active file. The default value is 10MB, and this is set to 1KB for demonstration purposes -->
                <maxFileSize>${error.filesize}</maxFileSize>
            </timeBasedFileNamingAndTriggeringPolicy>
        </rollingPolicy>
        <encoder>
            <pattern>${error.pattern}</pattern>
            <charset>${log.charset}</charset> <! -- Set character set -->
        </encoder>
    </appender>


    <appender name="logstash" class="net.logstash.logback.appender.LogstashTcpSocketAppender">
        <destination>${logstashAddress}</destination>
        <filter class="ch.qos.logback.classic.filter.ThresholdFilter">
            <level>INFO</level>
        </filter>
        <encoder class="net.logstash.logback.encoder.LoggingEventCompositeJsonEncoder">
            <providers>
                <timestamp>
                    <timeZone>UTC</timeZone>
                </timestamp>
                <pattern>
                    <pattern>
                        {
                        <! -- Set project -->
                        "app": "${springAppName:-}",
                        <! -- Set environment -->
                        "profile": "${springProfile:-}",
                        <! -- Set the level -->
                        "level": "%level",
                        <! - set the traceId -- -- >
                        "traceId": "%X{traceId}",
                        <! -- Set class name -->
                        "class": "%c",
                        <! -- Set method name -->
                        "method": "%M",
                        <! -- Set message -->
                        "message": "[%thread] [%X{traceId}] [%logger{35}:%L] --- %msg"
                        }
                    </pattern>
                </pattern>
            </providers>
        </encoder>
    </appender>

    <root level="info">
        <appender-ref ref="CONSOLE"/>
        <appender-ref ref="FILE_INFO"/>
        <appender-ref ref="FILE_ERROR"/>
        <appender-ref ref="logstash"/>
    </root>

</configuration>
Copy the code

Added traceId interceptor

See Log4j2 above

Kibana use

Modify the time display format

Open the menu -> Open Stack Management -> Find Kibana -> Select Advanced Settings -> Modify date format

Creating a Log View

Open the menu -> Open Stack Management -> Find Kibana -> Select Index mode -> click Create Index mode

Enter log expression, match format, match log index and click Next

Select the time field. The TCP Logstash log will be automatically generated after being pushed. Select the log and click Create Index mode

Using the Log View

Open the menu –> Open Discover –> click enter

Open the menu -> Open Discover -> click the drop – down box to select the index matcher created to open the log view

Log filter

Click Add Filter, select the operator is (equal), and set the log level to filter

Viewing specified Information

Click Message, click Add Message, and just view the Message

Click and view the result as follows

Added Log View Chart Analysis

Open the menu -> Open Dashboard -> Click Create -> Click Create Panel -> Create Lens Select your chart and log field to display statistics