WSO2 Log4J RollingFileAppender 在 wso2esb-4.8.1 中不起作用
WSO2 Log4J RollingFileAppendeder does not work in wso2esb-4.8.1
我们正在使用 WSO2esb-4.8.1。
默认情况下,log4j 属性使用
log4j.appender.CARBON_LOGFILE=org.wso2.carbon.logging.appenders.CarbonDailyRollingFileAppender
我希望这是基于大小的滚动文件。根据 https://docs.wso2.com/display/Carbon420/Managing+Logs 上的文档,以下应该可以解决问题。
##comment the following
###log4j.appender.CARBON_LOGFILE=org.wso2.carbon.logging.appenders.CarbonDailyRollingFileAppender
##Add the followng
log4j.appender.CARBON_LOGFILE=org.apache.log4j.RollingFileAppender
log4j.appender.CARBON_LOGFILE.MaxFileSize=10MB
log4j.appender.CARBON_LOGFILE.MaxBackupIndex=20
但经过这些更改后,日志以 10MB 的速度旋转,但只保留一个文件。
这是 WSO2 ESB 4.8.1 中的已知问题吗?
这在 WSO2 ESB 4.9.0 中运行良好。
但是,我们没有升级到该版本的选项,因为我们需要的其他一些功能在那里被破坏了。
最后,我在 wso2 任务中模拟了日志轮换行为。请参阅 https://docs.wso2.com/display/ESB481/Writing+Tasks+Sample 以了解如何编写示例 WSo2 任务。
这是代码
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.channels.FileChannel;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Date;
import java.util.List;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.synapse.ManagedLifecycle;
import org.apache.synapse.core.SynapseEnvironment;
import org.apache.synapse.task.Task;
public class LogFileBackupTaskSample implements Task, ManagedLifecycle
{
private static final Log LOG = LogFactory.getLog(LogFileBackupTask.class);
private SynapseEnvironment synapseEnvironment;
// By default, the program is assumed to run from the WSO2 Home Folder
public static final String DEFAULT_LOG_FILE_LOCATION ="repository/logs/";
public static final String WSO2_LOG_FILE_NAME ="wso2carbon.log";
// If a value is not provided for logFileSizeInMbStr, backup of the LOG file size would happen after it reaches 100 MB
public static final int DEFAULT_LOG_FILE_SIZE_IN_MB =100;
// If a value is not provided for noOfBackupFiles, 20 files would be backed up.
public static final int DEFAULT_BACKUP_FILES_NUMBER =20;
public static final int MB_TO_BYTES=1024 *1000;
private String logLocation;
private int logFileSizeInMb;
private String logFileSizeInMbStr;
private String noOfBackupFiles;
private int noOfBackupFilesInt;
public void execute()
{
FileChannel sourceChannel = null;
FileChannel outChannel = null;
if(logLocation==null || logLocation.trim().equals(""))
{
if(LOG.isInfoEnabled())
{
LOG.info("No LOG location provided. Therefore using the default location of "+DEFAULT_LOG_FILE_LOCATION);
}
logLocation= DEFAULT_LOG_FILE_LOCATION;
}
if(!logLocation.endsWith("/") && !logLocation.endsWith("\"))
{
logLocation= logLocation+File.separator;
}
if(logFileSizeInMb==0)
{
if(LOG.isInfoEnabled())
{
LOG.info("No LOG file size in MB. Therefore using the default size of "+DEFAULT_LOG_FILE_SIZE_IN_MB+" Mb");
}
logFileSizeInMb= DEFAULT_LOG_FILE_SIZE_IN_MB * MB_TO_BYTES;
}
String inputLogFileNameWithDirectory= logLocation+WSO2_LOG_FILE_NAME;
File inputLogFileWithDirectory = new File(inputLogFileNameWithDirectory);
long currentLogSize=0;
boolean fileSwapped= false;
try
{
currentLogSize = inputLogFileWithDirectory.length();
if(currentLogSize> logFileSizeInMb)
{
long currentDateLong = System.currentTimeMillis();
Date date = new Date(currentDateLong);
String outFileName= WSO2_LOG_FILE_NAME+"."+date.toString().replace(' ', '_').replace(':', '_');
sourceChannel = new FileInputStream(inputLogFileWithDirectory).getChannel();
File outFile = new File (logLocation+outFileName);
outFile.createNewFile();
outChannel = new FileOutputStream(outFile).getChannel();
outChannel.transferFrom(sourceChannel, 0, currentLogSize);
fileSwapped= true;
}
}
catch(IOException e)
{
LOG.error(e.toString(),e);
throw new RuntimeException(e);
}
finally
{
if(sourceChannel!=null)
{
try
{
sourceChannel.close();
}
catch (IOException e) {
// Ignored
LOG.error(e.toString(),e);
}
}
if(outChannel!=null)
{
try
{
outChannel.close();
}
catch (IOException e) {
// Ignored
LOG.error(e.toString(),e);
}
}
}
FileChannel sourceTruncateChannel = null;
try
{
if(fileSwapped)
{
sourceTruncateChannel = new FileOutputStream(inputLogFileWithDirectory).getChannel();
sourceTruncateChannel.truncate(currentLogSize);
}
}
catch(IOException e)
{
LOG.error(e.toString(),e);
throw new RuntimeException(e);
}
finally
{
if(sourceTruncateChannel!=null)
{
try
{
sourceTruncateChannel.close();
}
catch (IOException e) {
// Ignored
LOG.error(e.toString(),e);
}
}
}
if(fileSwapped)
{
deletingOldFiles();
}
}
public void deletingOldFiles()
{
if(noOfBackupFilesInt==0)
{
if(LOG.isInfoEnabled())
{
LOG.info("NoOfBackupFiles 0. Thus using the default number of "+DEFAULT_BACKUP_FILES_NUMBER);
}
noOfBackupFilesInt= DEFAULT_BACKUP_FILES_NUMBER;
}
File[] listOfFiles= new File(logLocation).listFiles();
List <TimeStampWiseFile> listOfWso2Files = new ArrayList<TimeStampWiseFile>();
for (int i = 0; i < listOfFiles.length; i++)
{
if(listOfFiles[i].getName().startsWith(WSO2_LOG_FILE_NAME) && !listOfFiles[i].getName().equals(WSO2_LOG_FILE_NAME))
{
listOfWso2Files.add(new TimeStampWiseFile(logLocation, listOfFiles[i].getName()));
}
}
// No files to delete in this case.
if(listOfWso2Files.size()<=noOfBackupFilesInt)
{
return;
}
TimeStampWiseFile[] listOfWSo2FilesArray = new TimeStampWiseFile[listOfWso2Files.size()];
listOfWSo2FilesArray= listOfWso2Files.toArray(listOfWSo2FilesArray);
// We need in descending order so that the old files are arranged at the bottom of the stack.
Arrays.sort(listOfWSo2FilesArray, Collections.reverseOrder());
int index=0;
for (int i = 0; i < listOfWSo2FilesArray.length; i++)
{
TimeStampWiseFile timeStampWiseFile = listOfWSo2FilesArray[i];
if(++index > noOfBackupFilesInt)
{
String fileName = timeStampWiseFile.getName();
timeStampWiseFile.delete();
if(LOG.isInfoEnabled())
{
LOG.info("Removed File "+fileName);
}
}
}
}
public void destroy()
{
}
public void init(SynapseEnvironment synapseEnvironment)
{
this.synapseEnvironment = synapseEnvironment;
}
public String getLogLocation()
{
return logLocation;
}
public void setLogLocation(String logLocation)
{
this.logLocation = logLocation;
if(logLocation== null || logLocation.trim().equals(""))
{
if(LOG.isInfoEnabled())
{
LOG.info("No LOG location provided. Therefore using the default location of "+DEFAULT_LOG_FILE_LOCATION);
}
logLocation= DEFAULT_LOG_FILE_LOCATION;
}
}
public String getLogFileSizeInMbStr()
{
return logFileSizeInMbStr;
}
public void setLogFileSizeInMbStr(String logFileSizeInMbStr)
{
this.logFileSizeInMbStr = logFileSizeInMbStr;
if(logFileSizeInMbStr== null || logFileSizeInMbStr.trim().equals(""))
{
if(LOG.isInfoEnabled())
{
LOG.info("No LOG file size in MB. Therefore using the default size of "+DEFAULT_LOG_FILE_SIZE_IN_MB+" Mb");
}
logFileSizeInMb= DEFAULT_LOG_FILE_SIZE_IN_MB * MB_TO_BYTES;
}
else
{
try
{
logFileSizeInMb= Integer.parseInt(logFileSizeInMbStr) * MB_TO_BYTES;
}
catch(NumberFormatException e)
{
LOG.error("logFileSizeInMb is not proper. If the size is 20MB, provide 20 as the 2nd argument. Due to the exception"
+ "using the default size of "+DEFAULT_LOG_FILE_SIZE_IN_MB+" Mb");
logFileSizeInMb= DEFAULT_LOG_FILE_SIZE_IN_MB * MB_TO_BYTES;
}
}
}
public String getNoOfBackupFiles()
{
return noOfBackupFiles;
}
public void setNoOfBackupFiles(String noOfBackupFiles)
{
this.noOfBackupFiles = noOfBackupFiles;
try
{
noOfBackupFilesInt= Integer.parseInt(noOfBackupFiles) ;
}
catch(NumberFormatException e)
{
LOG.error("NoOfBackupFiles is not proper. Proper a proper integer value. Due to the exception"
+ "using the default number of "+DEFAULT_BACKUP_FILES_NUMBER);
noOfBackupFilesInt= DEFAULT_BACKUP_FILES_NUMBER;
}
}
}
现在仅在主租户中将其添加为计划。有关详细信息,请参阅 https://docs.wso2.com/display/ESB480/Adding+and+Scheduling+Tasks。
<?xml version="1.0" encoding="UTF-8"?>
<task xmlns="http://ws.apache.org/ns/synapse"
name="LogFileBackupTask"
class="LogFileBackupTask"
group="synapse.simple.quartz">
<trigger cron="0 0/1 * * * ?"/>
<property xmlns:task="http://www.wso2.org/products/wso2commons/tasks"
name="noOfBackupFiles"
value="20"/>
<property xmlns:task="http://www.wso2.org/products/wso2commons/tasks"
name="logFileSizeInMbStr"
value="20"/>
<property xmlns:task="http://www.wso2.org/products/wso2commons/tasks"
name="logLocation"
value="repository/logs/"/>
</task>
我们正在使用 WSO2esb-4.8.1。
默认情况下,log4j 属性使用
log4j.appender.CARBON_LOGFILE=org.wso2.carbon.logging.appenders.CarbonDailyRollingFileAppender
我希望这是基于大小的滚动文件。根据 https://docs.wso2.com/display/Carbon420/Managing+Logs 上的文档,以下应该可以解决问题。
##comment the following
###log4j.appender.CARBON_LOGFILE=org.wso2.carbon.logging.appenders.CarbonDailyRollingFileAppender
##Add the followng
log4j.appender.CARBON_LOGFILE=org.apache.log4j.RollingFileAppender
log4j.appender.CARBON_LOGFILE.MaxFileSize=10MB
log4j.appender.CARBON_LOGFILE.MaxBackupIndex=20
但经过这些更改后,日志以 10MB 的速度旋转,但只保留一个文件。
这是 WSO2 ESB 4.8.1 中的已知问题吗?
这在 WSO2 ESB 4.9.0 中运行良好。
但是,我们没有升级到该版本的选项,因为我们需要的其他一些功能在那里被破坏了。 最后,我在 wso2 任务中模拟了日志轮换行为。请参阅 https://docs.wso2.com/display/ESB481/Writing+Tasks+Sample 以了解如何编写示例 WSo2 任务。
这是代码
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.channels.FileChannel;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Date;
import java.util.List;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.synapse.ManagedLifecycle;
import org.apache.synapse.core.SynapseEnvironment;
import org.apache.synapse.task.Task;
public class LogFileBackupTaskSample implements Task, ManagedLifecycle
{
private static final Log LOG = LogFactory.getLog(LogFileBackupTask.class);
private SynapseEnvironment synapseEnvironment;
// By default, the program is assumed to run from the WSO2 Home Folder
public static final String DEFAULT_LOG_FILE_LOCATION ="repository/logs/";
public static final String WSO2_LOG_FILE_NAME ="wso2carbon.log";
// If a value is not provided for logFileSizeInMbStr, backup of the LOG file size would happen after it reaches 100 MB
public static final int DEFAULT_LOG_FILE_SIZE_IN_MB =100;
// If a value is not provided for noOfBackupFiles, 20 files would be backed up.
public static final int DEFAULT_BACKUP_FILES_NUMBER =20;
public static final int MB_TO_BYTES=1024 *1000;
private String logLocation;
private int logFileSizeInMb;
private String logFileSizeInMbStr;
private String noOfBackupFiles;
private int noOfBackupFilesInt;
public void execute()
{
FileChannel sourceChannel = null;
FileChannel outChannel = null;
if(logLocation==null || logLocation.trim().equals(""))
{
if(LOG.isInfoEnabled())
{
LOG.info("No LOG location provided. Therefore using the default location of "+DEFAULT_LOG_FILE_LOCATION);
}
logLocation= DEFAULT_LOG_FILE_LOCATION;
}
if(!logLocation.endsWith("/") && !logLocation.endsWith("\"))
{
logLocation= logLocation+File.separator;
}
if(logFileSizeInMb==0)
{
if(LOG.isInfoEnabled())
{
LOG.info("No LOG file size in MB. Therefore using the default size of "+DEFAULT_LOG_FILE_SIZE_IN_MB+" Mb");
}
logFileSizeInMb= DEFAULT_LOG_FILE_SIZE_IN_MB * MB_TO_BYTES;
}
String inputLogFileNameWithDirectory= logLocation+WSO2_LOG_FILE_NAME;
File inputLogFileWithDirectory = new File(inputLogFileNameWithDirectory);
long currentLogSize=0;
boolean fileSwapped= false;
try
{
currentLogSize = inputLogFileWithDirectory.length();
if(currentLogSize> logFileSizeInMb)
{
long currentDateLong = System.currentTimeMillis();
Date date = new Date(currentDateLong);
String outFileName= WSO2_LOG_FILE_NAME+"."+date.toString().replace(' ', '_').replace(':', '_');
sourceChannel = new FileInputStream(inputLogFileWithDirectory).getChannel();
File outFile = new File (logLocation+outFileName);
outFile.createNewFile();
outChannel = new FileOutputStream(outFile).getChannel();
outChannel.transferFrom(sourceChannel, 0, currentLogSize);
fileSwapped= true;
}
}
catch(IOException e)
{
LOG.error(e.toString(),e);
throw new RuntimeException(e);
}
finally
{
if(sourceChannel!=null)
{
try
{
sourceChannel.close();
}
catch (IOException e) {
// Ignored
LOG.error(e.toString(),e);
}
}
if(outChannel!=null)
{
try
{
outChannel.close();
}
catch (IOException e) {
// Ignored
LOG.error(e.toString(),e);
}
}
}
FileChannel sourceTruncateChannel = null;
try
{
if(fileSwapped)
{
sourceTruncateChannel = new FileOutputStream(inputLogFileWithDirectory).getChannel();
sourceTruncateChannel.truncate(currentLogSize);
}
}
catch(IOException e)
{
LOG.error(e.toString(),e);
throw new RuntimeException(e);
}
finally
{
if(sourceTruncateChannel!=null)
{
try
{
sourceTruncateChannel.close();
}
catch (IOException e) {
// Ignored
LOG.error(e.toString(),e);
}
}
}
if(fileSwapped)
{
deletingOldFiles();
}
}
public void deletingOldFiles()
{
if(noOfBackupFilesInt==0)
{
if(LOG.isInfoEnabled())
{
LOG.info("NoOfBackupFiles 0. Thus using the default number of "+DEFAULT_BACKUP_FILES_NUMBER);
}
noOfBackupFilesInt= DEFAULT_BACKUP_FILES_NUMBER;
}
File[] listOfFiles= new File(logLocation).listFiles();
List <TimeStampWiseFile> listOfWso2Files = new ArrayList<TimeStampWiseFile>();
for (int i = 0; i < listOfFiles.length; i++)
{
if(listOfFiles[i].getName().startsWith(WSO2_LOG_FILE_NAME) && !listOfFiles[i].getName().equals(WSO2_LOG_FILE_NAME))
{
listOfWso2Files.add(new TimeStampWiseFile(logLocation, listOfFiles[i].getName()));
}
}
// No files to delete in this case.
if(listOfWso2Files.size()<=noOfBackupFilesInt)
{
return;
}
TimeStampWiseFile[] listOfWSo2FilesArray = new TimeStampWiseFile[listOfWso2Files.size()];
listOfWSo2FilesArray= listOfWso2Files.toArray(listOfWSo2FilesArray);
// We need in descending order so that the old files are arranged at the bottom of the stack.
Arrays.sort(listOfWSo2FilesArray, Collections.reverseOrder());
int index=0;
for (int i = 0; i < listOfWSo2FilesArray.length; i++)
{
TimeStampWiseFile timeStampWiseFile = listOfWSo2FilesArray[i];
if(++index > noOfBackupFilesInt)
{
String fileName = timeStampWiseFile.getName();
timeStampWiseFile.delete();
if(LOG.isInfoEnabled())
{
LOG.info("Removed File "+fileName);
}
}
}
}
public void destroy()
{
}
public void init(SynapseEnvironment synapseEnvironment)
{
this.synapseEnvironment = synapseEnvironment;
}
public String getLogLocation()
{
return logLocation;
}
public void setLogLocation(String logLocation)
{
this.logLocation = logLocation;
if(logLocation== null || logLocation.trim().equals(""))
{
if(LOG.isInfoEnabled())
{
LOG.info("No LOG location provided. Therefore using the default location of "+DEFAULT_LOG_FILE_LOCATION);
}
logLocation= DEFAULT_LOG_FILE_LOCATION;
}
}
public String getLogFileSizeInMbStr()
{
return logFileSizeInMbStr;
}
public void setLogFileSizeInMbStr(String logFileSizeInMbStr)
{
this.logFileSizeInMbStr = logFileSizeInMbStr;
if(logFileSizeInMbStr== null || logFileSizeInMbStr.trim().equals(""))
{
if(LOG.isInfoEnabled())
{
LOG.info("No LOG file size in MB. Therefore using the default size of "+DEFAULT_LOG_FILE_SIZE_IN_MB+" Mb");
}
logFileSizeInMb= DEFAULT_LOG_FILE_SIZE_IN_MB * MB_TO_BYTES;
}
else
{
try
{
logFileSizeInMb= Integer.parseInt(logFileSizeInMbStr) * MB_TO_BYTES;
}
catch(NumberFormatException e)
{
LOG.error("logFileSizeInMb is not proper. If the size is 20MB, provide 20 as the 2nd argument. Due to the exception"
+ "using the default size of "+DEFAULT_LOG_FILE_SIZE_IN_MB+" Mb");
logFileSizeInMb= DEFAULT_LOG_FILE_SIZE_IN_MB * MB_TO_BYTES;
}
}
}
public String getNoOfBackupFiles()
{
return noOfBackupFiles;
}
public void setNoOfBackupFiles(String noOfBackupFiles)
{
this.noOfBackupFiles = noOfBackupFiles;
try
{
noOfBackupFilesInt= Integer.parseInt(noOfBackupFiles) ;
}
catch(NumberFormatException e)
{
LOG.error("NoOfBackupFiles is not proper. Proper a proper integer value. Due to the exception"
+ "using the default number of "+DEFAULT_BACKUP_FILES_NUMBER);
noOfBackupFilesInt= DEFAULT_BACKUP_FILES_NUMBER;
}
}
}
现在仅在主租户中将其添加为计划。有关详细信息,请参阅 https://docs.wso2.com/display/ESB480/Adding+and+Scheduling+Tasks。
<?xml version="1.0" encoding="UTF-8"?>
<task xmlns="http://ws.apache.org/ns/synapse"
name="LogFileBackupTask"
class="LogFileBackupTask"
group="synapse.simple.quartz">
<trigger cron="0 0/1 * * * ?"/>
<property xmlns:task="http://www.wso2.org/products/wso2commons/tasks"
name="noOfBackupFiles"
value="20"/>
<property xmlns:task="http://www.wso2.org/products/wso2commons/tasks"
name="logFileSizeInMbStr"
value="20"/>
<property xmlns:task="http://www.wso2.org/products/wso2commons/tasks"
name="logLocation"
value="repository/logs/"/>
</task>