ELK 日志采集框架:日志模块开发

Posted AusKa_T

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了ELK 日志采集框架:日志模块开发相关的知识,希望对你有一定的参考价值。

1 资源

资源信息版本号备注
springboot2.1.5.RELEASE

springboot-elk-demo 源码 下载:https://download.csdn.net/download/qq_15769939/16756675

2 配置信息

2.1 pom文件

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.1.5.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>

    <groupId>com.auskat.demo</groupId>
    <artifactId>springboot-elk-demo</artifactId>
    <version>1.0-SNAPSHOT</version>

    <properties>
        <maven.compiler.source>8</maven.compiler.source>
        <maven.compiler.target>8</maven.compiler.target>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
            <!-- 	排除spring-boot-starter-logging -->
            <exclusions>
                <exclusion>
                    <groupId>org.springframework.boot</groupId>
                    <artifactId>spring-boot-starter-logging</artifactId>
                </exclusion>
            </exclusions>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
        </dependency>
        <!-- log4j2 -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-log4j2</artifactId>
        </dependency>
        <dependency>
            <groupId>com.lmax</groupId>
            <artifactId>disruptor</artifactId>
            <version>3.3.4</version>
        </dependency>

        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>fastjson</artifactId>
            <version>1.2.58</version>
        </dependency>
    </dependencies>

    <build>
        <finalName>collector</finalName>
        <!-- 打包时包含properties、xml -->
        <resources>
            <resource>
                <directory>src/main/java</directory>
                <includes>
                    <include>**/*.properties</include>
                    <include>**/*.xml</include>
                </includes>
                <!-- 是否替换资源中的属性-->
                <filtering>true</filtering>
            </resource>
            <resource>
                <directory>src/main/resources</directory>
            </resource>
        </resources>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
                <configuration>
                    <mainClass>com.auskat.demo.elk.Application</mainClass>
                </configuration>
            </plugin>
        </plugins>
    </build>
</project>

2.2 配置信息

2.2.1 application.yml

# 设置访问路径
server.servlet.context-path=/
# 设置端口号
server.port=8001
# 设置应用名称
spring.application.name=springboot-elk-demo
# 设置http编码
spring.http.encoding.charset=UTF-8
# 设置时间格式标准
spring.jackson.date-format=yyyy-MM-dd HH:mm:ss
# 设置时区
spring.jackson.time-zone=GMT+8
# 设置JSON默认格式化字段规则
spring.jackson.default-property-inclusion=NON_NULL

3.2.2 log4j2.xml

<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="INFO" schema="Log4J-V2.0.xsd" monitorInterval="600" >
    <Properties>
        <!-- 输出 日志文件路径 -->
        <Property name="LOG_HOME">logs</Property>
        <!-- 输出 日志文件名称 -->
        <property name="FILE_NAME">elk-demo</property>
        <!-- 输出 日志格式 -->
        <property name="patternLayout">[%d{yyyy-MM-dd'T'HH:mm:ss.SSSZZ}] [%level{length=5}] [%thread-%tid] [%logger] [%X{hostName}] [%X{ip}] [%X{applicationName}] [%F,%L,%C,%M] [%m] ## '%ex'%n</property>
    </Properties>
    <Appenders>
        <!-- 输出的组件 -->
        <Console name="CONSOLE" target="SYSTEM_OUT">
            <PatternLayout pattern="${patternLayout}"/>
        </Console>
        <!-- 输出 常规日志 -->
        <RollingRandomAccessFile name="appAppender" fileName="${LOG_HOME}/app-${FILE_NAME}.log" filePattern="${LOG_HOME}/app-${FILE_NAME}-%d{yyyy-MM-dd}-%i.log" >
            <PatternLayout pattern="${patternLayout}" />
            <Policies>
                <TimeBasedTriggeringPolicy interval="1"/>
                <SizeBasedTriggeringPolicy size="500MB"/>
            </Policies>
            <DefaultRolloverStrategy max="20"/>
        </RollingRandomAccessFile>
        <!-- 输出 错误日志 -->
        <RollingRandomAccessFile name="errorAppender" fileName="${LOG_HOME}/error-${FILE_NAME}.log" filePattern="${LOG_HOME}/error-${FILE_NAME}-%d{yyyy-MM-dd}-%i.log" >
            <PatternLayout pattern="${patternLayout}" />
            <!-- 允许 waring级别以上的日志收集  -->
            <Filters>
                <ThresholdFilter level="warn" onMatch="ACCEPT" onMismatch="DENY"/>
            </Filters>
            <Policies>
                <TimeBasedTriggeringPolicy interval="1"/>
                <SizeBasedTriggeringPolicy size="500MB"/>
            </Policies>
            <DefaultRolloverStrategy max="20"/>
        </RollingRandomAccessFile>
    </Appenders>
    <Loggers>
        <!-- 业务相关 异步logger -->
        <AsyncLogger name="com.auskat.*" level="info" includeLocation="true">
            <AppenderRef ref="appAppender"/>
        </AsyncLogger>
        <AsyncLogger name="com.auskat.*" level="info" includeLocation="true">
            <AppenderRef ref="errorAppender"/>
        </AsyncLogger>
        <Root level="info">
            <Appender-Ref ref="CONSOLE"/>
            <Appender-Ref ref="appAppender"/>
            <AppenderRef ref="errorAppender"/>
        </Root>
    </Loggers>
