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
How to configure PeriodicSizeRotatingFileHandler in JBoss 7?
提问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.PeriodicSizeRotatingFileHandler
you 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 Handler
is 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.java
for 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.jar
here.
jboss-logmanager-1.5.1.Final.jar
在这里下载。
Replace old jboss-logmanger-xxxx.jar
with jboss-logmanager-1.5.1.Final.jar
at <JBOSS_HOME>\modules\org\jboss\logmanager\main
directory.
jboss-logmanger-xxxx.jar
用jboss-logmanager-1.5.1.Final.jar
at<JBOSS_HOME>\modules\org\jboss\logmanager\main
目录替换旧的。
Change your module.xml
configuration 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>