如何在JBoss 7中配置PeriodicSizeRotatingFileHandler?

时间:2014-01-13 04:35:58

标签: java logging jboss7.x

我在网络中搜索Jboss 7的记录器配置。如何使用日期和大小配置记录器。

档案记录器1 size-rotating-file-handler

<size-rotating-file-handler name="FILE">
    <formatter>
        <pattern-formatter pattern="%d{HH:mm:ss,SSS} %-5p [%c] (%t) %s%E%n"/>
    </formatter>
    <file relative-to="jboss.server.log.dir" path="server.log"/>
    <rotate-size value="1000k"/>
    <max-backup-index value="20"/>
    <append value="true"/>
</size-rotating-file-handler>

Out Put Files are : 
    server.log.1
    server.log.2
    server.log.3
    ..

档案记录器2 periodic-rotating-file-handler

<periodic-rotating-file-handler name="FILE">
    <formatter>
        <pattern-formatter pattern="%d{HH:mm:ss,SSS} %-5p [%c] (%t) %s%E%n"/>
    </formatter>
    <file relative-to="jboss.server.log.dir" path="server.log"/>
    <suffix value=".yyyy-MM-dd"/>
    <append value="true"/>
</periodic-rotating-file-handler>

Out Put Files are : 
    server.log.2013-12-12
    server.log.2013-12-13
    server.log.2013-12-14
    ..

我的预期文件是

server.log.2013-12-12.1
server.log.2013-12-12.2
server.log.2013-12-12.3
server.log.2013-12-13.1
server.log.2013-12-13.2
server.log.2013-12-13.3         

5 个答案:

答案 0 :(得分:6)

根据您的JBoss AS 7版本,org.jboss.logmanager.handlers.PeriodicSizeRotatingFileHandler可以用作custom-handler。我相信它是在jboss-logmanager 1.3.0.Final中引入的。我记不起它在哪个版本的JBoss AS / WildFly。

这是一个示例CLI命令。

/subsystem=logging/custom-handler=example:add(class=org.jboss.logmanager.handlers.PeriodicSizeRotatingFileHandler, module=org.jboss.logmanager, formatter="%d{HH:mm:ss,SSS} %-5p [%c] (%t) %s%E%n", properties={rotateSize=1024000,maxBackupIndex=20,suffix=".yyyy-MM-dd",fileName="${jboss.server.log.dir}/example.log"})

答案 1 :(得分:4)

这对我有用(确保将rotationSize和maxBackupIndex更改为对你有意义的。我在那里的数字仅用于测试):

        <custom-handler name="FILESIZEDATE" class="org.jboss.logmanager.handlers.PeriodicSizeRotatingFileHandler" module="org.jboss.logmanager">
            <formatter>
                <pattern-formatter pattern="%d{HH:mm:ss,SSS} %-5p [%c] (%t) %s%E%n"/>
            </formatter>
            <properties>
                <property name="autoFlush" value="true"/>
                <property name="append" value="true"/>
                <property name="rotateSize" value="1000"/>
                <property name="maxBackupIndex" value="20"/>
                <property name="suffix" value=".yyyy-MM-dd"/>
                <property name="fileName" value="${jboss.server.log.dir}/server.log"/>
            </properties>
        </custom-handler>

        <root-logger>
            <level name="INFO"/>
            <handlers>
                <handler name="FILESIZEDATE"/>
                <handler name="CONSOLE"/>
            </handlers>
        </root-logger>

答案 2 :(得分:1)

Jboss 7 (AS)支持periodic-rotating-file-handler或size-rotating-file-handler,但不支持两者。

我得到一些参考(JBoss 7 Custom File Handler)以支持周期性和大小旋转。它写的是Custom File HandlerJBoss 7 Custom File Handler用于创建每日旋转大小限制日志。

但是,我根据我的要求更新了原始PeriodicSizeHandler.java的部分内容。

我的更新来源:

PeriodicSizeHandler.java

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.logging.ErrorManager;
import java.util.logging.Handler;
import java.util.logging.Level;
import java.util.logging.LogRecord;

public class PeriodicSizeHandler extends Handler {
    private int count = 1;
    protected static Long calculatedBytes;
    private String maxBytes = "2g";
    private String logFileName = "server.log";
    private static String logDirPath;
    private File logFile;
    private FileOutputStream outputStream;

