Java 如何在 JBoss 7 中配置 PeriodicSizeRotatingFileHandler?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/21083960/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-13 06:28:39  来源:igfitidea点击:

How to configure PeriodicSizeRotatingFileHandler in JBoss 7?

javaloggingjboss7.x

提问by Zaw Than oo

I search logger configuration in the web for Jboss 7. How to configure logger using date and size together.

我在网络中搜索记录器配置以获取Jboss 7. 如何同时使用日期和大小配置记录器。

File Logger 1 size-rotating-file-handler

文件记录器 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
    ..

File Logger 2 periodic-rotating-file-handler

文件记录器 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
    ..

My expected files are

我预期的文件是

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         

采纳答案by James R. Perkins

Depending on your version of JBoss AS 7 there is a org.jboss.logmanager.handlers.PeriodicSizeRotatingFileHandleryou can use as a custom-handler. I believe it was introduced in jboss-logmanager 1.3.0.Final. I can't recall which version of JBoss AS/WildFly it is in though.

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

Here's an example CLI command.

这是一个示例 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"})

回答by Zaw Than oo

Jboss 7 (AS)has support to either periodic-rotating-file-handler or size-rotating-file-handler but not both.

Jboss 7 (AS)支持 period-rotating-file-handler 或 size-rotating-file-handler,但不能同时支持两者。

I get some reference(JBoss 7 Custom File Handler) to support periodic and size rotating. It is writing the Custom File Handler. JBoss 7 Custom File Handleris used to create daily rotating size limited log.

我得到了一些参考(JBoss 7 Custom File Handler)来支持周期性和大小轮换。它正在编写Custom File Handler. JBoss 7 Custom File Handler用于创建每日旋转大小受限的日志。

But, I update the source some part of original PeriodicSizeHandler.javafor my requirement.

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

My updated source :

我更新的来源:

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

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());
    }
}

I got my expected output file as below

我得到了我预期的输出文件如下

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

If you would like use your customize file format, you just need to update archiveFile()method, I think so.

如果您想使用自定义文件格式,您只需要更新archiveFile()方法,我认为是这样。

Next solution: after James R. Perkinssuggestion.

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

Download jboss-logmanager-1.5.1.Final.jarhere.

jboss-logmanager-1.5.1.Final.jar在这里下载。

Replace old jboss-logmanger-xxxx.jarwith jboss-logmanager-1.5.1.Final.jarat <JBOSS_HOME>\modules\org\jboss\logmanager\maindirectory.

jboss-logmanger-xxxx.jarjboss-logmanager-1.5.1.Final.jarat<JBOSS_HOME>\modules\org\jboss\logmanager\main目录替换旧的。

Change your module.xmlconfiguration as below

更改您的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>

Configuration for standalone.xml

配置为 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>    

Output :

输出 :

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

回答by Creature

Here's what worked for me (make sure to change the rotationSize and maxBackupIndex to whatever makes sense for you. The numbers I have in there are just for testing):

这对我有用(确保将 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>

回答by Bruce Calvert

The examples by Creature and CycDemo worked for me. However, there is one important thing to note.

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>

A maxBackupIndex value of ten means that there could be ten index files for that particular day. However, this will NOT clean up log files that are more than ten days old, or after ten have been written. There is no parameter here like the old MaxRollFileCount in the old log4j.xml TimeAndSizeRollingAppender specification that will clean up log files after a certain number of them have been written.

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

If you want to clean up old JBoss log files, you will have to use cron and the find command with the +mtime parameter.

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

回答by Amin Agha

Another approach is to change JBOSS logging properties to both rotate log file based on time and size. Below is the way I did it and it works greatly for me.

另一种方法是更改​​ 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>