我正在尝试登录文件root.$date.log
,其中date
是提交日志的日期。
现在我创建了这个appender,但我遇到的问题是timestamp
只被评估一次(当Tomcat启动时)
appender("STDOUT", FileAppender) {
file = "$logDirectory/logs/root.${timestamp("yyyy-MM-dd")}.log"
append = true
encoder(PatternLayoutEncoder) {
pattern = loggerPattern
}
}
PS 我正在使用Grails 3.0.x
答案 0 :(得分:2)
而不是简单的FileAppender
,您应该使用RollingFileAppender
,它可以根据滚动策略创建新的日志文件。
使用logback's滚动文件追加器。
appender("ROLLING", RollingFileAppender) {
encoder(PatternLayoutEncoder) {
Pattern = "%d %level %thread %mdc %logger - %m%n"
}
rollingPolicy(TimeBasedRollingPolicy) {
FileNamePattern = "$logDirectory/logs/root-%d{yyyy-MM-dd}.zip"
}
}
如果您想使用Log4J,可以使用DailyRollingFileAppender
。但默认实现有一些问题:
已观察到DailyRollingFileAppender显示同步 问题和数据丢失。 log4j extras伴侣包括 新部署应考虑的替代方案,以及哪些方案 在文档中讨论 org.apache.log4j.rolling.RollingFileAppender。
有一些可用的名称为CustodianDailyRollingFileAppender
的自定义实现。这也允许您指定要保留的备份文件数。而且每天它还可以压缩前一天的日志文件以节省空间。我没有添加任何特定链接,因为在不久的将来可能会破坏。相反,我在过去的几个月里添加了我们在项目中使用的实现,没有任何问题。
package org.apache.log4j
import org.apache.log4j.helpers.LogLog
import org.apache.log4j.spi.LoggingEvent
import org.apache.tools.zip.ZipEntry
import org.apache.tools.zip.ZipOutputStream
import java.lang.reflect.Field
import java.text.SimpleDateFormat
class CustodianDailyRollingFileAppender extends DailyRollingFileAppender {
String datePattern = "'.'yyyy-MM-dd"
boolean compress
Integer maxNumberOfDays = 7
/**
* The next time we estimate a rollover should occur.
*/
private long nextCheck = System.currentTimeMillis() - 1
/*
* This method checks to see if we're exceeding the number of log backups
* that we are supposed to keep, and if so, deletes the offending files.
* It then delegates to the rollover method to rollover to a new file if
* required.
*/
protected void cleanupAndRollOver() throws IOException {
File file = new File(fileName)
Calendar cal = Calendar.getInstance()
cal.add(Calendar.DATE, -maxNumberOfDays)
Field field_sdf = DailyRollingFileAppender.getDeclaredField("sdf")
field_sdf.setAccessible(true)
SimpleDateFormat sdf = field_sdf.get(this) as SimpleDateFormat
Date cutoffDate = cal.getTime()
if (file.getParentFile().exists()) {
File[] files = file.getParentFile().listFiles(new StartsWithFileFilter(file.getName(), false))
int nameLength = file.getName().length()
files.each {
File logFile ->
String datePart
try {
datePart = logFile.getName().substring(nameLength)
Date date = sdf.parse(datePart)
if (date.before(cutoffDate)) {
logFile.delete()
} else if (compress) {
zipAndDelete(logFile)
}
}
catch (Exception pe) {
//This isn't a file we should touch (it isn't named correctly)
}
}
}
rollOver()
}
class StartsWithFileFilter implements FileFilter {
private String startsWith
private boolean inclDirs = false
public StartsWithFileFilter(String startsWith, boolean includeDirectories) {
super()
this.startsWith = startsWith.toUpperCase()
inclDirs = includeDirectories
}
public boolean accept(File pathname) {
if (!inclDirs && pathname.isDirectory()) {
return false
} else {
String upperCase = pathname.getName().toUpperCase()
return upperCase.startsWith(startsWith) && upperCase.length() > startsWith.length()
}
}
}
/**
* Compresses the passed file to a .zip file, stores the .zip in the
* same directory as the passed file, and then deletes the original,
* leaving only the .zipped archive.
* @param file
*/
private void zipAndDelete(File file) throws IOException {
if (!file.getName().endsWith(".zip")) {
File zipFile = new File(file.getParent(), file.getName() + ".zip")
FileInputStream fis = new FileInputStream(file)
FileOutputStream fos = new FileOutputStream(zipFile)
ZipOutputStream zos = new ZipOutputStream(fos)
ZipEntry zipEntry = new ZipEntry(file.getName())
zos.putNextEntry(zipEntry)
byte[] buffer = new byte[4096]
while (true) {
int bytesRead = fis.read(buffer)
if (bytesRead == -1) break
else {
zos.write(buffer, 0, bytesRead)
}
}
zos.closeEntry()
fis.close()
zos.close()
file.delete()
}
}
@Override
protected void subAppend(LoggingEvent event) {
long n = System.currentTimeMillis()
Field field_now = DailyRollingFileAppender.getDeclaredField("now")
field_now.setAccessible(true)
Date now = field_now.get(this) as Date
Field field_rc = DailyRollingFileAppender.getDeclaredField("rc")
field_rc.setAccessible(true)
def rc = field_rc.get(this)
if (n >= nextCheck) {
now.setTime(n)
nextCheck = rc.getNextCheckMillis(now)
try {
cleanupAndRollOver()
}
catch (IOException ioe) {
LogLog.error("cleanupAndRollover() failed.", ioe)
}
}
super.subAppend(event)
}
}
创建一个appender:
appender("ROLLING", CustodianDailyRollingFileAppender) {
file("$logDirectory/logs/root.log")
layout(EnhancedPatternLayout) {
Pattern = "%d %level %thread %mdc %logger - %m%n"
}
maxNumberOfDays(30)
compress(true)
}