126 lines
3.8 KiB
C#
126 lines
3.8 KiB
C#
using EonaCat.LogStack.Core;
|
|
using System;
|
|
using System.Threading;
|
|
using System.Threading.Tasks;
|
|
|
|
namespace EonaCat.LogStack.Flows;
|
|
|
|
// This file is part of the EonaCat project(s) which is released under the Apache License.
|
|
// See the LICENSE file or go to https://EonaCat.com/License for full license details.
|
|
|
|
/// <summary>
|
|
/// Flows are output destinations for log events (replacement for "sinks").
|
|
/// Each flow handles writing log events to a specific destination with optimized batching.
|
|
/// </summary>
|
|
public interface IFlow : IAsyncDisposable
|
|
{
|
|
/// <summary>
|
|
/// Gets the name of this flow for identification
|
|
/// </summary>
|
|
string Name { get; }
|
|
|
|
/// <summary>
|
|
/// Minimum log level this flow will process
|
|
/// </summary>
|
|
LogLevel MinimumLevel { get; }
|
|
|
|
/// <summary>
|
|
/// Whether this flow is currently enabled
|
|
/// </summary>
|
|
bool IsEnabled { get; }
|
|
|
|
/// <summary>
|
|
/// Blast a single log event to this flow
|
|
/// </summary>
|
|
Task<WriteResult> BlastAsync(LogEvent logEvent, CancellationToken cancellationToken = default);
|
|
|
|
/// <summary>
|
|
/// Blast a batch of log events to this flow (more efficient than single blasts)
|
|
/// </summary>
|
|
Task<WriteResult> BlastBatchAsync(ReadOnlyMemory<LogEvent> logEvents, CancellationToken cancellationToken = default);
|
|
|
|
/// <summary>
|
|
/// Flush any buffered log events immediately
|
|
/// </summary>
|
|
Task FlushAsync(CancellationToken cancellationToken = default);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Base class for flows with common functionality
|
|
/// </summary>
|
|
public abstract class FlowBase : IFlow
|
|
{
|
|
protected FlowBase(string name, LogLevel minimumLevel = LogLevel.Trace)
|
|
{
|
|
Name = name ?? throw new ArgumentNullException(nameof(name));
|
|
MinimumLevel = minimumLevel;
|
|
IsEnabled = true;
|
|
}
|
|
|
|
public string Name { get; }
|
|
public LogLevel MinimumLevel { get; protected set; }
|
|
public bool IsEnabled { get; protected set; }
|
|
|
|
protected long DroppedCount;
|
|
protected long BlastedCount;
|
|
|
|
protected bool IsLogLevelEnabled(LogEvent logEvent)
|
|
{
|
|
return logEvent.Level >= MinimumLevel;
|
|
}
|
|
|
|
public abstract Task<WriteResult> BlastAsync(LogEvent logEvent, CancellationToken cancellationToken = default);
|
|
|
|
public virtual async Task<WriteResult> BlastBatchAsync(ReadOnlyMemory<LogEvent> logEvents, CancellationToken cancellationToken = default)
|
|
{
|
|
var result = WriteResult.Success;
|
|
var eventsArray = logEvents.ToArray();
|
|
|
|
foreach (var logEvent in eventsArray)
|
|
{
|
|
var singleResult = await BlastAsync(logEvent, cancellationToken).ConfigureAwait(false);
|
|
if (singleResult != WriteResult.Success)
|
|
{
|
|
result = singleResult;
|
|
}
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
public abstract Task FlushAsync(CancellationToken cancellationToken = default);
|
|
|
|
public virtual async ValueTask DisposeAsync()
|
|
{
|
|
IsEnabled = false;
|
|
await FlushAsync(default).ConfigureAwait(false);
|
|
GC.SuppressFinalize(this);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Gets diagnostic information about this flow
|
|
/// </summary>
|
|
public virtual FlowDiagnostics GetDiagnostics()
|
|
{
|
|
return new FlowDiagnostics
|
|
{
|
|
Name = Name,
|
|
IsEnabled = IsEnabled,
|
|
MinimumLevel = MinimumLevel,
|
|
BlastedCount = Interlocked.Read(ref BlastedCount),
|
|
DroppedCount = Interlocked.Read(ref DroppedCount)
|
|
};
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Diagnostic information about a flow
|
|
/// </summary>
|
|
public sealed class FlowDiagnostics
|
|
{
|
|
public string Name { get; set; }
|
|
public bool IsEnabled { get; set; }
|
|
public LogLevel MinimumLevel { get; set; }
|
|
public long BlastedCount { get; set; }
|
|
public long DroppedCount { get; set; }
|
|
} |