本文主要研究一下rocketmq的DailyRollingFileAppender

DailyRollingFileAppender

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

   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


codecraft
11.9k 声望2k 粉丝

当一个代码的工匠回首往事时,不因虚度年华而悔恨,也不因碌碌无为而羞愧,这样,当他老的时候,可以很自豪告诉世人,我曾经将代码注入生命去打造互联网的浪潮之巅,那是个很疯狂的时代,我在一波波的浪潮上留下...


引用和评论

0 条评论