【发布时间】:2014-12-04 06:11:57
【问题描述】:
我想以这样一种方式配置 log4net,即所有前一天的日志都应该自动存档。是否有可能在 Log4Net 中自动存档以前的日志。我只想使用配置来执行此操作,而不使用任何第三方库(如Sharplibzip)编写任何代码来创建存档。
通过归档添加的另一件事是压缩 zip/rar 格式的文件以节省磁盘空间。
【问题讨论】:
我想以这样一种方式配置 log4net,即所有前一天的日志都应该自动存档。是否有可能在 Log4Net 中自动存档以前的日志。我只想使用配置来执行此操作,而不使用任何第三方库(如Sharplibzip)编写任何代码来创建存档。
通过归档添加的另一件事是压缩 zip/rar 格式的文件以节省磁盘空间。
【问题讨论】:
log4net 不包含任何压缩日志文件的功能。但是压缩是在 .Net 框架中(从 4.5 开始),或者您可以使用 the Windows Shell API 压缩文件,因此您将拥有定期获取所有不是当前日志文件的日志文件并将它们压缩的代码:
-- assuming you don't have more that one appender
appender = LogManager.GetRepository().GetAppenders()
.OfType<RollingFileAppender>().FirstOrDefault();
if (appender == null) return; // no appenders found
var currentFile = appender.File;
-- dropping to pseudocode:
var files = Get_all_files_in_log_directory_which_match_log_file_pattern
but_aren't_the_current_file(current file);
if (ZipFiles(files...))
(DeleteFiles(files); // presumably
【讨论】:
ILog 上的方法,因为您可能会在循环中结束,您应该改用 LogLog。
不编写代码就无法归档文件,抱歉。不过代码不会很复杂。
您可以创建一个继承自RollingFileAppender 的自定义附加程序,并覆盖AdjustFileBeforeAppend 方法以向文件滚动添加行为。这是为RollingFileAppender 滚动文件的现有方法,您可以覆盖该方法以添加归档。
使用File属性查找文件名处理吧
// log4net.Appender.RollingFileAppender
protected virtual void AdjustFileBeforeAppend()
{
var fileToZip = File; // save the current file
if (this.m_rollDate)
{
DateTime now = this.m_dateTime.Now;
if (now >= this.m_nextCheck)
{
this.m_now = now;
this.m_nextCheck = this.NextCheckDate(this.m_now, this.m_rollPoint);
this.RollOverTime(true);
// zip the file if roll occurs here
}
}
if (this.m_rollSize)
{
if (this.File != null && ((CountingQuietTextWriter)base.QuietWriter).Count >= this.m_maxFileSize)
{
this.RollOverSize();
// zip the file if roll occurs here
}
}
}
或者,您可以找到一个现有的附加程序来执行您想要的操作,但我不知道。
我冒昧地将@stuartd 的评论提升到答案中,因为他的建议非常优雅。您可以通过这种方式简单地覆盖AdjustFileBeforeAppend:
protected override void AdjustFileBeforeAppend() {
var previousFile = File;
base.AdjustFileBeforeAppend();
if (File != previousFile) { // zip the file }
}
这是一种非常巧妙的方法,但您可能希望能够区分两种卷(即日期和大小)。例如,仅在日期卷上压缩,以便将某个日期范围内的文件保存在一起。
【讨论】:
这是我使用缩减版 DotNetZip 的解决方案。
public class CustomRollingFileAppender : RollingFileAppender
{
protected override void AdjustFileBeforeAppend()
{
var currentFile = File;
FileInfo fa = new System.IO.FileInfo(currentFile);
if (fa.Length >= 10000000)
{
using (ZipFile zip = new ZipFile(File + ".zip"))
{
string newFile = DateTime.Now.ToString("HHmmss") + fa.Name;
zip.AddFile(File).FileName = newFile;
zip.Save(File + ".zip");
}
}
base.AdjustFileBeforeAppend();
}
}
【讨论】:
我想指出,正确实现这一点的唯一方法是完全复制RollingFileAppender 源代码并从中创建FileAppender 的子类。在此代码中,您可以在adjustFileBeforeAppend() 中添加压缩部分。
上面samy的建议不起作用
【讨论】:
这是一个建议。这是一个工作代码。 它还避免读取每个日志附加的文件信息。 相反,它将适用于第一个文件翻转。基于时间或基于大小。两个都。 一旦它处于压缩当前文件的过程中。它也会 gzip 退出旧文件。那是在应用程序停止后留下的。 它不需要重新编码所有 RollingFileAppender 类。
public class CustomRollingFileAppender : RollingFileAppender
{
override protected void AdjustFileBeforeAppend()
{
var currentFile = this.File;
base.AdjustFileBeforeAppend();
if (!currentFile.Equals(this.File))
{
CompressFileGzip(currentFile);
var dirName = Path.GetDirectoryName(this.File);
var files = Directory.GetFiles(dirName);
var fileExtension = Path.GetExtension(this.File);
foreach (var file in files)
{
if (!file.EndsWith(this.File) && file.EndsWith(fileExtension))
{
CompressFileGzip(file.ToString());
}
}
}
}
private void CompressFileGzip(string fileToGzip)
{
if (!FileExists(fileToGzip))
{
return;
}
FileInfo fileToBeGZipped = new FileInfo(fileToGzip);
FileInfo gzipFileName = new FileInfo(string.Concat(fileToBeGZipped.FullName, ".gz"));
using (FileStream fileToBeZippedAsStream = fileToBeGZipped.OpenRead())
{
using (FileStream gzipTargetAsStream = gzipFileName.Create())
{
using (GZipStream gzipStream = new GZipStream(gzipTargetAsStream, CompressionMode.Compress))
{
fileToBeZippedAsStream.CopyTo(gzipStream);
}
}
}
System.IO.File.Delete(fileToGzip);
}
}
【讨论】:
我已经修改了 Masood 的实现,但是我没有使用 File 属性(似乎没有改变),而是阅读了“Move [from] -> [to]”事件的 LogLog 消息。
为 gz 添加了文件时间以避免多个“myLog.xml.1.gz”冲突。 不想让文件名更整洁。
public class CompressedRollingFileAppender : RollingFileAppender {
private readonly Regex _moveRegex;
private string _moveToFile = null;
public CompressedRollingFileAppender() : base() {
LogLog.LogReceived += LogReceived;
_moveRegex = new Regex(@"^Moving \[(.+)\] -> \[(.+)\]$");
}
private void LogReceived(object source, LogReceivedEventArgs e) {
var match = _moveRegex.Match(e.LogLog.Message);
if (match.Groups[1].Value == this.File) {
_moveToFile = match.Groups[2].Value;
}
}
protected override void AdjustFileBeforeAppend() {
var currentFile = this.File;
base.AdjustFileBeforeAppend();
if (_moveToFile != null) {
CompressFileGzip(_moveToFile);
_moveToFile = null;
}
}
private void CompressFileGzip(string fileToGzip) {
if (!FileExists(fileToGzip)) {
return;
}
FileInfo fileToBeGZipped = new FileInfo(fileToGzip);
// filetime
var filetime = DateTime.Now.ToFileTimeUtc().ToString(System.Globalization.CultureInfo.InvariantCulture);
FileInfo gzipFileName = new FileInfo(string.Concat(fileToBeGZipped.FullName, "." + filetime + ".gz"));
using (FileStream fileToBeZippedAsStream = fileToBeGZipped.OpenRead())
using (FileStream gzipTargetAsStream = gzipFileName.Create())
using (GZipStream gzipStream = new GZipStream(gzipTargetAsStream, CompressionMode.Compress))
fileToBeZippedAsStream.CopyTo(gzipStream);
System.IO.File.Delete(fileToGzip);
}
}
【讨论】: