日誌收集(ElasticSearch)串聯查詢 MDC

  以前寫過將應用程序或服務程序產生的日誌直接寫入搜索引擎的博客 其中基本過程就是  app->redis->logstash->elasticsearch 整個鏈路過程  原本想將redis替換成kafka的 無奈公司領導不讓(不要問我爲何沒有緣由不想回答,哦也!就這麼酷!!!)nginx

  而後又寫了相關的優化,其實道理很簡單 就是 部署多個redis 多個logstash就ok了 (注意redis建議不要部署集羣單節點就OK由於他只承擔了消息傳輸的功能別無其餘,架集羣的好處就是APP應用本身分發負載了,若是是多個redis單節點須要個相似nginx的東西作負載轉發,其實最好使用F5這類的硬件會更好)好了很少說廢話下面直奔主題。git

  遇到的問題github

    一、去ES(ElasticSearch 如下簡稱ES)查詢日誌用關鍵字搜索要搜索好幾回才能定位的問題?redis

    二、多線程調用公用的方法不少時候是否是有點迷糊找不着北等等 不止這些spring

  想要達到的目的數據庫

    經過關鍵字(關鍵字能夠是訂單號,操做碼等能夠標識一條信息,通常在數據庫裏面都是主鍵)一次查詢出來全部的整個鏈路的相關日誌多線程

  好,咱們的目的很明確,不想各類過濾條件一大堆去定位真正想要的日誌,一個關鍵搞定多全部。app

  說道這裏可能有不少童鞋對日誌框架比較瞭解第一就會想到MDC,沒錯就是他。下面纔是真正的主題,哈哈!框架

  MDC我就很少介紹這裏我在網上隨便找了一個介紹的 若是熟悉能夠略過(https://blog.csdn.net/liubo2012/article/details/46337063)elasticsearch

  MDC其實就是在方法裏面先後標記一下,而後在這個標記範圍內(包括中間調用的方法嵌套)全部的日誌都會打上相應的標籤記錄方便查詢

  那怎麼和咱們以前的 方案結合和 咱們以前用的是下面這個包,這個包是支持MDC傳輸的具體源碼你們能夠參看github實現https://github.com/kmtong/logback-redis-appender

  

<dependency>
            <groupId>com.cwbase</groupId>
            <artifactId>logback-redis-appender</artifactId>
            <version>1.1.5</version>
        </dependency>

當咱們引入這個包以後logback.xml文件是以下配置的

<?xml version="1.0" encoding="UTF-8"?>
<configuration debug="false" scan="true" scanPeriod="1 seconds">
    <include resource="org/springframework/boot/logging/logback/base.xml" />
    <!-- <jmxConfigurator/> -->
    <contextName>logback</contextName>

    <property name="log.path" value="\logs\logback.log" />

    <property name="log.pattern"
        value="%d{yyyy-MM-dd HH:mm:ss.SSS} -%5p ${PID} --- traceId:[%X{mdc_trace_id}] [%15.15t] %-40.40logger{39} : %m%n" />

    <appender name="file"
        class="ch.qos.logback.core.rolling.RollingFileAppender">
        <file>${log.path}</file>

        <encoder>
            <pattern>${log.pattern}</pattern>
        </encoder>

        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">

            <fileNamePattern>info-%d{yyyy-MM-dd}-%i.log
            </fileNamePattern>

            <timeBasedFileNamingAndTriggeringPolicy
                class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">

                <maxFileSize>10MB</maxFileSize>
            </timeBasedFileNamingAndTriggeringPolicy>
            <maxHistory>10</maxHistory>
        </rollingPolicy>

    </appender>

    <appender name="redis" class="com.cwbase.logback.RedisAppender">

        <tags>test</tags>
        <host>10.10.12.21</host>
        <port>6379</port>
        <key>spp</key>
        <mdc>true</mdc>
        <callerStackIndex>0</callerStackIndex>
        <location>true</location>
        
        <!-- <additionalField>
            <key>traceId</key>
            <value>@{destination}</value>
        </additionalField> -->
    </appender>
    
    <root level="info">
        <!-- <appender-ref ref="file" /> -->
        <!-- <appender-ref ref="UdpSocket" /> -->
        <!-- <appender-ref ref="TcpSocket" /> -->
        <appender-ref ref="redis" />
    </root>

    <!-- <logger name="com.example.logback" level="warn" /> -->

</configuration>

咱們把<mdc>true</mdc>標籤設置爲true 默認是false就能夠了,下面咱們看下咱們的測試代碼

package com.zjs.canal.client.client;

import org.junit.Test;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.slf4j.MDC;

public class testaa {
    protected final static Logger logger = LoggerFactory.getLogger(testaa.class);

    
    @Test
    public void test(){
        
        MDC.put("destination", "123456789");
        for (int i = 0; i < 10; i++) {
            logger.info("aaaaaaaa"+i);
            test1();
        }
        MDC.remove("destination");
    }
    public void test1()
    {
        for (int i = 0; i < 10; i++) {
            logger.info("bbbbbbbb"+i);
        }
    }
}

上面的測試有兩層嵌套下面是ES日誌輸出

你們能夠看到日誌輸出內容包含了兩個方法,都包含相應的properties.destination字段而且值也是同樣的(固然真正使用的時候destination MDC的關鍵字是動態的,選查詢的主要關鍵字)

這樣經過關鍵字一下就能把全部相關的日誌都查詢出來就能看出數據整個處理流程,這樣就很是方便咱們的查詢定位排查問題

我上面的代碼有一段註釋不知道你們有沒有注意到

就是下面這段

   <!-- <additionalField>
            <key>traceId</key>
            <value>@{destination}</value>
        </additionalField> -->                

其實咱們把<mdc>true</mdc>這句設爲false也是能夠了不過須要添加一個字段來引用數據(把上面的配置取消註釋)這樣咱們就能夠自定義命名跟蹤字段的名稱了(本人更傾向使用這種)

而後配置就辦成下面這樣

    <appender name="redis" class="com.cwbase.logback.RedisAppender">

        <tags>test</tags>
        <host>10.10.12.21</host>
        <port>6379</port>
        <key>spp</key>
        <!-- <mdc>true</mdc> -->
        <callerStackIndex>0</callerStackIndex>
        <location>true</location>
        
         <additionalField>
            <key>traceId</key>
            <value>@{destination}</value>
        </additionalField>
    </appender>

而後看下效果

這是以前的默認字段就沒有值了mdc引用的值變成咱們新的字段裏面去了

其實均可以開啓 可是會打印兩份MDC和自定義字段,這樣就會重複了,因此說不必了

好了 今天就說的這裏但願對看博客的你有所幫助

相關文章
相關標籤/搜索