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

1 资源

资源信息 版本号 备注
springboot 2.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
                    **/*.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


<Configuration status="INFO" schema="Log4J-V2.0.xsd" monitorInterval="600" >
    <Properties>
        
        <Property name="LOG_HOME">logsProperty>
        
        <property name="FILE_NAME">elk-demoproperty>
        
        <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'%nproperty>
    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}" />
            
            <Filters>
                <ThresholdFilter level="warn" onMatch="ACCEPT" onMismatch="DENY"/>
            Filters>
            <Policies>
                <TimeBasedTriggeringPolicy interval="1"/>
                <SizeBasedTriggeringPolicy size="500MB"/>
            Policies>
            <DefaultRolloverStrategy max="20"/>
        RollingRandomAccessFile>
    Appenders>
    <Loggers>
        
        <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
 * 

*

* 类描述: *

* 作 者: AusKa_T *

* 日 期: 2021/3/28 0028 *

* 时 间: 14:07 *

*/ @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
 * 

*

* 类描述: *

* 作 者: AusKa_T *

* 日 期: 2021/3/26 0026 *

* 时 间: 14:14 *

*/ 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(); String res = String.format("%s", addr); return res; } public static String localAddress(SocketChannel channel){ SocketAddress addr = channel.socket().getLocalSocketAddress(); String res = String.format("%s", addr); return addr==null? res: res.substring(1); } public static String getPid(){ RuntimeMXBean runtime = ManagementFactory.getRuntimeMXBean(); String name = runtime.getName(); int index = name.indexOf("@"); if (index != -1) { return name.substring(0, index); } return null; } public static String getLocalHostName() { try { return (InetAddress.getLocalHost()).getHostName(); } catch (UnknownHostException uhe) { String host = uhe.getMessage(); if (host != null) { int colon = host.indexOf(':'); if (colon > 0) { return host.substring(0, colon); } } return "UnknownHost"; } } }

3.2.2 InputMDC

package com.auskat.demo.elk.utils;

import org.jboss.logging.MDC;
import org.springframework.context.EnvironmentAware;
import org.springframework.core.env.Environment;
import org.springframework.stereotype.Component;

/**
 * 类文件: InputMDC
 * 

*

* 类描述: *

* 作 者: AusKa_T *

* 日 期: 2021/3/26 0026 *

* 时 间: 14:13 *

*/ @Component public class InputMDC implements EnvironmentAware { private static Environment environment; @Override public void setEnvironment(Environment environment) { InputMDC.environment = environment; } public static void putMDC() { MDC.put("hostName", NetUtil.getLocalHostName()); MDC.put("ip", NetUtil.getLocalIp()); MDC.put("applicationName", environment.getProperty("spring.application.name")); } }

3.2.3 FastJsonConverUtil

package com.auskat.demo.elk.utils;

import java.util.ArrayList;
import java.util.List;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.serializer.SerializerFeature;

import lombok.extern.slf4j.Slf4j;

/**
 * 类文件: FastJsonConvertUtil
 * 

*

* 类描述: *

* 作 者: AusKa_T *

* 日 期: 2021/3/26 0026 *

* 时 间: 14:13 *

*/ @Slf4j public class FastJsonConvertUtil { private static final SerializerFeature[] featuresWithNullValue = { SerializerFeature.WriteMapNullValue, SerializerFeature.WriteNullBooleanAsFalse, SerializerFeature.WriteNullListAsEmpty, SerializerFeature.WriteNullNumberAsZero, SerializerFeature.WriteNullStringAsEmpty }; /** * 方法名称:将JSON字符串转换为实体对象
* 概要说明:将JSON字符串转换为实体对象
* @author hezhuo.bai * @since 2019年1月15日 下午4:53:49 * @param data JSON字符串 * @param clzss 转换对象 * @return T */
public static <T> T convertJSONToObject(String data, Class<T> clzss) { try { T t = JSON.parseObject(data, clzss); return t; } catch (Exception e) { log.error("convertJSONToObject Exception", e); return null; } } /** * 方法名称:将JSONObject对象转换为实体对象
* 概要说明:将JSONObject对象转换为实体对象
* @author hezhuo.bai * @since 2019年1月15日 下午4:54:32 * @param data JSONObject对象 * @param clzss 转换对象 * @return T */
public static <T> T convertJSONToObject(JSONObject data, Class<T> clzss) { try { T t = JSONObject.toJavaObject(data, clzss); return t; } catch (Exception e) { log.error("convertJSONToObject Exception", e); return null; } } /** * 方法名称:将JSON字符串数组转为List集合对象
* 概要说明:将JSON字符串数组转为List集合对象
* @author hezhuo.bai * @since 2019年1月15日 下午4:54:50 * @param data JSON字符串数组 * @param clzss 转换对象 * @return List集合对象 */
public static <T> List<T> convertJSONToArray(String data, Class<T> clzss) { try { List<T> t = JSON.parseArray(data, clzss); return t; } catch (Exception e) { log.error("convertJSONToArray Exception", e); return null; } } /** * 方法名称:将List转为List集合对象
* 概要说明:将List转为List集合对象
* @author hezhuo.bai * @since 2019年1月15日 下午4:55:11 * @param data List * @param clzss 转换对象 * @return List集合对象 */
public static <T> List<T> convertJSONToArray(List<JSONObject> data, Class<T> clzss) { try { List<T> t = new ArrayList<T>(); for (JSONObject jsonObject : data) { t.add(convertJSONToObject(jsonObject, clzss)); } return t; } catch (Exception e) { log.error("convertJSONToArray Exception", e); return null; } } /** * 方法名称:将对象转为JSON字符串
* 概要说明:将对象转为JSON字符串
* @author hezhuo.bai * @since 2019年1月15日 下午4:55:41 * @param obj 任意对象 * @return JSON字符串 */
public static String convertObjectToJSON(Object obj) { try { String text = JSON.toJSONString(obj); return text; } catch (Exception e) { log.error("convertObjectToJSON Exception", e); return null; } } /** * 方法名称:将对象转为JSONObject对象
* 概要说明:将对象转为JSONObject对象
* @author hezhuo.bai * @since 2019年1月15日 下午4:55:55 * @param obj 任意对象 * @return JSONObject对象 */
public static JSONObject convertObjectToJSONObject(Object obj){ try { JSONObject jsonObject = (JSONObject) JSONObject.toJSON(obj); return jsonObject; } catch (Exception e) { log.error("convertObjectToJSONObject Exception", e); return null; } } public static String convertObjectToJSONWithNullValue(Object obj) { try { String text = JSON.toJSONString(obj, featuresWithNullValue); return text; } catch (Exception e) { log.error("convertObjectToJSONWithNullValue Exception", e); return null; } } }

