问题
We are using WSO2esb-4.8.1.
By default the log4j properties uses
log4j.appender.CARBON_LOGFILE=org.wso2.carbon.logging.appenders.CarbonDailyRollingFileAppender
I want this to be Size based rolling file. As per documentation at https://docs.wso2.com/display/Carbon420/Managing+Logs, the following should do the trick.
##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
But after these changes, the logs are rotating at 10MB, but only one file is maintained.
Is this a known issue in WSO2 ESB 4.8.1 ?
回答1:
This was working cleanly in WSO2 ESB 4.9.0.
However, we do not have the option to upgrade to that since some of the other features that we need are broken there. Finally I simulated log rotation behavior in a wso2 task. Refer https://docs.wso2.com/display/ESB481/Writing+Tasks+Sample to understand how to a write a sample WSo2 task.
This is the code
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;
}
}
}
Now add this as a scheduled only in the master tenant. Refer https://docs.wso2.com/display/ESB480/Adding+and+Scheduling+Tasks for the details on this.
<?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>
来源:https://stackoverflow.com/questions/38073853/wso2-log4j-rollingfileappendeder-does-not-work-in-wso2esb-4-8-1