    static {
        logDirPath = System.getenv("JBOSS_HOME") + "\\standalone\\log";
    }

    public enum Bytes {
        Byte("b", 1l), KiloBytes("k", (Byte.bytes * 1024)), MegaBytes("m",
                (KiloBytes.bytes * 1024)), GigaBytes("g",
                (MegaBytes.bytes * 1024)), ;

        private Bytes(String byteAcronym, Long bytes) {
            this.byteAcronym = byteAcronym;
            this.bytes = bytes;
        }

        private String byteAcronym;
        private Long bytes;

        public static long getBytes(String maxBytesRep) throws Exception {
            if (maxBytesRep == null && "".equals(maxBytesRep)) {
                throw new Exception(
                        "The max bytes representation cannot be empty or null");
            }
            String uByteRepresentation = maxBytesRep.toLowerCase();
            for (Bytes b : values()) {
                if (uByteRepresentation.endsWith(b.byteAcronym)) {
                    String strNumVal = uByteRepresentation.substring(0,
                            uByteRepresentation.indexOf(b.byteAcronym));
                    try {
                        return getBytes(Double.valueOf(strNumVal), b);
                    } catch (Exception e) {
                        throw new Exception(
                                "The max bytes representation: "
                                        + maxBytesRep
                                        + ", is not valid. Shoubl be of the form XXX..(B or b) / M or m /G or g). Ex: '1000b', '100m', '1g'");
                    }
                }
            }
            // If no acronym is mentioned consider it as Byte representation Ex.
            // maxBytes = 1000
            try {
                return getBytes(Double.valueOf(uByteRepresentation), Bytes.Byte);
            } catch (Exception e) {
                throw new Exception(
                        "The max bytes representation: "
                                + maxBytesRep
                                + ", is not valid. Shoubl      be of the form XXX../(B or b) / M or m /G or g). Ex: '1000', '1000b', '100m', '1g'");
            }
        }

        public String getByteAcronym() {
            return this.byteAcronym;
        }

        public Long getBytes() {
            return this.bytes;
        }

        public static long getBytes(double multiple, Bytes bytes) {
            return Math.round(multiple * bytes.bytes);
        }
    }

    public PeriodicSizeHandler() {
    }

    @Override
    public void flush() {
        try {
            if (outputStream != null) {
                outputStream.flush();
            }
        } catch (IOException e) {
            reportError(e.getMessage(), e, ErrorManager.FLUSH_FAILURE);
        }
    }

    @Override
    public void close() {
        if (outputStream != null) {
            try {
                outputStream.close();
            } catch (IOException e) {
                reportError(e.getMessage(), e, ErrorManager.CLOSE_FAILURE);
            }

        }
    }

    @Override
    public void publish(LogRecord record) {
        init();
        if (rollOver(record)) {
            archiveFile();
            createLogChannel();
        }
        logToFile(record);
    }

    // Initialize
    public synchronized void init() {
        if (outputStream == null) {
            try {
                logFile = new File(getFilePath());
                if (logFile.exists()) {
                    outputStream = new FileOutputStream(logFile, true);
                } else {
                    createLogChannel();
                }
            } catch (FileNotFoundException e) {
                reportError(e.getMessage(), e, ErrorManager.OPEN_FAILURE);
            }
        }
    }

    private String getFilePath() {
        return getLogDirPath() + File.separator + logFileName;
    }

    // check the file size
    private boolean rollOver(LogRecord record) {
        try {
            StringBuilder logMessage = new StringBuilder(getFormatter().format(record));
            if ((outputStream.getChannel().size() + logMessage.length()) > getByteValue(getMaxBytes())) {
                return true;
            }
        } catch (IOException e) {
            reportError(e.getMessage(), e, ErrorManager.GENERIC_FAILURE);
        }
        return false;
    }

