Projekt

Obecné

Profil

Stáhnout (5.17 KB) Statistiky
| Větev: | Tag: | Revize:
1 74bd1e40 Pultak
using System.IO.Compression;
2
3
namespace LDClient.utils.loggers; 
4
5
public class FileLogger : ALogger {
6
7 d7aeccba Pultak
    /// <summary>
8
    /// Folder name for the created log files
9
    /// </summary>
10 74bd1e40 Pultak
    private const string LogFolderName = "logs";
11 d7aeccba Pultak
    /// <summary>
12
    /// Base name of the log file
13
    /// </summary>
14 74bd1e40 Pultak
    private const string LogFileName = "app_info.log";
15 d7aeccba Pultak
    
16 74bd1e40 Pultak
    private readonly int _logChunkSize = Program.Config.LogChunkSize;
17
    private readonly int _logChunkMaxCount = Program.Config.LogChunkMaxCount;
18
    private readonly int _logArchiveMaxCount = Program.Config.LogArchiveMaxCount;
19
    private readonly int _logCleanupPeriod = Program.Config.LogCleanupPeriod;
20
21 d7aeccba Pultak
    /// <summary>
22
    /// Destination folder used to store the created logs and zipped chunks
23
    /// </summary>
24 74bd1e40 Pultak
    private const string LogFolderPath = $"ldClient\\{LogFolderName}";
25
26 d7aeccba Pultak
    /// <summary>
27
    /// Flag that indicates that the log folder is already created
28
    /// </summary>
29 74bd1e40 Pultak
    private bool _logDirExists;
30
31 d7aeccba Pultak
    /// <summary>
32
    /// Creates one entry in the rotating file.
33
    /// If the current log file is too big, it creates new log file.
34
    /// If there is too many log files it archives them.
35
    /// Deletes all archived files that are too old
36
    /// </summary>
37
    /// <param name="message">Desired message to be logged<</param>
38 74bd1e40 Pultak
    protected override void CreateLog(string message) {
39
40
        if (!_logDirExists) {
41
            _logDirExists = Directory.Exists(LogFolderPath);
42
            if (!_logDirExists) {
43
                Directory.CreateDirectory(LogFolderPath);
44
                _logDirExists = true;
45
            }
46
        }
47
48
        var logFilePath = Path.Combine(LogFolderPath, LogFileName);
49
50
        Rotate(logFilePath);
51
52
        using var sw = File.AppendText(logFilePath);
53
        sw.WriteLine(message);
54
    }
55
56 d7aeccba Pultak
    /// <summary>
57
    /// Rotates last log file by creating new logging file in the process
58
    /// </summary>
59
    /// <param name="filePath">path to the last log file</param>
60 74bd1e40 Pultak
    private void Rotate(string filePath) {
61
        if (!File.Exists(filePath)) {
62
            return;
63
        }
64
65
        var fileInfo = new FileInfo(filePath);
66
        if (fileInfo.Length < _logChunkSize) {
67
            return;
68
        }
69
        var fileTime = DateTime.Now.ToString("dd-MM-yyyy,hh-mm-ss,fff");
70
        var rotatedPath = filePath.Replace(".log", $".{fileTime}");
71
        File.Move(filePath, rotatedPath);
72
73
        var folderPath = Path.GetDirectoryName(rotatedPath);
74
        var logFolderContent = new DirectoryInfo(folderPath ?? string.Empty).GetFileSystemInfos();
75
76
        var chunks = logFolderContent.Where(x => 
77
            !x.Extension.Equals(".zip", StringComparison.OrdinalIgnoreCase));
78
79
        if (chunks.Count() <= _logChunkMaxCount) {
80
            return;
81
        }
82
83
        Archive(chunks, rotatedPath, fileTime, folderPath);
84
        DeleteOldArchives(logFolderContent);
85
    }
86
87 d7aeccba Pultak
    /// <summary>
88
    /// Archives the all the last log files (chunks) 
89
    /// </summary>
90
    /// <param name="chunks">All log files that will be archived</param>
91
    /// <param name="rotatedPath">path to the log files, which will be archived</param>
92
    /// <param name="fileTime">current time stamp in string</param>
93
    /// <param name="folderPath">path to to the exported archives</param>
94 74bd1e40 Pultak
    private void Archive(IEnumerable<FileSystemInfo> chunks, string rotatedPath, string fileTime, string? folderPath) {
95
96
        var archiveFolderInfo = Directory.CreateDirectory(Path.Combine(Path.GetDirectoryName(rotatedPath) ?? LogFolderPath, $"{LogFolderName}_{fileTime}"));
97
98
        foreach (var chunk in chunks) {
99
            var destination = Path.Combine(archiveFolderInfo.FullName, chunk.Name);
100
            Directory.Move(chunk.FullName, destination);
101
        }
102
103
        ZipFile.CreateFromDirectory(archiveFolderInfo.FullName, Path.Combine(folderPath ?? LogFolderPath, $"{LogFolderName}_{fileTime}.zip"));
104
        Directory.Delete(archiveFolderInfo.FullName, true);
105
    }
106
107 d7aeccba Pultak
    /// <summary>
108
    /// This function deletes all archives that are too old and exceeds the maximum zip files.
109
    /// Cleanup period and zip max count can be specified in the configuration file.
110
    /// </summary>
111
    /// <param name="logFolderContent">filesystem info of the log folder</param>
112 74bd1e40 Pultak
    private void DeleteOldArchives(FileSystemInfo[] logFolderContent) {
113
114
        var archives = logFolderContent.Where(x => x.Extension.Equals(".zip", StringComparison.OrdinalIgnoreCase)).ToArray();
115 d7aeccba Pultak
        
116 74bd1e40 Pultak
        if (archives.Length <= _logArchiveMaxCount)
117
            return;
118
119 d7aeccba Pultak
        //find oldest archive in the folder
120 74bd1e40 Pultak
        var oldestArchive = archives.OrderBy(x => x.CreationTime).First();
121
        var cleanupDate = oldestArchive.CreationTime.AddDays(_logCleanupPeriod);
122 d7aeccba Pultak
        //is there any file older than specified cleanup cleanup period
123 74bd1e40 Pultak
        if (DateTime.Compare(cleanupDate, DateTime.Now) <= 0) {
124
            foreach (var file in logFolderContent) {
125
                file.Delete();
126
            }
127
        } else {
128
            File.Delete(oldestArchive.FullName);
129
        }
130
    }
131
    public override string ToString() => $"{base.ToString()}, Chunk Size: {_logChunkSize}, Max chunk count: {_logChunkMaxCount}, Max log archive count: {_logArchiveMaxCount}, Cleanup period: {_logCleanupPeriod} days]";
132
}