NLog中的顺序文件名

时间:2019-06-18 14:06:33

标签: c# logging nlog

我希望动态更改我的文件名并包含序列号。在每次归档过程/日志轮换时,都应更改文件名(增加编号)。 归档文件时,归档文件名应与带有序号的文件名相同(递增之前)。

从文件名开始为“ file.log.1”,在归档存档文件时,文件名将为“ file.log.1”,文件名将更改为“ file.log.2”。 下一个存档文件名将为“ file.log.2”,依此类推...

是否可以使用NLog? 在网络或NLog源代码中找不到任何线索。

1 个答案:

答案 0 :(得分:0)

所以我实现了一个自定义FileTarget来满足我的需求:

internal sealed class CustomFileTarget : NLog.Targets.FileTarget
{
    private const int _maxOldFilesToKeep = 10;

    private readonly string _directory;
    private readonly long _fileMaxSize = (long)10.Megabytes().Bytes;
    private readonly string _fileNamePrefix;

    private int _sequential;

    private string FullFileName => $"{Path.Combine(_directory, _fileNamePrefix)}.{_sequential}.log";

    public CustomFileTarget(string directory, string fileNamePrefix)
    {
        _directory = directory;
        _fileNamePrefix = fileNamePrefix;
        _sequential = GetLatestSequence() ?? 0;

        ConcurrentWrites = false;
        FileName = FullFileName;
        KeepFileOpen = false;
    }

    protected override void Write(IList<AsyncLogEventInfo> logEvents)
    {
        base.Write(logEvents);

        if (GetFileSize() >= _fileMaxSize)
        {
            ChangeName();
            DeleteOld();
        }
    }

    private long GetFileSize() =>
        new FileInfo(FullFileName).Length;

    private void ChangeName()
    {
        _sequential++;
        FileName = FullFileName;
        LogManager.ReconfigExistingLoggers();
    }

    private void DeleteOld()
    {
        var fileNamesAndSequences = GetFileNamesAndSequences();
        if (fileNamesAndSequences.Count() > _maxOldFilesToKeep + 1)
        {
            fileNamesAndSequences.Take(
                fileNamesAndSequences.Count() - _maxOldFilesToKeep + 1)
                .ForEach(
                    _ => Directory.Delete(Path.Combine(_directory, _.FileName)));
        }
    }

    private int? GetLatestSequence()
    {
        var fileNamesAndSequences = GetFileNamesAndSequences();
        return fileNamesAndSequences.Any()
            ? fileNamesAndSequences.Last().Sequence
            : (int?)null;
    }

    private IEnumerable<(string FileName, int Sequence)> GetFileNamesAndSequences() =>
        Directory.GetFiles(_directory, $"{_fileNamePrefix}*.log").
            Select(
                _ =>
                {
                    var fileNameParts = _.Split('.');
                    return (_, Sequence: int.Parse(fileNameParts[fileNameParts.Length - 2]));
                }).
            OrderBy(_ => _.Sequence);
}