    /**
     * Rename with date and time stamp
     */
    private void archiveFile() {
        System.out.println("archiveFile..........");
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd");
//      String logDir = getLogDirPath() +  File.separator + simpleDateFormat.format(new Date());
        String newFilePath = getLogDirPath()  + File.separator + logFileName + "_" + simpleDateFormat.format(new Date()) + "_" + count++;
        File newFile = new File(newFilePath);
        try {
            OutputStream oos = new FileOutputStream(newFile);
            byte[] buf = new byte[8192];
            InputStream is = new FileInputStream(logFile);
            int c = 0;
            while ((c = is.read(buf, 0, buf.length)) > 0) {
                oos.write(buf, 0, c);
                oos.flush();
            }
            oos.close();
            is.close();
            PrintWriter writer = new PrintWriter(logFile);
            writer.print("");
            writer.close();         
        } catch(Exception e) {
            reportError("Unable to rename old file: " + logFile.getName()
                    + " to new file: " + newFile, null, ErrorManager.GENERIC_FAILURE);
        }
    }

    private void createLogChannel() {
        try {
            // make directories
            File logDir = new File(getLogDirPath());
            logDir.mkdirs();

            // create log file
            System.out.println("getFilePath( : " + getFilePath());
            logFile = new File(getFilePath());
            logFile.createNewFile();

            // create the channel
            outputStream = new FileOutputStream(logFile, true);
        } catch (FileNotFoundException e) {
            reportError(e.getMessage(), e, ErrorManager.OPEN_FAILURE);
        } catch (IOException e) {
            reportError(e.getMessage(), e, ErrorManager.OPEN_FAILURE);
        }
    }

    private synchronized void logToFile(LogRecord record) {
        StringBuilder logMessage = new StringBuilder(getFormatter().format(record));
        try {
            if (outputStream != null) {
                outputStream.write(logMessage.toString().getBytes());
                outputStream.flush();
            }
        } catch (IOException e) {
            reportError(e.getMessage(), e, ErrorManager.WRITE_FAILURE);
        }
    }

    protected long getByteValue(String maxBytes) {
        if (calculatedBytes != null) {
            return calculatedBytes;
        }
        try {
            calculatedBytes = Bytes.getBytes(maxBytes);
        } catch (Exception e) {
            logToFile(new LogRecord(Level.INFO, "Failed to get byte value from maxBytes: " + maxBytes + ", exception: " + e));
            calculatedBytes = getDefaultBytes();
        }
        return calculatedBytes;
    }

    // Use Default - 2GB
    protected Long getDefaultBytes() {
        int multiple = 2;
        logToFile(new LogRecord(Level.INFO, "Using the default: '" + multiple + Bytes.GigaBytes.byteAcronym + "'"));
        return Bytes.getBytes(multiple, Bytes.GigaBytes);
    }

    public String getMaxBytes() {
        return maxBytes;
    }

    public void setMaxBytes(String maxBytes) {
        this.maxBytes = maxBytes;
    }

    public String getLogFileName() {
        return logFileName;
    }

    public void setLogFileName(String logFileName) {
        this.logFileName = logFileName;
    }

    public File getLogFile() {
        return logFile;
    }

    public void setLogFile(File logFile) {
        this.logFile = logFile;
    }

    public FileOutputStream getOutputStream() {
        return outputStream;
    }

    public void setOutputStream(FileOutputStream outputStream) {
        this.outputStream = outputStream;
    }

    public void setLogDirPath(String logDirPath) {
        this.logDirPath = logDirPath;
    }

    public String getLogDirPath() {
        return logDirPath;
    }
}

PeriodicSizeHandlerTest.java

import java.io.BufferedReader;
import java.io.FileReader;
import java.util.logging.Formatter;
import java.util.logging.Level;
import java.util.logging.LogRecord;

import junit.framework.TestCase;

import org.junit.Before;
import org.junit.Test;

import com.cyc.jboss.logging.PeriodicSizeHandler.Bytes;

public class PeriodicSizeHandlerTest extends TestCase {
    @Before
    public void setUp() {
        PeriodicSizeHandler.calculatedBytes = null;
    }

    Long bytes = Bytes.getBytes(100, Bytes.Byte);

    @Test
    public void testPublishRollOverTrue() throws Exception {
        PeriodicSizeHandler psh = new PeriodicSizeHandler();
        psh.setMaxBytes("3k");
        setupFormatter(psh);
        // text.txt file size is `151k`
        FileReader fr = new FileReader("D:/temp/test.txt");
        BufferedReader br = new BufferedReader(fr);
        String message;
        while ((message = br.readLine()) != null) {
            LogRecord logRecord = new LogRecord(Level.INFO, message);
            psh.publish(logRecord);
        }
        fr.close();
        assertTrue(psh.getOutputStream() != null);
    }

