【ELK】springboot + ELK

发布时间 2023-04-27 14:33:43作者: 日月星宿

 

 

添加依赖:(注意依赖版本)

        <!-- logstash -->
        <dependency>
            <groupId>net.logstash.logback</groupId>
            <artifactId>logstash-logback-encoder</artifactId>
            <version>5.3</version>
        </dependency>

测试时使用的 spring-boot-starter-parent 版本为2.7.1

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

logback配置文件:logback-spring.xml

<?xml version="1.0" encoding="UTF-8"?>

<!-- debug:打印logback内部日志信息,实时查看logback的运行状态,默认为false -->
<!-- scan:配置文件如果发生改变,是否被重新加载,默认为true。 -->
<!-- scanPeriod:设置检测配置文件是否有修改的时间间隔,如果没有给出时间单位,默认单位是毫秒,默认的时间间隔为1分钟,默认为true。 -->

<configuration debug="false" scan="false" scanPeriod="30 seconds">

    <contextName>Application</contextName>

    <!-- 时间戳定义,timeReference:使用日志产生日期为时间基准 -->
    <timestamp key="byDay" datePattern="yyyy-MM-dd" timeReference="contextBirth"/>

    <!-- 定义日志文件的存储地址 勿在 LogBack 的配置中使用相对路径,可以使用系统变量 -->
    <!-- <property name="LOG_HOME" value="${app.home}/log" /> -->
    <!-- 日志会放在项目根路径下的 logdir 目录 -->
    <property name="LOG_HOME" value="logdir"/>

    <!-- 控制台输出,生产环境将请stdout去掉 -->
    <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
        <encoder>
            <!--格式化输出:%d表示日期,%thread表示线程名,%-5level:级别从左显示5个字符宽度,%msg:日志消息,%n是换行符 -->
            <pattern>
                %d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n
            </pattern>
        </encoder>
    </appender>


    <!-- file for all 打印所有日志 -->
    <appender name="FILE-ALL" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <!-- 日志输出文件 -->
        <file>${LOG_HOME}/LoggingBack-${byDay}.log</file>
        <!-- 追加日志到原文件结尾 -->
        <append>true</append>
        <!-- timebasedrollingpolicy:演示时间和大小为基础的日志文件归档 -->
        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
            <!-- 归档的日志文件的路径,例如今天是2013-12-21日志,当前写的日志文件路径为file节点指定。 -->
            <!--可以将此文件与file指定文件路径设置为不同路径,从而将当前日志文件或归档日志文件置不同的目录。 -->
            <!--而2013-12-21的日志文件在由fileNamePattern指定。%d{yyyy-MM-dd}指定日期格式,%i指定索引 -->
            <!-- 文件滚动日期格式:每天:.YYYY-MM-dd(默认);每星期:.YYYY-ww;每月:.YYYY-MM -->
            <!-- 每隔半天:.YYYY-MM-dd-a;每小时:.YYYY-MM-dd-HH;每分钟:.YYYY-MM-dd-HH-mm -->
            <fileNamePattern>${LOG_HOME}/log-%d{yyyy-MM-dd}.%i.log</fileNamePattern>
            <!-- 控制归档文件的最大数量的保存,删除旧的文件,默认单位天数 -->
            <maxHistory>7</maxHistory>
            <!-- 设置当前日志的文件的大小,决定日志翻滚 -->
            <timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
                <!-- 除按日志记录之外,还配置了日志文件不能超过10M(默认),若超过10M,日志文件会以索引0开始, -->
                <maxFileSize>10MB</maxFileSize>
            </timeBasedFileNamingAndTriggeringPolicy>
        </rollingPolicy>
        <encoder>
            <pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger - %msg%n
            </pattern>
        </encoder>
    </appender>


    <!-- file for info 只打印 info 级别的日志 -->
    <appender name="FILE-INFO" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <!-- 这里添加一个过滤器 -->
        <file>${LOG_HOME}/LoggingBack-info.log</file>
        <filter class="ch.qos.logback.classic.filter.LevelFilter">
            <level>INFO</level>
            <onMatch>ACCEPT</onMatch>
            <onMismatch>DENY</onMismatch>
        </filter>
        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
            <fileNamePattern>${LOG_HOME}/LOG-INFO-%d{yyyy-MM-dd}.%i.log</fileNamePattern>
            <maxHistory>7</maxHistory>
            <timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
                <maxFileSize>10MB</maxFileSize>
            </timeBasedFileNamingAndTriggeringPolicy>
        </rollingPolicy>
        <encoder>
            <pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger - %msg%n
            </pattern>
        </encoder>
    </appender>


    <!-- file for error 只打印 error 级别的日志-->
    <appender name="FILE-ERROR" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <file>${LOG_HOME}/LoggingBack-error.log</file>
        <filter class="ch.qos.logback.classic.filter.LevelFilter">
            <level>ERROR</level>
            <onMatch>ACCEPT</onMatch>
            <onMismatch>DENY</onMismatch>
        </filter>
        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
            <fileNamePattern>${LOG_HOME}/LOG-ERROR-%d{yyyy-MM-dd}.%i.log</fileNamePattern>
            <maxHistory>7</maxHistory>
            <timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
                <maxFileSize>10MB</maxFileSize>
            </timeBasedFileNamingAndTriggeringPolicy>
        </rollingPolicy>
        <encoder>
            <pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger - %msg%n
            </pattern>
        </encoder>
    </appender>


    <!-- 输出到logstash的相关日志 appender-->
    <appender name="LOGSTASH" class="net.logstash.logback.appender.LogstashTcpSocketAppender">
        <!-- 配置可以访问的logstash日志收集端口 -->
        <destination>127.0.0.1:4560</destination>
        <!--        <encoder charset="UTF-8" class="net.logstash.logback.encoder.LogstashEncoder">-->
        <!--            &lt;!&ndash; 在elasticsearch的index中追加applicationName字段 &ndash;&gt;-->
        <!--            <customFields>{"applicationName":"logstash-test"}</customFields>-->
        <!--        </encoder>-->
        <encoder charset="UTF-8" class="net.logstash.logback.encoder.LoggingEventCompositeJsonEncoder">
            <providers>
                <timestamp>
                    <timeZone>Asia/Shanghai</timeZone>
                </timestamp>
                <!--自定义日志输出格式-->
                <pattern>
                    <pattern>
                        {
                        "project": "wxpublic",
                        "level": "%level",
                        "service": "${APP_NAME:-}",
                        "pid": "${PID:-}",
                        "thread": "%thread",
                        "class": "%logger",
                        "message": "%message",
                        "stack_trace": "%exception{20}"
                        }
                    </pattern>
                </pattern>
            </providers>
        </encoder>

    </appender>
    <!-- 号码相关信息日志,输出到logstash--> 
    <logger name="logStashTest01Log" level="INFO" additivity="true">      
        <appender-ref ref="LOGSTASH"/>    
    </logger>

    <!-- root,所有logger标签的父类,若 logger标签中的additivity=false,则日志不重复输出,以子类为准。 -->
    <root level="INFO">
        <appender-ref ref="STDOUT"/>
        <appender-ref ref="FILE-ALL"/>
        <appender-ref ref="FILE-INFO"/>
        <appender-ref ref="FILE-ERROR"/>
    </root>

