最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

logback的AsyncAppender高效日志處理方式源碼解析

 更新時間:2023年10月29日 08:31:59   作者:codecraft  
這篇文章主要為大家介紹了logback的AsyncAppender高效日志處理方式源碼解析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪

本文主要研究一下logback的AsyncAppender

AsyncAppender

ch/qos/logback/classic/AsyncAppender.java

public class AsyncAppender extends AsyncAppenderBase<ILoggingEvent> {
    boolean includeCallerData = false;
    /**
     * Events of level TRACE, DEBUG and INFO are deemed to be discardable.
     * @param event
     * @return true if the event is of level TRACE, DEBUG or INFO false otherwise.
     */
    protected boolean isDiscardable(ILoggingEvent event) {
        Level level = event.getLevel();
        return level.toInt() <= Level.INFO_INT;
    }
    protected void preprocess(ILoggingEvent eventObject) {
        eventObject.prepareForDeferredProcessing();
        if (includeCallerData)
            eventObject.getCallerData();
    }
    public boolean isIncludeCallerData() {
        return includeCallerData;
    }
    public void setIncludeCallerData(boolean includeCallerData) {
        this.includeCallerData = includeCallerData;
    }
}
AsyncAppender繼承了AsyncAppenderBase,它新增了includeCallerData配置,另外覆蓋了isDiscardable、preprocess方法,isDiscardable針對TRACE、DEBUG的級別返回true,INFO返回false;preprocess則判斷是否includeCallerData,是的話則執(zhí)行eventObject.getCallerData()

AsyncAppenderBase

ch/qos/logback/core/AsyncAppenderBase.java

public class AsyncAppenderBase<E> extends UnsynchronizedAppenderBase<E> implements AppenderAttachable<E> {
    AppenderAttachableImpl<E> aai = new AppenderAttachableImpl<E>();
    BlockingQueue<E> blockingQueue;
    /**
     * The default buffer size.
     */
    public static final int DEFAULT_QUEUE_SIZE = 256;
    int queueSize = DEFAULT_QUEUE_SIZE;
    int appenderCount = 0;
    static final int UNDEFINED = -1;
    int discardingThreshold = UNDEFINED;
    boolean neverBlock = false;
    Worker worker = new Worker();
    /**
     * The default maximum queue flush time allowed during appender stop. If the 
     * worker takes longer than this time it will exit, discarding any remaining 
     * items in the queue
     */
    public static final int DEFAULT_MAX_FLUSH_TIME = 1000;
    int maxFlushTime = DEFAULT_MAX_FLUSH_TIME;
    /**
     * Is the eventObject passed as parameter discardable? The base class's implementation of this method always returns
     * 'false' but sub-classes may (and do) override this method.
     * <p/>
     * <p>Note that only if the buffer is nearly full are events discarded. Otherwise, when the buffer is "not full"
     * all events are logged.
     *
     * @param eventObject
     * @return - true if the event can be discarded, false otherwise
     */
    protected boolean isDiscardable(E eventObject) {
        return false;
    }
    /**
     * Pre-process the event prior to queueing. The base class does no pre-processing but sub-classes can
     * override this behavior.
     *
     * @param eventObject
     */
    protected void preprocess(E eventObject) {
    }
    @Override
    public void start() {
        if (isStarted())
            return;
        if (appenderCount == 0) {
            addError("No attached appenders found.");
            return;
        }
        if (queueSize < 1) {
            addError("Invalid queue size [" + queueSize + "]");
            return;
        }
        blockingQueue = new ArrayBlockingQueue<E>(queueSize);
        if (discardingThreshold == UNDEFINED)
            discardingThreshold = queueSize / 5;
        addInfo("Setting discardingThreshold to " + discardingThreshold);
        worker.setDaemon(true);
        worker.setName("AsyncAppender-Worker-" + getName());
        // make sure this instance is marked as "started" before staring the worker Thread
        super.start();
        worker.start();
    }
    @Override
    public void stop() {
        if (!isStarted())
            return;
        // mark this appender as stopped so that Worker can also processPriorToRemoval if it is invoking
        // aii.appendLoopOnAppenders
        // and sub-appenders consume the interruption
        super.stop();
        // interrupt the worker thread so that it can terminate. Note that the interruption can be consumed
        // by sub-appenders
        worker.interrupt();
        InterruptUtil interruptUtil = new InterruptUtil(context);
        try {
            interruptUtil.maskInterruptFlag();
            worker.join(maxFlushTime);
            // check to see if the thread ended and if not add a warning message
            if (worker.isAlive()) {
                addWarn("Max queue flush timeout (" + maxFlushTime + " ms) exceeded. Approximately " + blockingQueue.size()
                                + " queued events were possibly discarded.");
            } else {
                addInfo("Queue flush finished successfully within timeout.");
            }
        } catch (InterruptedException e) {
            int remaining = blockingQueue.size();
            addError("Failed to join worker thread. " + remaining + " queued events may be discarded.", e);
        } finally {
            interruptUtil.unmaskInterruptFlag();
        }
    }
    @Override
    protected void append(E eventObject) {
        if (isQueueBelowDiscardingThreshold() && isDiscardable(eventObject)) {
            return;
        }
        preprocess(eventObject);
        put(eventObject);
    }
    protected boolean isDiscardable(E eventObject) {
        return false;
    }
    protected void preprocess(E eventObject) {
    }
    private boolean isQueueBelowDiscardingThreshold() {
        return (blockingQueue.remainingCapacity() < discardingThreshold);
    }
    private void put(E eventObject) {
        if (neverBlock) {
            blockingQueue.offer(eventObject);
        } else {
            putUninterruptibly(eventObject);
        }
    }
    private void putUninterruptibly(E eventObject) {
        boolean interrupted = false;
        try {
            while (true) {
                try {
                    blockingQueue.put(eventObject);
                    break;
                } catch (InterruptedException e) {
                    interrupted = true;
                }
            }
        } finally {
            if (interrupted) {
                Thread.currentThread().interrupt();
            }
        }
    }
    //......
}
AsyncAppenderBase繼承了UnsynchronizedAppenderBase,實現(xiàn)了AppenderAttachable接口,它定義了queueSize、discardingThreshold、neverBlock等屬性,其start方法會根據(jù)queueSize創(chuàng)建ArrayBlockingQueue,discardingThreshold默認(rèn)為queueSize / 5,之后啟動Wroker;stop方法則執(zhí)行worker.interrupt(),然后等待maxFlushTime讓log進(jìn)行flush;其append方法會先判斷isQueueBelowDiscardingThreshold及isDiscardable,都為true則直接返回,否則執(zhí)行preprocess、put方法