    private void setupFormatter(PeriodicSizeHandler psh) {
        Formatter formatr = new Formatter() {
            @Override
            public String format(LogRecord record) {
                return record.getLevel() + " :: " + record.getMessage();
            }
        };
        psh.setFormatter(formatr);
    }

    public static void main(String[] args) {
        org.junit.runner.JUnitCore
                .main(PeriodicSizeHandlerTest.class.getName());
    }
}

我的预期输出文件如下所示

server.log_2014-01-13_1
server.log_2014-01-13_2
server.log_2014-01-13_3
....
server.log_2014-01-13_55

如果您想使用自定义文件格式,则只需更新archiveFile()方法即可。

下一个解决方案:在 James R. Perkins 建议之后。

下载jboss-logmanager-1.5.1.Final.jar here

将旧版jboss-logmanger-xxxx.jar替换为jboss-logmanager-1.5.1.Final.jar目录下的<JBOSS_HOME>\modules\org\jboss\logmanager\main

更改module.xml配置如下

<module xmlns="urn:jboss:module:1.1" name="org.jboss.logmanager">
    <resources>
        <resource-root path="jboss-logmanager-1.5.1.Final.jar"/>
        <!-- Insert resources here -->
    </resources>

    <dependencies/>
</module>

standalone.xml

的配置
<subsystem xmlns="urn:jboss:domain:logging:1.1">
    .....
    <custom-handler name="FILE" class="org.jboss.logmanager.handlers.PeriodicSizeRotatingFileHandler" module="org.jboss.logmanager">
        <formatter>
            <pattern-formatter pattern="%d{HH:mm:ss,SSS} %-5p [%c] (%t) %s%E%n"/>
        </formatter>
        <properties>
            <property name="file" value="D:\temp\server.log"/>  <--- your log directory          
            <property name="rotateSize" value="50000"/>         <--- 50000 byte
            <property name="maxBackupIndex" value="50"/>        
            <property name="append " value="true"/>
            <property name="suffix" value=".yyyy-MM-dd"/>
            <property name="autoflush" value="true"/>
        </properties>
    </custom-handler>
    ....
    <root-logger>
        <level name="INFO"/>
        <handlers>
            <handler name="CONSOLE"/>
            <handler name="FILE"/>
        </handlers>
    </root-logger>
</subsystem>    

输出:

server.log.2014-01-16.1 
server.log.2014-01-16.2 
server.log.2014-01-16.3 

答案 3 :(得分:0)

另一种方法是更改​​JBOSS日志记录属性,以根据时间和大小轮换日志文件。下面是我的操作方式,它对我很有用。

        <periodic-size-rotating-file-handler name="FILE" autoflush="true">
            <formatter>
                <named-formatter name="PATTERN"/>
            </formatter>
            <file relative-to="jboss.server.log.dir" path="server.log"/>
            <suffix value=".yyyy-MM-dd"/>
            <append value="true"/>
            <max-backup-index value="4"/>
            <rotate-size value="10000k"/>
            <encoding value="UTF-8"/>
        </periodic-size-rotating-file-handler>

答案 4 :(得分:-1)

Creature和CycDemo的例子为我工作。但是,有一点需要注意。

            <custom-handler name="FILE"
            class="org.jboss.logmanager.handlers.PeriodicSizeRotatingFileHandler"
            module="org.jboss.logmanager">
            <properties>
                <property name="maxBackupIndex" value="10"/>
                <property name="rotateSize" value="500000"/> <!-- 500 Kb -->
                <property name="suffix" value=".yyyy-MM-dd"/>
                <property name="fileName" value="${jboss.server.log.dir}/server.log"/>
                <property name="append" value="true"/>
                <property name="autoFlush" value="true"/>
            </properties>
        </custom-handler>

maxBackupIndex值为10表示该特定日期可能有十个索引文件。但是,这不会清除超过十天的日志文件,也不会清除十个日志文件。这里没有像旧的log4j.xml TimeAndSizeRollingAppender规范中的旧MaxRollFileCount那样的参数,它将在写入一定数量的日志文件后清理日志文件。

如果要清理旧的JBoss日志文件,则必须使用cron和带有+ mtime参数的find命令。