3.3 接口

3.3.1 日志接口

package com.auskat.demo.elk.controller;

import com.auskat.demo.elk.utils.InputMDC;
import org.jboss.logging.MDC;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;


import lombok.extern.slf4j.Slf4j;

/**
 * 类文件: IndexController
 * 

*

* 类描述: *

* 作 者: AusKa_T *

* 日 期: 2021/3/26 0026 *

* 时 间: 14:15 *

*/ @Slf4j @RestController public class IndexController { /** * [%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] F 当前执行类, L 行数, C class ,M method * [%m] ## '%ex'%n * ----------------------------------------------- * [2019-09-18T14:42:51.451+08:00] * [INFO] * [main-1] * [org.springframework.boot.web.embedded.tomcat.TomcatWebServer] * [] * [] * [] * [TomcatWebServer.java,90,org.springframework.boot.web.embedded.tomcat.TomcatWebServer,initialize] * [Tomcat initialized with port(s): 8001 (http)] ## '' * * ["message", * "\[%{NOTSPACE:currentDateTime}\] * \[%{NOTSPACE:level}\] * \[%{NOTSPACE:thread-id}\] * \[%{NOTSPACE:class}\] * \[%{DATA:hostName}\] * \[%{DATA:ip}\] * \[%{DATA:applicationName}\] * \[%{DATA:location}\] * \[%{DATA:messageInfo}\] * ## (\'\'|%{QUOTEDSTRING:throwable})"] * @return */ @RequestMapping(value = "/index") public String index() { // MDC 当前线程绑定的局部变量 InputMDC.putMDC(); log.info("我是一条info日志"); log.warn("我是一条warn日志"); log.error("我是一条error日志"); return "idx"; } @RequestMapping(value = "/err") public String err() { InputMDC.putMDC(); try { int a = 1/0; } catch (Exception e) { log.error("算术异常", e); } return "err"; } }

3.3.2 告警接口

package com.auskat.demo.elk.controller;

import com.alibaba.fastjson.JSON;
import com.auskat.demo.elk.entity.AccurateWatcherMessage;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

/**
 * 类文件: WatcherController
 * 

*

* 类描述: *

* 作 者: AusKa_T *

* 日 期: 2021/3/28 0028 *

* 时 间: 14:06 *

*/ @RestController public class WatcherController { @RequestMapping(value ="/accurateWatch") public String watch(@RequestBody AccurateWatcherMessage accurateWatcherMessage) { String ret = JSON.toJSONString(accurateWatcherMessage); System.err.println("----告警内容----:" + ret); return "is watched" + ret; } }

4 相关信息

第①篇:ELK 日志采集框架(一):架构设计

第②篇:ELK 日志采集框架(二):日志模块开发

第③篇:ELK 日志采集框架(三):Filebeat安装与配置

第④篇:ELK 日志采集框架(四):Kafka安装与配置

第⑤篇:ELK 日志采集框架(五):Logstash安装与配置

第⑥篇:ELK 日志采集框架(六):ElasticSearch安装与配置

第⑦篇:ELK 日志采集框架(七):Kibana安装与配置

第⑧篇:ELK 日志采集框架(八):功能测试与告警集成

博文不易,辛苦各位猿友点个关注和赞,感谢

你可能感兴趣的:(ELK,日志采集框架,elk)