Worker

ch/qos/logback/core/AsyncAppenderBase.java

class Worker extends Thread {
        public void run() {
            AsyncAppenderBase<E> parent = AsyncAppenderBase.this;
            AppenderAttachableImpl<E> aai = parent.aai;
            // loop while the parent is started
            while (parent.isStarted()) {
                try {
                    E e = parent.blockingQueue.take();
                    aai.appendLoopOnAppenders(e);
                } catch (InterruptedException ie) {
                    break;
                }
            }
            addInfo("Worker thread will flush remaining events before exiting. ");
            for (E e : parent.blockingQueue) {
                aai.appendLoopOnAppenders(e);
                parent.blockingQueue.remove(e);
            }
            aai.detachAndStopAllAppenders();
        }
    }
Worker的run方法會不斷循環(huán)從blockingQueue阻塞取出原生,然后添加到AppenderAttachableImpl;在started為false的時候跳槽循環(huán),然后遍歷blockingQueue,添加到AppenderAttachableImpl,然后將其從blockingQueue;最后執(zhí)行detachAndStopAllAppenders

AppenderAttachableImpl

ch/qos/logback/core/spi/AppenderAttachableImpl.java

public int appendLoopOnAppenders(E e) {
        int size = 0;
        final Appender<E>[] appenderArray = appenderList.asTypedArray();
        final int len = appenderArray.length;
        for (int i = 0; i < len; i++) {
            appenderArray[i].doAppend(e);
            size++;
        }
        return size;
    }
    /**
     * Remove and processPriorToRemoval all previously attached appenders.
     */
    public void detachAndStopAllAppenders() {
        for (Appender<E> a : appenderList) {
            a.stop();
        }
        appenderList.clear();
    }
AppenderAttachableImpl的appendLoopOnAppenders方法會遍歷所有的appenderList執(zhí)行doAppend方法;其detachAndStopAllAppenders則遍歷appenderList,挨個執(zhí)行stop,最后clear掉整個appenderList

小結(jié)

logback的AsyncAppender使用ArrayBlockingQueue(默認(rèn)size為256)來進(jìn)行緩沖,每次append的時候會先判斷isQueueBelowDiscardingThreshold及isDiscardable,為true則直接返回/丟棄,之后執(zhí)行preprocess,最后執(zhí)行put,put的時候有個參數(shù)neverBlock,為true則使用的是offer方法,隊列滿的時候會被丟棄,為false則是阻塞的方法,等到put成功才返回;另外它有個worker線程,不斷從blockingQueue阻塞take元素出來然后寫入到appenderList,在關(guān)閉時還會遍歷隊列寫入到appenderList然后從隊列移除,最后清空隊列。

