Updated
This commit is contained in:
@@ -256,13 +256,13 @@ public sealed class FileLoggerProvider : BatchingLoggerProvider, IDisposable
|
|||||||
const int maxBatch = 5000;
|
const int maxBatch = 5000;
|
||||||
int batchCount = 0;
|
int batchCount = 0;
|
||||||
|
|
||||||
// Rent a buffer
|
// Start with a reasonably sized buffer from the pool
|
||||||
byte[] combined = ArrayPool<byte>.Shared.Rent(BufferSize);
|
int estimatedSize = 1024 * 64; // 64KB starting buffer
|
||||||
|
byte[] combined = ArrayPool<byte>.Shared.Rent(estimatedSize);
|
||||||
int pos = 0;
|
int pos = 0;
|
||||||
|
|
||||||
while (queue.TryDequeue(out var msg) && batchCount < maxBatch)
|
while (queue.TryDequeue(out var msg) && batchCount < maxBatch)
|
||||||
{
|
{
|
||||||
// Rotate file if date changed
|
|
||||||
var msgDate = msg.Timestamp.UtcDateTime.Date;
|
var msgDate = msg.Timestamp.UtcDateTime.Date;
|
||||||
if (state.Date != msgDate)
|
if (state.Date != msgDate)
|
||||||
{
|
{
|
||||||
@@ -270,66 +270,68 @@ public sealed class FileLoggerProvider : BatchingLoggerProvider, IDisposable
|
|||||||
RotateByDate(state, msgDate, string.Empty);
|
RotateByDate(state, msgDate, string.Empty);
|
||||||
}
|
}
|
||||||
|
|
||||||
var msgText = BuildMessage(msg);
|
var messageString = BuildMessage(msg);
|
||||||
int byteCount = Utf8.GetByteCount(msgText);
|
int requiredLength = Utf8.GetByteCount(messageString);
|
||||||
|
|
||||||
// Flush buffer if message won't fit
|
// Grow buffer if needed
|
||||||
if (pos + byteCount > combined.Length)
|
if (pos + requiredLength > combined.Length)
|
||||||
{
|
{
|
||||||
await FlushBufferAsync(state).ConfigureAwait(false);
|
int newSize = Math.Max(combined.Length * 2, pos + requiredLength);
|
||||||
pos = 0;
|
byte[] newBuffer = ArrayPool<byte>.Shared.Rent(newSize);
|
||||||
|
Array.Copy(combined, 0, newBuffer, 0, pos);
|
||||||
|
ArrayPool<byte>.Shared.Return(combined);
|
||||||
|
combined = newBuffer;
|
||||||
}
|
}
|
||||||
|
|
||||||
Utf8.GetBytes(msgText, 0, msgText.Length, combined, pos);
|
// Write directly into combined buffer
|
||||||
pos += byteCount;
|
pos += Utf8.GetBytes(messageString, 0, messageString.Length, combined, pos);
|
||||||
batchCount++;
|
batchCount++;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (pos == 0)
|
if (pos == 0)
|
||||||
{
|
{
|
||||||
ArrayPool<byte>.Shared.Return(combined);
|
ArrayPool<byte>.Shared.Return(combined);
|
||||||
return;
|
return; // nothing to write
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// If encryption is enabled, encrypt into a new array
|
||||||
byte[] dataToWrite;
|
byte[] dataToWrite;
|
||||||
|
|
||||||
if (_isEncryptionEnabled)
|
if (_isEncryptionEnabled)
|
||||||
{
|
{
|
||||||
// Encrypt creates a new array, old buffer cleared immediately
|
|
||||||
dataToWrite = Encrypt(combined.AsSpan(0, pos).ToArray());
|
dataToWrite = Encrypt(combined.AsSpan(0, pos).ToArray());
|
||||||
Array.Clear(combined, 0, pos);
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
// No encryption: just use the pooled buffer slice directly
|
||||||
dataToWrite = combined;
|
dataToWrite = combined;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Flush buffer if needed
|
// Flush buffer if needed
|
||||||
if (state.BufferPosition + dataToWrite.Length > BufferSize)
|
if (state.BufferPosition + pos > BufferSize)
|
||||||
{
|
{
|
||||||
await FlushBufferAsync(state).ConfigureAwait(false);
|
await FlushBufferAsync(state).ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Rollover if file exceeds max size
|
// Rollover if file exceeds max size
|
||||||
if (_maxFileSize > 0 && state.Size + dataToWrite.Length > _maxFileSize)
|
if (_maxFileSize > 0 && state.Size + pos > _maxFileSize)
|
||||||
{
|
{
|
||||||
await FlushBufferAsync(state).ConfigureAwait(false);
|
await FlushBufferAsync(state).ConfigureAwait(false);
|
||||||
RollOverAndCompressOldest(state, string.Empty);
|
RollOverAndCompressOldest(state, string.Empty);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Copy into buffer
|
// Copy directly into the file buffer
|
||||||
Array.Copy(dataToWrite, 0, state.Buffer, state.BufferPosition, dataToWrite.Length);
|
Array.Copy(dataToWrite, 0, state.Buffer, state.BufferPosition, pos);
|
||||||
state.BufferPosition += dataToWrite.Length;
|
state.BufferPosition += pos;
|
||||||
state.Size += dataToWrite.Length;
|
state.Size += pos;
|
||||||
|
|
||||||
|
// Clear sensitive data
|
||||||
|
Array.Clear(dataToWrite, 0, pos);
|
||||||
|
|
||||||
|
// Return buffer if unencrypted
|
||||||
if (!_isEncryptionEnabled)
|
if (!_isEncryptionEnabled)
|
||||||
{
|
{
|
||||||
// return pooled buffer if not encrypted
|
|
||||||
ArrayPool<byte>.Shared.Return(dataToWrite);
|
ArrayPool<byte>.Shared.Return(dataToWrite);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Clear encrypted array immediately
|
|
||||||
Array.Clear(dataToWrite, 0, dataToWrite.Length);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task FlushBufferAsync(FileState state, CancellationToken token = default)
|
private async Task FlushBufferAsync(FileState state, CancellationToken token = default)
|
||||||
|
|||||||
Reference in New Issue
Block a user