</Configuration>

3 功能实现

3.1 messge对象

package com.auskat.demo.elk.entity;

import lombok.Data;

/**
 * 类文件: AccurateWatcherMessage
 * <p>
 * <p>
 * 类描述:
 * <p>
 * 作     者: AusKa_T
 * <p>
 * 日     期: 2021/3/28 0028
 * <p>
 * 时     间: 14:07
 * <p>
 */
@Data
public class AccurateWatcherMessage {

    /**
     * 标题
     */
    private String title;

    /**
     * 执行时间
     */
    private String executionTime;

    /**
     * 业务名称
     */
    private String applicationName;

    /**
     * 等级
     */
    private String level;

    /**
     * 内容
     */
    private String body;
}

3.2 工具类

3.2.1 NetUtil

package com.auskat.demo.elk.utils;

import java.lang.management.ManagementFactory;
import java.lang.management.RuntimeMXBean;
import java.net.InetAddress;
import java.net.NetworkInterface;
import java.net.SocketAddress;
import java.net.UnknownHostException;
import java.nio.channels.SocketChannel;
import java.util.Enumeration;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * 类文件: NetUtil
 * <p>
 * <p>
 * 类描述:
 * <p>
 * 作     者: AusKa_T
 * <p>
 * 日     期: 2021/3/26 0026
 * <p>
 * 时     间: 14:14
 * <p>
 */
public class NetUtil {

    public static String normalizeAddress(String address){
        String[] blocks = address.split("[:]");
        if(blocks.length > 2){
            throw new IllegalArgumentException(address + " is invalid");
        }
        String host = blocks[0];
        int port = 80;
        if(blocks.length > 1){
            port = Integer.valueOf(blocks[1]);
        } else {
            address += ":"+port; //use default 80
        }
        String serverAddr = String.format("%s:%d", host, port);
        return serverAddr;
    }

    public static String getLocalAddress(String address){
        String[] blocks = address.split("[:]");
        if(blocks.length != 2){
            throw new IllegalArgumentException(address + " is invalid address");
        }
        String host = blocks[0];
        int port = Integer.valueOf(blocks[1]);

        if("0.0.0.0".equals(host)){
            return String.format("%s:%d",NetUtil.getLocalIp(), port);
        }
        return address;
    }

    private static int matchedIndex(String ip, String[] prefix){
        for(int i=0; i<prefix.length; i++){
            String p = prefix[i];
            if("*".equals(p)){ //*, assumed to be IP
                if(ip.startsWith("127.") ||
                        ip.startsWith("10.") ||
                        ip.startsWith("172.") ||
                        ip.startsWith("192.")){
                    continue;
                }
                return i;
            } else {
                if(ip.startsWith(p)){
                    return i;
                }
            }
        }

        return -1;
    }

    public static String getLocalIp(String ipPreference) {
        if(ipPreference == null){
            ipPreference = "*>10>172>192>127";
        }
        String[] prefix = ipPreference.split("[> ]+");
        try {
            Pattern pattern = Pattern.compile("[0-9]+\\\\.[0-9]+\\\\.[0-9]+\\\\.[0-9]+");
            Enumeration<NetworkInterface> interfaces = NetworkInterface.getNetworkInterfaces();
            String matchedIp = null;
            int matchedIdx = -1;
            while (interfaces.hasMoreElements()) {
                NetworkInterface ni = interfaces.nextElement();
                Enumeration<InetAddress> en = ni.getInetAddresses();
                while (en.hasMoreElements()) {
                    InetAddress addr = en.nextElement();
                    String ip = addr.getHostAddress();
                    Matcher matcher = pattern.matcher(ip);
                    if (matcher.matches()) {
                        int idx = matchedIndex(ip, prefix);
                        if(idx == -1) continue;
                        if(matchedIdx == -1){
                            matchedIdx = idx;
                            matchedIp = ip;
                        } else {
                            if(matchedIdx>idx){
                                matchedIdx = idx;
                                matchedIp = ip;
                            }
                        }
                    }
                }
            }
            if(matchedIp != null) return matchedIp;
            return "127.0.0.1";
        } catch (Exception e) {
            return "127.0.0.1";
        }
    }

    public static String getLocalIp() {
        return getLocalIp("*>10>172>192>127");
    }

    public static String remoteAddress(SocketChannel channel){
        SocketAddress addr = channel.socket().getRemoteSocketAddress以上是关于ELK 日志采集框架:日志模块开发的主要内容,如果未能解决你的问题,请参考以下文章

ELK 日志采集框架:Kafka安装与配置

常用日志采集框架对比

ELK 日志采集框架:架构设计

ELK 日志采集框架:Filebeat安装与配置

ELK 日志采集框架:Kibana安装与配置

ELK 日志采集框架:ElasticSearch安装与配置