聊聊rocketmq的DailyRollingFileAppender

本文主要研究一下rocketmq的DailyRollingFileAppenderjava

DailyRollingFileAppender

org/apache/rocketmq/logging/inner/LoggingBuilder.javagit

public static class DailyRollingFileAppender extends FileAppender {

        static final int TOP_OF_TROUBLE = -1;
        static final int TOP_OF_MINUTE = 0;
        static final int TOP_OF_HOUR = 1;
        static final int HALF_DAY = 2;
        static final int TOP_OF_DAY = 3;
        static final int TOP_OF_WEEK = 4;
        static final int TOP_OF_MONTH = 5;


        /**
         * The date pattern. By default, the pattern is set to
         * "'.'yyyy-MM-dd" meaning daily rollover.
         */
        private String datePattern = "'.'yyyy-MM-dd";

        private String scheduledFilename;

        private long nextCheck = System.currentTimeMillis() - 1;

        Date now = new Date();

        SimpleDateFormat sdf;

        RollingCalendar rc = new RollingCalendar();

        final TimeZone gmtTimeZone = TimeZone.getTimeZone("GMT");


        public void setDatePattern(String pattern) {
            datePattern = pattern;
        }

        public String getDatePattern() {
            return datePattern;
        }

        public void activateOptions() {
            super.activateOptions();
            if (datePattern != null && fileName != null) {
                now.setTime(System.currentTimeMillis());
                sdf = new SimpleDateFormat(datePattern);
                int type = computeCheckPeriod();
                printPeriodicity(type);
                rc.setType(type);
                File file = new File(fileName);
                scheduledFilename = fileName + sdf.format(new Date(file.lastModified()));

            } else {
                SysLogger.error("Either File or DatePattern options are not set for appender [" + name + "].");
            }
        }

        void printPeriodicity(int type) {
            switch (type) {
                case TOP_OF_MINUTE:
                    SysLogger.debug("Appender [" + name + "] to be rolled every minute.");
                    break;
                case TOP_OF_HOUR:
                    SysLogger.debug("Appender [" + name + "] to be rolled on top of every hour.");
                    break;
                case HALF_DAY:
                    SysLogger.debug("Appender [" + name + "] to be rolled at midday and midnight.");
                    break;
                case TOP_OF_DAY:
                    SysLogger.debug("Appender [" + name + "] to be rolled at midnight.");
                    break;
                case TOP_OF_WEEK:
                    SysLogger.debug("Appender [" + name + "] to be rolled at start of week.");
                    break;
                case TOP_OF_MONTH:
                    SysLogger.debug("Appender [" + name + "] to be rolled at start of every month.");
                    break;
                default:
                    SysLogger.warn("Unknown periodicity for appender [" + name + "].");
            }
        }

        int computeCheckPeriod() {
            RollingCalendar rollingCalendar = new RollingCalendar(gmtTimeZone, Locale.getDefault());
            // set sate to 1970-01-01 00:00:00 GMT
            Date epoch = new Date(0);
            if (datePattern != null) {
                for (int i = TOP_OF_MINUTE; i <= TOP_OF_MONTH; i++) {
                    SimpleDateFormat simpleDateFormat = new SimpleDateFormat(datePattern);
                    simpleDateFormat.setTimeZone(gmtTimeZone);
                    String r0 = simpleDateFormat.format(epoch);
                    rollingCalendar.setType(i);
                    Date next = new Date(rollingCalendar.getNextCheckMillis(epoch));
                    String r1 = simpleDateFormat.format(next);
                    if (r0 != null && r1 != null && !r0.equals(r1)) {
                        return i;
                    }
                }
            }
            return TOP_OF_TROUBLE;
        }

        void rollOver() throws IOException {

            if (datePattern == null) {
                handleError("Missing DatePattern option in rollOver().");
                return;
            }

            String datedFilename = fileName + sdf.format(now);

            if (scheduledFilename.equals(datedFilename)) {
                return;
            }
            this.closeFile();

            File target = new File(scheduledFilename);
            if (target.exists() && !target.delete()) {
                SysLogger.error("Failed to delete [" + scheduledFilename + "].");
            }

            File file = new File(fileName);
            boolean result = file.renameTo(target);
            if (result) {
                SysLogger.debug(fileName + " -> " + scheduledFilename);
            } else {
                SysLogger.error("Failed to rename [" + fileName + "] to [" + scheduledFilename + "].");
            }

            try {
                this.setFile(fileName, true, this.bufferedIO, this.bufferSize);
            } catch (IOException e) {
                handleError("setFile(" + fileName + ", true) call failed.");
            }
            scheduledFilename = datedFilename;
        }

        protected void subAppend(LoggingEvent event) {
            long n = System.currentTimeMillis();
            if (n >= nextCheck) {
                now.setTime(n);
                nextCheck = rc.getNextCheckMillis(now);
                try {
                    rollOver();
                } catch (IOException ioe) {
                    if (ioe instanceof InterruptedIOException) {
                        Thread.currentThread().interrupt();
                    }
                    SysLogger.error("rollOver() failed.", ioe);
                }
            }
            super.subAppend(event);
        }
    }
  • 這裏重寫了subAppend方法,先檢查當前時間是否大於nextCheck值,大於則更新nextCheck值,而後進行rollOver操做,最後在調用父類的subAppend方法
  • rollOver方法先檢查datedFilename是否等於scheduledFilename,若是不等則進行重命名操做,而後調用FileAppender的setFile操做,最後更新scheduledFilename值

小結

  • rocketmq的DailyRollingFileAppender的實現是重寫subAppend,每次subAppend以前先檢查是否須要重命名文件,若是須要則調用rollOver方法
  • rollOver方法主要是將文件名重名爲scheduledFilename,datePattern的格式爲.yyyy-MM-dd

doc

相關文章
相關標籤/搜索