以上就是logback的AsyncAppender的詳細(xì)內(nèi)容,更多關(guān)于logback的AsyncAppender的資料請關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • 關(guān)于Java8新特性O(shè)ptional類的詳細(xì)解讀

    關(guān)于Java8新特性O(shè)ptional類的詳細(xì)解讀

    Optional類是一個容器類,它可以保存類型T的值,代表這個值存在?;蛘邇H僅保存null,表示這個值不存在,原來用 null 表示一個值不存在,現(xiàn)在Optional 可以更好的表達(dá)這個概念。并且可以避免空指針異常,需要的朋友可以參考下
    2023-05-05
  • SpringMVC上傳文件并保存到本地代碼實例

    SpringMVC上傳文件并保存到本地代碼實例

    這篇文章主要介紹了SpringMVC上傳文件并保存到本地代碼實例,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下
    2019-11-11
  • SpringBoot獲取不到用戶真實IP的解決方法

    SpringBoot獲取不到用戶真實IP的解決方法

    最近遇到個問題,項目部署后發(fā)現(xiàn)服務(wù)端無法獲取到客戶端真實的IP地址,本文就來介紹一下這個問題的解決方法,感興趣的可以了解一下
    2023-08-08
  • Java中幾種常用加密算法盤點

    Java中幾種常用加密算法盤點

    隨著互聯(lián)網(wǎng)的發(fā)展,信息安全問題日益受到重視,加密算法在保證信息安全傳輸方面發(fā)揮著重要作用,本文將簡要盤點幾種常用的Java加密算法,介紹它們的基本原理、特點及應(yīng)用情況,以幫助讀者全面了解當(dāng)前加密算法的發(fā)展?fàn)顩r,需要的朋友可以參考下
    2023-11-11
  • 透徹理解Java中Synchronized(對象鎖)和Static Synchronized(類鎖)的區(qū)別

    透徹理解Java中Synchronized(對象鎖)和Static Synchronized(類鎖)的區(qū)別

    這篇文章主要介紹了Java中Synchronized(對象鎖)和Static Synchronized(類鎖)的區(qū)別,希望對大家有所幫助,一起跟隨小編過來看看吧
    2018-05-05
  • SpringBoot日志配置SLF4J和Logback的方法實現(xiàn)

    SpringBoot日志配置SLF4J和Logback的方法實現(xiàn)

    日志記錄是不可或缺的一部分,本文主要介紹了SpringBoot日志配置SLF4J和Logback的方法實現(xiàn),文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2025-04-04
  • RocketMQ普通消息實戰(zhàn)演練詳解

    RocketMQ普通消息實戰(zhàn)演練詳解

    這篇文章主要為大家介紹了RocketMQ普通消息實戰(zhàn)演練詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-08-08
  • Spring Boot 中使用 Mybatis Plus的操作方法

    Spring Boot 中使用 Mybatis Plus的操作方法

    本文介紹了如何在 Spring Boot 項目中集成 Mybatis Plus,Spring Boot 與 MyBatis Plus 的集成非常簡單,通過自動配置和簡潔的 API,可以大大減少開發(fā)中常見的數(shù)據(jù)庫操作代碼,需要的朋友參考下吧
    2024-12-12
  • Zookeeper ZkClient使用介紹

    Zookeeper ZkClient使用介紹

    ZkClient是Github上?個開源的zookeeper客戶端,在Zookeeper原生API接口之上進(jìn)行了包裝,是?個更易用的Zookeeper客戶端,同時,zkClient在內(nèi)部還實現(xiàn)了諸如Session超時重連、Watcher反復(fù)注冊等功能
    2022-09-09
  • Mybatis基礎(chǔ)概念與高級應(yīng)用小結(jié)

    Mybatis基礎(chǔ)概念與高級應(yīng)用小結(jié)

    這篇文章主要介紹了Mybatis基礎(chǔ)回顧與高級應(yīng)用,本文內(nèi)容有點小長,希望大家耐心閱讀,此文結(jié)合實例代碼給大家介紹的非常詳細(xì),需要的朋友可以參考下
    2022-06-06

最新評論

柞水县| 曲周县| 阳曲县| 乐昌市| 淳安县| 七台河市| 治县。| 成都市| 应城市| 辽源市| 鲁甸县| 涿州市| 和政县| 新沂市| 独山县| 铁岭市| 林口县| 金门县| 平阳县| 湖口县| 含山县| 监利县| 承德县| 湾仔区| 扶余县| 墨玉县| 电白县| 日照市| 通山县| 营山县| 沂水县| 温宿县| 祁阳县| 荔浦县| 邢台市| 昌江| 鄂伦春自治旗| 绥化市| 察隅县| 商洛市| 翁牛特旗|