</configuration>

application.yml 配置文件:

server:
  port: 1654

logging:
  config: classpath:logback-spring.xml
  # config: logstash-test/src/main/resources/logback-spring.xml
  level:
    com.eastcom: debug

创建日志类:

import com.ryxx.util.StringUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;

@Component
public class LogStashLog {
    private Logger logStashTest01Log = LoggerFactory.getLogger("logStashTest01Log");
//    public void saveLogStashTest01Log(String info) {
//        logStashTest01Log.info("info[{}]", info);
//    }
    public void saveLogStashTest01Log(String info) {
        logStashTest01Log.info(info);
    }
}

创建测试接口:

import com.fasterxml.jackson.databind.ObjectMapper;
import com.ryxx.log.LogStashLog;
import com.ryxx.pojo.Example;
import com.ryxx.util.StringUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.servlet.http.HttpServletRequest;

@Slf4j
@RestController
public class Test01Controller {
    @Autowired
    private LogStashLog logStashLog;

    @PostMapping("/test01")
    public void test01(HttpServletRequest request) {
        logStashLog.saveLogStashTest01Log(StringUtil.uuid());
    }
}

 

本地安装Logstash、Elasticsearch、Kibana,注意版本号要保持一致。

在Logstash的config目录下创建20230424-test05.conf配置文件,指定logstash的输入与输出,input中的端口要和logback-spring.xml配置文件中的配置保持一致,output中指定了日志输出的目的地Elasticsearch的地址、索引。内容如下:

input { 
  tcp {
    mode => "server"
    host => "0.0.0.0"
    port => 4560
    codec => json_lines
  }
}

output{
        elasticsearch {
        hosts => ["127.0.0.1:9200"]
        index => "logstash-test-%{+YYYY.MM.dd}"
    }
}

在bin目录下,打开控制台,输入以下命令启动Logstash:

logstash -f ../config/20230424-test05.conf --config.reload.automatic

点击Elasticsearch的bin目录下的sticsearch.bat启动Elasticsearch:

点击Kibana的bin目录下的kibana.bat启动Kibana:

至此,调用接口,日志便会由 Logstash --> Elasticsearch --> Kibana 。