Code
·
53 lines
·
1821 bytes
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53namespace VanDerHeijden.Logging.File;
/// <summary>
/// Writes batches of log messages to a daily rotating text file.
/// A new file is opened automatically whenever the calendar date changes.
/// </summary>
/// <param name="logDirectory">
/// Directory in which log files are created. Defaults to <c>"Logs"</c>.
/// Files follow the naming pattern <c>log-yyyyMMdd.txt</c>.
/// </param>
public sealed class FileLogWriter(string logDirectory = "Logs") : IBatchedLogWriter<string>
{
private StreamWriter? writer;
private DateTime currentDate = DateTime.MinValue;
/// <summary>
/// Appends all messages in the batch to the current day's log file.
/// If the date has changed since the last write, the previous file is closed
/// and a new one is opened.
/// </summary>
/// <param name="messages">The pre-formatted log lines to write.</param>
/// <param name="ct">A token that can cancel the operation.</param>
public async Task WriteBatchAsync(List<string> messages, CancellationToken ct)
{
var today = DateTime.Today;
if (writer == null || today != currentDate)
{
await DisposeAsync();
currentDate = today;
Directory.CreateDirectory(logDirectory);
var stream = new FileStream(
Path.Combine(logDirectory, $"log-{today:yyyyMMdd}.txt"),
FileMode.Append, FileAccess.Write, FileShare.ReadWrite, 65536, useAsync: true);
writer = new StreamWriter(stream) { AutoFlush = false };
}
foreach (var msg in messages)
await writer.WriteAsync(msg.AsMemory(), ct);
await writer.FlushAsync(ct);
}
/// <summary>
/// Flushes and closes the current log file, releasing all file handles.
/// </summary>
public async ValueTask DisposeAsync()
{
if (writer == null) return;
try { await writer.FlushAsync(); await writer.DisposeAsync(); }
catch { }
finally { writer = null; }
}
}